@github/copilot-sdk 1.0.8 → 1.0.9-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/README.md +18 -1
- package/dist/cjs/client.js +9 -0
- package/dist/cjs/extension.js +21 -6
- package/dist/cjs/factory.js +123 -0
- package/dist/cjs/generated/rpc.js +376 -11
- package/dist/cjs/index.js +11 -2
- package/dist/cjs/session.js +598 -3
- package/dist/cjs/sessionFsProvider.js +43 -0
- package/dist/cjs/types.js +3 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +9 -0
- package/dist/extension.d.ts +11 -2
- package/dist/extension.js +22 -6
- package/dist/factory.d.ts +273 -0
- package/dist/factory.js +96 -0
- package/dist/generated/rpc.d.ts +2445 -228
- package/dist/generated/rpc.js +376 -11
- package/dist/generated/session-events.d.ts +260 -6
- package/dist/index.d.ts +4 -2
- package/dist/index.js +7 -1
- package/dist/session.d.ts +21 -0
- package/dist/session.js +602 -3
- package/dist/sessionFsProvider.d.ts +38 -2
- package/dist/sessionFsProvider.js +42 -0
- package/dist/types.d.ts +95 -10
- package/dist/types.js +2 -0
- package/docs/extensions.md +1 -0
- package/docs/factories.md +240 -0
- package/docs/factory-patterns.md +194 -0
- package/package.json +2 -2
|
@@ -18,9 +18,19 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var sessionFsProvider_exports = {};
|
|
20
20
|
__export(sessionFsProvider_exports, {
|
|
21
|
+
SessionFsSqliteTransactionFailure: () => SessionFsSqliteTransactionFailure,
|
|
21
22
|
createSessionFsAdapter: () => createSessionFsAdapter
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(sessionFsProvider_exports);
|
|
25
|
+
class SessionFsSqliteTransactionFailure extends Error {
|
|
26
|
+
/** Failure classification reported to the runtime. */
|
|
27
|
+
errorClass;
|
|
28
|
+
constructor(message, errorClass = "fatal") {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = "SessionFsSqliteTransactionFailure";
|
|
31
|
+
this.errorClass = errorClass;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
24
34
|
function normalizeSqliteParams(params) {
|
|
25
35
|
if (!params) {
|
|
26
36
|
return void 0;
|
|
@@ -136,6 +146,29 @@ function createSessionFsAdapter(provider) {
|
|
|
136
146
|
);
|
|
137
147
|
return result ?? { rows: [], columns: [], rowsAffected: 0 };
|
|
138
148
|
},
|
|
149
|
+
sqliteTransaction: async ({ statements }) => {
|
|
150
|
+
if (!provider.sqlite?.transaction) {
|
|
151
|
+
return {
|
|
152
|
+
results: [],
|
|
153
|
+
error: {
|
|
154
|
+
errorClass: "fatal",
|
|
155
|
+
message: "SQLite transactions are not supported by this provider"
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
const results = await provider.sqlite.transaction(
|
|
161
|
+
statements.map((statement) => ({
|
|
162
|
+
queryType: statement.queryType,
|
|
163
|
+
query: statement.query,
|
|
164
|
+
params: normalizeSqliteParams(statement.params)
|
|
165
|
+
}))
|
|
166
|
+
);
|
|
167
|
+
return { results: results.map((result) => ({ ...result })) };
|
|
168
|
+
} catch (err) {
|
|
169
|
+
return { results: [], error: toSqliteTransactionError(err) };
|
|
170
|
+
}
|
|
171
|
+
},
|
|
139
172
|
sqliteExists: async () => {
|
|
140
173
|
if (!provider.sqlite) {
|
|
141
174
|
throw new Error("SQLite is not supported by this provider");
|
|
@@ -149,7 +182,17 @@ function toSessionFsError(err) {
|
|
|
149
182
|
const code = e.code === "ENOENT" ? "ENOENT" : "UNKNOWN";
|
|
150
183
|
return { code, message: e.message ?? String(err) };
|
|
151
184
|
}
|
|
185
|
+
function toSqliteTransactionError(err) {
|
|
186
|
+
if (err instanceof SessionFsSqliteTransactionFailure) {
|
|
187
|
+
return { errorClass: err.errorClass, message: err.message };
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
errorClass: "fatal",
|
|
191
|
+
message: err instanceof Error ? err.message : String(err)
|
|
192
|
+
};
|
|
193
|
+
}
|
|
152
194
|
// Annotate the CommonJS export names for ESM import in node:
|
|
153
195
|
0 && (module.exports = {
|
|
196
|
+
SessionFsSqliteTransactionFailure,
|
|
154
197
|
createSessionFsAdapter
|
|
155
198
|
});
|
package/dist/cjs/types.js
CHANGED
|
@@ -24,6 +24,7 @@ __export(types_exports, {
|
|
|
24
24
|
CopilotWebSocketHandler: () => import_copilotRequestHandler.CopilotWebSocketHandler,
|
|
25
25
|
RuntimeConnection: () => RuntimeConnection,
|
|
26
26
|
SYSTEM_MESSAGE_SECTIONS: () => SYSTEM_MESSAGE_SECTIONS,
|
|
27
|
+
SessionFsSqliteTransactionFailure: () => import_sessionFsProvider2.SessionFsSqliteTransactionFailure,
|
|
27
28
|
approveAll: () => approveAll,
|
|
28
29
|
convertMcpCallToolResult: () => convertMcpCallToolResult,
|
|
29
30
|
createSessionFsAdapter: () => import_sessionFsProvider.createSessionFsAdapter,
|
|
@@ -32,6 +33,7 @@ __export(types_exports, {
|
|
|
32
33
|
});
|
|
33
34
|
module.exports = __toCommonJS(types_exports);
|
|
34
35
|
var import_sessionFsProvider = require("./sessionFsProvider.js");
|
|
36
|
+
var import_sessionFsProvider2 = require("./sessionFsProvider.js");
|
|
35
37
|
var import_copilotRequestHandler = require("./copilotRequestHandler.js");
|
|
36
38
|
const RuntimeConnection = {
|
|
37
39
|
/**
|
|
@@ -151,6 +153,7 @@ const defaultJoinSessionPermissionHandler = () => ({
|
|
|
151
153
|
CopilotWebSocketHandler,
|
|
152
154
|
RuntimeConnection,
|
|
153
155
|
SYSTEM_MESSAGE_SECTIONS,
|
|
156
|
+
SessionFsSqliteTransactionFailure,
|
|
154
157
|
approveAll,
|
|
155
158
|
convertMcpCallToolResult,
|
|
156
159
|
createSessionFsAdapter,
|
package/dist/client.d.ts
CHANGED
|
@@ -224,6 +224,7 @@ export declare class CopilotClient {
|
|
|
224
224
|
* ```
|
|
225
225
|
*/
|
|
226
226
|
resumeSession(sessionId: string, config: ResumeSessionConfig): Promise<CopilotSession>;
|
|
227
|
+
private resumeSessionInternal;
|
|
227
228
|
/**
|
|
228
229
|
* Sends a ping request to the server to verify connectivity.
|
|
229
230
|
*
|
package/dist/client.js
CHANGED
|
@@ -1180,6 +1180,13 @@ class CopilotClient {
|
|
|
1180
1180
|
* ```
|
|
1181
1181
|
*/
|
|
1182
1182
|
async resumeSession(sessionId, config) {
|
|
1183
|
+
return this.resumeSessionInternal(sessionId, config);
|
|
1184
|
+
}
|
|
1185
|
+
/** @internal */
|
|
1186
|
+
async resumeSessionForExtension(sessionId, config, factories) {
|
|
1187
|
+
return this.resumeSessionInternal(sessionId, config, factories);
|
|
1188
|
+
}
|
|
1189
|
+
async resumeSessionInternal(sessionId, config, factories) {
|
|
1183
1190
|
if (!this.connection) {
|
|
1184
1191
|
await this.start();
|
|
1185
1192
|
}
|
|
@@ -1193,6 +1200,7 @@ class CopilotClient {
|
|
|
1193
1200
|
session.registerTools(config.tools);
|
|
1194
1201
|
session.registerCanvases(config.canvases);
|
|
1195
1202
|
session.registerCommands(config.commands);
|
|
1203
|
+
session.registerFactories(factories);
|
|
1196
1204
|
const {
|
|
1197
1205
|
wireProvider: bearerWireProvider,
|
|
1198
1206
|
wireProviders: bearerWireProviders,
|
|
@@ -1259,6 +1267,7 @@ class CopilotClient {
|
|
|
1259
1267
|
})),
|
|
1260
1268
|
toolSearch: config.toolSearch,
|
|
1261
1269
|
canvases: config.canvases?.map((canvas) => canvas.declaration),
|
|
1270
|
+
factories: factories?.map((factory) => factory.meta),
|
|
1262
1271
|
requestCanvasRenderer: config.requestCanvasRenderer,
|
|
1263
1272
|
requestExtensions: config.requestExtensions,
|
|
1264
1273
|
extensionSdkPath: config.extensionSdkPath,
|
package/dist/extension.d.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import type { CopilotSession } from "./session.js";
|
|
2
|
-
import { type
|
|
2
|
+
import { type PermissionHandler, type ResumeSessionConfig } from "./types.js";
|
|
3
|
+
import type { FactoryHandle } from "./factory.js";
|
|
3
4
|
export { Canvas, CanvasError, createCanvas, type CanvasAction, type CanvasDeclaration, type CanvasHostContext, type CanvasJsonSchema, type CanvasOptions, } from "./canvas.js";
|
|
4
5
|
export type JoinSessionConfig = Omit<ResumeSessionConfig, "onPermissionRequest" | "extensionSdkPath"> & {
|
|
5
6
|
onPermissionRequest?: PermissionHandler;
|
|
7
|
+
/**
|
|
8
|
+
* Factory handles to register when the extension joins the session.
|
|
9
|
+
*
|
|
10
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
11
|
+
* change or be removed in future SDK or CLI releases.
|
|
12
|
+
*/
|
|
13
|
+
factories?: FactoryHandle[];
|
|
6
14
|
};
|
|
7
|
-
export type { ExtensionInfo };
|
|
15
|
+
export type { ExtensionInfo, FactoryLimits, FactoryMeta } from "./types.js";
|
|
16
|
+
export { defineFactory, FactoryResumeError, isFactoryRunTerminal, type RunOptions, type ResumeOptions, type FactoryResumeErrorCode, type SessionFactoryApi, type FactoryAgentOptions, type FactoryContext, type FactoryDefinition, type FactoryHandle, type FactoryJsonSchema, type JsonValue, type FactoryPipelineStage, type FactoryStepOptions, type FactoryRunResult, type FactoryRunStatus, type FactoryRunSummary, type FactoryRunDetail, type FactoryProgressPage, type FactoryProgressLine, type FactoryPhaseObservation, type FactoryPhaseStatus, type FactoryAgentSummary, } from "./factory.js";
|
|
8
17
|
/**
|
|
9
18
|
* Joins the current foreground session.
|
|
10
19
|
*
|
package/dist/extension.js
CHANGED
|
@@ -7,6 +7,11 @@ import {
|
|
|
7
7
|
CanvasError,
|
|
8
8
|
createCanvas
|
|
9
9
|
} from "./canvas.js";
|
|
10
|
+
import {
|
|
11
|
+
defineFactory,
|
|
12
|
+
FactoryResumeError,
|
|
13
|
+
isFactoryRunTerminal
|
|
14
|
+
} from "./factory.js";
|
|
10
15
|
async function joinSession(config = {}) {
|
|
11
16
|
const sessionId = process.env.SESSION_ID;
|
|
12
17
|
if (!sessionId) {
|
|
@@ -15,17 +20,28 @@ async function joinSession(config = {}) {
|
|
|
15
20
|
);
|
|
16
21
|
}
|
|
17
22
|
const client = new CopilotClient({ _internalConnection: { kind: "parent-process" } });
|
|
18
|
-
const {
|
|
23
|
+
const {
|
|
24
|
+
extensionSdkPath: _stripped,
|
|
25
|
+
factories,
|
|
26
|
+
...rest
|
|
27
|
+
} = config;
|
|
19
28
|
void _stripped;
|
|
20
|
-
return client.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
return client.resumeSessionForExtension(
|
|
30
|
+
sessionId,
|
|
31
|
+
{
|
|
32
|
+
...rest,
|
|
33
|
+
onPermissionRequest: config.onPermissionRequest ?? defaultJoinSessionPermissionHandler,
|
|
34
|
+
suppressResumeEvent: config.suppressResumeEvent ?? true
|
|
35
|
+
},
|
|
36
|
+
factories
|
|
37
|
+
);
|
|
25
38
|
}
|
|
26
39
|
export {
|
|
27
40
|
Canvas,
|
|
28
41
|
CanvasError,
|
|
42
|
+
FactoryResumeError,
|
|
29
43
|
createCanvas,
|
|
44
|
+
defineFactory,
|
|
45
|
+
isFactoryRunTerminal,
|
|
30
46
|
joinSession
|
|
31
47
|
};
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import type { FactoryGetRunProgressRequest, FactoryProgressPage, FactoryRunDetail, FactoryRunResult as WireFactoryRunResult, FactoryRunStatus, FactoryRunSummary } from "./generated/rpc.js";
|
|
2
|
+
import type { CopilotSession } from "./session.js";
|
|
3
|
+
import type { FactoryLimits, FactoryMeta } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* The envelope describing a factory run: its identity, status, and — once it
|
|
6
|
+
* has completed — its result. `getRun` returns this for an in-flight run too,
|
|
7
|
+
* so `status` may be `pending` or `running` and the outcome fields absent.
|
|
8
|
+
*
|
|
9
|
+
* `result` is re-typed here rather than taken from the generated wire type. The
|
|
10
|
+
* runtime returns any JSON value — including `null`, a string, a number, or an
|
|
11
|
+
* array — but the schema models the field as an opaque node, which the
|
|
12
|
+
* generator renders as an object. Narrowing the correction to this surface
|
|
13
|
+
* keeps the `x-opaque-json` handling unchanged for every other consumer.
|
|
14
|
+
*
|
|
15
|
+
* This override is temporary. Once the schema distinguishes an opaque JSON
|
|
16
|
+
* value from an opaque in-process value and that ships in a CLI release,
|
|
17
|
+
* regenerating produces the right type directly, and this declaration, the
|
|
18
|
+
* `toPublicFactoryRunResult` boundary helper, and the casts around it should
|
|
19
|
+
* all be deleted. Tracked by github/copilot-agent-runtime#14122.
|
|
20
|
+
*
|
|
21
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
22
|
+
* change or be removed in future SDK or CLI releases.
|
|
23
|
+
*/
|
|
24
|
+
export type FactoryRunResult = Omit<WireFactoryRunResult, "result"> & {
|
|
25
|
+
/** Completed factory result. */
|
|
26
|
+
result?: JsonValue;
|
|
27
|
+
};
|
|
28
|
+
export type { FactoryAgentSummary, FactoryPhaseStatus, FactoryPhaseObservation, FactoryProgressLine, FactoryProgressPage, FactoryRunDetail, FactoryRunStatus, FactoryRunSummary, } from "./generated/rpc.js";
|
|
29
|
+
/**
|
|
30
|
+
* Whether a factory run status is terminal.
|
|
31
|
+
*
|
|
32
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
33
|
+
* change or be removed in future SDK or CLI releases.
|
|
34
|
+
*/
|
|
35
|
+
export declare function isFactoryRunTerminal(status: FactoryRunStatus): boolean;
|
|
36
|
+
declare const factoryHandleBrand: unique symbol;
|
|
37
|
+
/** A value that can be represented losslessly on the SDK JSON wire. */
|
|
38
|
+
export type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
39
|
+
[key: string]: JsonValue;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Conservative JSON shape language accepted for structured factory agent output.
|
|
43
|
+
*
|
|
44
|
+
* This is a best-effort structural guard used to decide whether a subagent's
|
|
45
|
+
* structured output should be accepted or retried — **not** a full JSON Schema
|
|
46
|
+
* validator. Only these keywords are honored: `type`, `required`, `enum`,
|
|
47
|
+
* `const`, recursive `properties`/`items`, and `anyOf`/`oneOf`/`allOf`.
|
|
48
|
+
*
|
|
49
|
+
* Everything else is **ignored, not enforced**. In particular, string
|
|
50
|
+
* constraints (`pattern`, `minLength`, `maxLength`, `format`), numeric ranges
|
|
51
|
+
* (`minimum`, `maximum`), `additionalProperties`, and boolean (`true`/`false`)
|
|
52
|
+
* schemas do not reject non-conforming output. `oneOf` is treated like `anyOf`
|
|
53
|
+
* (at least one branch must match) rather than strict exactly-one. Author
|
|
54
|
+
* schemas within this subset; do not rely on unsupported constraints for
|
|
55
|
+
* correctness.
|
|
56
|
+
*
|
|
57
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
58
|
+
* change or be removed in future SDK or CLI releases.
|
|
59
|
+
*/
|
|
60
|
+
export type FactoryJsonSchema = {
|
|
61
|
+
[key: string]: JsonValue;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Options for one factory-scoped subagent call.
|
|
65
|
+
*
|
|
66
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
67
|
+
* change or be removed in future SDK or CLI releases.
|
|
68
|
+
*/
|
|
69
|
+
export interface FactoryAgentOptions {
|
|
70
|
+
label?: string;
|
|
71
|
+
schema?: FactoryJsonSchema;
|
|
72
|
+
model?: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Options for a durable factory step.
|
|
76
|
+
*
|
|
77
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
78
|
+
* change or be removed in future SDK or CLI releases.
|
|
79
|
+
*/
|
|
80
|
+
export interface FactoryStepOptions {
|
|
81
|
+
/** Skip the journal and always invoke the producer. */
|
|
82
|
+
volatile?: boolean;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* One stage in a per-item factory pipeline.
|
|
86
|
+
*
|
|
87
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
88
|
+
* change or be removed in future SDK or CLI releases.
|
|
89
|
+
*/
|
|
90
|
+
export type FactoryPipelineStage<TInput = unknown, TResult = unknown> = (previous: TInput, item: unknown, index: number) => Promise<TResult> | TResult;
|
|
91
|
+
/**
|
|
92
|
+
* Context passed to an extension-authored factory body.
|
|
93
|
+
*
|
|
94
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
95
|
+
* change or be removed in future SDK or CLI releases.
|
|
96
|
+
*/
|
|
97
|
+
export interface FactoryContext<TArgs extends JsonValue = JsonValue> {
|
|
98
|
+
/** Stable identifier for the current factory run. */
|
|
99
|
+
readonly runId: string;
|
|
100
|
+
/** Spawn and await one factory-scoped subagent. */
|
|
101
|
+
agent(prompt: string, options?: FactoryAgentOptions): Promise<unknown>;
|
|
102
|
+
/** Memoize an arbitrary producer under a stable author-supplied key. */
|
|
103
|
+
step(key: string, producer: () => Promise<JsonValue> | JsonValue, options?: FactoryStepOptions): Promise<JsonValue>;
|
|
104
|
+
/**
|
|
105
|
+
* Run thunks concurrently and await all of them.
|
|
106
|
+
*
|
|
107
|
+
* A thunk that throws becomes `null` in the result array, so one failed
|
|
108
|
+
* item does not lose the rest. Cancellation and hard runtime failures
|
|
109
|
+
* (`ResponseError`, `ConnectionError`) are the exception: those propagate
|
|
110
|
+
* and reject the whole call, because they mean the run itself is in
|
|
111
|
+
* trouble rather than one item having failed.
|
|
112
|
+
*/
|
|
113
|
+
parallel<TResult>(thunks: Array<() => Promise<TResult> | TResult>): Promise<Array<TResult | null>>;
|
|
114
|
+
/**
|
|
115
|
+
* Run each item through every stage without barriers between stages.
|
|
116
|
+
*
|
|
117
|
+
* A stage that throws drops that item to `null` and skips its remaining
|
|
118
|
+
* stages. As with {@link FactoryContext.parallel}, cancellation and hard
|
|
119
|
+
* runtime failures propagate instead of being recorded per item.
|
|
120
|
+
*/
|
|
121
|
+
pipeline(items: unknown[], ...stages: FactoryPipelineStage[]): Promise<unknown[]>;
|
|
122
|
+
/** Start a named factory progress phase. */
|
|
123
|
+
phase(title: string): void;
|
|
124
|
+
/** Emit a factory progress line. */
|
|
125
|
+
log(message: string): void;
|
|
126
|
+
/** Reject because nested factories are not supported. */
|
|
127
|
+
factory(name: string, args?: JsonValue): Promise<JsonValue | void>;
|
|
128
|
+
/** Caller-supplied input, forwarded verbatim. */
|
|
129
|
+
args: TArgs;
|
|
130
|
+
/** The same full session instance returned by `joinSession`. */
|
|
131
|
+
session: CopilotSession;
|
|
132
|
+
/** Cooperative cancellation signal for the current factory run. */
|
|
133
|
+
signal: AbortSignal;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Definition accepted by {@link defineFactory}.
|
|
137
|
+
*
|
|
138
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
139
|
+
* change or be removed in future SDK or CLI releases.
|
|
140
|
+
*/
|
|
141
|
+
export interface FactoryDefinition<TArgs extends JsonValue = JsonValue, TResult extends JsonValue | void = JsonValue | void> {
|
|
142
|
+
meta: FactoryMeta;
|
|
143
|
+
run(context: FactoryContext<TArgs>): Promise<TResult>;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* A deeply immutable view of a value.
|
|
147
|
+
*
|
|
148
|
+
* `defineFactory` deep-freezes the metadata it stores, so the handle's view of
|
|
149
|
+
* it has to be readonly all the way down or `handle.meta.name = "..."` and
|
|
150
|
+
* `handle.meta.phases.push(...)` would compile and then throw at runtime.
|
|
151
|
+
*/
|
|
152
|
+
type DeepReadonly<T> = T extends (infer U)[] ? readonly DeepReadonly<U>[] : T extends object ? {
|
|
153
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
154
|
+
} : T;
|
|
155
|
+
/**
|
|
156
|
+
* Opaque reusable reference to a defined factory.
|
|
157
|
+
*
|
|
158
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
159
|
+
* change or be removed in future SDK or CLI releases.
|
|
160
|
+
*/
|
|
161
|
+
export interface FactoryHandle<TArgs extends JsonValue = JsonValue, TResult extends JsonValue | void = JsonValue | void> {
|
|
162
|
+
readonly meta: DeepReadonly<FactoryMeta>;
|
|
163
|
+
readonly [factoryHandleBrand]: {
|
|
164
|
+
readonly args: TArgs;
|
|
165
|
+
readonly result: TResult;
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Options for invoking a factory.
|
|
170
|
+
*
|
|
171
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
172
|
+
* change or be removed in future SDK or CLI releases.
|
|
173
|
+
*/
|
|
174
|
+
export interface RunOptions<TArgs extends JsonValue = JsonValue> {
|
|
175
|
+
/** Input surfaced as `context.args`. */
|
|
176
|
+
args?: TArgs;
|
|
177
|
+
/** Optional per-invocation resource ceiling overrides. */
|
|
178
|
+
limits?: FactoryLimits;
|
|
179
|
+
/**
|
|
180
|
+
* Prior run whose persisted identity, arguments, journal, and accounting should be resumed.
|
|
181
|
+
*
|
|
182
|
+
* @deprecated Use {@link SessionFactoryApi.resume} instead.
|
|
183
|
+
*/
|
|
184
|
+
resumeFromRunId?: string;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Options for resuming a factory run by ID.
|
|
188
|
+
*
|
|
189
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
190
|
+
* change or be removed in future SDK or CLI releases.
|
|
191
|
+
*/
|
|
192
|
+
export interface ResumeOptions {
|
|
193
|
+
/** Optional per-invocation resource ceiling overrides. */
|
|
194
|
+
limits?: FactoryLimits;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Machine-readable pre-execution factory resume failure.
|
|
198
|
+
*
|
|
199
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
200
|
+
* change or be removed in future SDK or CLI releases.
|
|
201
|
+
*/
|
|
202
|
+
export type FactoryResumeErrorCode = "not_found" | "non_resumable" | "already_active" | "reapproval_declined" | "no_approval_provider";
|
|
203
|
+
/**
|
|
204
|
+
* Friendly factory API exposed on a session.
|
|
205
|
+
*
|
|
206
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
207
|
+
* change or be removed in future SDK or CLI releases.
|
|
208
|
+
*/
|
|
209
|
+
export interface SessionFactoryApi {
|
|
210
|
+
/**
|
|
211
|
+
* Run a registered factory and resolve with its run envelope.
|
|
212
|
+
*
|
|
213
|
+
* The envelope is returned for every outcome, including `error`, `halted`,
|
|
214
|
+
* and `cancelled` — inspect `status` and read `result` only when the run
|
|
215
|
+
* completed. A declined fresh run resolves with a terminal `cancelled`
|
|
216
|
+
* envelope. Failures that occur before a run exists (such as an unknown
|
|
217
|
+
* factory or an already-active session) still reject.
|
|
218
|
+
*/
|
|
219
|
+
run(name: string, options?: RunOptions): Promise<FactoryRunResult>;
|
|
220
|
+
run<TArgs extends JsonValue>(factory: FactoryHandle<TArgs, JsonValue | void>, options?: RunOptions<TArgs>): Promise<FactoryRunResult>;
|
|
221
|
+
/**
|
|
222
|
+
* Resume a run from its persisted factory name, arguments, journal, and accounting.
|
|
223
|
+
*
|
|
224
|
+
* Resolves with the run envelope like {@link SessionFactoryApi.run}. A
|
|
225
|
+
* pre-execution failure, including declined reapproval, rejects with
|
|
226
|
+
* {@link FactoryResumeError}.
|
|
227
|
+
*/
|
|
228
|
+
resume(runId: string, options?: ResumeOptions): Promise<FactoryRunResult>;
|
|
229
|
+
/** Read the latest durable envelope for a factory run. */
|
|
230
|
+
getRun(runId: string): Promise<FactoryRunResult>;
|
|
231
|
+
/**
|
|
232
|
+
* Wait for a run to settle and resolve with its terminal envelope.
|
|
233
|
+
*
|
|
234
|
+
* Resolves as soon as the run reaches `completed`, `error`, `halted`, or
|
|
235
|
+
* `cancelled`, and resolves immediately when it has already settled. A
|
|
236
|
+
* terminal envelope is final, so the resolved value never changes
|
|
237
|
+
* afterwards.
|
|
238
|
+
*
|
|
239
|
+
* This watches the run's `factory.run_updated` invalidation events and
|
|
240
|
+
* periodically re-reads the durable envelope so a missed event cannot
|
|
241
|
+
* leave the wait hanging. Pass a `signal` to stop waiting; aborting rejects
|
|
242
|
+
* and has no effect on the run itself, which keeps executing. Use
|
|
243
|
+
* {@link SessionFactoryApi.cancel} to actually stop it.
|
|
244
|
+
*/
|
|
245
|
+
waitForRun(runId: string, options?: {
|
|
246
|
+
signal?: AbortSignal;
|
|
247
|
+
}): Promise<FactoryRunResult>;
|
|
248
|
+
/** List this session's durable factory runs in creation order. */
|
|
249
|
+
listRuns(): Promise<FactoryRunSummary[]>;
|
|
250
|
+
/** Read durable phases, direct agents, and the latest progress tail for a run. */
|
|
251
|
+
getRunDetail(runId: string): Promise<FactoryRunDetail>;
|
|
252
|
+
/** Page durable progress forward, backward, or from the latest tail. */
|
|
253
|
+
getRunProgress(runId: string, options?: Omit<FactoryGetRunProgressRequest, "runId">): Promise<FactoryProgressPage>;
|
|
254
|
+
/** Cancel a factory run and return its terminal envelope. */
|
|
255
|
+
cancel(runId: string): Promise<FactoryRunResult>;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Error thrown when a factory cannot be resumed before execution begins.
|
|
259
|
+
*
|
|
260
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
261
|
+
* change or be removed in future SDK or CLI releases.
|
|
262
|
+
*/
|
|
263
|
+
export declare class FactoryResumeError extends Error {
|
|
264
|
+
readonly code: FactoryResumeErrorCode;
|
|
265
|
+
constructor(code: FactoryResumeErrorCode, message: string);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Defines an extension-authored factory and returns an opaque registration handle.
|
|
269
|
+
*
|
|
270
|
+
* @experimental Part of the experimental Agent Factories surface and may
|
|
271
|
+
* change or be removed in future SDK or CLI releases.
|
|
272
|
+
*/
|
|
273
|
+
export declare function defineFactory<TArgs extends JsonValue = JsonValue, TResult extends JsonValue | void = JsonValue | void>(definition: FactoryDefinition<TArgs, TResult>): FactoryHandle<TArgs, TResult>;
|
package/dist/factory.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
const FACTORY_TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
2
|
+
"completed",
|
|
3
|
+
"halted",
|
|
4
|
+
"cancelled",
|
|
5
|
+
"error"
|
|
6
|
+
]);
|
|
7
|
+
function isFactoryRunTerminal(status) {
|
|
8
|
+
return FACTORY_TERMINAL_STATUSES.has(status);
|
|
9
|
+
}
|
|
10
|
+
class FactoryResumeError extends Error {
|
|
11
|
+
constructor(code, message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.name = "FactoryResumeError";
|
|
15
|
+
}
|
|
16
|
+
code;
|
|
17
|
+
}
|
|
18
|
+
const factoryHandles = /* @__PURE__ */ new WeakMap();
|
|
19
|
+
const MAX_FACTORY_TIMEOUT_SECONDS = 2147483647e-3;
|
|
20
|
+
const NANO_AIU_PER_AIU = 1e9;
|
|
21
|
+
function deepFreeze(value) {
|
|
22
|
+
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
|
|
23
|
+
Object.freeze(value);
|
|
24
|
+
for (const nested of Object.values(value)) {
|
|
25
|
+
deepFreeze(nested);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
function validateLimits(meta) {
|
|
31
|
+
const limits = meta.limits;
|
|
32
|
+
if (!limits) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
for (const field of ["maxConcurrentSubagents", "maxTotalSubagents"]) {
|
|
36
|
+
const value = limits[field];
|
|
37
|
+
if (value !== void 0 && (!Number.isInteger(value) || value <= 0)) {
|
|
38
|
+
throw new Error(`Factory limit "${field}" must be a positive integer`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (limits.timeoutSeconds !== void 0 && (!Number.isFinite(limits.timeoutSeconds) || limits.timeoutSeconds <= 0)) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
'Factory limit "timeoutSeconds" must be a positive, finite number of seconds'
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (limits.timeoutSeconds !== void 0 && limits.timeoutSeconds > MAX_FACTORY_TIMEOUT_SECONDS) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Factory limit "timeoutSeconds" must not exceed ${MAX_FACTORY_TIMEOUT_SECONDS} seconds`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
if (limits.maxAiCredits !== void 0) {
|
|
52
|
+
const maxNanoAiu = Math.round(limits.maxAiCredits * NANO_AIU_PER_AIU);
|
|
53
|
+
if (!Number.isFinite(limits.maxAiCredits) || limits.maxAiCredits <= 0 || !Number.isSafeInteger(maxNanoAiu) || maxNanoAiu < 1) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
'Factory limit "maxAiCredits" must be a positive, finite number that rounds to a safe positive integer nano-AIU ceiling'
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function validatePhases(meta) {
|
|
61
|
+
const titles = /* @__PURE__ */ new Set();
|
|
62
|
+
for (const phase of meta.phases) {
|
|
63
|
+
if (phase.title.trim().length === 0) {
|
|
64
|
+
throw new Error("Factory phase titles must not be empty");
|
|
65
|
+
}
|
|
66
|
+
if (titles.has(phase.title)) {
|
|
67
|
+
throw new Error(`Factory phase title "${phase.title}" is declared more than once`);
|
|
68
|
+
}
|
|
69
|
+
titles.add(phase.title);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function defineFactory(definition) {
|
|
73
|
+
const meta = deepFreeze(structuredClone(definition.meta));
|
|
74
|
+
validateLimits(meta);
|
|
75
|
+
validatePhases(meta);
|
|
76
|
+
const stored = {
|
|
77
|
+
meta,
|
|
78
|
+
run: definition.run
|
|
79
|
+
};
|
|
80
|
+
const handle = Object.freeze({ meta });
|
|
81
|
+
factoryHandles.set(handle, stored);
|
|
82
|
+
return handle;
|
|
83
|
+
}
|
|
84
|
+
function getFactoryDefinition(handle) {
|
|
85
|
+
const definition = factoryHandles.get(handle);
|
|
86
|
+
if (!definition) {
|
|
87
|
+
throw new Error("Invalid factory handle");
|
|
88
|
+
}
|
|
89
|
+
return definition;
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
FactoryResumeError,
|
|
93
|
+
defineFactory,
|
|
94
|
+
getFactoryDefinition,
|
|
95
|
+
isFactoryRunTerminal
|
|
96
|
+
};
|