@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.
Files changed (53) hide show
  1. package/dist/built-in-routes.js +3278 -2139
  2. package/dist/built-in-routes.js.map +1 -1
  3. package/dist/client/{ApiKeysView-CnybtFho.js → ApiKeysView-CxelZw61.js} +1 -1
  4. package/dist/client/CenteredContentView-CeQNRQH8.js +1 -0
  5. package/dist/client/CompositionView-YO0nHsYV.js +32 -0
  6. 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
  7. 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
  8. 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
  9. package/dist/client/{JsonViewer-w11hvBiv.js → JsonViewer-71rdOpyq.js} +1 -1
  10. package/dist/client/{LoginView-BhkGzCFE.js → LoginView-CkDpPh8U.js} +1 -1
  11. package/dist/client/{MarketplaceView-yZXHH-T4.js → MarketplaceView-UYrMBLon.js} +1 -1
  12. 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
  13. 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
  14. package/dist/client/{ModelsView-C4xTc0Ut.js → ModelsView-DKYzp2fJ.js} +1 -1
  15. package/dist/client/{PromptEditView-B1TvKsvK.js → PromptEditView-BlYHZ0ao.js} +1 -1
  16. package/dist/client/{PromptModal-C3CMojNY.js → PromptModal-B1neRzSc.js} +1 -1
  17. package/dist/client/{PromptsView-cnbYo7GZ.js → PromptsView-C0Ez74j0.js} +1 -1
  18. package/dist/client/{ProvidersView-01sjKjFL.js → ProvidersView-CFc4K0IC.js} +1 -1
  19. package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-CXbSQo2-.js +23 -0
  20. package/dist/client/{ThreadsView-BLmcRVRx.js → ThreadsView-B1hFXL-4.js} +1 -1
  21. package/dist/client/{ToolsView-HCxNKC5q.js → ToolsView-B3KqeOZD.js} +1 -1
  22. 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
  23. package/dist/client/{UsersView-BDAOlNJQ.js → UsersView-CF1tomjI.js} +1 -1
  24. package/dist/client/{VariablesView-Co_hp_tq.js → VariablesView-CP0TDspK.js} +1 -1
  25. package/dist/client/assets/{ThreadInspectorPane-G2muXE6J.css → ThreadInspectorPane-2QOWOtet.css} +1 -1
  26. package/dist/client/{check-pGlck8qX.js → check-DeHZQcv4.js} +1 -1
  27. package/dist/client/{chevron-right-FpPE1Obh.js → chevron-right-C8Mb0B59.js} +1 -1
  28. package/dist/client/{copy-Dt1FLh3s.js → copy-BxJsl-KZ.js} +1 -1
  29. package/dist/client/{formkit-DcZQH9-p.js → formkit-0eyyCEP_.js} +1 -1
  30. package/dist/client/{index-CU9i-w9T.js → index-BTs3PMFs.js} +3 -3
  31. package/dist/client/index.html +3 -3
  32. package/dist/client/{package-DSNwOrcN.js → package-B9czwyIu.js} +1 -1
  33. package/dist/client/{plus-D0GkkdA7.js → plus-DqtuqJFm.js} +1 -1
  34. package/dist/client/timeAgo-CDt-vAhI.js +1 -0
  35. package/dist/client/{useActionFeedback-Dxh_Xp0q.js → useActionFeedback-B6UfBJ7l.js} +1 -1
  36. package/dist/client/{vue-KXHVRwln.js → vue-Dw7WLX4c.js} +1 -1
  37. package/dist/{index-DP9GxPHu.d.ts → index-DUIfQjBW.d.ts} +3 -0
  38. package/dist/index.d.ts +1 -1
  39. package/dist/index.js +322 -13
  40. package/dist/index.js.map +1 -1
  41. package/dist/plugin.d.ts +1 -1
  42. package/dist/plugin.js +7 -0
  43. package/dist/plugin.js.map +1 -1
  44. package/dist/runtime.d.ts +26 -2
  45. package/dist/runtime.js +315 -13
  46. package/dist/runtime.js.map +1 -1
  47. package/dist/test.d.ts +1 -1
  48. package/package.json +25 -25
  49. package/LICENSE.txt +0 -48
  50. package/dist/client/CenteredContentView-Ch18yAzL.js +0 -1
  51. package/dist/client/CompositionView-Ctlbn0vj.js +0 -32
  52. package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-BiimzVFD.js +0 -22
  53. package/dist/client/timeAgo-X3Xeq5Kz.js +0 -1
