@openclaw/copilot 2026.7.1 → 2026.7.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,13 +14,11 @@ The harness claims the canonical subscription `github-copilot` provider plus
14
14
  custom BYOK provider entries that the Copilot SDK can represent. Manifest-owned
15
15
  native provider ids stay with their owning runtimes. The harness is opt-in only:
16
16
  selection requires explicit `agentRuntime.id: "copilot"` on a model or provider
17
- entry; `auto` never picks it. PI remains the default embedded runtime.
17
+ entry; `auto` never picks it. OpenClaw remains the default embedded runtime.
18
18
 
19
19
  See [GitHub Copilot agent runtime](../../docs/plugins/copilot.md) for
20
20
  configuration, the doctor contract, transcript mirroring, compaction, side
21
21
  questions, replay, and the supported-surface contract.
22
- See [qa/copilot-capabilities.md](../../qa/copilot-capabilities.md)
23
- for the SDK capability inventory the harness is pinned to.
24
22
 
25
23
  ## Package
26
24
 
@@ -1,29 +1,12 @@
1
- import { a as resolveCopilotAuth, i as createCopilotByokAuth, n as resolveCopilotProvider, r as createCopilotByokProxy } from "./harness-BQhGzc1Z.js";
2
- import { applyEmbeddedAttemptToolsAllow, awaitAgentEndSideEffects, buildAgentHarnessUserInputAnswers, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, clearActiveEmbeddedRun, deliverAgentHarnessUserInputPrompt, detectAndLoadAgentHarnessPromptImages, embeddedAgentLog, extractToolErrorMessage, getModelProviderRequestTransport, getPluginToolMeta, isSubagentSessionKey, isToolResultError, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptFsWorkspaceOnly, resolveAttemptSpawnWorkspaceDir, resolveBootstrapContextForRun, resolveCompactionTimeoutMs, resolveEmbeddedAttemptToolConstructionPlan, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveUserPath, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, sanitizeToolResult, setActiveEmbeddedRun } from "openclaw/plugin-sdk/agent-harness-runtime";
1
+ import { a as resolveCopilotAuth, i as createCopilotByokAuth, n as resolveCopilotProvider, r as createCopilotByokProxy } from "./harness-DnbBZBdi.js";
2
+ import { applyEmbeddedAttemptToolsAllow, awaitAgentEndSideEffects, buildAgentHarnessUserInputAnswers, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, clearActiveEmbeddedRun, deliverAgentHarnessUserInputPrompt, detectAndLoadAgentHarnessPromptImages, embeddedAgentLog, extractToolErrorMessage, getModelProviderRequestTransport, getPluginToolMeta, isHostScopedAgentToolActive, isSubagentSessionKey, isToolResultError, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptFsWorkspaceOnly, resolveAttemptSpawnWorkspaceDir, resolveBootstrapContextForRun, resolveCompactionTimeoutMs, resolveEmbeddedAttemptToolConstructionPlan, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveUserPath, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, sanitizeToolResult, setActiveEmbeddedRun } from "openclaw/plugin-sdk/agent-harness-runtime";
3
3
  import { createHash } from "node:crypto";
4
4
  import path from "node:path";
5
5
  import fsp from "node:fs/promises";
6
- import { publishSessionTranscriptUpdateByIdentity, withSessionTranscriptWriteLock } from "openclaw/plugin-sdk/session-transcript-runtime";
6
+ import { withSessionTranscriptWriteLock } from "openclaw/plugin-sdk/session-transcript-runtime";
7
7
  import { createAgentHarnessTaskRuntime } from "openclaw/plugin-sdk/agent-harness-task-runtime";
8
+ import { convertMcpCallToolResult } from "@github/copilot-sdk";
8
9
  import { createAgentHarnessToolSurfaceRuntime } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
