mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-02 03:55:15 +08:00
Persist GitHub Copilot SDK session ids in the plugin-state SQLite store so separate OpenClaw process turns can resume the same Copilot-side session when the compatibility fingerprint still matches. The fingerprint covers provider/model/cwd, resolved agent id, resolved Copilot home, and auth identity. Plugin-state lookup/register/delete failures are non-fatal, stale rows are invalidated, and reset delete failures use an in-process tombstone so reset does not accidentally reuse a durable binding. Also routes the QQBot token POST through the plugin SDK SSRF guard with capture disabled for the secret-bearing request, preserving the current token lifetime validation from main. Verification: focused Copilot and QQBot Vitest suites, raw channel fetch guard, autoreview clean, Blacksmith Testbox pnpm check:changed tbx_01kst9fwjmsfzwaxqatszcbf40, live local Copilot two-turn smoke with the same SDK session id persisted in SQLite. Refs #88064
46 lines
1.3 KiB
TypeScript
46 lines
1.3 KiB
TypeScript
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
import { createCopilotAgentHarness, type CopilotSessionBinding } from "./harness.js";
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
}
|
|
|
|
function readPoolOptions(pluginConfig: unknown): { idleTtlMs: number } | undefined {
|
|
if (!isRecord(pluginConfig)) {
|
|
return undefined;
|
|
}
|
|
|
|
const pool = pluginConfig.pool;
|
|
if (!isRecord(pool)) {
|
|
return undefined;
|
|
}
|
|
|
|
const idleTtlMs = pool.idleTtlMs;
|
|
if (typeof idleTtlMs !== "number" || !Number.isFinite(idleTtlMs) || idleTtlMs < 1) {
|
|
return undefined;
|
|
}
|
|
|
|
return { idleTtlMs };
|
|
}
|
|
|
|
export default definePluginEntry({
|
|
id: "copilot",
|
|
name: "GitHub Copilot agent runtime",
|
|
description: "Registers the GitHub Copilot agent runtime.",
|
|
register(api) {
|
|
const poolOptions = readPoolOptions(api.pluginConfig);
|
|
const sessionStore = api.runtime.state.openSyncKeyedStore<CopilotSessionBinding>({
|
|
namespace: "sdk-sessions",
|
|
maxEntries: 5000,
|
|
defaultTtlMs: 90 * 24 * 60 * 60 * 1000,
|
|
});
|
|
|
|
api.registerAgentHarness(
|
|
createCopilotAgentHarness({
|
|
...(poolOptions ? { poolOptions } : {}),
|
|
sessionStore,
|
|
}),
|
|
);
|
|
},
|
|
});
|