@github/copilot-sdk 1.0.15-preview.2 → 1.0.15-preview.4
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 +53 -25
- package/dist/cjs/cliVersion.js +1 -1
- package/dist/cjs/client.js +21 -6
- package/dist/cjs/extension.js +1 -12
- package/dist/cjs/generated/rpc.js +307 -177
- package/dist/cjs/index.js +0 -7
- package/dist/cjs/installationConfirmation.js +98 -0
- package/dist/cjs/session.js +15 -524
- package/dist/cliVersion.d.ts +1 -1
- package/dist/cliVersion.js +1 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.js +23 -6
- package/dist/extension.d.ts +10 -24
- package/dist/extension.js +1 -13
- package/dist/generated/rpc.d.ts +4455 -2788
- package/dist/generated/rpc.js +307 -177
- package/dist/generated/session-events.d.ts +211 -120
- package/dist/index.d.ts +2 -4
- package/dist/index.js +0 -4
- package/dist/installationConfirmation.d.ts +19 -0
- package/dist/installationConfirmation.js +77 -0
- package/dist/session.d.ts +3 -25
- package/dist/session.js +15 -529
- package/dist/types.d.ts +31 -66
- package/dist/workflow.d.ts +5 -2
- package/docs/extensions.md +0 -1
- package/docs/workflows.md +2 -4
- package/package.json +10 -10
- package/dist/cjs/factory.js +0 -134
- package/dist/factory.d.ts +0 -327
- package/dist/factory.js +0 -106
- package/docs/factories.md +0 -296
- package/docs/factory-patterns.md +0 -194
package/dist/session.js
CHANGED
|
@@ -5,27 +5,12 @@ import { CanvasError } from "./canvas.js";
|
|
|
5
5
|
import { getTraceContext } from "./telemetry.js";
|
|
6
6
|
import { isResponseSchema, toJsonSchema } from "./schema.js";
|
|
7
7
|
import { isAttributedPermissionResult } from "./types.js";
|
|
8
|
-
import {
|
|
9
|
-
FACTORY_AGENT_OPTION_KEYS,
|
|
10
|
-
getFactoryDefinition,
|
|
11
|
-
FactoryResumeError,
|
|
12
|
-
isFactoryRunTerminal
|
|
13
|
-
} from "./factory.js";
|
|
14
8
|
import {
|
|
15
9
|
WORKFLOW_AGENT_OPTION_KEYS,
|
|
16
10
|
getWorkflowDefinition,
|
|
17
11
|
WorkflowResumeError,
|
|
18
12
|
isWorkflowRunTerminal
|
|
19
13
|
} from "./workflow.js";
|
|
20
|
-
function isFactoryResumeErrorCode(value) {
|
|
21
|
-
return value === "not_found" || value === "non_resumable" || value === "already_active" || value === "factory_already_running" || value === "factory_limits_invalid" || value === "factory_session_disposed" || value === "factory_storage_unavailable" || value === "factory_storage_corrupt";
|
|
22
|
-
}
|
|
23
|
-
function copyDefinedFactoryAgentOption(source, target, key) {
|
|
24
|
-
const value = source[key];
|
|
25
|
-
if (value !== void 0) {
|
|
26
|
-
target[key] = value;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
14
|
function isWorkflowResumeErrorCode(value) {
|
|
30
15
|
return value === "not_found" || value === "non_resumable" || value === "workflow_run_not_resumable" || value === "already_active" || value === "workflow_already_running" || value === "workflow_limits_invalid" || value === "workflow_session_disposed" || value === "workflow_storage_unavailable" || value === "workflow_storage_corrupt";
|
|
31
16
|
}
|
|
@@ -35,14 +20,6 @@ function copyDefinedWorkflowAgentOption(source, target, key) {
|
|
|
35
20
|
target[key] = value;
|
|
36
21
|
}
|
|
37
22
|
}
|
|
38
|
-
const factoryExecutionStore = new AsyncLocalStorage();
|
|
39
|
-
function throwIfFactoryExecutionIsActive() {
|
|
40
|
-
if (factoryExecutionStore.getStore()?.active) {
|
|
41
|
-
throw new Error(
|
|
42
|
-
"factory.run, factory.resume, and factory.pause are not allowed while a factory body is running on this call path."
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
23
|
const workflowExecutionStore = new AsyncLocalStorage();
|
|
47
24
|
function throwIfWorkflowExecutionIsActive() {
|
|
48
25
|
if (workflowExecutionStore.getStore()?.active) {
|
|
@@ -55,10 +32,6 @@ function runInWorkflowHelperScope(helperScope, callback) {
|
|
|
55
32
|
const current = workflowExecutionStore.getStore();
|
|
56
33
|
return workflowExecutionStore.run({ active: current?.active ?? false, helperScope }, callback);
|
|
57
34
|
}
|
|
58
|
-
function runInFactoryHelperScope(helperScope, callback) {
|
|
59
|
-
const current = factoryExecutionStore.getStore();
|
|
60
|
-
return factoryExecutionStore.run({ active: current?.active ?? false, helperScope }, callback);
|
|
61
|
-
}
|
|
62
35
|
function deserializeHookInput(raw) {
|
|
63
36
|
if (!raw || typeof raw !== "object" || typeof raw.timestamp !== "number") {
|
|
64
37
|
return raw;
|
|
@@ -81,68 +54,20 @@ function isOpenCanvasInstance(value) {
|
|
|
81
54
|
}
|
|
82
55
|
const FACTORY_LOG_FLUSH_DELAY_MS = 10;
|
|
83
56
|
const MAX_FACTORY_FANOUT_ITEMS = 4096;
|
|
84
|
-
function
|
|
57
|
+
function assertWorkflowFanoutSize(kind, size) {
|
|
85
58
|
if (size > MAX_FACTORY_FANOUT_ITEMS) {
|
|
86
59
|
throw new Error(
|
|
87
60
|
`${kind}() accepts at most ${MAX_FACTORY_FANOUT_ITEMS} items; got ${size}.`
|
|
88
61
|
);
|
|
89
62
|
}
|
|
90
63
|
}
|
|
91
|
-
async function runFactoryParallel(thunks) {
|
|
92
|
-
if (!Array.isArray(thunks)) {
|
|
93
|
-
throw new Error(
|
|
94
|
-
"parallel() expects an array of functions, not promises. Wrap each call: () => agent(...)"
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
assertFactoryFanoutSize("parallel", thunks.length);
|
|
98
|
-
if (thunks.some((thunk) => typeof thunk !== "function")) {
|
|
99
|
-
throw new Error(
|
|
100
|
-
"parallel() expects an array of functions, not promises. Wrap each call: () => agent(...)"
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
return Promise.all(
|
|
104
|
-
thunks.map(
|
|
105
|
-
(thunk) => Promise.resolve().then(() => runInFactoryHelperScope("parallel", thunk)).catch((error) => {
|
|
106
|
-
if (isFactoryFatalError(error)) {
|
|
107
|
-
throw error;
|
|
108
|
-
}
|
|
109
|
-
return null;
|
|
110
|
-
})
|
|
111
|
-
)
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
async function runFactoryPipeline(items, ...stages) {
|
|
115
|
-
if (!Array.isArray(items)) {
|
|
116
|
-
throw new Error("pipeline(items, ...stages): items must be an array");
|
|
117
|
-
}
|
|
118
|
-
assertFactoryFanoutSize("pipeline", items.length);
|
|
119
|
-
return Promise.all(
|
|
120
|
-
items.map(async (item, index) => {
|
|
121
|
-
let previous = item;
|
|
122
|
-
for (const stage of stages) {
|
|
123
|
-
try {
|
|
124
|
-
previous = await runInFactoryHelperScope(
|
|
125
|
-
"pipeline",
|
|
126
|
-
() => stage(previous, item, index)
|
|
127
|
-
);
|
|
128
|
-
} catch (error) {
|
|
129
|
-
if (isFactoryFatalError(error)) {
|
|
130
|
-
throw error;
|
|
131
|
-
}
|
|
132
|
-
return null;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return previous;
|
|
136
|
-
})
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
64
|
async function runWorkflowParallel(thunks) {
|
|
140
65
|
if (!Array.isArray(thunks)) {
|
|
141
66
|
throw new Error(
|
|
142
67
|
"parallel() expects an array of functions, not promises. Wrap each call: () => agent(...)"
|
|
143
68
|
);
|
|
144
69
|
}
|
|
145
|
-
|
|
70
|
+
assertWorkflowFanoutSize("parallel", thunks.length);
|
|
146
71
|
if (thunks.some((thunk) => typeof thunk !== "function")) {
|
|
147
72
|
throw new Error(
|
|
148
73
|
"parallel() expects an array of functions, not promises. Wrap each call: () => agent(...)"
|
|
@@ -151,7 +76,7 @@ async function runWorkflowParallel(thunks) {
|
|
|
151
76
|
return Promise.all(
|
|
152
77
|
thunks.map(
|
|
153
78
|
(thunk) => Promise.resolve().then(() => runInWorkflowHelperScope("parallel", thunk)).catch((error) => {
|
|
154
|
-
if (
|
|
79
|
+
if (isWorkflowFatalError(error)) {
|
|
155
80
|
throw error;
|
|
156
81
|
}
|
|
157
82
|
return null;
|
|
@@ -163,7 +88,7 @@ async function runWorkflowPipeline(items, ...stages) {
|
|
|
163
88
|
if (!Array.isArray(items)) {
|
|
164
89
|
throw new Error("pipeline(items, ...stages): items must be an array");
|
|
165
90
|
}
|
|
166
|
-
|
|
91
|
+
assertWorkflowFanoutSize("pipeline", items.length);
|
|
167
92
|
return Promise.all(
|
|
168
93
|
items.map(async (item, index) => {
|
|
169
94
|
let previous = item;
|
|
@@ -174,7 +99,7 @@ async function runWorkflowPipeline(items, ...stages) {
|
|
|
174
99
|
() => stage(previous, item, index)
|
|
175
100
|
);
|
|
176
101
|
} catch (error) {
|
|
177
|
-
if (
|
|
102
|
+
if (isWorkflowFatalError(error)) {
|
|
178
103
|
throw error;
|
|
179
104
|
}
|
|
180
105
|
return null;
|
|
@@ -184,85 +109,6 @@ async function runWorkflowPipeline(items, ...stages) {
|
|
|
184
109
|
})
|
|
185
110
|
);
|
|
186
111
|
}
|
|
187
|
-
class FactoryProgressBuffer {
|
|
188
|
-
constructor(send) {
|
|
189
|
-
this.send = send;
|
|
190
|
-
}
|
|
191
|
-
send;
|
|
192
|
-
nextSeq = 0;
|
|
193
|
-
pending = [];
|
|
194
|
-
flushTimer;
|
|
195
|
-
flushTail = Promise.resolve();
|
|
196
|
-
flushError;
|
|
197
|
-
flushFailed = false;
|
|
198
|
-
closed = false;
|
|
199
|
-
enqueue(kind, text) {
|
|
200
|
-
if (this.closed) {
|
|
201
|
-
throw new Error("Cannot log after the factory run has settled");
|
|
202
|
-
}
|
|
203
|
-
this.pending.push({ seq: this.nextSeq++, kind, text });
|
|
204
|
-
this.scheduleFlush();
|
|
205
|
-
}
|
|
206
|
-
async flush() {
|
|
207
|
-
this.clearFlushTimer();
|
|
208
|
-
const lines = this.pending.splice(0);
|
|
209
|
-
if (lines.length > 0) {
|
|
210
|
-
this.flushTail = this.flushTail.then(async () => {
|
|
211
|
-
try {
|
|
212
|
-
await this.send(lines);
|
|
213
|
-
} catch (error) {
|
|
214
|
-
if (!this.flushFailed) {
|
|
215
|
-
this.flushFailed = true;
|
|
216
|
-
this.flushError = error;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
await this.flushTail;
|
|
222
|
-
if (this.flushFailed) {
|
|
223
|
-
throw this.flushError;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
async close() {
|
|
227
|
-
this.closed = true;
|
|
228
|
-
this.clearFlushTimer();
|
|
229
|
-
const lines = this.pending.splice(0);
|
|
230
|
-
await this.flushTail;
|
|
231
|
-
if (this.flushFailed) {
|
|
232
|
-
console.warn(
|
|
233
|
-
"Ignoring a background factory progress flush failure after the factory body settled",
|
|
234
|
-
this.flushError
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
if (lines.length > 0) {
|
|
238
|
-
try {
|
|
239
|
-
await this.send(lines);
|
|
240
|
-
} catch (error) {
|
|
241
|
-
console.warn(
|
|
242
|
-
"Failed to flush final factory progress after the factory body settled",
|
|
243
|
-
error
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
scheduleFlush() {
|
|
249
|
-
if (this.flushTimer !== void 0) {
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
this.flushTimer = setTimeout(() => {
|
|
253
|
-
this.flushTimer = void 0;
|
|
254
|
-
void this.flush().catch(() => {
|
|
255
|
-
});
|
|
256
|
-
}, FACTORY_LOG_FLUSH_DELAY_MS);
|
|
257
|
-
this.flushTimer.unref?.();
|
|
258
|
-
}
|
|
259
|
-
clearFlushTimer() {
|
|
260
|
-
if (this.flushTimer !== void 0) {
|
|
261
|
-
clearTimeout(this.flushTimer);
|
|
262
|
-
this.flushTimer = void 0;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
112
|
class WorkflowProgressBuffer {
|
|
267
113
|
constructor(send) {
|
|
268
114
|
this.send = send;
|
|
@@ -342,38 +188,30 @@ class WorkflowProgressBuffer {
|
|
|
342
188
|
}
|
|
343
189
|
}
|
|
344
190
|
}
|
|
345
|
-
async function
|
|
191
|
+
async function awaitWorkflowOperation(operation, signal) {
|
|
346
192
|
let rejectAbort;
|
|
347
193
|
const abortPromise = new Promise((_resolve, reject) => {
|
|
348
194
|
rejectAbort = reject;
|
|
349
195
|
});
|
|
350
|
-
const onAbort = () => rejectAbort?.(signal.reason ?? new DOMException("
|
|
196
|
+
const onAbort = () => rejectAbort?.(signal.reason ?? new DOMException("Workflow run was aborted", "AbortError"));
|
|
351
197
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
352
198
|
try {
|
|
353
|
-
|
|
199
|
+
throwIfWorkflowAborted(signal);
|
|
354
200
|
return await Promise.race([operation(), abortPromise]);
|
|
355
201
|
} finally {
|
|
356
202
|
signal.removeEventListener("abort", onAbort);
|
|
357
203
|
}
|
|
358
204
|
}
|
|
359
|
-
async function awaitWorkflowOperation(operation, signal) {
|
|
360
|
-
return awaitFactoryOperation(operation, signal);
|
|
361
|
-
}
|
|
362
|
-
function throwIfFactoryAborted(signal) {
|
|
363
|
-
if (signal.aborted) {
|
|
364
|
-
throw signal.reason ?? new DOMException("Factory run was aborted", "AbortError");
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
205
|
function throwIfWorkflowAborted(signal) {
|
|
368
206
|
if (signal.aborted) {
|
|
369
207
|
throw signal.reason ?? new DOMException("Workflow run was aborted", "AbortError");
|
|
370
208
|
}
|
|
371
209
|
}
|
|
372
|
-
function
|
|
210
|
+
function isWorkflowAbortError(error) {
|
|
373
211
|
return typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
|
|
374
212
|
}
|
|
375
|
-
function
|
|
376
|
-
return
|
|
213
|
+
function isWorkflowFatalError(error) {
|
|
214
|
+
return isWorkflowAbortError(error) || error instanceof ResponseError || error instanceof ConnectionError;
|
|
377
215
|
}
|
|
378
216
|
const TOOL_SEARCH_TOOL_NAME = "tool_search_tool";
|
|
379
217
|
class CopilotSession {
|
|
@@ -405,8 +243,6 @@ class CopilotSession {
|
|
|
405
243
|
canvases = /* @__PURE__ */ new Map();
|
|
406
244
|
bearerTokenProviders = /* @__PURE__ */ new Map();
|
|
407
245
|
commandHandlers = /* @__PURE__ */ new Map();
|
|
408
|
-
factories = /* @__PURE__ */ new Map();
|
|
409
|
-
factoryAbortControllers = /* @__PURE__ */ new Map();
|
|
410
246
|
workflows = /* @__PURE__ */ new Map();
|
|
411
247
|
workflowAbortControllers = /* @__PURE__ */ new Map();
|
|
412
248
|
permissionHandler;
|
|
@@ -430,68 +266,11 @@ class CopilotSession {
|
|
|
430
266
|
/** @internal Client session API handlers, populated by CopilotClient during create/resume. */
|
|
431
267
|
clientSessionApis = {};
|
|
432
268
|
/**
|
|
433
|
-
* Friendly
|
|
269
|
+
* Friendly workflow API for running registered workflows by name or handle.
|
|
434
270
|
*
|
|
435
|
-
* @experimental Part of the experimental
|
|
271
|
+
* @experimental Part of the experimental Dynamic Workflows surface and may
|
|
436
272
|
* change or be removed in future SDK or CLI releases.
|
|
437
273
|
*/
|
|
438
|
-
factory = {
|
|
439
|
-
run: (async (nameOrHandle, options) => {
|
|
440
|
-
throwIfFactoryExecutionIsActive();
|
|
441
|
-
const name = typeof nameOrHandle === "string" ? nameOrHandle : getFactoryDefinition(nameOrHandle).meta.name;
|
|
442
|
-
if (options?.resumeFromRunId !== void 0) {
|
|
443
|
-
return this.factory.resume(options.resumeFromRunId, {
|
|
444
|
-
limits: options.limits,
|
|
445
|
-
notifyOnComplete: options.notifyOnComplete,
|
|
446
|
-
logPhaseNames: options.logPhaseNames
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
const envelope = await this.rpc.factory.run({
|
|
450
|
-
name,
|
|
451
|
-
args: options?.args === void 0 ? {} : options.args,
|
|
452
|
-
options: {
|
|
453
|
-
limits: options?.limits,
|
|
454
|
-
notifyOnComplete: options?.notifyOnComplete,
|
|
455
|
-
logPhaseNames: options?.logPhaseNames
|
|
456
|
-
}
|
|
457
|
-
});
|
|
458
|
-
return this.settleFactoryRun(envelope);
|
|
459
|
-
}),
|
|
460
|
-
resume: (async (runId, options) => {
|
|
461
|
-
throwIfFactoryExecutionIsActive();
|
|
462
|
-
let response;
|
|
463
|
-
try {
|
|
464
|
-
response = await this.rpc.factory.resume({
|
|
465
|
-
runId,
|
|
466
|
-
limits: options?.limits,
|
|
467
|
-
notifyOnComplete: options?.notifyOnComplete,
|
|
468
|
-
logPhaseNames: options?.logPhaseNames
|
|
469
|
-
});
|
|
470
|
-
} catch (error) {
|
|
471
|
-
if (error instanceof ResponseError && typeof error.data === "object" && error.data !== null) {
|
|
472
|
-
const code = error.data.code;
|
|
473
|
-
if (isFactoryResumeErrorCode(code)) {
|
|
474
|
-
throw new FactoryResumeError(code, error.message);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
throw error;
|
|
478
|
-
}
|
|
479
|
-
return this.settleFactoryRun(response.run);
|
|
480
|
-
}),
|
|
481
|
-
getRun: async (runId) => this.rpc.factory.getRun({ runId }),
|
|
482
|
-
waitForRun: (runId, options) => this.waitForFactoryRun(runId, options?.signal),
|
|
483
|
-
listRuns: (async (options) => {
|
|
484
|
-
const page = await this.rpc.factory.listRuns(options ?? {});
|
|
485
|
-
return options === void 0 ? page.runs : page;
|
|
486
|
-
}),
|
|
487
|
-
getRunDetail: (runId) => this.rpc.factory.getRunDetail({ runId }),
|
|
488
|
-
getRunProgress: (runId, options = {}) => this.rpc.factory.getRunProgress({ runId, ...options }),
|
|
489
|
-
pause: async (runId) => {
|
|
490
|
-
throwIfFactoryExecutionIsActive();
|
|
491
|
-
return this.rpc.factory.pause({ runId });
|
|
492
|
-
},
|
|
493
|
-
cancel: async (runId) => this.rpc.factory.cancel({ runId })
|
|
494
|
-
};
|
|
495
274
|
workflow = {
|
|
496
275
|
run: (async (nameOrHandle, options) => {
|
|
497
276
|
throwIfWorkflowExecutionIsActive();
|
|
@@ -542,93 +321,6 @@ class CopilotSession {
|
|
|
542
321
|
},
|
|
543
322
|
cancel: async (runId) => this.rpc.workflow.cancel({ runId })
|
|
544
323
|
};
|
|
545
|
-
/**
|
|
546
|
-
* Resolve a start/resume envelope into the terminal envelope callers expect.
|
|
547
|
-
*
|
|
548
|
-
* The CLI may answer `session.factory.run` and `session.factory.resume`
|
|
549
|
-
* before the run settles, so a non-terminal envelope is followed by a wait
|
|
550
|
-
* on the run's terminal state.
|
|
551
|
-
*/
|
|
552
|
-
settleFactoryRun(envelope) {
|
|
553
|
-
if (isFactoryRunTerminal(envelope.status)) {
|
|
554
|
-
return Promise.resolve(envelope);
|
|
555
|
-
}
|
|
556
|
-
return this.waitForFactoryRun(envelope.runId);
|
|
557
|
-
}
|
|
558
|
-
/**
|
|
559
|
-
* Resolve when a factory run reaches a terminal status.
|
|
560
|
-
*
|
|
561
|
-
* The subscription is installed *before* the first read so a transition
|
|
562
|
-
* landing between the two cannot be missed, and re-reads are serialized so
|
|
563
|
-
* overlapping invalidation events cannot interleave — the run's revision
|
|
564
|
-
* advances once per operation, so a burst of events is common and must
|
|
565
|
-
* collapse into a single in-flight read. A bounded periodic re-read keeps a
|
|
566
|
-
* dropped invalidation from leaving the wait pending forever.
|
|
567
|
-
*/
|
|
568
|
-
waitForFactoryRun(runId, signal) {
|
|
569
|
-
const abortError = () => signal?.reason ?? new DOMException("Factory run wait was aborted", "AbortError");
|
|
570
|
-
if (signal?.aborted === true) {
|
|
571
|
-
return Promise.reject(abortError());
|
|
572
|
-
}
|
|
573
|
-
return new Promise((resolve, reject) => {
|
|
574
|
-
let settled = false;
|
|
575
|
-
let reading = false;
|
|
576
|
-
let rereadRequested = false;
|
|
577
|
-
let pollHandle;
|
|
578
|
-
let unsubscribe;
|
|
579
|
-
let onAbort;
|
|
580
|
-
const finish = (complete) => {
|
|
581
|
-
if (settled) {
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
settled = true;
|
|
585
|
-
if (pollHandle !== void 0) {
|
|
586
|
-
clearInterval(pollHandle);
|
|
587
|
-
}
|
|
588
|
-
unsubscribe?.();
|
|
589
|
-
if (onAbort !== void 0) {
|
|
590
|
-
signal?.removeEventListener("abort", onAbort);
|
|
591
|
-
}
|
|
592
|
-
complete();
|
|
593
|
-
};
|
|
594
|
-
const read = async () => {
|
|
595
|
-
if (settled) {
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
if (reading) {
|
|
599
|
-
rereadRequested = true;
|
|
600
|
-
return;
|
|
601
|
-
}
|
|
602
|
-
reading = true;
|
|
603
|
-
try {
|
|
604
|
-
do {
|
|
605
|
-
rereadRequested = false;
|
|
606
|
-
const envelope = await this.rpc.factory.getRun({ runId });
|
|
607
|
-
if (isFactoryRunTerminal(envelope.status)) {
|
|
608
|
-
finish(() => resolve(envelope));
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
} while (rereadRequested && !settled);
|
|
612
|
-
} catch (error) {
|
|
613
|
-
finish(() => reject(error));
|
|
614
|
-
} finally {
|
|
615
|
-
reading = false;
|
|
616
|
-
}
|
|
617
|
-
};
|
|
618
|
-
if (signal !== void 0) {
|
|
619
|
-
onAbort = () => finish(() => reject(abortError()));
|
|
620
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
621
|
-
}
|
|
622
|
-
unsubscribe = this.on("factory.run_updated", (event) => {
|
|
623
|
-
if (event.data.runId === runId) {
|
|
624
|
-
void read();
|
|
625
|
-
}
|
|
626
|
-
});
|
|
627
|
-
pollHandle = setInterval(() => void read(), 5e3);
|
|
628
|
-
pollHandle.unref?.();
|
|
629
|
-
void read();
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
324
|
settleWorkflowRun(envelope) {
|
|
633
325
|
if (isWorkflowRunTerminal(envelope.status)) {
|
|
634
326
|
return Promise.resolve(envelope);
|
|
@@ -699,7 +391,7 @@ class CopilotSession {
|
|
|
699
391
|
onAbort = () => finish(() => reject(abortError()));
|
|
700
392
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
701
393
|
}
|
|
702
|
-
unsubscribe = this.on("
|
|
394
|
+
unsubscribe = this.on("workflow.run_updated", (event) => {
|
|
703
395
|
if (event.data.runId === runId) {
|
|
704
396
|
void read();
|
|
705
397
|
}
|
|
@@ -825,6 +517,7 @@ class CopilotSession {
|
|
|
825
517
|
});
|
|
826
518
|
let lastAssistantMessage;
|
|
827
519
|
const unsubscribe = this.on((event) => {
|
|
520
|
+
if (event.agentId) return;
|
|
828
521
|
if (event.type === "assistant.message") {
|
|
829
522
|
lastAssistantMessage = event;
|
|
830
523
|
} else if (event.type === "session.idle" && event.data.mode !== "autopilot") {
|
|
@@ -964,13 +657,6 @@ class CopilotSession {
|
|
|
964
657
|
this.autoModeSwitchHandler = void 0;
|
|
965
658
|
this.commandHandlers.clear();
|
|
966
659
|
this.canvases.clear();
|
|
967
|
-
this.factories.clear();
|
|
968
|
-
for (const controllersForRun of this.factoryAbortControllers.values()) {
|
|
969
|
-
for (const controller of controllersForRun.values()) {
|
|
970
|
-
controller.abort();
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
this.factoryAbortControllers.clear();
|
|
974
660
|
this.workflows.clear();
|
|
975
661
|
for (const controllersForRun of this.workflowAbortControllers.values()) {
|
|
976
662
|
for (const controller of controllersForRun.values()) {
|
|
@@ -1425,192 +1111,6 @@ class CopilotSession {
|
|
|
1425
1111
|
}
|
|
1426
1112
|
};
|
|
1427
1113
|
}
|
|
1428
|
-
/**
|
|
1429
|
-
* Registers factory closures and reverse-RPC handlers for this session.
|
|
1430
|
-
*
|
|
1431
|
-
* @param factories - Factory handles declared by the joining extension.
|
|
1432
|
-
* @internal Called by the SDK when an extension joins a session.
|
|
1433
|
-
*/
|
|
1434
|
-
registerFactories(factories) {
|
|
1435
|
-
this.factories.clear();
|
|
1436
|
-
if (!factories || factories.length === 0) {
|
|
1437
|
-
delete this.clientSessionApis.factory;
|
|
1438
|
-
return;
|
|
1439
|
-
}
|
|
1440
|
-
for (const handle of factories) {
|
|
1441
|
-
const definition = getFactoryDefinition(handle);
|
|
1442
|
-
if (this.factories.has(definition.meta.name)) {
|
|
1443
|
-
throw new Error(
|
|
1444
|
-
`Duplicate factory name "${definition.meta.name}". Factory names must be unique within a joinSession call.`
|
|
1445
|
-
);
|
|
1446
|
-
}
|
|
1447
|
-
this.factories.set(definition.meta.name, definition);
|
|
1448
|
-
}
|
|
1449
|
-
const self = this;
|
|
1450
|
-
this.clientSessionApis.factory = {
|
|
1451
|
-
async execute(params) {
|
|
1452
|
-
const definition = self.factories.get(params.name);
|
|
1453
|
-
if (!definition) {
|
|
1454
|
-
const message = `No factory registered with name "${params.name}"`;
|
|
1455
|
-
throw new ResponseError(ErrorCodes.InvalidParams, message, {
|
|
1456
|
-
code: "factory_not_found",
|
|
1457
|
-
name: params.name
|
|
1458
|
-
});
|
|
1459
|
-
}
|
|
1460
|
-
const controller = new AbortController();
|
|
1461
|
-
let controllersForRun = self.factoryAbortControllers.get(params.runId);
|
|
1462
|
-
if (controllersForRun === void 0) {
|
|
1463
|
-
controllersForRun = /* @__PURE__ */ new Map();
|
|
1464
|
-
self.factoryAbortControllers.set(params.runId, controllersForRun);
|
|
1465
|
-
}
|
|
1466
|
-
controllersForRun.set(params.executionToken, controller);
|
|
1467
|
-
const progress = new FactoryProgressBuffer(async (lines) => {
|
|
1468
|
-
await self.rpc.factory.log({
|
|
1469
|
-
runId: params.runId,
|
|
1470
|
-
executionToken: params.executionToken,
|
|
1471
|
-
lines
|
|
1472
|
-
});
|
|
1473
|
-
});
|
|
1474
|
-
try {
|
|
1475
|
-
const context = {
|
|
1476
|
-
runId: params.runId,
|
|
1477
|
-
args: params.args,
|
|
1478
|
-
session: self,
|
|
1479
|
-
signal: controller.signal,
|
|
1480
|
-
phase: (title) => {
|
|
1481
|
-
throwIfFactoryAborted(controller.signal);
|
|
1482
|
-
progress.enqueue("phase", title);
|
|
1483
|
-
},
|
|
1484
|
-
log: (message) => {
|
|
1485
|
-
throwIfFactoryAborted(controller.signal);
|
|
1486
|
-
progress.enqueue("log", message);
|
|
1487
|
-
},
|
|
1488
|
-
agent: async (prompt, options = {}) => {
|
|
1489
|
-
await progress.flush();
|
|
1490
|
-
const opts = {};
|
|
1491
|
-
for (const key of FACTORY_AGENT_OPTION_KEYS) {
|
|
1492
|
-
copyDefinedFactoryAgentOption(options, opts, key);
|
|
1493
|
-
}
|
|
1494
|
-
const response = await awaitFactoryOperation(
|
|
1495
|
-
() => self.rpc.factory.agent({
|
|
1496
|
-
factoryRunId: params.runId,
|
|
1497
|
-
executionToken: params.executionToken,
|
|
1498
|
-
prompt,
|
|
1499
|
-
opts
|
|
1500
|
-
}),
|
|
1501
|
-
controller.signal
|
|
1502
|
-
);
|
|
1503
|
-
return response.result ?? null;
|
|
1504
|
-
},
|
|
1505
|
-
step: async (key, producer, options = {}) => {
|
|
1506
|
-
await progress.flush();
|
|
1507
|
-
if (options.volatile) {
|
|
1508
|
-
throwIfFactoryAborted(controller.signal);
|
|
1509
|
-
return producer();
|
|
1510
|
-
}
|
|
1511
|
-
const cached = await awaitFactoryOperation(
|
|
1512
|
-
() => self.rpc.factory.journal.get({
|
|
1513
|
-
runId: params.runId,
|
|
1514
|
-
executionToken: params.executionToken,
|
|
1515
|
-
key
|
|
1516
|
-
}),
|
|
1517
|
-
controller.signal
|
|
1518
|
-
);
|
|
1519
|
-
if (cached.hit) {
|
|
1520
|
-
if (cached.resultJson === void 0) {
|
|
1521
|
-
throw new Error(
|
|
1522
|
-
`step("${key}") journal returned a hit without a result`
|
|
1523
|
-
);
|
|
1524
|
-
}
|
|
1525
|
-
assertFactoryStepResult(cached.resultJson, key);
|
|
1526
|
-
return cached.resultJson;
|
|
1527
|
-
}
|
|
1528
|
-
const result2 = await producer();
|
|
1529
|
-
assertFactoryStepResult(result2, key);
|
|
1530
|
-
await awaitFactoryOperation(
|
|
1531
|
-
() => self.rpc.factory.journal.put({
|
|
1532
|
-
runId: params.runId,
|
|
1533
|
-
executionToken: params.executionToken,
|
|
1534
|
-
key,
|
|
1535
|
-
resultJson: result2
|
|
1536
|
-
}),
|
|
1537
|
-
controller.signal
|
|
1538
|
-
);
|
|
1539
|
-
return result2;
|
|
1540
|
-
},
|
|
1541
|
-
pause: async (key) => {
|
|
1542
|
-
if (typeof key !== "string" || key.length === 0) {
|
|
1543
|
-
throw new Error("Factory pause checkpoint key must not be empty");
|
|
1544
|
-
}
|
|
1545
|
-
const helperScope = factoryExecutionStore.getStore()?.helperScope;
|
|
1546
|
-
if (helperScope !== void 0) {
|
|
1547
|
-
throw new Error(
|
|
1548
|
-
`Factory pause checkpoints are not allowed inside ${helperScope}() branches`
|
|
1549
|
-
);
|
|
1550
|
-
}
|
|
1551
|
-
await progress.flush();
|
|
1552
|
-
const response = await awaitFactoryOperation(
|
|
1553
|
-
() => self.internalRpc.factory.pauseAtCheckpoint({
|
|
1554
|
-
runId: params.runId,
|
|
1555
|
-
executionToken: params.executionToken,
|
|
1556
|
-
key
|
|
1557
|
-
}),
|
|
1558
|
-
controller.signal
|
|
1559
|
-
);
|
|
1560
|
-
switch (response.action) {
|
|
1561
|
-
case "continue":
|
|
1562
|
-
return;
|
|
1563
|
-
case "pause":
|
|
1564
|
-
await awaitFactoryOperation(
|
|
1565
|
-
() => new Promise(() => {
|
|
1566
|
-
}),
|
|
1567
|
-
controller.signal
|
|
1568
|
-
);
|
|
1569
|
-
}
|
|
1570
|
-
},
|
|
1571
|
-
parallel: runFactoryParallel,
|
|
1572
|
-
pipeline: runFactoryPipeline,
|
|
1573
|
-
factory: async () => {
|
|
1574
|
-
throw new Error("nested factories are not supported");
|
|
1575
|
-
}
|
|
1576
|
-
};
|
|
1577
|
-
const execution = { active: true };
|
|
1578
|
-
const result = await factoryExecutionStore.run(execution, async () => {
|
|
1579
|
-
try {
|
|
1580
|
-
return await definition.run(context);
|
|
1581
|
-
} finally {
|
|
1582
|
-
execution.active = false;
|
|
1583
|
-
}
|
|
1584
|
-
});
|
|
1585
|
-
if (result === void 0) {
|
|
1586
|
-
return {};
|
|
1587
|
-
}
|
|
1588
|
-
assertFactoryResult(result);
|
|
1589
|
-
return { result };
|
|
1590
|
-
} finally {
|
|
1591
|
-
try {
|
|
1592
|
-
await progress.close();
|
|
1593
|
-
} finally {
|
|
1594
|
-
const controllersForRun2 = self.factoryAbortControllers.get(params.runId);
|
|
1595
|
-
if (controllersForRun2?.get(params.executionToken) === controller) {
|
|
1596
|
-
controllersForRun2.delete(params.executionToken);
|
|
1597
|
-
if (controllersForRun2.size === 0) {
|
|
1598
|
-
self.factoryAbortControllers.delete(params.runId);
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
}
|
|
1603
|
-
},
|
|
1604
|
-
async abort(params) {
|
|
1605
|
-
const controllersForRun = self.factoryAbortControllers.get(params.runId);
|
|
1606
|
-
const controller = controllersForRun?.get(params.executionToken);
|
|
1607
|
-
if (controller !== void 0) {
|
|
1608
|
-
controller.abort(new DOMException("Factory run was aborted", "AbortError"));
|
|
1609
|
-
}
|
|
1610
|
-
return {};
|
|
1611
|
-
}
|
|
1612
|
-
};
|
|
1613
|
-
}
|
|
1614
1114
|
/**
|
|
1615
1115
|
* Registers workflow closures and reverse-RPC handlers for this session.
|
|
1616
1116
|
*
|
|
@@ -2477,20 +1977,6 @@ function assertStrictJson(value, context) {
|
|
|
2477
1977
|
};
|
|
2478
1978
|
visit(value, "$", context.allowTopLevelUndefined);
|
|
2479
1979
|
}
|
|
2480
|
-
function assertFactoryResult(value) {
|
|
2481
|
-
assertStrictJson(value, {
|
|
2482
|
-
code: "factory_result_not_json",
|
|
2483
|
-
label: "Factory result",
|
|
2484
|
-
allowTopLevelUndefined: true
|
|
2485
|
-
});
|
|
2486
|
-
}
|
|
2487
|
-
function assertFactoryStepResult(value, key) {
|
|
2488
|
-
assertStrictJson(value, {
|
|
2489
|
-
code: "factory_step_not_json",
|
|
2490
|
-
label: `Factory step "${key}" result`,
|
|
2491
|
-
allowTopLevelUndefined: false
|
|
2492
|
-
});
|
|
2493
|
-
}
|
|
2494
1980
|
function assertWorkflowResult(value) {
|
|
2495
1981
|
assertStrictJson(value, {
|
|
2496
1982
|
code: "workflow_result_not_json",
|