@ai-sdk/code-mode 1.0.79 → 1.0.80
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/approval-continuation.js +48 -74
- package/dist/approval-continuation.js.map +1 -1
- package/dist/approval.js +12 -23
- package/dist/approval.js.map +1 -1
- package/dist/code-mode-tool.js +39 -51
- package/dist/code-mode-tool.js.map +1 -1
- package/dist/continuation-capability.js +74 -105
- package/dist/continuation-capability.js.map +1 -1
- package/dist/direct-tool-call.js +9 -3
- package/dist/direct-tool-call.js.map +1 -1
- package/dist/errors.js +109 -96
- package/dist/errors.js.map +1 -1
- package/dist/host-interrupt.js +7 -12
- package/dist/host-interrupt.js.map +1 -1
- package/dist/index.d.ts +172 -163
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -61
- package/dist/interrupt-continuation.js +54 -90
- package/dist/interrupt-continuation.js.map +1 -1
- package/dist/run-code-mode.js +292 -494
- package/dist/run-code-mode.js.map +1 -1
- package/dist/tool-invocation.js +98 -176
- package/dist/tool-invocation.js.map +1 -1
- package/dist/tool-prompt.js +254 -392
- package/dist/tool-prompt.js.map +1 -1
- package/dist/types.js +1 -1
- package/dist/utils/serialization.js +23 -39
- package/dist/utils/serialization.js.map +1 -1
- package/package.json +6 -6
- package/dist/index.js.map +0 -1
- package/dist/types.js.map +0 -1
|
@@ -1,83 +1,57 @@
|
|
|
1
|
-
import {
|
|
2
|
-
assertCodeModeApprovalResponse,
|
|
3
|
-
CODE_MODE_TOOL_APPROVAL_KIND
|
|
4
|
-
} from "./approval.js";
|
|
5
1
|
import { CodeModeProtocolError } from "./errors.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./interrupt-continuation.js";
|
|
2
|
+
import { assertCodeModeApprovalResponse } from "./approval.js";
|
|
3
|
+
import { continueCodeModeInterrupt, isCodeModeInterrupt } from "./interrupt-continuation.js";
|
|
4
|
+
//#region src/approval-continuation.ts
|
|
10
5
|
function isCodeModeApprovalInterrupt(value, continuationSecurity = {}) {
|
|
11
|
-
|
|
6
|
+
return isCodeModeInterrupt(value, continuationSecurity) && value.payload.kind === "ai-sdk-code-mode/tool-approval";
|
|
12
7
|
}
|
|
13
|
-
async function continueCodeModeApproval({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
tools,
|
|
33
|
-
options: {
|
|
34
|
-
...options,
|
|
35
|
-
approval: { ...options.approval, mode: "interrupt" }
|
|
36
|
-
},
|
|
37
|
-
...toolExecutionOptions !== void 0 ? { toolExecutionOptions } : {}
|
|
38
|
-
});
|
|
8
|
+
async function continueCodeModeApproval({ interrupt, approvalResponse, tools, options = {}, toolExecutionOptions }) {
|
|
9
|
+
assertCodeModeApprovalResponse(approvalResponse);
|
|
10
|
+
if (approvalResponse.approvalId !== interrupt.interruptId) throw new CodeModeProtocolError(`Approval response ${approvalResponse.approvalId} does not match pending code-mode approval ${interrupt.interruptId}.`);
|
|
11
|
+
return await continueCodeModeInterrupt({
|
|
12
|
+
interrupt,
|
|
13
|
+
resolution: {
|
|
14
|
+
approved: approvalResponse.approved,
|
|
15
|
+
...approvalResponse.reason !== void 0 ? { reason: approvalResponse.reason } : {}
|
|
16
|
+
},
|
|
17
|
+
tools,
|
|
18
|
+
options: {
|
|
19
|
+
...options,
|
|
20
|
+
approval: {
|
|
21
|
+
...options.approval,
|
|
22
|
+
mode: "interrupt"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
...toolExecutionOptions !== void 0 ? { toolExecutionOptions } : {}
|
|
26
|
+
});
|
|
39
27
|
}
|
|
40
28
|
function toCodeModeApprovalMessages(interrupt) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
toolCallId: interrupt.toolCallId
|
|
55
|
-
}
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
];
|
|
29
|
+
return [{
|
|
30
|
+
role: "assistant",
|
|
31
|
+
content: [{
|
|
32
|
+
type: "tool-call",
|
|
33
|
+
toolCallId: interrupt.toolCallId,
|
|
34
|
+
toolName: interrupt.toolName,
|
|
35
|
+
input: interrupt.input
|
|
36
|
+
}, {
|
|
37
|
+
type: "tool-approval-request",
|
|
38
|
+
approvalId: interrupt.interruptId,
|
|
39
|
+
toolCallId: interrupt.toolCallId
|
|
40
|
+
}]
|
|
41
|
+
}];
|
|
59
42
|
}
|
|
60
43
|
function getCodeModeApprovalResponse(messages, interrupt) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
approved: part.approved,
|
|
71
|
-
...part.reason !== void 0 ? { reason: part.reason } : {}
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
44
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
45
|
+
const message = messages[index];
|
|
46
|
+
if (message?.role !== "tool") continue;
|
|
47
|
+
for (const part of message.content) if (part.type === "tool-approval-response" && part.approvalId === interrupt.interruptId && typeof part.approved === "boolean" && (part.reason === void 0 || typeof part.reason === "string")) return {
|
|
48
|
+
approvalId: part.approvalId,
|
|
49
|
+
approved: part.approved,
|
|
50
|
+
...part.reason !== void 0 ? { reason: part.reason } : {}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
76
53
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
isCodeModeApprovalInterrupt,
|
|
81
|
-
toCodeModeApprovalMessages
|
|
82
|
-
};
|
|
54
|
+
//#endregion
|
|
55
|
+
export { continueCodeModeApproval, getCodeModeApprovalResponse, isCodeModeApprovalInterrupt, toCodeModeApprovalMessages };
|
|
56
|
+
|
|
83
57
|
//# sourceMappingURL=approval-continuation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/approval-continuation.ts"],"sourcesContent":["import type { ModelMessage } from 'ai';\nimport {\n assertCodeModeApprovalResponse,\n CODE_MODE_TOOL_APPROVAL_KIND,\n} from './approval.js';\nimport { CodeModeProtocolError } from './errors.js';\nimport {\n continueCodeModeInterrupt,\n isCodeModeInterrupt,\n} from './interrupt-continuation.js';\nimport type {\n CodeModeApprovalInterrupt,\n CodeModeApprovalResponse,\n CodeModeContinuationSecurityOptions,\n CodeModeOptions,\n CodeModeToolExecutionOptions,\n CodeModeToolSet,\n} from './types.js';\n\nexport function isCodeModeApprovalInterrupt(\n value: unknown,\n continuationSecurity: CodeModeContinuationSecurityOptions = {},\n): value is CodeModeApprovalInterrupt {\n return (\n isCodeModeInterrupt(value, continuationSecurity) &&\n value.payload.kind === CODE_MODE_TOOL_APPROVAL_KIND\n );\n}\n\nexport async function continueCodeModeApproval({\n interrupt,\n approvalResponse,\n tools,\n options = {},\n toolExecutionOptions,\n}: {\n interrupt: CodeModeApprovalInterrupt;\n approvalResponse: CodeModeApprovalResponse;\n tools: CodeModeToolSet;\n options?: CodeModeOptions;\n toolExecutionOptions?: Partial<CodeModeToolExecutionOptions>;\n}): Promise<unknown> {\n assertCodeModeApprovalResponse(approvalResponse);\n if (approvalResponse.approvalId !== interrupt.interruptId) {\n throw new CodeModeProtocolError(\n `Approval response ${approvalResponse.approvalId} does not match pending code-mode approval ${interrupt.interruptId}.`,\n );\n }\n\n return await continueCodeModeInterrupt({\n interrupt,\n resolution: {\n approved: approvalResponse.approved,\n ...(approvalResponse.reason !== undefined\n ? { reason: approvalResponse.reason }\n : {}),\n },\n tools,\n options: {\n ...options,\n approval: { ...options.approval, mode: 'interrupt' },\n },\n ...(toolExecutionOptions !== undefined ? { toolExecutionOptions } : {}),\n });\n}\n\nexport function toCodeModeApprovalMessages(\n interrupt: CodeModeApprovalInterrupt,\n): ModelMessage[] {\n return [\n {\n role: 'assistant',\n content: [\n {\n type: 'tool-call',\n toolCallId: interrupt.toolCallId,\n toolName: interrupt.toolName,\n input: interrupt.input,\n },\n {\n type: 'tool-approval-request',\n approvalId: interrupt.interruptId,\n toolCallId: interrupt.toolCallId,\n },\n ],\n },\n ];\n}\n\nexport function getCodeModeApprovalResponse(\n messages: ModelMessage[],\n interrupt: CodeModeApprovalInterrupt,\n): CodeModeApprovalResponse | undefined {\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index];\n if (message?.role !== 'tool') {\n continue;\n }\n for (const part of message.content) {\n if (\n part.type === 'tool-approval-response' &&\n part.approvalId === interrupt.interruptId &&\n typeof part.approved === 'boolean' &&\n (part.reason === undefined || typeof part.reason === 'string')\n ) {\n return {\n approvalId: part.approvalId,\n approved: part.approved,\n ...(part.reason !== undefined ? { reason: part.reason } : {}),\n };\n }\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"approval-continuation.js","names":[],"sources":["../src/approval-continuation.ts"],"sourcesContent":["import type { ModelMessage } from 'ai';\nimport {\n assertCodeModeApprovalResponse,\n CODE_MODE_TOOL_APPROVAL_KIND,\n} from './approval.js';\nimport { CodeModeProtocolError } from './errors.js';\nimport {\n continueCodeModeInterrupt,\n isCodeModeInterrupt,\n} from './interrupt-continuation.js';\nimport type {\n CodeModeApprovalInterrupt,\n CodeModeApprovalResponse,\n CodeModeContinuationSecurityOptions,\n CodeModeOptions,\n CodeModeToolExecutionOptions,\n CodeModeToolSet,\n} from './types.js';\n\nexport function isCodeModeApprovalInterrupt(\n value: unknown,\n continuationSecurity: CodeModeContinuationSecurityOptions = {},\n): value is CodeModeApprovalInterrupt {\n return (\n isCodeModeInterrupt(value, continuationSecurity) &&\n value.payload.kind === CODE_MODE_TOOL_APPROVAL_KIND\n );\n}\n\nexport async function continueCodeModeApproval({\n interrupt,\n approvalResponse,\n tools,\n options = {},\n toolExecutionOptions,\n}: {\n interrupt: CodeModeApprovalInterrupt;\n approvalResponse: CodeModeApprovalResponse;\n tools: CodeModeToolSet;\n options?: CodeModeOptions;\n toolExecutionOptions?: Partial<CodeModeToolExecutionOptions>;\n}): Promise<unknown> {\n assertCodeModeApprovalResponse(approvalResponse);\n if (approvalResponse.approvalId !== interrupt.interruptId) {\n throw new CodeModeProtocolError(\n `Approval response ${approvalResponse.approvalId} does not match pending code-mode approval ${interrupt.interruptId}.`,\n );\n }\n\n return await continueCodeModeInterrupt({\n interrupt,\n resolution: {\n approved: approvalResponse.approved,\n ...(approvalResponse.reason !== undefined\n ? { reason: approvalResponse.reason }\n : {}),\n },\n tools,\n options: {\n ...options,\n approval: { ...options.approval, mode: 'interrupt' },\n },\n ...(toolExecutionOptions !== undefined ? { toolExecutionOptions } : {}),\n });\n}\n\nexport function toCodeModeApprovalMessages(\n interrupt: CodeModeApprovalInterrupt,\n): ModelMessage[] {\n return [\n {\n role: 'assistant',\n content: [\n {\n type: 'tool-call',\n toolCallId: interrupt.toolCallId,\n toolName: interrupt.toolName,\n input: interrupt.input,\n },\n {\n type: 'tool-approval-request',\n approvalId: interrupt.interruptId,\n toolCallId: interrupt.toolCallId,\n },\n ],\n },\n ];\n}\n\nexport function getCodeModeApprovalResponse(\n messages: ModelMessage[],\n interrupt: CodeModeApprovalInterrupt,\n): CodeModeApprovalResponse | undefined {\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index];\n if (message?.role !== 'tool') {\n continue;\n }\n for (const part of message.content) {\n if (\n part.type === 'tool-approval-response' &&\n part.approvalId === interrupt.interruptId &&\n typeof part.approved === 'boolean' &&\n (part.reason === undefined || typeof part.reason === 'string')\n ) {\n return {\n approvalId: part.approvalId,\n approved: part.approved,\n ...(part.reason !== undefined ? { reason: part.reason } : {}),\n };\n }\n }\n }\n}\n"],"mappings":";;;;AAmBA,SAAgB,4BACd,OACA,uBAA4D,CAAC,GACzB;CACpC,OACE,oBAAoB,OAAO,oBAAoB,KAC/C,MAAM,QAAQ,SAAA;AAElB;AAEA,eAAsB,yBAAyB,EAC7C,WACA,kBACA,OACA,UAAU,CAAC,GACX,wBAOmB;CACnB,+BAA+B,gBAAgB;CAC/C,IAAI,iBAAiB,eAAe,UAAU,aAC5C,MAAM,IAAI,sBACR,qBAAqB,iBAAiB,WAAW,6CAA6C,UAAU,YAAY,EACtH;CAGF,OAAO,MAAM,0BAA0B;EACrC;EACA,YAAY;GACV,UAAU,iBAAiB;GAC3B,GAAI,iBAAiB,WAAW,KAAA,IAC5B,EAAE,QAAQ,iBAAiB,OAAO,IAClC,CAAC;EACP;EACA;EACA,SAAS;GACP,GAAG;GACH,UAAU;IAAE,GAAG,QAAQ;IAAU,MAAM;GAAY;EACrD;EACA,GAAI,yBAAyB,KAAA,IAAY,EAAE,qBAAqB,IAAI,CAAC;CACvE,CAAC;AACH;AAEA,SAAgB,2BACd,WACgB;CAChB,OAAO,CACL;EACE,MAAM;EACN,SAAS,CACP;GACE,MAAM;GACN,YAAY,UAAU;GACtB,UAAU,UAAU;GACpB,OAAO,UAAU;EACnB,GACA;GACE,MAAM;GACN,YAAY,UAAU;GACtB,YAAY,UAAU;EACxB,CACF;CACF,CACF;AACF;AAEA,SAAgB,4BACd,UACA,WACsC;CACtC,KAAK,IAAI,QAAQ,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS;EACzD,MAAM,UAAU,SAAS;EACzB,IAAI,SAAS,SAAS,QACpB;EAEF,KAAK,MAAM,QAAQ,QAAQ,SACzB,IACE,KAAK,SAAS,4BACd,KAAK,eAAe,UAAU,eAC9B,OAAO,KAAK,aAAa,cACxB,KAAK,WAAW,KAAA,KAAa,OAAO,KAAK,WAAW,WAErD,OAAO;GACL,YAAY,KAAK;GACjB,UAAU,KAAK;GACf,GAAI,KAAK,WAAW,KAAA,IAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;EAC7D;CAGN;AACF"}
|
package/dist/approval.js
CHANGED
|
@@ -1,32 +1,21 @@
|
|
|
1
1
|
import { CodeModeProtocolError } from "./errors.js";
|
|
2
|
+
//#region src/approval.ts
|
|
2
3
|
const CODE_MODE_TOOL_APPROVAL_KIND = "ai-sdk-code-mode/tool-approval";
|
|
3
4
|
function isCodeModeApprovalInterruptPayload(payload) {
|
|
4
|
-
|
|
5
|
+
return payload.kind === CODE_MODE_TOOL_APPROVAL_KIND;
|
|
5
6
|
}
|
|
6
7
|
function assertCodeModeApprovalResponse(value) {
|
|
7
|
-
|
|
8
|
-
throw new CodeModeProtocolError(
|
|
9
|
-
"Code mode approval response is malformed."
|
|
10
|
-
);
|
|
11
|
-
}
|
|
8
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || typeof value.approvalId !== "string" || typeof value.approved !== "boolean" || "reason" in value && value.reason !== void 0 && typeof value.reason !== "string") throw new CodeModeProtocolError("Code mode approval response is malformed.");
|
|
12
9
|
}
|
|
13
10
|
function normalizeApprovalResolution(resolution) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const { approved, reason } = resolution;
|
|
21
|
-
return {
|
|
22
|
-
approved,
|
|
23
|
-
...reason !== void 0 ? { reason } : {}
|
|
24
|
-
};
|
|
11
|
+
if (typeof resolution !== "object" || resolution === null || Array.isArray(resolution) || typeof resolution.approved !== "boolean" || "reason" in resolution && resolution.reason !== void 0 && typeof resolution.reason !== "string") throw new CodeModeProtocolError("Code mode approval resolution must be a boolean approval decision.", { resolution });
|
|
12
|
+
const { approved, reason } = resolution;
|
|
13
|
+
return {
|
|
14
|
+
approved,
|
|
15
|
+
...reason !== void 0 ? { reason } : {}
|
|
16
|
+
};
|
|
25
17
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
isCodeModeApprovalInterruptPayload,
|
|
30
|
-
normalizeApprovalResolution
|
|
31
|
-
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { CODE_MODE_TOOL_APPROVAL_KIND, assertCodeModeApprovalResponse, isCodeModeApprovalInterruptPayload, normalizeApprovalResolution };
|
|
20
|
+
|
|
32
21
|
//# sourceMappingURL=approval.js.map
|
package/dist/approval.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/approval.ts"],"sourcesContent":["import { CodeModeProtocolError } from './errors.js';\nimport type {\n CodeModeApprovalInterruptPayload,\n CodeModeApprovalResolution,\n CodeModeApprovalResponse,\n CodeModeInterruptPayload,\n} from './types.js';\n\nexport const CODE_MODE_TOOL_APPROVAL_KIND =\n 'ai-sdk-code-mode/tool-approval' as const;\n\nexport function isCodeModeApprovalInterruptPayload(\n payload: CodeModeInterruptPayload,\n): payload is CodeModeApprovalInterruptPayload {\n return payload.kind === CODE_MODE_TOOL_APPROVAL_KIND;\n}\n\nexport function assertCodeModeApprovalResponse(\n value: unknown,\n): asserts value is CodeModeApprovalResponse {\n if (\n typeof value !== 'object' ||\n value === null ||\n Array.isArray(value) ||\n typeof (value as { approvalId?: unknown }).approvalId !== 'string' ||\n typeof (value as { approved?: unknown }).approved !== 'boolean' ||\n ('reason' in value &&\n (value as { reason?: unknown }).reason !== undefined &&\n typeof (value as { reason?: unknown }).reason !== 'string')\n ) {\n throw new CodeModeProtocolError(\n 'Code mode approval response is malformed.',\n );\n }\n}\n\nexport function normalizeApprovalResolution(\n resolution: unknown,\n): CodeModeApprovalResolution {\n if (\n typeof resolution !== 'object' ||\n resolution === null ||\n Array.isArray(resolution) ||\n typeof (resolution as { approved?: unknown }).approved !== 'boolean' ||\n ('reason' in resolution &&\n (resolution as { reason?: unknown }).reason !== undefined &&\n typeof (resolution as { reason?: unknown }).reason !== 'string')\n ) {\n throw new CodeModeProtocolError(\n 'Code mode approval resolution must be a boolean approval decision.',\n { resolution },\n );\n }\n\n const { approved, reason } = resolution as CodeModeApprovalResolution;\n return {\n approved,\n ...(reason !== undefined ? { reason } : {}),\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"approval.js","names":[],"sources":["../src/approval.ts"],"sourcesContent":["import { CodeModeProtocolError } from './errors.js';\nimport type {\n CodeModeApprovalInterruptPayload,\n CodeModeApprovalResolution,\n CodeModeApprovalResponse,\n CodeModeInterruptPayload,\n} from './types.js';\n\nexport const CODE_MODE_TOOL_APPROVAL_KIND =\n 'ai-sdk-code-mode/tool-approval' as const;\n\nexport function isCodeModeApprovalInterruptPayload(\n payload: CodeModeInterruptPayload,\n): payload is CodeModeApprovalInterruptPayload {\n return payload.kind === CODE_MODE_TOOL_APPROVAL_KIND;\n}\n\nexport function assertCodeModeApprovalResponse(\n value: unknown,\n): asserts value is CodeModeApprovalResponse {\n if (\n typeof value !== 'object' ||\n value === null ||\n Array.isArray(value) ||\n typeof (value as { approvalId?: unknown }).approvalId !== 'string' ||\n typeof (value as { approved?: unknown }).approved !== 'boolean' ||\n ('reason' in value &&\n (value as { reason?: unknown }).reason !== undefined &&\n typeof (value as { reason?: unknown }).reason !== 'string')\n ) {\n throw new CodeModeProtocolError(\n 'Code mode approval response is malformed.',\n );\n }\n}\n\nexport function normalizeApprovalResolution(\n resolution: unknown,\n): CodeModeApprovalResolution {\n if (\n typeof resolution !== 'object' ||\n resolution === null ||\n Array.isArray(resolution) ||\n typeof (resolution as { approved?: unknown }).approved !== 'boolean' ||\n ('reason' in resolution &&\n (resolution as { reason?: unknown }).reason !== undefined &&\n typeof (resolution as { reason?: unknown }).reason !== 'string')\n ) {\n throw new CodeModeProtocolError(\n 'Code mode approval resolution must be a boolean approval decision.',\n { resolution },\n );\n }\n\n const { approved, reason } = resolution as CodeModeApprovalResolution;\n return {\n approved,\n ...(reason !== undefined ? { reason } : {}),\n };\n}\n"],"mappings":";;AAQA,MAAa,+BACX;AAEF,SAAgB,mCACd,SAC6C;CAC7C,OAAO,QAAQ,SAAS;AAC1B;AAEA,SAAgB,+BACd,OAC2C;CAC3C,IACE,OAAO,UAAU,YACjB,UAAU,QACV,MAAM,QAAQ,KAAK,KACnB,OAAQ,MAAmC,eAAe,YAC1D,OAAQ,MAAiC,aAAa,aACrD,YAAY,SACV,MAA+B,WAAW,KAAA,KAC3C,OAAQ,MAA+B,WAAW,UAEpD,MAAM,IAAI,sBACR,2CACF;AAEJ;AAEA,SAAgB,4BACd,YAC4B;CAC5B,IACE,OAAO,eAAe,YACtB,eAAe,QACf,MAAM,QAAQ,UAAU,KACxB,OAAQ,WAAsC,aAAa,aAC1D,YAAY,cACV,WAAoC,WAAW,KAAA,KAChD,OAAQ,WAAoC,WAAW,UAEzD,MAAM,IAAI,sBACR,sEACA,EAAE,WAAW,CACf;CAGF,MAAM,EAAE,UAAU,WAAW;CAC7B,OAAO;EACL;EACA,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;CAC3C;AACF"}
|
package/dist/code-mode-tool.js
CHANGED
|
@@ -1,59 +1,47 @@
|
|
|
1
|
-
import {
|
|
2
|
-
experimental_toolCaller,
|
|
3
|
-
jsonSchema,
|
|
4
|
-
tool
|
|
5
|
-
} from "ai";
|
|
6
1
|
import { runCodeMode } from "./run-code-mode.js";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
import { buildCodeModeToolCatalogMessage, buildCodeModeToolDescription } from "./tool-prompt.js";
|
|
3
|
+
import { experimental_toolCaller, jsonSchema, tool } from "ai";
|
|
4
|
+
//#region src/code-mode-tool.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates an AI SDK tool that executes code-mode TypeScript in an isolated
|
|
7
|
+
* sandbox.
|
|
8
|
+
*/
|
|
11
9
|
function createCodeModeTool(tools, options = {}) {
|
|
12
|
-
|
|
10
|
+
return createCodeModeToolWithDiscovery(tools, options, "description");
|
|
13
11
|
}
|
|
14
12
|
function createCodeModeToolWithDiscovery(tools, options, toolDiscovery) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
})
|
|
34
|
-
});
|
|
13
|
+
return tool({
|
|
14
|
+
description: buildCodeModeToolDescription(tools, toolDiscovery),
|
|
15
|
+
inputSchema: jsonSchema({
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: { js: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "Code-mode TypeScript source to execute. The code-mode context lists the available global `tools` API, input types, and call examples."
|
|
20
|
+
} },
|
|
21
|
+
required: ["js"],
|
|
22
|
+
additionalProperties: false
|
|
23
|
+
}),
|
|
24
|
+
execute: async (input, executionOptions) => await runCodeMode({
|
|
25
|
+
js: input.js,
|
|
26
|
+
tools,
|
|
27
|
+
toolExecutionOptions: executionOptions,
|
|
28
|
+
options
|
|
29
|
+
})
|
|
30
|
+
});
|
|
35
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Creates a code-mode caller whose host tools are bound by the surrounding
|
|
34
|
+
* AI SDK generation call.
|
|
35
|
+
*/
|
|
36
36
|
function codeModeTool(options = {}) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
tools,
|
|
44
|
-
codeModeOptions,
|
|
45
|
-
toolDiscovery
|
|
46
|
-
),
|
|
47
|
-
...toolDiscovery === "conversation" ? {
|
|
48
|
-
prepareModelMessage: (tools) => buildCodeModeToolCatalogMessage(
|
|
49
|
-
tools
|
|
50
|
-
)
|
|
51
|
-
} : {}
|
|
52
|
-
}
|
|
53
|
-
);
|
|
37
|
+
const { toolDiscovery = "description", ...codeModeOptions } = options;
|
|
38
|
+
return experimental_toolCaller(createCodeModeToolWithDiscovery({}, codeModeOptions, toolDiscovery), {
|
|
39
|
+
type: "local",
|
|
40
|
+
bind: (tools) => createCodeModeToolWithDiscovery(tools, codeModeOptions, toolDiscovery),
|
|
41
|
+
...toolDiscovery === "conversation" ? { prepareModelMessage: (tools) => buildCodeModeToolCatalogMessage(tools) } : {}
|
|
42
|
+
});
|
|
54
43
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
};
|
|
44
|
+
//#endregion
|
|
45
|
+
export { codeModeTool, createCodeModeTool };
|
|
46
|
+
|
|
59
47
|
//# sourceMappingURL=code-mode-tool.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/code-mode-tool.ts"],"sourcesContent":["import {\n experimental_toolCaller,\n jsonSchema,\n tool,\n type Experimental_ToolCallerTool,\n} from 'ai';\nimport { runCodeMode } from './run-code-mode.js';\nimport {\n buildCodeModeToolCatalogMessage,\n buildCodeModeToolDescription,\n} from './tool-prompt.js';\nimport type {\n CodeModeOptions,\n CodeModeTool,\n CodeModeToolInput,\n CodeModeToolOptions,\n CodeModeToolSet,\n} from './types.js';\n\n/**\n * Creates an AI SDK tool that executes code-mode TypeScript in an isolated\n * sandbox.\n */\nexport function createCodeModeTool(\n tools: CodeModeToolSet,\n options: CodeModeOptions = {},\n): CodeModeTool {\n return createCodeModeToolWithDiscovery(tools, options, 'description');\n}\n\nfunction createCodeModeToolWithDiscovery(\n tools: CodeModeToolSet,\n options: CodeModeOptions,\n toolDiscovery: 'description' | 'conversation',\n): CodeModeTool {\n return tool<CodeModeToolInput, unknown, Record<string, unknown>>({\n description: buildCodeModeToolDescription(tools, toolDiscovery),\n inputSchema: jsonSchema<CodeModeToolInput>({\n type: 'object',\n properties: {\n js: {\n type: 'string',\n description:\n 'Code-mode TypeScript source to execute. The code-mode context lists the available global `tools` API, input types, and call examples.',\n },\n },\n required: ['js'],\n additionalProperties: false,\n }),\n execute: async (input, executionOptions) =>\n await runCodeMode({\n js: input.js,\n tools,\n toolExecutionOptions: executionOptions,\n options,\n }),\n }) as CodeModeTool;\n}\n\n/**\n * Creates a code-mode caller whose host tools are bound by the surrounding\n * AI SDK generation call.\n */\nexport function codeModeTool(\n options: CodeModeToolOptions = {},\n): Experimental_ToolCallerTool<CodeModeTool> {\n const { toolDiscovery = 'description', ...codeModeOptions } = options;\n\n return experimental_toolCaller(\n createCodeModeToolWithDiscovery({}, codeModeOptions, toolDiscovery),\n {\n type: 'local',\n bind: tools =>\n createCodeModeToolWithDiscovery(\n tools as unknown as CodeModeToolSet,\n codeModeOptions,\n toolDiscovery,\n ),\n ...(toolDiscovery === 'conversation'\n ? {\n prepareModelMessage: tools =>\n buildCodeModeToolCatalogMessage(\n tools as unknown as CodeModeToolSet,\n ),\n }\n : {}),\n },\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"code-mode-tool.js","names":[],"sources":["../src/code-mode-tool.ts"],"sourcesContent":["import {\n experimental_toolCaller,\n jsonSchema,\n tool,\n type Experimental_ToolCallerTool,\n} from 'ai';\nimport { runCodeMode } from './run-code-mode.js';\nimport {\n buildCodeModeToolCatalogMessage,\n buildCodeModeToolDescription,\n} from './tool-prompt.js';\nimport type {\n CodeModeOptions,\n CodeModeTool,\n CodeModeToolInput,\n CodeModeToolOptions,\n CodeModeToolSet,\n} from './types.js';\n\n/**\n * Creates an AI SDK tool that executes code-mode TypeScript in an isolated\n * sandbox.\n */\nexport function createCodeModeTool(\n tools: CodeModeToolSet,\n options: CodeModeOptions = {},\n): CodeModeTool {\n return createCodeModeToolWithDiscovery(tools, options, 'description');\n}\n\nfunction createCodeModeToolWithDiscovery(\n tools: CodeModeToolSet,\n options: CodeModeOptions,\n toolDiscovery: 'description' | 'conversation',\n): CodeModeTool {\n return tool<CodeModeToolInput, unknown, Record<string, unknown>>({\n description: buildCodeModeToolDescription(tools, toolDiscovery),\n inputSchema: jsonSchema<CodeModeToolInput>({\n type: 'object',\n properties: {\n js: {\n type: 'string',\n description:\n 'Code-mode TypeScript source to execute. The code-mode context lists the available global `tools` API, input types, and call examples.',\n },\n },\n required: ['js'],\n additionalProperties: false,\n }),\n execute: async (input, executionOptions) =>\n await runCodeMode({\n js: input.js,\n tools,\n toolExecutionOptions: executionOptions,\n options,\n }),\n }) as CodeModeTool;\n}\n\n/**\n * Creates a code-mode caller whose host tools are bound by the surrounding\n * AI SDK generation call.\n */\nexport function codeModeTool(\n options: CodeModeToolOptions = {},\n): Experimental_ToolCallerTool<CodeModeTool> {\n const { toolDiscovery = 'description', ...codeModeOptions } = options;\n\n return experimental_toolCaller(\n createCodeModeToolWithDiscovery({}, codeModeOptions, toolDiscovery),\n {\n type: 'local',\n bind: tools =>\n createCodeModeToolWithDiscovery(\n tools as unknown as CodeModeToolSet,\n codeModeOptions,\n toolDiscovery,\n ),\n ...(toolDiscovery === 'conversation'\n ? {\n prepareModelMessage: tools =>\n buildCodeModeToolCatalogMessage(\n tools as unknown as CodeModeToolSet,\n ),\n }\n : {}),\n },\n );\n}\n"],"mappings":";;;;;;;;AAuBA,SAAgB,mBACd,OACA,UAA2B,CAAC,GACd;CACd,OAAO,gCAAgC,OAAO,SAAS,aAAa;AACtE;AAEA,SAAS,gCACP,OACA,SACA,eACc;CACd,OAAO,KAA0D;EAC/D,aAAa,6BAA6B,OAAO,aAAa;EAC9D,aAAa,WAA8B;GACzC,MAAM;GACN,YAAY,EACV,IAAI;IACF,MAAM;IACN,aACE;GACJ,EACF;GACA,UAAU,CAAC,IAAI;GACf,sBAAsB;EACxB,CAAC;EACD,SAAS,OAAO,OAAO,qBACrB,MAAM,YAAY;GAChB,IAAI,MAAM;GACV;GACA,sBAAsB;GACtB;EACF,CAAC;CACL,CAAC;AACH;;;;;AAMA,SAAgB,aACd,UAA+B,CAAC,GACW;CAC3C,MAAM,EAAE,gBAAgB,eAAe,GAAG,oBAAoB;CAE9D,OAAO,wBACL,gCAAgC,CAAC,GAAG,iBAAiB,aAAa,GAClE;EACE,MAAM;EACN,OAAM,UACJ,gCACE,OACA,iBACA,aACF;EACF,GAAI,kBAAkB,iBAClB,EACE,sBAAqB,UACnB,gCACE,KACF,EACJ,IACA,CAAC;CACP,CACF;AACF"}
|
|
@@ -1,130 +1,99 @@
|
|
|
1
|
-
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
1
|
import { CodeModeProtocolError } from "./errors.js";
|
|
2
|
+
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
3
|
+
//#region src/continuation-capability.ts
|
|
3
4
|
const SIGNATURE_ALGORITHM = "HMAC-SHA256";
|
|
4
|
-
const DEFAULT_MAX_AGE_MS =
|
|
5
|
+
const DEFAULT_MAX_AGE_MS = 36e5;
|
|
5
6
|
let defaultSigningKey = randomBytes(32);
|
|
6
7
|
let defaultMaxAgeMs = DEFAULT_MAX_AGE_MS;
|
|
7
8
|
function setCodeModeContinuationSigningKey(key, options = {}) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const resolved = resolveCodeModeContinuationSecurity({
|
|
10
|
+
signingKey: key ?? randomBytes(32),
|
|
11
|
+
maxAgeMs: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS
|
|
12
|
+
});
|
|
13
|
+
defaultSigningKey = resolved.signingKey;
|
|
14
|
+
defaultMaxAgeMs = resolved.maxAgeMs;
|
|
14
15
|
}
|
|
15
16
|
function resolveCodeModeContinuationSecurity(options = {}) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return { signingKey, maxAgeMs };
|
|
17
|
+
const signingKey = options.signingKey === void 0 ? Buffer.from(defaultSigningKey) : typeof options.signingKey === "string" ? Buffer.from(options.signingKey) : Buffer.from(options.signingKey);
|
|
18
|
+
if (signingKey.byteLength === 0) throw new TypeError("Continuation signing key must not be empty.");
|
|
19
|
+
const maxAgeMs = options.maxAgeMs ?? defaultMaxAgeMs;
|
|
20
|
+
if (!Number.isInteger(maxAgeMs) || !Number.isFinite(maxAgeMs) || maxAgeMs <= 0) throw new TypeError("Continuation maxAgeMs must be a positive integer.");
|
|
21
|
+
return {
|
|
22
|
+
signingKey,
|
|
23
|
+
maxAgeMs
|
|
24
|
+
};
|
|
25
25
|
}
|
|
26
26
|
function signCodeModeContinuation(continuation, security = resolveCodeModeContinuationSecurity()) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
27
|
+
const issuedAtMs = Date.now();
|
|
28
|
+
const auth = {
|
|
29
|
+
alg: SIGNATURE_ALGORITHM,
|
|
30
|
+
nonce: randomBytes(16).toString("hex"),
|
|
31
|
+
issuedAtMs,
|
|
32
|
+
expiresAtMs: issuedAtMs + security.maxAgeMs
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
...structuredClone(continuation),
|
|
36
|
+
auth: {
|
|
37
|
+
...auth,
|
|
38
|
+
signature: signContinuationPayload({
|
|
39
|
+
...continuation,
|
|
40
|
+
auth
|
|
41
|
+
}, security.signingKey)
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
44
|
}
|
|
45
45
|
function verifyCodeModeContinuation(continuation, security = {}) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
throw new CodeModeProtocolError(
|
|
61
|
-
"Code mode continuation was issued in the future.",
|
|
62
|
-
{ issuedAtMs: continuation.auth.issuedAtMs, now }
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
const { signingKey } = resolveCodeModeContinuationSecurity(security);
|
|
66
|
-
const expected = signContinuationPayload(
|
|
67
|
-
stripSignature(continuation),
|
|
68
|
-
signingKey
|
|
69
|
-
);
|
|
70
|
-
if (!constantTimeEqual(continuation.auth.signature, expected)) {
|
|
71
|
-
throw new CodeModeProtocolError(
|
|
72
|
-
"Code mode continuation signature is invalid."
|
|
73
|
-
);
|
|
74
|
-
}
|
|
46
|
+
if (typeof continuation !== "object" || continuation === null || continuation.version !== 2 || typeof continuation.js !== "string" || typeof continuation.outerToolCallId !== "string" || !Array.isArray(continuation.toolNames) || !continuation.toolNames.every((name) => typeof name === "string") || typeof continuation.token !== "string" || continuation.token.length === 0 || !Array.isArray(continuation.pendingInterruptions) || continuation.pendingInterruptions.length === 0 || !Array.isArray(continuation.resolutions)) throw new CodeModeProtocolError("Code mode continuation envelope is malformed.");
|
|
47
|
+
assertAuthShape(continuation.auth);
|
|
48
|
+
const now = Date.now();
|
|
49
|
+
if (continuation.auth.expiresAtMs < now) throw new CodeModeProtocolError("Code mode continuation has expired.", {
|
|
50
|
+
expiresAtMs: continuation.auth.expiresAtMs,
|
|
51
|
+
now
|
|
52
|
+
});
|
|
53
|
+
if (continuation.auth.issuedAtMs > now + 6e4) throw new CodeModeProtocolError("Code mode continuation was issued in the future.", {
|
|
54
|
+
issuedAtMs: continuation.auth.issuedAtMs,
|
|
55
|
+
now
|
|
56
|
+
});
|
|
57
|
+
const { signingKey } = resolveCodeModeContinuationSecurity(security);
|
|
58
|
+
const expected = signContinuationPayload(stripSignature(continuation), signingKey);
|
|
59
|
+
if (!constantTimeEqual(continuation.auth.signature, expected)) throw new CodeModeProtocolError("Code mode continuation signature is invalid.");
|
|
75
60
|
}
|
|
76
61
|
function hasValidCodeModeContinuationCapability(value, security = {}) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
62
|
+
try {
|
|
63
|
+
verifyCodeModeContinuation(value, security);
|
|
64
|
+
return true;
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
83
68
|
}
|
|
84
69
|
function signContinuationPayload(continuation, signingKey) {
|
|
85
|
-
|
|
70
|
+
return createHmac("sha256", signingKey).update(canonicalJson(continuation)).digest("base64url");
|
|
86
71
|
}
|
|
87
72
|
function stripSignature(continuation) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
73
|
+
const { auth, ...rest } = continuation;
|
|
74
|
+
const { signature: _signature, ...unsignedAuth } = auth;
|
|
75
|
+
return {
|
|
76
|
+
...rest,
|
|
77
|
+
auth: unsignedAuth
|
|
78
|
+
};
|
|
91
79
|
}
|
|
92
80
|
function assertAuthShape(auth) {
|
|
93
|
-
|
|
94
|
-
throw new CodeModeProtocolError(
|
|
95
|
-
"Code mode continuation is missing valid signed auth metadata."
|
|
96
|
-
);
|
|
97
|
-
}
|
|
81
|
+
if (typeof auth !== "object" || auth === null || Array.isArray(auth) || auth.alg !== SIGNATURE_ALGORITHM || typeof auth.nonce !== "string" || !/^[0-9a-f]{32}$/i.test(auth.nonce) || typeof auth.issuedAtMs !== "number" || !Number.isInteger(auth.issuedAtMs) || typeof auth.expiresAtMs !== "number" || !Number.isInteger(auth.expiresAtMs) || auth.expiresAtMs <= auth.issuedAtMs || typeof auth.signature !== "string" || auth.signature.length === 0) throw new CodeModeProtocolError("Code mode continuation is missing valid signed auth metadata.");
|
|
98
82
|
}
|
|
99
83
|
function constantTimeEqual(left, right) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
84
|
+
const leftBytes = Buffer.from(left);
|
|
85
|
+
const rightBytes = Buffer.from(right);
|
|
86
|
+
return leftBytes.byteLength === rightBytes.byteLength && timingSafeEqual(leftBytes, rightBytes);
|
|
103
87
|
}
|
|
104
88
|
function canonicalJson(value) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
112
|
-
return JSON.stringify(value);
|
|
113
|
-
}
|
|
114
|
-
if (Array.isArray(value)) {
|
|
115
|
-
return `[${value.map(canonicalJson).join(",")}]`;
|
|
116
|
-
}
|
|
117
|
-
if (typeof value === "object") {
|
|
118
|
-
const entries = Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right));
|
|
119
|
-
return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
|
|
120
|
-
}
|
|
121
|
-
throw new TypeError("Continuation contains a non-JSON-serializable value.");
|
|
89
|
+
if (value === null) return "null";
|
|
90
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
91
|
+
if (typeof value === "number" || typeof value === "boolean") return JSON.stringify(value);
|
|
92
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
93
|
+
if (typeof value === "object") return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
|
|
94
|
+
throw new TypeError("Continuation contains a non-JSON-serializable value.");
|
|
122
95
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
setCodeModeContinuationSigningKey,
|
|
127
|
-
signCodeModeContinuation,
|
|
128
|
-
verifyCodeModeContinuation
|
|
129
|
-
};
|
|
96
|
+
//#endregion
|
|
97
|
+
export { hasValidCodeModeContinuationCapability, resolveCodeModeContinuationSecurity, setCodeModeContinuationSigningKey, signCodeModeContinuation, verifyCodeModeContinuation };
|
|
98
|
+
|
|
130
99
|
//# sourceMappingURL=continuation-capability.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/continuation-capability.ts"],"sourcesContent":["import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';\nimport { CodeModeProtocolError } from './errors.js';\nimport type {\n CodeModeContinuation,\n CodeModeContinuationAuth,\n CodeModeContinuationSecurityOptions,\n UnsignedCodeModeContinuation,\n} from './types.js';\n\nconst SIGNATURE_ALGORITHM = 'HMAC-SHA256';\nconst DEFAULT_MAX_AGE_MS = 60 * 60 * 1000;\n\nlet defaultSigningKey: Uint8Array = randomBytes(32);\nlet defaultMaxAgeMs = DEFAULT_MAX_AGE_MS;\n\nexport interface ResolvedCodeModeContinuationSecurity {\n signingKey: Buffer;\n maxAgeMs: number;\n}\n\nexport function setCodeModeContinuationSigningKey(\n key?: string | Uint8Array,\n options: { maxAgeMs?: number } = {},\n): void {\n const resolved = resolveCodeModeContinuationSecurity({\n signingKey: key ?? randomBytes(32),\n maxAgeMs: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS,\n });\n defaultSigningKey = resolved.signingKey;\n defaultMaxAgeMs = resolved.maxAgeMs;\n}\n\nexport function resolveCodeModeContinuationSecurity(\n options: CodeModeContinuationSecurityOptions = {},\n): ResolvedCodeModeContinuationSecurity {\n const signingKey =\n options.signingKey === undefined\n ? Buffer.from(defaultSigningKey)\n : typeof options.signingKey === 'string'\n ? Buffer.from(options.signingKey)\n : Buffer.from(options.signingKey);\n if (signingKey.byteLength === 0) {\n throw new TypeError('Continuation signing key must not be empty.');\n }\n\n const maxAgeMs = options.maxAgeMs ?? defaultMaxAgeMs;\n if (\n !Number.isInteger(maxAgeMs) ||\n !Number.isFinite(maxAgeMs) ||\n maxAgeMs <= 0\n ) {\n throw new TypeError('Continuation maxAgeMs must be a positive integer.');\n }\n\n return { signingKey, maxAgeMs };\n}\n\nexport function signCodeModeContinuation(\n continuation: UnsignedCodeModeContinuation,\n security = resolveCodeModeContinuationSecurity(),\n): CodeModeContinuation {\n const issuedAtMs = Date.now();\n const auth: Omit<CodeModeContinuationAuth, 'signature'> = {\n alg: SIGNATURE_ALGORITHM,\n nonce: randomBytes(16).toString('hex'),\n issuedAtMs,\n expiresAtMs: issuedAtMs + security.maxAgeMs,\n };\n return {\n ...structuredClone(continuation),\n auth: {\n ...auth,\n signature: signContinuationPayload(\n { ...continuation, auth },\n security.signingKey,\n ),\n },\n };\n}\n\nexport function verifyCodeModeContinuation(\n continuation: CodeModeContinuation,\n security: CodeModeContinuationSecurityOptions = {},\n): void {\n if (\n typeof continuation !== 'object' ||\n continuation === null ||\n continuation.version !== 2 ||\n typeof continuation.js !== 'string' ||\n typeof continuation.outerToolCallId !== 'string' ||\n !Array.isArray(continuation.toolNames) ||\n !continuation.toolNames.every(name => typeof name === 'string') ||\n typeof continuation.token !== 'string' ||\n continuation.token.length === 0 ||\n !Array.isArray(continuation.pendingInterruptions) ||\n continuation.pendingInterruptions.length === 0 ||\n !Array.isArray(continuation.resolutions)\n ) {\n throw new CodeModeProtocolError(\n 'Code mode continuation envelope is malformed.',\n );\n }\n assertAuthShape(continuation.auth);\n const now = Date.now();\n if (continuation.auth.expiresAtMs < now) {\n throw new CodeModeProtocolError('Code mode continuation has expired.', {\n expiresAtMs: continuation.auth.expiresAtMs,\n now,\n });\n }\n if (continuation.auth.issuedAtMs > now + 60_000) {\n throw new CodeModeProtocolError(\n 'Code mode continuation was issued in the future.',\n { issuedAtMs: continuation.auth.issuedAtMs, now },\n );\n }\n\n const { signingKey } = resolveCodeModeContinuationSecurity(security);\n const expected = signContinuationPayload(\n stripSignature(continuation),\n signingKey,\n );\n if (!constantTimeEqual(continuation.auth.signature, expected)) {\n throw new CodeModeProtocolError(\n 'Code mode continuation signature is invalid.',\n );\n }\n}\n\nexport function hasValidCodeModeContinuationCapability(\n value: unknown,\n security: CodeModeContinuationSecurityOptions = {},\n): value is CodeModeContinuation {\n try {\n verifyCodeModeContinuation(value as CodeModeContinuation, security);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction signContinuationPayload(\n continuation: UnsignedCodeModeContinuation & {\n auth: Omit<CodeModeContinuationAuth, 'signature'>;\n },\n signingKey: Uint8Array,\n): string {\n return createHmac('sha256', signingKey)\n .update(canonicalJson(continuation))\n .digest('base64url');\n}\n\nfunction stripSignature(\n continuation: CodeModeContinuation,\n): UnsignedCodeModeContinuation & {\n auth: Omit<CodeModeContinuationAuth, 'signature'>;\n} {\n const { auth, ...rest } = continuation;\n const { signature: _signature, ...unsignedAuth } = auth;\n return { ...rest, auth: unsignedAuth };\n}\n\nfunction assertAuthShape(\n auth: unknown,\n): asserts auth is CodeModeContinuationAuth {\n if (\n typeof auth !== 'object' ||\n auth === null ||\n Array.isArray(auth) ||\n (auth as { alg?: unknown }).alg !== SIGNATURE_ALGORITHM ||\n typeof (auth as { nonce?: unknown }).nonce !== 'string' ||\n !/^[0-9a-f]{32}$/i.test((auth as { nonce: string }).nonce) ||\n typeof (auth as { issuedAtMs?: unknown }).issuedAtMs !== 'number' ||\n !Number.isInteger((auth as { issuedAtMs: number }).issuedAtMs) ||\n typeof (auth as { expiresAtMs?: unknown }).expiresAtMs !== 'number' ||\n !Number.isInteger((auth as { expiresAtMs: number }).expiresAtMs) ||\n (auth as { expiresAtMs: number }).expiresAtMs <=\n (auth as { issuedAtMs: number }).issuedAtMs ||\n typeof (auth as { signature?: unknown }).signature !== 'string' ||\n (auth as { signature: string }).signature.length === 0\n ) {\n throw new CodeModeProtocolError(\n 'Code mode continuation is missing valid signed auth metadata.',\n );\n }\n}\n\nfunction constantTimeEqual(left: string, right: string): boolean {\n const leftBytes = Buffer.from(left);\n const rightBytes = Buffer.from(right);\n return (\n leftBytes.byteLength === rightBytes.byteLength &&\n timingSafeEqual(leftBytes, rightBytes)\n );\n}\n\nfunction canonicalJson(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) {\n return `[${value.map(canonicalJson).join(',')}]`;\n }\n if (typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, item]) => item !== undefined)\n .sort(([left], [right]) => left.localeCompare(right));\n return `{${entries\n .map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`)\n .join(',')}}`;\n }\n throw new TypeError('Continuation contains a non-JSON-serializable value.');\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"file":"continuation-capability.js","names":[],"sources":["../src/continuation-capability.ts"],"sourcesContent":["import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';\nimport { CodeModeProtocolError } from './errors.js';\nimport type {\n CodeModeContinuation,\n CodeModeContinuationAuth,\n CodeModeContinuationSecurityOptions,\n UnsignedCodeModeContinuation,\n} from './types.js';\n\nconst SIGNATURE_ALGORITHM = 'HMAC-SHA256';\nconst DEFAULT_MAX_AGE_MS = 60 * 60 * 1000;\n\nlet defaultSigningKey: Uint8Array = randomBytes(32);\nlet defaultMaxAgeMs = DEFAULT_MAX_AGE_MS;\n\nexport interface ResolvedCodeModeContinuationSecurity {\n signingKey: Buffer;\n maxAgeMs: number;\n}\n\nexport function setCodeModeContinuationSigningKey(\n key?: string | Uint8Array,\n options: { maxAgeMs?: number } = {},\n): void {\n const resolved = resolveCodeModeContinuationSecurity({\n signingKey: key ?? randomBytes(32),\n maxAgeMs: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS,\n });\n defaultSigningKey = resolved.signingKey;\n defaultMaxAgeMs = resolved.maxAgeMs;\n}\n\nexport function resolveCodeModeContinuationSecurity(\n options: CodeModeContinuationSecurityOptions = {},\n): ResolvedCodeModeContinuationSecurity {\n const signingKey =\n options.signingKey === undefined\n ? Buffer.from(defaultSigningKey)\n : typeof options.signingKey === 'string'\n ? Buffer.from(options.signingKey)\n : Buffer.from(options.signingKey);\n if (signingKey.byteLength === 0) {\n throw new TypeError('Continuation signing key must not be empty.');\n }\n\n const maxAgeMs = options.maxAgeMs ?? defaultMaxAgeMs;\n if (\n !Number.isInteger(maxAgeMs) ||\n !Number.isFinite(maxAgeMs) ||\n maxAgeMs <= 0\n ) {\n throw new TypeError('Continuation maxAgeMs must be a positive integer.');\n }\n\n return { signingKey, maxAgeMs };\n}\n\nexport function signCodeModeContinuation(\n continuation: UnsignedCodeModeContinuation,\n security = resolveCodeModeContinuationSecurity(),\n): CodeModeContinuation {\n const issuedAtMs = Date.now();\n const auth: Omit<CodeModeContinuationAuth, 'signature'> = {\n alg: SIGNATURE_ALGORITHM,\n nonce: randomBytes(16).toString('hex'),\n issuedAtMs,\n expiresAtMs: issuedAtMs + security.maxAgeMs,\n };\n return {\n ...structuredClone(continuation),\n auth: {\n ...auth,\n signature: signContinuationPayload(\n { ...continuation, auth },\n security.signingKey,\n ),\n },\n };\n}\n\nexport function verifyCodeModeContinuation(\n continuation: CodeModeContinuation,\n security: CodeModeContinuationSecurityOptions = {},\n): void {\n if (\n typeof continuation !== 'object' ||\n continuation === null ||\n continuation.version !== 2 ||\n typeof continuation.js !== 'string' ||\n typeof continuation.outerToolCallId !== 'string' ||\n !Array.isArray(continuation.toolNames) ||\n !continuation.toolNames.every(name => typeof name === 'string') ||\n typeof continuation.token !== 'string' ||\n continuation.token.length === 0 ||\n !Array.isArray(continuation.pendingInterruptions) ||\n continuation.pendingInterruptions.length === 0 ||\n !Array.isArray(continuation.resolutions)\n ) {\n throw new CodeModeProtocolError(\n 'Code mode continuation envelope is malformed.',\n );\n }\n assertAuthShape(continuation.auth);\n const now = Date.now();\n if (continuation.auth.expiresAtMs < now) {\n throw new CodeModeProtocolError('Code mode continuation has expired.', {\n expiresAtMs: continuation.auth.expiresAtMs,\n now,\n });\n }\n if (continuation.auth.issuedAtMs > now + 60_000) {\n throw new CodeModeProtocolError(\n 'Code mode continuation was issued in the future.',\n { issuedAtMs: continuation.auth.issuedAtMs, now },\n );\n }\n\n const { signingKey } = resolveCodeModeContinuationSecurity(security);\n const expected = signContinuationPayload(\n stripSignature(continuation),\n signingKey,\n );\n if (!constantTimeEqual(continuation.auth.signature, expected)) {\n throw new CodeModeProtocolError(\n 'Code mode continuation signature is invalid.',\n );\n }\n}\n\nexport function hasValidCodeModeContinuationCapability(\n value: unknown,\n security: CodeModeContinuationSecurityOptions = {},\n): value is CodeModeContinuation {\n try {\n verifyCodeModeContinuation(value as CodeModeContinuation, security);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction signContinuationPayload(\n continuation: UnsignedCodeModeContinuation & {\n auth: Omit<CodeModeContinuationAuth, 'signature'>;\n },\n signingKey: Uint8Array,\n): string {\n return createHmac('sha256', signingKey)\n .update(canonicalJson(continuation))\n .digest('base64url');\n}\n\nfunction stripSignature(\n continuation: CodeModeContinuation,\n): UnsignedCodeModeContinuation & {\n auth: Omit<CodeModeContinuationAuth, 'signature'>;\n} {\n const { auth, ...rest } = continuation;\n const { signature: _signature, ...unsignedAuth } = auth;\n return { ...rest, auth: unsignedAuth };\n}\n\nfunction assertAuthShape(\n auth: unknown,\n): asserts auth is CodeModeContinuationAuth {\n if (\n typeof auth !== 'object' ||\n auth === null ||\n Array.isArray(auth) ||\n (auth as { alg?: unknown }).alg !== SIGNATURE_ALGORITHM ||\n typeof (auth as { nonce?: unknown }).nonce !== 'string' ||\n !/^[0-9a-f]{32}$/i.test((auth as { nonce: string }).nonce) ||\n typeof (auth as { issuedAtMs?: unknown }).issuedAtMs !== 'number' ||\n !Number.isInteger((auth as { issuedAtMs: number }).issuedAtMs) ||\n typeof (auth as { expiresAtMs?: unknown }).expiresAtMs !== 'number' ||\n !Number.isInteger((auth as { expiresAtMs: number }).expiresAtMs) ||\n (auth as { expiresAtMs: number }).expiresAtMs <=\n (auth as { issuedAtMs: number }).issuedAtMs ||\n typeof (auth as { signature?: unknown }).signature !== 'string' ||\n (auth as { signature: string }).signature.length === 0\n ) {\n throw new CodeModeProtocolError(\n 'Code mode continuation is missing valid signed auth metadata.',\n );\n }\n}\n\nfunction constantTimeEqual(left: string, right: string): boolean {\n const leftBytes = Buffer.from(left);\n const rightBytes = Buffer.from(right);\n return (\n leftBytes.byteLength === rightBytes.byteLength &&\n timingSafeEqual(leftBytes, rightBytes)\n );\n}\n\nfunction canonicalJson(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) {\n return `[${value.map(canonicalJson).join(',')}]`;\n }\n if (typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, item]) => item !== undefined)\n .sort(([left], [right]) => left.localeCompare(right));\n return `{${entries\n .map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`)\n .join(',')}}`;\n }\n throw new TypeError('Continuation contains a non-JSON-serializable value.');\n}\n"],"mappings":"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"}
|
package/dist/direct-tool-call.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
//#region src/direct-tool-call.ts
|
|
2
|
+
/**
|
|
3
|
+
* Allows the model to call a tool directly.
|
|
4
|
+
*
|
|
5
|
+
* Use a string instead of a Symbol to allow for serializability.
|
|
6
|
+
*/
|
|
1
7
|
const DIRECT_TOOL_CALL = "AI_SDK_DIRECT_TOOL_CALL";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
8
|
+
//#endregion
|
|
9
|
+
export { DIRECT_TOOL_CALL };
|
|
10
|
+
|
|
5
11
|
//# sourceMappingURL=direct-tool-call.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/direct-tool-call.ts"],"sourcesContent":["/**\n * Allows the model to call a tool directly.\n *\n * Use a string instead of a Symbol to allow for serializability.\n */\nexport const DIRECT_TOOL_CALL = 'AI_SDK_DIRECT_TOOL_CALL';\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"direct-tool-call.js","names":[],"sources":["../src/direct-tool-call.ts"],"sourcesContent":["/**\n * Allows the model to call a tool directly.\n *\n * Use a string instead of a Symbol to allow for serializability.\n */\nexport const DIRECT_TOOL_CALL = 'AI_SDK_DIRECT_TOOL_CALL';\n"],"mappings":";;;;;;AAKA,MAAa,mBAAmB"}
|