9
- //#region extensions/copilot/src/compaction-bridge.ts
10
- /**
11
- * Shape an `InfiniteSessionConfig` for `SessionConfig.infiniteSessions`.
12
- * Returns `undefined` when no fields were supplied so callers can
13
- * spread conditionally and let the SDK apply its own defaults
14
- * (`enabled: true`, background 0.80, buffer 0.95). Any explicitly-set
15
- * value (including `enabled: false` to disable infinite sessions) is
16
- * preserved.
17
- */
18
- function createInfiniteSessionConfig(options) {
19
- if (!options) return;
20
- const result = {};
21
- if (options.enabled !== void 0) result.enabled = options.enabled;
22
- if (options.backgroundCompactionThreshold !== void 0) result.backgroundCompactionThreshold = options.backgroundCompactionThreshold;
23
- if (options.bufferExhaustionThreshold !== void 0) result.bufferExhaustionThreshold = options.bufferExhaustionThreshold;
24
- return Object.keys(result).length > 0 ? result : void 0;
25
- }
26
- //#endregion
27
10
  //#region extensions/copilot/src/dual-write-transcripts.ts
28
11
  /**
29
12
  * Mirrors the AgentMessages produced by the copilot agent runtime into the
@@ -98,9 +81,8 @@ function buildMirrorDedupeIdentity(message) {
98
81
  async function mirrorCopilotTranscript(params) {
99
82
  const messages = params.messages.filter((message) => message.role === "user" || message.role === "assistant" || message.role === "toolResult");
100
83
  if (messages.length === 0) return;
101
- const transcriptTarget = resolveCopilotMirrorTranscriptTarget(params);
102
- if (await withSessionTranscriptWriteLock({
103
- ...transcriptTarget,
84
+ await withCopilotMirrorTranscriptWriteLock({
85
+ ...resolveCopilotMirrorTranscriptTarget(params),
104
86
  config: params.config
105
87
  }, async (transcript) => {
106
88
  let didAppendMessage = false;
@@ -130,22 +112,24 @@ async function mirrorCopilotTranscript(params) {
130
112
  didAppendMessage = true;
131
113
  if (idempotencyKey) existingIdempotencyKeys.add(idempotencyKey);
132
114
  }
115
+ if (didAppendMessage) await transcript.publishUpdate(params.sessionKey ? { sessionKey: params.sessionKey } : void 0);
133
116
  return didAppendMessage;
134
- })) await publishSessionTranscriptUpdateByIdentity({
135
- ...transcriptTarget,
136
- update: params.sessionKey ? { sessionKey: params.sessionKey } : void 0
137
117
  });
138
118
  }
139
119
  function resolveCopilotMirrorTranscriptTarget(params) {
140
- const sessionFile = params.sessionFile.trim();
141
- if (!sessionFile) throw new Error("Copilot transcript mirror requires a sessionFile target");
120
+ const sessionKey = params.sessionKey?.trim();
121
+ const storePath = params.storePath?.trim();
122
+ if (!sessionKey || !storePath) throw new Error("Copilot transcript mirror requires a runtime session identity");
142
123
  return {
143
124
  ...params.agentId ? { agentId: params.agentId } : {},
144
- sessionFile,
145
125
  sessionId: params.sessionId,
146
- sessionKey: params.sessionKey ?? ""
126
+ sessionKey,
127
+ storePath
147
128
  };
148
129
  }
130
+ function withCopilotMirrorTranscriptWriteLock(params, run) {
131
+ return withSessionTranscriptWriteLock(params, run);
132
+ }
149
133
  function readTranscriptIdempotencyKeys(events) {
150
134
  const keys = /* @__PURE__ */ new Set();