@@ -1040,6 +1040,7 @@ interface Env extends ThreadEnv {
1040
1040
  OPENROUTER_API_KEY?: string;
1041
1041
  GOOGLE_API_KEY?: string;
1042
1042
  NOVITA_API_KEY?: string;
1043
+ DEEPINFRA_API_KEY?: string;
1043
1044
  XAI_API_KEY?: string;
1044
1045
  UI_DEV_SERVER?: string;
1045
1046
  ASSETS?: {
@@ -1162,6 +1163,8 @@ interface LogEntry {
1162
1163
  parent_log_id: string | null;
1163
1164
  retry_of_log_id: string | null;
1164
1165
  error: string | null;
1166
+ /** Machine error classification ('user_interrupted' = stop, not failure). */
1167
+ error_type?: string | null;
1165
1168
  cost_total: number | null;
1166
1169
  is_complete: number;
1167
1170
  created_at: number;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ModelDefinition, AgentDefinition } from './runtime.js';
2
2
  export { AgentBuilderEnv, AuthContext, AuthUser, BroadcastOptions, CodeExecutionBridge, DurableAgentBuilder, DurableThread, DurableUserHub, FlowStateSdk, FlowStateWithSdk, HubClientInfo, ImageContextConfig, InjectMessageOptions, LLMProviderInterface, NamespaceResolutionError, PromptContent, PromptDefinition, PromptIncludePart, PromptPart, PromptToolConfig, Provider, ProviderContentPart, ProviderFilePart, ProviderImagePart, ProviderRegistry, ProviderTextPart, SessionToolBinding, SessionToolConfig, SideConfig, SubagentToolConfig, SubpromptConfig, ThreadRegistryEntry, ThreadWatchdog, ThreadWatchdogState, ToolConfig, UpdateThreadParams, User, WatchdogCheckin, WatchdogProbeResult, authenticate, buildImageDescription, cat, createNamespaceContext, emitThreadEvent, enhanceFlowState, exists, find, forceTurn, generateImageDescription, getFileStats, getMessages, getMessagesToSummarize, getShortName, getThumbnail, getUnsummarizedImageAttachments, getVisibleAgentNames, getVisibleModelNames, getVisiblePromptNames, getVisibleToolNames, grep, hasImageAttachments, head, injectMessage, isQualifiedName, linkFile, mkdir, move, optimizeImageContext, parseQualifiedName, qualifyName, queueTool, readFile, readdir, reloadHistory, rename, replaceImagesWithDescriptions, requireAdmin, requireAuth, resolveAgent, resolveHook, resolveModel, resolvePrompt, resolveTool, rmdir, stat, tail, unlink, updateThread, writeFile, writeImage } from './runtime.js';
3
3
  export { AgentPluginOptions, agentbuilder, builder } from './plugin.js';
4
- export { A as Agent, x as AttachmentRef, f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, o as ClientDuplex, p as ClientForwarding, m as ClientStreamRequest, n as ClientStreamResponse, k as ClientToolRequest, l as ClientToolResponse, B as Controller, a as ControllerContext, E as Env, w as FileRecord, y as FileStats, u as FlowResult, F as FlowState, G as GrepResult, D as ImageContentPart, I as ImageMetadata, L as LLMResponse, M as Message, J as MessageContent, H as MultimodalContent, R as RequestContext, S as StorageBackend, v as TelemetryEvent, z as TextContentPart, b as ThreadEndpointContext, e as ThreadEnv, q as ThreadInstance, r as ThreadMetadata, T as ToolCall, t as ToolResult, g as callClient, h as callClientStream, c as createThreadEndpointHandler, j as decodeStreamChunk, d as defineController, i as encodeStreamChunk, s as supportsClientForwarding } from './index-DP9GxPHu.js';
4
+ export { A as Agent, x as AttachmentRef, f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, o as ClientDuplex, p as ClientForwarding, m as ClientStreamRequest, n as ClientStreamResponse, k as ClientToolRequest, l as ClientToolResponse, B as Controller, a as ControllerContext, E as Env, w as FileRecord, y as FileStats, u as FlowResult, F as FlowState, G as GrepResult, D as ImageContentPart, I as ImageMetadata, L as LLMResponse, M as Message, J as MessageContent, H as MultimodalContent, R as RequestContext, S as StorageBackend, v as TelemetryEvent, z as TextContentPart, b as ThreadEndpointContext, e as ThreadEnv, q as ThreadInstance, r as ThreadMetadata, T as ToolCall, t as ToolResult, 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';
5
5
  export { AgentType, DefinitionLoader, GlobalNamespaceContext, HookSignatures, ImageContent, ModelCapabilities, ModelProvider, NamespaceContext, PackageSignature, PackedExports, PackedMeta, PackedMetadata, PackedNamespaceContext, PromptInput, PromptTextPart, ProviderAssistantMessage, ProviderConfigSlot, ProviderConfigSlots, ProviderConfigValueSource, ProviderDefinition, ProviderError, ProviderErrorCode, ProviderFactory, ProviderFactoryConfig, ProviderFinishReason, ProviderGeneratedImage, ProviderMessage, ProviderMessageContent, ProviderMethodOverrides, ModelCapabilities as ProviderModelCapabilities, ProviderOverride, ProviderOverrideContext, ProviderReasoningDetail, ProviderRequest, ProviderResponse, ProviderStreamChunk, ProviderSyncOverride, ProviderSystemMessage, ProviderTool, ProviderToolCallPart, ProviderToolMessage, ProviderToolResultContent, ProviderUsage, ProviderUserMessage, ReasoningConfig, StructuredPrompt, TextContent, Tool, ToolArgs, ToolArgsNode, ToolArgsRawShape, ToolContent, belongsToPackage, defineAgent, defineHook, defineModel, definePrompt, defineProvider, defineTool, isPacked, isVisibleInNamespace, mapReasoningLevel, providerConst, providerEnv, providerValue } from '@standardagents/spec';
6
6
  export { C as ConstituentItem, D as DiscoveredPackage, N as NamespacedRegistry, P as PackingAnalysis, a as PackingOptions, b as PackingResult, c as UnpackOptions, d as UnpackResult } from './types-Bpe7IANZ.js';
7
7
  export { D as DiscoveryConfig, P as PackageDiscoveryService, d as discoverPackages } from './discovery-DiMJWisl.js';
package/dist/index.js CHANGED
@@ -940,12 +940,23 @@ function resolvePlatformRouting(providerName, env) {
940
940
  baseUrl: `${origin}/v1/proxy/${encodeURIComponent(provider)}${basePath}`
941
941
  };
942
942
  }
943
+ function platformProviderFactoryConfig(providerName, routing) {
944
+ const config = {
945
+ apiKey: routing.apiKey,
946
+ baseUrl: routing.baseUrl
947
+ };
948
+ if (providerName.toLowerCase() === "deepinfra") {
949
+ config.modelsUrl = `${routing.origin}/v1/proxy/deepinfra/models`;
950
+ }
951
+ return config;
952
+ }
943
953
  var DEFAULT_PLATFORM_PROXY_ORIGIN, PROVIDER_BASE_PATHS;
944
954
  var init_platform_routing = __esm({
945
955
  "src/agents/providers/platform-routing.ts"() {
946
956
  DEFAULT_PLATFORM_PROXY_ORIGIN = "https://api.standardagents.ai";
947
957
  PROVIDER_BASE_PATHS = {
948
- cloudflare: "/ai/v1"
958
+ cloudflare: "/ai/v1",
959
+ deepinfra: "/openai"
949
960
  };
950
961
  }
951
962
  });
@@ -1238,10 +1249,7 @@ var init_ProviderRegistry = __esm({
1238
1249
  }
1239
1250
  const routing = resolvePlatformRouting(providerName, env);
1240
1251
  if (routing) {
1241
- const config = {
1242
- apiKey: routing.apiKey,
1243
- baseUrl: routing.baseUrl
1244
- };
1252
+ const config = platformProviderFactoryConfig(providerName, routing);
1245
1253
  registerPlatformProxyOrigin(routing.origin);
1246
1254
  const fingerprint = this.getProviderFingerprint(`platform:${providerName}`, modelDef, config);
1247
1255
  const cached = this.providerCache.get(modelName);
@@ -1277,6 +1285,7 @@ var init_ProviderRegistry = __esm({
1277
1285
  google: "GOOGLE_API_KEY",
1278
1286
  groq: "GROQ_API_KEY",
1279
1287
  novita: "NOVITA_API_KEY",
1288
+ deepinfra: "DEEPINFRA_API_KEY",
1280
1289
  openai: "OPENAI_API_KEY",
1281
1290
  openrouter: "OPENROUTER_API_KEY",
1282
1291
  anthropic: "ANTHROPIC_API_KEY",
@@ -1714,7 +1723,9 @@ function buildRequestBody(context, modelDef) {
1714
1723
  messages: requestMessages,
1715
1724
  tools,
1716
1725
  toolChoice,
1717
- parallelToolCalls: supportsToolCalls ? context.parallel_tool_calls : void 0,
1726
+ // null (prompt didn't set it) normalizes to undefined so providers omit
1727
+ // the wire param entirely and their default applies (2026-08-04).
1728
+ parallelToolCalls: supportsToolCalls ? context.parallel_tool_calls ?? void 0 : void 0,
1718
1729
  reasoning: context.reasoning ? {
1719
1730
  level: reasoningEffortToLevel(context.reasoning.effort),
1720
1731
  maxTokens: context.reasoning.max_tokens,
@@ -1833,6 +1844,9 @@ var init_LLMRequest = __esm({
1833
1844
  try {
1834
1845
  return await this.tryModel(context, state, context.model, startTime, void 0);
1835
1846
  } catch (primaryError) {
1847
+ if (primaryError?._userStop) {
1848
+ throw primaryError;
1849
+ }
1836
1850
  console.error(`Primary model ${context.model} failed:`, primaryError);
1837
1851
  lastFailedLogId = primaryError?._lastLogId;
1838
1852
  state.emitTelemetry?.({
@@ -1859,6 +1873,9 @@ var init_LLMRequest = __esm({
1859
1873
  lastFailedLogId
1860
1874
  );
1861
1875
  } catch (fallbackError) {
1876
+ if (fallbackError?._userStop) {
1877
+ throw fallbackError;
1878
+ }
1862
1879
  console.error(
1863
1880
  `Fallback model ${fallback.fallback_model_id} failed:`,
1864
1881
  fallbackError
@@ -1948,9 +1965,24 @@ var init_LLMRequest = __esm({
1948
1965
  this.fireAsyncMetadataFetch(response, state, logId);
1949
1966
  return { response, logId };
1950
1967
  } catch (error2) {
1968
+ if (state.abortController?.signal?.aborted) {
1969
+ await this.logError(
1970
+ state,
1971
+ new Error("Interrupted by user"),
1972
+ "user_interrupted",
1973
+ actualModelId,
1974
+ startTime,
1975
+ logId
1976
+ );
1977
+ const stopError = new Error("aborted");
1978
+ stopError._lastLogId = logId;
1979
+ stopError._userStop = true;
1980
+ throw stopError;
1981
+ }
1951
1982
  console.error(`Error calling ${actualModelId} (attempt ${attempts}):`, error2);
1952
1983
  await this.logError(state, error2, "api_error", actualModelId, startTime, logId);
1953
- if (attempts < MAX_RETRIES_PER_MODEL) {
1984
+ const isStallTimeout = error2?.code === "timeout";
1985
+ if (attempts < MAX_RETRIES_PER_MODEL && !isStallTimeout) {
1954
1986
  const base = BACKOFF_BASE * Math.pow(2, attempts - 1);
1955
1987
  const retryAfterMs = typeof error2?.retryAfter === "number" ? error2.retryAfter * 1e3 : 0;
1956
1988
  const backoffMs = Math.max(base, retryAfterMs);
@@ -3858,7 +3890,7 @@ __export(ToolExecutor_exports, {
3858
3890
  function getPackageId(state) {
3859
3891
  return state.namespaceContext.type === "packed" ? state.namespaceContext.packageId : void 0;
3860
3892
  }
3861
- var SUBAGENT_CREATE_TOOL, SUBAGENT_MESSAGE_TOOL, LEGACY_SEND_TO_AGENT_TOOL, INTERNAL_SCOPED_ENV_ARGUMENT, INTERNAL_SCOPED_ENV_CONTEXT_KEY, ToolExecutor;
3893
+ 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;
3862
3894
  var init_ToolExecutor = __esm({
3863
3895
  "src/agents/ToolExecutor.ts"() {
3864
3896
  init_types();
@@ -3866,6 +3898,7 @@ var init_ToolExecutor = __esm({
3866
3898
  init_sessionTools();
3867
3899
  SUBAGENT_CREATE_TOOL = "subagent_create";
3868
3900
  SUBAGENT_MESSAGE_TOOL = "subagent_message";
3901
+ SUBAGENTS_LIST_TOOL = "subagents";
3869
3902
  LEGACY_SEND_TO_AGENT_TOOL = "send_to_agent";
3870
3903
  INTERNAL_SCOPED_ENV_ARGUMENT = "__scoped_env";
3871
3904
  INTERNAL_SCOPED_ENV_CONTEXT_KEY = "__immediate_scoped_env_by_call_id";
@@ -4024,6 +4057,33 @@ var init_ToolExecutor = __esm({
4024
4057
  * Execute a single tool call
4025
4058
  */
4026
4059
  static async executeToolCall(call, state, toolMessageId) {
4060
+ try {
4061
+ const n = call.function?.name;
4062
+ if (n && n.includes("_") && n !== "mcp") {
4063
+ const cat2 = await state.thread.instance.getValue("mcp_catalog");
4064
+ for (const srv of cat2?.servers ?? []) {
4065
+ const sname = srv.name ?? srv.serverInfo?.name;
4066
+ if (!sname || !n.startsWith(`${sname}_`)) continue;
4067
+ const mtool = n.slice(sname.length + 1);
4068
+ if (!Array.isArray(srv.tools) || !srv.tools.some((t) => t.name === mtool)) continue;
4069
+ call = {
4070
+ ...call,
4071
+ function: {
4072
+ ...call.function,
4073
+ name: "mcp",
4074
+ arguments: JSON.stringify({
4075
+ action: "call",
4076
+ server: sname,
4077
+ tool: mtool,
4078
+ arguments_json: call.function.arguments || "{}"
4079
+ })
4080
+ }
4081
+ };
4082
+ break;
4083
+ }
4084
+ }
4085
+ } catch {
4086
+ }
4027
4087
  const toolType = await this.identifyToolType(call, state);
4028
4088
  switch (toolType) {
4029
4089
  case "native":
@@ -4073,7 +4133,7 @@ var init_ToolExecutor = __esm({
4073
4133
  */
4074
4134
  static async identifyToolType(call, state) {
4075
4135
  const toolName = call.function.name;
4076
- if (toolName === SUBAGENT_CREATE_TOOL || toolName === SUBAGENT_MESSAGE_TOOL || toolName === LEGACY_SEND_TO_AGENT_TOOL) {
4136
+ if (toolName === SUBAGENT_CREATE_TOOL || toolName === SUBAGENT_MESSAGE_TOOL || toolName === SUBAGENTS_LIST_TOOL || toolName === LEGACY_SEND_TO_AGENT_TOOL) {
4077
4137
  return "agent";
4078
4138
  }
4079
4139
  if (state.allowedTools) {
@@ -4606,6 +4666,22 @@ ${errorLines.join("\n")}`);
4606
4666
  if (builtinSubagentAction === "message") {
4607
4667
  return await this.executeSubagentMessageTool(call, state);
4608
4668
  }
4669
+ if (call.function.name === SUBAGENTS_LIST_TOOL) {
4670
+ const { FlowEngine: FlowEngine2 } = await Promise.resolve().then(() => (init_FlowEngine(), FlowEngine_exports));
4671
+ const registry = await FlowEngine2.listModelVisibleSubagents(state);
4672
+ if (registry.length === 0) {
4673
+ return { status: "success", result: "No active subagent instances." };
4674
+ }
4675
+ const lines = registry.map(
4676
+ (entry) => `- ${entry.reference}: ${entry.name} \u2014 ${entry.status ?? "unknown"}${entry.description ? ` (${entry.description})` : ""}`
4677
+ );
4678
+ return {
4679
+ status: "success",
4680
+ result: `Active subagent instances:
4681
+ ${lines.join("\n")}
4682
+ Message one with subagent_message(referenceId, message).`
4683
+ };
4684
+ }
4609
4685
  const createArgs = builtinSubagentAction === "create" ? this.parseSubagentCreateArgs(call.function.arguments) : null;
4610
4686
  if (createArgs?.error) {
4611
4687
  return { status: "error", error: createArgs.error };
@@ -6928,7 +7004,10 @@ This usually points to something I can't fix from here \u2014 for example the wo
6928
7004
  model: def.model,
6929
7005
  include_chat: def.includeChat ?? false,
6930
7006
  include_past_tools: def.includePastTools ?? false,
6931
- parallel_tool_calls: def.parallelToolCalls ?? false,
7007
+ // Unset stays unset (2026-08-04): defaulting to `false` forbade the
7008
+ // parallel batching agentic-tuned models are trained on; absent lets
7009
+ // the provider default apply, while an explicit prompt value is honored.
7010
+ parallel_tool_calls: def.parallelToolCalls ?? null,
6932
7011
  tool_choice: def.toolChoice ?? "auto",
6933
7012
  reasoning_effort: def.reasoning?.effort ?? null,
6934
7013
  reasoning_max_tokens: def.reasoning?.maxTokens ?? null,
@@ -8210,6 +8289,13 @@ This usually points to something I can't fix from here \u2014 for example the wo
8210
8289
  if (hidden.size === 0) return registry;
8211
8290
  return registry.filter((entry) => !hidden.has(entry.name));
8212
8291
  }
8292
+ /** Public snapshot for the `subagents` built-in tool (ToolExecutor). */
8293
+ static async listModelVisibleSubagents(state) {
8294
+ return _FlowEngine.filterModelVisibleSubagents(
8295
+ await this.getSubagentRegistry(state),
8296
+ state.prompt?._tools
8297
+ );
8298
+ }
8213
8299
  static async getSubagentRegistry(state) {
8214
8300
  if (typeof state.thread.instance.getChildrenRegistry === "function") {
8215
8301
  try {
@@ -8479,7 +8565,8 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
8479
8565
  await this.getSubagentRegistry(state),
8480
8566
  state.prompt?._tools
8481
8567
  );
8482
- if (subagentRegistry.length > 0) {
8568
+ const suppressRegistryMessage = Array.isArray(state.prompt?.hooks) ? state.prompt.hooks.includes("append_static_session_env") : false;
8569
+ if (subagentRegistry.length > 0 && !suppressRegistryMessage) {
8483
8570
  const fallbackNameMap = await this.resolveRegistryThreadNameMap(state, subagentRegistry);
8484
8571
  const lines = subagentRegistry.map((entry) => {
8485
8572
  const threadName = this.getRegistryThreadName(entry) ?? fallbackNameMap.get(entry.reference) ?? null;
@@ -8838,6 +8925,16 @@ ${lines.join("\n\n")}`
8838
8925
  }
8839
8926
  if (resumablePromptSubagents.length > 0 && !tools.some((tool) => tool.function.name === "subagent_create")) {
8840
8927
  tools.push(this.buildSubagentCreateTool(resumablePromptSubagents));
8928
+ if (!tools.some((tool) => tool.function.name === "subagents")) {
8929
+ tools.push({
8930
+ type: "function",
8931
+ function: {
8932
+ name: "subagents",
8933
+ 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.",
8934
+ parameters: { type: "object", properties: {} }
8935
+ }
8936
+ });
8937
+ }
8841
8938
  }
8842
8939
  const hasActiveResumable = childrenRegistry.some(
8843
8940
  (entry) => entry.status !== "terminated"
@@ -8872,6 +8969,73 @@ ${lines.join("\n\n")}`
8872
8969
  }
8873
8970
  });
8874
8971
  }
8972
+ try {
8973
+ const cat2 = await state.thread.instance.getValue("mcp_catalog");
8974
+ const servers = cat2?.servers ?? [];
8975
+ const have = new Set(tools.map((t) => t.function?.name));
8976
+ const sanitizeProperty = (p) => {
8977
+ const prop = p ?? {};
8978
+ const t = prop.type;
8979
+ if (t === "string" || t === "number" || t === "integer" || t === "boolean") {
8980
+ const out = { type: t };
8981
+ if (typeof prop.description === "string") out.description = prop.description;
8982
+ if (Array.isArray(prop.enum)) out.enum = prop.enum;
8983
+ return out;
8984
+ }
8985
+ if (t === "array") {
8986
+ return {
8987
+ type: "array",
8988
+ items: sanitizeProperty(prop.items),
8989
+ ...typeof prop.description === "string" ? { description: prop.description } : {}
8990
+ };
8991
+ }
8992
+ if (t === "object") {
8993
+ const props = prop.properties ?? {};
8994
+ const out = {};
8995
+ for (const [k, v] of Object.entries(props)) out[k] = sanitizeProperty(v);
8996
+ return {
8997
+ type: "object",
8998
+ properties: out,
8999
+ ...Array.isArray(prop.required) ? { required: prop.required.filter((r) => typeof r === "string" && r in out) } : {},
9000
+ ...typeof prop.description === "string" ? { description: prop.description } : {}
9001
+ };
9002
+ }
9003
+ return {
9004
+ type: "string",
9005
+ ...typeof prop.description === "string" ? { description: prop.description } : {}
9006
+ };
9007
+ };
9008
+ const sanitizeSchema = (schema) => {
9009
+ const s = schema ?? { type: "object", properties: {} };
9010
+ if (s.type !== void 0 && s.type !== "object") return null;
9011
+ const sanitized = sanitizeProperty({ ...s, type: "object" });
9012
+ return sanitized;
9013
+ };
9014
+ for (const srv of servers) {
9015
+ const sname = srv.name ?? srv.serverInfo?.name;
9016
+ if (!sname || srv.error || !Array.isArray(srv.tools)) continue;
9017
+ for (const mt of srv.tools) {
9018
+ const pname = `${sname}_${mt.name}`;
9019
+ if (have.has(pname)) continue;
9020
+ const parameters = sanitizeSchema(mt.inputSchema);
9021
+ if (!parameters) {
9022
+ console.log(`[FlowEngine] mcp projection: skipped ${pname} (non-object schema)`);
9023
+ continue;
9024
+ }
9025
+ tools.push({
9026
+ type: "function",
9027
+ function: {
9028
+ name: pname,
9029
+ description: mt.description || `${mt.name} via the ${sname} MCP server`,
9030
+ parameters
9031
+ }
9032
+ });
9033
+ have.add(pname);
9034
+ }
9035
+ }
9036
+ console.log(`[FlowEngine] mcp projection: ${tools.length} tools after catalog merge`);
9037
+ } catch {
9038
+ }
8875
9039
  console.log(`[FlowEngine] getToolsForPrompt result: ${tools.length} tools loaded for prompt ${promptData.name}`);
8876
9040
  return tools;
8877
9041
  } catch (error) {
@@ -15294,6 +15458,12 @@ var FIRST_PARTY_PROVIDERS = [
15294
15458
  label: "Cerebras",
15295
15459
  envKeys: ["CEREBRAS_API_KEY"]
15296
15460
  },
15461
+ {
15462
+ name: "deepinfra",
15463
+ package: "@standardagents/deepinfra",
15464
+ label: "DeepInfra",
15465
+ envKeys: ["DEEPINFRA_API_KEY"]
15466
+ },
15297
15467
  {
15298
15468
  name: "google",
15299
15469
  package: "@standardagents/google",
@@ -22399,6 +22569,7 @@ var firstPartyProviderPackages = [
22399
22569
  "@standardagents/anthropic",
22400
22570
  "@standardagents/cloudflare",
22401
22571
  "@standardagents/cerebras",
22572
+ "@standardagents/deepinfra",
22402
22573
  "@standardagents/google",
22403
22574
  "@standardagents/groq",
22404
22575
  "@standardagents/novita",
@@ -23995,6 +24166,25 @@ var migration34 = {
23995
24166
  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];
23996
24167
  var LATEST_SCHEMA_VERSION = migrations.length;
23997
24168
 
24169
+ // src/durable-objects/subagent-reconcile.ts
24170
+ var CHILD_STALE_AFTER_MS = 5 * 6e4;
24171
+ var CHILD_AUDIT_MIN_INTERVAL_MS = 6e4;
24172
+ var CHILD_AUDIT_MAX_PER_SWEEP = 4;
24173
+ var SETTLED_STATUSES = /* @__PURE__ */ new Set(["idle", "terminated"]);
24174
+ function isAuditCandidate(entry, nowMs) {
24175
+ if (SETTLED_STATUSES.has(entry.status)) return false;
24176
+ const createdMs = (entry.createdAt ?? 0) / 1e3;
24177
+ return nowMs - createdMs >= CHILD_STALE_AFTER_MS;
24178
+ }
24179
+ function resolveStaleChildStatus(entry, child, nowMs) {
24180
+ if (SETTLED_STATUSES.has(entry.status)) return null;
24181
+ if (!child) return "terminated";
24182
+ if (child.terminated) return "terminated";
24183
+ if (child.executing) return null;
24184
+ if (nowMs - child.lastActivityMs < CHILD_STALE_AFTER_MS) return null;
24185
+ return entry.resumable ? "idle" : "terminated";
24186
+ }
24187
+
23998
24188
  // src/durable-objects/DurableThread.ts
23999
24189
  init_types();
24000
24190
 
@@ -25797,12 +25987,103 @@ var DurableThread = class _DurableThread extends DurableObject {
25797
25987
  );
25798
25988
  const rows = cursor.toArray();
25799
25989
  const raw = rows[0]?.value ?? "[]";
25990
+ let entries;
25800
25991
  try {
25801
25992
  const parsed = JSON.parse(raw);
25802
- return Array.isArray(parsed) ? parsed : [];
25993
+ entries = Array.isArray(parsed) ? parsed : [];
25803
25994
  } catch {
25804
25995
  return [];
25805
25996
  }
25997
+ return this.reconcileStaleChildren(entries);
25998
+ }
25999
+ /** In-memory throttle/reentrancy guards for the stale-child reconciler. */
26000
+ lastChildAuditAt = 0;
26001
+ childAuditInFlight = false;
26002
+ /**
26003
+ * Lazily heal registry entries stranded at a "working" status. The normal
26004
+ * settlement chain lives only in the parent's `waitUntil`; a parent
26005
+ * eviction/deploy/kill during a child's run leaves the entry at `running`
26006
+ * forever and clients render an eternal spinner. On registry reads, audit
26007
+ * old unsettled entries against the child thread's ACTUAL state and settle
26008
+ * them — conservatively (see subagent-reconcile.ts): resumable children
26009
+ * are never deterministically terminated.
26010
+ */
26011
+ async reconcileStaleChildren(entries) {
26012
+ const nowMs = Date.now();
26013
+ if (this.childAuditInFlight) return entries;
26014
+ if (nowMs - this.lastChildAuditAt < CHILD_AUDIT_MIN_INTERVAL_MS) return entries;
26015
+ const candidates = entries.filter((entry) => isAuditCandidate(entry, nowMs));
26016
+ if (candidates.length === 0) return entries;
26017
+ this.childAuditInFlight = true;
26018
+ this.lastChildAuditAt = nowMs;
26019
+ try {
26020
+ const agentBuilderId = this.env.AGENT_BUILDER.idFromName("singleton");
26021
+ const agentBuilder = this.env.AGENT_BUILDER.get(agentBuilderId);
26022
+ const changed = [];
26023
+ for (const entry of candidates.slice(0, CHILD_AUDIT_MAX_PER_SWEEP)) {
26024
+ let facts = null;
26025
+ try {
26026
+ const child = await agentBuilder.getThread(entry.reference);
26027
+ facts = child ? {
26028
+ terminated: child.terminated ?? null,
26029
+ executing: child.executing === true,
26030
+ lastActivityMs: Number(child.last_activity_at ?? child.created_at ?? 0) * 1e3
26031
+ } : null;
26032
+ } catch {
26033
+ continue;
26034
+ }
26035
+ const resolution = resolveStaleChildStatus(entry, facts, nowMs);
26036
+ if (resolution) {
26037
+ changed.push({
26038
+ reference: entry.reference,
26039
+ status: resolution,
26040
+ // Settling a live one-shot child to terminated also terminates
26041
+ // the thread itself so registry and reality agree.
26042
+ terminateChild: resolution === "terminated" && facts !== null && !facts.terminated
26043
+ });
26044
+ }
26045
+ }
26046
+ if (changed.length === 0) return entries;
26047
+ const byRef = new Map(changed.map((c) => [c.reference, c]));
26048
+ const healed = entries.map(
26049
+ (entry) => byRef.has(entry.reference) ? { ...entry, status: byRef.get(entry.reference).status } : entry
26050
+ );
26051
+ await this.setChildrenRegistry(healed);
26052
+ for (const c of changed) {
26053
+ if (c.terminateChild) {
26054
+ try {
26055
+ const childId = this.env.AGENT_BUILDER_THREAD.idFromName(c.reference);
26056
+ const childStub = this.env.AGENT_BUILDER_THREAD.get(childId);
26057
+ await childStub.terminateThread?.(c.reference);
26058
+ } catch (error) {
26059
+ console.error("[DurableThread] Stale-child terminate failed (non-fatal):", error);
26060
+ }
26061
+ }
26062
+ await this.broadcastChildStatusChanged(c.reference);
26063
+ }
26064
+ console.log(
26065
+ `[DurableThread] Reconciled ${changed.length} stale subagent entr${changed.length === 1 ? "y" : "ies"}:`,
26066
+ changed.map((c) => `${c.reference.slice(0, 8)}\u2192${c.status}`).join(", ")
26067
+ );
26068
+ return healed;
26069
+ } finally {
26070
+ this.childAuditInFlight = false;
26071
+ }
26072
+ }
26073
+ /**
26074
+ * Child-side registry settlement: called from the CHILD's own DO whenever
26075
+ * a run ends, so the spinner clears even when the parent-held completion
26076
+ * chain died with the parent. Only downgrades a live "working" status to
26077
+ * idle — never clobbers terminated.
26078
+ */
26079
+ async settleChildRegistryIdle(_threadId, reference) {
26080
+ const entries = await this.getChildrenRegistry("");
26081
+ const entry = entries.find((e) => e.reference === reference);
26082
+ if (!entry || entry.status === "terminated" || entry.status === "idle") return;
26083
+ await this.setChildrenRegistry(
26084
+ entries.map((e) => e.reference === reference ? { ...e, status: "idle" } : e)
26085
+ );
26086
+ await this.broadcastChildStatusChanged(reference);
25806
26087
  }
25807
26088
  async setChildrenRegistry(entries) {
25808
26089
  await this.ctx.storage.sql.exec(
@@ -26384,6 +26665,33 @@ var DurableThread = class _DurableThread extends DurableObject {
26384
26665
  * Used by blocking subagent tool calls.
26385
26666
  */
26386
26667
  async executeBlocking(threadId, agentId, initial_messages, data) {
26668
+ try {
26669
+ return await this.executeBlockingImpl(threadId, agentId, initial_messages, data);
26670
+ } finally {
26671
+ this.ctx.waitUntil?.(this.settleOwnRegistryEntry(threadId));
26672
+ }
26673
+ }
26674
+ /** Best-effort: mark this child's entry idle in its parent's registry. */
26675
+ async settleOwnRegistryEntry(threadId) {
26676
+ try {
26677
+ const terminatedCursor = await this.ctx.storage.sql.exec(
26678
+ `SELECT value FROM execution_state WHERE key = 'terminated' LIMIT 1`
26679
+ );
26680
+ const terminated = terminatedCursor.toArray()[0]?.value;
26681
+ if (terminated && terminated !== "" && terminated !== "null") return;
26682
+ const agentBuilderId = this.env.AGENT_BUILDER.idFromName("singleton");
26683
+ const agentBuilder = this.env.AGENT_BUILDER.get(agentBuilderId);
26684
+ const meta = await agentBuilder.getThread(threadId);
26685
+ const parent = meta?.parent;
26686
+ if (!parent) return;
26687
+ const parentId = this.env.AGENT_BUILDER_THREAD.idFromName(parent);
26688
+ const parentStub = this.env.AGENT_BUILDER_THREAD.get(parentId);
26689
+ await parentStub.settleChildRegistryIdle?.(parent, threadId);
26690
+ } catch (error) {
26691
+ console.error("[DurableThread] Child-side registry settlement failed (non-fatal):", error);
26692
+ }
26693
+ }
26694
+ async executeBlockingImpl(threadId, agentId, initial_messages, data) {
26387
26695
  await this.ensureMigrated();
26388
26696
  await this.assertNotTerminated();
26389
26697
  let parentThreadId = null;
@@ -27760,7 +28068,7 @@ ${resultContent}${attachmentSummary}`;
27760
28068
  `
27761
28069
  SELECT
27762
28070
  id, message_id, provider, actual_provider, standard_agents_router_used, model, model_name, prompt_name,
27763
- tools_called, queued_tools, provider_tools, parent_log_id, retry_of_log_id, error, cost_total,
28071
+ tools_called, queued_tools, provider_tools, parent_log_id, retry_of_log_id, error, error_type, cost_total,
27764
28072
  input_tokens, cached_tokens, output_tokens, total_tokens,
27765
28073
  is_complete, created_at
27766
28074
  FROM logs
@@ -27785,6 +28093,7 @@ ${resultContent}${attachmentSummary}`;
27785
28093
  parent_log_id: row.parent_log_id,
27786
28094
  retry_of_log_id: row.retry_of_log_id,
27787
28095
  error: row.error,
28096
+ error_type: row.error_type,
27788
28097
  cost_total: row.cost_total,
27789
28098
  input_tokens: row.input_tokens,
27790
28099
  cached_tokens: row.cached_tokens,