@standardagents/builder 0.35.4 → 0.36.2
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/built-in-routes.js +3278 -2139
- package/dist/built-in-routes.js.map +1 -1
- package/dist/client/{ApiKeysView-CnybtFho.js → ApiKeysView-CxelZw61.js} +1 -1
- package/dist/client/CenteredContentView-CeQNRQH8.js +1 -0
- package/dist/client/CompositionView-YO0nHsYV.js +32 -0
- package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-CqwPyg0f.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-_Y_F2vcO.js} +1 -1
- package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-CyfjQKbm.js → CopyButton.vue_vue_type_script_setup_true_lang-CtC06f6H.js} +1 -1
- package/dist/client/{DataTable.vue_vue_type_script_setup_true_lang-ns-DYcKW.js → DataTable.vue_vue_type_script_setup_true_lang-CqaWkS63.js} +1 -1
- package/dist/client/{JsonViewer-w11hvBiv.js → JsonViewer-71rdOpyq.js} +1 -1
- package/dist/client/{LoginView-BhkGzCFE.js → LoginView-CkDpPh8U.js} +1 -1
- package/dist/client/{MarketplaceView-yZXHH-T4.js → MarketplaceView-UYrMBLon.js} +1 -1
- package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-B6K3Zkh6.js → Modal.vue_vue_type_script_setup_true_lang-B1HPGo8o.js} +1 -1
- package/dist/client/{ModelModal.vue_vue_type_script_setup_true_lang-DebPdGdQ.js → ModelModal.vue_vue_type_script_setup_true_lang-DejoTM9W.js} +1 -1
- package/dist/client/{ModelsView-C4xTc0Ut.js → ModelsView-DKYzp2fJ.js} +1 -1
- package/dist/client/{PromptEditView-B1TvKsvK.js → PromptEditView-BlYHZ0ao.js} +1 -1
- package/dist/client/{PromptModal-C3CMojNY.js → PromptModal-B1neRzSc.js} +1 -1
- package/dist/client/{PromptsView-cnbYo7GZ.js → PromptsView-C0Ez74j0.js} +1 -1
- package/dist/client/{ProvidersView-01sjKjFL.js → ProvidersView-CFc4K0IC.js} +1 -1
- package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-CXbSQo2-.js +23 -0
- package/dist/client/{ThreadsView-BLmcRVRx.js → ThreadsView-B1hFXL-4.js} +1 -1
- package/dist/client/{ToolsView-HCxNKC5q.js → ToolsView-B3KqeOZD.js} +1 -1
- package/dist/client/{UiCodeBlock.vue_vue_type_script_setup_true_lang-QytRm7Ql.js → UiCodeBlock.vue_vue_type_script_setup_true_lang-DjDQOYjB.js} +1 -1
- package/dist/client/{UsersView-BDAOlNJQ.js → UsersView-CF1tomjI.js} +1 -1
- package/dist/client/{VariablesView-Co_hp_tq.js → VariablesView-CP0TDspK.js} +1 -1
- package/dist/client/assets/{ThreadInspectorPane-G2muXE6J.css → ThreadInspectorPane-2QOWOtet.css} +1 -1
- package/dist/client/{check-pGlck8qX.js → check-DeHZQcv4.js} +1 -1
- package/dist/client/{chevron-right-FpPE1Obh.js → chevron-right-C8Mb0B59.js} +1 -1
- package/dist/client/{copy-Dt1FLh3s.js → copy-BxJsl-KZ.js} +1 -1
- package/dist/client/{formkit-DcZQH9-p.js → formkit-0eyyCEP_.js} +1 -1
- package/dist/client/{index-CU9i-w9T.js → index-BTs3PMFs.js} +3 -3
- package/dist/client/index.html +3 -3
- package/dist/client/{package-DSNwOrcN.js → package-B9czwyIu.js} +1 -1
- package/dist/client/{plus-D0GkkdA7.js → plus-DqtuqJFm.js} +1 -1
- package/dist/client/timeAgo-CDt-vAhI.js +1 -0
- package/dist/client/{useActionFeedback-Dxh_Xp0q.js → useActionFeedback-B6UfBJ7l.js} +1 -1
- package/dist/client/{vue-KXHVRwln.js → vue-Dw7WLX4c.js} +1 -1
- package/dist/{index-DP9GxPHu.d.ts → index-DUIfQjBW.d.ts} +3 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +322 -13
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.js +7 -0
- package/dist/plugin.js.map +1 -1
- package/dist/runtime.d.ts +26 -2
- package/dist/runtime.js +315 -13
- package/dist/runtime.js.map +1 -1
- package/dist/test.d.ts +1 -1
- package/package.json +25 -25
- package/LICENSE.txt +0 -48
- package/dist/client/CenteredContentView-Ch18yAzL.js +0 -1
- package/dist/client/CompositionView-Ctlbn0vj.js +0 -32
- package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-BiimzVFD.js +0 -22
- package/dist/client/timeAgo-X3Xeq5Kz.js +0 -1
package/dist/runtime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { e as ThreadEnv, A as Agent, r as ThreadMetadata, t as ToolResult, M as Message, k as ClientToolRequest, l as ClientToolResponse, m as ClientStreamRequest, n as ClientStreamResponse, w as FileRecord, F as FlowState, y as FileStats, G as GrepResult, x as AttachmentRef, J as MessageContent, E as Env, q as ThreadInstance } from './index-
|
|
2
|
-
export { f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, o as ClientDuplex, p as ClientForwarding, B as Controller, a as ControllerContext, u as FlowResult, D as ImageContentPart, I as ImageMetadata, L as LLMResponse, H as MultimodalContent, R as RequestContext, S as StorageBackend, v as TelemetryEvent, z as TextContentPart, b as ThreadEndpointContext, T as ToolCall, g as callClient, h as callClientStream, c as createThreadEndpointHandler, j as decodeStreamChunk, d as defineController, i as encodeStreamChunk, s as supportsClientForwarding } from './index-
|
|
1
|
+
import { e as ThreadEnv, A as Agent, r as ThreadMetadata, t as ToolResult, M as Message, k as ClientToolRequest, l as ClientToolResponse, m as ClientStreamRequest, n as ClientStreamResponse, w as FileRecord, F as FlowState, y as FileStats, G as GrepResult, x as AttachmentRef, J as MessageContent, E as Env, q as ThreadInstance } from './index-DUIfQjBW.js';
|
|
2
|
+
export { f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, o as ClientDuplex, p as ClientForwarding, B as Controller, a as ControllerContext, u as FlowResult, D as ImageContentPart, I as ImageMetadata, L as LLMResponse, H as MultimodalContent, R as RequestContext, S as StorageBackend, v as TelemetryEvent, z as TextContentPart, b as ThreadEndpointContext, T as ToolCall, g as callClient, h as callClientStream, c as createThreadEndpointHandler, j as decodeStreamChunk, d as defineController, i as encodeStreamChunk, s as supportsClientForwarding } from './index-DUIfQjBW.js';
|
|
3
3
|
import { CodeExecutionOptions, CodeExecutionResult, SubagentRegistryEntry, InjectMessageInput, QueueMessageInput, CredentialGrant, SkillMetadata, SkillFileInput, ModelDefinition as ModelDefinition$1, ToolArgs, PromptTextPart, PromptEnvPart, VariableDefinition, SubpromptConfig as SubpromptConfig$1, PromptToolConfig as PromptToolConfig$1, SubagentToolConfig as SubagentToolConfig$1, ReasoningConfig, SideConfig as SideConfig$1, LLMProviderInterface, ContentPart, TextPart, ImagePart, FilePart, ThreadState, NamespaceContext, DefinitionLoader } from '@standardagents/spec';
|
|
4
4
|
export { AgentType, DefinitionLoader, GlobalNamespaceContext, HookSignatures, ImageContent, ModelCapabilities, ModelProvider, NamespaceContext, PackageSignature, PackedExports, PackedMeta, PackedMetadata, PackedNamespaceContext, PromptInput, PromptTextPart, ProviderAssistantMessage, ProviderError, ProviderErrorCode, ProviderFactory, ProviderFactoryConfig, ProviderFinishReason, ProviderGeneratedImage, ProviderMessage, ProviderMessageContent, ModelCapabilities as ProviderModelCapabilities, ProviderReasoningDetail, ProviderRequest, ProviderResponse, ProviderStreamChunk, ProviderSystemMessage, ProviderTool, ProviderToolCallPart, ProviderToolMessage, ProviderToolResultContent, ProviderUsage, ProviderUserMessage, ReasoningConfig, StructuredPrompt, TextContent, Tool, ToolArgs, ToolArgsNode, ToolArgsRawShape, ToolContent, belongsToPackage, defineAgent, defineHook, defineModel, definePrompt, defineTool, isPacked, isVisibleInNamespace, mapReasoningLevel } from '@standardagents/spec';
|
|
5
5
|
import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
|
|
@@ -428,6 +428,26 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
|
|
|
428
428
|
* Get the persisted resumable-subagent registry for this thread.
|
|
429
429
|
*/
|
|
430
430
|
getChildrenRegistry(_threadId: string): Promise<SubagentRegistryEntry[]>;
|
|
431
|
+
/** In-memory throttle/reentrancy guards for the stale-child reconciler. */
|
|
432
|
+
private lastChildAuditAt;
|
|
433
|
+
private childAuditInFlight;
|
|
434
|
+
/**
|
|
435
|
+
* Lazily heal registry entries stranded at a "working" status. The normal
|
|
436
|
+
* settlement chain lives only in the parent's `waitUntil`; a parent
|
|
437
|
+
* eviction/deploy/kill during a child's run leaves the entry at `running`
|
|
438
|
+
* forever and clients render an eternal spinner. On registry reads, audit
|
|
439
|
+
* old unsettled entries against the child thread's ACTUAL state and settle
|
|
440
|
+
* them — conservatively (see subagent-reconcile.ts): resumable children
|
|
441
|
+
* are never deterministically terminated.
|
|
442
|
+
*/
|
|
443
|
+
private reconcileStaleChildren;
|
|
444
|
+
/**
|
|
445
|
+
* Child-side registry settlement: called from the CHILD's own DO whenever
|
|
446
|
+
* a run ends, so the spinner clears even when the parent-held completion
|
|
447
|
+
* chain died with the parent. Only downgrades a live "working" status to
|
|
448
|
+
* idle — never clobbers terminated.
|
|
449
|
+
*/
|
|
450
|
+
settleChildRegistryIdle(_threadId: string, reference: string): Promise<void>;
|
|
431
451
|
private setChildrenRegistry;
|
|
432
452
|
upsertChildRegistry(_threadId: string, entry: SubagentRegistryEntry): Promise<void>;
|
|
433
453
|
updateChildRegistryStatus(_threadId: string, reference: string, status: string): Promise<void>;
|
|
@@ -565,6 +585,9 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
|
|
|
565
585
|
attachments?: unknown[];
|
|
566
586
|
terminal?: boolean;
|
|
567
587
|
}>;
|
|
588
|
+
/** Best-effort: mark this child's entry idle in its parent's registry. */
|
|
589
|
+
private settleOwnRegistryEntry;
|
|
590
|
+
private executeBlockingImpl;
|
|
568
591
|
/**
|
|
569
592
|
* Send a new message to the thread (RPC method)
|
|
570
593
|
* Enqueues the message processing to be handled by the alarm handler
|
|
@@ -785,6 +808,7 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
|
|
|
785
808
|
parent_log_id: string | null;
|
|
786
809
|
retry_of_log_id: string | null;
|
|
787
810
|
error: string | null;
|
|
811
|
+
error_type: string | null;
|
|
788
812
|
cost_total: number | null;
|
|
789
813
|
input_tokens: number | null;
|
|
790
814
|
cached_tokens: number | null;
|
package/dist/runtime.js
CHANGED
|
@@ -931,12 +931,23 @@ function resolvePlatformRouting(providerName, env) {
|
|
|
931
931
|
baseUrl: `${origin}/v1/proxy/${encodeURIComponent(provider)}${basePath}`
|
|
932
932
|
};
|
|
933
933
|
}
|
|
934
|
+
function platformProviderFactoryConfig(providerName, routing) {
|
|
935
|
+
const config = {
|
|
936
|
+
apiKey: routing.apiKey,
|
|
937
|
+
baseUrl: routing.baseUrl
|
|
938
|
+
};
|
|
939
|
+
if (providerName.toLowerCase() === "deepinfra") {
|
|
940
|
+
config.modelsUrl = `${routing.origin}/v1/proxy/deepinfra/models`;
|
|
941
|
+
}
|
|
942
|
+
return config;
|
|
943
|
+
}
|
|
934
944
|
var DEFAULT_PLATFORM_PROXY_ORIGIN, PROVIDER_BASE_PATHS;
|
|
935
945
|
var init_platform_routing = __esm({
|
|
936
946
|
"src/agents/providers/platform-routing.ts"() {
|
|
937
947
|
DEFAULT_PLATFORM_PROXY_ORIGIN = "https://api.standardagents.ai";
|
|
938
948
|
PROVIDER_BASE_PATHS = {
|
|
939
|
-
cloudflare: "/ai/v1"
|
|
949
|
+
cloudflare: "/ai/v1",
|
|
950
|
+
deepinfra: "/openai"
|
|
940
951
|
};
|
|
941
952
|
}
|
|
942
953
|
});
|
|
@@ -1229,10 +1240,7 @@ var init_ProviderRegistry = __esm({
|
|
|
1229
1240
|
}
|
|
1230
1241
|
const routing = resolvePlatformRouting(providerName, env);
|
|
1231
1242
|
if (routing) {
|
|
1232
|
-
const config =
|
|
1233
|
-
apiKey: routing.apiKey,
|
|
1234
|
-
baseUrl: routing.baseUrl
|
|
1235
|
-
};
|
|
1243
|
+
const config = platformProviderFactoryConfig(providerName, routing);
|
|
1236
1244
|
registerPlatformProxyOrigin(routing.origin);
|
|
1237
1245
|
const fingerprint = this.getProviderFingerprint(`platform:${providerName}`, modelDef, config);
|
|
1238
1246
|
const cached = this.providerCache.get(modelName);
|
|
@@ -1268,6 +1276,7 @@ var init_ProviderRegistry = __esm({
|
|
|
1268
1276
|
google: "GOOGLE_API_KEY",
|
|
1269
1277
|
groq: "GROQ_API_KEY",
|
|
1270
1278
|
novita: "NOVITA_API_KEY",
|
|
1279
|
+
deepinfra: "DEEPINFRA_API_KEY",
|
|
1271
1280
|
openai: "OPENAI_API_KEY",
|
|
1272
1281
|
openrouter: "OPENROUTER_API_KEY",
|
|
1273
1282
|
anthropic: "ANTHROPIC_API_KEY",
|
|
@@ -1705,7 +1714,9 @@ function buildRequestBody(context, modelDef) {
|
|
|
1705
1714
|
messages: requestMessages,
|
|
1706
1715
|
tools,
|
|
1707
1716
|
toolChoice,
|
|
1708
|
-
|
|
1717
|
+
// null (prompt didn't set it) normalizes to undefined so providers omit
|
|
1718
|
+
// the wire param entirely and their default applies (2026-08-04).
|
|
1719
|
+
parallelToolCalls: supportsToolCalls ? context.parallel_tool_calls ?? void 0 : void 0,
|
|
1709
1720
|
reasoning: context.reasoning ? {
|
|
1710
1721
|
level: reasoningEffortToLevel(context.reasoning.effort),
|
|
1711
1722
|
maxTokens: context.reasoning.max_tokens,
|
|
@@ -1824,6 +1835,9 @@ var init_LLMRequest = __esm({
|
|
|
1824
1835
|
try {
|
|
1825
1836
|
return await this.tryModel(context, state, context.model, startTime, void 0);
|
|
1826
1837
|
} catch (primaryError) {
|
|
1838
|
+
if (primaryError?._userStop) {
|
|
1839
|
+
throw primaryError;
|
|
1840
|
+
}
|
|
1827
1841
|
console.error(`Primary model ${context.model} failed:`, primaryError);
|
|
1828
1842
|
lastFailedLogId = primaryError?._lastLogId;
|
|
1829
1843
|
state.emitTelemetry?.({
|
|
@@ -1850,6 +1864,9 @@ var init_LLMRequest = __esm({
|
|
|
1850
1864
|
lastFailedLogId
|
|
1851
1865
|
);
|
|
1852
1866
|
} catch (fallbackError) {
|
|
1867
|
+
if (fallbackError?._userStop) {
|
|
1868
|
+
throw fallbackError;
|
|
1869
|
+
}
|
|
1853
1870
|
console.error(
|
|
1854
1871
|
`Fallback model ${fallback.fallback_model_id} failed:`,
|
|
1855
1872
|
fallbackError
|
|
@@ -1939,9 +1956,24 @@ var init_LLMRequest = __esm({
|
|
|
1939
1956
|
this.fireAsyncMetadataFetch(response, state, logId);
|
|
1940
1957
|
return { response, logId };
|
|
1941
1958
|
} catch (error2) {
|
|
1959
|
+
if (state.abortController?.signal?.aborted) {
|
|
1960
|
+
await this.logError(
|
|
1961
|
+
state,
|
|
1962
|
+
new Error("Interrupted by user"),
|
|
1963
|
+
"user_interrupted",
|
|
1964
|
+
actualModelId,
|
|
1965
|
+
startTime,
|
|
1966
|
+
logId
|
|
1967
|
+
);
|
|
1968
|
+
const stopError = new Error("aborted");
|
|
1969
|
+
stopError._lastLogId = logId;
|
|
1970
|
+
stopError._userStop = true;
|
|
1971
|
+
throw stopError;
|
|
1972
|
+
}
|
|
1942
1973
|
console.error(`Error calling ${actualModelId} (attempt ${attempts}):`, error2);
|
|
1943
1974
|
await this.logError(state, error2, "api_error", actualModelId, startTime, logId);
|
|
1944
|
-
|
|
1975
|
+
const isStallTimeout = error2?.code === "timeout";
|
|
1976
|
+
if (attempts < MAX_RETRIES_PER_MODEL && !isStallTimeout) {
|
|
1945
1977
|
const base = BACKOFF_BASE * Math.pow(2, attempts - 1);
|
|
1946
1978
|
const retryAfterMs = typeof error2?.retryAfter === "number" ? error2.retryAfter * 1e3 : 0;
|
|
1947
1979
|
const backoffMs = Math.max(base, retryAfterMs);
|
|
@@ -3849,7 +3881,7 @@ __export(ToolExecutor_exports, {
|
|
|
3849
3881
|
function getPackageId(state) {
|
|
3850
3882
|
return state.namespaceContext.type === "packed" ? state.namespaceContext.packageId : void 0;
|
|
3851
3883
|
}
|
|
3852
|
-
var SUBAGENT_CREATE_TOOL, SUBAGENT_MESSAGE_TOOL, LEGACY_SEND_TO_AGENT_TOOL, INTERNAL_SCOPED_ENV_ARGUMENT, INTERNAL_SCOPED_ENV_CONTEXT_KEY, ToolExecutor;
|
|
3884
|
+
var SUBAGENT_CREATE_TOOL, SUBAGENT_MESSAGE_TOOL, SUBAGENTS_LIST_TOOL, LEGACY_SEND_TO_AGENT_TOOL, INTERNAL_SCOPED_ENV_ARGUMENT, INTERNAL_SCOPED_ENV_CONTEXT_KEY, ToolExecutor;
|
|
3853
3885
|
var init_ToolExecutor = __esm({
|
|
3854
3886
|
"src/agents/ToolExecutor.ts"() {
|
|
3855
3887
|
init_types();
|
|
@@ -3857,6 +3889,7 @@ var init_ToolExecutor = __esm({
|
|
|
3857
3889
|
init_sessionTools();
|
|
3858
3890
|
SUBAGENT_CREATE_TOOL = "subagent_create";
|
|
3859
3891
|
SUBAGENT_MESSAGE_TOOL = "subagent_message";
|
|
3892
|
+
SUBAGENTS_LIST_TOOL = "subagents";
|
|
3860
3893
|
LEGACY_SEND_TO_AGENT_TOOL = "send_to_agent";
|
|
3861
3894
|
INTERNAL_SCOPED_ENV_ARGUMENT = "__scoped_env";
|
|
3862
3895
|
INTERNAL_SCOPED_ENV_CONTEXT_KEY = "__immediate_scoped_env_by_call_id";
|
|
@@ -4015,6 +4048,33 @@ var init_ToolExecutor = __esm({
|
|
|
4015
4048
|
* Execute a single tool call
|
|
4016
4049
|
*/
|
|
4017
4050
|
static async executeToolCall(call, state, toolMessageId) {
|
|
4051
|
+
try {
|
|
4052
|
+
const n = call.function?.name;
|
|
4053
|
+
if (n && n.includes("_") && n !== "mcp") {
|
|
4054
|
+
const cat2 = await state.thread.instance.getValue("mcp_catalog");
|
|
4055
|
+
for (const srv of cat2?.servers ?? []) {
|
|
4056
|
+
const sname = srv.name ?? srv.serverInfo?.name;
|
|
4057
|
+
if (!sname || !n.startsWith(`${sname}_`)) continue;
|
|
4058
|
+
const mtool = n.slice(sname.length + 1);
|
|
4059
|
+
if (!Array.isArray(srv.tools) || !srv.tools.some((t) => t.name === mtool)) continue;
|
|
4060
|
+
call = {
|
|
4061
|
+
...call,
|
|
4062
|
+
function: {
|
|
4063
|
+
...call.function,
|
|
4064
|
+
name: "mcp",
|
|
4065
|
+
arguments: JSON.stringify({
|
|
4066
|
+
action: "call",
|
|
4067
|
+
server: sname,
|
|
4068
|
+
tool: mtool,
|
|
4069
|
+
arguments_json: call.function.arguments || "{}"
|
|
4070
|
+
})
|
|
4071
|
+
}
|
|
4072
|
+
};
|
|
4073
|
+
break;
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
} catch {
|
|
4077
|
+
}
|
|
4018
4078
|
const toolType = await this.identifyToolType(call, state);
|
|
4019
4079
|
switch (toolType) {
|
|
4020
4080
|
case "native":
|
|
@@ -4064,7 +4124,7 @@ var init_ToolExecutor = __esm({
|
|
|
4064
4124
|
*/
|
|
4065
4125
|
static async identifyToolType(call, state) {
|
|
4066
4126
|
const toolName = call.function.name;
|
|
4067
|
-
if (toolName === SUBAGENT_CREATE_TOOL || toolName === SUBAGENT_MESSAGE_TOOL || toolName === LEGACY_SEND_TO_AGENT_TOOL) {
|
|
4127
|
+
if (toolName === SUBAGENT_CREATE_TOOL || toolName === SUBAGENT_MESSAGE_TOOL || toolName === SUBAGENTS_LIST_TOOL || toolName === LEGACY_SEND_TO_AGENT_TOOL) {
|
|
4068
4128
|
return "agent";
|
|
4069
4129
|
}
|
|
4070
4130
|
if (state.allowedTools) {
|
|
@@ -4597,6 +4657,22 @@ ${errorLines.join("\n")}`);
|
|
|
4597
4657
|
if (builtinSubagentAction === "message") {
|
|
4598
4658
|
return await this.executeSubagentMessageTool(call, state);
|
|
4599
4659
|
}
|
|
4660
|
+
if (call.function.name === SUBAGENTS_LIST_TOOL) {
|
|
4661
|
+
const { FlowEngine: FlowEngine2 } = await Promise.resolve().then(() => (init_FlowEngine(), FlowEngine_exports));
|
|
4662
|
+
const registry = await FlowEngine2.listModelVisibleSubagents(state);
|
|
4663
|
+
if (registry.length === 0) {
|
|
4664
|
+
return { status: "success", result: "No active subagent instances." };
|
|
4665
|
+
}
|
|
4666
|
+
const lines = registry.map(
|
|
4667
|
+
(entry) => `- ${entry.reference}: ${entry.name} \u2014 ${entry.status ?? "unknown"}${entry.description ? ` (${entry.description})` : ""}`
|
|
4668
|
+
);
|
|
4669
|
+
return {
|
|
4670
|
+
status: "success",
|
|
4671
|
+
result: `Active subagent instances:
|
|
4672
|
+
${lines.join("\n")}
|
|
4673
|
+
Message one with subagent_message(referenceId, message).`
|
|
4674
|
+
};
|
|
4675
|
+
}
|
|
4600
4676
|
const createArgs = builtinSubagentAction === "create" ? this.parseSubagentCreateArgs(call.function.arguments) : null;
|
|
4601
4677
|
if (createArgs?.error) {
|
|
4602
4678
|
return { status: "error", error: createArgs.error };
|
|
@@ -6919,7 +6995,10 @@ This usually points to something I can't fix from here \u2014 for example the wo
|
|
|
6919
6995
|
model: def.model,
|
|
6920
6996
|
include_chat: def.includeChat ?? false,
|
|
6921
6997
|
include_past_tools: def.includePastTools ?? false,
|
|
6922
|
-
|
|
6998
|
+
// Unset stays unset (2026-08-04): defaulting to `false` forbade the
|
|
6999
|
+
// parallel batching agentic-tuned models are trained on; absent lets
|
|
7000
|
+
// the provider default apply, while an explicit prompt value is honored.
|
|
7001
|
+
parallel_tool_calls: def.parallelToolCalls ?? null,
|
|
6923
7002
|
tool_choice: def.toolChoice ?? "auto",
|
|
6924
7003
|
reasoning_effort: def.reasoning?.effort ?? null,
|
|
6925
7004
|
reasoning_max_tokens: def.reasoning?.maxTokens ?? null,
|
|
@@ -8201,6 +8280,13 @@ This usually points to something I can't fix from here \u2014 for example the wo
|
|
|
8201
8280
|
if (hidden.size === 0) return registry;
|
|
8202
8281
|
return registry.filter((entry) => !hidden.has(entry.name));
|
|
8203
8282
|
}
|
|
8283
|
+
/** Public snapshot for the `subagents` built-in tool (ToolExecutor). */
|
|
8284
|
+
static async listModelVisibleSubagents(state) {
|
|
8285
|
+
return _FlowEngine.filterModelVisibleSubagents(
|
|
8286
|
+
await this.getSubagentRegistry(state),
|
|
8287
|
+
state.prompt?._tools
|
|
8288
|
+
);
|
|
8289
|
+
}
|
|
8204
8290
|
static async getSubagentRegistry(state) {
|
|
8205
8291
|
if (typeof state.thread.instance.getChildrenRegistry === "function") {
|
|
8206
8292
|
try {
|
|
@@ -8470,7 +8556,8 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
|
|
|
8470
8556
|
await this.getSubagentRegistry(state),
|
|
8471
8557
|
state.prompt?._tools
|
|
8472
8558
|
);
|
|
8473
|
-
|
|
8559
|
+
const suppressRegistryMessage = Array.isArray(state.prompt?.hooks) ? state.prompt.hooks.includes("append_static_session_env") : false;
|
|
8560
|
+
if (subagentRegistry.length > 0 && !suppressRegistryMessage) {
|
|
8474
8561
|
const fallbackNameMap = await this.resolveRegistryThreadNameMap(state, subagentRegistry);
|
|
8475
8562
|
const lines = subagentRegistry.map((entry) => {
|
|
8476
8563
|
const threadName = this.getRegistryThreadName(entry) ?? fallbackNameMap.get(entry.reference) ?? null;
|
|
@@ -8829,6 +8916,16 @@ ${lines.join("\n\n")}`
|
|
|
8829
8916
|
}
|
|
8830
8917
|
if (resumablePromptSubagents.length > 0 && !tools.some((tool) => tool.function.name === "subagent_create")) {
|
|
8831
8918
|
tools.push(this.buildSubagentCreateTool(resumablePromptSubagents));
|
|
8919
|
+
if (!tools.some((tool) => tool.function.name === "subagents")) {
|
|
8920
|
+
tools.push({
|
|
8921
|
+
type: "function",
|
|
8922
|
+
function: {
|
|
8923
|
+
name: "subagents",
|
|
8924
|
+
description: "List your active subagent instances: reference id, name, status, and working-status text. Use when you need to check on children you created; completions also arrive as messages.",
|
|
8925
|
+
parameters: { type: "object", properties: {} }
|
|
8926
|
+
}
|
|
8927
|
+
});
|
|
8928
|
+
}
|
|
8832
8929
|
}
|
|
8833
8930
|
const hasActiveResumable = childrenRegistry.some(
|
|
8834
8931
|
(entry) => entry.status !== "terminated"
|
|
@@ -8863,6 +8960,73 @@ ${lines.join("\n\n")}`
|
|
|
8863
8960
|
}
|
|
8864
8961
|
});
|
|
8865
8962
|
}
|
|
8963
|
+
try {
|
|
8964
|
+
const cat2 = await state.thread.instance.getValue("mcp_catalog");
|
|
8965
|
+
const servers = cat2?.servers ?? [];
|
|
8966
|
+
const have = new Set(tools.map((t) => t.function?.name));
|
|
8967
|
+
const sanitizeProperty = (p) => {
|
|
8968
|
+
const prop = p ?? {};
|
|
8969
|
+
const t = prop.type;
|
|
8970
|
+
if (t === "string" || t === "number" || t === "integer" || t === "boolean") {
|
|
8971
|
+
const out = { type: t };
|
|
8972
|
+
if (typeof prop.description === "string") out.description = prop.description;
|
|
8973
|
+
if (Array.isArray(prop.enum)) out.enum = prop.enum;
|
|
8974
|
+
return out;
|
|
8975
|
+
}
|
|
8976
|
+
if (t === "array") {
|
|
8977
|
+
return {
|
|
8978
|
+
type: "array",
|
|
8979
|
+
items: sanitizeProperty(prop.items),
|
|
8980
|
+
...typeof prop.description === "string" ? { description: prop.description } : {}
|
|
8981
|
+
};
|
|
8982
|
+
}
|
|
8983
|
+
if (t === "object") {
|
|
8984
|
+
const props = prop.properties ?? {};
|
|
8985
|
+
const out = {};
|
|
8986
|
+
for (const [k, v] of Object.entries(props)) out[k] = sanitizeProperty(v);
|
|
8987
|
+
return {
|
|
8988
|
+
type: "object",
|
|
8989
|
+
properties: out,
|
|
8990
|
+
...Array.isArray(prop.required) ? { required: prop.required.filter((r) => typeof r === "string" && r in out) } : {},
|
|
8991
|
+
...typeof prop.description === "string" ? { description: prop.description } : {}
|
|
8992
|
+
};
|
|
8993
|
+
}
|
|
8994
|
+
return {
|
|
8995
|
+
type: "string",
|
|
8996
|
+
...typeof prop.description === "string" ? { description: prop.description } : {}
|
|
8997
|
+
};
|
|
8998
|
+
};
|
|
8999
|
+
const sanitizeSchema = (schema) => {
|
|
9000
|
+
const s = schema ?? { type: "object", properties: {} };
|
|
9001
|
+
if (s.type !== void 0 && s.type !== "object") return null;
|
|
9002
|
+
const sanitized = sanitizeProperty({ ...s, type: "object" });
|
|
9003
|
+
return sanitized;
|
|
9004
|
+
};
|
|
9005
|
+
for (const srv of servers) {
|
|
9006
|
+
const sname = srv.name ?? srv.serverInfo?.name;
|
|
9007
|
+
if (!sname || srv.error || !Array.isArray(srv.tools)) continue;
|
|
9008
|
+
for (const mt of srv.tools) {
|
|
9009
|
+
const pname = `${sname}_${mt.name}`;
|
|
9010
|
+
if (have.has(pname)) continue;
|
|
9011
|
+
const parameters = sanitizeSchema(mt.inputSchema);
|
|
9012
|
+
if (!parameters) {
|
|
9013
|
+
console.log(`[FlowEngine] mcp projection: skipped ${pname} (non-object schema)`);
|
|
9014
|
+
continue;
|
|
9015
|
+
}
|
|
9016
|
+
tools.push({
|
|
9017
|
+
type: "function",
|
|
9018
|
+
function: {
|
|
9019
|
+
name: pname,
|
|
9020
|
+
description: mt.description || `${mt.name} via the ${sname} MCP server`,
|
|
9021
|
+
parameters
|
|
9022
|
+
}
|
|
9023
|
+
});
|
|
9024
|
+
have.add(pname);
|
|
9025
|
+
}
|
|
9026
|
+
}
|
|
9027
|
+
console.log(`[FlowEngine] mcp projection: ${tools.length} tools after catalog merge`);
|
|
9028
|
+
} catch {
|
|
9029
|
+
}
|
|
8866
9030
|
console.log(`[FlowEngine] getToolsForPrompt result: ${tools.length} tools loaded for prompt ${promptData.name}`);
|
|
8867
9031
|
return tools;
|
|
8868
9032
|
} catch (error) {
|
|
@@ -15586,6 +15750,25 @@ var migration34 = {
|
|
|
15586
15750
|
var migrations = [migration, migration2, migration3, migration4, migration5, migration6, migration7, migration8, migration9, migration10, migration11, migration12, migration13, migration14, migration15, migration16, migration17, migration18, migration19, migration20, migration21, migration22, migration23, migration24, migration25, migration26, migration27, migration28, migration29, migration30, migration31, migration32, migration33, migration34];
|
|
15587
15751
|
var LATEST_SCHEMA_VERSION = migrations.length;
|
|
15588
15752
|
|
|
15753
|
+
// src/durable-objects/subagent-reconcile.ts
|
|
15754
|
+
var CHILD_STALE_AFTER_MS = 5 * 6e4;
|
|
15755
|
+
var CHILD_AUDIT_MIN_INTERVAL_MS = 6e4;
|
|
15756
|
+
var CHILD_AUDIT_MAX_PER_SWEEP = 4;
|
|
15757
|
+
var SETTLED_STATUSES = /* @__PURE__ */ new Set(["idle", "terminated"]);
|
|
15758
|
+
function isAuditCandidate(entry, nowMs) {
|
|
15759
|
+
if (SETTLED_STATUSES.has(entry.status)) return false;
|
|
15760
|
+
const createdMs = (entry.createdAt ?? 0) / 1e3;
|
|
15761
|
+
return nowMs - createdMs >= CHILD_STALE_AFTER_MS;
|
|
15762
|
+
}
|
|
15763
|
+
function resolveStaleChildStatus(entry, child, nowMs) {
|
|
15764
|
+
if (SETTLED_STATUSES.has(entry.status)) return null;
|
|
15765
|
+
if (!child) return "terminated";
|
|
15766
|
+
if (child.terminated) return "terminated";
|
|
15767
|
+
if (child.executing) return null;
|
|
15768
|
+
if (nowMs - child.lastActivityMs < CHILD_STALE_AFTER_MS) return null;
|
|
15769
|
+
return entry.resumable ? "idle" : "terminated";
|
|
15770
|
+
}
|
|
15771
|
+
|
|
15589
15772
|
// src/durable-objects/DurableThread.ts
|
|
15590
15773
|
init_types();
|
|
15591
15774
|
|
|
@@ -17388,12 +17571,103 @@ var DurableThread = class _DurableThread extends DurableObject {
|
|
|
17388
17571
|
);
|
|
17389
17572
|
const rows = cursor.toArray();
|
|
17390
17573
|
const raw = rows[0]?.value ?? "[]";
|
|
17574
|
+
let entries;
|
|
17391
17575
|
try {
|
|
17392
17576
|
const parsed = JSON.parse(raw);
|
|
17393
|
-
|
|
17577
|
+
entries = Array.isArray(parsed) ? parsed : [];
|
|
17394
17578
|
} catch {
|
|
17395
17579
|
return [];
|
|
17396
17580
|
}
|
|
17581
|
+
return this.reconcileStaleChildren(entries);
|
|
17582
|
+
}
|
|
17583
|
+
/** In-memory throttle/reentrancy guards for the stale-child reconciler. */
|
|
17584
|
+
lastChildAuditAt = 0;
|
|
17585
|
+
childAuditInFlight = false;
|
|
17586
|
+
/**
|
|
17587
|
+
* Lazily heal registry entries stranded at a "working" status. The normal
|
|
17588
|
+
* settlement chain lives only in the parent's `waitUntil`; a parent
|
|
17589
|
+
* eviction/deploy/kill during a child's run leaves the entry at `running`
|
|
17590
|
+
* forever and clients render an eternal spinner. On registry reads, audit
|
|
17591
|
+
* old unsettled entries against the child thread's ACTUAL state and settle
|
|
17592
|
+
* them — conservatively (see subagent-reconcile.ts): resumable children
|
|
17593
|
+
* are never deterministically terminated.
|
|
17594
|
+
*/
|
|
17595
|
+
async reconcileStaleChildren(entries) {
|
|
17596
|
+
const nowMs = Date.now();
|
|
17597
|
+
if (this.childAuditInFlight) return entries;
|
|
17598
|
+
if (nowMs - this.lastChildAuditAt < CHILD_AUDIT_MIN_INTERVAL_MS) return entries;
|
|
17599
|
+
const candidates = entries.filter((entry) => isAuditCandidate(entry, nowMs));
|
|
17600
|
+
if (candidates.length === 0) return entries;
|
|
17601
|
+
this.childAuditInFlight = true;
|
|
17602
|
+
this.lastChildAuditAt = nowMs;
|
|
17603
|
+
try {
|
|
17604
|
+
const agentBuilderId = this.env.AGENT_BUILDER.idFromName("singleton");
|
|
17605
|
+
const agentBuilder = this.env.AGENT_BUILDER.get(agentBuilderId);
|
|
17606
|
+
const changed = [];
|
|
17607
|
+
for (const entry of candidates.slice(0, CHILD_AUDIT_MAX_PER_SWEEP)) {
|
|
17608
|
+
let facts = null;
|
|
17609
|
+
try {
|
|
17610
|
+
const child = await agentBuilder.getThread(entry.reference);
|
|
17611
|
+
facts = child ? {
|
|
17612
|
+
terminated: child.terminated ?? null,
|
|
17613
|
+
executing: child.executing === true,
|
|
17614
|
+
lastActivityMs: Number(child.last_activity_at ?? child.created_at ?? 0) * 1e3
|
|
17615
|
+
} : null;
|
|
17616
|
+
} catch {
|
|
17617
|
+
continue;
|
|
17618
|
+
}
|
|
17619
|
+
const resolution = resolveStaleChildStatus(entry, facts, nowMs);
|
|
17620
|
+
if (resolution) {
|
|
17621
|
+
changed.push({
|
|
17622
|
+
reference: entry.reference,
|
|
17623
|
+
status: resolution,
|
|
17624
|
+
// Settling a live one-shot child to terminated also terminates
|
|
17625
|
+
// the thread itself so registry and reality agree.
|
|
17626
|
+
terminateChild: resolution === "terminated" && facts !== null && !facts.terminated
|
|
17627
|
+
});
|
|
17628
|
+
}
|
|
17629
|
+
}
|
|
17630
|
+
if (changed.length === 0) return entries;
|
|
17631
|
+
const byRef = new Map(changed.map((c) => [c.reference, c]));
|
|
17632
|
+
const healed = entries.map(
|
|
17633
|
+
(entry) => byRef.has(entry.reference) ? { ...entry, status: byRef.get(entry.reference).status } : entry
|
|
17634
|
+
);
|
|
17635
|
+
await this.setChildrenRegistry(healed);
|
|
17636
|
+
for (const c of changed) {
|
|
17637
|
+
if (c.terminateChild) {
|
|
17638
|
+
try {
|
|
17639
|
+
const childId = this.env.AGENT_BUILDER_THREAD.idFromName(c.reference);
|
|
17640
|
+
const childStub = this.env.AGENT_BUILDER_THREAD.get(childId);
|
|
17641
|
+
await childStub.terminateThread?.(c.reference);
|
|
17642
|
+
} catch (error) {
|
|
17643
|
+
console.error("[DurableThread] Stale-child terminate failed (non-fatal):", error);
|
|
17644
|
+
}
|
|
17645
|
+
}
|
|
17646
|
+
await this.broadcastChildStatusChanged(c.reference);
|
|
17647
|
+
}
|
|
17648
|
+
console.log(
|
|
17649
|
+
`[DurableThread] Reconciled ${changed.length} stale subagent entr${changed.length === 1 ? "y" : "ies"}:`,
|
|
17650
|
+
changed.map((c) => `${c.reference.slice(0, 8)}\u2192${c.status}`).join(", ")
|
|
17651
|
+
);
|
|
17652
|
+
return healed;
|
|
17653
|
+
} finally {
|
|
17654
|
+
this.childAuditInFlight = false;
|
|
17655
|
+
}
|
|
17656
|
+
}
|
|
17657
|
+
/**
|
|
17658
|
+
* Child-side registry settlement: called from the CHILD's own DO whenever
|
|
17659
|
+
* a run ends, so the spinner clears even when the parent-held completion
|
|
17660
|
+
* chain died with the parent. Only downgrades a live "working" status to
|
|
17661
|
+
* idle — never clobbers terminated.
|
|
17662
|
+
*/
|
|
17663
|
+
async settleChildRegistryIdle(_threadId, reference) {
|
|
17664
|
+
const entries = await this.getChildrenRegistry("");
|
|
17665
|
+
const entry = entries.find((e) => e.reference === reference);
|
|
17666
|
+
if (!entry || entry.status === "terminated" || entry.status === "idle") return;
|
|
17667
|
+
await this.setChildrenRegistry(
|
|
17668
|
+
entries.map((e) => e.reference === reference ? { ...e, status: "idle" } : e)
|
|
17669
|
+
);
|
|
17670
|
+
await this.broadcastChildStatusChanged(reference);
|
|
17397
17671
|
}
|
|
17398
17672
|
async setChildrenRegistry(entries) {
|
|
17399
17673
|
await this.ctx.storage.sql.exec(
|
|
@@ -17975,6 +18249,33 @@ var DurableThread = class _DurableThread extends DurableObject {
|
|
|
17975
18249
|
* Used by blocking subagent tool calls.
|
|
17976
18250
|
*/
|
|
17977
18251
|
async executeBlocking(threadId, agentId, initial_messages, data) {
|
|
18252
|
+
try {
|
|
18253
|
+
return await this.executeBlockingImpl(threadId, agentId, initial_messages, data);
|
|
18254
|
+
} finally {
|
|
18255
|
+
this.ctx.waitUntil?.(this.settleOwnRegistryEntry(threadId));
|
|
18256
|
+
}
|
|
18257
|
+
}
|
|
18258
|
+
/** Best-effort: mark this child's entry idle in its parent's registry. */
|
|
18259
|
+
async settleOwnRegistryEntry(threadId) {
|
|
18260
|
+
try {
|
|
18261
|
+
const terminatedCursor = await this.ctx.storage.sql.exec(
|
|
18262
|
+
`SELECT value FROM execution_state WHERE key = 'terminated' LIMIT 1`
|
|
18263
|
+
);
|
|
18264
|
+
const terminated = terminatedCursor.toArray()[0]?.value;
|
|
18265
|
+
if (terminated && terminated !== "" && terminated !== "null") return;
|
|
18266
|
+
const agentBuilderId = this.env.AGENT_BUILDER.idFromName("singleton");
|
|
18267
|
+
const agentBuilder = this.env.AGENT_BUILDER.get(agentBuilderId);
|
|
18268
|
+
const meta = await agentBuilder.getThread(threadId);
|
|
18269
|
+
const parent = meta?.parent;
|
|
18270
|
+
if (!parent) return;
|
|
18271
|
+
const parentId = this.env.AGENT_BUILDER_THREAD.idFromName(parent);
|
|
18272
|
+
const parentStub = this.env.AGENT_BUILDER_THREAD.get(parentId);
|
|
18273
|
+
await parentStub.settleChildRegistryIdle?.(parent, threadId);
|
|
18274
|
+
} catch (error) {
|
|
18275
|
+
console.error("[DurableThread] Child-side registry settlement failed (non-fatal):", error);
|
|
18276
|
+
}
|
|
18277
|
+
}
|
|
18278
|
+
async executeBlockingImpl(threadId, agentId, initial_messages, data) {
|
|
17978
18279
|
await this.ensureMigrated();
|
|
17979
18280
|
await this.assertNotTerminated();
|
|
17980
18281
|
let parentThreadId = null;
|
|
@@ -19351,7 +19652,7 @@ ${resultContent}${attachmentSummary}`;
|
|
|
19351
19652
|
`
|
|
19352
19653
|
SELECT
|
|
19353
19654
|
id, message_id, provider, actual_provider, standard_agents_router_used, model, model_name, prompt_name,
|
|
19354
|
-
tools_called, queued_tools, provider_tools, parent_log_id, retry_of_log_id, error, cost_total,
|
|
19655
|
+
tools_called, queued_tools, provider_tools, parent_log_id, retry_of_log_id, error, error_type, cost_total,
|
|
19355
19656
|
input_tokens, cached_tokens, output_tokens, total_tokens,
|
|
19356
19657
|
is_complete, created_at
|
|
19357
19658
|
FROM logs
|
|
@@ -19376,6 +19677,7 @@ ${resultContent}${attachmentSummary}`;
|
|
|
19376
19677
|
parent_log_id: row.parent_log_id,
|
|
19377
19678
|
retry_of_log_id: row.retry_of_log_id,
|
|
19378
19679
|
error: row.error,
|
|
19680
|
+
error_type: row.error_type,
|
|
19379
19681
|
cost_total: row.cost_total,
|
|
19380
19682
|
input_tokens: row.input_tokens,
|
|
19381
19683
|
cached_tokens: row.cached_tokens,
|