151
135
  for (const event of events) {
@@ -223,7 +207,7 @@ function attachEventBridge(session, options) {
223
207
  let usage;
224
208
  let streamError;
225
209
  const toolMetas = [];
226
- const toolNamesByCallId = /* @__PURE__ */ new Map();
210
+ const toolMetaIndexByCallId = /* @__PURE__ */ new Map();
227
211
  let startedCount = 0;
228
212
  let completedCount = 0;
229
213
  let activeCompactionCount = 0;
@@ -244,7 +228,7 @@ function attachEventBridge(session, options) {
244
228
  const unsubscribeFns = [];
245
229
  registerListener(session, unsubscribeFns, "assistant.message_delta", (event) => {
246
230
  if (!isRootSessionEvent(event)) return;
247
- const messageId = readString$2(event.data.messageId) ?? "assistant-message";
231
+ const messageId = readString$1(event.data.messageId) ?? "assistant-message";
248
232
  const delta = event.data.deltaContent;
249
233
  if (!delta) return;
250
234
  const entry = ensureMessageAccumulator(messagesById, messageOrder, messageId);
@@ -267,7 +251,7 @@ function attachEventBridge(session, options) {
267
251
  });
268
252
  registerListener(session, unsubscribeFns, "assistant.reasoning_delta", (event) => {
269
253
  if (!isRootSessionEvent(event)) return;
270
- const reasoningId = readString$2(event.data.reasoningId) ?? "assistant-reasoning";
254
+ const reasoningId = readString$1(event.data.reasoningId) ?? "assistant-reasoning";
271
255
  const delta = event.data.deltaContent;
272
256
  if (!delta) return;
273
257
  if (!reasoningById.has(reasoningId)) {
@@ -288,17 +272,19 @@ function attachEventBridge(session, options) {
288
272
  });
289
273
  registerListener(session, unsubscribeFns, "tool.execution_start", (event) => {
290
274
  if (isRootSessionEvent(event)) startedCount += 1;
291
- toolNamesByCallId.set(event.data.toolCallId, event.data.toolName);
275
+ toolMetaIndexByCallId.set(event.data.toolCallId, toolMetas.length);
292
276
  toolMetas.push({ toolName: event.data.toolName });
293
277
  });
294
278
  registerListener(session, unsubscribeFns, "tool.execution_complete", (event) => {
295
279
  if (isRootSessionEvent(event)) completedCount += 1;
296
- const toolName = toolNamesByCallId.get(event.data.toolCallId);
280
+ const toolMetaIndex = toolMetaIndexByCallId.get(event.data.toolCallId);
281
+ const toolName = toolMetaIndex === void 0 ? void 0 : toolMetas[toolMetaIndex]?.toolName;
297
282
  const meta = event.data.success ? event.data.result?.detailedContent ?? event.data.result?.content : event.data.error?.message;
298
- if (toolName) toolMetas.push({
299
- meta,
300
- toolName
301
- });
283
+ if (toolName && toolMetaIndex !== void 0) toolMetas[toolMetaIndex] = {
284
+ ...meta ? { meta } : {},
285
+ toolName,
286
+ ...event.data.success ? {} : { isError: true }
287
+ };
302
288
  });
303
289
  registerListener(session, unsubscribeFns, "session.plan_changed", (event) => {
304
290
  enqueueAgentEvent({
@@ -364,6 +350,9 @@ function attachEventBridge(session, options) {
364
350
  enqueueCompactionCallback(options.onCompactionStart);
365
351
  });
366
352
  registerListener(session, unsubscribeFns, "session.compaction_complete", (event) => {
353
+ if (event.data.success) try {
354
+ options.onContextCompacted?.();
355
+ } catch {}
367
356
  if (!isRootCompactionEvent(event)) return;
368
357
  activeCompactionCount = Math.max(0, activeCompactionCount - 1);
369
358
  enqueueCompactionCallback(() => options.onCompactionComplete?.({
@@ -553,7 +542,7 @@ function joinReasoning(order, reasoningById) {
553
542
  function splitPlanText(text) {
554
543
  return (text ?? "").split(/\r?\n/).map((line) => line.trim().replace(/^[-*]\s+/, "")).filter((line) => line.length > 0);
555
544
  }
556
- function readString$2(value) {
545
+ function readString$1(value) {
557
546
  return typeof value === "string" && value.length > 0 ? value : void 0;
558
547
  }
559
548
  function registerListener(session, unsubscribeFns, eventType, handler) {
@@ -1113,9 +1102,12 @@ function buildOpenClawCodingToolsOptions(input, toolPlan, toolSurfaceRuntime) {
1113
1102
  elevated: a.bashElevated
1114
1103
  },
1115
1104
  messageProvider: a.messageProvider ?? a.messageChannel,
1105
+ chatType: a.chatType,
1116
1106
  agentAccountId: a.agentAccountId,
1117
1107
  messageTo: a.messageTo,
1118
1108
  messageThreadId: a.messageThreadId,
1109
+ nativeChannelId: a.chatId,
1110
+ messageActionTurnCapability: a.messageActionTurnCapability,
1119
1111
  groupId: a.groupId,
1120
1112
  groupChannel: a.groupChannel,
1121
1113
  groupSpace: a.groupSpace,
@@ -1164,6 +1156,7 @@ function buildOpenClawCodingToolsOptions(input, toolPlan, toolSurfaceRuntime) {
1164
1156
  enableHeartbeatTool: a.enableHeartbeatTool,
1165
1157
  forceHeartbeatTool: a.forceHeartbeatTool,
1166
1158
  authProfileStore: a.toolAuthProfileStore ?? a.authProfileStore,
1159
+ computerContextEpoch: input.computerContextEpoch,
1167
1160
  onToolOutcome: a.onToolOutcome,
1168
1161
  onYield: (message) => {
1169
1162
  try {
@@ -1249,7 +1242,7 @@ function convertOpenClawToolToSdkTool(sourceTool, ctx) {
1249
1242
  } catch (error) {
1250
1243
  return failureResult(preparedArgs, invocation, startedAt, `[copilot-tool-bridge] tool '${sourceTool.name}' failed: ${toError$1(error).message}`, error);
1251
1244
  }
1252
- const sdkResult = agentToolResultToSdk(result);
1245
+ const sdkResult = convertMcpCallToolResult({ content: result.content });
1253
1246
  const sanitizedResult = sanitizeToolResult(result);
1254
1247
  const resultIsError = sdkResult.resultType === "failure" || isToolResultError(sanitizedResult);
1255
1248
  const resultError = resultIsError ? extractToolErrorMessage(sanitizedResult) : void 0;
@@ -1331,51 +1324,6 @@ async function executeCatalogTool(input, params) {
1331
1324
  function toToolStartArgs(args) {
1332
1325
  return args && typeof args === "object" && !Array.isArray(args) ? args : { value: args };
1333
1326
  }
1334
- function agentToolResultToSdk(result) {
1335
- const content = result?.content;
1336
- if (content == null) return createSuccessResult("");
1337
- if (!Array.isArray(content)) return createUnsupportedContentFailure(typeof content);
1338
- const textParts = [];
1339
- const binaryResults = [];
1340
- for (const block of content) {
1341
- if (!block || typeof block !== "object") return createUnsupportedContentFailure(typeof block);
1342
- const kind = readString$1(block.type);
1343
- if (kind === "text") {
1344
- const text = readString$1(block.text, { allowEmpty: true });
1345
- if (text === void 0) return createUnsupportedContentFailure(kind);
1346
- textParts.push(text);
1347
- continue;
1348
- }
1349
- if (kind === "image") {
1350
- const base64Data = readString$1(block.data);
1351
- const mimeType = readString$1(block.mimeType);
1352
- if (!base64Data || !mimeType) return createUnsupportedContentFailure(kind);
1353
- binaryResults.push({
1354
- base64Data,
1355
- data: base64Data,
1356
- mimeType,
1357
- type: "image"
1358
- });
1359
- continue;
1360
- }
1361
- return createUnsupportedContentFailure(kind ?? typeof block);
1362
- }
1363
- return {
1364
- ...binaryResults.length > 0 ? { binaryResultsForLlm: binaryResults } : {},
1365
- resultType: "success",
1366
- textResultForLlm: textParts.join("\n")
1367
- };
1368
- }
1369
- function createUnsupportedContentFailure(kind) {
1370
- const message = `[copilot-tool-bridge] unsupported AgentToolResult content shape: ${kind}`;
1371
- return createFailureResult(message, new Error(message));
1372
- }
1373
- function createSuccessResult(textResultForLlm) {
1374
- return {
1375
- resultType: "success",
1376
- textResultForLlm
1377
- };
1378
- }
1379
1327
  function createFailureResult(message, error) {
1380
1328
  return {
1381
1329
  error: toError$1(error).message,
@@ -1449,10 +1397,6 @@ function findDuplicateToolNames(sourceTools) {
1449
1397
  }
1450
1398
  return [...counts.entries()].filter(([, count]) => count > 1).map(([name]) => name).toSorted();
1451
1399
  }
1452
- function readString$1(value, options = {}) {
1453
- if (typeof value !== "string") return;
1454
- if (options.allowEmpty || value.length > 0) return value;
1455
- }
1456
1400
  function toError$1(error) {
1457
1401
  return error instanceof Error ? error : new Error(String(error));
1458
1402
  }
@@ -1622,9 +1566,9 @@ async function resolveCopilotWorkspaceBootstrapContext(params) {
1622
1566
  * (`src/agents/pi-embedded-runner/run/attempt.ts:603`). Files whose
1623
1567
  * resolved relative path escapes the source workspace (parent
1624
1568
  * traversal or absolute) are left untouched so we never pretend a
1625
- * file lives inside the sandbox when it does not. Exported for unit
1626
- * tests; intentionally local to the Copilot extension (codex keeps
1627
- * similar helpers extension-local rather than importing from PI).
1569
+ * file lives inside the sandbox when it does not. Intentionally local
1570
+ * to the Copilot extension (codex keeps similar helpers extension-local
1571
+ * rather than importing from PI).
1628
1572
  */
1629
1573
  function remapCopilotBootstrapContextFiles(params) {
1630
1574
  if (params.sourceWorkspaceDir === params.targetWorkspaceDir) return params.files;
@@ -1801,6 +1745,7 @@ async function runCopilotAttempt(params, deps) {
1801
1745
  const attemptStartedAt = now();
1802
1746
  const input = params;
1803
1747
  const createToolBridge = deps.createToolBridge ?? createCopilotToolBridge;
1748
+ const ringZeroSystemAgentRun = (deps.isHostScopedToolActive?.("openclaw") ?? isHostScopedAgentToolActive("openclaw")) && isSystemAgentOnlyToolAllowlist(input.toolsAllow);
1804
1749
  const messages = getMessagesSnapshotInput(input);
1805
1750
  const modelRef = resolveModelRef(input);
1806
1751
  const resolvedWorkspaceForSandbox = readResolvedAttemptPath(input.workspaceDir) ?? readResolvedAttemptPath(input.cwd);
@@ -1963,6 +1908,7 @@ async function runCopilotAttempt(params, deps) {
1963
1908
  const cleanupByokProxy = byokProxy?.close;
1964
1909
  const sessionProvider = byokProxy?.provider ?? poolAcquire.provider;
1965
1910
  const sessionRef = { current: void 0 };
1911
+ const computerContextEpoch = { value: 0 };
1966
1912
  try {
1967
1913
  let sdkTools;
1968
1914
  try {
@@ -1980,6 +1926,7 @@ async function runCopilotAttempt(params, deps) {
1980
1926
  spawnWorkspaceDir: sandboxAwareSpawnWorkspaceDir,
1981
1927
  abortSignal: params.abortSignal,
1982
1928
  attemptParams: input,
1929
+ computerContextEpoch,
1983
1930
  sessionRef,
1984
1931
  onYieldDetected: () => {
1985
1932
  yieldDetected = true;
@@ -2054,8 +2001,14 @@ async function runCopilotAttempt(params, deps) {
2054
2001
  signal: params.abortSignal
2055
2002
  });
2056
2003
  userInputBridgeRef = userInputBridge;
2057
- const sessionConfig = createSessionConfig(attemptInput, modelRef.id, sdkTools, poolAcquire.auth, sessionProvider, promptBuild.developerInstructions || void 0, effectiveWorkspaceDir, effectiveCwd, userInputBridge.onUserInputRequest, hasNativePromptHook ? { onUserPromptSubmitted: ({ additionalContext, prompt }) => emitLlmInput(prompt, additionalContext) } : void 0);
2058
- const compactionSessionConfig = byokProxy ? createSessionConfig(attemptInput, modelRef.id, sdkTools, poolAcquire.auth, poolAcquire.provider, promptBuild.developerInstructions || void 0, effectiveWorkspaceDir, effectiveCwd, userInputBridge.onUserInputRequest, hasNativePromptHook ? { onUserPromptSubmitted: ({ additionalContext, prompt }) => emitLlmInput(prompt, additionalContext) } : void 0) : sessionConfig;
2004
+ const sessionConfig = createSessionConfig(attemptInput, modelRef.id, sdkTools, poolAcquire.auth, sessionProvider, promptBuild.developerInstructions || void 0, effectiveWorkspaceDir, effectiveCwd, userInputBridge.onUserInputRequest, {
2005
+ hooksBridgeOptions: hasNativePromptHook ? { onUserPromptSubmitted: ({ additionalContext, prompt }) => emitLlmInput(prompt, additionalContext) } : void 0,
2006
+ includeAskUser: !ringZeroSystemAgentRun
2007
+ });
2008
+ const compactionSessionConfig = byokProxy ? createSessionConfig(attemptInput, modelRef.id, sdkTools, poolAcquire.auth, poolAcquire.provider, promptBuild.developerInstructions || void 0, effectiveWorkspaceDir, effectiveCwd, userInputBridge.onUserInputRequest, {
2009
+ hooksBridgeOptions: hasNativePromptHook ? { onUserPromptSubmitted: ({ additionalContext, prompt }) => emitLlmInput(prompt, additionalContext) } : void 0,
2010
+ includeAskUser: !ringZeroSystemAgentRun
2011
+ }) : sessionConfig;
2059
2012
  const replayDecision = decideReplayAction({
2060
2013
  sdkSessionId: input.initialReplayState?.sdkSessionId,
2061
2014
  replayInvalid: input.initialReplayState?.replayInvalid
@@ -2088,6 +2041,11 @@ async function runCopilotAttempt(params, deps) {
2088
2041
  onAssistantDelta: input.onAssistantDelta,
2089
2042
  onAgentEvent: input.onAgentEvent,
2090
2043
  onNativeSubagentEvent: (event) => nativeSubagentTaskMirror?.handleEvent(event),
2044
+ onContextCompacted: () => {
2045
+ computerContextEpoch.value += 1;
2046
+ delete computerContextEpoch.frameToolCallId;
2047
+ delete computerContextEpoch.frameImageIdentity;
2048
+ },
2091
2049
  onCompactionStart: async () => {
2092
2050
  const sessionFile = readString(input.sessionFile);
2093
2051
  if (!sessionFile) return;
@@ -2245,20 +2203,21 @@ async function runCopilotAttempt(params, deps) {
2245
2203
  ...syntheticUser ? [syntheticUser] : [],
2246
2204
  ...taggedLastAssistant ? [taggedLastAssistant] : []
2247
2205
  ];
2248
- const sessionFileForMirror = readString(input.sessionFile);
2249
2206
  const openClawSessionIdForMirror = readString(input.sessionId);
2207
+ const openClawSessionKeyForMirror = readString(input.sessionKey);
2208
+ const openClawStorePathForMirror = readString(input.sessionTarget?.storePath);
2250
2209
  const mirrorScopeSessionId = sessionIdUsed ?? openClawSessionIdForMirror;
2251
- if (sessionFileForMirror && openClawSessionIdForMirror && messagesSnapshot.length > 0) {
2210
+ if (openClawSessionIdForMirror && openClawSessionKeyForMirror && openClawStorePathForMirror && messagesSnapshot.length > 0) {
2252
2211
  const taggedMessages = messagesSnapshot.map((message, index) => {
2253
2212
  if (message.role !== "user" && message.role !== "assistant" && message.role !== "toolResult") return message;
2254
2213
  if (hasMirrorIdentity(message)) return message;
2255
2214
  return attachCopilotMirrorIdentity(message, `${sdkSessionId ?? mirrorScopeSessionId ?? "attempt"}:${message.role}:${index}`);
2256
2215
  });
2257
2216
  await dualWriteCopilotTranscriptBestEffort({
2258
- sessionFile: sessionFileForMirror,
2259
2217
  sessionId: openClawSessionIdForMirror,
2260
- sessionKey: readString(input.sessionKey),
2218
+ sessionKey: openClawSessionKeyForMirror,
2261
2219
  agentId: readString(input.agentId),
2220
+ storePath: openClawStorePathForMirror,
2262
2221
  messages: taggedMessages,
2263
2222
  idempotencyScope: mirrorScopeSessionId ? `copilot:${mirrorScopeSessionId}` : void 0,
2264
2223
  config: input.config
@@ -2364,10 +2323,9 @@ function createPromptError(code, message, cause) {
2364
2323
  if (cause !== void 0) error.cause = cause;
2365
2324
  return error;
2366
2325
  }
2367
- function createSessionConfig(params, sdkModelId, sdkTools, resolvedAuth, resolvedProvider, systemMessageContent, effectiveWorkspaceDir, effectiveCwd, onUserInputRequest, hooksBridgeOptions) {
2326
+ function createSessionConfig(params, sdkModelId, sdkTools, resolvedAuth, resolvedProvider, systemMessageContent, effectiveWorkspaceDir, effectiveCwd, onUserInputRequest, options) {
2368
2327
  const permissionPolicy = params.permissionPolicy ?? rejectAllPolicy;
2369
- const hooks = createHooksBridge(params.hooksConfig, hooksBridgeOptions);
2370
- const infiniteSessions = createInfiniteSessionConfig(params.infiniteSessionConfig);
2328
+ const hooks = createHooksBridge(params.hooksConfig, options.hooksBridgeOptions);
2371
2329
  return {
2372
2330
  model: sdkModelId,
2373
2331
  onPermissionRequest: createPermissionBridge(permissionPolicy),
@@ -2375,10 +2333,10 @@ function createSessionConfig(params, sdkModelId, sdkTools, resolvedAuth, resolve
2375
2333
  ...resolvedProvider.provider ? { provider: resolvedProvider.provider } : {},
2376
2334
  ...hooks ? { hooks } : {},
2377
2335
  ...typeof params.enableSessionTelemetry === "boolean" ? { enableSessionTelemetry: params.enableSessionTelemetry } : {},
2378
- ...infiniteSessions ? { infiniteSessions } : {},
2336
+ ...params.infiniteSessionConfig ? { infiniteSessions: params.infiniteSessionConfig } : {},
2379
2337
  reasoningEffort: params.reasoningEffort,
2380
2338
  tools: sdkTools,
2381
- availableTools: buildCopilotAvailableTools(sdkTools),
2339
+ availableTools: buildCopilotAvailableTools(sdkTools, options.includeAskUser),
2382
2340
  workingDirectory: effectiveCwd ?? effectiveWorkspaceDir ?? readResolvedAttemptPath(params.workspaceDir),
2383
2341
  ...effectiveWorkspaceDir && effectiveCwd && effectiveCwd !== effectiveWorkspaceDir ? { instructionDirectories: [effectiveWorkspaceDir] } : {},
2384
2342
  ...resolvedAuth.authMode === "gitHubToken" && resolvedAuth.gitHubToken ? { gitHubToken: resolvedAuth.gitHubToken } : {},
@@ -2388,8 +2346,13 @@ function createSessionConfig(params, sdkModelId, sdkTools, resolvedAuth, resolve
2388
2346
  } } : {}
2389
2347
  };
2390
2348
  }
2391
- function buildCopilotAvailableTools(sdkTools) {
2392
- return [.../* @__PURE__ */ new Set([...sdkTools.map((tool) => tool.name), ...COPILOT_ASK_USER_AVAILABLE_TOOLS])];
2349
+ function buildCopilotAvailableTools(sdkTools, includeAskUser) {
2350
+ const availableTools = sdkTools.map((tool) => tool.name);
2351
+ if (includeAskUser) availableTools.push(...COPILOT_ASK_USER_AVAILABLE_TOOLS);
2352
+ return [...new Set(availableTools)];
2353
+ }
2354
+ function isSystemAgentOnlyToolAllowlist(toolsAllow) {
2355
+ return toolsAllow?.length === 1 && toolsAllow[0]?.trim().toLowerCase() === "openclaw";
2393
2356
  }
2394
2357
  async function createMessageOptions(params, context) {
2395
2358
  const attachments = createPromptImageAttachments(await resolvePromptImages(params, context));
@@ -10,8 +10,7 @@ function normalizeCompatibilityConfig({ cfg }) {
10
10
  * Session-state ownership claim for the copilot agent runtime.
11
11
  *
12
12
  * - id / label: Identify the extension in doctor output.
13
- * - providerIds: The subscription Copilot providers (kept in sync
14
- * with `SUPPORTED_PROVIDERS` in attempt.ts).
13
+ * - providerIds: The subscription Copilot providers.
15
14
  * - runtimeIds: Our harness id (matches harness.ts `id` field).
16
15
  * - cliSessionKeys: Session keys this harness writes; doctor uses
17
16
  * this when pruning stale CLI session state.
@@ -481,7 +481,7 @@ function resolveCopilotProvider(params) {
481
481
  };
482
482
  }
483
483
  function isCopilotByokUnsupportedProviderError(error) {
484
- return error instanceof Error && (error.message === "[copilot-attempt] BYOK requires an OpenAI-compatible or Anthropic model api and a non-empty baseUrl" || error.message === "[copilot-attempt] BYOK does not support OpenClaw provider request proxy, TLS, or private-network policy overrides" || error.message === "[copilot-attempt] BYOK endpoint is blocked by OpenClaw SSRF policy");
484
+ return error instanceof Error && (error.message === COPILOT_BYOK_PROVIDER_ERROR || error.message === COPILOT_BYOK_TRANSPORT_POLICY_ERROR || error.message === COPILOT_BYOK_ENDPOINT_POLICY_ERROR);
485
485
  }
486
486
  function supportsCopilotByokProviderShape(model) {
487
487
  if (!readString(model.baseUrl) || hasUnsupportedTransportPolicy(model)) return false;
@@ -894,7 +894,7 @@ function createCopilotAgentHarness(options) {
894
894
  async runAttempt(params) {
895
895
  const attemptPromise = (async () => {
896
896
  if (disposed) throw new Error("[copilot] harness has been disposed; cannot start new attempts");
897
- const { resolvePoolAcquire, runCopilotAttempt } = await import("./attempt-D6MSc00N.js");
897
+ const { resolvePoolAcquire, runCopilotAttempt } = await import("./attempt-BxxMpQmE.js");
898
898
  if (disposed) throw new Error("[copilot] harness was disposed while starting an attempt");
899
899
  const pool = await getPool();
900
900
  if (disposed) throw new Error("[copilot] harness was disposed while starting an attempt");
@@ -1010,7 +1010,7 @@ function createCopilotAgentHarness(options) {
1010
1010
  };
1011
1011
  const tracked = trackedSessions.get(openclawSessionId);
1012
1012
  const currentCompactKey = computeSessionCompactKey(params);
1013
- const { resolvePoolAcquire } = await import("./attempt-D6MSc00N.js");
1013
+ const { resolvePoolAcquire } = await import("./attempt-BxxMpQmE.js");
1014
1014
  let resolvedPoolAcquire;
1015
1015
  let currentAuth;
1016
1016
  try {
package/dist/harness.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as createCopilotAgentHarness } from "./harness-BQhGzc1Z.js";
1
+ import { t as createCopilotAgentHarness } from "./harness-DnbBZBdi.js";
2
2
  export { createCopilotAgentHarness };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as createCopilotAgentHarness } from "./harness-BQhGzc1Z.js";
1
+ import { t as createCopilotAgentHarness } from "./harness-DnbBZBdi.js";
2
2
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
3
3
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  //#region extensions/copilot/index.ts
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/copilot",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/copilot",
9
- "version": "2026.7.1",
9
+ "version": "2026.7.2-beta.1",
10
10
  "dependencies": {
11
11
  "@github/copilot-sdk": "1.0.5"
12
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/copilot",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.1",
4
4
  "description": "OpenClaw GitHub Copilot agent runtime plugin (registers a `github-copilot` AgentHarness backed by @github/copilot-sdk over JSON-RPC to the GitHub Copilot CLI)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,10 +25,10 @@
25
25
  "minHostVersion": ">=2026.5.28"
26
26
  },
27
27
  "compat": {
28
- "pluginApi": ">=2026.7.1"
28
+ "pluginApi": ">=2026.7.2-beta.1"
29
29
  },
30
30
  "build": {
31
- "openclawVersion": "2026.7.1",
31
+ "openclawVersion": "2026.7.2-beta.1",
32
32
  "bundledDist": false
33
33
  },
34
34
  "release": {
@@ -47,7 +47,7 @@
47
47
  "README.md"
48
48
  ],
49
49
  "peerDependencies": {
50
- "openclaw": ">=2026.7.1"
50
+ "openclaw": ">=2026.7.2-beta.1"
51
51
  },
52
52
  "peerDependenciesMeta": {
53
53
  "openclaw": {