@standardagents/cli 0.14.0 → 0.15.0
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/index.js +152 -30
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -141,14 +141,19 @@ interface ThreadState {
|
|
|
141
141
|
loadAgent(name): Promise<AgentConfig>; // Load agent definition
|
|
142
142
|
env(propertyName): Promise<string>; // Resolve env value for this thread
|
|
143
143
|
setEnv(propertyName, value): Promise<void>; // Set thread env + propagate to active descendants
|
|
144
|
+
getValue<T = unknown>(key: string): Promise<T | null>; // Read durable per-thread JSON value
|
|
145
|
+
setValue(key: string, value: unknown): Promise<void>; // Write durable value; null/undefined deletes
|
|
144
146
|
notifyParent(content): Promise<void>; // Explicitly queue a silent message to the parent
|
|
145
147
|
setStatus(status): Promise<void>; // Update this child in the parent registry
|
|
146
148
|
getChildThread(referenceId): Promise<ThreadState | null>; // Resolve child thread
|
|
147
149
|
getParentThread(): Promise<ThreadState | null>; // Resolve parent thread
|
|
148
150
|
terminate(): Promise<void>; // Soft-terminate thread
|
|
151
|
+
runCode(source, options?): CodeExecution; // Run JS/TS in a fresh Dynamic Worker sandbox
|
|
149
152
|
}
|
|
150
153
|
\`\`\`
|
|
151
154
|
|
|
155
|
+
\`runCode\` has no implicit access to thread state, filesystem, network, timers, or host globals. Bridge only the exact capabilities needed through \`imports\` or \`globals\`; use \`modules\` for local relative ES modules; use \`execute\` to select the export and args to run. \`modules\` keys are graph-root relative paths; entry-source imports resolve from \`filename\` when supplied, including \`../\` parent paths that stay inside the supplied graph. TypeScript input is accepted by default and erased before evaluation. In thread endpoints, \`runCode\` is forwarded into the thread Durable Object; pass plain transferable options there and keep function-backed bridges in tools or in-thread execution contexts.
|
|
156
|
+
|
|
152
157
|
## Subagents
|
|
153
158
|
|
|
154
159
|
\`dual_ai\` agents can be used as subagents from prompt tool configs:
|
|
@@ -165,6 +170,8 @@ Access in tools:
|
|
|
165
170
|
export default defineTool('...', schema, async (state, args) => {
|
|
166
171
|
const threadId = state.threadId;
|
|
167
172
|
const { messages } = await state.getMessages();
|
|
173
|
+
const count = (await state.getValue<number>('invocation_count')) ?? 0;
|
|
174
|
+
await state.setValue('invocation_count', count + 1);
|
|
168
175
|
// ...
|
|
169
176
|
});
|
|
170
177
|
\`\`\`
|
|
@@ -236,6 +243,7 @@ Models define which LLM provider and model to use for prompts.
|
|
|
236
243
|
| \`outputPrice\` | \`number\` | No | Cost per 1M output tokens (USD) |
|
|
237
244
|
| \`cachedPrice\` | \`number\` | No | Cost per 1M cached input tokens |
|
|
238
245
|
| \`includedProviders\` | \`string[]\` | No | Provider prefixes for OpenRouter routing |
|
|
246
|
+
| \`providerTools\` | \`string[]\` | No | Provider-built-in tool names to make available for prompts using this model |
|
|
239
247
|
|
|
240
248
|
## Example
|
|
241
249
|
|
|
@@ -250,6 +258,19 @@ export default defineModel({
|
|
|
250
258
|
});
|
|
251
259
|
\`\`\`
|
|
252
260
|
|
|
261
|
+
## Provider Tools
|
|
262
|
+
|
|
263
|
+
Providers can expose built-in tools such as search, file search, code execution,
|
|
264
|
+
or provider-specific tools through their \`getTools()\` implementation. Enable the
|
|
265
|
+
provider tool names on the model with \`providerTools\`; prompts can then include
|
|
266
|
+
those tools like normal tool names. Provider tools execute on the upstream
|
|
267
|
+
provider, not in AgentBuilder, and successful calls are logged as provider tool
|
|
268
|
+
entries.
|
|
269
|
+
|
|
270
|
+
OpenRouter exposes \`web_search\`, \`web_fetch\`, \`datetime\`, and \`image_generation\`
|
|
271
|
+
as provider-executed server tools. Configure optional OpenRouter parameters with
|
|
272
|
+
\`providerOptions.serverTools\` on the model.
|
|
273
|
+
|
|
253
274
|
## Recommended Models (OpenRouter)
|
|
254
275
|
|
|
255
276
|
| Use Case | Model ID | Description |
|
|
@@ -372,6 +393,12 @@ export default definePrompt({
|
|
|
372
393
|
|
|
373
394
|
\`type: 'env'\` inserts a resolved thread variable value. Use this only for non-secret values that are safe to expose to the LLM.
|
|
374
395
|
|
|
396
|
+
The sandboxed coding prompt declares \`HTTP_HOST\` as a text variable. Its URL helper uses that value as the origin for files exposed from the thread \`public/\` directory and endpoints exposed from the thread \`api/\` directory. Public URLs should usually omit extensions; extensionless public paths resolve \`.html\`, then \`.js\`, then \`.ts\`, then matching \`index\` files in the same order. Browser pages should reference only public files, \`api/\` endpoints, or absolute external URLs, using relative asset URLs like \`./app\` and \`./api/todos\`; private \`src/\` files are not served directly. Public \`.ts\` files are transformed to browser JavaScript and are not server endpoints. Server-side endpoints live under the thread filesystem \`api/\` directory, and the \`api/\` directory name stays in the public URL: \`api/todo.ts\` is \`/api/threads/{threadId}/api/todo\`, while \`api/todo.ts\` is not \`/api/threads/{threadId}/todo\` or \`/api/threads/{threadId}/todos\`. Endpoint files default-export a function that accepts \`Request\` and returns \`Response\` or \`Promise<Response>\`. Endpoint code can import \`fetch\`, \`fs\`, and \`storage\`, and can import private helpers with relative paths such as \`../src/todo.ts\`. When the coding agent creates a site, page, or endpoint, it should call \`get_public_url\` with the created file path and use the returned URL.
|
|
397
|
+
|
|
398
|
+
Sandboxed code and \`api/\` endpoints can persist small JSON-serializable runtime data through \`import { storage } from "storage"\`. Use \`storage.get\`, \`storage.set\`, \`storage.delete\`, and \`storage.has\` with stable logical keys. Do not expose, mention, or depend on internal storage key prefixes.
|
|
399
|
+
|
|
400
|
+
The sandboxed coding prompt includes \`delete_file\` for removing files or empty directories from the thread filesystem. Use it to clean up obsolete implementation files, stale public assets, and abandoned endpoint routes after the replacement is working.
|
|
401
|
+
|
|
375
402
|
## Tool Configuration
|
|
376
403
|
|
|
377
404
|
Tools can be simple names or detailed configs:
|
|
@@ -389,6 +416,12 @@ tools: [
|
|
|
389
416
|
],
|
|
390
417
|
\`\`\`
|
|
391
418
|
|
|
419
|
+
Provider-built-in tools use the same \`tools\` list once the selected model enables
|
|
420
|
+
them with \`providerTools\`. AgentBuilder passes them to the provider and records
|
|
421
|
+
provider-reported calls in request logs; it does not execute those tools locally.
|
|
422
|
+
Generated prompt files may store these selections as \`provider:<toolName>\` to
|
|
423
|
+
distinguish provider tools from local tools with the same name.
|
|
424
|
+
|
|
392
425
|
### Subagent Tool Configuration
|
|
393
426
|
|
|
394
427
|
Use \`SubagentToolConfig\` when the tool is a \`dual_ai\` agent:
|
|
@@ -422,14 +455,14 @@ When prompt-configured resumable dual_ai subagents exist, the runtime auto-injec
|
|
|
422
455
|
- \`subagent_create\` for spawning new child instances
|
|
423
456
|
- \`subagent_message\` for messaging active resumable instances
|
|
424
457
|
|
|
425
|
-
\`subagent_create\`
|
|
426
|
-
|
|
458
|
+
\`subagent_create\` requires a non-empty \`name\` for human-friendly child thread labels.
|
|
459
|
+
AgentBuilder stores that argument as a \`name:<value>\` thread tag.
|
|
427
460
|
|
|
428
461
|
Set \`immediate: true\` to run a tool automatically when the prompt activates.
|
|
429
462
|
Use \`immediate: { nameEnv, descriptionEnv, scopedEnv }\` when you want safe per-instance bootstrap hints while keeping copied scoped env runtime-only.
|
|
430
463
|
Set \`optional: 'ENV_NAME'\` to enable a subagent branch only when env resolves to \`true\`, \`1\`, or \`yes\`.
|
|
431
464
|
Set \`resumable.parentCommunication: 'explicit'\` when the child should stay quiet until its own tools or hooks call \`state.notifyParent()\` or \`state.setStatus()\`.
|
|
432
|
-
If required scoped vars are missing, the runtime returns \`error_code: "subagent_env_required"\` with a temporary \`GET/POST /api/threads/:
|
|
465
|
+
If required scoped vars are missing, the runtime returns \`error_code: "subagent_env_required"\` with a temporary \`GET/POST /api/threads/:threadId/variables/:requestId\` endpoint in \`error_data.endpoint\`.
|
|
433
466
|
|
|
434
467
|
## Input Validation
|
|
435
468
|
|
|
@@ -710,6 +743,10 @@ export default defineTool({
|
|
|
710
743
|
});
|
|
711
744
|
\`\`\`
|
|
712
745
|
|
|
746
|
+
## Argument Schemas
|
|
747
|
+
|
|
748
|
+
Tool args must be a top-level \`z.object(...)\`. Prefer explicit, bounded schemas made from strings, numbers, booleans, nulls, literals, enums, arrays, objects, optionals, nullables, and defaults. Avoid provider-visible recursive or open-ended schemas such as \`z.unknown()\`, \`z.any()\`, and \`z.object({}).catchall(...)\`; strict tool providers can reject the generated JSON Schema. If a tool needs arbitrary JSON input, accept it as a JSON string and parse it inside \`execute\`.
|
|
749
|
+
|
|
713
750
|
## ToolResult Interface
|
|
714
751
|
|
|
715
752
|
| Property | Type | Description |
|
|
@@ -742,11 +779,29 @@ execute: async (state, args) => {
|
|
|
742
779
|
const apiKey = await state.env('GOOGLE_API_KEY');
|
|
743
780
|
await state.setEnv('LAST_TOOL_RUN_AT', new Date().toISOString());
|
|
744
781
|
|
|
782
|
+
// Durable per-thread JSON values
|
|
783
|
+
const runCount = (await state.getValue<number>('run_count')) ?? 0;
|
|
784
|
+
await state.setValue('run_count', runCount + 1);
|
|
785
|
+
|
|
786
|
+
// Sandboxed JS/TS execution with explicit bridge capabilities
|
|
787
|
+
const run = state.runCode('export async function main(path) { return await read(path) }', {
|
|
788
|
+
execute: { fn: 'main', args: ['/notes.txt'] },
|
|
789
|
+
globals: {
|
|
790
|
+
read: async (path: string) => {
|
|
791
|
+
const data = await state.readFile(path);
|
|
792
|
+
return data ? new TextDecoder().decode(data) : null;
|
|
793
|
+
},
|
|
794
|
+
},
|
|
795
|
+
});
|
|
796
|
+
const codeResult = await run;
|
|
797
|
+
|
|
745
798
|
// Parent state (for sub-prompts)
|
|
746
799
|
const root = state.rootState;
|
|
747
800
|
}
|
|
748
801
|
\`\`\`
|
|
749
802
|
|
|
803
|
+
Use \`state.runCode()\` instead of \`eval\` or \`new Function\` for model- or user-authored JavaScript/TypeScript. The sandbox starts with no ambient host capabilities; provide imports/globals explicitly, use \`modules\` for local relative ES modules, use \`execute\` to select an export and pass args, use \`report\` for streamed observations, and call \`run.terminate(reason)\` from your own timeout budget when needed. \`modules\` keys are graph-root relative paths; entry-source imports resolve from \`options.filename\` when supplied. Relative module imports may use \`./\` and \`../\` as long as they resolve within the supplied module graph. In thread endpoints, \`runCode\` is forwarded into the thread Durable Object; pass plain transferable option values there, and do function-backed bridges from tools or in-thread execution contexts.
|
|
804
|
+
|
|
750
805
|
## Tool Without Arguments
|
|
751
806
|
|
|
752
807
|
\`\`\`typescript
|
|
@@ -912,6 +967,9 @@ Hooks intercept and modify agent execution at specific lifecycle points.
|
|
|
912
967
|
|
|
913
968
|
| Hook | Signature | Purpose |
|
|
914
969
|
|------|-----------|---------|
|
|
970
|
+
| \`after_thread_created\` | \`(state: ThreadState) => void\` | Initialize a newly created thread before execution |
|
|
971
|
+
| \`after_subagent_created\` | \`(state: ThreadState, childState: ThreadState) => void\` | Run parent-side logic after a child thread is created |
|
|
972
|
+
| \`after_system_message\` | \`(state: ThreadState, systemMessage: string) => string \\| null \\| undefined\` | Modify the rendered system message for a request |
|
|
915
973
|
| \`filter_messages\` | \`(state: ThreadState, messages: Message[]) => Message[]\` | Filter raw messages before LLM context |
|
|
916
974
|
| \`prefilter_llm_history\` | \`(state: ThreadState, messages: LLMMessage[]) => LLMMessage[]\` | Modify chat completion messages before LLM |
|
|
917
975
|
| \`before_create_message\` | \`(state: ThreadState, message: Message) => Message\` | Modify message before database insert |
|
|
@@ -922,7 +980,7 @@ Hooks intercept and modify agent execution at specific lifecycle points.
|
|
|
922
980
|
| \`after_tool_call_success\` | \`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\| null\` | Process successful tool execution |
|
|
923
981
|
| \`after_tool_call_failure\` | \`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\| null\` | Process failed tool execution |
|
|
924
982
|
|
|
925
|
-
All hooks receive \`ThreadState\` as their first parameter, providing access to thread identity, message history, and
|
|
983
|
+
All hooks receive \`ThreadState\` as their first parameter, providing access to thread identity, message history, resource loading, durable per-thread values via \`getValue\` / \`setValue\`, and sandboxed JS/TS execution via \`runCode\`.
|
|
926
984
|
|
|
927
985
|
## Creating a Hook
|
|
928
986
|
|
|
@@ -1086,6 +1144,7 @@ export default defineHook({
|
|
|
1086
1144
|
## Hook Categories
|
|
1087
1145
|
|
|
1088
1146
|
**Transformation hooks** (return modified data):
|
|
1147
|
+
- \`after_system_message\` (return replacement string, or null/undefined for no change)
|
|
1089
1148
|
- \`filter_messages\`
|
|
1090
1149
|
- \`prefilter_llm_history\`
|
|
1091
1150
|
- \`before_create_message\`
|
|
@@ -1095,6 +1154,8 @@ export default defineHook({
|
|
|
1095
1154
|
- \`after_tool_call_failure\` (return modified result or null)
|
|
1096
1155
|
|
|
1097
1156
|
**Event hooks** (side effects only):
|
|
1157
|
+
- \`after_thread_created\`
|
|
1158
|
+
- \`after_subagent_created\`
|
|
1098
1159
|
- \`after_create_message\`
|
|
1099
1160
|
- \`after_update_message\`
|
|
1100
1161
|
|
|
@@ -1121,25 +1182,33 @@ Define custom API endpoints that operate on specific threads with access to the
|
|
|
1121
1182
|
|
|
1122
1183
|
| File Pattern | HTTP Method | Route |
|
|
1123
1184
|
|--------------|-------------|-------|
|
|
1124
|
-
| \`name.ts\` | GET | \`/api/threads/:
|
|
1125
|
-
| \`name.get.ts\` | GET | \`/api/threads/:
|
|
1126
|
-
| \`name.post.ts\` | POST | \`/api/threads/:
|
|
1127
|
-
| \`name.put.ts\` | PUT | \`/api/threads/:
|
|
1128
|
-
| \`name.delete.ts\` | DELETE | \`/api/threads/:
|
|
1129
|
-
| \`
|
|
1185
|
+
| \`name.ts\` | GET | \`/api/threads/:threadId/name\` |
|
|
1186
|
+
| \`name.get.ts\` | GET | \`/api/threads/:threadId/name\` |
|
|
1187
|
+
| \`name.post.ts\` | POST | \`/api/threads/:threadId/name\` |
|
|
1188
|
+
| \`name.put.ts\` | PUT | \`/api/threads/:threadId/name\` |
|
|
1189
|
+
| \`name.delete.ts\` | DELETE | \`/api/threads/:threadId/name\` |
|
|
1190
|
+
| \`index.ts\` | GET | \`/api/threads/:threadId\` |
|
|
1191
|
+
| \`nested/route.ts\` | GET | \`/api/threads/:threadId/nested/route\` |
|
|
1192
|
+
| \`items/[id].ts\` | GET | \`/api/threads/:threadId/items/:id\` |
|
|
1193
|
+
| \`files/[*].ts\` | GET | \`/api/threads/:threadId/files/*\` |
|
|
1194
|
+
|
|
1195
|
+
Files without a method suffix default to GET. Method suffixes are case-insensitive and support \`.get.ts\`, \`.post.ts\`, \`.put.ts\`, \`.patch.ts\`, and \`.delete.ts\`.
|
|
1196
|
+
|
|
1197
|
+
Dynamic segments use \`[name]\` and are passed to the handler as \`params.name\`. Catch-all segments use \`[*]\` and are passed as \`params['*']\`; the catch-all value may contain \`/\` for nested paths. Static routes match before dynamic routes, and dynamic routes match before catch-all routes.
|
|
1130
1198
|
|
|
1131
1199
|
## Basic Example
|
|
1132
1200
|
|
|
1133
1201
|
\`\`\`typescript
|
|
1134
|
-
// agents/api/status.get.ts -> GET /api/threads/:
|
|
1202
|
+
// agents/api/status.get.ts -> GET /api/threads/:threadId/status
|
|
1135
1203
|
import { defineThreadEndpoint } from '@standardagents/spec';
|
|
1136
1204
|
|
|
1137
|
-
export default defineThreadEndpoint(async (req, state) => {
|
|
1205
|
+
export default defineThreadEndpoint(async (req, state, params) => {
|
|
1138
1206
|
const { messages, total } = await state.getMessages();
|
|
1139
1207
|
return Response.json({
|
|
1140
1208
|
threadId: state.threadId,
|
|
1141
1209
|
messageCount: total,
|
|
1142
1210
|
status: 'active',
|
|
1211
|
+
params,
|
|
1143
1212
|
});
|
|
1144
1213
|
});
|
|
1145
1214
|
\`\`\`
|
|
@@ -1149,9 +1218,10 @@ export default defineThreadEndpoint(async (req, state) => {
|
|
|
1149
1218
|
| Parameter | Type | Description |
|
|
1150
1219
|
|-----------|------|-------------|
|
|
1151
1220
|
| \`req\` | \`Request\` | The incoming HTTP request |
|
|
1152
|
-
| \`state\` | \`ThreadState\` | Thread state with messages, identity, file system, etc. |
|
|
1221
|
+
| \`state\` | \`ThreadState\` | Thread state with messages, identity, file system, \`runCode\`, etc. |
|
|
1222
|
+
| \`params\` | \`Record<string, string>\` | Route parameters captured from \`[name]\` and \`[*]\` path segments |
|
|
1153
1223
|
|
|
1154
|
-
Note: \`state.execution\` is always \`null\` in endpoints since the thread is at rest.
|
|
1224
|
+
Note: \`state.execution\` is always \`null\` in endpoints since the thread is at rest. \`state.runCode()\` is available from endpoints and is forwarded into the thread runtime; pass plain transferable option values there, and do function-backed sandbox bridges from tools or in-thread execution contexts.
|
|
1155
1225
|
|
|
1156
1226
|
## ThreadState Methods
|
|
1157
1227
|
|
|
@@ -1177,6 +1247,10 @@ export default defineThreadEndpoint(async (req, state) => {
|
|
|
1177
1247
|
const approvalGate = await state.env('TOPDOWN_APPROVAL_GATE');
|
|
1178
1248
|
await state.setEnv('TOPDOWN_APPROVAL_GATE', approvalGate || 'open');
|
|
1179
1249
|
|
|
1250
|
+
// Durable per-thread JSON values
|
|
1251
|
+
const exports = (await state.getValue<number>('export_count')) ?? 0;
|
|
1252
|
+
await state.setValue('export_count', exports + 1);
|
|
1253
|
+
|
|
1180
1254
|
// File system operations
|
|
1181
1255
|
const files = await state.findFiles('**/*.json');
|
|
1182
1256
|
const data = await state.readFile('/data/config.json');
|
|
@@ -1192,7 +1266,7 @@ export default defineThreadEndpoint(async (req, state) => {
|
|
|
1192
1266
|
## POST with Request Body
|
|
1193
1267
|
|
|
1194
1268
|
\`\`\`typescript
|
|
1195
|
-
// agents/api/export.post.ts -> POST /api/threads/:
|
|
1269
|
+
// agents/api/export.post.ts -> POST /api/threads/:threadId/export
|
|
1196
1270
|
import { defineThreadEndpoint } from '@standardagents/spec';
|
|
1197
1271
|
|
|
1198
1272
|
export default defineThreadEndpoint(async (req, state) => {
|
|
@@ -1218,11 +1292,12 @@ Create directories for nested routes:
|
|
|
1218
1292
|
|
|
1219
1293
|
\`\`\`
|
|
1220
1294
|
agents/api/
|
|
1221
|
-
\u251C\u2500\u2500 status.get.ts -> GET /api/threads/:
|
|
1222
|
-
\u251C\u2500\u2500 export.post.ts -> POST /api/threads/:
|
|
1295
|
+
\u251C\u2500\u2500 status.get.ts -> GET /api/threads/:threadId/status
|
|
1296
|
+
\u251C\u2500\u2500 export.post.ts -> POST /api/threads/:threadId/export
|
|
1223
1297
|
\u2514\u2500\u2500 messages/
|
|
1224
|
-
\u251C\u2500\u2500 count.ts -> GET /api/threads/:
|
|
1225
|
-
\
|
|
1298
|
+
\u251C\u2500\u2500 count.ts -> GET /api/threads/:threadId/messages/count
|
|
1299
|
+
\u251C\u2500\u2500 [id].ts -> GET /api/threads/:threadId/messages/:id
|
|
1300
|
+
\u2514\u2500\u2500 [*].ts -> GET /api/threads/:threadId/messages/*
|
|
1226
1301
|
\`\`\`
|
|
1227
1302
|
|
|
1228
1303
|
## Error Handling
|
|
@@ -1287,10 +1362,18 @@ var WRANGLER_TEMPLATE = (name) => {
|
|
|
1287
1362
|
"name": "${name}",
|
|
1288
1363
|
"main": "worker/index.ts",
|
|
1289
1364
|
"compatibility_date": "${getScaffoldCompatibilityDate()}",
|
|
1290
|
-
"compatibility_flags": ["nodejs_compat"],
|
|
1365
|
+
"compatibility_flags": ["nodejs_compat", "enable_ctx_exports"],
|
|
1291
1366
|
"observability": {
|
|
1292
1367
|
"enabled": true
|
|
1293
1368
|
},
|
|
1369
|
+
"worker_loaders": [
|
|
1370
|
+
{
|
|
1371
|
+
"binding": "AGENT_BUILDER_CODE_LOADER"
|
|
1372
|
+
}
|
|
1373
|
+
],
|
|
1374
|
+
"vars": {
|
|
1375
|
+
"AGENT_BUILDER_CODE_COMPATIBILITY_DATE": "${getScaffoldCompatibilityDate()}"
|
|
1376
|
+
},
|
|
1294
1377
|
"assets": {
|
|
1295
1378
|
"directory": "dist/client",
|
|
1296
1379
|
"not_found_handling": "single-page-application",
|
|
@@ -1330,7 +1413,7 @@ var AGENT_BUILDER_TS = `import { DurableAgentBuilder } from 'virtual:@standardag
|
|
|
1330
1413
|
|
|
1331
1414
|
export default class AgentBuilder extends DurableAgentBuilder {}
|
|
1332
1415
|
`;
|
|
1333
|
-
var WORKER_INDEX = `import { router } from "virtual:@standardagents/builder"
|
|
1416
|
+
var WORKER_INDEX = `import { router, CodeExecutionBridge } from "virtual:@standardagents/builder"
|
|
1334
1417
|
import DurableThread from '../agents/Thread';
|
|
1335
1418
|
import DurableAgentBuilder from '../agents/AgentBuilder';
|
|
1336
1419
|
|
|
@@ -1341,7 +1424,7 @@ export default {
|
|
|
1341
1424
|
},
|
|
1342
1425
|
} satisfies ExportedHandler<Env>
|
|
1343
1426
|
|
|
1344
|
-
export { DurableThread, DurableAgentBuilder }
|
|
1427
|
+
export { DurableThread, DurableAgentBuilder, CodeExecutionBridge }
|
|
1345
1428
|
`;
|
|
1346
1429
|
function getProjectName(cwd) {
|
|
1347
1430
|
const packageJsonPath = path3.join(cwd, "package.json");
|
|
@@ -1427,11 +1510,34 @@ function createOrUpdateWranglerConfig(cwd, projectName, force) {
|
|
|
1427
1510
|
const hasBindings = config.durable_objects?.bindings?.some(
|
|
1428
1511
|
(b) => b.name === "AGENT_BUILDER_THREAD" || b.name === "AGENT_BUILDER"
|
|
1429
1512
|
);
|
|
1430
|
-
|
|
1513
|
+
const hasCodeLoader = config.worker_loaders?.some(
|
|
1514
|
+
(loader) => loader.binding === "AGENT_BUILDER_CODE_LOADER"
|
|
1515
|
+
);
|
|
1516
|
+
const hasCodeCompatibilityDate = config.vars?.AGENT_BUILDER_CODE_COMPATIBILITY_DATE === getScaffoldCompatibilityDate();
|
|
1517
|
+
const hasCtxExportsFlag = Array.isArray(config.compatibility_flags) ? config.compatibility_flags.includes("enable_ctx_exports") : false;
|
|
1518
|
+
if (hasBindings && hasCodeLoader && hasCodeCompatibilityDate && hasCtxExportsFlag) {
|
|
1431
1519
|
logger.info("wrangler.jsonc already configured for Standard Agents");
|
|
1432
1520
|
return true;
|
|
1433
1521
|
}
|
|
1434
1522
|
let result = text;
|
|
1523
|
+
if (!hasCodeLoader) {
|
|
1524
|
+
const loaders = [...config.worker_loaders || [], { binding: "AGENT_BUILDER_CODE_LOADER" }];
|
|
1525
|
+
const edits = modify(result, ["worker_loaders"], loaders, {});
|
|
1526
|
+
result = applyEdits(result, edits);
|
|
1527
|
+
}
|
|
1528
|
+
if (!hasCodeCompatibilityDate) {
|
|
1529
|
+
const vars = {
|
|
1530
|
+
...config.vars || {},
|
|
1531
|
+
AGENT_BUILDER_CODE_COMPATIBILITY_DATE: getScaffoldCompatibilityDate()
|
|
1532
|
+
};
|
|
1533
|
+
const edits = modify(result, ["vars"], vars, {});
|
|
1534
|
+
result = applyEdits(result, edits);
|
|
1535
|
+
}
|
|
1536
|
+
if (!hasCtxExportsFlag) {
|
|
1537
|
+
const flags = Array.isArray(config.compatibility_flags) ? [...config.compatibility_flags, "enable_ctx_exports"] : ["nodejs_compat", "enable_ctx_exports"];
|
|
1538
|
+
const edits = modify(result, ["compatibility_flags"], flags, {});
|
|
1539
|
+
result = applyEdits(result, edits);
|
|
1540
|
+
}
|
|
1435
1541
|
if (!config.durable_objects) {
|
|
1436
1542
|
const edits = modify(result, ["durable_objects"], {
|
|
1437
1543
|
bindings: [
|
|
@@ -1442,10 +1548,12 @@ function createOrUpdateWranglerConfig(cwd, projectName, force) {
|
|
|
1442
1548
|
result = applyEdits(result, edits);
|
|
1443
1549
|
} else {
|
|
1444
1550
|
const bindings = config.durable_objects.bindings || [];
|
|
1445
|
-
bindings.
|
|
1446
|
-
{ name: "AGENT_BUILDER_THREAD", class_name: "DurableThread" }
|
|
1447
|
-
|
|
1448
|
-
)
|
|
1551
|
+
if (!bindings.some((b) => b.name === "AGENT_BUILDER_THREAD")) {
|
|
1552
|
+
bindings.push({ name: "AGENT_BUILDER_THREAD", class_name: "DurableThread" });
|
|
1553
|
+
}
|
|
1554
|
+
if (!bindings.some((b) => b.name === "AGENT_BUILDER")) {
|
|
1555
|
+
bindings.push({ name: "AGENT_BUILDER", class_name: "DurableAgentBuilder" });
|
|
1556
|
+
}
|
|
1449
1557
|
const edits = modify(result, ["durable_objects", "bindings"], bindings, {});
|
|
1450
1558
|
result = applyEdits(result, edits);
|
|
1451
1559
|
}
|
|
@@ -1512,10 +1620,23 @@ async function createOrUpdateWorkerEntry(cwd, force) {
|
|
|
1512
1620
|
const content = fs3.readFileSync(entryPath, "utf-8");
|
|
1513
1621
|
const hasRouter = content.includes("virtual:@standardagents/builder") && content.includes("router");
|
|
1514
1622
|
const hasDurableExports = content.includes("DurableThread") && content.includes("DurableAgentBuilder");
|
|
1515
|
-
|
|
1623
|
+
const hasCodeBridge = content.includes("CodeExecutionBridge");
|
|
1624
|
+
if (hasRouter && hasDurableExports && hasCodeBridge && !force) {
|
|
1516
1625
|
logger.info(`${path3.relative(cwd, entryPath)} already configured`);
|
|
1517
1626
|
return true;
|
|
1518
1627
|
}
|
|
1628
|
+
if (hasRouter && hasDurableExports && !hasCodeBridge && !force) {
|
|
1629
|
+
fs3.writeFileSync(
|
|
1630
|
+
entryPath,
|
|
1631
|
+
`${content.trimEnd()}
|
|
1632
|
+
|
|
1633
|
+
export { CodeExecutionBridge } from "virtual:@standardagents/builder"
|
|
1634
|
+
`,
|
|
1635
|
+
"utf-8"
|
|
1636
|
+
);
|
|
1637
|
+
logger.success(`Updated ${path3.relative(cwd, entryPath)} with CodeExecutionBridge export`);
|
|
1638
|
+
return true;
|
|
1639
|
+
}
|
|
1519
1640
|
try {
|
|
1520
1641
|
const mod = await loadFile(entryPath);
|
|
1521
1642
|
if (!content.includes("virtual:@standardagents/builder") || force) {
|
|
@@ -1565,6 +1686,7 @@ async function createOrUpdateWorkerEntry(cwd, force) {
|
|
|
1565
1686
|
logger.log("");
|
|
1566
1687
|
logger.log(" // Export Durable Objects:");
|
|
1567
1688
|
logger.log(" export { DurableThread, DurableAgentBuilder }");
|
|
1689
|
+
logger.log(' export { CodeExecutionBridge } from "virtual:@standardagents/builder"');
|
|
1568
1690
|
logger.log("");
|
|
1569
1691
|
return false;
|
|
1570
1692
|
}
|
|
@@ -1880,7 +2002,7 @@ function getWorkspacePackageVersion() {
|
|
|
1880
2002
|
if (process.env.STANDARDAGENTS_WORKSPACE === "1") {
|
|
1881
2003
|
return "workspace:*";
|
|
1882
2004
|
}
|
|
1883
|
-
return "0.
|
|
2005
|
+
return "0.15.0";
|
|
1884
2006
|
}
|
|
1885
2007
|
function getSipPackageVersion() {
|
|
1886
2008
|
return "1.0.1";
|
|
@@ -4111,7 +4233,7 @@ async function availableModels(options = {}) {
|
|
|
4111
4233
|
|
|
4112
4234
|
// src/index.ts
|
|
4113
4235
|
var program = new Command();
|
|
4114
|
-
program.name("agents").description("CLI tool for Standard Agents / AgentBuilder").version("0.
|
|
4236
|
+
program.name("agents").description("CLI tool for Standard Agents / AgentBuilder").version("0.15.0");
|
|
4115
4237
|
program.command("init [project-name]").description("Create a new Standard Agents project (runs create vite, then scaffold)").option("-y, --yes", "Skip prompts and use defaults").option("--template <template>", "Vite template to use", "vanilla-ts").action(init);
|
|
4116
4238
|
program.command("scaffold").description("Add Standard Agents to an existing Vite project").option("--force", "Overwrite existing configuration").action(scaffold);
|
|
4117
4239
|
program.command("init-chat [project-name]").description("Scaffold a frontend chat application").option("-y, --yes", "Skip prompts and use defaults").option("--framework <framework>", "Framework to use (vite or nextjs)").action(initChat);
|