@github/copilot-sdk 1.0.14-preview.0 → 1.0.14-preview.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/dist/cjs/factory.js +1 -0
- package/dist/cjs/session.js +55 -8
- package/dist/factory.d.ts +42 -16
- package/dist/factory.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/session.d.ts +1 -0
- package/dist/session.js +56 -9
- package/docs/factories.md +36 -19
- package/package.json +9 -9
package/dist/cjs/factory.js
CHANGED
package/dist/cjs/session.js
CHANGED
|
@@ -41,10 +41,14 @@ const factoryExecutionStore = new import_node_async_hooks.AsyncLocalStorage();
|
|
|
41
41
|
function throwIfFactoryExecutionIsActive() {
|
|
42
42
|
if (factoryExecutionStore.getStore()?.active) {
|
|
43
43
|
throw new Error(
|
|
44
|
-
"factory.run and factory.
|
|
44
|
+
"factory.run, factory.resume, and factory.pause are not allowed while a factory body is running on this call path."
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
function runInFactoryHelperScope(helperScope, callback) {
|
|
49
|
+
const current = factoryExecutionStore.getStore();
|
|
50
|
+
return factoryExecutionStore.run({ active: current?.active ?? false, helperScope }, callback);
|
|
51
|
+
}
|
|
48
52
|
function deserializeHookInput(raw) {
|
|
49
53
|
if (!raw || typeof raw !== "object" || typeof raw.timestamp !== "number") {
|
|
50
54
|
return raw;
|
|
@@ -88,7 +92,7 @@ async function runFactoryParallel(thunks) {
|
|
|
88
92
|
}
|
|
89
93
|
return Promise.all(
|
|
90
94
|
thunks.map(
|
|
91
|
-
(thunk) => Promise.resolve().then(() => thunk
|
|
95
|
+
(thunk) => Promise.resolve().then(() => runInFactoryHelperScope("parallel", thunk)).catch((error) => {
|
|
92
96
|
if (isFactoryFatalError(error)) {
|
|
93
97
|
throw error;
|
|
94
98
|
}
|
|
@@ -107,7 +111,10 @@ async function runFactoryPipeline(items, ...stages) {
|
|
|
107
111
|
let previous = item;
|
|
108
112
|
for (const stage of stages) {
|
|
109
113
|
try {
|
|
110
|
-
previous = await
|
|
114
|
+
previous = await runInFactoryHelperScope(
|
|
115
|
+
"pipeline",
|
|
116
|
+
() => stage(previous, item, index)
|
|
117
|
+
);
|
|
111
118
|
} catch (error) {
|
|
112
119
|
if (isFactoryFatalError(error)) {
|
|
113
120
|
throw error;
|
|
@@ -264,6 +271,7 @@ class CopilotSession {
|
|
|
264
271
|
hooks;
|
|
265
272
|
transformCallbacks;
|
|
266
273
|
_rpc = null;
|
|
274
|
+
_internalRpc = null;
|
|
267
275
|
traceContextProvider;
|
|
268
276
|
managedSettingsEnabled;
|
|
269
277
|
_capabilities = {};
|
|
@@ -330,6 +338,10 @@ class CopilotSession {
|
|
|
330
338
|
}),
|
|
331
339
|
getRunDetail: (runId) => this.rpc.factory.getRunDetail({ runId }),
|
|
332
340
|
getRunProgress: (runId, options = {}) => this.rpc.factory.getRunProgress({ runId, ...options }),
|
|
341
|
+
pause: async (runId) => {
|
|
342
|
+
throwIfFactoryExecutionIsActive();
|
|
343
|
+
return this.rpc.factory.pause({ runId });
|
|
344
|
+
},
|
|
333
345
|
cancel: async (runId) => this.rpc.factory.cancel({ runId })
|
|
334
346
|
};
|
|
335
347
|
/**
|
|
@@ -428,6 +440,13 @@ class CopilotSession {
|
|
|
428
440
|
}
|
|
429
441
|
return this._rpc;
|
|
430
442
|
}
|
|
443
|
+
/** @internal */
|
|
444
|
+
get internalRpc() {
|
|
445
|
+
if (!this._internalRpc) {
|
|
446
|
+
this._internalRpc = (0, import_rpc.createInternalSessionRpc)(this.connection, this.sessionId);
|
|
447
|
+
}
|
|
448
|
+
return this._internalRpc;
|
|
449
|
+
}
|
|
431
450
|
/**
|
|
432
451
|
* Path to the session workspace directory when infinite sessions are enabled.
|
|
433
452
|
* Contains checkpoints/, plan.md, and files/ subdirectories.
|
|
@@ -1110,6 +1129,36 @@ class CopilotSession {
|
|
|
1110
1129
|
);
|
|
1111
1130
|
return result2;
|
|
1112
1131
|
},
|
|
1132
|
+
pause: async (key) => {
|
|
1133
|
+
if (typeof key !== "string" || key.length === 0) {
|
|
1134
|
+
throw new Error("Factory pause checkpoint key must not be empty");
|
|
1135
|
+
}
|
|
1136
|
+
const helperScope = factoryExecutionStore.getStore()?.helperScope;
|
|
1137
|
+
if (helperScope !== void 0) {
|
|
1138
|
+
throw new Error(
|
|
1139
|
+
`Factory pause checkpoints are not allowed inside ${helperScope}() branches`
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
await progress.flush();
|
|
1143
|
+
const response = await awaitFactoryOperation(
|
|
1144
|
+
() => self.internalRpc.factory.pauseAtCheckpoint({
|
|
1145
|
+
runId: params.runId,
|
|
1146
|
+
executionToken: params.executionToken,
|
|
1147
|
+
key
|
|
1148
|
+
}),
|
|
1149
|
+
controller.signal
|
|
1150
|
+
);
|
|
1151
|
+
switch (response.action) {
|
|
1152
|
+
case "continue":
|
|
1153
|
+
return;
|
|
1154
|
+
case "pause":
|
|
1155
|
+
await awaitFactoryOperation(
|
|
1156
|
+
() => new Promise(() => {
|
|
1157
|
+
}),
|
|
1158
|
+
controller.signal
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
},
|
|
1113
1162
|
parallel: runFactoryParallel,
|
|
1114
1163
|
pipeline: runFactoryPipeline,
|
|
1115
1164
|
factory: async () => {
|
|
@@ -1145,11 +1194,9 @@ class CopilotSession {
|
|
|
1145
1194
|
},
|
|
1146
1195
|
async abort(params) {
|
|
1147
1196
|
const controllersForRun = self.factoryAbortControllers.get(params.runId);
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
controller.abort(reason);
|
|
1152
|
-
}
|
|
1197
|
+
const controller = controllersForRun?.get(params.executionToken);
|
|
1198
|
+
if (controller !== void 0) {
|
|
1199
|
+
controller.abort(new DOMException("Factory run was aborted", "AbortError"));
|
|
1153
1200
|
}
|
|
1154
1201
|
return {};
|
|
1155
1202
|
}
|
package/dist/factory.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FactoryGetRunProgressRequest, FactoryListRunsRequest, FactoryListRunsResult, FactoryProgressPage, FactoryRunDetail, FactoryRunResult, FactoryRunStatus, FactoryRunSummary } from "./generated/rpc.js";
|
|
2
2
|
import type { ContextTier } from "./generated/session-events.js";
|
|
3
3
|
import type { CopilotSession } from "./session.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { FactoryMeta } from "./types.js";
|
|
5
5
|
export type { FactoryRunResult };
|
|
6
6
|
export type { FactoryAgentSummary, FactoryPhaseStatus, FactoryPhaseObservation, FactoryProgressLine, FactoryProgressPage, FactoryRunDetail, FactoryRunStatus, FactoryRunSummary, } from "./generated/rpc.js";
|
|
7
7
|
/**
|
|
@@ -81,6 +81,21 @@ export interface FactoryStepOptions {
|
|
|
81
81
|
/** Skip the journal and always invoke the producer. */
|
|
82
82
|
volatile?: boolean;
|
|
83
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Per-invocation factory resource ceiling overrides.
|
|
86
|
+
*
|
|
87
|
+
* An omitted field preserves the existing/default ceiling, a number replaces
|
|
88
|
+
* it, and `null` explicitly makes that dimension unlimited.
|
|
89
|
+
*
|
|
90
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
91
|
+
* change or be removed in future SDK or CLI releases.
|
|
92
|
+
*/
|
|
93
|
+
export interface FactoryLimitOverrides {
|
|
94
|
+
maxConcurrentSubagents?: number | null;
|
|
95
|
+
maxTotalSubagents?: number | null;
|
|
96
|
+
maxAiCredits?: number | null;
|
|
97
|
+
timeoutSeconds?: number | null;
|
|
98
|
+
}
|
|
84
99
|
/**
|
|
85
100
|
* One stage in a per-item factory pipeline.
|
|
86
101
|
*
|
|
@@ -101,6 +116,13 @@ export interface FactoryContext<TArgs extends JsonValue = JsonValue> {
|
|
|
101
116
|
agent(prompt: string, options?: FactoryAgentOptions): Promise<unknown>;
|
|
102
117
|
/** Memoize an arbitrary producer under a stable author-supplied key. */
|
|
103
118
|
step(key: string, producer: () => Promise<JsonValue> | JsonValue, options?: FactoryStepOptions): Promise<JsonValue>;
|
|
119
|
+
/**
|
|
120
|
+
* Pause this run at a durable, one-shot checkpoint.
|
|
121
|
+
*
|
|
122
|
+
* The first attempt to reach a key pauses and aborts cooperatively. A
|
|
123
|
+
* resumed attempt returns from the same key and continues.
|
|
124
|
+
*/
|
|
125
|
+
pause(key: string): Promise<void>;
|
|
104
126
|
/**
|
|
105
127
|
* Run thunks concurrently and await all of them.
|
|
106
128
|
*
|
|
@@ -129,7 +151,7 @@ export interface FactoryContext<TArgs extends JsonValue = JsonValue> {
|
|
|
129
151
|
args: TArgs;
|
|
130
152
|
/**
|
|
131
153
|
* The session instance returned by `joinSession`. It refuses calls that
|
|
132
|
-
* start or
|
|
154
|
+
* start, resume, or pause a factory run.
|
|
133
155
|
*/
|
|
134
156
|
session: CopilotSession;
|
|
135
157
|
/** Cooperative cancellation signal for the current factory run. */
|
|
@@ -178,7 +200,7 @@ export interface RunOptions<TArgs extends JsonValue = JsonValue> {
|
|
|
178
200
|
/** Input surfaced as `context.args`. */
|
|
179
201
|
args?: TArgs;
|
|
180
202
|
/** Optional per-invocation resource ceiling overrides. */
|
|
181
|
-
limits?:
|
|
203
|
+
limits?: FactoryLimitOverrides;
|
|
182
204
|
/** Whether to notify the originating session when the factory completes. */
|
|
183
205
|
notifyOnComplete?: boolean;
|
|
184
206
|
/** Whether to emit factory phase names to the session transcript. */
|
|
@@ -198,7 +220,7 @@ export interface RunOptions<TArgs extends JsonValue = JsonValue> {
|
|
|
198
220
|
*/
|
|
199
221
|
export interface ResumeOptions {
|
|
200
222
|
/** Optional per-invocation resource ceiling overrides. */
|
|
201
|
-
limits?:
|
|
223
|
+
limits?: FactoryLimitOverrides;
|
|
202
224
|
/** Whether to notify the originating session when the factory completes. */
|
|
203
225
|
notifyOnComplete?: boolean;
|
|
204
226
|
/** Whether to emit factory phase names to the session transcript. */
|
|
@@ -222,13 +244,14 @@ export interface SessionFactoryApi {
|
|
|
222
244
|
* Run a registered factory and resolve with its run envelope.
|
|
223
245
|
*
|
|
224
246
|
* The envelope is returned for every outcome, including `error`, `halted`,
|
|
225
|
-
* and `cancelled` — inspect `status` and read `result` only when
|
|
226
|
-
* completed.
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
247
|
+
* `paused`, and `cancelled` — inspect `status` and read `result` only when
|
|
248
|
+
* the run completed. `paused` settles the current attempt, but the same
|
|
249
|
+
* durable run can later resume under its existing run ID. SDK-initiated
|
|
250
|
+
* runs do not request permission, so they have no declined outcome. The
|
|
251
|
+
* model's `run_factory` tool requests permission before a durable row
|
|
252
|
+
* exists; declining it creates no run row. Failures that occur before a run
|
|
253
|
+
* exists (such as an unknown factory or attempting to start a run while the
|
|
254
|
+
* session is at its active top-level run limit) still reject.
|
|
232
255
|
*/
|
|
233
256
|
run(name: string, options?: RunOptions): Promise<FactoryRunResult>;
|
|
234
257
|
run<TArgs extends JsonValue>(factory: FactoryHandle<TArgs, JsonValue | void>, options?: RunOptions<TArgs>): Promise<FactoryRunResult>;
|
|
@@ -243,12 +266,13 @@ export interface SessionFactoryApi {
|
|
|
243
266
|
/** Read the latest durable envelope for a factory run. */
|
|
244
267
|
getRun(runId: string): Promise<FactoryRunResult>;
|
|
245
268
|
/**
|
|
246
|
-
* Wait for
|
|
269
|
+
* Wait for the current attempt to settle and resolve with its envelope.
|
|
247
270
|
*
|
|
248
|
-
* Resolves as soon as the run reaches `completed`, `error`, `halted`,
|
|
249
|
-
* `cancelled`, and resolves immediately when
|
|
250
|
-
*
|
|
251
|
-
*
|
|
271
|
+
* Resolves as soon as the run reaches `completed`, `error`, `halted`,
|
|
272
|
+
* `paused`, or `cancelled`, and resolves immediately when the current
|
|
273
|
+
* attempt has already settled. A `paused` envelope is an attempt-level
|
|
274
|
+
* snapshot: resuming the same durable run can later change the envelope
|
|
275
|
+
* returned by {@link SessionFactoryApi.getRun}.
|
|
252
276
|
*
|
|
253
277
|
* This watches the run's `factory.run_updated` invalidation events and
|
|
254
278
|
* periodically re-reads the durable envelope so a missed event cannot
|
|
@@ -279,6 +303,8 @@ export interface SessionFactoryApi {
|
|
|
279
303
|
getRunDetail(runId: string): Promise<FactoryRunDetail>;
|
|
280
304
|
/** Page durable progress forward, backward, or from the latest tail. */
|
|
281
305
|
getRunProgress(runId: string, options?: Omit<FactoryGetRunProgressRequest, "runId">): Promise<FactoryProgressPage>;
|
|
306
|
+
/** Pause a running factory attempt and return its `paused` envelope. */
|
|
307
|
+
pause(runId: string): Promise<FactoryRunResult>;
|
|
282
308
|
/** Cancel a factory run and return its terminal envelope. */
|
|
283
309
|
cancel(runId: string): Promise<FactoryRunResult>;
|
|
284
310
|
}
|
package/dist/factory.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -12,4 +12,4 @@ export { Canvas, CanvasError, createCanvas, type CanvasAction, type CanvasDeclar
|
|
|
12
12
|
export { defineTool, approveAll, createAttributedPermissionResult, convertMcpCallToolResult, createSessionFsAdapter, CopilotRequestHandler, CopilotWebSocketHandler, CopilotWebSocketCloseStatus, CopilotWebSocketForwarder, SessionFsSqliteTransactionFailure, SYSTEM_MESSAGE_SECTIONS, } from "./types.js";
|
|
13
13
|
export type * from "./generated/session-events.js";
|
|
14
14
|
export type { AskUserVariant, CommandContext, CommandDefinition, CommandHandler, CanvasProviderIdentity, CloudSessionOptions, CloudSessionRepository, AutoModeSwitchHandler, AutoModeSwitchRequest, AutoModeSwitchResponse, AgentStopHandler, AgentStopHookInput, AgentStopHookOutput, UserPromptTransformedHandler, UserPromptTransformedHookInput, UserPromptTransformedHookOutput, CopilotClientInfo, CopilotClientMode, CopilotClientOptions, CopilotExpAssignmentResponse, StdioRuntimeConnection, InProcessRuntimeConnection, TcpRuntimeConnection, UriRuntimeConnection, ChildProcessRuntimeConnection, CustomAgentConfig, ElicitationFieldValue, ElicitationHandler, ElicitationParams, ElicitationContext, ElicitationResult, ElicitationSchema, ElicitationSchemaField, ExpConfigEntry, ExpFlagValue, ExitPlanModeHandler, ExitPlanModeRequest, ExitPlanModeResult, ExtensionInfo, ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse, GitHubMcpToolConfig, GitHubTelemetryNotification, GitHubTelemetryEvent, GitHubTelemetryClientInfo, GitHubTokenAcquireReason, GitHubTokenAcquireResult, GitHubTokenProvider, GitHubTokenProviderArgs, GitHubTokenProviderResult, InfiniteSessionConfig, LargeToolOutputConfig, MemoryConfiguration, UiInputOptions, FactoryLimits, FactoryMeta, MCPStdioServerConfig, MCPHTTPServerConfig, MCPServerConfig, DefaultAgentConfig, BearerTokenProvider, MessageOptions, MessageSource, ManagedSettings, ManagedSettingsPermissions, ModelBilling, ModelBillingTokenPrices, ModelBillingTokenPricesLongContext, AutoTier, CapiSessionOptions, CurrentModel, ModelSwitchAutoTierResult, ModelSwitchAutoTierStatus, ModelCapabilities, ModelCapabilitiesOverride, ModelInfo, ModelPolicy, NamedProviderConfig, PermissionHandler, PermissionRequest, PermissionRequestedData, PermissionRequestedEvent, PermissionRequestResult, AttributedPermissionResult, PermissionDecisionContext, PermissionDecisionOutcome, PermissionDecisionSource, PermissionDecisionSurface, PermissionResponseCapability, ProviderConfig, ProviderModelConfig, ProviderTokenArgs, RemoteSessionMode, ResumeSessionConfig, SectionOverride, SectionOverrideAction, SectionTransformFn, SessionCapabilities, SessionConfig, SessionConfigBase, SessionEvent, SessionEventHandler, SessionEventPayload, SessionEventType, SessionLifecycleEvent, SessionLifecycleEventMetadata, SessionLifecycleEventType, SessionLifecycleHandler, SessionHooks, SessionCreatedEvent, SessionDeletedEvent, SessionUpdatedEvent, SessionForegroundEvent, SessionBackgroundEvent, SessionContext, SessionListFilter, SessionMetadata, SessionUiApi, SessionFsConfig, SessionFsProvider, SessionFsFileInfo, SessionFsSqliteQueryResult, SessionFsSqliteQueryType, SessionFsSqliteProvider, SessionFsSqliteStatement, SessionFsSqliteTransactionErrorClass, CopilotRequestContext, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageCustomizeConfig, SystemMessageReplaceConfig, SystemMessageSection, TelemetryConfig, TraceContext, TraceContextProvider, Tool, ToolHandler, ToolInvocation, CurrentToolMetadata, ToolTelemetry, ToolResultObject, ToolSearchConfig, TypedSessionEventHandler, TypedSessionLifecycleHandler, ZodSchema, } from "./types.js";
|
|
15
|
-
export type { RunOptions, ResumeOptions, FactoryResumeErrorCode, SessionFactoryApi, FactoryAgentOptions, FactoryContext, FactoryDefinition, FactoryHandle, FactoryJsonSchema, JsonValue, FactoryPipelineStage, FactoryStepOptions, FactoryRunResult, FactoryRunStatus, FactoryRunSummary, FactoryListRunsOptions, FactoryRunsPage, FactoryRunDetail, FactoryProgressPage, FactoryProgressLine, FactoryPhaseObservation, FactoryPhaseStatus, FactoryAgentSummary, } from "./factory.js";
|
|
15
|
+
export type { RunOptions, ResumeOptions, FactoryLimitOverrides, FactoryResumeErrorCode, SessionFactoryApi, FactoryAgentOptions, FactoryContext, FactoryDefinition, FactoryHandle, FactoryJsonSchema, JsonValue, FactoryPipelineStage, FactoryStepOptions, FactoryRunResult, FactoryRunStatus, FactoryRunSummary, FactoryListRunsOptions, FactoryRunsPage, FactoryRunDetail, FactoryProgressPage, FactoryProgressLine, FactoryPhaseObservation, FactoryPhaseStatus, FactoryAgentSummary, } from "./factory.js";
|
package/dist/session.d.ts
CHANGED
package/dist/session.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
2
|
import { ConnectionError, ErrorCodes, ResponseError } from "vscode-jsonrpc/node.js";
|
|
3
|
-
import { createSessionRpc } from "./generated/rpc.js";
|
|
3
|
+
import { createInternalSessionRpc, createSessionRpc } from "./generated/rpc.js";
|
|
4
4
|
import { CanvasError } from "./canvas.js";
|
|
5
5
|
import { getTraceContext } from "./telemetry.js";
|
|
6
6
|
import { isAttributedPermissionResult } from "./types.js";
|
|
@@ -23,10 +23,14 @@ const factoryExecutionStore = new AsyncLocalStorage();
|
|
|
23
23
|
function throwIfFactoryExecutionIsActive() {
|
|
24
24
|
if (factoryExecutionStore.getStore()?.active) {
|
|
25
25
|
throw new Error(
|
|
26
|
-
"factory.run and factory.
|
|
26
|
+
"factory.run, factory.resume, and factory.pause are not allowed while a factory body is running on this call path."
|
|
27
27
|
);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
function runInFactoryHelperScope(helperScope, callback) {
|
|
31
|
+
const current = factoryExecutionStore.getStore();
|
|
32
|
+
return factoryExecutionStore.run({ active: current?.active ?? false, helperScope }, callback);
|
|
33
|
+
}
|
|
30
34
|
function deserializeHookInput(raw) {
|
|
31
35
|
if (!raw || typeof raw !== "object" || typeof raw.timestamp !== "number") {
|
|
32
36
|
return raw;
|
|
@@ -70,7 +74,7 @@ async function runFactoryParallel(thunks) {
|
|
|
70
74
|
}
|
|
71
75
|
return Promise.all(
|
|
72
76
|
thunks.map(
|
|
73
|
-
(thunk) => Promise.resolve().then(() => thunk
|
|
77
|
+
(thunk) => Promise.resolve().then(() => runInFactoryHelperScope("parallel", thunk)).catch((error) => {
|
|
74
78
|
if (isFactoryFatalError(error)) {
|
|
75
79
|
throw error;
|
|
76
80
|
}
|
|
@@ -89,7 +93,10 @@ async function runFactoryPipeline(items, ...stages) {
|
|
|
89
93
|
let previous = item;
|
|
90
94
|
for (const stage of stages) {
|
|
91
95
|
try {
|
|
92
|
-
previous = await
|
|
96
|
+
previous = await runInFactoryHelperScope(
|
|
97
|
+
"pipeline",
|
|
98
|
+
() => stage(previous, item, index)
|
|
99
|
+
);
|
|
93
100
|
} catch (error) {
|
|
94
101
|
if (isFactoryFatalError(error)) {
|
|
95
102
|
throw error;
|
|
@@ -246,6 +253,7 @@ class CopilotSession {
|
|
|
246
253
|
hooks;
|
|
247
254
|
transformCallbacks;
|
|
248
255
|
_rpc = null;
|
|
256
|
+
_internalRpc = null;
|
|
249
257
|
traceContextProvider;
|
|
250
258
|
managedSettingsEnabled;
|
|
251
259
|
_capabilities = {};
|
|
@@ -312,6 +320,10 @@ class CopilotSession {
|
|
|
312
320
|
}),
|
|
313
321
|
getRunDetail: (runId) => this.rpc.factory.getRunDetail({ runId }),
|
|
314
322
|
getRunProgress: (runId, options = {}) => this.rpc.factory.getRunProgress({ runId, ...options }),
|
|
323
|
+
pause: async (runId) => {
|
|
324
|
+
throwIfFactoryExecutionIsActive();
|
|
325
|
+
return this.rpc.factory.pause({ runId });
|
|
326
|
+
},
|
|
315
327
|
cancel: async (runId) => this.rpc.factory.cancel({ runId })
|
|
316
328
|
};
|
|
317
329
|
/**
|
|
@@ -410,6 +422,13 @@ class CopilotSession {
|
|
|
410
422
|
}
|
|
411
423
|
return this._rpc;
|
|
412
424
|
}
|
|
425
|
+
/** @internal */
|
|
426
|
+
get internalRpc() {
|
|
427
|
+
if (!this._internalRpc) {
|
|
428
|
+
this._internalRpc = createInternalSessionRpc(this.connection, this.sessionId);
|
|
429
|
+
}
|
|
430
|
+
return this._internalRpc;
|
|
431
|
+
}
|
|
413
432
|
/**
|
|
414
433
|
* Path to the session workspace directory when infinite sessions are enabled.
|
|
415
434
|
* Contains checkpoints/, plan.md, and files/ subdirectories.
|
|
@@ -1092,6 +1111,36 @@ class CopilotSession {
|
|
|
1092
1111
|
);
|
|
1093
1112
|
return result2;
|
|
1094
1113
|
},
|
|
1114
|
+
pause: async (key) => {
|
|
1115
|
+
if (typeof key !== "string" || key.length === 0) {
|
|
1116
|
+
throw new Error("Factory pause checkpoint key must not be empty");
|
|
1117
|
+
}
|
|
1118
|
+
const helperScope = factoryExecutionStore.getStore()?.helperScope;
|
|
1119
|
+
if (helperScope !== void 0) {
|
|
1120
|
+
throw new Error(
|
|
1121
|
+
`Factory pause checkpoints are not allowed inside ${helperScope}() branches`
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
await progress.flush();
|
|
1125
|
+
const response = await awaitFactoryOperation(
|
|
1126
|
+
() => self.internalRpc.factory.pauseAtCheckpoint({
|
|
1127
|
+
runId: params.runId,
|
|
1128
|
+
executionToken: params.executionToken,
|
|
1129
|
+
key
|
|
1130
|
+
}),
|
|
1131
|
+
controller.signal
|
|
1132
|
+
);
|
|
1133
|
+
switch (response.action) {
|
|
1134
|
+
case "continue":
|
|
1135
|
+
return;
|
|
1136
|
+
case "pause":
|
|
1137
|
+
await awaitFactoryOperation(
|
|
1138
|
+
() => new Promise(() => {
|
|
1139
|
+
}),
|
|
1140
|
+
controller.signal
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
},
|
|
1095
1144
|
parallel: runFactoryParallel,
|
|
1096
1145
|
pipeline: runFactoryPipeline,
|
|
1097
1146
|
factory: async () => {
|
|
@@ -1127,11 +1176,9 @@ class CopilotSession {
|
|
|
1127
1176
|
},
|
|
1128
1177
|
async abort(params) {
|
|
1129
1178
|
const controllersForRun = self.factoryAbortControllers.get(params.runId);
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
controller.abort(reason);
|
|
1134
|
-
}
|
|
1179
|
+
const controller = controllersForRun?.get(params.executionToken);
|
|
1180
|
+
if (controller !== void 0) {
|
|
1181
|
+
controller.abort(new DOMException("Factory run was aborted", "AbortError"));
|
|
1135
1182
|
}
|
|
1136
1183
|
return {};
|
|
1137
1184
|
}
|
package/docs/factories.md
CHANGED
|
@@ -62,19 +62,20 @@ Validation covers the model's `run_factory` path only. An extension calling `ses
|
|
|
62
62
|
|
|
63
63
|
The `run()` context provides:
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
* `ctx.runId`: Stable ID reused across resumed attempts.
|
|
66
|
+
* `ctx.args`: Invocation arguments, forwarded verbatim. When the caller omits `args`, this is `{}` rather than `undefined`.
|
|
67
|
+
* `ctx.agent(prompt, options?)`: Runs one factory-owned subagent. Options are exactly `label`, `schema`, `model`, `agent`, `reasoningEffort`, and `contextTier`. See [Subagent calls](#subagent-calls).
|
|
68
|
+
* `ctx.parallel(thunks)`: Runs thunks concurrently and awaits all of them (a barrier). A thunk that throws becomes `null` in the result array, so one failed item does not lose the rest. Cancellation and hard runtime failures (`ResponseError`, `ConnectionError`) are the exception — those propagate and reject the whole call, because they mean the run itself is in trouble rather than one item having failed. Handle them at run level; do not assume every failure arrives as a `null`. Rejects above 4096 items.
|
|
69
|
+
* `ctx.pipeline(items, ...stages)`: Flows each item through every stage without a barrier between stages, so one item can be in a later stage while another is still in an earlier one. Each stage is called as `(previous, item, index)`, where `previous` is the prior stage's result and `item` is the original input. A stage that throws drops that item to `null` and skips its remaining stages, with the same exception for cancellation and hard runtime failures. Rejects above 4096 items.
|
|
70
|
+
* `ctx.phase(title)`: Starts a named progress phase. This sets a single run-global value, so calling it from inside concurrent `parallel`/`pipeline` stages races. Call it at run-level transitions and distinguish concurrent work by `label` instead.
|
|
71
|
+
* `ctx.log(message)`: Appends a progress line. When a factory bounds its own coverage (top-N, sampling), log what was dropped.
|
|
72
|
+
* `ctx.step(key, producer, options?)`: Journals the producer's JSON result under a stable key so a resume replays it without re-running the producer. A journaled (default) producer must return a JSON-serializable value; `undefined` or a non-JSON value is rejected. Pass `{ volatile: true }` to bypass the journal and run the producer every time.
|
|
73
73
|
|
|
74
74
|
The key is the *sole* identity: neither the producer body nor its inputs contribute to it. A resume replays the cached value for a matching key even if the producer has since changed, so version the key (`"scan-v2"`) whenever its inputs or meaning change. Journaled producers are best-effort at-least-once and may run again across crashes or concurrent same-key callers, so keep side effects idempotent.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
* `ctx.pause(key)`: Pauses at a durable, one-shot checkpoint. The first attempt records the checkpoint, pauses, and throws `AbortError` after cooperative cancellation. When the run resumes, the factory starts again and the same checkpoint returns so execution can continue. Call it only from the main factory flow, not inside `ctx.parallel()` or `ctx.pipeline()`.
|
|
76
|
+
* `ctx.session`: The session returned by `joinSession`. It refuses calls that start, resume, or pause a factory run. Call `extensions_manage` with `operation: "guide"` to read more about the session APIs.
|
|
77
|
+
* `ctx.signal`: Cooperative cancellation signal for extension work and subprocesses.
|
|
78
|
+
* `ctx.factory(...)`: Always rejects because nested factories are not supported.
|
|
78
79
|
|
|
79
80
|
Factory-owned subagents are intentionally hidden from `read_agent` and `write_agent`. Use the factory observability APIs instead.
|
|
80
81
|
|
|
@@ -157,7 +158,7 @@ session.factory.run(
|
|
|
157
158
|
name: string,
|
|
158
159
|
options?: {
|
|
159
160
|
args?: JsonValue;
|
|
160
|
-
limits?:
|
|
161
|
+
limits?: FactoryLimitOverrides;
|
|
161
162
|
notifyOnComplete?: boolean;
|
|
162
163
|
logPhaseNames?: boolean;
|
|
163
164
|
},
|
|
@@ -180,7 +181,7 @@ The signature is:
|
|
|
180
181
|
session.factory.resume(
|
|
181
182
|
runId: string,
|
|
182
183
|
options?: {
|
|
183
|
-
limits?:
|
|
184
|
+
limits?: FactoryLimitOverrides;
|
|
184
185
|
notifyOnComplete?: boolean;
|
|
185
186
|
logPhaseNames?: boolean;
|
|
186
187
|
},
|
|
@@ -189,15 +190,31 @@ session.factory.resume(
|
|
|
189
190
|
|
|
190
191
|
Set `notifyOnComplete` to `true` for factories that are likely to be invoked by an agent, so the originating session is notified when the factory completes. Set it to `false` for factories intended to be invoked programmatically, where the caller awaits the result directly. Set `logPhaseNames` to emit factory phase names to the session transcript. Both options apply to new and resumed runs.
|
|
191
192
|
|
|
192
|
-
Both resolve with the run envelope (`FactoryRunResult`) for **every** outcome
|
|
193
|
+
Both resolve with the run envelope (`FactoryRunResult`) for **every** outcome—`completed`, `error`, `halted`, `paused`, and `cancelled` alike. Inspect `status` and read `result` only when the run completed; a limit breach carries a typed `failure`. A `paused` envelope means that the current attempt settled, not that the durable run is permanently finished. Resume the same run ID to start another attempt with its journal and accounting intact. SDK-initiated `run` and `resume` do not request permission, so they have no declined outcome. The model's `run_factory` tool requests permission before the durable row exists; declining it creates no run row. An SDK-initiated run is refused only when the session already has its maximum number of active top-level runs. Pre-execution resume failures throw `FactoryResumeError`, whose `code` is one of `not_found`, `non_resumable`, `already_active`, `factory_already_running`, `factory_limits_invalid`, `factory_session_disposed`, `factory_storage_unavailable`, or `factory_storage_corrupt`.
|
|
193
194
|
|
|
194
195
|
An agent that no longer has a prior run's ID in context can recover it with `factories_manage` and `operation: "runs"`, which lists the session's factory runs with their IDs and statuses. This matters for resume: a run that reached a limit keeps its journal, so resuming it replays completed work for free, while restarting it from scratch pays for that work twice.
|
|
195
196
|
|
|
197
|
+
Pause a running attempt from outside its factory body:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
const paused = await session.factory.pause(runId);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Inside a factory body, use a durable checkpoint instead:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
await ctx.step("prepare", prepareInput);
|
|
207
|
+
await ctx.pause("review-ready");
|
|
208
|
+
await ctx.agent("Review the prepared input");
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The first attempt pauses at `"review-ready"` and ends through cooperative cancellation. On resume, the factory starts from the beginning, reuses the journaled step, returns from the checkpoint, and continues.
|
|
212
|
+
|
|
196
213
|
The agent-facing `run_factory` tool has exactly two input branches:
|
|
197
214
|
|
|
198
215
|
```ts
|
|
199
|
-
{ name: string; args?: JsonValue; limits?:
|
|
200
|
-
{ resumeFromRunId: string; limits?:
|
|
216
|
+
{ name: string; args?: JsonValue; limits?: FactoryLimitOverrides }
|
|
217
|
+
{ resumeFromRunId: string; limits?: FactoryLimitOverrides }
|
|
201
218
|
```
|
|
202
219
|
|
|
203
220
|
## Authoring a factory from inside a session
|
|
@@ -253,9 +270,9 @@ const progressPage = await session.factory.getRunProgress(runId, {
|
|
|
253
270
|
- `getRunDetail(runId)` returns phases, prompt-safe agent summaries, and the latest progress page.
|
|
254
271
|
- `getRunProgress(runId, options?)` pages progress forward, backward, by phase, or from the latest tail.
|
|
255
272
|
|
|
256
|
-
`getRun(runId)` reads the latest run envelope
|
|
273
|
+
`getRun(runId)` reads the latest run envelope. `pause(runId)` pauses a running attempt and returns its `paused` envelope. `cancel(runId)` cancels a run and returns its terminal envelope.
|
|
257
274
|
|
|
258
|
-
`waitForRun(runId, options?)` resolves with the
|
|
275
|
+
`waitForRun(runId, options?)` resolves with the current attempt's envelope once it settles into `completed`, `error`, `halted`, `paused`, or `cancelled`. It resolves immediately when the current attempt has already settled:
|
|
259
276
|
|
|
260
277
|
```ts
|
|
261
278
|
const settled = await session.factory.waitForRun(runId);
|
|
@@ -272,7 +289,7 @@ setTimeout(() => controller.abort(), 30_000);
|
|
|
272
289
|
const settled = await session.factory.waitForRun(runId, { signal: controller.signal });
|
|
273
290
|
```
|
|
274
291
|
|
|
275
|
-
Aborting rejects the wait and has no effect on the run, which keeps executing
|
|
292
|
+
Aborting rejects the wait and has no effect on the run, which keeps executing—use `pause(runId)` or `cancel(runId)` to stop it. The resolved object is a snapshot of that settled attempt. If its status is `paused`, a later resume updates the durable envelope under the same run ID. Call `getRun(runId)` to read the latest envelope. `isFactoryRunTerminal(status)` exposes the same current-attempt settlement test for callers driving their own loop.
|
|
276
293
|
|
|
277
294
|
Listen for the ephemeral `factory.run_updated` event. Its `{ runId, revision }` payload is an invalidation signal. Re-read the desired API when a newer monotonic revision arrives.
|
|
278
295
|
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "https://github.com/github/copilot-sdk.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "1.0.14-preview.
|
|
7
|
+
"version": "1.0.14-preview.1",
|
|
8
8
|
"copilotCliVersion": "1.0.84-5",
|
|
9
9
|
"description": "TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC",
|
|
10
10
|
"main": "./dist/cjs/index.js",
|
|
@@ -96,13 +96,13 @@
|
|
|
96
96
|
"README.md"
|
|
97
97
|
],
|
|
98
98
|
"optionalDependencies": {
|
|
99
|
-
"@github/copilot-sdk-darwin-arm64": "1.0.14-preview.
|
|
100
|
-
"@github/copilot-sdk-darwin-x64": "1.0.14-preview.
|
|
101
|
-
"@github/copilot-sdk-linux-arm64": "1.0.14-preview.
|
|
102
|
-
"@github/copilot-sdk-linux-x64": "1.0.14-preview.
|
|
103
|
-
"@github/copilot-sdk-linuxmusl-arm64": "1.0.14-preview.
|
|
104
|
-
"@github/copilot-sdk-linuxmusl-x64": "1.0.14-preview.
|
|
105
|
-
"@github/copilot-sdk-win32-arm64": "1.0.14-preview.
|
|
106
|
-
"@github/copilot-sdk-win32-x64": "1.0.14-preview.
|
|
99
|
+
"@github/copilot-sdk-darwin-arm64": "1.0.14-preview.1",
|
|
100
|
+
"@github/copilot-sdk-darwin-x64": "1.0.14-preview.1",
|
|
101
|
+
"@github/copilot-sdk-linux-arm64": "1.0.14-preview.1",
|
|
102
|
+
"@github/copilot-sdk-linux-x64": "1.0.14-preview.1",
|
|
103
|
+
"@github/copilot-sdk-linuxmusl-arm64": "1.0.14-preview.1",
|
|
104
|
+
"@github/copilot-sdk-linuxmusl-x64": "1.0.14-preview.1",
|
|
105
|
+
"@github/copilot-sdk-win32-arm64": "1.0.14-preview.1",
|
|
106
|
+
"@github/copilot-sdk-win32-x64": "1.0.14-preview.1"
|
|
107
107
|
}
|
|
108
108
|
}
|