@standardagents/builder 0.41.7 → 0.41.8
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 +48 -39
- package/dist/built-in-routes.js.map +1 -1
- package/dist/{discovery-CIGNVJfG.d.ts → discovery-D5pmuazY.d.ts} +1 -1
- package/dist/{index-PSu6cMEz.d.ts → index-ChHAVogf.d.ts} +2 -2
- package/dist/index.d.ts +5 -5
- package/dist/index.js +88 -11
- package/dist/index.js.map +1 -1
- package/dist/packing.d.ts +3 -3
- package/dist/plugin.js +9 -1
- package/dist/plugin.js.map +1 -1
- package/dist/resolver-BMZAzKD3.d.ts +4522 -0
- package/dist/runtime.d.ts +10 -4519
- package/dist/runtime.js +80 -11
- package/dist/runtime.js.map +1 -1
- package/dist/test.d.ts +2 -2
- package/dist/{types-D1ABHvAH.d.ts → types-Dhd0M369.d.ts} +1 -1
- package/package.json +5 -5
package/dist/runtime.d.ts
CHANGED
|
@@ -1,4526 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
export { A as AuthUser,
|
|
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, ReasoningConfig, HumanSide as HumanSide$1, SubagentRelationship as SubagentRelationship$1, ParentHookRequirement, LLMProviderInterface, ContentPart, TextPart, ImagePart, FilePart, ThreadState, NamespaceContext, DefinitionLoader } from '@standardagents/spec';
|
|
1
|
+
export { m as AgentBuilderEnv, n as AgentBuilderEvent, A as AgentDefinition, ah as BroadcastOptions, C as CodeExecutionBridge, h as DurableAgentBuilder, D as DurableThread, l as DurableUserHub, af as FlowStateSdk, ai as FlowStateWithSdk, G as HandlerSide, H as HubClientInfo, E as HumanSide, aq as ImageContextConfig, ae as InjectMessageOptions, as as LLMProviderInterface, M as ModelDefinition, aL as NamespaceResolutionError, w as PromptContent, s as PromptDefinition, y as PromptIncludePart, x as PromptPart, F as PromptSide, t as PromptToolConfig, P as Provider, at as ProviderContentPart, aw as ProviderFilePart, av as ProviderImagePart, ar as ProviderRegistry, au as ProviderTextPart, B as SessionToolBinding, z as SessionToolConfig, I as SideConfig, J as SubagentRelationship, u as SubagentToolConfig, S as SubpromptConfig, o as ThreadEventPayload, p as ThreadRegistryEntry, T as ThreadWatchdog, j as ThreadWatchdogState, v as ToolConfig, U as UpdateThreadParams, q as User, k as WatchdogCheckin, W as WatchdogProbeResult, f as applyRuntimeCors, am as buildImageDescription, c as canAccessThread, a9 as cat, aJ as createNamespaceContext, Q as emitThreadEvent, ag as enhanceFlowState, a0 as exists, ad as find, R as forceTurn, ap as generateImageDescription, a7 as getFileStats, N as getMessages, al as getMessagesToSummarize, az as getShortName, a8 as getThumbnail, ak as getUnsummarizedImageAttachments, aG as getVisibleAgentNames, aI as getVisibleModelNames, aH as getVisiblePromptNames, aF as getVisibleToolNames, ac as grep, aj as hasImageAttachments, aa as head, L as injectMessage, d as isAdminOnlyApiRoute, i as isHostedInstance, b as isPublicApiRoute, aK as isQualifiedName, e as isSameOriginBrowserRequest, a as isTrustedLocalDevelopmentRequest, Z as linkFile, a2 as mkdir, a5 as move, ao as optimizeImageContext, ax as parseQualifiedName, ay as qualifyName, K as queueTool, _ as readFile, a3 as readdir, O as reloadHistory, a6 as rename, an as replaceImagesWithDescriptions, aD as resolveAgent, aE as resolveHook, aC as resolveModel, aB as resolvePrompt, aA as resolveTool, a4 as rmdir, r as runtimeCorsHeaders, g as runtimePreflightResponse, $ as stat, ab as tail, a1 as unlink, V as updateThread, X as writeFile, Y as writeImage } from './resolver-BMZAzKD3.js';
|
|
2
|
+
export { v as Agent, J as AttachmentRef, i as AuthContext, A as AuthUser, e as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, t as ClientDuplex, u as ClientForwarding, p as ClientStreamRequest, q as ClientStreamResponse, n as ClientToolRequest, o as ClientToolResponse, B as Controller, a as ControllerContext, G as Env, H as FileRecord, N as FileStats, D as FlowResult, F as FlowState, K as GrepResult, P as ImageContentPart, I as ImageMetadata, L as LLMResponse, M as Message, U as MessageContent, Q as MultimodalContent, R as RequestContext, S as StorageBackend, E as TelemetryEvent, O as TextContentPart, T as ThreadEndpointContext, b as ThreadEnv, w as ThreadInstance, x as ThreadMetadata, y as ToolCall, z as ToolResult, f as authenticate, j as callClient, k as callClientStream, c as createThreadEndpointHandler, m as decodeStreamChunk, d as defineController, l as encodeStreamChunk, h as endpointCallerFromAuth, g as requireAdmin, r as requireAuth, s as supportsClientForwarding } from './index-ChHAVogf.js';
|
|
4
3
|
export { AgentType, DefineHandlerOptions, DefinitionLoader, GlobalNamespaceContext, HANDLER_SYMBOL, HandlerDefinition, HookExecutionContext, HookExecutionSource, HookSignatures, ImageContent, ModelCapabilities, ModelProvider, NamespaceContext, PackageSignature, PackedExports, PackedMeta, PackedMetadata, PackedNamespaceContext, ParentHookRequirement, ParentHookStage, 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, ThreadHookName, Tool, ToolArgs, ToolArgsNode, ToolArgsRawShape, ToolContent, belongsToPackage, defineAgent, defineHandler, defineHook, defineModel, definePrompt, defineProvider, defineTool, isHandler, isPacked, isVisibleInNamespace, mapReasoningLevel, providerConst, providerEnv, providerValue } from '@standardagents/spec';
|
|
5
|
-
|
|
6
|
-
import
|
|
4
|
+
export { N as NamespacedRegistry } from './types-Dhd0M369.js';
|
|
5
|
+
import 'cloudflare:workers';
|
|
7
6
|
import '@cloudflare/workers-types';
|
|
8
7
|
import 'zod';
|
|
9
8
|
|
|
9
|
+
/** Format one metric, rounded to a tenth of a millisecond. */
|
|
10
|
+
declare function formatUpstreamTiming(name: string, durationMs: number): string;
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* This namespace provides type-safe references for models, prompts, agents, and tools.
|
|
14
|
-
* Types are automatically populated when you run `pnpm dev` or `pnpm build`,
|
|
15
|
-
* which scans your `agentbuilder/` directories and generates types.
|
|
16
|
-
*
|
|
17
|
-
* The generated types are placed in `.agents/types.d.ts` and augment the
|
|
18
|
-
* StandardAgentSpec namespace from @standardagents/spec.
|
|
19
|
-
*
|
|
20
|
-
* Note: This namespace is provided for backward compatibility. New code should
|
|
21
|
-
* use StandardAgentSpec types directly, which are defined in @standardagents/spec.
|
|
22
|
-
*
|
|
23
|
-
* @deprecated Use StandardAgentSpec namespace from @standardagents/spec instead
|
|
12
|
+
* A copy of `request` whose upstream-timing header is `value`. The body
|
|
13
|
+
* stream and every other header (WebSocket upgrades included) carry over.
|
|
24
14
|
*/
|
|
25
|
-
declare
|
|
26
|
-
namespace AgentBuilder {
|
|
27
|
-
/**
|
|
28
|
-
* Interface for model type registration.
|
|
29
|
-
* @deprecated Use StandardAgentSpec.ModelRegistry instead
|
|
30
|
-
*/
|
|
31
|
-
interface ModelRegistry extends StandardAgentSpec.ModelRegistry {
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Interface for prompt type registration.
|
|
35
|
-
* @deprecated Use StandardAgentSpec.PromptRegistry instead
|
|
36
|
-
*/
|
|
37
|
-
interface PromptRegistry extends StandardAgentSpec.PromptRegistry {
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Interface for agent type registration.
|
|
41
|
-
* @deprecated Use StandardAgentSpec.AgentRegistry instead
|
|
42
|
-
*/
|
|
43
|
-
interface AgentRegistry extends StandardAgentSpec.AgentRegistry {
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Interface for tool type registration.
|
|
47
|
-
* @deprecated Use StandardAgentSpec.ToolRegistry instead
|
|
48
|
-
*/
|
|
49
|
-
interface ToolRegistry extends StandardAgentSpec.ToolRegistry {
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Interface for callable type registration (prompts, agents, tools).
|
|
53
|
-
* @deprecated Use StandardAgentSpec.CallableRegistry instead
|
|
54
|
-
*/
|
|
55
|
-
interface CallableRegistry extends StandardAgentSpec.CallableRegistry {
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Union type of all model names defined in agentbuilder/models/.
|
|
59
|
-
* @deprecated Use StandardAgentSpec.Models instead
|
|
60
|
-
*/
|
|
61
|
-
type Models = StandardAgentSpec.Models;
|
|
62
|
-
/**
|
|
63
|
-
* Union type of all prompt names defined in agentbuilder/prompts/.
|
|
64
|
-
* @deprecated Use StandardAgentSpec.Prompts instead
|
|
65
|
-
*/
|
|
66
|
-
type Prompts = StandardAgentSpec.Prompts;
|
|
67
|
-
/**
|
|
68
|
-
* Union type of all agent names defined in agentbuilder/agents/.
|
|
69
|
-
* @deprecated Use StandardAgentSpec.Agents instead
|
|
70
|
-
*/
|
|
71
|
-
type Agents = StandardAgentSpec.Agents;
|
|
72
|
-
/**
|
|
73
|
-
* Union type of all tool names defined in agentbuilder/tools/.
|
|
74
|
-
* @deprecated Use StandardAgentSpec.Tools instead
|
|
75
|
-
*/
|
|
76
|
-
type Tools = StandardAgentSpec.Tools;
|
|
77
|
-
/**
|
|
78
|
-
* Union type of all callable items (prompts, agents, tools) that can be used as tools.
|
|
79
|
-
* @deprecated Use StandardAgentSpec.Callables instead
|
|
80
|
-
*/
|
|
81
|
-
type Callables = StandardAgentSpec.Callables;
|
|
82
|
-
/**
|
|
83
|
-
* Interface for hook ID registration.
|
|
84
|
-
* @deprecated Use StandardAgentSpec.HookIdRegistry instead
|
|
85
|
-
*/
|
|
86
|
-
interface HookIdRegistry extends StandardAgentSpec.HookIdRegistry {
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Union type of all hook IDs defined in agents/hooks/.
|
|
90
|
-
* @deprecated Use StandardAgentSpec.HookIds instead
|
|
91
|
-
*/
|
|
92
|
-
type Hooks = StandardAgentSpec.HookIds;
|
|
93
|
-
/**
|
|
94
|
-
* Interface for handler name registration.
|
|
95
|
-
* @deprecated Use StandardAgentSpec.HandlerRegistry instead
|
|
96
|
-
*/
|
|
97
|
-
interface HandlerRegistry extends StandardAgentSpec.HandlerRegistry {
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Union type of all handler names defined in agents/handlers/.
|
|
101
|
-
* @deprecated Use StandardAgentSpec.Handlers instead
|
|
102
|
-
*/
|
|
103
|
-
type Handlers = StandardAgentSpec.Handlers;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
15
|
+
declare function withUpstreamTiming(request: Request, value: string): Request;
|
|
106
16
|
|
|
107
|
-
|
|
108
|
-
* Permissions utility for role-based access control
|
|
109
|
-
*
|
|
110
|
-
* Current behavior:
|
|
111
|
-
* - Admin role can do everything (early return true)
|
|
112
|
-
* - Other roles only get baseline access (own threads)
|
|
113
|
-
*
|
|
114
|
-
* The `can()` function checks arbitrary permission strings.
|
|
115
|
-
* Currently, non-admin users have no explicit permissions,
|
|
116
|
-
* meaning they rely on ownership checks for access.
|
|
117
|
-
*/
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Check if a user can access a specific thread
|
|
121
|
-
*
|
|
122
|
-
* @param auth - The authenticated user context
|
|
123
|
-
* @param thread - The thread to check access for (must have user_id)
|
|
124
|
-
* @returns true if the user can access the thread
|
|
125
|
-
*/
|
|
126
|
-
declare function canAccessThread(auth: AuthContext, thread: {
|
|
127
|
-
user_id: string | null;
|
|
128
|
-
}): boolean;
|
|
129
|
-
|
|
130
|
-
/** Central API exposure policy shared by the generated Worker router and tests. */
|
|
131
|
-
declare function isHostedInstance(env: unknown): boolean;
|
|
132
|
-
/**
|
|
133
|
-
* Local-only conveniences are enabled by the request destination, not merely
|
|
134
|
-
* by the absence of a deployment flag. This makes an incorrectly configured
|
|
135
|
-
* internet-facing Worker fail closed while preserving localhost and OrbStack.
|
|
136
|
-
*/
|
|
137
|
-
declare function isTrustedLocalDevelopmentRequest(request: Request, env: Record<string, unknown> | undefined, trustedDevHosts?: readonly string[]): boolean;
|
|
138
|
-
declare function isPublicApiRoute(routePath: string, request: Request, env: Record<string, unknown> | undefined): boolean;
|
|
139
|
-
/**
|
|
140
|
-
* Reject browser requests initiated by another origin. Requests without
|
|
141
|
-
* browser provenance headers remain available to local CLI/test clients; they
|
|
142
|
-
* still need the normal route credential once bootstrap has completed.
|
|
143
|
-
*
|
|
144
|
-
* `Sec-Fetch-Site: same-origin` is a forbidden header, so a real browser that
|
|
145
|
-
* sends it is attesting same-origin even when a local reverse proxy rewrote
|
|
146
|
-
* `request.url`. Page JavaScript cannot forge that header.
|
|
147
|
-
*/
|
|
148
|
-
declare function isSameOriginBrowserRequest(request: Request): boolean;
|
|
149
|
-
/** Instance-global authoring and package-management surfaces are admin-only. */
|
|
150
|
-
declare function isAdminOnlyApiRoute(routePath: string, method?: string): boolean;
|
|
151
|
-
|
|
152
|
-
declare function runtimeCorsHeaders(request: Request, env: Record<string, unknown> | undefined): Record<string, string>;
|
|
153
|
-
declare function applyRuntimeCors(response: Response, request: Request, env: Record<string, unknown> | undefined): Response;
|
|
154
|
-
declare function runtimePreflightResponse(request: Request, env: Record<string, unknown> | undefined): Response;
|
|
155
|
-
|
|
156
|
-
type AlarmQueueStatus = "pending" | "processing" | "completed" | "failed" | "agent_canceled" | "user_canceled";
|
|
157
|
-
type EffectCancelSource = "agent" | "user";
|
|
158
|
-
interface EffectRunRecord {
|
|
159
|
-
id: string;
|
|
160
|
-
name: string;
|
|
161
|
-
args: Record<string, unknown>;
|
|
162
|
-
scheduledAt: number;
|
|
163
|
-
createdAt: number;
|
|
164
|
-
status: AlarmQueueStatus;
|
|
165
|
-
attempts: number;
|
|
166
|
-
error: string | null;
|
|
167
|
-
completedAt: number | null;
|
|
168
|
-
manualRun: boolean;
|
|
169
|
-
manualRunAt: number | null;
|
|
170
|
-
replayedFrom: string | null;
|
|
171
|
-
}
|
|
172
|
-
interface EffectRunListOptions {
|
|
173
|
-
limit?: number;
|
|
174
|
-
offset?: number;
|
|
175
|
-
}
|
|
176
|
-
interface EffectRunListResult {
|
|
177
|
-
effects: EffectRunRecord[];
|
|
178
|
-
total: number;
|
|
179
|
-
upcomingCount: number;
|
|
180
|
-
limit: number;
|
|
181
|
-
offset: number;
|
|
182
|
-
}
|
|
183
|
-
interface EffectRunActionResult {
|
|
184
|
-
action: "ran" | "replayed";
|
|
185
|
-
id: string;
|
|
186
|
-
replayedId?: string;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
interface RuntimeSafetyStatus {
|
|
190
|
-
state: 'active' | 'quarantined';
|
|
191
|
-
reason: string | null;
|
|
192
|
-
source: string | null;
|
|
193
|
-
trippedAt: number | null;
|
|
194
|
-
resumedAt: number | null;
|
|
195
|
-
forensicHold: boolean;
|
|
196
|
-
lastActionId: string | null;
|
|
197
|
-
observed: Record<string, number>;
|
|
198
|
-
}
|
|
199
|
-
interface RuntimeQuarantineInput {
|
|
200
|
-
actionId: string;
|
|
201
|
-
reason: string;
|
|
202
|
-
source?: string;
|
|
203
|
-
forensicHold?: boolean;
|
|
204
|
-
observed?: Record<string, number>;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
interface CodeExecutionBridgeRegistration {
|
|
208
|
-
call(functionId: string, encodedArgs: unknown[]): Promise<unknown>;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
declare const INTERNAL_TOOL_DELIVERY: unique symbol;
|
|
212
|
-
type ThreadEndpointCodeOptions = Pick<CodeExecutionOptions, "language" | "filename" | "execute" | "modules" | "memoryLimitBytes">;
|
|
213
|
-
/**
|
|
214
|
-
* Result of one watchdog assessment (see performWatchdogAssessment). Returned
|
|
215
|
-
* to whichever delivery invoked it — the internal alarm check, the
|
|
216
|
-
* ThreadWatchdog companion probe, or the diagnostics revive endpoint — so the
|
|
217
|
-
* caller can schedule/record without re-deriving thread state.
|
|
218
|
-
*/
|
|
219
|
-
interface WatchdogProbeResult {
|
|
220
|
-
/** What the thread looked like, after any recovery action taken. */
|
|
221
|
-
verdict: "healthy" | "observing" | "recovered" | "parked" | "idle";
|
|
222
|
-
/** The recovery action performed (all actions are already done on return). */
|
|
223
|
-
action: "none" | "finalized_resumed" | "finalized_parked" | "finalized_deferred" | "aborted_takeover_resumed";
|
|
224
|
-
executing: boolean;
|
|
225
|
-
incompleteLogs: number;
|
|
226
|
-
queuedMessages: number;
|
|
227
|
-
/** Milliseconds since the last execution heartbeat; null when unknown/∞. */
|
|
228
|
-
silenceMs: number | null;
|
|
229
|
-
ceilingMs: number;
|
|
230
|
-
strikes: number;
|
|
231
|
-
/**
|
|
232
|
-
* True when a live-but-wedged executor was taken over: the zombie turn may
|
|
233
|
-
* still own this DO's alarm invocation, so the caller should force a
|
|
234
|
-
* restart (ThreadWatchdog calls forceRestart()) to free the alarm chain.
|
|
235
|
-
*/
|
|
236
|
-
requestRestart: boolean;
|
|
237
|
-
}
|
|
238
|
-
declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableObject<Env> {
|
|
239
|
-
private migratedToVersion;
|
|
240
|
-
private logSockets;
|
|
241
|
-
private messageSockets;
|
|
242
|
-
private bridgeSockets;
|
|
243
|
-
private bridgeLastSeen;
|
|
244
|
-
private bridgeClientInfo;
|
|
245
|
-
private executionOwnerCache;
|
|
246
|
-
private pendingClientCalls;
|
|
247
|
-
private clientStreams;
|
|
248
|
-
private proxyStreamReceivers;
|
|
249
|
-
private eventProxyStreams;
|
|
250
|
-
private alarmQueue;
|
|
251
|
-
private runtimeSafety;
|
|
252
|
-
private alarmQueueRearmed;
|
|
253
|
-
private currentAbortController;
|
|
254
|
-
private isExecuting;
|
|
255
|
-
/**
|
|
256
|
-
* In-memory waiters parked until the running flow finishes (AB-09): the
|
|
257
|
-
* executeFlow busy-guard awaits this signal instead of re-checking
|
|
258
|
-
* isExecuting every 500ms. Every isExecuting=false transition (execution
|
|
259
|
-
* finallys and the watchdog takeover) notifies. In-memory only — a DO
|
|
260
|
-
* restart drops waiters together with the busy caller.
|
|
261
|
-
*/
|
|
262
|
-
private executionIdleWaiters;
|
|
263
|
-
private notifyExecutionIdleWaiters;
|
|
264
|
-
private lastProgressAt;
|
|
265
|
-
private watchdogWedgeStrikes;
|
|
266
|
-
private readonly watchdogIntervalMs;
|
|
267
|
-
private readonly watchdogResumeWindowMs;
|
|
268
|
-
private readonly watchdogMaxResumesPerWindow;
|
|
269
|
-
private codeExecutionBridges;
|
|
270
|
-
constructor(ctx: DurableObjectState, env: Env);
|
|
271
|
-
/**
|
|
272
|
-
* Returns the tools registry for this thread.
|
|
273
|
-
* This method is implemented when you import DurableThread from 'virtual:@standardagents/builder'.
|
|
274
|
-
*
|
|
275
|
-
* @throws Error if not implemented in a subclass
|
|
276
|
-
* @returns Record of tool name to tool loader function
|
|
277
|
-
*
|
|
278
|
-
* @example
|
|
279
|
-
* ```typescript
|
|
280
|
-
* import { DurableThread } from 'virtual:@standardagents/builder'
|
|
281
|
-
*
|
|
282
|
-
* export class Thread extends DurableThread {}
|
|
283
|
-
* ```
|
|
284
|
-
*/
|
|
285
|
-
tools(): Record<string, () => Promise<any>>;
|
|
286
|
-
/**
|
|
287
|
-
* Returns the hooks registry for this thread.
|
|
288
|
-
* This method is implemented when you import DurableThread from 'virtual:@standardagents/builder'.
|
|
289
|
-
*
|
|
290
|
-
* @throws Error if not implemented in a subclass
|
|
291
|
-
* @returns Record of hook name to hook loader function
|
|
292
|
-
*
|
|
293
|
-
* @example
|
|
294
|
-
* ```typescript
|
|
295
|
-
* import { DurableThread } from 'virtual:@standardagents/builder'
|
|
296
|
-
*
|
|
297
|
-
* export class Thread extends DurableThread {}
|
|
298
|
-
* ```
|
|
299
|
-
*/
|
|
300
|
-
hooks(): Record<string, () => Promise<any>>;
|
|
301
|
-
/**
|
|
302
|
-
* Returns the models registry for lazy-loading model definitions.
|
|
303
|
-
* This method is implemented when you import DurableThread from 'virtual:@standardagents/builder'.
|
|
304
|
-
*
|
|
305
|
-
* @throws Error if not implemented in a subclass
|
|
306
|
-
* @returns Record of model name to model loader function
|
|
307
|
-
*/
|
|
308
|
-
models(): Record<string, () => Promise<any>>;
|
|
309
|
-
/**
|
|
310
|
-
* Returns the prompts registry for lazy-loading prompt definitions.
|
|
311
|
-
* This method is implemented when you import DurableThread from 'virtual:@standardagents/builder'.
|
|
312
|
-
*
|
|
313
|
-
* @throws Error if not implemented in a subclass
|
|
314
|
-
* @returns Record of prompt name to prompt loader function
|
|
315
|
-
*/
|
|
316
|
-
prompts(): Record<string, () => Promise<any>>;
|
|
317
|
-
/**
|
|
318
|
-
* Returns the agents registry for lazy-loading agent definitions.
|
|
319
|
-
* This method is implemented when you import DurableThread from 'virtual:@standardagents/builder'.
|
|
320
|
-
*
|
|
321
|
-
* @throws Error if not implemented in a subclass
|
|
322
|
-
* @returns Record of agent name to agent loader function
|
|
323
|
-
*/
|
|
324
|
-
agents(): Record<string, () => Promise<any>>;
|
|
325
|
-
/**
|
|
326
|
-
* Returns the effects registry for lazy-loading effect definitions.
|
|
327
|
-
* This method is implemented when you import DurableThread from 'virtual:@standardagents/builder'.
|
|
328
|
-
*
|
|
329
|
-
* Effects are scheduled operations that run outside the tool execution context,
|
|
330
|
-
* ideal for delayed notifications, webhooks, and cleanup tasks.
|
|
331
|
-
*
|
|
332
|
-
* @throws Error if not implemented in a subclass
|
|
333
|
-
* @returns Record of effect name to effect loader function
|
|
334
|
-
*/
|
|
335
|
-
effects(): Record<string, () => Promise<any>>;
|
|
336
|
-
/**
|
|
337
|
-
* Returns available handler loaders from the agents/handlers/ directory.
|
|
338
|
-
* This method is implemented when you import DurableThread from 'virtual:@standardagents/builder'.
|
|
339
|
-
*
|
|
340
|
-
* Handlers are deterministic code that backs one side of an agent and takes
|
|
341
|
-
* that side's turns in place of a model.
|
|
342
|
-
*
|
|
343
|
-
* @returns Record of handler name to handler loader function
|
|
344
|
-
*/
|
|
345
|
-
handlers(): Record<string, () => Promise<any>>;
|
|
346
|
-
/**
|
|
347
|
-
* Returns the namespaced registry for packed agent support.
|
|
348
|
-
* This method is implemented when you import DurableThread from 'virtual:@standardagents/builder'.
|
|
349
|
-
*
|
|
350
|
-
* @throws Error if not implemented in a subclass
|
|
351
|
-
* @returns The namespaced registry with global and packages namespaces
|
|
352
|
-
*/
|
|
353
|
-
registry(): any;
|
|
354
|
-
/**
|
|
355
|
-
* Load a model definition by name.
|
|
356
|
-
* Supports both global models and packed models (e.g., "packageId/modelName").
|
|
357
|
-
* For scoped packages, use "@scope/pkg/modelName".
|
|
358
|
-
* For packed context, tries package first then falls back to global.
|
|
359
|
-
*/
|
|
360
|
-
loadModel(name: string): Promise<any>;
|
|
361
|
-
/**
|
|
362
|
-
* List available model names.
|
|
363
|
-
*/
|
|
364
|
-
getModelNames(): string[];
|
|
365
|
-
/**
|
|
366
|
-
* Load a prompt definition by name.
|
|
367
|
-
* Supports both global prompts (e.g., "my-prompt") and packed prompts (e.g., "packageId/promptName").
|
|
368
|
-
*/
|
|
369
|
-
loadPrompt(name: string): Promise<any>;
|
|
370
|
-
/**
|
|
371
|
-
* A prompt whose tools array still carries a 0.1.0 SubagentToolConfig is a
|
|
372
|
-
* LOAD error — there is no compatibility window, and the boot failure is
|
|
373
|
-
* the migration UX. Relationship declarations live on the owning agent
|
|
374
|
-
* side's subagents array.
|
|
375
|
-
*/
|
|
376
|
-
static rejectLegacyPromptSubagentTools(promptDef: any, promptName: string): any;
|
|
377
|
-
/**
|
|
378
|
-
* List available prompt names.
|
|
379
|
-
*/
|
|
380
|
-
getPromptNames(): string[];
|
|
381
|
-
/**
|
|
382
|
-
* Load an agent definition by name.
|
|
383
|
-
* Supports both global agents (e.g., "my-agent") and packed agents (e.g., "packageId/agentName").
|
|
384
|
-
* For scoped packages, use "@scope/pkg/agentName".
|
|
385
|
-
*/
|
|
386
|
-
loadAgent(name: string): Promise<any>;
|
|
387
|
-
/**
|
|
388
|
-
* Convert a raw agent definition (defineAgent) into the runtime `Agent` config
|
|
389
|
-
* FlowEngine expects: maps `sideA/sideB.prompt` → `side_a/b_agent_prompt`,
|
|
390
|
-
* resolves session-tool bindings, and qualifies prompt names for packed
|
|
391
|
-
* agents. The execution entrypoints build this inline; this method is the
|
|
392
|
-
* shared path for code that resolves an agent OUTSIDE a live execution (e.g.
|
|
393
|
-
* `ThreadState.invokeTool()` from a thread endpoint), so the two can't drift
|
|
394
|
-
* (a raw def has no `side_a_agent_prompt`).
|
|
395
|
-
*/
|
|
396
|
-
static buildAgentConfig(agentDef: any, agentName: string): Agent;
|
|
397
|
-
/**
|
|
398
|
-
* Load an agent by name AND convert it to the runtime `Agent` config (see
|
|
399
|
-
* `buildAgentConfig`). Used by `ThreadState.invokeTool()` when firing a tool
|
|
400
|
-
* outside an active execution, so the assembled state has a real
|
|
401
|
-
* `side_a_agent_prompt` instead of the raw definition's `sideA.prompt`.
|
|
402
|
-
*/
|
|
403
|
-
loadAgentConfig(name: string): Promise<Agent>;
|
|
404
|
-
/**
|
|
405
|
-
* List available agent names.
|
|
406
|
-
*/
|
|
407
|
-
getAgentNames(): string[];
|
|
408
|
-
/**
|
|
409
|
-
* Load a handler definition by name.
|
|
410
|
-
* Supports packed handlers via qualified names ("packageId/handlerName").
|
|
411
|
-
*/
|
|
412
|
-
loadHandler(name: string): Promise<any>;
|
|
413
|
-
/**
|
|
414
|
-
* List available handler names.
|
|
415
|
-
*/
|
|
416
|
-
getHandlerNames(): string[];
|
|
417
|
-
/**
|
|
418
|
-
* Load an effect definition by name.
|
|
419
|
-
*/
|
|
420
|
-
loadEffect(name: string): Promise<any>;
|
|
421
|
-
/**
|
|
422
|
-
* List available effect names.
|
|
423
|
-
*/
|
|
424
|
-
getEffectNames(): string[];
|
|
425
|
-
/**
|
|
426
|
-
* Load a tool definition by name.
|
|
427
|
-
* Supports both global tools (e.g., "my_tool") and packed tools (e.g., "packageId/toolName").
|
|
428
|
-
*/
|
|
429
|
-
loadTool(name: string): Promise<any>;
|
|
430
|
-
/**
|
|
431
|
-
* Get thread metadata from DurableAgentBuilder.
|
|
432
|
-
* Used for creating ThreadState outside of flow execution.
|
|
433
|
-
*/
|
|
434
|
-
getThreadMetadata(threadId: string): Promise<ThreadMetadata>;
|
|
435
|
-
/**
|
|
436
|
-
* Execute sandboxed code for a thread endpoint from inside the thread DO.
|
|
437
|
-
*
|
|
438
|
-
* Thread endpoint handlers often start in the top-level Worker with only a
|
|
439
|
-
* Durable Object stub. Code execution must originate here so the dynamic
|
|
440
|
-
* worker can use this DO's env, ctx exports, and bridge registration map.
|
|
441
|
-
*/
|
|
442
|
-
executeThreadEndpointCode(threadId: string, source: string, options: ThreadEndpointCodeOptions): Promise<CodeExecutionResult>;
|
|
443
|
-
/**
|
|
444
|
-
* Execute ThreadState.runCode for endpoint handlers that only have a
|
|
445
|
-
* Durable Object stub. The actual Dynamic Worker must be started inside this
|
|
446
|
-
* DurableThread so it has access to env, ctx exports, and bridge callbacks.
|
|
447
|
-
*/
|
|
448
|
-
executeThreadStateRunCode(threadId: string, source: string, options?: CodeExecutionOptions, wantsReport?: boolean): Promise<CodeExecutionResult>;
|
|
449
|
-
/**
|
|
450
|
-
* Run `ThreadState.invokeTool()` INSIDE this Durable Object.
|
|
451
|
-
*
|
|
452
|
-
* Thread endpoints hold only a DO stub (no `ctx`/`env`/storage), so they can't
|
|
453
|
-
* build a standalone execution state in the top-level Worker. ThreadStateImpl
|
|
454
|
-
* forwards idle `invokeTool` calls here — where `this` is the real DO — so the
|
|
455
|
-
* assembled state has real storage and `ctx.waitUntil`, letting a non-blocking
|
|
456
|
-
* subagent (e.g. `compaction_agent`) be spawned from an endpoint. Mirrors
|
|
457
|
-
* `executeThreadStateRunCode`.
|
|
458
|
-
*/
|
|
459
|
-
executeThreadStateInvokeTool(threadId: string, toolName: string, args: Record<string, unknown>): Promise<ToolResult>;
|
|
460
|
-
/**
|
|
461
|
-
* Read a JSON value from this thread's durable key-value store.
|
|
462
|
-
*/
|
|
463
|
-
getValue<T = unknown>(key: string): Promise<T | null>;
|
|
464
|
-
/**
|
|
465
|
-
* Write a JSON value to this thread's durable key-value store.
|
|
466
|
-
*
|
|
467
|
-
* Per the Standard Agents spec, null and undefined delete the key.
|
|
468
|
-
*/
|
|
469
|
-
setValue(key: string, value: unknown): Promise<void>;
|
|
470
|
-
listValues(options?: {
|
|
471
|
-
search?: string | null;
|
|
472
|
-
limit?: number;
|
|
473
|
-
offset?: number;
|
|
474
|
-
}): Promise<{
|
|
475
|
-
values: Array<{
|
|
476
|
-
key: string;
|
|
477
|
-
value: unknown;
|
|
478
|
-
serialized: string;
|
|
479
|
-
size: number;
|
|
480
|
-
updatedAt: number;
|
|
481
|
-
parseError?: string;
|
|
482
|
-
}>;
|
|
483
|
-
total: number;
|
|
484
|
-
limit: number;
|
|
485
|
-
offset: number;
|
|
486
|
-
search: string | null;
|
|
487
|
-
}>;
|
|
488
|
-
private assertValidThreadValueKey;
|
|
489
|
-
private escapeThreadValueLike;
|
|
490
|
-
private serializeThreadValue;
|
|
491
|
-
private assertJsonSerializableThreadValue;
|
|
492
|
-
/**
|
|
493
|
-
* Trigger an agent to run on this thread.
|
|
494
|
-
*
|
|
495
|
-
* Queues an agent execution via the alarm queue. The execution
|
|
496
|
-
* runs asynchronously in the background.
|
|
497
|
-
*
|
|
498
|
-
* @param threadId - Thread ID for the execution
|
|
499
|
-
* @param agentName - Name of the agent to run
|
|
500
|
-
*/
|
|
501
|
-
runAgent(threadId: string, agentName: string): Promise<void>;
|
|
502
|
-
/**
|
|
503
|
-
* Get the persisted resumable-subagent registry for this thread.
|
|
504
|
-
*/
|
|
505
|
-
getChildrenRegistry(_threadId: string): Promise<SubagentRegistryEntry[]>;
|
|
506
|
-
/** In-memory throttle/reentrancy guards for the stale-child reconciler. */
|
|
507
|
-
private lastChildAuditAt;
|
|
508
|
-
private childAuditInFlight;
|
|
509
|
-
/**
|
|
510
|
-
* Lazily heal registry entries stranded at a "working" status. The normal
|
|
511
|
-
* settlement chain lives only in the parent's `waitUntil`; a parent
|
|
512
|
-
* eviction/deploy/kill during a child's run leaves the entry at `running`
|
|
513
|
-
* forever and clients render an eternal spinner. On registry reads, audit
|
|
514
|
-
* old unsettled entries against the child thread's ACTUAL state and settle
|
|
515
|
-
* them — conservatively (see subagent-reconcile.ts): resumable children
|
|
516
|
-
* are never deterministically terminated.
|
|
517
|
-
*/
|
|
518
|
-
private reconcileStaleChildren;
|
|
519
|
-
/**
|
|
520
|
-
* Child-side registry settlement: called from the CHILD's own DO whenever
|
|
521
|
-
* a run ends, so the spinner clears even when the parent-held completion
|
|
522
|
-
* chain died with the parent. Only downgrades a live "working" status to
|
|
523
|
-
* idle — never clobbers terminated.
|
|
524
|
-
*/
|
|
525
|
-
settleChildRegistryIdle(_threadId: string, reference: string): Promise<void>;
|
|
526
|
-
private setChildrenRegistry;
|
|
527
|
-
upsertChildRegistry(_threadId: string, entry: SubagentRegistryEntry): Promise<void>;
|
|
528
|
-
updateChildRegistryStatus(_threadId: string, reference: string, status: string): Promise<void>;
|
|
529
|
-
/**
|
|
530
|
-
* Nudge live event listeners after a child's registry status changes. The
|
|
531
|
-
* status (`running`/`idle`/`terminated`) lives here in the parent registry,
|
|
532
|
-
* not on the child's thread row, so without this a transition like running →
|
|
533
|
-
* idle would never reach `/api/events`. We re-broadcast a `thread_updated`
|
|
534
|
-
* for the child thread so consumers re-read its status. Best effort.
|
|
535
|
-
*/
|
|
536
|
-
private broadcastChildStatusChanged;
|
|
537
|
-
removeChildRegistry(_threadId: string, reference: string): Promise<void>;
|
|
538
|
-
/**
|
|
539
|
-
* Persist the invocation arguments supplied when this subagent thread was
|
|
540
|
-
* created. These are hydrated into prompt-interpolation context on every
|
|
541
|
-
* activation of either side, so they survive for the life of the thread.
|
|
542
|
-
*/
|
|
543
|
-
setSubagentArguments(_threadId: string, args: Record<string, unknown>): Promise<void>;
|
|
544
|
-
/**
|
|
545
|
-
* Read the persisted invocation arguments for this subagent thread.
|
|
546
|
-
* Returns an empty object when none were stored.
|
|
547
|
-
*/
|
|
548
|
-
getSubagentArguments(_threadId: string): Promise<Record<string, unknown>>;
|
|
549
|
-
private asOptionalString;
|
|
550
|
-
private asOptionalBoolean;
|
|
551
|
-
private getThreadNameFromTags;
|
|
552
|
-
private toSubagentProjection;
|
|
553
|
-
private resolveSubagentMessageProjections;
|
|
554
|
-
/**
|
|
555
|
-
* Build hook resolution context and a genuine at-rest ThreadState.
|
|
556
|
-
* Resolution failures abort insertion so lifecycle hooks cannot be bypassed.
|
|
557
|
-
*/
|
|
558
|
-
private buildAtRestHookState;
|
|
559
|
-
/**
|
|
560
|
-
* Inject a top-level message without starting a new execution.
|
|
561
|
-
*
|
|
562
|
-
* This path is used by effects and thread endpoints, which run without a
|
|
563
|
-
* FlowState but still need to write visible messages to the thread.
|
|
564
|
-
*/
|
|
565
|
-
injectMessage(threadId: string, message: InjectMessageInput): Promise<Message>;
|
|
566
|
-
/**
|
|
567
|
-
* Queue a message for deferred delivery.
|
|
568
|
-
*/
|
|
569
|
-
queueMessage(threadId: string, message: QueueMessageInput): Promise<void>;
|
|
570
|
-
private hasPendingTurnAlarm;
|
|
571
|
-
private ensureQueuedMessageExecution;
|
|
572
|
-
private ensureRootMessageId;
|
|
573
|
-
/**
|
|
574
|
-
* Soft-terminate this thread.
|
|
575
|
-
*/
|
|
576
|
-
terminateThread(threadId: string): Promise<{
|
|
577
|
-
success: boolean;
|
|
578
|
-
terminated: number;
|
|
579
|
-
}>;
|
|
580
|
-
/**
|
|
581
|
-
* Schedule an effect for future execution.
|
|
582
|
-
*
|
|
583
|
-
* @param threadId - Thread ID for the effect execution context
|
|
584
|
-
* @param effectName - Name of the effect to schedule
|
|
585
|
-
* @param effectArgs - Arguments to pass to the effect handler
|
|
586
|
-
* @param delayMs - Delay in milliseconds before execution (default: 0)
|
|
587
|
-
* @returns UUID of the scheduled effect
|
|
588
|
-
*/
|
|
589
|
-
scheduleEffect(threadId: string, effectName: string, effectArgs: Record<string, unknown>, delayMs?: number, options?: {
|
|
590
|
-
sourceLogId?: string | null;
|
|
591
|
-
}): Promise<string>;
|
|
592
|
-
/**
|
|
593
|
-
* Check whether an effect loader exists in either global or packed registries.
|
|
594
|
-
*/
|
|
595
|
-
private effectExists;
|
|
596
|
-
/**
|
|
597
|
-
* Get scheduled effects for this thread.
|
|
598
|
-
*
|
|
599
|
-
* @param name - Optional effect name to filter by
|
|
600
|
-
* @returns Array of scheduled effect records
|
|
601
|
-
*/
|
|
602
|
-
getScheduledEffects(name?: string): Promise<Array<{
|
|
603
|
-
id: string;
|
|
604
|
-
name: string;
|
|
605
|
-
args: Record<string, unknown>;
|
|
606
|
-
scheduledAt: number;
|
|
607
|
-
createdAt: number;
|
|
608
|
-
}>>;
|
|
609
|
-
/**
|
|
610
|
-
* List pending and historical effect runs for the AgentBuilder UI.
|
|
611
|
-
*/
|
|
612
|
-
listEffectRuns(options?: EffectRunListOptions): Promise<EffectRunListResult>;
|
|
613
|
-
/**
|
|
614
|
-
* Run a pending effect now, or replay a historical effect immediately.
|
|
615
|
-
*/
|
|
616
|
-
runEffectNow(effectRunId: string): Promise<EffectRunActionResult>;
|
|
617
|
-
/**
|
|
618
|
-
* Cancel a scheduled effect and keep it in history.
|
|
619
|
-
*
|
|
620
|
-
* @param id - The effect ID returned by scheduleEffect
|
|
621
|
-
* @returns true if the effect was found and canceled, false otherwise
|
|
622
|
-
*/
|
|
623
|
-
removeScheduledEffect(id: string, canceledBy?: EffectCancelSource): Promise<boolean>;
|
|
624
|
-
/**
|
|
625
|
-
* Ensures the database schema is up to date.
|
|
626
|
-
* This method is called on the first request to the Durable Object.
|
|
627
|
-
* It checks the schema version and runs any pending migrations.
|
|
628
|
-
*
|
|
629
|
-
* Performance:
|
|
630
|
-
* - Already migrated to latest: ~0.1ms (single SELECT + integer comparison)
|
|
631
|
-
* - Needs migration: Runs once per Durable Object lifetime per schema version
|
|
632
|
-
* - Detects new migrations after code deployment
|
|
633
|
-
*/
|
|
634
|
-
private ensureMigrated;
|
|
635
|
-
/**
|
|
636
|
-
* Gets the current schema version from the database.
|
|
637
|
-
* Returns 0 if the metadata table doesn't exist (brand new database).
|
|
638
|
-
*/
|
|
639
|
-
private getCurrentVersion;
|
|
640
|
-
/**
|
|
641
|
-
* Runs all pending migrations sequentially.
|
|
642
|
-
* Each migration is run in order, starting from the current version + 1.
|
|
643
|
-
*/
|
|
644
|
-
private runMigrations;
|
|
645
|
-
/**
|
|
646
|
-
* Legacy fetch handler for WebSocket upgrades only
|
|
647
|
-
*/
|
|
648
|
-
fetch(request: Request): Promise<Response>;
|
|
649
|
-
registerCodeExecutionBridge(runId: string, bridge: CodeExecutionBridgeRegistration): void;
|
|
650
|
-
unregisterCodeExecutionBridge(runId: string): void;
|
|
651
|
-
callCodeExecutionBridge(runId: string, functionId: string, encodedArgs: unknown[]): Promise<unknown>;
|
|
652
|
-
/**
|
|
653
|
-
* Execute thread with initial messages (RPC method)
|
|
654
|
-
* Enqueues the execution to be processed by the alarm handler
|
|
655
|
-
*/
|
|
656
|
-
execute(threadId: string, agentId: string, initial_messages?: any[], data?: any): Promise<Response>;
|
|
657
|
-
/**
|
|
658
|
-
* Execute a flow synchronously and return the final top-level message content.
|
|
659
|
-
* Used by blocking subagent tool calls.
|
|
660
|
-
*/
|
|
661
|
-
executeBlocking(threadId: string, agentId: string, initial_messages?: any[], data?: any): Promise<{
|
|
662
|
-
status: "success" | "error";
|
|
663
|
-
result?: string;
|
|
664
|
-
error?: string;
|
|
665
|
-
attachments?: unknown[];
|
|
666
|
-
terminal?: boolean;
|
|
667
|
-
}>;
|
|
668
|
-
/** Best-effort: mark this child's entry idle in its parent's registry. */
|
|
669
|
-
private settleOwnRegistryEntry;
|
|
670
|
-
private executeBlockingImpl;
|
|
671
|
-
/**
|
|
672
|
-
* Send a new message to the thread (RPC method)
|
|
673
|
-
* Enqueues the message processing to be handled by the alarm handler
|
|
674
|
-
*/
|
|
675
|
-
sendMessage(threadId: string, content: string, role?: string, attachments?: string): Promise<Response>;
|
|
676
|
-
/**
|
|
677
|
-
* Check if execution should be stopped (called by FlowEngine)
|
|
678
|
-
* Reads from SQLite for persistence across hibernation
|
|
679
|
-
*/
|
|
680
|
-
shouldStop(): Promise<boolean>;
|
|
681
|
-
/**
|
|
682
|
-
* Returns the termination timestamp (microseconds) or null when active.
|
|
683
|
-
*/
|
|
684
|
-
getTerminated(_threadId: string): Promise<number | null>;
|
|
685
|
-
private assertNotTerminated;
|
|
686
|
-
private getLatestTopLevelMessage;
|
|
687
|
-
private getTerminalSessionToolNames;
|
|
688
|
-
private parseAttachmentRefsJson;
|
|
689
|
-
private deleteAttachmentRefsFromJson;
|
|
690
|
-
private cancelQueuedMessage;
|
|
691
|
-
private parseMessageMetadata;
|
|
692
|
-
private extractSubagentIdFromMetadata;
|
|
693
|
-
private getLatestTerminalSessionMessageAfter;
|
|
694
|
-
private inferMimeTypeFromPath;
|
|
695
|
-
private extensionForMimeType;
|
|
696
|
-
private sanitizeFilename;
|
|
697
|
-
private splitFilename;
|
|
698
|
-
private resolveAttachmentMimeType;
|
|
699
|
-
private buildAttachmentTargetPath;
|
|
700
|
-
private copyAttachmentRefsToThread;
|
|
701
|
-
private readAttachmentDataFromSource;
|
|
702
|
-
private arrayBufferToBase64;
|
|
703
|
-
private formatSubagentAttachmentPathSummary;
|
|
704
|
-
private persistParentHandoffStatusMessage;
|
|
705
|
-
private buildMissingTerminalSessionFailure;
|
|
706
|
-
private deliverCompletionToParentIfNeeded;
|
|
707
|
-
private getParentRegistryEntryForChild;
|
|
708
|
-
/**
|
|
709
|
-
* Stop the currently executing thread (RPC method)
|
|
710
|
-
* Simple "off" switch - stops turns, only cleared by user messages
|
|
711
|
-
*/
|
|
712
|
-
/**
|
|
713
|
-
* Flip every still-`pending` message to `failed` and broadcast the change to
|
|
714
|
-
* all connected heads. This is THE settle path for any terminal condition
|
|
715
|
-
* that leaves a turn half-open — user stop, lost execution, terminal
|
|
716
|
-
* execution failure, and expired parked forwarded calls — so no head is
|
|
717
|
-
* left rendering a stuck "Working" state. Returns the failure timestamp.
|
|
718
|
-
*/
|
|
719
|
-
failPendingMessagesAndBroadcast(): Promise<number>;
|
|
720
|
-
/**
|
|
721
|
-
* A terminal failure ended a turn without a normal assistant reply: settle
|
|
722
|
-
* every pending message and persist a durable `failed` assistant message so
|
|
723
|
-
* all connected heads land on a real, visible end state — never a stuck
|
|
724
|
-
* "Working" spinner. Used by the FlowEngine's terminal catch and the parked
|
|
725
|
-
* forwarded-call TTL.
|
|
726
|
-
*/
|
|
727
|
-
settleTerminalFailure(errorMessage: string, threadId?: string): Promise<void>;
|
|
728
|
-
stop(): Promise<Response>;
|
|
729
|
-
/**
|
|
730
|
-
* Continue execution from where it stopped (RPC method)
|
|
731
|
-
* Useful for debugging - continues the FlowEngine with additional steps
|
|
732
|
-
* without adding a new message.
|
|
733
|
-
*
|
|
734
|
-
* @param threadId The thread ID
|
|
735
|
-
* @param side Which side to start from ('a' or 'b'), defaults to 'a'
|
|
736
|
-
*/
|
|
737
|
-
continueExecution(threadId: string, side?: 'a' | 'b'): Promise<Response>;
|
|
738
|
-
/**
|
|
739
|
-
* Get message history (RPC method)
|
|
740
|
-
*
|
|
741
|
-
* By default, returns the newest messages (when truncating), but in chronological
|
|
742
|
-
* order (oldest first in the array). This is ideal for chat UIs where messages
|
|
743
|
-
* should be appended and scrolled to the bottom.
|
|
744
|
-
*
|
|
745
|
-
* The offset parameter allows "scrolling up" to view older messages.
|
|
746
|
-
*
|
|
747
|
-
* Example:
|
|
748
|
-
* - getMessages(10, 0) -> newest 10 messages, oldest first in array
|
|
749
|
-
* - getMessages(10, 10) -> next 10 older messages, oldest first in array
|
|
750
|
-
*
|
|
751
|
-
* @param limit Number of messages to return (default: 100)
|
|
752
|
-
* @param offset Number of newest messages to skip (default: 0)
|
|
753
|
-
* @param order Internal query order - "DESC" (default) fetches newest first then reverses
|
|
754
|
-
* @param includeSilent Include silent messages (UI-only messages)
|
|
755
|
-
* @param maxDepth Maximum depth to include (default: 0 for top-level only)
|
|
756
|
-
*/
|
|
757
|
-
getMessages(limit?: number, offset?: number, order?: "ASC" | "DESC" | "asc" | "desc", includeSilent?: boolean, maxDepth?: number): Promise<{
|
|
758
|
-
messages: {
|
|
759
|
-
id: string;
|
|
760
|
-
role: string;
|
|
761
|
-
content: string | null;
|
|
762
|
-
name: string | null;
|
|
763
|
-
tool_calls: string | null;
|
|
764
|
-
tool_call_id: string | null;
|
|
765
|
-
tool_status: "success" | "error" | null;
|
|
766
|
-
log_id: string | null;
|
|
767
|
-
created_at: number;
|
|
768
|
-
silent: boolean;
|
|
769
|
-
parent_id: string | null;
|
|
770
|
-
depth: number;
|
|
771
|
-
status: "pending" | "completed" | "failed" | null;
|
|
772
|
-
reasoning_content: string | null;
|
|
773
|
-
reasoning_details: string | null;
|
|
774
|
-
attachments: any;
|
|
775
|
-
metadata: Record<string, unknown> | undefined;
|
|
776
|
-
subagent_id: string | null;
|
|
777
|
-
}[];
|
|
778
|
-
total: number;
|
|
779
|
-
hasMore: boolean;
|
|
780
|
-
}>;
|
|
781
|
-
/**
|
|
782
|
-
* Get specific messages, optionally expanding any requested tool-call message
|
|
783
|
-
* to the full contiguous workblock it belongs to.
|
|
784
|
-
*/
|
|
785
|
-
getMessagesByIds(ids: string[], includeSilent?: boolean, maxDepth?: number, includeWorkblocks?: boolean): Promise<{
|
|
786
|
-
messages: {
|
|
787
|
-
id: string;
|
|
788
|
-
role: string;
|
|
789
|
-
content: string | null;
|
|
790
|
-
name: string | null;
|
|
791
|
-
tool_calls: string | null;
|
|
792
|
-
tool_call_id: string | null;
|
|
793
|
-
tool_status: "success" | "error" | null;
|
|
794
|
-
log_id: string | null;
|
|
795
|
-
created_at: number;
|
|
796
|
-
silent: boolean;
|
|
797
|
-
parent_id: string | null;
|
|
798
|
-
depth: number;
|
|
799
|
-
status: "pending" | "completed" | "failed" | null;
|
|
800
|
-
reasoning_content: string | null;
|
|
801
|
-
reasoning_details: string | null;
|
|
802
|
-
attachments: any;
|
|
803
|
-
metadata: Record<string, unknown> | undefined;
|
|
804
|
-
subagent_id: string | null;
|
|
805
|
-
}[];
|
|
806
|
-
total: number;
|
|
807
|
-
hasMore: boolean;
|
|
808
|
-
}>;
|
|
809
|
-
/**
|
|
810
|
-
* Delete a message (RPC method)
|
|
811
|
-
* Also cleans up any attachment files stored on the thread filesystem
|
|
812
|
-
*/
|
|
813
|
-
deleteMessage(messageId: string): Promise<{
|
|
814
|
-
success: boolean;
|
|
815
|
-
error?: undefined;
|
|
816
|
-
} | {
|
|
817
|
-
success: boolean;
|
|
818
|
-
error: any;
|
|
819
|
-
}>;
|
|
820
|
-
/**
|
|
821
|
-
* Update a message's content (RPC method)
|
|
822
|
-
*/
|
|
823
|
-
updateMessageContent(messageId: string, content: string): Promise<{
|
|
824
|
-
success: boolean;
|
|
825
|
-
error?: undefined;
|
|
826
|
-
} | {
|
|
827
|
-
success: boolean;
|
|
828
|
-
error: any;
|
|
829
|
-
}>;
|
|
830
|
-
/**
|
|
831
|
-
* Seed messages directly into the database (RPC method - for testing)
|
|
832
|
-
* This bypasses the normal message processing flow
|
|
833
|
-
*/
|
|
834
|
-
seedMessages(args: {
|
|
835
|
-
messages: Array<{
|
|
836
|
-
id: string;
|
|
837
|
-
role: string;
|
|
838
|
-
content: string;
|
|
839
|
-
created_at: number;
|
|
840
|
-
log_id?: string | null;
|
|
841
|
-
}>;
|
|
842
|
-
}): Promise<{
|
|
843
|
-
success: boolean;
|
|
844
|
-
count: number;
|
|
845
|
-
error?: undefined;
|
|
846
|
-
} | {
|
|
847
|
-
success: boolean;
|
|
848
|
-
error: any;
|
|
849
|
-
count?: undefined;
|
|
850
|
-
}>;
|
|
851
|
-
/**
|
|
852
|
-
* Seed a log directly into the database (RPC method - for testing)
|
|
853
|
-
* This bypasses the normal log creation flow
|
|
854
|
-
*/
|
|
855
|
-
seedLog(args: {
|
|
856
|
-
id: string;
|
|
857
|
-
message_id: string;
|
|
858
|
-
provider: string;
|
|
859
|
-
model: string;
|
|
860
|
-
created_at: number;
|
|
861
|
-
is_complete?: boolean;
|
|
862
|
-
prompt_name?: string;
|
|
863
|
-
}): Promise<{
|
|
864
|
-
success: boolean;
|
|
865
|
-
id: string;
|
|
866
|
-
error?: undefined;
|
|
867
|
-
} | {
|
|
868
|
-
success: boolean;
|
|
869
|
-
error: any;
|
|
870
|
-
id?: undefined;
|
|
871
|
-
}>;
|
|
872
|
-
/**
|
|
873
|
-
* Get logs (RPC method)
|
|
874
|
-
*/
|
|
875
|
-
getLogs(limit?: number, offset?: number, order?: "ASC" | "DESC"): Promise<{
|
|
876
|
-
logs: {
|
|
877
|
-
id: string;
|
|
878
|
-
kind: string | null;
|
|
879
|
-
message_id: string;
|
|
880
|
-
provider: string;
|
|
881
|
-
actual_provider: string | null;
|
|
882
|
-
standard_agents_router_used: boolean;
|
|
883
|
-
model: string;
|
|
884
|
-
model_name: string | null;
|
|
885
|
-
prompt_name: string | null;
|
|
886
|
-
tools_called: string | null;
|
|
887
|
-
queued_tools: string | null;
|
|
888
|
-
provider_tools: string | null;
|
|
889
|
-
parent_log_id: string | null;
|
|
890
|
-
retry_of_log_id: string | null;
|
|
891
|
-
error: string | null;
|
|
892
|
-
error_type: string | null;
|
|
893
|
-
error_origin: string | null;
|
|
894
|
-
cost_total: number | null;
|
|
895
|
-
input_tokens: number | null;
|
|
896
|
-
cached_tokens: number | null;
|
|
897
|
-
output_tokens: number | null;
|
|
898
|
-
total_tokens: number | null;
|
|
899
|
-
is_complete: boolean;
|
|
900
|
-
created_at: number;
|
|
901
|
-
}[];
|
|
902
|
-
total: number;
|
|
903
|
-
hasMore: boolean;
|
|
904
|
-
}>;
|
|
905
|
-
/**
|
|
906
|
-
* This thread's OWN request-log cost summary (no descendants), aggregated
|
|
907
|
-
* in SQL so subtree cost reporting doesn't page full log rows out of every
|
|
908
|
-
* thread in the tree. Used by GET /api/threads/:id/cost, which merges these
|
|
909
|
-
* across the thread and all of its subagent descendants.
|
|
910
|
-
*/
|
|
911
|
-
getCostSummary(): Promise<{
|
|
912
|
-
totalCost: number;
|
|
913
|
-
inputCost: number;
|
|
914
|
-
cachedCost: number;
|
|
915
|
-
outputCost: number;
|
|
916
|
-
routerFeeCost: number;
|
|
917
|
-
requestCount: number;
|
|
918
|
-
messageCount: number;
|
|
919
|
-
byModel: Record<string, {
|
|
920
|
-
totalCost: number;
|
|
921
|
-
inputCost: number;
|
|
922
|
-
cachedCost: number;
|
|
923
|
-
outputCost: number;
|
|
924
|
-
routerFeeCost: number;
|
|
925
|
-
count: number;
|
|
926
|
-
}>;
|
|
927
|
-
}>;
|
|
928
|
-
/**
|
|
929
|
-
* Get specific logs, optionally including all descendant logs.
|
|
930
|
-
*/
|
|
931
|
-
getLogsByIds(ids: string[], includeDescendants?: boolean, order?: "ASC" | "DESC"): Promise<{
|
|
932
|
-
logs: {
|
|
933
|
-
id: string;
|
|
934
|
-
kind: string | null;
|
|
935
|
-
message_id: string;
|
|
936
|
-
provider: string;
|
|
937
|
-
actual_provider: string | null;
|
|
938
|
-
standard_agents_router_used: boolean;
|
|
939
|
-
model: string;
|
|
940
|
-
model_name: string | null;
|
|
941
|
-
prompt_name: string | null;
|
|
942
|
-
tools_called: string | null;
|
|
943
|
-
queued_tools: string | null;
|
|
944
|
-
provider_tools: string | null;
|
|
945
|
-
parent_log_id: string | null;
|
|
946
|
-
retry_of_log_id: string | null;
|
|
947
|
-
error: string | null;
|
|
948
|
-
error_type: string | null;
|
|
949
|
-
error_origin: string | null;
|
|
950
|
-
cost_total: number | null;
|
|
951
|
-
is_complete: boolean;
|
|
952
|
-
created_at: number;
|
|
953
|
-
}[];
|
|
954
|
-
total: number;
|
|
955
|
-
hasMore: boolean;
|
|
956
|
-
}>;
|
|
957
|
-
/**
|
|
958
|
-
* Get logs for specific messages, optionally expanding requested messages to
|
|
959
|
-
* the full contiguous workblock they belong to and including descendant logs.
|
|
960
|
-
*/
|
|
961
|
-
getLogsByMessageIds(messageIds: string[], includeWorkblocks?: boolean, includeDescendants?: boolean, order?: "ASC" | "DESC"): Promise<{
|
|
962
|
-
logs: {
|
|
963
|
-
id: string;
|
|
964
|
-
kind: string | null;
|
|
965
|
-
message_id: string;
|
|
966
|
-
provider: string;
|
|
967
|
-
actual_provider: string | null;
|
|
968
|
-
standard_agents_router_used: boolean;
|
|
969
|
-
model: string;
|
|
970
|
-
model_name: string | null;
|
|
971
|
-
prompt_name: string | null;
|
|
972
|
-
tools_called: string | null;
|
|
973
|
-
queued_tools: string | null;
|
|
974
|
-
provider_tools: string | null;
|
|
975
|
-
parent_log_id: string | null;
|
|
976
|
-
retry_of_log_id: string | null;
|
|
977
|
-
error: string | null;
|
|
978
|
-
error_type: string | null;
|
|
979
|
-
error_origin: string | null;
|
|
980
|
-
cost_total: number | null;
|
|
981
|
-
is_complete: boolean;
|
|
982
|
-
created_at: number;
|
|
983
|
-
}[];
|
|
984
|
-
total: number;
|
|
985
|
-
hasMore: boolean;
|
|
986
|
-
}>;
|
|
987
|
-
/**
|
|
988
|
-
* Scalar (non-heavy) log-detail fields plus joined source-message scalars
|
|
989
|
-
* and scheduled-effect provenance. The multi-MB TEXT columns are read one
|
|
990
|
-
* at a time via readLogDetailHeavyField so no caller ever holds them all
|
|
991
|
-
* in memory at once.
|
|
992
|
-
*/
|
|
993
|
-
private readLogDetailScalars;
|
|
994
|
-
/**
|
|
995
|
-
* Single-column reads for the multi-MB log-detail TEXT columns. Static SQL
|
|
996
|
-
* per field (never interpolated), keyed by the shared heavy-field list the
|
|
997
|
-
* streamed serializer iterates.
|
|
998
|
-
*/
|
|
999
|
-
private static readonly LOG_DETAIL_HEAVY_FIELD_SQL;
|
|
1000
|
-
private readLogDetailHeavyField;
|
|
1001
|
-
/**
|
|
1002
|
-
* Get detailed information for a single log (RPC method).
|
|
1003
|
-
*
|
|
1004
|
-
* Kept for RPC compatibility; HTTP routes use the streamed
|
|
1005
|
-
* `/internal/logs/:logId/details` fetch transport instead, because an
|
|
1006
|
-
* assembled detail object can approach the 32MiB RPC serialization cap.
|
|
1007
|
-
* `message_history` is no longer returned — it was byte-for-byte
|
|
1008
|
-
* `request_body.messages`; clients derive it from request_body.
|
|
1009
|
-
*/
|
|
1010
|
-
getLogDetails(logId: string): Promise<{
|
|
1011
|
-
request_body: string | null;
|
|
1012
|
-
response_body: string | null;
|
|
1013
|
-
tools_schema: string | null;
|
|
1014
|
-
system_prompt: string | null;
|
|
1015
|
-
tool_results: string | null;
|
|
1016
|
-
reasoning_content: string | null;
|
|
1017
|
-
source_message_content: string | null;
|
|
1018
|
-
id: string;
|
|
1019
|
-
kind: string | null;
|
|
1020
|
-
message_id: string;
|
|
1021
|
-
provider: string;
|
|
1022
|
-
actual_provider: string | null;
|
|
1023
|
-
standard_agents_router_used: boolean;
|
|
1024
|
-
model: string;
|
|
1025
|
-
model_name: string | null;
|
|
1026
|
-
endpoint: string | null;
|
|
1027
|
-
request_headers: string | null;
|
|
1028
|
-
response_headers: string | null;
|
|
1029
|
-
status_code: number | null;
|
|
1030
|
-
input_tokens: number | null;
|
|
1031
|
-
cached_tokens: number | null;
|
|
1032
|
-
output_tokens: number | null;
|
|
1033
|
-
reasoning_tokens: number | null;
|
|
1034
|
-
total_tokens: number | null;
|
|
1035
|
-
latency_ms: number | null;
|
|
1036
|
-
time_to_first_token_ms: number | null;
|
|
1037
|
-
generation_ms: number | null;
|
|
1038
|
-
finish_reason: string | null;
|
|
1039
|
-
error: string | null;
|
|
1040
|
-
error_type: string | null;
|
|
1041
|
-
error_origin: string | null;
|
|
1042
|
-
cost_input: number | null;
|
|
1043
|
-
cost_cached: number | null;
|
|
1044
|
-
cost_output: number | null;
|
|
1045
|
-
cost_router_fee: number | null;
|
|
1046
|
-
router_fee_percent: number | null;
|
|
1047
|
-
cost_total: number | null;
|
|
1048
|
-
message_history_length: number | null;
|
|
1049
|
-
tools_available: number | null;
|
|
1050
|
-
prompt_name: string | null;
|
|
1051
|
-
tools_called: string | null;
|
|
1052
|
-
queued_tools: string | null;
|
|
1053
|
-
provider_tools: string | null;
|
|
1054
|
-
parent_log_id: string | null;
|
|
1055
|
-
errors: string | null;
|
|
1056
|
-
retry_of_log_id: string | null;
|
|
1057
|
-
is_complete: boolean;
|
|
1058
|
-
created_at: number;
|
|
1059
|
-
source_message_role: string | null;
|
|
1060
|
-
source_message_created_at: number | null;
|
|
1061
|
-
source_message_metadata: string | null;
|
|
1062
|
-
scheduled_effects: string;
|
|
1063
|
-
} | null>;
|
|
1064
|
-
/**
|
|
1065
|
-
* Streamed transport for log details: same JSON shape as getLogDetails but
|
|
1066
|
-
* served as a fetch Response (no 32MiB RPC cap) whose body is written
|
|
1067
|
-
* field-by-field with backpressure, so the full multi-MB detail object is
|
|
1068
|
-
* never buffered in this DO.
|
|
1069
|
-
*/
|
|
1070
|
-
private streamLogDetails;
|
|
1071
|
-
/**
|
|
1072
|
-
* Get thread metadata (RPC method)
|
|
1073
|
-
*/
|
|
1074
|
-
getThreadMeta(threadId: string): Promise<Response | {
|
|
1075
|
-
thread: {
|
|
1076
|
-
id: any;
|
|
1077
|
-
agent_id: any;
|
|
1078
|
-
user_id: any;
|
|
1079
|
-
tags: any;
|
|
1080
|
-
parent: any;
|
|
1081
|
-
terminated: any;
|
|
1082
|
-
created_at: any;
|
|
1083
|
-
};
|
|
1084
|
-
agent: {
|
|
1085
|
-
id: any;
|
|
1086
|
-
title: any;
|
|
1087
|
-
description: any;
|
|
1088
|
-
icon: any;
|
|
1089
|
-
side_a_backing: string;
|
|
1090
|
-
side_b_backing: string;
|
|
1091
|
-
side_a_label: any;
|
|
1092
|
-
side_b_label: any;
|
|
1093
|
-
side_a_agent_prompt: string | null;
|
|
1094
|
-
side_b_agent_prompt: string | null;
|
|
1095
|
-
side_a_handler: any;
|
|
1096
|
-
side_b_handler: any;
|
|
1097
|
-
} | null;
|
|
1098
|
-
stats: {
|
|
1099
|
-
message_count: number;
|
|
1100
|
-
log_count: number;
|
|
1101
|
-
};
|
|
1102
|
-
}>;
|
|
1103
|
-
/**
|
|
1104
|
-
* Update thread metadata (RPC method)
|
|
1105
|
-
* Calls the DurableAgentBuilder to update the thread registry
|
|
1106
|
-
*/
|
|
1107
|
-
updateThreadMeta(threadId: string, params: {
|
|
1108
|
-
agent_name?: string;
|
|
1109
|
-
user_id?: string | null;
|
|
1110
|
-
tags?: string[] | null;
|
|
1111
|
-
env?: Record<string, string> | null;
|
|
1112
|
-
tenvs?: Record<string, unknown> | null;
|
|
1113
|
-
}): Promise<{
|
|
1114
|
-
success: boolean;
|
|
1115
|
-
thread: {
|
|
1116
|
-
id: any;
|
|
1117
|
-
agent_id: any;
|
|
1118
|
-
user_id: any;
|
|
1119
|
-
tags: any;
|
|
1120
|
-
created_at: any;
|
|
1121
|
-
};
|
|
1122
|
-
error?: undefined;
|
|
1123
|
-
} | {
|
|
1124
|
-
success: boolean;
|
|
1125
|
-
error: any;
|
|
1126
|
-
thread?: undefined;
|
|
1127
|
-
}>;
|
|
1128
|
-
/**
|
|
1129
|
-
* Delete thread data completely (RPC method)
|
|
1130
|
-
* This will permanently delete the Durable Object instance
|
|
1131
|
-
*/
|
|
1132
|
-
deleteThread(): Promise<{
|
|
1133
|
-
success: boolean;
|
|
1134
|
-
message: string;
|
|
1135
|
-
}>;
|
|
1136
|
-
/**
|
|
1137
|
-
* Handle WebSocket upgrade for real-time log streaming
|
|
1138
|
-
* Uses Hibernation API to reduce costs during inactivity
|
|
1139
|
-
*/
|
|
1140
|
-
private handleLogsWebSocketUpgrade;
|
|
1141
|
-
/**
|
|
1142
|
-
* Handle WebSocket upgrade for real-time message streaming
|
|
1143
|
-
* Uses Hibernation API to reduce costs during inactivity
|
|
1144
|
-
*/
|
|
1145
|
-
private handleMessagesWebSocketUpgrade;
|
|
1146
|
-
/**
|
|
1147
|
-
* Handle WebSocket upgrade for the client-tool bridge.
|
|
1148
|
-
*
|
|
1149
|
-
* A connected CLI holds this socket open. Forwarded tools send `tool_request`
|
|
1150
|
-
* frames down it and the client replies with `tool_response` frames, letting
|
|
1151
|
-
* the remotely-running agent execute filesystem/shell operations on the
|
|
1152
|
-
* user's own machine.
|
|
1153
|
-
*/
|
|
1154
|
-
private handleBridgeWebSocketUpgrade;
|
|
1155
|
-
/** Parse a raw KV value into an {@link ExecutionOwner}, or null. */
|
|
1156
|
-
private parseExecutionOwner;
|
|
1157
|
-
/** Load (and cache) the thread's persisted execution-owner record. */
|
|
1158
|
-
private getExecutionOwner;
|
|
1159
|
-
/** Owner id from the in-memory mirror only (for sync paths); null when
|
|
1160
|
-
* unloaded or unowned — both degrade to the historical any-socket rule. */
|
|
1161
|
-
private currentExecutionOwnerId;
|
|
1162
|
-
/** Persist + cache the execution-owner record (null releases ownership). */
|
|
1163
|
-
private setExecutionOwner;
|
|
1164
|
-
/** Whether the given client id has an open bridge socket (excluding `except`).
|
|
1165
|
-
* Idle bridge heartbeats are handled by Cloudflare without waking this object,
|
|
1166
|
-
* so timestamp liveness is intentionally enforced only for an in-flight call. */
|
|
1167
|
-
private hasLiveBridgeSocketForClient;
|
|
1168
|
-
/** Tell every other bridge socket that execution ownership moved. */
|
|
1169
|
-
private broadcastOwnerChanged;
|
|
1170
|
-
/** Whether any forwarded call is mid-flight (blocking await or parked). */
|
|
1171
|
-
hasInFlightClientCalls(): Promise<boolean>;
|
|
1172
|
-
/**
|
|
1173
|
-
* Ownership moved away from a dead client: settle everything that was
|
|
1174
|
-
* dispatched to it. In-memory blocking calls fail immediately; parked
|
|
1175
|
-
* durable calls get an error result and the turn resumes — re-sending them
|
|
1176
|
-
* to the NEW owner would silently re-run the operation on a different
|
|
1177
|
-
* machine's filesystem, which is worse than an honest retryable error.
|
|
1178
|
-
*/
|
|
1179
|
-
private failStalePendingWork;
|
|
1180
|
-
/**
|
|
1181
|
-
* Forward a tool operation to a connected bridge client and await its result.
|
|
1182
|
-
*
|
|
1183
|
-
* Returns a structured response rather than throwing so forwarded tools can
|
|
1184
|
-
* always produce a normal tool error (no client connected, timeout, or user
|
|
1185
|
-
* denial) for the model to reason about.
|
|
1186
|
-
*/
|
|
1187
|
-
callClientTool(request: ClientToolRequest, durability?: {
|
|
1188
|
-
toolCallId: string;
|
|
1189
|
-
side: "a" | "b";
|
|
1190
|
-
}): Promise<ClientToolResponse>;
|
|
1191
|
-
/** Settle a pending forwarded call exactly once, clearing its timers. */
|
|
1192
|
-
private settleClientCall;
|
|
1193
|
-
/** Close and forget a bridge socket we've deemed dead, failing remaining calls. */
|
|
1194
|
-
private markBridgeDead;
|
|
1195
|
-
/**
|
|
1196
|
-
* Return the bridge socket a forwarded call should be dispatched to, pruning
|
|
1197
|
-
* closed ones. Idle clients use Cloudflare's hibernation auto-response, so
|
|
1198
|
-
* their frames deliberately do not update `bridgeLastSeen`. Once a call is
|
|
1199
|
-
* dispatched, the client switches to application-visible pings and the
|
|
1200
|
-
* in-flight liveness timer above detects a half-open connection.
|
|
1201
|
-
*
|
|
1202
|
-
* With an execution owner recorded, only the owner's socket (or, as a
|
|
1203
|
-
* back-compat fallback, an unidentified legacy socket) is eligible; with no
|
|
1204
|
-
* owner, the first live socket wins as it always has.
|
|
1205
|
-
*/
|
|
1206
|
-
private getOpenBridgeSocket;
|
|
1207
|
-
/** Resolve an in-flight forwarded tool call from a client `tool_response`. */
|
|
1208
|
-
private resolveClientCall;
|
|
1209
|
-
/**
|
|
1210
|
-
* When the last bridge client that could serve forwarded calls disconnects,
|
|
1211
|
-
* fail any in-flight ones so the agent loop doesn't hang waiting on a client
|
|
1212
|
-
* that is gone. Uses the in-memory owner mirror (sync path); when the mirror
|
|
1213
|
-
* isn't loaded this degrades to the historical any-socket check, and the
|
|
1214
|
-
* per-call liveness interval still catches a dead dispatch target.
|
|
1215
|
-
*/
|
|
1216
|
-
private failPendingClientCallsIfNoBridge;
|
|
1217
|
-
/** Whether a bridge client that can execute forwarded calls is connected
|
|
1218
|
-
* right now (used to decide durable park). */
|
|
1219
|
-
hasBridge(): Promise<boolean>;
|
|
1220
|
-
private ensurePendingClientTable;
|
|
1221
|
-
/**
|
|
1222
|
-
* Durably dispatch a forwarded tool call WITHOUT blocking the agent loop.
|
|
1223
|
-
* Persists the request, sends it to the connected client (best effort), and
|
|
1224
|
-
* returns immediately. The client later delivers the result via
|
|
1225
|
-
* {@link deliverClientToolResult}, which resumes execution.
|
|
1226
|
-
*/
|
|
1227
|
-
dispatchClientTool(request: ClientToolRequest, toolCallId: string, side: "a" | "b"): Promise<{
|
|
1228
|
-
dispatched: boolean;
|
|
1229
|
-
}>;
|
|
1230
|
-
/**
|
|
1231
|
-
* Send one durable `tool_request` frame to the bridge if a client is
|
|
1232
|
-
* connected — and stamp the pending row with the identity+generation it was
|
|
1233
|
-
* dispatched to, fencing the eventual HTTP delivery to that client. A
|
|
1234
|
-
* legacy (unidentified) executor leaves the row unstamped, keeping the
|
|
1235
|
-
* historical accept-anything delivery for old CLIs.
|
|
1236
|
-
*/
|
|
1237
|
-
private sendClientToolRequest;
|
|
1238
|
-
/**
|
|
1239
|
-
* The delivered result of a parked forwarded call, if the client has
|
|
1240
|
-
* already resolved it — lets the approval-park path grace-wait briefly and
|
|
1241
|
-
* return the REAL result inline instead of a "⏳ Awaiting your approval…"
|
|
1242
|
-
* placeholder. Instant auto-accepts (the common case: the client's saved
|
|
1243
|
-
* permission level covers the call) otherwise race the placeholder into
|
|
1244
|
-
* stored history, leaving the model blind to its own tool outcomes.
|
|
1245
|
-
*/
|
|
1246
|
-
/**
|
|
1247
|
-
* In-memory waiters parked on a forwarded call's result delivery (AB-09).
|
|
1248
|
-
* `deliverClientToolResult` resolves them so the approval grace-wait reads
|
|
1249
|
-
* delivered state exactly once instead of re-polling it every 150ms.
|
|
1250
|
-
* In-memory only: a DO restart drops waiters along with the caller that
|
|
1251
|
-
* registered them, and the durable park path still resumes the turn.
|
|
1252
|
-
*/
|
|
1253
|
-
private deliveredResultWaiters;
|
|
1254
|
-
private notifyDeliveredResultWaiters;
|
|
1255
|
-
/**
|
|
1256
|
-
* Await a parked forwarded call's delivered result: one immediate read,
|
|
1257
|
-
* then a single parked wait resolved by result delivery, bounded by one
|
|
1258
|
-
* hard deadline, then one final read. Replaces the caller-side 150ms
|
|
1259
|
-
* re-poll of {@link getDeliveredClientToolResult}.
|
|
1260
|
-
*/
|
|
1261
|
-
awaitDeliveredClientToolResult(toolCallId: string, maxWaitMs: number): Promise<{
|
|
1262
|
-
content: string;
|
|
1263
|
-
toolStatus: string | null;
|
|
1264
|
-
} | null>;
|
|
1265
|
-
getDeliveredClientToolResult(toolCallId: string): Promise<{
|
|
1266
|
-
content: string;
|
|
1267
|
-
toolStatus: string | null;
|
|
1268
|
-
} | null>;
|
|
1269
|
-
/** Still-pending durable forwarded calls (for re-sending after a reconnect). */
|
|
1270
|
-
getPendingClientCalls(): Promise<Array<{
|
|
1271
|
-
toolCallId: string;
|
|
1272
|
-
tool: string;
|
|
1273
|
-
args: Record<string, unknown>;
|
|
1274
|
-
requestPermission: string | null;
|
|
1275
|
-
risk: number | null;
|
|
1276
|
-
}>>;
|
|
1277
|
-
/** Re-send all pending durable requests to a freshly connected bridge socket. */
|
|
1278
|
-
private resendPendingClientCalls;
|
|
1279
|
-
/**
|
|
1280
|
-
* Deliver a client's result for a durable forwarded call: rewrite the parked
|
|
1281
|
-
* "awaiting" placeholder tool-result message to the real result and mark the
|
|
1282
|
-
* call resolved. Returns the side to continue, or null if there is no pending
|
|
1283
|
-
* call (unknown id or already resolved — the delivery is idempotent).
|
|
1284
|
-
*/
|
|
1285
|
-
deliverClientToolResult(toolCallId: string, ok: boolean, result?: string, error?: string, deliveredByClientId?: string, deliveredGeneration?: number, deliveryToken?: string, internalAuthorization?: typeof INTERNAL_TOOL_DELIVERY): Promise<{
|
|
1286
|
-
side: "a" | "b";
|
|
1287
|
-
} | null>;
|
|
1288
|
-
/** Default time to wait for the client to accept a stream open. */
|
|
1289
|
-
private static readonly CLIENT_STREAM_OPEN_TIMEOUT_MS;
|
|
1290
|
-
/**
|
|
1291
|
-
* In-memory waiters parked on the owner's bridge socket returning (AB-09).
|
|
1292
|
-
* Resolved by bridge attach and by execution-owner changes; each waiter
|
|
1293
|
-
* re-evaluates against the CURRENT owner on wake. In-memory only: a DO
|
|
1294
|
-
* restart drops waiters with the stream-open call that registered them.
|
|
1295
|
-
*/
|
|
1296
|
-
private ownerBridgeWaiters;
|
|
1297
|
-
private notifyOwnerBridgeWaiters;
|
|
1298
|
-
/**
|
|
1299
|
-
* The thread HAS an elected execution owner, but its bridge socket is gone
|
|
1300
|
-
* (daemon restart, network blip, DO handoff). Summon the owning machine
|
|
1301
|
-
* through the per-user hub and wait for a bridge to re-attach instead of
|
|
1302
|
-
* failing the stream open instantly — that instant failure is what ended
|
|
1303
|
-
* Sama One turns with "workspace unavailable" whenever a slow tool/approval
|
|
1304
|
-
* outlived the socket. Threads with NO recorded owner (subagent children)
|
|
1305
|
-
* still fail fast so ancestor walk-up routing stays immediate.
|
|
1306
|
-
*
|
|
1307
|
-
* The wait parks on bridge-attach/owner-change signals under ONE hard
|
|
1308
|
-
* deadline — no re-poll cadence. Each wake re-reads the owner because the
|
|
1309
|
-
* returning daemon may reclaim with a new generation, and the socket must
|
|
1310
|
-
* match the CURRENT owner.
|
|
1311
|
-
*/
|
|
1312
|
-
private awaitOwnerBridgeSocket;
|
|
1313
|
-
private parseProxyStreamAttachments;
|
|
1314
|
-
/** Keep live proxy routes on the hibernating bridge socket for restart cleanup. */
|
|
1315
|
-
private updateBridgeProxyAttachment;
|
|
1316
|
-
private deliverProxyStreamFrame;
|
|
1317
|
-
/** Abort live proxy routes restored without their in-memory stream state. */
|
|
1318
|
-
private recoverInterruptedProxyStreams;
|
|
1319
|
-
/** Register the child side before any ancestor opens an owner stream. */
|
|
1320
|
-
createProxyStreamReceiver(onCancel: (error?: string) => void): ProxyStreamReceiver;
|
|
1321
|
-
proxyStreamReceiverExists(receiverId: string): Promise<boolean>;
|
|
1322
|
-
proxyStreamReceive(receiverId: string, frame: ProxyStreamFrame): Promise<boolean>;
|
|
1323
|
-
/** Open a bidirectional byte stream to the connected owner client. */
|
|
1324
|
-
openClientStream(request: ClientStreamRequest, proxyTarget?: ProxyStreamTarget | null): Promise<ClientStreamResponse>;
|
|
1325
|
-
proxyStreamOpen(request: ClientStreamRequest, target: ProxyStreamTarget): Promise<ProxyStreamOpenResult>;
|
|
1326
|
-
proxyStreamWrite(id: string, dataB64: string): Promise<void>;
|
|
1327
|
-
proxyStreamEnd(id: string): Promise<void>;
|
|
1328
|
-
proxyStreamAbort(id: string): Promise<void>;
|
|
1329
|
-
private forgetEventProxyStream;
|
|
1330
|
-
/** Settle and remove a client stream exactly once. */
|
|
1331
|
-
private settleClientStream;
|
|
1332
|
-
/** Abort a stream from the Worker side, telling the client to tear down. */
|
|
1333
|
-
private abortClientStream;
|
|
1334
|
-
/** Handle an incoming stream_* frame from a bridge client. */
|
|
1335
|
-
private handleClientStreamFrame;
|
|
1336
|
-
/** Fail every stream bound to a socket that closed or died. */
|
|
1337
|
-
private failClientStreamsForSocket;
|
|
1338
|
-
/** How long a parked forwarded call waits for a client before failing visibly. */
|
|
1339
|
-
private static readonly CLIENT_PARK_TTL_MS;
|
|
1340
|
-
/**
|
|
1341
|
-
* A forwarded call parked with NO client attached: ask the user's hub to
|
|
1342
|
-
* summon the owning machine's daemon to this thread, and arm the bounded
|
|
1343
|
-
* park TTL that turns an unreachable host into a visible durable failure
|
|
1344
|
-
* instead of a silent hang.
|
|
1345
|
-
*/
|
|
1346
|
-
notifyClientWaiting(toolCallId: string, threadId: string, userId: string | null): Promise<void>;
|
|
1347
|
-
/** Ask the user's hub to summon the owning machine's daemon to a thread.
|
|
1348
|
-
* Best-effort: wake failure must never fail the caller's own path. */
|
|
1349
|
-
private requestHubWake;
|
|
1350
|
-
/**
|
|
1351
|
-
* Park TTL expired: if the call is still pending, settle it as a durable,
|
|
1352
|
-
* VISIBLE failure — rewrite the waiting placeholder, mark the pending row
|
|
1353
|
-
* failed, fail any still-pending assistant messages, and persist a durable
|
|
1354
|
-
* failed assistant message so every connected head settles instead of
|
|
1355
|
-
* showing "Working" forever.
|
|
1356
|
-
*/
|
|
1357
|
-
private failParkedClientCall;
|
|
1358
|
-
/**
|
|
1359
|
-
* Broadcast a log record to all connected WebSocket clients
|
|
1360
|
-
*/
|
|
1361
|
-
private broadcastLog;
|
|
1362
|
-
/**
|
|
1363
|
-
* Broadcast a message record to all connected message WebSocket clients
|
|
1364
|
-
* Filters silent messages based on each socket's includeSilent preference
|
|
1365
|
-
*/
|
|
1366
|
-
private broadcastMessage;
|
|
1367
|
-
/**
|
|
1368
|
-
* The FlowEngine's message emit path: broadcast the record, and stamp
|
|
1369
|
-
* message recency when it is the thread's visible terminal assistant reply.
|
|
1370
|
-
*
|
|
1371
|
-
* This is the frame a client's reducer consumes to retire its provisional
|
|
1372
|
-
* draft, so it is the one place where "the user has something new to read"
|
|
1373
|
-
* is known. The stamp deliberately does NOT carry a preview: previews are
|
|
1374
|
-
* row labels and stay keyed to the user's own message, while recency has to
|
|
1375
|
-
* follow the agent's reply.
|
|
1376
|
-
*/
|
|
1377
|
-
private emitFlowMessage;
|
|
1378
|
-
private broadcastMessageWithSubagentProjection;
|
|
1379
|
-
/**
|
|
1380
|
-
* Broadcast a content chunk for real-time streaming
|
|
1381
|
-
* Does NOT update database - only broadcasts to connected clients
|
|
1382
|
-
*/
|
|
1383
|
-
private broadcastMessageChunk;
|
|
1384
|
-
/**
|
|
1385
|
-
* Broadcast an internal-reasoning chunk for real-time streaming.
|
|
1386
|
-
*
|
|
1387
|
-
* OPT-IN per the spec (`ThreadReasoningChunkEvent`): only sockets that
|
|
1388
|
-
* subscribed with `?reasoning=1` receive it. Like content chunks it does NOT
|
|
1389
|
-
* touch the database — reasoning is ephemeral display output.
|
|
1390
|
-
*/
|
|
1391
|
-
private broadcastReasoningChunk;
|
|
1392
|
-
/**
|
|
1393
|
-
* Broadcast a telemetry event to all connected message WebSocket clients
|
|
1394
|
-
* Used for execution status updates (step_started, tool_started, etc.)
|
|
1395
|
-
*/
|
|
1396
|
-
private broadcastTelemetry;
|
|
1397
|
-
/**
|
|
1398
|
-
* Broadcast a custom event to all connected message WebSocket clients
|
|
1399
|
-
* Used by tools via emitThreadEvent() to send user-defined events
|
|
1400
|
-
*/
|
|
1401
|
-
emitThreadEvent(_threadId: string, type: string, data: unknown): void;
|
|
1402
|
-
private broadcastEvent;
|
|
1403
|
-
/**
|
|
1404
|
-
* WebSocket Hibernation API handler for incoming messages
|
|
1405
|
-
* Called when a message is received on a hibernated WebSocket
|
|
1406
|
-
*/
|
|
1407
|
-
webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): Promise<void>;
|
|
1408
|
-
/**
|
|
1409
|
-
* WebSocket Hibernation API handler for connection close
|
|
1410
|
-
* Called when a WebSocket connection is closed
|
|
1411
|
-
* Note: Do NOT call ws.close() here - the connection is already closed
|
|
1412
|
-
*/
|
|
1413
|
-
webSocketClose(ws: WebSocket, _code: number, _reason: string, _wasClean: boolean): Promise<void>;
|
|
1414
|
-
/**
|
|
1415
|
-
* WebSocket Hibernation API handler for errors
|
|
1416
|
-
* Called when a WebSocket encounters an error
|
|
1417
|
-
*/
|
|
1418
|
-
webSocketError(ws: WebSocket, error: unknown): Promise<void>;
|
|
1419
|
-
/**
|
|
1420
|
-
* Alarm handler - called by Cloudflare when a scheduled alarm fires
|
|
1421
|
-
* Processes the next item in the alarm queue
|
|
1422
|
-
*
|
|
1423
|
-
* Important: This method must NEVER throw an exception, as that would break
|
|
1424
|
-
* the alarm chain. All errors are caught and logged.
|
|
1425
|
-
*/
|
|
1426
|
-
alarm(): Promise<void>;
|
|
1427
|
-
/** Persist a reversible emergency stop without scanning or deleting thread data. */
|
|
1428
|
-
emergencyQuarantine(input: RuntimeQuarantineInput): Promise<RuntimeSafetyStatus>;
|
|
1429
|
-
/** Return the low-cost quarantine status used by Brolly and diagnostics. */
|
|
1430
|
-
getRuntimeSafetyStatus(): Promise<RuntimeSafetyStatus>;
|
|
1431
|
-
/** Resume only through an explicit idempotent action; forensic holds need release. */
|
|
1432
|
-
emergencyResume(input: {
|
|
1433
|
-
actionId: string;
|
|
1434
|
-
reason: string;
|
|
1435
|
-
releaseForensicHold?: boolean;
|
|
1436
|
-
}): Promise<RuntimeSafetyStatus>;
|
|
1437
|
-
/** Heartbeat: called by LLMRequest on each attempt and streamed chunk. */
|
|
1438
|
-
noteExecutionProgress(): void;
|
|
1439
|
-
/**
|
|
1440
|
-
* The per-thread companion watchdog DO (ThreadWatchdog), derived from the
|
|
1441
|
-
* thread id. It exists because this thread's OWN alarm cannot fire while a
|
|
1442
|
-
* queue-dispatched turn runs inside alarm() — the companion delivers the
|
|
1443
|
-
* same check via RPC, which interleaves at await points even mid-turn.
|
|
1444
|
-
* Returns null on deployments whose generated config predates the binding.
|
|
1445
|
-
*/
|
|
1446
|
-
private watchdogCompanion;
|
|
1447
|
-
/**
|
|
1448
|
-
* Stamp thread activity on the registry so thread lists can sort by recency
|
|
1449
|
-
* of real work and show which threads are executing right now. Registry
|
|
1450
|
-
* bookkeeping is presentation state: a failure here must never take down the
|
|
1451
|
-
* turn that triggered it.
|
|
1452
|
-
*/
|
|
1453
|
-
private recordRegistryActivity;
|
|
1454
|
-
/**
|
|
1455
|
-
* The newest non-empty user message on this thread, for thread-list previews.
|
|
1456
|
-
* Returns null when the thread has none. The Durable Object does not know its
|
|
1457
|
-
* own thread id, so the caller is the one that stamps the registry.
|
|
1458
|
-
*/
|
|
1459
|
-
getLatestUserMessagePreview(): Promise<string | null>;
|
|
1460
|
-
/** Arm the standing watchdog for an execution start. One pending row max. */
|
|
1461
|
-
private armExecutionWatchdog;
|
|
1462
|
-
/** Disarm on clean execution end. Completed check rows are noise, not history. */
|
|
1463
|
-
private disarmExecutionWatchdog;
|
|
1464
|
-
/**
|
|
1465
|
-
* The standing check, alarm-queue delivery. Evaluates the thread's state AT
|
|
1466
|
-
* FIRE TIME — it knows nothing about whichever request was in flight when it
|
|
1467
|
-
* was armed. NOTE this delivery path cannot fire while a queue-dispatched
|
|
1468
|
-
* turn runs (the turn owns this DO's single alarm invocation); the
|
|
1469
|
-
* ThreadWatchdog companion delivers the same assessment via watchdogProbe()
|
|
1470
|
-
* in exactly that window.
|
|
1471
|
-
*/
|
|
1472
|
-
private watchdogCheck;
|
|
1473
|
-
/**
|
|
1474
|
-
* RPC delivery of the standing check — called by the ThreadWatchdog
|
|
1475
|
-
* companion (and the diagnostics revive endpoint). Runs in a fresh request
|
|
1476
|
-
* context, so it interleaves with a running turn at await points and its
|
|
1477
|
-
* own awaits/timers are alive even when a wedged turn's context is frozen.
|
|
1478
|
-
* Does NOT touch the internal watchdogCheck alarm rows — those belong to
|
|
1479
|
-
* the alarm delivery path.
|
|
1480
|
-
*/
|
|
1481
|
-
watchdogProbe(threadId: string): Promise<WatchdogProbeResult>;
|
|
1482
|
-
/**
|
|
1483
|
-
* Reset this Durable Object instance on request. Used by the watchdog
|
|
1484
|
-
* companion after a wedged-executor takeover: the zombie turn may still own
|
|
1485
|
-
* this DO's single alarm invocation, which would block the just-enqueued
|
|
1486
|
-
* recovery alarm forever. Aborting guarantees a fresh instance whose alarm
|
|
1487
|
-
* chain re-arms from persisted queue state on first wake.
|
|
1488
|
-
*/
|
|
1489
|
-
forceRestart(reason: string): Promise<void>;
|
|
1490
|
-
/**
|
|
1491
|
-
* Execution-health snapshot for the diagnostics endpoint and `agents diag`.
|
|
1492
|
-
* Exposes the state the 2026-07-08 post-mortem could not see from outside:
|
|
1493
|
-
* the alarm queue (was a turn item pending/processing/failed? was the
|
|
1494
|
-
* watchdog row gone?), the volatile execution flags, and open request logs.
|
|
1495
|
-
* Read-only; safe to call at any time.
|
|
1496
|
-
*/
|
|
1497
|
-
getDiagnostics(): Promise<{
|
|
1498
|
-
executing: boolean;
|
|
1499
|
-
lastProgressAt: number | null;
|
|
1500
|
-
silenceMs: number | null;
|
|
1501
|
-
watchdogStrikes: number;
|
|
1502
|
-
watchdogCeilingMs: number;
|
|
1503
|
-
stopped: boolean;
|
|
1504
|
-
runtimeSafety: RuntimeSafetyStatus;
|
|
1505
|
-
incompleteLogs: Array<{
|
|
1506
|
-
id: string;
|
|
1507
|
-
model: string | null;
|
|
1508
|
-
provider: string | null;
|
|
1509
|
-
created_at: number;
|
|
1510
|
-
}>;
|
|
1511
|
-
alarmQueue: Array<{
|
|
1512
|
-
id: string;
|
|
1513
|
-
method: string;
|
|
1514
|
-
status: string;
|
|
1515
|
-
scheduled_at: number;
|
|
1516
|
-
created_at: number;
|
|
1517
|
-
attempts: number;
|
|
1518
|
-
error: string | null;
|
|
1519
|
-
}>;
|
|
1520
|
-
messageQueueCount: number;
|
|
1521
|
-
contextUsage: Record<string, unknown> | null;
|
|
1522
|
-
}>;
|
|
1523
|
-
/**
|
|
1524
|
-
* The shared watchdog decision core. Both deliveries (alarm + companion
|
|
1525
|
-
* probe) evaluate and ACT through this method; the caller only decides what
|
|
1526
|
-
* to do with its own scheduling based on the verdict.
|
|
1527
|
-
*/
|
|
1528
|
-
private performWatchdogAssessment;
|
|
1529
|
-
/** Mark logs the dead executor abandoned, and tell connected clients. */
|
|
1530
|
-
private finalizeLostExecutionLogs;
|
|
1531
|
-
/**
|
|
1532
|
-
* A subagent whose execution the watchdog gave up on leaves its parent
|
|
1533
|
-
* waiting forever for a completion message. Deliver the failure the same way
|
|
1534
|
-
* a sessionFail would, so the parent's turn wakes and can route around it.
|
|
1535
|
-
* Explicit-communication children (e.g. the compaction agent) stay quiet by
|
|
1536
|
-
* contract — only the registry status updates for those.
|
|
1537
|
-
*/
|
|
1538
|
-
private notifyParentOfLostExecution;
|
|
1539
|
-
/** At most N auto-resumes per rolling window, tracked durably. */
|
|
1540
|
-
private consumeWatchdogResumeBudget;
|
|
1541
|
-
private normalizePlainRecord;
|
|
1542
|
-
private buildExecutionArguments;
|
|
1543
|
-
/**
|
|
1544
|
-
* Internal method: Execute a flow (called by alarm queue)
|
|
1545
|
-
* This is the actual execution logic, separate from the public execute() RPC method
|
|
1546
|
-
*/
|
|
1547
|
-
private executeFlow;
|
|
1548
|
-
/**
|
|
1549
|
-
* Internal method: Execute an effect (called by alarm queue)
|
|
1550
|
-
* Effects run outside the tool execution context.
|
|
1551
|
-
*/
|
|
1552
|
-
private executeEffect;
|
|
1553
|
-
/**
|
|
1554
|
-
* Internal method: Process a message (called by alarm queue)
|
|
1555
|
-
* This is the actual message processing logic, separate from the public sendMessage() RPC method
|
|
1556
|
-
*/
|
|
1557
|
-
private processMessage;
|
|
1558
|
-
/**
|
|
1559
|
-
* Internal method: Continue execution without adding a message (called by alarm queue)
|
|
1560
|
-
* This allows resuming FlowEngine execution from where it stopped.
|
|
1561
|
-
*/
|
|
1562
|
-
private doContinueExecution;
|
|
1563
|
-
private getLatestQueuedMessageSide;
|
|
1564
|
-
/**
|
|
1565
|
-
* TEST METHOD: Queue a test operation
|
|
1566
|
-
* Used for testing alarm queue ordering and timing
|
|
1567
|
-
*/
|
|
1568
|
-
queueTestOperation(id: string, label: string, expectedOrder: number, delayMs: number): Promise<Response>;
|
|
1569
|
-
/**
|
|
1570
|
-
* TEST METHOD: Get queue state
|
|
1571
|
-
*/
|
|
1572
|
-
getQueueState(): Promise<Response>;
|
|
1573
|
-
/**
|
|
1574
|
-
* TEST METHOD: Get test execution logs
|
|
1575
|
-
*/
|
|
1576
|
-
getTestLogs(): Promise<Response>;
|
|
1577
|
-
/**
|
|
1578
|
-
* TEST METHOD: Clear test logs
|
|
1579
|
-
*/
|
|
1580
|
-
clearTestLogs(): Promise<Response>;
|
|
1581
|
-
/**
|
|
1582
|
-
* TEST METHOD: Insert a malformed message with orphaned tool calls
|
|
1583
|
-
* This allows testing the tool call filtering logic
|
|
1584
|
-
*/
|
|
1585
|
-
insertOrphanedToolCall(params: {
|
|
1586
|
-
content?: string;
|
|
1587
|
-
toolCallId: string;
|
|
1588
|
-
toolName: string;
|
|
1589
|
-
toolArgs: string;
|
|
1590
|
-
}): Promise<Response>;
|
|
1591
|
-
/**
|
|
1592
|
-
* TEST METHOD: Execute a test operation
|
|
1593
|
-
* Internal method called by alarm queue
|
|
1594
|
-
*/
|
|
1595
|
-
private testOperation;
|
|
1596
|
-
/**
|
|
1597
|
-
* Get file storage helper instance
|
|
1598
|
-
*/
|
|
1599
|
-
private getFileStorage;
|
|
1600
|
-
/**
|
|
1601
|
-
* Write a file to storage (RPC method)
|
|
1602
|
-
*/
|
|
1603
|
-
writeFile(path: string, data: string, // base64 encoded
|
|
1604
|
-
mimeType: string, options?: {
|
|
1605
|
-
metadata?: Record<string, unknown>;
|
|
1606
|
-
thumbnail?: string;
|
|
1607
|
-
}): Promise<{
|
|
1608
|
-
success: boolean;
|
|
1609
|
-
file: any;
|
|
1610
|
-
error?: undefined;
|
|
1611
|
-
} | {
|
|
1612
|
-
success: boolean;
|
|
1613
|
-
error: any;
|
|
1614
|
-
file?: undefined;
|
|
1615
|
-
}>;
|
|
1616
|
-
/**
|
|
1617
|
-
* Write a text file to storage (RPC method)
|
|
1618
|
-
*/
|
|
1619
|
-
writeTextFile(path: string, content: string, mimeType?: string, options?: {
|
|
1620
|
-
metadata?: Record<string, unknown>;
|
|
1621
|
-
}): Promise<{
|
|
1622
|
-
success: boolean;
|
|
1623
|
-
file: any;
|
|
1624
|
-
error?: undefined;
|
|
1625
|
-
} | {
|
|
1626
|
-
success: boolean;
|
|
1627
|
-
error: any;
|
|
1628
|
-
file?: undefined;
|
|
1629
|
-
}>;
|
|
1630
|
-
/**
|
|
1631
|
-
* Process an image using sip (WASM-based image processing)
|
|
1632
|
-
* This runs inside the DO where WASM is properly initialized.
|
|
1633
|
-
*
|
|
1634
|
-
* @param data - base64 encoded image data
|
|
1635
|
-
* @param mimeType - MIME type of the input image
|
|
1636
|
-
* @returns Processed image data, dimensions, and mimeType
|
|
1637
|
-
*/
|
|
1638
|
-
processImage(data: string, mimeType: string): Promise<{
|
|
1639
|
-
success: boolean;
|
|
1640
|
-
data?: string;
|
|
1641
|
-
mimeType?: string;
|
|
1642
|
-
width?: number;
|
|
1643
|
-
height?: number;
|
|
1644
|
-
error?: string;
|
|
1645
|
-
}>;
|
|
1646
|
-
/**
|
|
1647
|
-
* Link to an external file (RPC method)
|
|
1648
|
-
*/
|
|
1649
|
-
linkFile(path: string, location: string, options?: {
|
|
1650
|
-
mimeType?: string;
|
|
1651
|
-
size?: number;
|
|
1652
|
-
metadata?: Record<string, unknown>;
|
|
1653
|
-
}): Promise<{
|
|
1654
|
-
success: boolean;
|
|
1655
|
-
file: any;
|
|
1656
|
-
error?: undefined;
|
|
1657
|
-
} | {
|
|
1658
|
-
success: boolean;
|
|
1659
|
-
error: any;
|
|
1660
|
-
file?: undefined;
|
|
1661
|
-
}>;
|
|
1662
|
-
/**
|
|
1663
|
-
* Read a file from storage (RPC method)
|
|
1664
|
-
* Returns base64-encoded data
|
|
1665
|
-
*/
|
|
1666
|
-
readFile(path: string): Promise<{
|
|
1667
|
-
success: boolean;
|
|
1668
|
-
data: string;
|
|
1669
|
-
error?: undefined;
|
|
1670
|
-
} | {
|
|
1671
|
-
success: boolean;
|
|
1672
|
-
error: any;
|
|
1673
|
-
data?: undefined;
|
|
1674
|
-
}>;
|
|
1675
|
-
/**
|
|
1676
|
-
* Read a text file from storage (RPC method)
|
|
1677
|
-
*/
|
|
1678
|
-
readTextFile(path: string): Promise<{
|
|
1679
|
-
success: boolean;
|
|
1680
|
-
content: any;
|
|
1681
|
-
error?: undefined;
|
|
1682
|
-
} | {
|
|
1683
|
-
success: boolean;
|
|
1684
|
-
error: any;
|
|
1685
|
-
content?: undefined;
|
|
1686
|
-
}>;
|
|
1687
|
-
/**
|
|
1688
|
-
* Get file metadata (RPC method)
|
|
1689
|
-
*/
|
|
1690
|
-
statFile(path: string): Promise<{
|
|
1691
|
-
success: boolean;
|
|
1692
|
-
file: any;
|
|
1693
|
-
error?: undefined;
|
|
1694
|
-
} | {
|
|
1695
|
-
success: boolean;
|
|
1696
|
-
error: any;
|
|
1697
|
-
file?: undefined;
|
|
1698
|
-
}>;
|
|
1699
|
-
/**
|
|
1700
|
-
* Check if file exists (RPC method)
|
|
1701
|
-
*/
|
|
1702
|
-
fileExists(path: string): Promise<{
|
|
1703
|
-
success: boolean;
|
|
1704
|
-
exists: any;
|
|
1705
|
-
error?: undefined;
|
|
1706
|
-
} | {
|
|
1707
|
-
success: boolean;
|
|
1708
|
-
error: any;
|
|
1709
|
-
exists?: undefined;
|
|
1710
|
-
}>;
|
|
1711
|
-
/**
|
|
1712
|
-
* Delete a file (RPC method)
|
|
1713
|
-
*/
|
|
1714
|
-
unlinkFile(path: string): Promise<{
|
|
1715
|
-
success: boolean;
|
|
1716
|
-
error?: undefined;
|
|
1717
|
-
} | {
|
|
1718
|
-
success: boolean;
|
|
1719
|
-
error: any;
|
|
1720
|
-
}>;
|
|
1721
|
-
/**
|
|
1722
|
-
* Create a directory (RPC method)
|
|
1723
|
-
*/
|
|
1724
|
-
mkdirFile(path: string): Promise<{
|
|
1725
|
-
success: boolean;
|
|
1726
|
-
directory: any;
|
|
1727
|
-
error?: undefined;
|
|
1728
|
-
} | {
|
|
1729
|
-
success: boolean;
|
|
1730
|
-
error: any;
|
|
1731
|
-
directory?: undefined;
|
|
1732
|
-
}>;
|
|
1733
|
-
/**
|
|
1734
|
-
* List directory contents (RPC method)
|
|
1735
|
-
*/
|
|
1736
|
-
readdirFile(path: string): Promise<{
|
|
1737
|
-
success: boolean;
|
|
1738
|
-
files: any;
|
|
1739
|
-
error?: undefined;
|
|
1740
|
-
} | {
|
|
1741
|
-
success: boolean;
|
|
1742
|
-
error: any;
|
|
1743
|
-
files?: undefined;
|
|
1744
|
-
}>;
|
|
1745
|
-
/**
|
|
1746
|
-
* Remove empty directory (RPC method)
|
|
1747
|
-
*/
|
|
1748
|
-
rmdirFile(path: string): Promise<{
|
|
1749
|
-
success: boolean;
|
|
1750
|
-
error?: undefined;
|
|
1751
|
-
} | {
|
|
1752
|
-
success: boolean;
|
|
1753
|
-
error: any;
|
|
1754
|
-
}>;
|
|
1755
|
-
/**
|
|
1756
|
-
* Move or rename a file or directory (RPC method).
|
|
1757
|
-
* Relocates inline files, chunked files, and whole directory subtrees.
|
|
1758
|
-
*/
|
|
1759
|
-
moveFile(sourcePath: string, destinationPath: string): Promise<{
|
|
1760
|
-
success: boolean;
|
|
1761
|
-
file: any;
|
|
1762
|
-
error?: undefined;
|
|
1763
|
-
} | {
|
|
1764
|
-
success: boolean;
|
|
1765
|
-
error: any;
|
|
1766
|
-
file?: undefined;
|
|
1767
|
-
}>;
|
|
1768
|
-
/**
|
|
1769
|
-
* Rename a file or directory in place (RPC method).
|
|
1770
|
-
*/
|
|
1771
|
-
renameFile(path: string, newName: string): Promise<{
|
|
1772
|
-
success: boolean;
|
|
1773
|
-
file: any;
|
|
1774
|
-
error?: undefined;
|
|
1775
|
-
} | {
|
|
1776
|
-
success: boolean;
|
|
1777
|
-
error: any;
|
|
1778
|
-
file?: undefined;
|
|
1779
|
-
}>;
|
|
1780
|
-
/**
|
|
1781
|
-
* Get file storage statistics (RPC method)
|
|
1782
|
-
*/
|
|
1783
|
-
getFileStats(): Promise<{
|
|
1784
|
-
success: boolean;
|
|
1785
|
-
stats: any;
|
|
1786
|
-
error?: undefined;
|
|
1787
|
-
} | {
|
|
1788
|
-
success: boolean;
|
|
1789
|
-
error: any;
|
|
1790
|
-
stats?: undefined;
|
|
1791
|
-
}>;
|
|
1792
|
-
/**
|
|
1793
|
-
* Get thumbnail for an image (RPC method)
|
|
1794
|
-
* Returns base64-encoded data
|
|
1795
|
-
*/
|
|
1796
|
-
getFileThumbnail(path: string): Promise<{
|
|
1797
|
-
success: boolean;
|
|
1798
|
-
data: string;
|
|
1799
|
-
error?: undefined;
|
|
1800
|
-
} | {
|
|
1801
|
-
success: boolean;
|
|
1802
|
-
error: any;
|
|
1803
|
-
data?: undefined;
|
|
1804
|
-
}>;
|
|
1805
|
-
/**
|
|
1806
|
-
* Search file contents using FTS5 (RPC method)
|
|
1807
|
-
*/
|
|
1808
|
-
grepFiles(pattern: string, options?: {
|
|
1809
|
-
path?: string;
|
|
1810
|
-
limit?: number;
|
|
1811
|
-
}): Promise<{
|
|
1812
|
-
success: boolean;
|
|
1813
|
-
results: any;
|
|
1814
|
-
error?: undefined;
|
|
1815
|
-
} | {
|
|
1816
|
-
success: boolean;
|
|
1817
|
-
error: any;
|
|
1818
|
-
results?: undefined;
|
|
1819
|
-
}>;
|
|
1820
|
-
/**
|
|
1821
|
-
* Find files by path pattern (RPC method)
|
|
1822
|
-
*/
|
|
1823
|
-
findFiles(pattern: string, options?: {
|
|
1824
|
-
type?: "file" | "directory" | "all";
|
|
1825
|
-
limit?: number;
|
|
1826
|
-
}): Promise<{
|
|
1827
|
-
success: boolean;
|
|
1828
|
-
files: any;
|
|
1829
|
-
error?: undefined;
|
|
1830
|
-
} | {
|
|
1831
|
-
success: boolean;
|
|
1832
|
-
error: any;
|
|
1833
|
-
files?: undefined;
|
|
1834
|
-
}>;
|
|
1835
|
-
/**
|
|
1836
|
-
* Start a chunked file upload.
|
|
1837
|
-
* Creates file record with is_chunked=1 and chunk_count=null.
|
|
1838
|
-
* Caller should then use writeFileChunk() to write chunks.
|
|
1839
|
-
*/
|
|
1840
|
-
startChunkedUpload(path: string, totalSize: number, mimeType: string, options?: {
|
|
1841
|
-
metadata?: Record<string, unknown>;
|
|
1842
|
-
width?: number;
|
|
1843
|
-
height?: number;
|
|
1844
|
-
}): Promise<{
|
|
1845
|
-
success: boolean;
|
|
1846
|
-
chunkSize?: number;
|
|
1847
|
-
expectedChunks?: number;
|
|
1848
|
-
error?: string;
|
|
1849
|
-
}>;
|
|
1850
|
-
/**
|
|
1851
|
-
* Write a single chunk of a chunked file upload.
|
|
1852
|
-
* @param path - File path
|
|
1853
|
-
* @param chunkIndex - 0-based chunk index
|
|
1854
|
-
* @param data - Base64 encoded chunk data
|
|
1855
|
-
*/
|
|
1856
|
-
writeFileChunk(path: string, chunkIndex: number, data: string): Promise<{
|
|
1857
|
-
success: boolean;
|
|
1858
|
-
error?: string;
|
|
1859
|
-
}>;
|
|
1860
|
-
/**
|
|
1861
|
-
* Complete a chunked file upload.
|
|
1862
|
-
* Validates all chunks are present and sets chunk_count.
|
|
1863
|
-
*/
|
|
1864
|
-
completeChunkedUpload(path: string, expectedChunks: number, options?: {
|
|
1865
|
-
thumbnail?: string;
|
|
1866
|
-
}): Promise<{
|
|
1867
|
-
success: boolean;
|
|
1868
|
-
file?: FileRecord;
|
|
1869
|
-
error?: string;
|
|
1870
|
-
}>;
|
|
1871
|
-
/**
|
|
1872
|
-
* Read a single chunk of a file.
|
|
1873
|
-
* Use for streaming large files to client.
|
|
1874
|
-
*/
|
|
1875
|
-
readFileChunk(path: string, chunkIndex: number): Promise<{
|
|
1876
|
-
success: boolean;
|
|
1877
|
-
data?: string;
|
|
1878
|
-
error?: string;
|
|
1879
|
-
}>;
|
|
1880
|
-
/**
|
|
1881
|
-
* Get file info including chunking metadata.
|
|
1882
|
-
*/
|
|
1883
|
-
getFileInfo(path: string): Promise<{
|
|
1884
|
-
success: boolean;
|
|
1885
|
-
file?: FileRecord;
|
|
1886
|
-
error?: string;
|
|
1887
|
-
}>;
|
|
1888
|
-
}
|
|
1889
|
-
|
|
1890
|
-
interface DurableUserHubEnv {
|
|
1891
|
-
/** Secret JSON registry of runtime-managed grants shared by all users. */
|
|
1892
|
-
AGENT_BUILDER_CREDENTIAL_GRANTS?: string;
|
|
1893
|
-
[key: string]: unknown;
|
|
1894
|
-
}
|
|
1895
|
-
interface HubClientInfo {
|
|
1896
|
-
clientId: string | null;
|
|
1897
|
-
clientName: string | null;
|
|
1898
|
-
clientKind: string | null;
|
|
1899
|
-
}
|
|
1900
|
-
declare class DurableUserHub extends DurableObject<DurableUserHubEnv> {
|
|
1901
|
-
/** Persistent client (daemon) sockets, restored across hibernation. */
|
|
1902
|
-
private clientSockets;
|
|
1903
|
-
private clientInfo;
|
|
1904
|
-
private migrated;
|
|
1905
|
-
constructor(ctx: DurableObjectState, env: DurableUserHubEnv);
|
|
1906
|
-
private ensureMigrated;
|
|
1907
|
-
/**
|
|
1908
|
-
* Returns the user endpoints registry for lazy-loading `users/` files.
|
|
1909
|
-
* Keys are endpoint file paths relative to `users/` with the extension
|
|
1910
|
-
* stripped except the method suffix (e.g. `standardcode/lease_acquire.post`).
|
|
1911
|
-
* Implemented when DurableUserHub is imported from
|
|
1912
|
-
* 'virtual:@standardagents/builder'.
|
|
1913
|
-
*/
|
|
1914
|
-
userEndpoints(): Record<string, () => Promise<unknown>>;
|
|
1915
|
-
/**
|
|
1916
|
-
* Returns the hooks registry (same registry the thread runtime uses). The
|
|
1917
|
-
* hub filters it to user-scope hook types at dispatch time. Implemented
|
|
1918
|
-
* when DurableUserHub is imported from 'virtual:@standardagents/builder'.
|
|
1919
|
-
*/
|
|
1920
|
-
userHooks(): Record<string, () => Promise<unknown>>;
|
|
1921
|
-
/**
|
|
1922
|
-
* Accept the user's persistent client (daemon) WebSocket. The daemon holds
|
|
1923
|
-
* this ONE socket for its whole lifetime; per-thread bridge sockets are
|
|
1924
|
-
* opened separately and only while a thread is active.
|
|
1925
|
-
*/
|
|
1926
|
-
fetch(request: Request): Promise<Response>;
|
|
1927
|
-
/** Idle sockets answer heartbeats at the edge without waking the object.
|
|
1928
|
-
* Registered at accept time rather than in the constructor so a hub that
|
|
1929
|
-
* never accepts a socket stays fully evictable (this also keeps
|
|
1930
|
-
* vitest-pool-workers' isolated storage able to pop the DO's frame). */
|
|
1931
|
-
private ensureHeartbeatAutoResponse;
|
|
1932
|
-
/** Sockets attached to the user event stream, restored after hibernation. */
|
|
1933
|
-
private streamSockets;
|
|
1934
|
-
private acceptUserStream;
|
|
1935
|
-
/**
|
|
1936
|
-
* Deliver an event frame to every socket attached to this user's stream.
|
|
1937
|
-
* At-most-once, live-only (spec: Users §4) — no history, no acks.
|
|
1938
|
-
*/
|
|
1939
|
-
broadcastUserEvent(userId: string, event: string, data?: unknown): void;
|
|
1940
|
-
/** Per-user execution chain (spec: Users §2.1) — see users/serialize.ts. */
|
|
1941
|
-
private executionChain;
|
|
1942
|
-
private scopeHost;
|
|
1943
|
-
private runUserEndpoint;
|
|
1944
|
-
/**
|
|
1945
|
-
* Fire every definition of a user hook type. Observational and best-effort:
|
|
1946
|
-
* failures are swallowed and dispatch never blocks the triggering
|
|
1947
|
-
* operation. Nested dispatch is suppressed so a `user_value_changed` hook
|
|
1948
|
-
* writing values cannot recurse.
|
|
1949
|
-
*/
|
|
1950
|
-
private inUserHookDispatch;
|
|
1951
|
-
private dispatchUserHooks;
|
|
1952
|
-
webSocketClose(ws: WebSocket): Promise<void>;
|
|
1953
|
-
/**
|
|
1954
|
-
* Store or replace a grant. `secret` is write-only from this point on.
|
|
1955
|
-
* Policy (`CredentialGrant` minus the secret) is kept as JSON config.
|
|
1956
|
-
*/
|
|
1957
|
-
setGrant(userId: string, grant: CredentialGrant, secret: string): Promise<void>;
|
|
1958
|
-
deleteGrant(userId: string, name: string): Promise<void>;
|
|
1959
|
-
/** Metadata-only listing — never returns secret material. */
|
|
1960
|
-
listGrants(userId: string): Promise<Array<Omit<CredentialGrant, "name"> & {
|
|
1961
|
-
name: string;
|
|
1962
|
-
}>>;
|
|
1963
|
-
/** Perform a privileged fetch with the grant's credential injected. */
|
|
1964
|
-
private grantFetch;
|
|
1965
|
-
private handleGrantFetch;
|
|
1966
|
-
webSocketMessage(ws: WebSocket, _message: string | ArrayBuffer): Promise<void>;
|
|
1967
|
-
webSocketError(ws: WebSocket): Promise<void>;
|
|
1968
|
-
/** Whether a persistent client (daemon) is connected right now. */
|
|
1969
|
-
hasClient(): Promise<boolean>;
|
|
1970
|
-
/**
|
|
1971
|
-
* Signal the connected daemon to attach a bridge to `threadId`. Called by a
|
|
1972
|
-
* cold thread DO that parked a forwarded call with no client attached. The
|
|
1973
|
-
* daemon reacts by opening a per-thread bridge socket, which triggers the
|
|
1974
|
-
* thread's drain-on-attach. Returns whether a daemon was reachable.
|
|
1975
|
-
*/
|
|
1976
|
-
requestWake(threadId: string): Promise<{
|
|
1977
|
-
delivered: boolean;
|
|
1978
|
-
}>;
|
|
1979
|
-
getUserValue(userId: string, key: string): Promise<unknown | null>;
|
|
1980
|
-
setUserValue(userId: string, key: string, value: unknown): Promise<void>;
|
|
1981
|
-
listUserValues(userId: string, options?: {
|
|
1982
|
-
prefix?: string | null;
|
|
1983
|
-
limit?: number;
|
|
1984
|
-
offset?: number;
|
|
1985
|
-
}): Promise<{
|
|
1986
|
-
entries: Array<{
|
|
1987
|
-
key: string;
|
|
1988
|
-
value: unknown;
|
|
1989
|
-
updated_at: number;
|
|
1990
|
-
}>;
|
|
1991
|
-
total: number;
|
|
1992
|
-
limit: number;
|
|
1993
|
-
offset: number;
|
|
1994
|
-
}>;
|
|
1995
|
-
}
|
|
1996
|
-
|
|
1997
|
-
type EnvValueType = 'text' | 'secret';
|
|
1998
|
-
/**
|
|
1999
|
-
* Environment type for DurableAgentBuilder.
|
|
2000
|
-
* Users extend this with their own bindings.
|
|
2001
|
-
*/
|
|
2002
|
-
interface AgentBuilderEnv {
|
|
2003
|
-
AGENT_BUILDER: DurableObjectNamespace<DurableAgentBuilder>;
|
|
2004
|
-
AGENT_BUILDER_THREAD: DurableObjectNamespace;
|
|
2005
|
-
AGENT_BUILDER_USER_HUB?: DurableObjectNamespace<DurableUserHub>;
|
|
2006
|
-
ENCRYPTION_KEY?: string;
|
|
2007
|
-
}
|
|
2008
|
-
/**
|
|
2009
|
-
* Thread metadata stored in the registry.
|
|
2010
|
-
*/
|
|
2011
|
-
interface ThreadRegistryEntry {
|
|
2012
|
-
id: string;
|
|
2013
|
-
agent_name: string;
|
|
2014
|
-
/**
|
|
2015
|
-
* Agent the thread was CREATED on. Never changed by handoffs
|
|
2016
|
-
* (updateThreadAgent only re-points agent_name), so lists can keep a
|
|
2017
|
-
* handed-off conversation visible on its original agent's page.
|
|
2018
|
-
*/
|
|
2019
|
-
origin_agent_name?: string | null;
|
|
2020
|
-
user_id: string | null;
|
|
2021
|
-
tags: string[] | null;
|
|
2022
|
-
env: Record<string, string> | null;
|
|
2023
|
-
env_types: Record<string, EnvValueType> | null;
|
|
2024
|
-
/** @deprecated Use env */
|
|
2025
|
-
tenvs: Record<string, unknown> | null;
|
|
2026
|
-
properties: Record<string, unknown> | null;
|
|
2027
|
-
parent: string | null;
|
|
2028
|
-
terminated: number | null;
|
|
2029
|
-
created_at: number;
|
|
2030
|
-
/** Unix seconds of the last message or execution on this thread (or a descendant). */
|
|
2031
|
-
last_activity_at?: number | null;
|
|
2032
|
-
/** True while the thread is executing a flow (stale markers read as false). */
|
|
2033
|
-
executing?: boolean;
|
|
2034
|
-
/** Short excerpt of the most recent user message, for thread-list rows. */
|
|
2035
|
-
last_message_preview?: string | null;
|
|
2036
|
-
/**
|
|
2037
|
-
* Unix seconds of the newest VISIBLE MESSAGE on this thread — the one field
|
|
2038
|
-
* clients key unread indicators on. It moves when a non-empty user (or
|
|
2039
|
-
* operator assistant-role) message arrives, and when a visible terminal
|
|
2040
|
-
* assistant record lands (`isVisibleTerminalAssistantMessage`): terminal
|
|
2041
|
-
* answers, attachment-only replies, and failed rows with visible text — but
|
|
2042
|
-
* never mid-turn tool-calling steps, silent rows, sub-prompt records, or
|
|
2043
|
-
* background execution activity (which move only `last_activity_at`).
|
|
2044
|
-
* Monotonic per thread and never propagated to ancestors.
|
|
2045
|
-
*/
|
|
2046
|
-
last_message_at?: number | null;
|
|
2047
|
-
}
|
|
2048
|
-
/**
|
|
2049
|
-
* Safe registry projection carried by system events. Thread env and arbitrary
|
|
2050
|
-
* properties are intentionally excluded: the stream is an invalidation/list
|
|
2051
|
-
* surface, not a second transport for thread configuration or secrets.
|
|
2052
|
-
*/
|
|
2053
|
-
type ThreadEventPayload = Pick<ThreadRegistryEntry, 'id' | 'agent_name' | 'origin_agent_name' | 'user_id' | 'tags' | 'parent' | 'terminated' | 'created_at' | 'last_activity_at' | 'executing' | 'last_message_preview' | 'last_message_at'>;
|
|
2054
|
-
interface PendingSubagentAttachmentRef {
|
|
2055
|
-
path: string;
|
|
2056
|
-
name?: string;
|
|
2057
|
-
mimeType?: string;
|
|
2058
|
-
size?: number;
|
|
2059
|
-
width?: number;
|
|
2060
|
-
height?: number;
|
|
2061
|
-
}
|
|
2062
|
-
interface PendingSubagentEnvRequestPayload {
|
|
2063
|
-
blocking: boolean;
|
|
2064
|
-
/** Relationship name (`as` ?? agent) the spawn was requested under. */
|
|
2065
|
-
relationship?: string;
|
|
2066
|
-
/** Which parent side OWNS the relationship ('a' when unrecorded). */
|
|
2067
|
-
owner?: 'a' | 'b';
|
|
2068
|
-
parent_communication: 'implicit' | 'explicit';
|
|
2069
|
-
initial_message_content: string;
|
|
2070
|
-
initial_message_attachments: PendingSubagentAttachmentRef[];
|
|
2071
|
-
initial_arguments?: Record<string, unknown>;
|
|
2072
|
-
initial_agent_name?: string | null;
|
|
2073
|
-
agent_title?: string | null;
|
|
2074
|
-
agent_description?: string | null;
|
|
2075
|
-
spawn_group_id?: string | null;
|
|
2076
|
-
/** Invocation arguments persisted for the life of the child thread. */
|
|
2077
|
-
arguments?: Record<string, unknown>;
|
|
2078
|
-
}
|
|
2079
|
-
interface PendingSubagentEnvRequest {
|
|
2080
|
-
request_id: string;
|
|
2081
|
-
parent_thread_id: string;
|
|
2082
|
-
agent_name: string;
|
|
2083
|
-
registry_agent_name: string;
|
|
2084
|
-
required: string[];
|
|
2085
|
-
missing: string[];
|
|
2086
|
-
payload: PendingSubagentEnvRequestPayload;
|
|
2087
|
-
created_at: number;
|
|
2088
|
-
}
|
|
2089
|
-
/**
|
|
2090
|
-
* Parameters for updating a thread.
|
|
2091
|
-
*/
|
|
2092
|
-
interface UpdateThreadParams {
|
|
2093
|
-
agent_name?: string;
|
|
2094
|
-
user_id?: string | null;
|
|
2095
|
-
tags?: string[] | null;
|
|
2096
|
-
env?: Record<string, string> | null;
|
|
2097
|
-
env_types?: Record<string, EnvValueType> | null;
|
|
2098
|
-
/** @deprecated Use env */
|
|
2099
|
-
tenvs?: Record<string, unknown> | null;
|
|
2100
|
-
properties?: Record<string, unknown> | null;
|
|
2101
|
-
parent?: string | null;
|
|
2102
|
-
terminated?: number | null;
|
|
2103
|
-
}
|
|
2104
|
-
/**
|
|
2105
|
-
* User record.
|
|
2106
|
-
*/
|
|
2107
|
-
type InstanceRole = 'admin' | 'user' | 'api';
|
|
2108
|
-
interface User {
|
|
2109
|
-
id: string;
|
|
2110
|
-
username: string;
|
|
2111
|
-
password_hash: string;
|
|
2112
|
-
role: InstanceRole;
|
|
2113
|
-
/** Explicit permission grants (e.g. 'logs'); null = legacy default. */
|
|
2114
|
-
permissions?: string[] | null;
|
|
2115
|
-
platform_user_id?: string | null;
|
|
2116
|
-
email?: string | null;
|
|
2117
|
-
display_name?: string | null;
|
|
2118
|
-
avatar_url?: string | null;
|
|
2119
|
-
source?: 'local' | 'standard_agents';
|
|
2120
|
-
replica_active?: number;
|
|
2121
|
-
created_at: number;
|
|
2122
|
-
updated_at: number;
|
|
2123
|
-
}
|
|
2124
|
-
interface PlatformReplicaUser {
|
|
2125
|
-
platform_user_id: string;
|
|
2126
|
-
username?: string | null;
|
|
2127
|
-
email?: string | null;
|
|
2128
|
-
display_name?: string | null;
|
|
2129
|
-
avatar_url?: string | null;
|
|
2130
|
-
role: InstanceRole;
|
|
2131
|
-
permissions?: string[] | null;
|
|
2132
|
-
session_revoked_at?: number | null;
|
|
2133
|
-
}
|
|
2134
|
-
interface PlatformReplicaApiKey {
|
|
2135
|
-
id: string;
|
|
2136
|
-
name?: string | null;
|
|
2137
|
-
key_hash: string;
|
|
2138
|
-
key_prefix: string;
|
|
2139
|
-
last_five?: string | null;
|
|
2140
|
-
user_platform_id?: string | null;
|
|
2141
|
-
scope?: string | null;
|
|
2142
|
-
created_at?: number | null;
|
|
2143
|
-
}
|
|
2144
|
-
interface PlatformReplicaSnapshot {
|
|
2145
|
-
users: PlatformReplicaUser[];
|
|
2146
|
-
api_keys?: PlatformReplicaApiKey[];
|
|
2147
|
-
}
|
|
2148
|
-
interface ScopedEnvEntry {
|
|
2149
|
-
name: string;
|
|
2150
|
-
value: string;
|
|
2151
|
-
type: EnvValueType;
|
|
2152
|
-
created_at: number;
|
|
2153
|
-
updated_at: number;
|
|
2154
|
-
}
|
|
2155
|
-
/**
|
|
2156
|
-
* Provider credentials.
|
|
2157
|
-
*/
|
|
2158
|
-
interface Provider$1 {
|
|
2159
|
-
name: string;
|
|
2160
|
-
sdk: string;
|
|
2161
|
-
api_key: string;
|
|
2162
|
-
}
|
|
2163
|
-
/**
|
|
2164
|
-
* Lightweight agent metadata included with real-time thread events.
|
|
2165
|
-
*/
|
|
2166
|
-
interface ThreadEventAgent {
|
|
2167
|
-
name: string;
|
|
2168
|
-
title: string;
|
|
2169
|
-
side_a_backing: 'human' | 'prompt' | 'handler';
|
|
2170
|
-
side_b_backing: 'human' | 'prompt' | 'handler';
|
|
2171
|
-
description?: string;
|
|
2172
|
-
icon?: string;
|
|
2173
|
-
}
|
|
2174
|
-
/**
|
|
2175
|
-
* DurableAgentBuilder - The root Durable Object for AgentBuilder.
|
|
2176
|
-
*
|
|
2177
|
-
* This is a singleton DO that stores:
|
|
2178
|
-
* - Thread registry (maps thread IDs to agent names)
|
|
2179
|
-
* - User authentication data
|
|
2180
|
-
* - Provider credentials (API keys for LLM providers)
|
|
2181
|
-
* - Edit lock state for coordinated edits
|
|
2182
|
-
*
|
|
2183
|
-
* ## Usage
|
|
2184
|
-
*
|
|
2185
|
-
* Users must extend this class to provide virtual module access:
|
|
2186
|
-
*
|
|
2187
|
-
* ```typescript
|
|
2188
|
-
* import { DurableAgentBuilder } from '@standardagents/builder/runtime';
|
|
2189
|
-
* import { models } from 'virtual:@standardagents-models';
|
|
2190
|
-
* import { prompts } from 'virtual:@standardagents-prompts';
|
|
2191
|
-
* import { agents } from 'virtual:@standardagents-agents';
|
|
2192
|
-
*
|
|
2193
|
-
* export class AgentBuilder extends DurableAgentBuilder {
|
|
2194
|
-
* models() { return models; }
|
|
2195
|
-
* prompts() { return prompts; }
|
|
2196
|
-
* agents() { return agents; }
|
|
2197
|
-
* }
|
|
2198
|
-
* ```
|
|
2199
|
-
*/
|
|
2200
|
-
/**
|
|
2201
|
-
* Event types that can be emitted via WebSocket
|
|
2202
|
-
*/
|
|
2203
|
-
type AgentBuilderEvent = {
|
|
2204
|
-
type: 'thread_created';
|
|
2205
|
-
thread: ThreadEventPayload & {
|
|
2206
|
-
agent?: ThreadEventAgent;
|
|
2207
|
-
};
|
|
2208
|
-
} | {
|
|
2209
|
-
type: 'thread_updated';
|
|
2210
|
-
thread: ThreadEventPayload & {
|
|
2211
|
-
agent?: ThreadEventAgent;
|
|
2212
|
-
};
|
|
2213
|
-
} | {
|
|
2214
|
-
type: 'thread_deleted';
|
|
2215
|
-
threadId: string;
|
|
2216
|
-
}
|
|
2217
|
-
/**
|
|
2218
|
-
* Lightweight activity signal. Kept separate from `thread_updated` because it
|
|
2219
|
-
* fires on every execution start/stop: re-broadcasting the whole registry
|
|
2220
|
-
* entry would decrypt thread env on each transition for data that never
|
|
2221
|
-
* changed.
|
|
2222
|
-
*/
|
|
2223
|
-
| {
|
|
2224
|
-
type: 'thread_activity';
|
|
2225
|
-
threadId: string;
|
|
2226
|
-
/** Present only when this event actually wrote the field: a message-only
|
|
2227
|
-
* recency stamp omits last_activity_at, and `executing` rides only on a
|
|
2228
|
-
* real transition — clients must leave their current value alone for
|
|
2229
|
-
* absent fields. */
|
|
2230
|
-
last_activity_at?: number;
|
|
2231
|
-
executing?: boolean;
|
|
2232
|
-
last_message_preview?: string | null;
|
|
2233
|
-
last_message_at?: number | null;
|
|
2234
|
-
};
|
|
2235
|
-
/** Sort orders supported by `listThreads`. */
|
|
2236
|
-
type ThreadListSort = 'activity' | 'created' | 'oldest';
|
|
2237
|
-
declare class DurableAgentBuilder<Env extends AgentBuilderEnv = AgentBuilderEnv> extends DurableObject<Env> {
|
|
2238
|
-
private migratedToVersion;
|
|
2239
|
-
private eventSockets;
|
|
2240
|
-
constructor(ctx: DurableObjectState, env: Env);
|
|
2241
|
-
private normalizeEnvRecord;
|
|
2242
|
-
private normalizePlainObject;
|
|
2243
|
-
private hasInitialArguments;
|
|
2244
|
-
private buildSubagentThreadProperties;
|
|
2245
|
-
private buildSubagentInitialArgumentsMessage;
|
|
2246
|
-
private normalizeEnvTypeRecord;
|
|
2247
|
-
private extractEnvTypeRecord;
|
|
2248
|
-
private withEnvTypeRecord;
|
|
2249
|
-
private serializeEnvTypes;
|
|
2250
|
-
private resolveRegistryKey;
|
|
2251
|
-
private extractScopedVariables;
|
|
2252
|
-
private filterScopedInheritedEnv;
|
|
2253
|
-
private filterScopedInheritedEnvTypes;
|
|
2254
|
-
private collectScopedVariablesForAgent;
|
|
2255
|
-
private getScopedVariableNamesForAgent;
|
|
2256
|
-
private getRequiredScopedVariableNamesForAgent;
|
|
2257
|
-
private normalizeScopedVariableList;
|
|
2258
|
-
private normalizePendingAttachments;
|
|
2259
|
-
private sanitizeFilename;
|
|
2260
|
-
private inferMimeTypeFromPath;
|
|
2261
|
-
private extensionForMimeType;
|
|
2262
|
-
private buildAttachmentTargetPath;
|
|
2263
|
-
private formatSubagentAttachmentPathSummary;
|
|
2264
|
-
private formatSubagentTerminalMessage;
|
|
2265
|
-
private copyPendingAttachmentsBetweenThreads;
|
|
2266
|
-
private buildThreadNameTag;
|
|
2267
|
-
private encryptEnvRecord;
|
|
2268
|
-
private decryptEnvRecord;
|
|
2269
|
-
private listActiveDescendantThreadIds;
|
|
2270
|
-
private propagateThreadEnvToDescendants;
|
|
2271
|
-
/**
|
|
2272
|
-
* Returns the tools registry for lazy-loading tool definitions.
|
|
2273
|
-
* Must be overridden in a subclass.
|
|
2274
|
-
*/
|
|
2275
|
-
tools(): Record<string, () => Promise<any>>;
|
|
2276
|
-
/**
|
|
2277
|
-
* Returns the hooks registry for lazy-loading hook definitions.
|
|
2278
|
-
* Must be overridden in a subclass.
|
|
2279
|
-
*/
|
|
2280
|
-
hooks(): Record<string, () => Promise<any>>;
|
|
2281
|
-
/**
|
|
2282
|
-
* Returns the models registry for lazy-loading model definitions.
|
|
2283
|
-
* Must be overridden in a subclass.
|
|
2284
|
-
*/
|
|
2285
|
-
models(): Record<string, () => Promise<any>>;
|
|
2286
|
-
/**
|
|
2287
|
-
* Returns the prompts registry for lazy-loading prompt definitions.
|
|
2288
|
-
* Must be overridden in a subclass.
|
|
2289
|
-
*/
|
|
2290
|
-
prompts(): Record<string, () => Promise<any>>;
|
|
2291
|
-
/**
|
|
2292
|
-
* Returns the agents registry for lazy-loading agent definitions.
|
|
2293
|
-
* Must be overridden in a subclass.
|
|
2294
|
-
*/
|
|
2295
|
-
agents(): Record<string, () => Promise<any>>;
|
|
2296
|
-
/**
|
|
2297
|
-
* Returns the namespaced registry for packed agent support.
|
|
2298
|
-
* Must be overridden in a subclass.
|
|
2299
|
-
*/
|
|
2300
|
-
registry(): any;
|
|
2301
|
-
private ensureMigrated;
|
|
2302
|
-
private getCurrentVersion;
|
|
2303
|
-
private runMigrations;
|
|
2304
|
-
/**
|
|
2305
|
-
* Create a new thread and add it to the registry.
|
|
2306
|
-
*/
|
|
2307
|
-
createThread(params: {
|
|
2308
|
-
agent_name: string;
|
|
2309
|
-
user_id?: string;
|
|
2310
|
-
tags?: string[];
|
|
2311
|
-
env?: Record<string, string>;
|
|
2312
|
-
env_types?: Record<string, EnvValueType>;
|
|
2313
|
-
/** @deprecated Use env */
|
|
2314
|
-
tenvs?: Record<string, unknown>;
|
|
2315
|
-
properties?: Record<string, unknown>;
|
|
2316
|
-
parent?: string;
|
|
2317
|
-
}): Promise<ThreadRegistryEntry>;
|
|
2318
|
-
/**
|
|
2319
|
-
* Spawn `immediate` subagent relationships at THREAD CREATION, before any
|
|
2320
|
-
* side takes a turn — required even when the owning side is a handler, or
|
|
2321
|
-
* when the first inbound message arrives instantly. Spawns run through the
|
|
2322
|
-
* normal `subagent_create` machinery (registry, scoped env, hidden,
|
|
2323
|
-
* maxInstances) via the standalone invokeTool path. A relationship whose
|
|
2324
|
-
* child demands invocation arguments this path cannot synthesize fails
|
|
2325
|
-
* softly here; the FlowEngine immediate runner bootstraps it with an
|
|
2326
|
-
* internal model call before the owning side's first turn.
|
|
2327
|
-
*/
|
|
2328
|
-
private spawnImmediateSubagents;
|
|
2329
|
-
private runAfterThreadCreatedHook;
|
|
2330
|
-
/**
|
|
2331
|
-
* Get a thread by ID.
|
|
2332
|
-
*/
|
|
2333
|
-
getThread(id: string): Promise<ThreadRegistryEntry | null>;
|
|
2334
|
-
/**
|
|
2335
|
-
* All descendant threads of a root thread (children, grandchildren, …),
|
|
2336
|
-
* excluding the root itself. Used for subtree cost reporting: a thread's
|
|
2337
|
-
* displayed cost is its own plus every subagent thread it spawned,
|
|
2338
|
-
* recursively. Ordered parents-before-children (breadth by creation time).
|
|
2339
|
-
*/
|
|
2340
|
-
getDescendantThreads(rootId: string): Promise<Array<{
|
|
2341
|
-
id: string;
|
|
2342
|
-
agent_name: string;
|
|
2343
|
-
parent: string | null;
|
|
2344
|
-
tags: string[] | null;
|
|
2345
|
-
terminated: number | null;
|
|
2346
|
-
created_at: number;
|
|
2347
|
-
}>>;
|
|
2348
|
-
/**
|
|
2349
|
-
* List threads with optional filtering.
|
|
2350
|
-
* Note: tenvs are not decrypted in list operations for performance.
|
|
2351
|
-
* Use getThread() to retrieve a thread with decrypted tenvs.
|
|
2352
|
-
*/
|
|
2353
|
-
listThreads(params?: {
|
|
2354
|
-
agent_name?: string;
|
|
2355
|
-
user_id?: string;
|
|
2356
|
-
search?: string;
|
|
2357
|
-
startDate?: number;
|
|
2358
|
-
endDate?: number;
|
|
2359
|
-
limit?: number;
|
|
2360
|
-
offset?: number;
|
|
2361
|
-
include_children?: boolean;
|
|
2362
|
-
/** Default `activity`: most recently worked-on threads first. */
|
|
2363
|
-
sort?: ThreadListSort;
|
|
2364
|
-
/** `true` → only threads currently executing; `false` → only idle ones. */
|
|
2365
|
-
executing?: boolean;
|
|
2366
|
-
/** `false` hides terminated threads; `true` shows only terminated ones. */
|
|
2367
|
-
terminated?: boolean;
|
|
2368
|
-
}): Promise<{
|
|
2369
|
-
threads: ThreadRegistryEntry[];
|
|
2370
|
-
total: number;
|
|
2371
|
-
}>;
|
|
2372
|
-
/**
|
|
2373
|
-
* Distinct owners of threads visible to the caller, with counts, so a thread
|
|
2374
|
-
* list can offer an "owner" filter without exposing the admin-only user
|
|
2375
|
-
* directory (which is unavailable on hosted instances).
|
|
2376
|
-
*/
|
|
2377
|
-
listThreadOwners(params?: {
|
|
2378
|
-
user_id?: string;
|
|
2379
|
-
}): Promise<Array<{
|
|
2380
|
-
user_id: string | null;
|
|
2381
|
-
username: string | null;
|
|
2382
|
-
display_name: string | null;
|
|
2383
|
-
email: string | null;
|
|
2384
|
-
thread_count: number;
|
|
2385
|
-
}>>;
|
|
2386
|
-
/**
|
|
2387
|
-
* Record that a thread did work: stamp `last_activity_at` and flip the
|
|
2388
|
-
* executing marker. Activity bubbles up the parent chain so a root thread
|
|
2389
|
-
* sorts by the freshest work anywhere in its subagent tree — otherwise a
|
|
2390
|
-
* long-running subagent would let its parent sink down an activity-sorted
|
|
2391
|
-
* list.
|
|
2392
|
-
*/
|
|
2393
|
-
recordThreadActivity(threadId: string, options?: {
|
|
2394
|
-
executing?: boolean;
|
|
2395
|
-
messagePreview?: string | null;
|
|
2396
|
-
messageAt?: number;
|
|
2397
|
-
}): Promise<void>;
|
|
2398
|
-
/**
|
|
2399
|
-
* Fill in previews for threads that predate preview tracking. Callers read
|
|
2400
|
-
* each thread's newest user message and stamp the results here in one batch.
|
|
2401
|
-
*
|
|
2402
|
-
* A thread with no user message is stamped with an empty string rather than
|
|
2403
|
-
* left NULL: NULL means "not looked at yet", so without the sentinel an
|
|
2404
|
-
* empty thread would be re-read on every list request forever.
|
|
2405
|
-
*/
|
|
2406
|
-
backfillThreadPreviews(entries: Array<{
|
|
2407
|
-
id: string;
|
|
2408
|
-
preview: string | null;
|
|
2409
|
-
}>): Promise<void>;
|
|
2410
|
-
/**
|
|
2411
|
-
* Delete a thread from the registry.
|
|
2412
|
-
*/
|
|
2413
|
-
deleteThread(id: string): Promise<boolean>;
|
|
2414
|
-
/**
|
|
2415
|
-
* Delete all singleton AgentBuilder storage for platform-owned teardown.
|
|
2416
|
-
* Used when the hosting platform expires a preview branch deployment after
|
|
2417
|
-
* all thread Durable Objects have already been wiped.
|
|
2418
|
-
*/
|
|
2419
|
-
deleteAllStorage(): Promise<{
|
|
2420
|
-
success: boolean;
|
|
2421
|
-
message: string;
|
|
2422
|
-
}>;
|
|
2423
|
-
/**
|
|
2424
|
-
* Get a thread tree (root + all descendants) in child-first order.
|
|
2425
|
-
*
|
|
2426
|
-
* Child-first ordering allows callers to perform destructive operations
|
|
2427
|
-
* (like deletes) without leaving child rows referencing a deleted parent.
|
|
2428
|
-
*/
|
|
2429
|
-
getThreadTreeIds(rootThreadId: string): Promise<string[]>;
|
|
2430
|
-
/**
|
|
2431
|
-
* Update a thread's agent_name (used during agent handoff).
|
|
2432
|
-
* origin_agent_name is deliberately untouched — it pins the thread to the
|
|
2433
|
-
* agent page it started on. Broadcasts thread_updated so connected clients
|
|
2434
|
-
* re-render the row immediately instead of on the next activity tick
|
|
2435
|
-
* (which is when handed-off threads used to silently vanish mid-watch).
|
|
2436
|
-
*/
|
|
2437
|
-
updateThreadAgent(id: string, agent_name: string): Promise<boolean>;
|
|
2438
|
-
/**
|
|
2439
|
-
* Update a thread's metadata.
|
|
2440
|
-
*/
|
|
2441
|
-
updateThread(id: string, params: UpdateThreadParams): Promise<ThreadRegistryEntry | null>;
|
|
2442
|
-
private getEncryptionKey;
|
|
2443
|
-
private encryptEnvValue;
|
|
2444
|
-
private decryptEnvValue;
|
|
2445
|
-
private listScopedEnv;
|
|
2446
|
-
private listScopedEnvEntries;
|
|
2447
|
-
private getScopedEnvTypeRecord;
|
|
2448
|
-
private replaceScopedEnv;
|
|
2449
|
-
private patchScopedEnv;
|
|
2450
|
-
getInstanceEnv(): Promise<Record<string, string>>;
|
|
2451
|
-
getInstanceEnvTypes(): Promise<Record<string, EnvValueType>>;
|
|
2452
|
-
getInstanceEnvEntries(): Promise<ScopedEnvEntry[]>;
|
|
2453
|
-
setInstanceEnv(env: Record<string, string>, envTypes?: Record<string, EnvValueType> | null): Promise<void>;
|
|
2454
|
-
patchInstanceEnv(params: {
|
|
2455
|
-
env_patch?: Record<string, unknown> | null;
|
|
2456
|
-
env_type_patch?: Record<string, unknown> | null;
|
|
2457
|
-
env_delete?: string[] | null;
|
|
2458
|
-
}): Promise<void>;
|
|
2459
|
-
getUserEnv(userId: string): Promise<Record<string, string>>;
|
|
2460
|
-
getUserEnvTypes(userId: string): Promise<Record<string, EnvValueType>>;
|
|
2461
|
-
getUserEnvEntries(userId: string): Promise<ScopedEnvEntry[]>;
|
|
2462
|
-
setUserEnv(userId: string, env: Record<string, string>, envTypes?: Record<string, EnvValueType> | null): Promise<void>;
|
|
2463
|
-
patchUserEnv(userId: string, params: {
|
|
2464
|
-
env_patch?: Record<string, unknown> | null;
|
|
2465
|
-
env_type_patch?: Record<string, unknown> | null;
|
|
2466
|
-
env_delete?: string[] | null;
|
|
2467
|
-
}): Promise<void>;
|
|
2468
|
-
private assertValidUserValueKey;
|
|
2469
|
-
private assertValidUserValueUserId;
|
|
2470
|
-
/**
|
|
2471
|
-
* The per-user hub is the sharded home for account-wide KV. When the binding
|
|
2472
|
-
* exists, the singleton delegates so the global object is no longer a
|
|
2473
|
-
* per-user bottleneck; without it (pre-hub deploys, unit tests) it keeps the
|
|
2474
|
-
* local `user_values` table.
|
|
2475
|
-
*/
|
|
2476
|
-
private userHub;
|
|
2477
|
-
/** Read one JSON value from a user's account-wide key-value store. */
|
|
2478
|
-
getUserValue(userId: string, key: string): Promise<unknown | null>;
|
|
2479
|
-
/** Write one JSON value to a user's account-wide store; null/undefined deletes. */
|
|
2480
|
-
setUserValue(userId: string, key: string, value: unknown): Promise<void>;
|
|
2481
|
-
/** List a user's account-wide values, optionally filtered by key prefix. */
|
|
2482
|
-
listUserValues(userId: string, options?: {
|
|
2483
|
-
prefix?: string | null;
|
|
2484
|
-
limit?: number;
|
|
2485
|
-
offset?: number;
|
|
2486
|
-
}): Promise<{
|
|
2487
|
-
entries: Array<{
|
|
2488
|
-
key: string;
|
|
2489
|
-
value: unknown;
|
|
2490
|
-
updated_at: number;
|
|
2491
|
-
}>;
|
|
2492
|
-
total: number;
|
|
2493
|
-
limit: number;
|
|
2494
|
-
offset: number;
|
|
2495
|
-
}>;
|
|
2496
|
-
getMissingRequiredScopedSubagentEnv(params: {
|
|
2497
|
-
parent_thread_id: string;
|
|
2498
|
-
agent_name: string;
|
|
2499
|
-
provided_env?: Record<string, string> | null;
|
|
2500
|
-
}): Promise<string[]>;
|
|
2501
|
-
createPendingSubagentEnvRequest(params: {
|
|
2502
|
-
parent_thread_id: string;
|
|
2503
|
-
agent_name: string;
|
|
2504
|
-
registry_agent_name: string;
|
|
2505
|
-
required_variables: string[];
|
|
2506
|
-
missing_variables: string[];
|
|
2507
|
-
payload: PendingSubagentEnvRequestPayload;
|
|
2508
|
-
}): Promise<PendingSubagentEnvRequest>;
|
|
2509
|
-
getPendingSubagentEnvRequest(parentThreadId: string, requestId: string): Promise<PendingSubagentEnvRequest | null>;
|
|
2510
|
-
private clearPendingSubagentEnvRequest;
|
|
2511
|
-
completePendingSubagentEnvRequest(params: {
|
|
2512
|
-
parent_thread_id: string;
|
|
2513
|
-
request_id: string;
|
|
2514
|
-
env: Record<string, string>;
|
|
2515
|
-
}): Promise<{
|
|
2516
|
-
request_id: string;
|
|
2517
|
-
child_thread_id: string;
|
|
2518
|
-
status: 'success';
|
|
2519
|
-
}>;
|
|
2520
|
-
resolveThreadEnv(params: {
|
|
2521
|
-
threadId: string;
|
|
2522
|
-
property: string;
|
|
2523
|
-
promptName?: string;
|
|
2524
|
-
}): Promise<string | null>;
|
|
2525
|
-
resolveThreadEnvType(params: {
|
|
2526
|
-
threadId: string;
|
|
2527
|
-
property: string;
|
|
2528
|
-
promptName?: string;
|
|
2529
|
-
}): Promise<EnvValueType>;
|
|
2530
|
-
private toThreadEventPayload;
|
|
2531
|
-
/**
|
|
2532
|
-
* Load a model definition by name.
|
|
2533
|
-
*/
|
|
2534
|
-
loadModel(name: string): Promise<any>;
|
|
2535
|
-
/**
|
|
2536
|
-
* List available model names.
|
|
2537
|
-
*/
|
|
2538
|
-
getModelNames(): string[];
|
|
2539
|
-
/**
|
|
2540
|
-
* Load a prompt definition by name.
|
|
2541
|
-
*/
|
|
2542
|
-
loadPrompt(name: string): Promise<any>;
|
|
2543
|
-
/**
|
|
2544
|
-
* List available prompt names.
|
|
2545
|
-
*/
|
|
2546
|
-
getPromptNames(): string[];
|
|
2547
|
-
/**
|
|
2548
|
-
* Load an agent definition by name.
|
|
2549
|
-
* Supports both global agents (e.g., "my-agent") and packed agents (e.g., "packageId/agentName").
|
|
2550
|
-
* For scoped packages, use "@scope/pkg/agentName".
|
|
2551
|
-
*/
|
|
2552
|
-
loadAgent(name: string): Promise<any>;
|
|
2553
|
-
/**
|
|
2554
|
-
* List available agent names.
|
|
2555
|
-
*/
|
|
2556
|
-
getAgentNames(): string[];
|
|
2557
|
-
/**
|
|
2558
|
-
* Get a provider's credentials.
|
|
2559
|
-
*/
|
|
2560
|
-
getProvider(name: string): Promise<Provider$1 | null>;
|
|
2561
|
-
/**
|
|
2562
|
-
* Set a provider's credentials.
|
|
2563
|
-
*/
|
|
2564
|
-
setProvider(provider: Provider$1): Promise<void>;
|
|
2565
|
-
/**
|
|
2566
|
-
* List all providers.
|
|
2567
|
-
*/
|
|
2568
|
-
listProviders(): Promise<Provider$1[]>;
|
|
2569
|
-
/**
|
|
2570
|
-
* Delete a provider.
|
|
2571
|
-
*/
|
|
2572
|
-
deleteProvider(name: string): Promise<boolean>;
|
|
2573
|
-
private normalizeReplicaUsername;
|
|
2574
|
-
private availableReplicaUsername;
|
|
2575
|
-
private userFromRow;
|
|
2576
|
-
/**
|
|
2577
|
-
* Get a user by username.
|
|
2578
|
-
*/
|
|
2579
|
-
getUserByUsername(username: string): Promise<User | null>;
|
|
2580
|
-
/**
|
|
2581
|
-
* Get a user by ID.
|
|
2582
|
-
*/
|
|
2583
|
-
getUserById(id: string): Promise<User | null>;
|
|
2584
|
-
/**
|
|
2585
|
-
* Create a new user.
|
|
2586
|
-
*/
|
|
2587
|
-
createUser(params: {
|
|
2588
|
-
username: string;
|
|
2589
|
-
password_hash: string;
|
|
2590
|
-
role?: InstanceRole;
|
|
2591
|
-
permissions?: string[] | null;
|
|
2592
|
-
platform_user_id?: string | null;
|
|
2593
|
-
email?: string | null;
|
|
2594
|
-
display_name?: string | null;
|
|
2595
|
-
avatar_url?: string | null;
|
|
2596
|
-
source?: 'local' | 'standard_agents';
|
|
2597
|
-
}): Promise<User>;
|
|
2598
|
-
/**
|
|
2599
|
-
* Check if any users exist (for first-time setup).
|
|
2600
|
-
*/
|
|
2601
|
-
hasUsers(): Promise<boolean>;
|
|
2602
|
-
/**
|
|
2603
|
-
* List all users (excludes password hash).
|
|
2604
|
-
*/
|
|
2605
|
-
listUsers(): Promise<Array<{
|
|
2606
|
-
id: string;
|
|
2607
|
-
username: string;
|
|
2608
|
-
role: InstanceRole;
|
|
2609
|
-
platform_user_id: string | null;
|
|
2610
|
-
email: string | null;
|
|
2611
|
-
display_name: string | null;
|
|
2612
|
-
avatar_url: string | null;
|
|
2613
|
-
source: 'local' | 'standard_agents';
|
|
2614
|
-
replica_active: number;
|
|
2615
|
-
created_at: number;
|
|
2616
|
-
updated_at: number;
|
|
2617
|
-
}>>;
|
|
2618
|
-
/**
|
|
2619
|
-
* Update a user.
|
|
2620
|
-
*/
|
|
2621
|
-
updateUser(id: string, params: {
|
|
2622
|
-
username?: string;
|
|
2623
|
-
password_hash?: string;
|
|
2624
|
-
role?: InstanceRole;
|
|
2625
|
-
permissions?: string[] | null;
|
|
2626
|
-
platform_user_id?: string | null;
|
|
2627
|
-
email?: string | null;
|
|
2628
|
-
display_name?: string | null;
|
|
2629
|
-
avatar_url?: string | null;
|
|
2630
|
-
source?: 'local' | 'standard_agents';
|
|
2631
|
-
replica_active?: number;
|
|
2632
|
-
}): Promise<User | null>;
|
|
2633
|
-
/**
|
|
2634
|
-
* Delete a user.
|
|
2635
|
-
*/
|
|
2636
|
-
deleteUser(id: string): Promise<boolean>;
|
|
2637
|
-
/**
|
|
2638
|
-
* Upsert a platform-replicated identity and return the local user row.
|
|
2639
|
-
*/
|
|
2640
|
-
upsertPlatformReplicaUser(replica: PlatformReplicaUser): Promise<User>;
|
|
2641
|
-
/**
|
|
2642
|
-
* Apply a full platform read-replica snapshot for this instance.
|
|
2643
|
-
*/
|
|
2644
|
-
applyPlatformReplicaSnapshot(snapshot: PlatformReplicaSnapshot): Promise<{
|
|
2645
|
-
users: number;
|
|
2646
|
-
api_keys: number;
|
|
2647
|
-
}>;
|
|
2648
|
-
getUserByPlatformUserId(platformUserId: string): Promise<User | null>;
|
|
2649
|
-
private getFirstReplicaAdminUser;
|
|
2650
|
-
private upsertPlatformReplicaApiKey;
|
|
2651
|
-
/**
|
|
2652
|
-
* Create a new session.
|
|
2653
|
-
*/
|
|
2654
|
-
createSession(params: {
|
|
2655
|
-
user_id: string;
|
|
2656
|
-
token_hash: string;
|
|
2657
|
-
expires_at: number;
|
|
2658
|
-
}): Promise<string>;
|
|
2659
|
-
/**
|
|
2660
|
-
* Validate a session token.
|
|
2661
|
-
*/
|
|
2662
|
-
validateSession(tokenHash: string): Promise<{
|
|
2663
|
-
user_id: string;
|
|
2664
|
-
expires_at: number;
|
|
2665
|
-
} | null>;
|
|
2666
|
-
/**
|
|
2667
|
-
* Delete expired sessions.
|
|
2668
|
-
*/
|
|
2669
|
-
cleanupSessions(): Promise<number>;
|
|
2670
|
-
/**
|
|
2671
|
-
* Delete a session.
|
|
2672
|
-
*/
|
|
2673
|
-
deleteSession(tokenHash: string): Promise<void>;
|
|
2674
|
-
/** Register a short-lived super-admin token so it can be revoked alone. */
|
|
2675
|
-
createSuperAdminSession(params: {
|
|
2676
|
-
token_hash: string;
|
|
2677
|
-
expires_at: number;
|
|
2678
|
-
}): Promise<void>;
|
|
2679
|
-
/** A valid signature is insufficient: the session must still be registered. */
|
|
2680
|
-
validateSuperAdminSession(tokenHash: string): Promise<boolean>;
|
|
2681
|
-
/** Revoke only the presented super-admin session; no key rotation required. */
|
|
2682
|
-
deleteSuperAdminSession(tokenHash: string): Promise<void>;
|
|
2683
|
-
/** Register a path-bound bearer ticket for one WebSocket handshake. */
|
|
2684
|
-
createWebSocketTicket(params: {
|
|
2685
|
-
ticket_hash: string;
|
|
2686
|
-
pathname: string;
|
|
2687
|
-
auth_json: string;
|
|
2688
|
-
expires_at: number;
|
|
2689
|
-
}): Promise<void>;
|
|
2690
|
-
/**
|
|
2691
|
-
* Atomically consume a WebSocket ticket. Deleting before validating its path
|
|
2692
|
-
* means even a mistaken or malicious first presentation burns the bearer.
|
|
2693
|
-
*/
|
|
2694
|
-
consumeWebSocketTicket(params: {
|
|
2695
|
-
ticket_hash: string;
|
|
2696
|
-
pathname: string;
|
|
2697
|
-
}): Promise<string | null>;
|
|
2698
|
-
/** Atomically accept an unexpired platform handoff identifier once. */
|
|
2699
|
-
consumePlatformHandoffJti(params: {
|
|
2700
|
-
jti: string;
|
|
2701
|
-
expires_at: number;
|
|
2702
|
-
}): Promise<boolean>;
|
|
2703
|
-
/**
|
|
2704
|
-
* Atomically consume one attempt from a fixed-window authentication bucket.
|
|
2705
|
-
* The singleton Durable Object serializes calls, preventing parallel bypass.
|
|
2706
|
-
*/
|
|
2707
|
-
consumeAuthRateLimit(params: {
|
|
2708
|
-
key: string;
|
|
2709
|
-
limit: number;
|
|
2710
|
-
window_seconds: number;
|
|
2711
|
-
}): Promise<{
|
|
2712
|
-
allowed: boolean;
|
|
2713
|
-
retry_after: number;
|
|
2714
|
-
remaining: number;
|
|
2715
|
-
}>;
|
|
2716
|
-
/**
|
|
2717
|
-
* Create an API key.
|
|
2718
|
-
*/
|
|
2719
|
-
createApiKey(params: {
|
|
2720
|
-
name: string;
|
|
2721
|
-
key_hash: string;
|
|
2722
|
-
key_prefix: string;
|
|
2723
|
-
last_five: string;
|
|
2724
|
-
user_id: string;
|
|
2725
|
-
}): Promise<string>;
|
|
2726
|
-
/**
|
|
2727
|
-
* Validate an API key.
|
|
2728
|
-
*/
|
|
2729
|
-
validateApiKey(keyHash: string): Promise<{
|
|
2730
|
-
user_id: string;
|
|
2731
|
-
id: string;
|
|
2732
|
-
} | null>;
|
|
2733
|
-
/**
|
|
2734
|
-
* List API keys for a user.
|
|
2735
|
-
*/
|
|
2736
|
-
listApiKeys(userId: string): Promise<Array<{
|
|
2737
|
-
id: string;
|
|
2738
|
-
name: string;
|
|
2739
|
-
key_prefix: string;
|
|
2740
|
-
last_five: string;
|
|
2741
|
-
source: 'local' | 'standard_agents';
|
|
2742
|
-
created_at: number;
|
|
2743
|
-
last_used_at: number | null;
|
|
2744
|
-
}>>;
|
|
2745
|
-
/**
|
|
2746
|
-
* Delete an API key.
|
|
2747
|
-
*/
|
|
2748
|
-
deleteApiKey(id: string, userId: string): Promise<boolean>;
|
|
2749
|
-
/**
|
|
2750
|
-
* Link an OAuth account to a user.
|
|
2751
|
-
*/
|
|
2752
|
-
linkOAuthAccount(params: {
|
|
2753
|
-
user_id: string;
|
|
2754
|
-
provider: 'github' | 'google';
|
|
2755
|
-
provider_user_id: string;
|
|
2756
|
-
provider_username?: string;
|
|
2757
|
-
}): Promise<void>;
|
|
2758
|
-
/**
|
|
2759
|
-
* Find user by OAuth account.
|
|
2760
|
-
*/
|
|
2761
|
-
findUserByOAuth(provider: 'github' | 'google', providerUserId: string): Promise<User | null>;
|
|
2762
|
-
/**
|
|
2763
|
-
* Acquire edit lock for coordinated edits.
|
|
2764
|
-
*/
|
|
2765
|
-
acquireEditLock(params: {
|
|
2766
|
-
locked_by: string;
|
|
2767
|
-
lock_reason: string;
|
|
2768
|
-
}): Promise<boolean>;
|
|
2769
|
-
/**
|
|
2770
|
-
* Release edit lock.
|
|
2771
|
-
*/
|
|
2772
|
-
releaseEditLock(lockedBy: string): Promise<boolean>;
|
|
2773
|
-
/**
|
|
2774
|
-
* Get current lock state.
|
|
2775
|
-
*/
|
|
2776
|
-
getEditLockState(): Promise<{
|
|
2777
|
-
locked: boolean;
|
|
2778
|
-
locked_by: string | null;
|
|
2779
|
-
locked_at: number | null;
|
|
2780
|
-
lock_reason: string | null;
|
|
2781
|
-
pending_changes: string | null;
|
|
2782
|
-
}>;
|
|
2783
|
-
/**
|
|
2784
|
-
* Store pending changes for commit.
|
|
2785
|
-
*/
|
|
2786
|
-
setPendingChanges(changes: string): Promise<void>;
|
|
2787
|
-
/**
|
|
2788
|
-
* Get the Durable Object stub for a thread.
|
|
2789
|
-
*/
|
|
2790
|
-
getThreadStub(threadId: string): DurableObjectStub;
|
|
2791
|
-
/**
|
|
2792
|
-
* Handle fetch requests - used for WebSocket upgrades
|
|
2793
|
-
*/
|
|
2794
|
-
fetch(request: Request): Promise<Response>;
|
|
2795
|
-
/**
|
|
2796
|
-
* Handle WebSocket upgrade for events channel
|
|
2797
|
-
* Uses Hibernation API to reduce costs during inactivity
|
|
2798
|
-
*/
|
|
2799
|
-
private handleEventsWebSocketUpgrade;
|
|
2800
|
-
/**
|
|
2801
|
-
* Re-broadcast a `thread_updated` for a single thread to all event listeners.
|
|
2802
|
-
*
|
|
2803
|
-
* Subagent running/idle status lives in the *parent's* child registry, not on
|
|
2804
|
-
* the thread row, so a status change (e.g. running → idle) normally produces
|
|
2805
|
-
* no thread-registry event. The child-registry writer calls this so live
|
|
2806
|
-
* listeners (the CLI subagent indicator) re-read `/api/threads/:id/subagents`
|
|
2807
|
-
* and reflect the new status without polling.
|
|
2808
|
-
*/
|
|
2809
|
-
broadcastThreadUpdated(threadId: string): Promise<void>;
|
|
2810
|
-
/**
|
|
2811
|
-
* Broadcast an event only to its owner or an explicitly all-scoped admin.
|
|
2812
|
-
*/
|
|
2813
|
-
private broadcastEvent;
|
|
2814
|
-
/** Resolve a thread owner without decrypting its env or loading the row. */
|
|
2815
|
-
private getThreadOwnerId;
|
|
2816
|
-
/**
|
|
2817
|
-
* WebSocket Hibernation API handler for incoming messages
|
|
2818
|
-
* Called when a message is received on a hibernated WebSocket
|
|
2819
|
-
*/
|
|
2820
|
-
webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): Promise<void>;
|
|
2821
|
-
/**
|
|
2822
|
-
* WebSocket Hibernation API handler for connection close
|
|
2823
|
-
* Called when a WebSocket connection is closed
|
|
2824
|
-
*/
|
|
2825
|
-
webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean): Promise<void>;
|
|
2826
|
-
/**
|
|
2827
|
-
* WebSocket Hibernation API handler for errors
|
|
2828
|
-
* Called when a WebSocket encounters an error
|
|
2829
|
-
*/
|
|
2830
|
-
webSocketError(ws: WebSocket, error: unknown): Promise<void>;
|
|
2831
|
-
/** Installed skills, metadata only (no file contents). */
|
|
2832
|
-
listSkills(scope: SkillStorageScope, options?: {
|
|
2833
|
-
includeDisabled?: boolean;
|
|
2834
|
-
}): Promise<SkillMetadata[]>;
|
|
2835
|
-
/** One skill's metadata (null when not installed). */
|
|
2836
|
-
getSkill(scope: SkillStorageScope, name: string): Promise<SkillMetadata | null>;
|
|
2837
|
-
/** One bundled file's text (null when the skill or file is missing). */
|
|
2838
|
-
getSkillFile(scope: SkillStorageScope, name: string, path: string): Promise<string | null>;
|
|
2839
|
-
/**
|
|
2840
|
-
* Install (or replace) a skill from its file set. Validates the payload and
|
|
2841
|
-
* the root SKILL.md frontmatter; the skill's identity always comes from
|
|
2842
|
-
* that frontmatter. Throws SkillValidationError with an actionable message
|
|
2843
|
-
* on any standard violation.
|
|
2844
|
-
*/
|
|
2845
|
-
upsertSkill(scope: SkillStorageScope, files: SkillFileInput[]): Promise<SkillMetadata>;
|
|
2846
|
-
/** Enable/disable an installed skill. Returns false when not installed. */
|
|
2847
|
-
setSkillEnabled(scope: SkillStorageScope, name: string, enabled: boolean): Promise<boolean>;
|
|
2848
|
-
private sweepDeviceLogins;
|
|
2849
|
-
startDeviceLogin(codeHash: string): Promise<void>;
|
|
2850
|
-
/** Poll a device login. An approved row returns its token exactly once. */
|
|
2851
|
-
pollDeviceLogin(codeHash: string): Promise<{
|
|
2852
|
-
status: string;
|
|
2853
|
-
token?: string;
|
|
2854
|
-
} | null>;
|
|
2855
|
-
/** Deny a pending device login without creating a user or API key. */
|
|
2856
|
-
denyDeviceLogin(codeHash: string): Promise<boolean>;
|
|
2857
|
-
/** Approve a pending device login: mint a personal API key for the user and
|
|
2858
|
-
* park its plaintext for the single claim. A retry by the same user remains
|
|
2859
|
-
* successful after the row is approved or claimed, without minting another
|
|
2860
|
-
* key. Returns false for unknown, expired, denied, or differently-owned
|
|
2861
|
-
* logins. */
|
|
2862
|
-
approveDeviceLogin(params: {
|
|
2863
|
-
code_hash: string;
|
|
2864
|
-
user_id: string;
|
|
2865
|
-
token: string;
|
|
2866
|
-
token_hash: string;
|
|
2867
|
-
key_prefix: string;
|
|
2868
|
-
last_five: string;
|
|
2869
|
-
key_name: string;
|
|
2870
|
-
}): Promise<boolean>;
|
|
2871
|
-
/** Uninstall a skill and its files. Returns false when not installed. */
|
|
2872
|
-
deleteSkill(scope: SkillStorageScope, name: string): Promise<boolean>;
|
|
2873
|
-
}
|
|
2874
|
-
|
|
2875
|
-
interface CodeExecutionBridgeProps {
|
|
2876
|
-
threadId?: string;
|
|
2877
|
-
runId?: string;
|
|
2878
|
-
}
|
|
2879
|
-
declare class CodeExecutionBridge extends WorkerEntrypoint<ThreadEnv, CodeExecutionBridgeProps> {
|
|
2880
|
-
call(threadId: string, runId: string, functionId: string, encodedArgs: unknown[]): Promise<unknown>;
|
|
2881
|
-
}
|
|
2882
|
-
|
|
2883
|
-
/**
|
|
2884
|
-
* ThreadWatchdog — a per-thread companion Durable Object whose only job is to
|
|
2885
|
-
* deliver liveness checks INTO a DurableThread on a schedule the thread cannot
|
|
2886
|
-
* starve.
|
|
2887
|
-
*
|
|
2888
|
-
* Why this exists (2026-07-08 incident, api.standardcode.ai): every normal
|
|
2889
|
-
* turn is dispatched through the thread's own AlarmQueue and runs INSIDE its
|
|
2890
|
-
* alarm() handler. Cloudflare serializes alarm invocations per object and the
|
|
2891
|
-
* queue only re-arms the storage alarm after the current item finishes — so
|
|
2892
|
-
* while a turn runs, the thread's own standing `watchdogCheck` alarm rows are
|
|
2893
|
-
* inert. When a provider request wedged (zero bytes for 18+ minutes, in-flight
|
|
2894
|
-
* stall-guard timers frozen with the turn's context), nothing could fire: the
|
|
2895
|
-
* thread sat "working" forever, and the user's UI polling kept the instance
|
|
2896
|
-
* resident, which is exactly what prevented fresh-instance wake recovery.
|
|
2897
|
-
* A manual RPC delivery of the same check recovered the thread in one call —
|
|
2898
|
-
* the LOGIC was sound, the DELIVERY was starved. This object is that delivery.
|
|
2899
|
-
*
|
|
2900
|
-
* Design rules:
|
|
2901
|
-
* - The alarm handler stays tiny: one probe RPC + reschedule. It must never
|
|
2902
|
-
* run long work, so it can never starve itself the way thread turns do.
|
|
2903
|
-
* - Reschedule-first: the next alarm is set before the probe runs, so a crash
|
|
2904
|
-
* mid-probe never kills the chain.
|
|
2905
|
-
* - Parent-child lifecycle is explicit (Cloudflare has no cascade): the
|
|
2906
|
-
* companion is created lazily by the thread's execution start (`arm`),
|
|
2907
|
-
* stands itself down when the thread probes clean, and is destroyed by
|
|
2908
|
-
* `DurableThread.deleteThread()`/`terminateThread()`. Standing down keeps
|
|
2909
|
-
* the check-in history (the UI reads it) but drops the alarm — a DO with no
|
|
2910
|
-
* alarm and no traffic hibernates at zero cost.
|
|
2911
|
-
* - Probe timeouts are counted, not fatal: a thread DO whose input gate is
|
|
2912
|
-
* permanently blocked cannot be revived at the application layer, so after
|
|
2913
|
-
* MAX_UNREACHABLE consecutive timeouts the companion logs loudly and stands
|
|
2914
|
-
* down instead of ticking forever.
|
|
2915
|
-
*/
|
|
2916
|
-
/** One recorded check-in, newest first in storage. */
|
|
2917
|
-
interface WatchdogCheckin {
|
|
2918
|
-
at: number;
|
|
2919
|
-
/** Thread verdict, or 'unreachable' when the probe itself failed/timed out. */
|
|
2920
|
-
verdict: "healthy" | "observing" | "recovered" | "parked" | "idle" | "unreachable";
|
|
2921
|
-
/** What the probe did, for the UI's determination column. */
|
|
2922
|
-
action: string;
|
|
2923
|
-
executing: boolean | null;
|
|
2924
|
-
incompleteLogs: number | null;
|
|
2925
|
-
silenceMs: number | null;
|
|
2926
|
-
probeMs: number;
|
|
2927
|
-
error?: string;
|
|
2928
|
-
}
|
|
2929
|
-
interface ThreadWatchdogState {
|
|
2930
|
-
armed: boolean;
|
|
2931
|
-
threadId: string | null;
|
|
2932
|
-
armedAt: number | null;
|
|
2933
|
-
history: WatchdogCheckin[];
|
|
2934
|
-
}
|
|
2935
|
-
interface ThreadWatchdogEnv {
|
|
2936
|
-
AGENT_BUILDER_THREAD: {
|
|
2937
|
-
idFromName(name: string): unknown;
|
|
2938
|
-
get(id: unknown): unknown;
|
|
2939
|
-
};
|
|
2940
|
-
[key: string]: unknown;
|
|
2941
|
-
}
|
|
2942
|
-
declare class ThreadWatchdog extends DurableObject<ThreadWatchdogEnv> {
|
|
2943
|
-
/**
|
|
2944
|
-
* Arm (or re-arm) the standing check for a thread execution. Idempotent —
|
|
2945
|
-
* called at every execution start. Resets the unreachable counter because a
|
|
2946
|
-
* fresh arm proves the thread is answering RPCs right now.
|
|
2947
|
-
*/
|
|
2948
|
-
arm(threadId: string): Promise<void>;
|
|
2949
|
-
/**
|
|
2950
|
-
* Hint that the thread believes its execution ended cleanly. The companion
|
|
2951
|
-
* does NOT trust this (a bogus "clean end" was one of the incident's failure
|
|
2952
|
-
* modes) — it just moves the next check close so a genuinely clean thread
|
|
2953
|
-
* stands down in seconds instead of a full cadence.
|
|
2954
|
-
*/
|
|
2955
|
-
disarmHint(): Promise<void>;
|
|
2956
|
-
/** Diagnostics view for the thread inspector UI and the diag CLI. */
|
|
2957
|
-
getState(): Promise<ThreadWatchdogState>;
|
|
2958
|
-
/**
|
|
2959
|
-
* Explicit cascade from the parent thread (delete/terminate). Cloudflare
|
|
2960
|
-
* has no automatic parent-child cleanup — this IS the cleanup.
|
|
2961
|
-
*/
|
|
2962
|
-
destroy(): Promise<void>;
|
|
2963
|
-
alarm(): Promise<void>;
|
|
2964
|
-
private getThreadStub;
|
|
2965
|
-
private probeThread;
|
|
2966
|
-
private recordCheckin;
|
|
2967
|
-
}
|
|
2968
|
-
|
|
2969
|
-
/**
|
|
2970
|
-
* Model definition module for AgentBuilder.
|
|
2971
|
-
*
|
|
2972
|
-
* This module re-exports model types from @standardagents/spec and provides
|
|
2973
|
-
* a builder-specific version of ModelDefinition that supports the generated
|
|
2974
|
-
* AgentBuilder.Models type for fallback references.
|
|
2975
|
-
*
|
|
2976
|
-
* @module
|
|
2977
|
-
*/
|
|
2978
|
-
|
|
2979
|
-
/**
|
|
2980
|
-
* Model definition configuration with AgentBuilder-specific fallback typing.
|
|
2981
|
-
*
|
|
2982
|
-
* Extends the base ModelDefinition from @standardagents/spec to support
|
|
2983
|
-
* the generated AgentBuilder.Models type for type-safe fallback references.
|
|
2984
|
-
*
|
|
2985
|
-
* @template N - The model name as a string literal type for type inference
|
|
2986
|
-
*/
|
|
2987
|
-
interface ModelDefinition<N extends string = string> extends Omit<ModelDefinition$1<N>, 'fallbacks'> {
|
|
2988
|
-
/**
|
|
2989
|
-
* Fallback models to try if this model fails.
|
|
2990
|
-
* Referenced by model name (must be defined in agents/models/).
|
|
2991
|
-
* Tried in order after primary model exhausts retries.
|
|
2992
|
-
*
|
|
2993
|
-
* @example ['gpt-4', 'gpt-3.5-turbo']
|
|
2994
|
-
*/
|
|
2995
|
-
fallbacks?: AgentBuilder.Models[];
|
|
2996
|
-
}
|
|
2997
|
-
|
|
2998
|
-
/**
|
|
2999
|
-
* Prompt definition module for AgentBuilder.
|
|
3000
|
-
*
|
|
3001
|
-
* This module re-exports prompt types from @standardagents/spec and provides
|
|
3002
|
-
* builder-specific versions that use the generated AgentBuilder namespace types.
|
|
3003
|
-
*
|
|
3004
|
-
* @module
|
|
3005
|
-
*/
|
|
3006
|
-
|
|
3007
|
-
/**
|
|
3008
|
-
* A prompt inclusion part with type-safe autocomplete.
|
|
3009
|
-
* Uses AgentBuilder.Prompts for type-safe prompt name references.
|
|
3010
|
-
*/
|
|
3011
|
-
interface PromptIncludePart {
|
|
3012
|
-
type: 'include';
|
|
3013
|
-
/** The name of the prompt to include (type-safe with autocomplete) */
|
|
3014
|
-
prompt: AgentBuilder.Prompts;
|
|
3015
|
-
}
|
|
3016
|
-
/**
|
|
3017
|
-
* A single part of a structured prompt.
|
|
3018
|
-
*/
|
|
3019
|
-
type PromptPart = PromptTextPart | PromptIncludePart | PromptEnvPart;
|
|
3020
|
-
/**
|
|
3021
|
-
* Prompt content can be a string or structured array with type-safe includes.
|
|
3022
|
-
*/
|
|
3023
|
-
type PromptContent = string | PromptPart[];
|
|
3024
|
-
/**
|
|
3025
|
-
* Sub-prompt configuration with type-safe name references.
|
|
3026
|
-
*/
|
|
3027
|
-
interface SubpromptConfig<T extends string = AgentBuilder.Callables> extends Omit<SubpromptConfig$1<T>, 'name'> {
|
|
3028
|
-
/** Name of the sub-prompt (type-safe with autocomplete) */
|
|
3029
|
-
name: T;
|
|
3030
|
-
}
|
|
3031
|
-
/**
|
|
3032
|
-
* Prompt tool configuration with static tenvs/options.
|
|
3033
|
-
*/
|
|
3034
|
-
interface PromptToolConfig<T extends string = AgentBuilder.Callables> extends Omit<PromptToolConfig$1, 'name'> {
|
|
3035
|
-
/** Name of the callable tool/agent (type-safe with autocomplete). */
|
|
3036
|
-
name: T;
|
|
3037
|
-
/** Environment values scoped to this tool invocation. */
|
|
3038
|
-
env?: Record<string, string>;
|
|
3039
|
-
/** @deprecated Use env */
|
|
3040
|
-
tenvs?: Record<string, unknown>;
|
|
3041
|
-
}
|
|
3042
|
-
/**
|
|
3043
|
-
* @deprecated Removed in 0.2.0 — subagent relationships are no longer
|
|
3044
|
-
* declared in a prompt's `tools` array. Declare them on the owning side's
|
|
3045
|
-
* `subagents` array instead (see `SubagentRelationship`). The owning side's
|
|
3046
|
-
* prompt automatically receives the lifecycle tools (`subagents`,
|
|
3047
|
-
* `subagent_create`, `subagent_message`).
|
|
3048
|
-
*/
|
|
3049
|
-
type SubagentToolConfig<T extends string = string> = never;
|
|
3050
|
-
/**
|
|
3051
|
-
* @deprecated Use SubpromptConfig instead
|
|
3052
|
-
*/
|
|
3053
|
-
type ToolConfig<T extends string = AgentBuilder.Callables> = SubpromptConfig<T>;
|
|
3054
|
-
|
|
3055
|
-
/**
|
|
3056
|
-
* Prompt definition configuration with AgentBuilder-specific typing.
|
|
3057
|
-
*
|
|
3058
|
-
* Provides type-safe references to models, tools, and agents via the
|
|
3059
|
-
* generated AgentBuilder namespace.
|
|
3060
|
-
*
|
|
3061
|
-
* @template N - The prompt name as a string literal type
|
|
3062
|
-
* @template S - The Zod schema type for requiredSchema (inferred automatically)
|
|
3063
|
-
*/
|
|
3064
|
-
interface PromptDefinition<N extends string = string, S extends ToolArgs = ToolArgs> {
|
|
3065
|
-
/** Unique name for this prompt. */
|
|
3066
|
-
name: N;
|
|
3067
|
-
/** Description shown when this prompt is exposed as a tool. */
|
|
3068
|
-
toolDescription: string;
|
|
3069
|
-
/** The system prompt content with type-safe includes. */
|
|
3070
|
-
prompt: PromptContent;
|
|
3071
|
-
/** Model to use (type-safe with autocomplete). */
|
|
3072
|
-
model: AgentBuilder.Models;
|
|
3073
|
-
/**
|
|
3074
|
-
* @deprecated All prompts are now automatically exposed as tools.
|
|
3075
|
-
*/
|
|
3076
|
-
exposeAsTool?: boolean;
|
|
3077
|
-
/** Include full chat history in the LLM context. @default false */
|
|
3078
|
-
includeChat?: boolean;
|
|
3079
|
-
/** Include results from past tool calls. @default false */
|
|
3080
|
-
includePastTools?: boolean;
|
|
3081
|
-
/** Allow parallel execution of multiple tool calls. @default false */
|
|
3082
|
-
parallelToolCalls?: boolean;
|
|
3083
|
-
/** Tool calling strategy. @default 'auto' */
|
|
3084
|
-
toolChoice?: 'auto' | 'none' | 'required';
|
|
3085
|
-
/** Zod schema for validating inputs when called as a tool. */
|
|
3086
|
-
requiredSchema?: S;
|
|
3087
|
-
/** Variable declarations for this prompt. */
|
|
3088
|
-
variables?: VariableDefinition[];
|
|
3089
|
-
/**
|
|
3090
|
-
* Tools available to this prompt (type-safe with autocomplete). To enable
|
|
3091
|
-
* handoffs, include exposed agent names. Subagent relationships are NOT
|
|
3092
|
-
* declared here — they live on the owning side's `subagents` array, and
|
|
3093
|
-
* the runtime injects the lifecycle tools automatically. Handlers may
|
|
3094
|
-
* never appear in this array.
|
|
3095
|
-
*/
|
|
3096
|
-
tools?: (AgentBuilder.Callables | SubpromptConfig | PromptToolConfig)[];
|
|
3097
|
-
/** Prompt-level environment values. */
|
|
3098
|
-
env?: Record<string, string>;
|
|
3099
|
-
/** @deprecated Use env */
|
|
3100
|
-
tenvs?: Record<string, unknown>;
|
|
3101
|
-
/** Reasoning configuration for extended thinking models. */
|
|
3102
|
-
reasoning?: ReasoningConfig;
|
|
3103
|
-
/** Number of recent messages to keep actual images for. @default 10 */
|
|
3104
|
-
recentImageThreshold?: number;
|
|
3105
|
-
/** Hook IDs to run when this prompt is active. Falls back to agent-level hooks if not set. */
|
|
3106
|
-
hooks?: AgentBuilder.Hooks[];
|
|
3107
|
-
}
|
|
3108
|
-
|
|
3109
|
-
/**
|
|
3110
|
-
* Agent definition module for AgentBuilder.
|
|
3111
|
-
*
|
|
3112
|
-
* This module re-exports agent types from @standardagents/spec and provides
|
|
3113
|
-
* builder-specific versions that use the generated AgentBuilder namespace types.
|
|
3114
|
-
*
|
|
3115
|
-
* An agent has exactly two sides; each side is backed by exactly one of
|
|
3116
|
-
* `human`, `prompt`, or `handler`. There is no agent "type".
|
|
3117
|
-
*
|
|
3118
|
-
* @module
|
|
3119
|
-
*/
|
|
3120
|
-
|
|
3121
|
-
/**
|
|
3122
|
-
* Session lifecycle tool configuration with type-safe autocomplete.
|
|
3123
|
-
* Object form only — the bare-string binding was removed in 0.2.0.
|
|
3124
|
-
*/
|
|
3125
|
-
interface SessionToolConfig {
|
|
3126
|
-
/**
|
|
3127
|
-
* Tool name for this lifecycle binding.
|
|
3128
|
-
*/
|
|
3129
|
-
readonly name: AgentBuilder.Callables;
|
|
3130
|
-
/**
|
|
3131
|
-
* Optional tool-argument property used as message text.
|
|
3132
|
-
*/
|
|
3133
|
-
readonly messageProperty?: string;
|
|
3134
|
-
/**
|
|
3135
|
-
* Optional tool-argument property containing attachment path(s).
|
|
3136
|
-
*/
|
|
3137
|
-
readonly attachmentsProperty?: string;
|
|
3138
|
-
}
|
|
3139
|
-
/**
|
|
3140
|
-
* Session lifecycle binding.
|
|
3141
|
-
* Object form only — use `{ name: 'tool_name' }` in place of `'tool_name'`.
|
|
3142
|
-
*/
|
|
3143
|
-
type SessionToolBinding = SessionToolConfig;
|
|
3144
|
-
/**
|
|
3145
|
-
* A side-owned subagent relationship with type-safe agent references.
|
|
3146
|
-
* See the spec `SubagentRelationship` for full semantics.
|
|
3147
|
-
*/
|
|
3148
|
-
interface SubagentRelationship extends Omit<SubagentRelationship$1, 'agent' | 'initUserMessageProperty' | 'initAttachmentsProperty' | 'initAgentNameProperty'> {
|
|
3149
|
-
/**
|
|
3150
|
-
* Which agent definition to instantiate (type-safe with autocomplete).
|
|
3151
|
-
* Must reference an agent with `exposeAsTool: true`.
|
|
3152
|
-
*/
|
|
3153
|
-
readonly agent: AgentBuilder.Agents;
|
|
3154
|
-
/**
|
|
3155
|
-
* Property from `subagent_create` arguments used as the initial user
|
|
3156
|
-
* message when spawning an instance.
|
|
3157
|
-
*/
|
|
3158
|
-
readonly initUserMessageProperty?: string;
|
|
3159
|
-
/**
|
|
3160
|
-
* Property from `subagent_create` arguments containing attachment path(s)
|
|
3161
|
-
* to include with the initial message.
|
|
3162
|
-
*/
|
|
3163
|
-
readonly initAttachmentsProperty?: string;
|
|
3164
|
-
/**
|
|
3165
|
-
* Property from `subagent_create` arguments used as a human-readable name
|
|
3166
|
-
* for each spawned instance.
|
|
3167
|
-
*/
|
|
3168
|
-
readonly initAgentNameProperty?: string;
|
|
3169
|
-
}
|
|
3170
|
-
/**
|
|
3171
|
-
* A side backed by a human: a person takes this side's turns. The runtime
|
|
3172
|
-
* parks execution awaiting inbound input on this side's perspective.
|
|
3173
|
-
*/
|
|
3174
|
-
type HumanSide = HumanSide$1;
|
|
3175
|
-
/**
|
|
3176
|
-
* A side backed by a prompt: a model takes this side's turns
|
|
3177
|
-
* (type-safe with autocomplete).
|
|
3178
|
-
*/
|
|
3179
|
-
interface PromptSide {
|
|
3180
|
-
/**
|
|
3181
|
-
* The prompt to use for this side.
|
|
3182
|
-
* Must reference a prompt defined in agents/prompts/.
|
|
3183
|
-
*/
|
|
3184
|
-
readonly prompt: AgentBuilder.Prompts;
|
|
3185
|
-
/** Custom label for this side of the conversation. */
|
|
3186
|
-
readonly label?: string;
|
|
3187
|
-
/**
|
|
3188
|
-
* Subagent relationships OWNED by this side. The side's prompt
|
|
3189
|
-
* automatically receives the lifecycle tools (`subagents`,
|
|
3190
|
-
* `subagent_create`, `subagent_message`) for the side's non-hidden
|
|
3191
|
-
* relationships; inbound child traffic lands on this side's perspective.
|
|
3192
|
-
*/
|
|
3193
|
-
readonly subagents?: readonly SubagentRelationship[];
|
|
3194
|
-
/**
|
|
3195
|
-
* Stop this side's turn when it returns a text response (no tool calls).
|
|
3196
|
-
* @default true
|
|
3197
|
-
*/
|
|
3198
|
-
readonly stopOnResponse?: boolean;
|
|
3199
|
-
/**
|
|
3200
|
-
* Stop this side's turn when a specific tool is called (type-safe with
|
|
3201
|
-
* autocomplete). Requires stopToolResponseProperty to extract the result.
|
|
3202
|
-
*/
|
|
3203
|
-
readonly stopTool?: AgentBuilder.Callables;
|
|
3204
|
-
/**
|
|
3205
|
-
* Property to extract from the stop tool's result.
|
|
3206
|
-
* Required when stopTool is set.
|
|
3207
|
-
*/
|
|
3208
|
-
readonly stopToolResponseProperty?: string;
|
|
3209
|
-
/**
|
|
3210
|
-
* Maximum steps for this side before forcing a stop.
|
|
3211
|
-
* A step is one complete LLM request/response cycle.
|
|
3212
|
-
*/
|
|
3213
|
-
readonly maxSteps?: number;
|
|
3214
|
-
/**
|
|
3215
|
-
* Tool that ends the entire session when called. Ending a session never
|
|
3216
|
-
* terminates the thread.
|
|
3217
|
-
*/
|
|
3218
|
-
readonly sessionStop?: SessionToolBinding;
|
|
3219
|
-
/**
|
|
3220
|
-
* Tool that fails the entire session when called. Failing a session never
|
|
3221
|
-
* terminates the thread.
|
|
3222
|
-
*/
|
|
3223
|
-
readonly sessionFail?: SessionToolBinding;
|
|
3224
|
-
/**
|
|
3225
|
-
* Tool that publishes status updates to the parent thread when this agent
|
|
3226
|
-
* runs as a subagent.
|
|
3227
|
-
*/
|
|
3228
|
-
readonly sessionStatus?: SessionToolBinding;
|
|
3229
|
-
/**
|
|
3230
|
-
* Enable manual stop condition handling via hooks.
|
|
3231
|
-
* Builder-specific feature for custom stop logic.
|
|
3232
|
-
* @default false
|
|
3233
|
-
*/
|
|
3234
|
-
readonly manualStopCondition?: boolean;
|
|
3235
|
-
readonly human?: never;
|
|
3236
|
-
readonly handler?: never;
|
|
3237
|
-
}
|
|
3238
|
-
/**
|
|
3239
|
-
* A side backed by a handler: deterministic code takes this side's turns
|
|
3240
|
-
* (type-safe with autocomplete). A handler turn has no steps to cap and no
|
|
3241
|
-
* session bindings — handlers end sessions via `state.stopSession()`.
|
|
3242
|
-
*/
|
|
3243
|
-
interface HandlerSide {
|
|
3244
|
-
/**
|
|
3245
|
-
* The handler that takes this side's turns.
|
|
3246
|
-
* Must reference a handler defined in agents/handlers/.
|
|
3247
|
-
*/
|
|
3248
|
-
readonly handler: AgentBuilder.Handlers;
|
|
3249
|
-
/** Custom label for this side of the conversation. */
|
|
3250
|
-
readonly label?: string;
|
|
3251
|
-
/**
|
|
3252
|
-
* Subagent relationships OWNED by this side. Handlers need no tool grant;
|
|
3253
|
-
* they reach children through `ThreadState`.
|
|
3254
|
-
*/
|
|
3255
|
-
readonly subagents?: readonly SubagentRelationship[];
|
|
3256
|
-
readonly human?: never;
|
|
3257
|
-
readonly prompt?: never;
|
|
3258
|
-
readonly stopOnResponse?: never;
|
|
3259
|
-
readonly stopTool?: never;
|
|
3260
|
-
readonly stopToolResponseProperty?: never;
|
|
3261
|
-
readonly maxSteps?: never;
|
|
3262
|
-
readonly sessionStop?: never;
|
|
3263
|
-
readonly sessionFail?: never;
|
|
3264
|
-
readonly sessionStatus?: never;
|
|
3265
|
-
readonly manualStopCondition?: never;
|
|
3266
|
-
}
|
|
3267
|
-
/**
|
|
3268
|
-
* Configuration for one side of an agent conversation — exactly one backing:
|
|
3269
|
-
* `human`, `prompt`, or `handler`. Both sides human is reserved and rejected.
|
|
3270
|
-
*/
|
|
3271
|
-
type SideConfig = HumanSide | PromptSide | HandlerSide;
|
|
3272
|
-
/**
|
|
3273
|
-
* Agent definition configuration with AgentBuilder-specific typing.
|
|
3274
|
-
*
|
|
3275
|
-
* Provides type-safe references to prompts, handlers, and agents via the
|
|
3276
|
-
* generated AgentBuilder namespace.
|
|
3277
|
-
*
|
|
3278
|
-
* @template N - The agent name as a string literal type
|
|
3279
|
-
*
|
|
3280
|
-
* @example
|
|
3281
|
-
* ```typescript
|
|
3282
|
-
* import { defineAgent } from '@standardagents/builder';
|
|
3283
|
-
*
|
|
3284
|
-
* export default defineAgent({
|
|
3285
|
-
* name: 'support_agent',
|
|
3286
|
-
* sideA: {
|
|
3287
|
-
* label: 'Support',
|
|
3288
|
-
* prompt: 'customer_support',
|
|
3289
|
-
* stopOnResponse: true,
|
|
3290
|
-
* },
|
|
3291
|
-
* sideB: { human: true },
|
|
3292
|
-
* });
|
|
3293
|
-
* ```
|
|
3294
|
-
*/
|
|
3295
|
-
interface AgentDefinition<N extends string = string> {
|
|
3296
|
-
/** Unique name for this agent. */
|
|
3297
|
-
readonly name: N;
|
|
3298
|
-
/**
|
|
3299
|
-
* Human-readable title for the agent.
|
|
3300
|
-
* @deprecated Use name instead. Title will be removed in a future version.
|
|
3301
|
-
*/
|
|
3302
|
-
readonly title?: string;
|
|
3303
|
-
/**
|
|
3304
|
-
* @deprecated Removed in 0.2.0 — there is no agent "type". Delete this
|
|
3305
|
-
* field and declare both sides explicitly: `type: 'ai_human'` becomes
|
|
3306
|
-
* `sideB: { human: true }`; `type: 'dual_ai'` is two prompt-backed sides.
|
|
3307
|
-
*/
|
|
3308
|
-
readonly type?: never;
|
|
3309
|
-
/**
|
|
3310
|
-
* Maximum total exchanges across both sides before the runtime ends the
|
|
3311
|
-
* session. Optional on every side combination; exchange counting is
|
|
3312
|
-
* uniform across backings. Reaching the cap ends the session, never the
|
|
3313
|
-
* thread.
|
|
3314
|
-
*/
|
|
3315
|
-
readonly maxSessionTurns?: number;
|
|
3316
|
-
/** Configuration for side A (type-safe with autocomplete). */
|
|
3317
|
-
readonly sideA: SideConfig;
|
|
3318
|
-
/** Configuration for side B (type-safe with autocomplete). */
|
|
3319
|
-
readonly sideB: SideConfig;
|
|
3320
|
-
/**
|
|
3321
|
-
* Expose this agent as a tool for other prompts.
|
|
3322
|
-
* Enables handoffs and subagent composition.
|
|
3323
|
-
* @default false
|
|
3324
|
-
*/
|
|
3325
|
-
readonly exposeAsTool?: boolean;
|
|
3326
|
-
/**
|
|
3327
|
-
* Whether this agent is a PRIMARY, user-facing entry point.
|
|
3328
|
-
* Set false on internal handoff targets (e.g. domain-gearbox variants) so
|
|
3329
|
-
* UIs keep them out of top-level agent lists while they stay fully
|
|
3330
|
-
* addressable for handoffs and thread resumption.
|
|
3331
|
-
* @default true
|
|
3332
|
-
*/
|
|
3333
|
-
readonly primary?: boolean;
|
|
3334
|
-
/** Description shown when agent is used as a tool. */
|
|
3335
|
-
readonly toolDescription?: string;
|
|
3336
|
-
/**
|
|
3337
|
-
* Thread-scoped hooks this child requires on every direct parent side that
|
|
3338
|
-
* declares a relationship targeting it. Legal on any exposed agent.
|
|
3339
|
-
*/
|
|
3340
|
-
readonly parentHooks?: readonly ParentHookRequirement[];
|
|
3341
|
-
/**
|
|
3342
|
-
* Environment values provided by this agent.
|
|
3343
|
-
*/
|
|
3344
|
-
readonly env?: Readonly<Record<string, string>>;
|
|
3345
|
-
/**
|
|
3346
|
-
* @deprecated Use env
|
|
3347
|
-
*/
|
|
3348
|
-
readonly tenvs?: Readonly<Record<string, unknown>>;
|
|
3349
|
-
/** Brief description of what this agent does. */
|
|
3350
|
-
readonly description?: string;
|
|
3351
|
-
/** Icon URL or absolute path for the agent. */
|
|
3352
|
-
readonly icon?: string;
|
|
3353
|
-
/**
|
|
3354
|
-
* npm package name for this agent when packed.
|
|
3355
|
-
* Preserved through unpack → edit → pack cycles.
|
|
3356
|
-
*/
|
|
3357
|
-
readonly packageName?: string;
|
|
3358
|
-
/**
|
|
3359
|
-
* Package version (semver format).
|
|
3360
|
-
* Preserved through unpack → edit → pack cycles.
|
|
3361
|
-
*/
|
|
3362
|
-
readonly version?: string;
|
|
3363
|
-
/**
|
|
3364
|
-
* Package author/copyright holder.
|
|
3365
|
-
* Preserved through unpack → edit → pack cycles.
|
|
3366
|
-
*/
|
|
3367
|
-
readonly author?: string;
|
|
3368
|
-
/**
|
|
3369
|
-
* License identifier (SPDX format).
|
|
3370
|
-
* Preserved through unpack → edit → pack cycles.
|
|
3371
|
-
*/
|
|
3372
|
-
readonly license?: string;
|
|
3373
|
-
}
|
|
3374
|
-
|
|
3375
|
-
/**
|
|
3376
|
-
* Options for injecting a message
|
|
3377
|
-
*/
|
|
3378
|
-
interface InjectMessageOptions {
|
|
3379
|
-
/** The message content */
|
|
3380
|
-
content: string;
|
|
3381
|
-
/** The message role */
|
|
3382
|
-
role: "system" | "user" | "assistant" | "tool";
|
|
3383
|
-
/** Optional message ID. If not provided, a UUID will be generated */
|
|
3384
|
-
id?: string;
|
|
3385
|
-
/** Optional message to insert before. If not provided, message is appended to the end */
|
|
3386
|
-
beforeMessageId?: string;
|
|
3387
|
-
/** Optional tool call ID (for role="tool" only) */
|
|
3388
|
-
toolCallId?: string;
|
|
3389
|
-
/** Optional name field */
|
|
3390
|
-
name?: string;
|
|
3391
|
-
/** Whether this message is silent (not shown in UI). Default: false */
|
|
3392
|
-
silent?: boolean;
|
|
3393
|
-
/** Optional structured metadata */
|
|
3394
|
-
metadata?: Record<string, unknown>;
|
|
3395
|
-
/** Force message to be top-level (depth 0) even when called from sub-prompts. Default: false */
|
|
3396
|
-
forceTopLevel?: boolean;
|
|
3397
|
-
/** Force a specific side to play the next turn after injecting the message */
|
|
3398
|
-
forceTurn?: "side_a" | "side_b";
|
|
3399
|
-
}
|
|
3400
|
-
/**
|
|
3401
|
-
* Queue a new tool call to be executed in the current flow
|
|
3402
|
-
*
|
|
3403
|
-
* This adds a tool call to the execution queue without immediately executing it.
|
|
3404
|
-
* The tool will be executed as part of the normal flow processing.
|
|
3405
|
-
*
|
|
3406
|
-
* If the current tool has a `uses` list defined, the toolName must be in that list.
|
|
3407
|
-
* This enforces namespace isolation for packed agents.
|
|
3408
|
-
*
|
|
3409
|
-
* @param flow - The current FlowState
|
|
3410
|
-
* @param toolName - The name of the tool to call
|
|
3411
|
-
* @param args - The arguments to pass to the tool
|
|
3412
|
-
* @throws Error if toolName is not in the current tool's uses list (when defined)
|
|
3413
|
-
*
|
|
3414
|
-
* @example
|
|
3415
|
-
* ```typescript
|
|
3416
|
-
* import { queueTool } from '@standardagents/builder';
|
|
3417
|
-
*
|
|
3418
|
-
* queueTool(flow, "search_user", { email: "user@example.com" });
|
|
3419
|
-
* ```
|
|
3420
|
-
*/
|
|
3421
|
-
declare function queueTool(flow: FlowState, toolName: string, args?: Record<string, unknown>): void;
|
|
3422
|
-
/**
|
|
3423
|
-
* Inject a message into the thread without triggering execution
|
|
3424
|
-
*
|
|
3425
|
-
* This allows you to add messages to the conversation history programmatically.
|
|
3426
|
-
* The message is persisted to storage but does not cause the agent to execute.
|
|
3427
|
-
*
|
|
3428
|
-
* By default, messages are appended to the end of the conversation.
|
|
3429
|
-
* You can optionally insert a message before another message by providing beforeMessageId.
|
|
3430
|
-
*
|
|
3431
|
-
* @param flow - The current FlowState
|
|
3432
|
-
* @param options - Message options
|
|
3433
|
-
*
|
|
3434
|
-
* @example
|
|
3435
|
-
* ```typescript
|
|
3436
|
-
* import { injectMessage } from '@standardagents/builder';
|
|
3437
|
-
*
|
|
3438
|
-
* // Append a system message
|
|
3439
|
-
* await injectMessage(flow, {
|
|
3440
|
-
* role: "system",
|
|
3441
|
-
* content: "Context has been updated"
|
|
3442
|
-
* });
|
|
3443
|
-
*
|
|
3444
|
-
* // Insert a user message before a specific message
|
|
3445
|
-
* await injectMessage(flow, {
|
|
3446
|
-
* role: "user",
|
|
3447
|
-
* content: "Additional context",
|
|
3448
|
-
* beforeMessageId: "msg-123"
|
|
3449
|
-
* });
|
|
3450
|
-
*
|
|
3451
|
-
* // Inject a message and force a specific side to play next
|
|
3452
|
-
* await injectMessage(flow, {
|
|
3453
|
-
* role: "system",
|
|
3454
|
-
* content: "New instructions for the AI",
|
|
3455
|
-
* forceTurn: "side_a" // Force side_a to respond to this message
|
|
3456
|
-
* });
|
|
3457
|
-
* ```
|
|
3458
|
-
*/
|
|
3459
|
-
declare function injectMessage(flow: FlowState, options: InjectMessageOptions): Promise<Message>;
|
|
3460
|
-
/**
|
|
3461
|
-
* Get messages from the thread history
|
|
3462
|
-
*
|
|
3463
|
-
* Retrieves message history from the thread's SQLite storage.
|
|
3464
|
-
* Messages are ordered by creation time (oldest first by default).
|
|
3465
|
-
*
|
|
3466
|
-
* @param flow - The current FlowState
|
|
3467
|
-
* @param limit - Maximum number of messages to retrieve (default: 100)
|
|
3468
|
-
* @param offset - Number of messages to skip (default: 0)
|
|
3469
|
-
* @param order - Sort order: "asc" (oldest first) or "desc" (newest first) (default: "asc")
|
|
3470
|
-
* @returns Array of messages
|
|
3471
|
-
*
|
|
3472
|
-
* @example
|
|
3473
|
-
* ```typescript
|
|
3474
|
-
* import { getMessages } from '@standardagents/builder';
|
|
3475
|
-
*
|
|
3476
|
-
* // Get last 10 messages
|
|
3477
|
-
* const messages = await getMessages(flow, 10);
|
|
3478
|
-
*
|
|
3479
|
-
* // Get 10 messages, skipping the first 20
|
|
3480
|
-
* const messages = await getMessages(flow, 10, 20);
|
|
3481
|
-
*
|
|
3482
|
-
* // Get newest 10 messages
|
|
3483
|
-
* const messages = await getMessages(flow, 10, 0, "desc");
|
|
3484
|
-
* ```
|
|
3485
|
-
*/
|
|
3486
|
-
declare function getMessages(flow: FlowState, limit?: number, offset?: number, order?: "asc" | "desc"): Promise<Message[]>;
|
|
3487
|
-
/**
|
|
3488
|
-
* Reload message history from storage
|
|
3489
|
-
*
|
|
3490
|
-
* Re-loads the complete message history from the thread's SQLite storage.
|
|
3491
|
-
* This is useful when you need to refresh the message history after making
|
|
3492
|
-
* changes (e.g., injecting messages).
|
|
3493
|
-
*
|
|
3494
|
-
* @param flow - The current FlowState
|
|
3495
|
-
* @returns Array of messages (reloaded from storage)
|
|
3496
|
-
*
|
|
3497
|
-
* @example
|
|
3498
|
-
* ```typescript
|
|
3499
|
-
* import { injectMessage, reloadHistory } from '@standardagents/builder';
|
|
3500
|
-
*
|
|
3501
|
-
* // Reload history after injecting a silent message
|
|
3502
|
-
* await injectMessage(flow, { role: "system", content: "...", silent: true });
|
|
3503
|
-
* flow.messageHistory = await reloadHistory(flow);
|
|
3504
|
-
* ```
|
|
3505
|
-
*/
|
|
3506
|
-
declare function reloadHistory(state: FlowState): Promise<Message[]>;
|
|
3507
|
-
/**
|
|
3508
|
-
* Emit a custom event to WebSocket clients via the stream
|
|
3509
|
-
*
|
|
3510
|
-
* Sends a custom event to all connected WebSocket clients on the stream channel.
|
|
3511
|
-
* This allows backend code to push arbitrary data to the frontend
|
|
3512
|
-
* outside of the standard message events.
|
|
3513
|
-
*
|
|
3514
|
-
* @param flow - The current FlowState
|
|
3515
|
-
* @param type - The event type name (e.g., "progress", "notification")
|
|
3516
|
-
* @param data - The event payload (any serializable data)
|
|
3517
|
-
*
|
|
3518
|
-
* @example
|
|
3519
|
-
* ```typescript
|
|
3520
|
-
* import { emitThreadEvent } from '@standardagents/builder';
|
|
3521
|
-
*
|
|
3522
|
-
* // Emit a progress update
|
|
3523
|
-
* emitThreadEvent(flow, "progress", { step: 3, total: 10, message: "Processing data..." });
|
|
3524
|
-
*
|
|
3525
|
-
* // Emit a custom notification
|
|
3526
|
-
* emitThreadEvent(flow, "notification", { level: "info", message: "User authenticated" });
|
|
3527
|
-
*
|
|
3528
|
-
* // Emit metadata
|
|
3529
|
-
* emitThreadEvent(flow, "metadata", { userId: "123", sessionId: "abc" });
|
|
3530
|
-
* ```
|
|
3531
|
-
*/
|
|
3532
|
-
declare function emitThreadEvent(flow: FlowState, type: string, data: unknown): void;
|
|
3533
|
-
/**
|
|
3534
|
-
* Force a specific side to play the next turn
|
|
3535
|
-
*
|
|
3536
|
-
* This queues the specified side to play next without interrupting the current turn.
|
|
3537
|
-
* The forced turn only takes effect at the END of the current turn execution.
|
|
3538
|
-
*
|
|
3539
|
-
* If the tool queue is currently being processed (sequence.isHandling is true),
|
|
3540
|
-
* the forced turn is deferred until all queued tools complete. This allows patterns like:
|
|
3541
|
-
*
|
|
3542
|
-
* ```typescript
|
|
3543
|
-
* import { queueTool, forceTurn } from '@standardagents/builder';
|
|
3544
|
-
*
|
|
3545
|
-
* queueTool(flow, 'myTool', {});
|
|
3546
|
-
* forceTurn(flow, 'side_a');
|
|
3547
|
-
* // myTool executes first, THEN the turn switches to side_a
|
|
3548
|
-
* ```
|
|
3549
|
-
*
|
|
3550
|
-
* @param flow - The current FlowState
|
|
3551
|
-
* @param side - Which side should play next ('side_a' or 'side_b')
|
|
3552
|
-
*
|
|
3553
|
-
* @example
|
|
3554
|
-
* ```typescript
|
|
3555
|
-
* import { forceTurn } from '@standardagents/builder';
|
|
3556
|
-
*
|
|
3557
|
-
* // Force current side to continue (override stop condition)
|
|
3558
|
-
* // If side_a is playing and would stop, this forces it to play at least 1 more turn
|
|
3559
|
-
* forceTurn(flow, 'side_a');
|
|
3560
|
-
*
|
|
3561
|
-
* // Force switch to other side
|
|
3562
|
-
* // If side_a is playing, this forces side_b to play next turn
|
|
3563
|
-
* forceTurn(flow, 'side_b');
|
|
3564
|
-
*
|
|
3565
|
-
* // Forcing a HUMAN-backed side parks execution: the thread stops and waits
|
|
3566
|
-
* // for that side's next inbound message instead of taking a runtime turn.
|
|
3567
|
-
* forceTurn(flow, 'side_b'); // side B human-backed → parks awaiting input
|
|
3568
|
-
* ```
|
|
3569
|
-
*/
|
|
3570
|
-
declare function forceTurn(flow: FlowState, side: 'side_a' | 'side_b'): void;
|
|
3571
|
-
/**
|
|
3572
|
-
* Thread context from defineThreadEndpoint
|
|
3573
|
-
*/
|
|
3574
|
-
interface ThreadContext {
|
|
3575
|
-
instance: {
|
|
3576
|
-
updateThreadMeta: (threadId: string, params: {
|
|
3577
|
-
agent_name?: string;
|
|
3578
|
-
user_id?: string | null;
|
|
3579
|
-
tags?: string[] | null;
|
|
3580
|
-
}) => Promise<{
|
|
3581
|
-
success: boolean;
|
|
3582
|
-
error?: string;
|
|
3583
|
-
thread?: {
|
|
3584
|
-
id: string;
|
|
3585
|
-
agent_id: string;
|
|
3586
|
-
user_id: string | null;
|
|
3587
|
-
tags: string[];
|
|
3588
|
-
created_at: number;
|
|
3589
|
-
};
|
|
3590
|
-
}>;
|
|
3591
|
-
};
|
|
3592
|
-
metadata: {
|
|
3593
|
-
id: string;
|
|
3594
|
-
agent_name: string;
|
|
3595
|
-
user_id: string | null;
|
|
3596
|
-
tags: string[] | null;
|
|
3597
|
-
created_at: number;
|
|
3598
|
-
};
|
|
3599
|
-
}
|
|
3600
|
-
/**
|
|
3601
|
-
* Update a thread's metadata in the DurableAgentBuilder registry
|
|
3602
|
-
*
|
|
3603
|
-
* This allows updating the agent_name, user_id, and tags for an existing thread.
|
|
3604
|
-
* Uses the thread instance from defineThreadEndpoint context.
|
|
3605
|
-
*
|
|
3606
|
-
* @param thread - The thread context from defineThreadEndpoint ({ instance, metadata })
|
|
3607
|
-
* @param params - The fields to update (agent_name, user_id, tags)
|
|
3608
|
-
* @returns The updated thread info, or null if update failed
|
|
3609
|
-
*
|
|
3610
|
-
* @example
|
|
3611
|
-
* ```typescript
|
|
3612
|
-
* import { defineThreadEndpoint, updateThread } from '@standardagents/builder';
|
|
3613
|
-
*
|
|
3614
|
-
* export default defineThreadEndpoint(async (req, thread) => {
|
|
3615
|
-
* // Update thread's user_id
|
|
3616
|
-
* await updateThread(thread, { user_id: 'user-123' });
|
|
3617
|
-
*
|
|
3618
|
-
* // Update thread's tags
|
|
3619
|
-
* await updateThread(thread, { tags: ['support', 'urgent'] });
|
|
3620
|
-
*
|
|
3621
|
-
* // Update multiple fields
|
|
3622
|
-
* const result = await updateThread(thread, {
|
|
3623
|
-
* agent_name: 'new-agent',
|
|
3624
|
-
* user_id: 'user-456',
|
|
3625
|
-
* tags: ['sales']
|
|
3626
|
-
* });
|
|
3627
|
-
*
|
|
3628
|
-
* return Response.json(result);
|
|
3629
|
-
* });
|
|
3630
|
-
* ```
|
|
3631
|
-
*/
|
|
3632
|
-
declare function updateThread(thread: ThreadContext, params: {
|
|
3633
|
-
agent_name?: string;
|
|
3634
|
-
user_id?: string | null;
|
|
3635
|
-
tags?: string[] | null;
|
|
3636
|
-
}): Promise<{
|
|
3637
|
-
id: string;
|
|
3638
|
-
agent_id: string;
|
|
3639
|
-
user_id: string | null;
|
|
3640
|
-
tags: string[];
|
|
3641
|
-
created_at: number;
|
|
3642
|
-
} | null>;
|
|
3643
|
-
/**
|
|
3644
|
-
* Write a file to thread storage
|
|
3645
|
-
*
|
|
3646
|
-
* @param flow - The current FlowState
|
|
3647
|
-
* @param path - File path (e.g., "/images/photo.jpg")
|
|
3648
|
-
* @param data - File data as ArrayBuffer or string
|
|
3649
|
-
* @param mimeType - MIME type of the file
|
|
3650
|
-
* @param options - Optional metadata and thumbnail
|
|
3651
|
-
* @returns The created file record
|
|
3652
|
-
*
|
|
3653
|
-
* @example
|
|
3654
|
-
* ```typescript
|
|
3655
|
-
* import { writeFile } from '@standardagents/builder';
|
|
3656
|
-
*
|
|
3657
|
-
* // Write binary file
|
|
3658
|
-
* const imageData = new Uint8Array([...]);
|
|
3659
|
-
* await writeFile(flow, "/images/photo.jpg", imageData.buffer, "image/jpeg");
|
|
3660
|
-
*
|
|
3661
|
-
* // Write text file
|
|
3662
|
-
* await writeFile(flow, "/docs/readme.md", "# Hello", "text/markdown");
|
|
3663
|
-
* ```
|
|
3664
|
-
*/
|
|
3665
|
-
declare function writeFile(flow: FlowState, path: string, data: ArrayBuffer | string, mimeType: string, options?: {
|
|
3666
|
-
metadata?: Record<string, unknown>;
|
|
3667
|
-
thumbnail?: ArrayBuffer;
|
|
3668
|
-
}): Promise<FileRecord>;
|
|
3669
|
-
/**
|
|
3670
|
-
* Write an image file with optional thumbnail
|
|
3671
|
-
*
|
|
3672
|
-
* @param flow - The current FlowState
|
|
3673
|
-
* @param path - File path
|
|
3674
|
-
* @param data - Image data as ArrayBuffer
|
|
3675
|
-
* @param mimeType - Image MIME type
|
|
3676
|
-
* @param options - Image metadata (width, height) and optional thumbnail
|
|
3677
|
-
* @returns The created file record
|
|
3678
|
-
*
|
|
3679
|
-
* @example
|
|
3680
|
-
* ```typescript
|
|
3681
|
-
* import { writeImage } from '@standardagents/builder';
|
|
3682
|
-
*
|
|
3683
|
-
* await writeImage(flow, "/images/photo.jpg", imageBuffer, "image/jpeg", {
|
|
3684
|
-
* metadata: { width: 1024, height: 768 },
|
|
3685
|
-
* thumbnail: thumbnailBuffer
|
|
3686
|
-
* });
|
|
3687
|
-
* ```
|
|
3688
|
-
*/
|
|
3689
|
-
declare function writeImage(flow: FlowState, path: string, data: ArrayBuffer, mimeType: string, options?: {
|
|
3690
|
-
metadata?: {
|
|
3691
|
-
width: number;
|
|
3692
|
-
height: number;
|
|
3693
|
-
[key: string]: unknown;
|
|
3694
|
-
};
|
|
3695
|
-
thumbnail?: ArrayBuffer;
|
|
3696
|
-
}): Promise<FileRecord>;
|
|
3697
|
-
/**
|
|
3698
|
-
* Link to an external file (URL, S3, R2)
|
|
3699
|
-
*
|
|
3700
|
-
* Creates a file entry pointing to an external location without storing the data locally.
|
|
3701
|
-
*
|
|
3702
|
-
* @param flow - The current FlowState
|
|
3703
|
-
* @param path - File path in thread storage
|
|
3704
|
-
* @param location - External location (https://, s3://, r2://)
|
|
3705
|
-
* @param options - Optional MIME type, size, and metadata
|
|
3706
|
-
* @returns The created file record
|
|
3707
|
-
*
|
|
3708
|
-
* @example
|
|
3709
|
-
* ```typescript
|
|
3710
|
-
* import { linkFile } from '@standardagents/builder';
|
|
3711
|
-
*
|
|
3712
|
-
* // Link to a URL
|
|
3713
|
-
* await linkFile(flow, "/images/hero.jpg", "https://cdn.example.com/hero.jpg");
|
|
3714
|
-
*
|
|
3715
|
-
* // Link to S3
|
|
3716
|
-
* await linkFile(flow, "/data/large.csv", "s3://mybucket/data/large.csv", {
|
|
3717
|
-
* mimeType: "text/csv",
|
|
3718
|
-
* size: 10 * 1024 * 1024 * 1024 // 10GB
|
|
3719
|
-
* });
|
|
3720
|
-
* ```
|
|
3721
|
-
*/
|
|
3722
|
-
declare function linkFile(flow: FlowState, path: string, location: string, options?: {
|
|
3723
|
-
mimeType?: string;
|
|
3724
|
-
size?: number;
|
|
3725
|
-
metadata?: Record<string, unknown>;
|
|
3726
|
-
}): Promise<FileRecord>;
|
|
3727
|
-
/**
|
|
3728
|
-
* Read a file from thread storage
|
|
3729
|
-
*
|
|
3730
|
-
* @param flow - The current FlowState
|
|
3731
|
-
* @param path - File path
|
|
3732
|
-
* @returns File data as ArrayBuffer, or null if not found/external
|
|
3733
|
-
*
|
|
3734
|
-
* @example
|
|
3735
|
-
* ```typescript
|
|
3736
|
-
* import { readFile } from '@standardagents/builder';
|
|
3737
|
-
*
|
|
3738
|
-
* const data = await readFile(flow, "/images/photo.jpg");
|
|
3739
|
-
* if (data) {
|
|
3740
|
-
* // Process binary data
|
|
3741
|
-
* }
|
|
3742
|
-
* ```
|
|
3743
|
-
*/
|
|
3744
|
-
declare function readFile(flow: FlowState, path: string): Promise<ArrayBuffer | null>;
|
|
3745
|
-
/**
|
|
3746
|
-
* Get file metadata
|
|
3747
|
-
*
|
|
3748
|
-
* @param flow - The current FlowState
|
|
3749
|
-
* @param path - File path
|
|
3750
|
-
* @returns File record or null if not found
|
|
3751
|
-
*
|
|
3752
|
-
* @example
|
|
3753
|
-
* ```typescript
|
|
3754
|
-
* import { stat } from '@standardagents/builder';
|
|
3755
|
-
*
|
|
3756
|
-
* const file = await stat(flow, "/images/photo.jpg");
|
|
3757
|
-
* if (file) {
|
|
3758
|
-
* console.log(`Size: ${file.size}, Type: ${file.mimeType}`);
|
|
3759
|
-
* }
|
|
3760
|
-
* ```
|
|
3761
|
-
*/
|
|
3762
|
-
declare function stat(flow: FlowState, path: string): Promise<FileRecord | null>;
|
|
3763
|
-
/**
|
|
3764
|
-
* Check if file or directory exists
|
|
3765
|
-
*
|
|
3766
|
-
* @param flow - The current FlowState
|
|
3767
|
-
* @param path - File path
|
|
3768
|
-
* @returns true if exists, false otherwise
|
|
3769
|
-
*
|
|
3770
|
-
* @example
|
|
3771
|
-
* ```typescript
|
|
3772
|
-
* import { exists } from '@standardagents/builder';
|
|
3773
|
-
*
|
|
3774
|
-
* if (await exists(flow, "/config.json")) {
|
|
3775
|
-
* // File exists
|
|
3776
|
-
* }
|
|
3777
|
-
* ```
|
|
3778
|
-
*/
|
|
3779
|
-
declare function exists(flow: FlowState, path: string): Promise<boolean>;
|
|
3780
|
-
/**
|
|
3781
|
-
* Delete a file
|
|
3782
|
-
*
|
|
3783
|
-
* @param flow - The current FlowState
|
|
3784
|
-
* @param path - File path
|
|
3785
|
-
*
|
|
3786
|
-
* @example
|
|
3787
|
-
* ```typescript
|
|
3788
|
-
* import { unlink } from '@standardagents/builder';
|
|
3789
|
-
*
|
|
3790
|
-
* await unlink(flow, "/temp/draft.txt");
|
|
3791
|
-
* ```
|
|
3792
|
-
*/
|
|
3793
|
-
declare function unlink(flow: FlowState, path: string): Promise<void>;
|
|
3794
|
-
/**
|
|
3795
|
-
* Create a directory
|
|
3796
|
-
*
|
|
3797
|
-
* @param flow - The current FlowState
|
|
3798
|
-
* @param path - Directory path
|
|
3799
|
-
* @returns The created directory record
|
|
3800
|
-
*
|
|
3801
|
-
* @example
|
|
3802
|
-
* ```typescript
|
|
3803
|
-
* import { mkdir } from '@standardagents/builder';
|
|
3804
|
-
*
|
|
3805
|
-
* await mkdir(flow, "/uploads/2024");
|
|
3806
|
-
* ```
|
|
3807
|
-
*/
|
|
3808
|
-
declare function mkdir(flow: FlowState, path: string): Promise<FileRecord>;
|
|
3809
|
-
/**
|
|
3810
|
-
* List directory contents
|
|
3811
|
-
*
|
|
3812
|
-
* @param flow - The current FlowState
|
|
3813
|
-
* @param path - Directory path
|
|
3814
|
-
* @returns Array of file records in the directory
|
|
3815
|
-
*
|
|
3816
|
-
* @example
|
|
3817
|
-
* ```typescript
|
|
3818
|
-
* import { readdir } from '@standardagents/builder';
|
|
3819
|
-
*
|
|
3820
|
-
* const files = await readdir(flow, "/images");
|
|
3821
|
-
* for (const file of files) {
|
|
3822
|
-
* console.log(file.name, file.size);
|
|
3823
|
-
* }
|
|
3824
|
-
* ```
|
|
3825
|
-
*/
|
|
3826
|
-
declare function readdir(flow: FlowState, path: string): Promise<FileRecord[]>;
|
|
3827
|
-
/**
|
|
3828
|
-
* Remove an empty directory
|
|
3829
|
-
*
|
|
3830
|
-
* @param flow - The current FlowState
|
|
3831
|
-
* @param path - Directory path
|
|
3832
|
-
*
|
|
3833
|
-
* @example
|
|
3834
|
-
* ```typescript
|
|
3835
|
-
* import { rmdir } from '@standardagents/builder';
|
|
3836
|
-
*
|
|
3837
|
-
* await rmdir(flow, "/temp");
|
|
3838
|
-
* ```
|
|
3839
|
-
*/
|
|
3840
|
-
declare function rmdir(flow: FlowState, path: string): Promise<void>;
|
|
3841
|
-
/**
|
|
3842
|
-
* Move or rename a file or directory to a new path.
|
|
3843
|
-
*
|
|
3844
|
-
* Works for files (inline or chunked) and directories (the whole subtree is
|
|
3845
|
-
* relocated). The destination must not already exist.
|
|
3846
|
-
*
|
|
3847
|
-
* @param flow - The current FlowState
|
|
3848
|
-
* @param sourcePath - Existing file or directory path
|
|
3849
|
-
* @param destinationPath - New path
|
|
3850
|
-
* @returns The moved file record at its new path
|
|
3851
|
-
*
|
|
3852
|
-
* @example
|
|
3853
|
-
* ```typescript
|
|
3854
|
-
* import { move } from '@standardagents/builder';
|
|
3855
|
-
*
|
|
3856
|
-
* await move(flow, "/drafts/post.md", "/published/post.md");
|
|
3857
|
-
* await move(flow, "/tmp/work", "/archive/2024/work");
|
|
3858
|
-
* ```
|
|
3859
|
-
*/
|
|
3860
|
-
declare function move(flow: FlowState, sourcePath: string, destinationPath: string): Promise<FileRecord>;
|
|
3861
|
-
/**
|
|
3862
|
-
* Rename a file or directory in place, keeping it in the same directory.
|
|
3863
|
-
*
|
|
3864
|
-
* @param flow - The current FlowState
|
|
3865
|
-
* @param path - Existing file or directory path
|
|
3866
|
-
* @param newName - New name (must not contain path separators)
|
|
3867
|
-
* @returns The renamed file record at its new path
|
|
3868
|
-
*
|
|
3869
|
-
* @example
|
|
3870
|
-
* ```typescript
|
|
3871
|
-
* import { rename } from '@standardagents/builder';
|
|
3872
|
-
*
|
|
3873
|
-
* await rename(flow, "/notes/draft.txt", "final.txt");
|
|
3874
|
-
* ```
|
|
3875
|
-
*/
|
|
3876
|
-
declare function rename(flow: FlowState, path: string, newName: string): Promise<FileRecord>;
|
|
3877
|
-
/**
|
|
3878
|
-
* Get file storage statistics
|
|
3879
|
-
*
|
|
3880
|
-
* @param flow - The current FlowState
|
|
3881
|
-
* @returns Storage statistics (total size and file count)
|
|
3882
|
-
*
|
|
3883
|
-
* @example
|
|
3884
|
-
* ```typescript
|
|
3885
|
-
* import { getFileStats } from '@standardagents/builder';
|
|
3886
|
-
*
|
|
3887
|
-
* const stats = await getFileStats(flow);
|
|
3888
|
-
* console.log(`Total: ${stats.totalSize} bytes, Files: ${stats.fileCount}`);
|
|
3889
|
-
* ```
|
|
3890
|
-
*/
|
|
3891
|
-
declare function getFileStats(flow: FlowState): Promise<FileStats>;
|
|
3892
|
-
/**
|
|
3893
|
-
* Get thumbnail for an image file
|
|
3894
|
-
*
|
|
3895
|
-
* @param flow - The current FlowState
|
|
3896
|
-
* @param path - Image file path
|
|
3897
|
-
* @returns Thumbnail data as ArrayBuffer, or null if not found
|
|
3898
|
-
*
|
|
3899
|
-
* @example
|
|
3900
|
-
* ```typescript
|
|
3901
|
-
* import { getThumbnail } from '@standardagents/builder';
|
|
3902
|
-
*
|
|
3903
|
-
* const thumb = await getThumbnail(flow, "/images/photo.jpg");
|
|
3904
|
-
* ```
|
|
3905
|
-
*/
|
|
3906
|
-
declare function getThumbnail(flow: FlowState, path: string): Promise<ArrayBuffer | null>;
|
|
3907
|
-
/**
|
|
3908
|
-
* Read a text file as string
|
|
3909
|
-
*
|
|
3910
|
-
* @param flow - The current FlowState
|
|
3911
|
-
* @param path - File path
|
|
3912
|
-
* @returns File content as string, or null if not found
|
|
3913
|
-
*
|
|
3914
|
-
* @example
|
|
3915
|
-
* ```typescript
|
|
3916
|
-
* import { cat } from '@standardagents/builder';
|
|
3917
|
-
*
|
|
3918
|
-
* const content = await cat(flow, "/docs/readme.md");
|
|
3919
|
-
* ```
|
|
3920
|
-
*/
|
|
3921
|
-
declare function cat(flow: FlowState, path: string): Promise<string | null>;
|
|
3922
|
-
/**
|
|
3923
|
-
* Read first N lines of a text file
|
|
3924
|
-
*
|
|
3925
|
-
* @param flow - The current FlowState
|
|
3926
|
-
* @param path - File path
|
|
3927
|
-
* @param lines - Number of lines to read (default: 10)
|
|
3928
|
-
* @returns First N lines as string, or null if not found
|
|
3929
|
-
*
|
|
3930
|
-
* @example
|
|
3931
|
-
* ```typescript
|
|
3932
|
-
* import { head } from '@standardagents/builder';
|
|
3933
|
-
*
|
|
3934
|
-
* const firstLines = await head(flow, "/logs/app.log", 20);
|
|
3935
|
-
* ```
|
|
3936
|
-
*/
|
|
3937
|
-
declare function head(flow: FlowState, path: string, lines?: number): Promise<string | null>;
|
|
3938
|
-
/**
|
|
3939
|
-
* Read last N lines of a text file
|
|
3940
|
-
*
|
|
3941
|
-
* @param flow - The current FlowState
|
|
3942
|
-
* @param path - File path
|
|
3943
|
-
* @param lines - Number of lines to read (default: 10)
|
|
3944
|
-
* @returns Last N lines as string, or null if not found
|
|
3945
|
-
*
|
|
3946
|
-
* @example
|
|
3947
|
-
* ```typescript
|
|
3948
|
-
* import { tail } from '@standardagents/builder';
|
|
3949
|
-
*
|
|
3950
|
-
* const lastLines = await tail(flow, "/logs/app.log", 50);
|
|
3951
|
-
* ```
|
|
3952
|
-
*/
|
|
3953
|
-
declare function tail(flow: FlowState, path: string, lines?: number): Promise<string | null>;
|
|
3954
|
-
/**
|
|
3955
|
-
* Search text file contents using FTS5 full-text search
|
|
3956
|
-
*
|
|
3957
|
-
* @param flow - The current FlowState
|
|
3958
|
-
* @param pattern - Search pattern (FTS5 syntax)
|
|
3959
|
-
* @param options - Search options
|
|
3960
|
-
* @returns Array of matching results with snippets
|
|
3961
|
-
*
|
|
3962
|
-
* @example
|
|
3963
|
-
* ```typescript
|
|
3964
|
-
* import { grep } from '@standardagents/builder';
|
|
3965
|
-
*
|
|
3966
|
-
* // Search all files
|
|
3967
|
-
* const results = await grep(flow, "error");
|
|
3968
|
-
*
|
|
3969
|
-
* // Search in specific directory
|
|
3970
|
-
* const results = await grep(flow, "TODO", { path: "/src" });
|
|
3971
|
-
* ```
|
|
3972
|
-
*/
|
|
3973
|
-
declare function grep(flow: FlowState, pattern: string, options?: {
|
|
3974
|
-
path?: string;
|
|
3975
|
-
limit?: number;
|
|
3976
|
-
}): Promise<GrepResult[]>;
|
|
3977
|
-
/**
|
|
3978
|
-
* Find files by path pattern
|
|
3979
|
-
*
|
|
3980
|
-
* @param flow - The current FlowState
|
|
3981
|
-
* @param pattern - Glob-like pattern (e.g., "*.md", "/docs/subdir/*.txt")
|
|
3982
|
-
* @param options - Find options
|
|
3983
|
-
* @returns Array of matching file records
|
|
3984
|
-
*
|
|
3985
|
-
* @example
|
|
3986
|
-
* ```typescript
|
|
3987
|
-
* import { find } from '@standardagents/builder';
|
|
3988
|
-
*
|
|
3989
|
-
* // Find all markdown files
|
|
3990
|
-
* const mdFiles = await find(flow, "*.md");
|
|
3991
|
-
*
|
|
3992
|
-
* // Find all files in docs
|
|
3993
|
-
* const docFiles = await find(flow, "/docs/*", { type: "file" });
|
|
3994
|
-
* ```
|
|
3995
|
-
*/
|
|
3996
|
-
declare function find(flow: FlowState, pattern: string, options?: {
|
|
3997
|
-
type?: "file" | "directory" | "all";
|
|
3998
|
-
limit?: number;
|
|
3999
|
-
}): Promise<FileRecord[]>;
|
|
4000
|
-
|
|
4001
|
-
/**
|
|
4002
|
-
* Options for broadcasting custom data
|
|
4003
|
-
*/
|
|
4004
|
-
interface BroadcastOptions {
|
|
4005
|
-
/** The type of the broadcast message */
|
|
4006
|
-
type: string;
|
|
4007
|
-
/** The value/payload of the broadcast message */
|
|
4008
|
-
value: unknown;
|
|
4009
|
-
}
|
|
4010
|
-
/**
|
|
4011
|
-
* FlowState SDK - Utility methods for working with FlowState
|
|
4012
|
-
*
|
|
4013
|
-
* These methods extend the FlowState object with helpful utilities for:
|
|
4014
|
-
* - Queuing tool calls
|
|
4015
|
-
* - Injecting messages
|
|
4016
|
-
* - Retrieving message history
|
|
4017
|
-
* - Broadcasting custom data via WebSocket
|
|
4018
|
-
*/
|
|
4019
|
-
declare class FlowStateSdk {
|
|
4020
|
-
/**
|
|
4021
|
-
* Queue a new tool call to be executed in the current flow
|
|
4022
|
-
*
|
|
4023
|
-
* This adds a tool call to the execution queue without immediately executing it.
|
|
4024
|
-
* The tool will be executed as part of the normal flow processing.
|
|
4025
|
-
*
|
|
4026
|
-
* @param flow - The current FlowState
|
|
4027
|
-
* @param toolName - The name of the tool to call (autocompletes from available tools)
|
|
4028
|
-
* @param args - The arguments to pass to the tool
|
|
4029
|
-
*
|
|
4030
|
-
* @example
|
|
4031
|
-
* ```typescript
|
|
4032
|
-
* FlowStateSdk.queueTool(flow, "search_user", { email: "user@example.com" });
|
|
4033
|
-
* ```
|
|
4034
|
-
*/
|
|
4035
|
-
static queueTool(flow: FlowState, toolName: StandardAgentSpec.Callables, args?: Record<string, unknown>): void;
|
|
4036
|
-
/**
|
|
4037
|
-
* Inject a message into the thread without triggering execution
|
|
4038
|
-
*
|
|
4039
|
-
* This allows you to add messages to the conversation history programmatically.
|
|
4040
|
-
* The message is persisted to storage but does not cause the agent to execute.
|
|
4041
|
-
*
|
|
4042
|
-
* By default, messages are appended to the end of the conversation.
|
|
4043
|
-
* You can optionally insert a message before another message by providing beforeMessageId.
|
|
4044
|
-
*
|
|
4045
|
-
* @param flow - The current FlowState
|
|
4046
|
-
* @param options - Message options
|
|
4047
|
-
*
|
|
4048
|
-
* @example
|
|
4049
|
-
* ```typescript
|
|
4050
|
-
* // Append a system message
|
|
4051
|
-
* await FlowStateSdk.injectMessage(flow, {
|
|
4052
|
-
* role: "system",
|
|
4053
|
-
* content: "Context has been updated"
|
|
4054
|
-
* });
|
|
4055
|
-
*
|
|
4056
|
-
* // Insert a user message before a specific message
|
|
4057
|
-
* await FlowStateSdk.injectMessage(flow, {
|
|
4058
|
-
* role: "user",
|
|
4059
|
-
* content: "Additional context",
|
|
4060
|
-
* beforeMessageId: "msg-123"
|
|
4061
|
-
* });
|
|
4062
|
-
*
|
|
4063
|
-
* // Inject a message and force a specific side to play next
|
|
4064
|
-
* await FlowStateSdk.injectMessage(flow, {
|
|
4065
|
-
* role: "system",
|
|
4066
|
-
* content: "New instructions for the AI",
|
|
4067
|
-
* forceTurn: "side_a" // Force side_a to respond to this message
|
|
4068
|
-
* });
|
|
4069
|
-
* ```
|
|
4070
|
-
*/
|
|
4071
|
-
static injectMessage(flow: FlowState, options: InjectMessageOptions): Promise<Message>;
|
|
4072
|
-
/**
|
|
4073
|
-
* Get messages from the thread history
|
|
4074
|
-
*
|
|
4075
|
-
* Retrieves message history from the thread's SQLite storage.
|
|
4076
|
-
* Messages are ordered by creation time (oldest first by default).
|
|
4077
|
-
*
|
|
4078
|
-
* @param flow - The current FlowState
|
|
4079
|
-
* @param limit - Maximum number of messages to retrieve (default: 100)
|
|
4080
|
-
* @param offset - Number of messages to skip (default: 0)
|
|
4081
|
-
* @param order - Sort order: "asc" (oldest first) or "desc" (newest first) (default: "asc")
|
|
4082
|
-
* @returns Array of messages
|
|
4083
|
-
*
|
|
4084
|
-
* @example
|
|
4085
|
-
* ```typescript
|
|
4086
|
-
* // Get last 10 messages
|
|
4087
|
-
* const messages = await FlowStateSdk.getMessages(flow, 10);
|
|
4088
|
-
*
|
|
4089
|
-
* // Get 10 messages, skipping the first 20
|
|
4090
|
-
* const messages = await FlowStateSdk.getMessages(flow, 10, 20);
|
|
4091
|
-
*
|
|
4092
|
-
* // Get newest 10 messages
|
|
4093
|
-
* const messages = await FlowStateSdk.getMessages(flow, 10, 0, "desc");
|
|
4094
|
-
* ```
|
|
4095
|
-
*/
|
|
4096
|
-
static getMessages(flow: FlowState, limit?: number, offset?: number, order?: "asc" | "desc"): Promise<Message[]>;
|
|
4097
|
-
/**
|
|
4098
|
-
* Reload message history from storage
|
|
4099
|
-
*
|
|
4100
|
-
* Re-loads the complete message history from the thread's SQLite storage.
|
|
4101
|
-
* This is useful when you need to refresh the message history after making
|
|
4102
|
-
* changes (e.g., injecting messages).
|
|
4103
|
-
*
|
|
4104
|
-
* @param flow - The current FlowState
|
|
4105
|
-
* @returns Array of messages (reloaded from storage)
|
|
4106
|
-
*
|
|
4107
|
-
* @example
|
|
4108
|
-
* ```typescript
|
|
4109
|
-
* // Reload history after injecting a silent message
|
|
4110
|
-
* await FlowStateSdk.injectMessage(flow, { role: "system", content: "...", silent: true });
|
|
4111
|
-
* flow.messageHistory = await FlowStateSdk.reloadHistory(flow);
|
|
4112
|
-
* ```
|
|
4113
|
-
*/
|
|
4114
|
-
static reloadHistory(state: FlowState): Promise<Message[]>;
|
|
4115
|
-
/**
|
|
4116
|
-
* Broadcast custom data to WebSocket clients
|
|
4117
|
-
*
|
|
4118
|
-
* Sends a custom message to all connected WebSocket clients.
|
|
4119
|
-
* This allows backend code to push arbitrary data to the frontend
|
|
4120
|
-
* outside of the standard telemetry events.
|
|
4121
|
-
*
|
|
4122
|
-
* The message is sent with the structure: { type: string, value: unknown }
|
|
4123
|
-
*
|
|
4124
|
-
* @param flow - The current FlowState
|
|
4125
|
-
* @param options - Broadcast options
|
|
4126
|
-
*
|
|
4127
|
-
* @example
|
|
4128
|
-
* ```typescript
|
|
4129
|
-
* // Broadcast a progress update
|
|
4130
|
-
* FlowStateSdk.broadcast(flow, {
|
|
4131
|
-
* type: "progress",
|
|
4132
|
-
* value: { step: 3, total: 10, message: "Processing data..." }
|
|
4133
|
-
* });
|
|
4134
|
-
*
|
|
4135
|
-
* // Broadcast a custom notification
|
|
4136
|
-
* FlowStateSdk.broadcast(flow, {
|
|
4137
|
-
* type: "notification",
|
|
4138
|
-
* value: { level: "info", message: "User authenticated successfully" }
|
|
4139
|
-
* });
|
|
4140
|
-
*
|
|
4141
|
-
* // Broadcast metadata
|
|
4142
|
-
* FlowStateSdk.broadcast(flow, {
|
|
4143
|
-
* type: "metadata",
|
|
4144
|
-
* value: { userId: "123", sessionId: "abc", timestamp: Date.now() }
|
|
4145
|
-
* });
|
|
4146
|
-
* ```
|
|
4147
|
-
*/
|
|
4148
|
-
static broadcast(flow: FlowState, options: BroadcastOptions): void;
|
|
4149
|
-
/**
|
|
4150
|
-
* Force a specific side to play the next turn
|
|
4151
|
-
*
|
|
4152
|
-
* This queues the specified side to play next without interrupting the current turn.
|
|
4153
|
-
* The forced turn only takes effect at the END of the current turn execution.
|
|
4154
|
-
*
|
|
4155
|
-
* If the tool queue is currently being processed (sequence.isHandling is true),
|
|
4156
|
-
* the forced turn is deferred until all queued tools complete. This allows patterns like:
|
|
4157
|
-
*
|
|
4158
|
-
* ```typescript
|
|
4159
|
-
* FlowStateSdk.queueTool(flow, 'myTool', {});
|
|
4160
|
-
* FlowStateSdk.forceTurn(flow, 'side_a');
|
|
4161
|
-
* // myTool executes first, THEN the turn switches to side_a
|
|
4162
|
-
* ```
|
|
4163
|
-
*
|
|
4164
|
-
* @param flow - The current FlowState
|
|
4165
|
-
* @param side - Which side should play next ('side_a' or 'side_b')
|
|
4166
|
-
*
|
|
4167
|
-
* @example
|
|
4168
|
-
* ```typescript
|
|
4169
|
-
* // Force current side to continue (override stop condition)
|
|
4170
|
-
* // If side_a is playing and would stop, this forces it to play at least 1 more turn
|
|
4171
|
-
* FlowStateSdk.forceTurn(flow, 'side_a');
|
|
4172
|
-
*
|
|
4173
|
-
* // Force switch to other side
|
|
4174
|
-
* // If side_a is playing, this forces side_b to play next turn
|
|
4175
|
-
* FlowStateSdk.forceTurn(flow, 'side_b');
|
|
4176
|
-
*
|
|
4177
|
-
* // Forcing a HUMAN-backed side parks execution: the thread stops and
|
|
4178
|
-
* // waits for that side's next inbound message instead of taking a turn.
|
|
4179
|
-
* FlowStateSdk.forceTurn(flow, 'side_b'); // side B human-backed → parks
|
|
4180
|
-
* ```
|
|
4181
|
-
*/
|
|
4182
|
-
static forceTurn(flow: FlowState, side: 'side_a' | 'side_b'): void;
|
|
4183
|
-
}
|
|
4184
|
-
/**
|
|
4185
|
-
* Convenience methods added to FlowState (optional - can be used via static methods above)
|
|
4186
|
-
*
|
|
4187
|
-
* These are helper methods that can be added to FlowState instances for convenience.
|
|
4188
|
-
* They delegate to the static methods above.
|
|
4189
|
-
*/
|
|
4190
|
-
interface FlowStateWithSdk extends FlowState {
|
|
4191
|
-
queueTool: (toolName: StandardAgentSpec.Callables, args?: Record<string, unknown>) => void;
|
|
4192
|
-
injectMessage: (options: InjectMessageOptions) => Promise<Message>;
|
|
4193
|
-
getMessages: (limit?: number, offset?: number, order?: "asc" | "desc") => Promise<Message[]>;
|
|
4194
|
-
reloadHistory: () => Promise<Message[]>;
|
|
4195
|
-
broadcast: (options: BroadcastOptions) => void;
|
|
4196
|
-
forceTurn: (side: 'side_a' | 'side_b') => void;
|
|
4197
|
-
}
|
|
4198
|
-
/**
|
|
4199
|
-
* Enhance a FlowState object with SDK methods
|
|
4200
|
-
*
|
|
4201
|
-
* This adds convenience methods to a FlowState instance that delegate to
|
|
4202
|
-
* the static FlowStateSdk methods.
|
|
4203
|
-
*
|
|
4204
|
-
* @param flow - The FlowState to enhance
|
|
4205
|
-
* @returns The enhanced FlowState with SDK methods
|
|
4206
|
-
*
|
|
4207
|
-
* @example
|
|
4208
|
-
* ```typescript
|
|
4209
|
-
* const enhancedFlow = enhanceFlowState(flow);
|
|
4210
|
-
*
|
|
4211
|
-
* // Now you can use methods directly on the flow object
|
|
4212
|
-
* enhancedFlow.queueTool("search_user", { email: "user@example.com" });
|
|
4213
|
-
* await enhancedFlow.injectMessage({ role: "system", content: "Context updated" });
|
|
4214
|
-
* const messages = await enhancedFlow.getMessages(10);
|
|
4215
|
-
* flow.messageHistory = await enhancedFlow.reloadHistory();
|
|
4216
|
-
* enhancedFlow.broadcast({ type: "progress", value: { step: 1 } });
|
|
4217
|
-
* enhancedFlow.forceTurn('side_b'); // Force side_b to play next turn
|
|
4218
|
-
* ```
|
|
4219
|
-
*/
|
|
4220
|
-
declare function enhanceFlowState(flow: FlowState): FlowStateWithSdk;
|
|
4221
|
-
|
|
4222
|
-
/**
|
|
4223
|
-
* Context Management for Image Attachments
|
|
4224
|
-
*
|
|
4225
|
-
* Handles auto-summarization of old images to reduce context window usage
|
|
4226
|
-
* while preserving the semantic meaning of image content.
|
|
4227
|
-
*/
|
|
4228
|
-
|
|
4229
|
-
/**
|
|
4230
|
-
* Configuration for image context management
|
|
4231
|
-
*/
|
|
4232
|
-
interface ImageContextConfig {
|
|
4233
|
-
/** Number of recent messages to keep images for (default: 10) */
|
|
4234
|
-
recentMessageThreshold: number;
|
|
4235
|
-
/** System prompt for generating image descriptions */
|
|
4236
|
-
descriptionPrompt: string;
|
|
4237
|
-
}
|
|
4238
|
-
/**
|
|
4239
|
-
* Check if a message has image attachments that could be summarized
|
|
4240
|
-
*/
|
|
4241
|
-
declare function hasImageAttachments(message: Message): boolean;
|
|
4242
|
-
/**
|
|
4243
|
-
* Get image attachments from a message that don't have descriptions yet
|
|
4244
|
-
*/
|
|
4245
|
-
declare function getUnsummarizedImageAttachments(message: Message): AttachmentRef[];
|
|
4246
|
-
/**
|
|
4247
|
-
* Determine which messages should have their images replaced with descriptions.
|
|
4248
|
-
* Returns indices of messages that are old enough to be summarized.
|
|
4249
|
-
*/
|
|
4250
|
-
declare function getMessagesToSummarize(messages: Message[], config?: ImageContextConfig): number[];
|
|
4251
|
-
/**
|
|
4252
|
-
* Build text representation for an image attachment (used when image is too old)
|
|
4253
|
-
*/
|
|
4254
|
-
declare function buildImageDescription(attachment: AttachmentRef): string;
|
|
4255
|
-
/**
|
|
4256
|
-
* Transform message content to replace old images with text descriptions.
|
|
4257
|
-
* This modifies the content array for LLM context building.
|
|
4258
|
-
*/
|
|
4259
|
-
declare function replaceImagesWithDescriptions(content: MessageContent, attachments: AttachmentRef[]): MessageContent;
|
|
4260
|
-
/**
|
|
4261
|
-
* Process message history to optimize context window usage.
|
|
4262
|
-
* Old images are replaced with their text descriptions.
|
|
4263
|
-
*
|
|
4264
|
-
* @param messages - Full message history
|
|
4265
|
-
* @param config - Context management configuration
|
|
4266
|
-
* @returns Processed messages with old images replaced by descriptions
|
|
4267
|
-
*/
|
|
4268
|
-
declare function optimizeImageContext(messages: Message[], config?: ImageContextConfig): Message[];
|
|
4269
|
-
/**
|
|
4270
|
-
* Generate a description for an image using a vision model.
|
|
4271
|
-
* This should be called when storing new messages with images.
|
|
4272
|
-
*
|
|
4273
|
-
* Note: This function is a placeholder for the actual LLM call.
|
|
4274
|
-
* The actual implementation would need to make an API call to a vision model.
|
|
4275
|
-
*
|
|
4276
|
-
* @param imageBase64 - Base64-encoded image data
|
|
4277
|
-
* @param mimeType - MIME type of the image
|
|
4278
|
-
* @param state - Flow state for LLM access
|
|
4279
|
-
* @returns Generated description
|
|
4280
|
-
*/
|
|
4281
|
-
declare function generateImageDescription(_imageBase64: string, _mimeType: string, _state: FlowState): Promise<string | null>;
|
|
4282
|
-
|
|
4283
|
-
/** @public Alias for LLMProviderInterface */
|
|
4284
|
-
type Provider = LLMProviderInterface;
|
|
4285
|
-
/** @public Alias for ContentPart */
|
|
4286
|
-
type ProviderContentPart = ContentPart;
|
|
4287
|
-
/** @public Alias for TextPart */
|
|
4288
|
-
type ProviderTextPart = TextPart;
|
|
4289
|
-
/** @public Alias for ImagePart */
|
|
4290
|
-
type ProviderImagePart = ImagePart;
|
|
4291
|
-
/** @public Alias for FilePart */
|
|
4292
|
-
type ProviderFilePart = FilePart;
|
|
4293
|
-
|
|
4294
|
-
/**
|
|
4295
|
-
* Function that can intercept provider creation.
|
|
4296
|
-
* Returns a provider to override the default, or null to fall through.
|
|
4297
|
-
*/
|
|
4298
|
-
type ProviderOverrideFn = (modelName: string, modelDef: ModelDefinition$1<string>, env: Env) => LLMProviderInterface | null;
|
|
4299
|
-
interface ProviderLookupResult {
|
|
4300
|
-
provider: LLMProviderInterface;
|
|
4301
|
-
modelName: string;
|
|
4302
|
-
modelDef: ModelDefinition$1<string>;
|
|
4303
|
-
/** True when requests route through the Standard Agents platform (hosted routing or a registered override). */
|
|
4304
|
-
viaPlatform: boolean;
|
|
4305
|
-
/**
|
|
4306
|
-
* Platform origin serving the passthrough proxy when built-in hosted routing
|
|
4307
|
-
* is active. Lets request logging look up the router-fee percent observed on
|
|
4308
|
-
* this origin's proxied responses.
|
|
4309
|
-
*/
|
|
4310
|
-
platformProxyOrigin?: string;
|
|
4311
|
-
}
|
|
4312
|
-
/**
|
|
4313
|
-
* Provider registry implementation
|
|
4314
|
-
*
|
|
4315
|
-
* Models must use ProviderFactory functions imported from provider packages
|
|
4316
|
-
* (e.g., @standardagents/openai, @standardagents/openrouter).
|
|
4317
|
-
*
|
|
4318
|
-
* Loads model configs from TypeScript virtual modules and
|
|
4319
|
-
* provider API keys from environment variables.
|
|
4320
|
-
*/
|
|
4321
|
-
declare class ProviderRegistryImpl {
|
|
4322
|
-
private providerCache;
|
|
4323
|
-
/** Why the last thread-scoped resolution did (not) contribute user env,
|
|
4324
|
-
* keyed by the env object handed back — surfaced in missing-variable
|
|
4325
|
-
* errors so a silent user-env failure is diagnosable from the log. */
|
|
4326
|
-
private scopeDiagnostics;
|
|
4327
|
-
private providerOverrideFn;
|
|
4328
|
-
private providerOverrideRevision;
|
|
4329
|
-
setProviderOverride(fn: ProviderOverrideFn | null): void;
|
|
4330
|
-
/**
|
|
4331
|
-
* The env a provider resolves against for a given execution, scoped to the
|
|
4332
|
-
* THREAD rather than just the instance: thread env overrides win, then the
|
|
4333
|
-
* thread OWNER's user env, then instance/Worker env. This is what makes
|
|
4334
|
-
* per-user BYOK providers work — a credential a user installs in their own
|
|
4335
|
-
* account env (e.g. an OAuth token a companion service rotates) is honored
|
|
4336
|
-
* for that user's threads no matter which authorized actor plays the turn.
|
|
4337
|
-
*
|
|
4338
|
-
* Best-effort by design: a missing user id (super-admin/local threads) or
|
|
4339
|
-
* an older AgentBuilder DO without user-env storage simply contributes
|
|
4340
|
-
* nothing, leaving instance-env behavior untouched.
|
|
4341
|
-
*/
|
|
4342
|
-
buildThreadScopedEnv(state: {
|
|
4343
|
-
env: Env;
|
|
4344
|
-
thread: {
|
|
4345
|
-
metadata?: {
|
|
4346
|
-
user_id?: string | null;
|
|
4347
|
-
parent?: string | null;
|
|
4348
|
-
env?: Record<string, unknown> | null;
|
|
4349
|
-
tenvs?: Record<string, unknown> | null;
|
|
4350
|
-
};
|
|
4351
|
-
};
|
|
4352
|
-
}): Promise<Env>;
|
|
4353
|
-
/**
|
|
4354
|
-
* Get provider for a model.
|
|
4355
|
-
*
|
|
4356
|
-
* Models must use ProviderFactory functions (imported from provider packages).
|
|
4357
|
-
*
|
|
4358
|
-
* @param modelName - The model name (from TypeScript config)
|
|
4359
|
-
* @param env - Environment bindings
|
|
4360
|
-
* @param thread - Thread instance for loading model from virtual modules
|
|
4361
|
-
* @returns Provider and model definition
|
|
4362
|
-
*/
|
|
4363
|
-
getProvider(modelName: string, env: Env, thread?: ThreadInstance, getState?: () => Promise<ThreadState>): Promise<ProviderLookupResult>;
|
|
4364
|
-
private buildResult;
|
|
4365
|
-
private cacheAndReturn;
|
|
4366
|
-
private getProviderFingerprint;
|
|
4367
|
-
/**
|
|
4368
|
-
* Get API key for a provider from environment variables.
|
|
4369
|
-
*/
|
|
4370
|
-
private getApiKeyForProvider;
|
|
4371
|
-
/**
|
|
4372
|
-
* Clear the provider cache
|
|
4373
|
-
* Useful for testing or when configurations change
|
|
4374
|
-
*/
|
|
4375
|
-
clearCache(): void;
|
|
4376
|
-
}
|
|
4377
|
-
/**
|
|
4378
|
-
* Singleton instance
|
|
4379
|
-
*/
|
|
4380
|
-
declare const ProviderRegistry: ProviderRegistryImpl;
|
|
4381
|
-
|
|
4382
|
-
/**
|
|
4383
|
-
* Namespace-scoped resolution for the packing system.
|
|
4384
|
-
*
|
|
4385
|
-
* This module provides functions to resolve items (tools, prompts, models, agents)
|
|
4386
|
-
* within the correct namespace context, enforcing isolation between packed and
|
|
4387
|
-
* unpacked code.
|
|
4388
|
-
*
|
|
4389
|
-
* @module
|
|
4390
|
-
*/
|
|
4391
|
-
|
|
4392
|
-
/**
|
|
4393
|
-
* Error thrown when an item cannot be resolved in the current namespace.
|
|
4394
|
-
*/
|
|
4395
|
-
declare class NamespaceResolutionError extends Error {
|
|
4396
|
-
readonly itemType: 'tool' | 'prompt' | 'model' | 'agent' | 'hook';
|
|
4397
|
-
readonly itemName: string;
|
|
4398
|
-
readonly namespace: NamespaceContext;
|
|
4399
|
-
constructor(itemType: 'tool' | 'prompt' | 'model' | 'agent' | 'hook', itemName: string, namespace: NamespaceContext, message: string);
|
|
4400
|
-
}
|
|
4401
|
-
/**
|
|
4402
|
-
* Parse a potentially qualified name into package ID and short name.
|
|
4403
|
-
*
|
|
4404
|
-
* For scoped npm packages (starting with @), the format is @scope/pkg-name/item-name
|
|
4405
|
-
* where @scope/pkg-name is the package and item-name is the short name.
|
|
4406
|
-
*
|
|
4407
|
-
* For non-scoped packages, the format is pkg-name/item-name.
|
|
4408
|
-
*
|
|
4409
|
-
* @param name - The name to parse (e.g., 'tool', 'pkg/tool', or '@scope/pkg/tool')
|
|
4410
|
-
* @returns Tuple of [packageId, shortName] where packageId is null for unqualified names
|
|
4411
|
-
*/
|
|
4412
|
-
declare function parseQualifiedName(name: string): [string | null, string];
|
|
4413
|
-
/**
|
|
4414
|
-
* Create a qualified name from package ID and short name.
|
|
4415
|
-
*/
|
|
4416
|
-
declare function qualifyName(packageId: string, shortName: string): string;
|
|
4417
|
-
/**
|
|
4418
|
-
* Get the short name (strip any package qualification).
|
|
4419
|
-
*/
|
|
4420
|
-
declare function getShortName(name: string): string;
|
|
4421
|
-
/**
|
|
4422
|
-
* Resolve a tool by name within a namespace context.
|
|
4423
|
-
*
|
|
4424
|
-
* Resolution rules:
|
|
4425
|
-
* - Qualified names (pkg:tool) → resolve cross-package entry point
|
|
4426
|
-
* - Unqualified names in packed context → resolve from own package
|
|
4427
|
-
* - Unqualified names in global context → resolve from global namespace
|
|
4428
|
-
*
|
|
4429
|
-
* @param registry - The namespaced registry
|
|
4430
|
-
* @param name - Tool name (can be qualified with packageId:toolName)
|
|
4431
|
-
* @param namespace - Current namespace context
|
|
4432
|
-
* @returns Loader function for the tool definition
|
|
4433
|
-
* @throws NamespaceResolutionError if tool cannot be found or accessed
|
|
4434
|
-
*/
|
|
4435
|
-
declare function resolveTool(registry: NamespacedRegistry, name: string, namespace: NamespaceContext): DefinitionLoader<unknown>;
|
|
4436
|
-
/**
|
|
4437
|
-
* Resolve a prompt by name within a namespace context.
|
|
4438
|
-
*
|
|
4439
|
-
* @param registry - The namespaced registry
|
|
4440
|
-
* @param name - Prompt name (can be qualified)
|
|
4441
|
-
* @param namespace - Current namespace context
|
|
4442
|
-
* @returns Loader function for the prompt definition
|
|
4443
|
-
*/
|
|
4444
|
-
declare function resolvePrompt(registry: NamespacedRegistry, name: string, namespace: NamespaceContext): DefinitionLoader<unknown>;
|
|
4445
|
-
/**
|
|
4446
|
-
* Resolve a model by name within a namespace context.
|
|
4447
|
-
*
|
|
4448
|
-
* Models are special: packed agents include their model definitions,
|
|
4449
|
-
* but the host must provide API keys.
|
|
4450
|
-
*
|
|
4451
|
-
* @param registry - The namespaced registry
|
|
4452
|
-
* @param name - Model name
|
|
4453
|
-
* @param namespace - Current namespace context
|
|
4454
|
-
* @returns Loader function for the model definition
|
|
4455
|
-
*/
|
|
4456
|
-
declare function resolveModel(registry: NamespacedRegistry, name: string, namespace: NamespaceContext): DefinitionLoader<unknown>;
|
|
4457
|
-
/**
|
|
4458
|
-
* Resolve an agent by name within a namespace context.
|
|
4459
|
-
*
|
|
4460
|
-
* Resolution rules:
|
|
4461
|
-
* - Qualified names (pkg:agent) → resolve cross-package entry point
|
|
4462
|
-
* - Unqualified in packed → resolve from own package
|
|
4463
|
-
* - Unqualified in global → resolve from global + entry points
|
|
4464
|
-
*
|
|
4465
|
-
* @param registry - The namespaced registry
|
|
4466
|
-
* @param name - Agent name (can be qualified)
|
|
4467
|
-
* @param namespace - Current namespace context
|
|
4468
|
-
* @returns Loader function for the agent definition
|
|
4469
|
-
*/
|
|
4470
|
-
declare function resolveAgent(registry: NamespacedRegistry, name: string, namespace: NamespaceContext): DefinitionLoader<unknown>;
|
|
4471
|
-
/**
|
|
4472
|
-
* Resolve a hook by name within a namespace context.
|
|
4473
|
-
*
|
|
4474
|
-
* Hooks follow similar rules to tools but are keyed by hook type.
|
|
4475
|
-
*
|
|
4476
|
-
* @param registry - The namespaced registry
|
|
4477
|
-
* @param name - Hook name (file name, e.g., 'filter_messages')
|
|
4478
|
-
* @param namespace - Current namespace context
|
|
4479
|
-
* @returns Loader function for the hook implementation
|
|
4480
|
-
*/
|
|
4481
|
-
declare function resolveHook(registry: NamespacedRegistry, name: string, namespace: NamespaceContext): DefinitionLoader<unknown> | null;
|
|
4482
|
-
/**
|
|
4483
|
-
* Get all tool names visible in a namespace context.
|
|
4484
|
-
*
|
|
4485
|
-
* @param registry - The namespaced registry
|
|
4486
|
-
* @param namespace - Current namespace context
|
|
4487
|
-
* @returns Array of visible tool names (short names)
|
|
4488
|
-
*/
|
|
4489
|
-
declare function getVisibleToolNames(registry: NamespacedRegistry, namespace: NamespaceContext): string[];
|
|
4490
|
-
/**
|
|
4491
|
-
* Get all agent names visible in a namespace context.
|
|
4492
|
-
*
|
|
4493
|
-
* @param registry - The namespaced registry
|
|
4494
|
-
* @param namespace - Current namespace context
|
|
4495
|
-
* @returns Array of visible agent names (may include qualified names for cross-package)
|
|
4496
|
-
*/
|
|
4497
|
-
declare function getVisibleAgentNames(registry: NamespacedRegistry, namespace: NamespaceContext): string[];
|
|
4498
|
-
/**
|
|
4499
|
-
* Get all prompt names visible in a namespace context.
|
|
4500
|
-
*/
|
|
4501
|
-
declare function getVisiblePromptNames(registry: NamespacedRegistry, namespace: NamespaceContext): string[];
|
|
4502
|
-
/**
|
|
4503
|
-
* Get all model names visible in a namespace context.
|
|
4504
|
-
*/
|
|
4505
|
-
declare function getVisibleModelNames(registry: NamespacedRegistry, namespace: NamespaceContext): string[];
|
|
4506
|
-
/**
|
|
4507
|
-
* Create a namespace context for an agent definition.
|
|
4508
|
-
*
|
|
4509
|
-
* @param agentDef - Agent definition (may have __package field)
|
|
4510
|
-
* @returns Appropriate namespace context
|
|
4511
|
-
*/
|
|
4512
|
-
declare function createNamespaceContext(agentDef: {
|
|
4513
|
-
__package?: {
|
|
4514
|
-
packageId: string;
|
|
4515
|
-
};
|
|
4516
|
-
} | undefined): NamespaceContext;
|
|
4517
|
-
/**
|
|
4518
|
-
* Check if a name is qualified (contains package prefix).
|
|
4519
|
-
*
|
|
4520
|
-
* For scoped packages (@scope/name), there must be at least two slashes
|
|
4521
|
-
* to be considered qualified (e.g., @scope/pkg/item).
|
|
4522
|
-
* For non-scoped packages, a single slash qualifies it (e.g., pkg/item).
|
|
4523
|
-
*/
|
|
4524
|
-
declare function isQualifiedName(name: string): boolean;
|
|
4525
|
-
|
|
4526
|
-
export { Agent, type AgentBuilderEnv, type AgentBuilderEvent, type AgentDefinition, AttachmentRef, AuthContext, type BroadcastOptions, ClientStreamRequest, ClientStreamResponse, ClientToolRequest, ClientToolResponse, CodeExecutionBridge, DurableAgentBuilder, DurableThread, DurableUserHub, Env, FileRecord, FileStats, FlowState, FlowStateSdk, type FlowStateWithSdk, GrepResult, type HandlerSide, type HubClientInfo, type HumanSide, type ImageContextConfig, type InjectMessageOptions, type Provider as LLMProviderInterface, Message, MessageContent, type ModelDefinition, NamespaceResolutionError, NamespacedRegistry, type PromptContent, type PromptDefinition, type PromptIncludePart, type PromptPart, type PromptSide, type PromptToolConfig, type Provider$1 as Provider, type ProviderContentPart, type ProviderFilePart, type ProviderImagePart, ProviderRegistry, type ProviderTextPart, type SessionToolBinding, type SessionToolConfig, type SideConfig, type SubagentRelationship, type SubagentToolConfig, type SubpromptConfig, ThreadEnv, type ThreadEventPayload, ThreadInstance, ThreadMetadata, type ThreadRegistryEntry, ThreadWatchdog, type ThreadWatchdogState, type ToolConfig, ToolResult, type UpdateThreadParams, type User, type WatchdogCheckin, type WatchdogProbeResult, applyRuntimeCors, buildImageDescription, canAccessThread, cat, createNamespaceContext, emitThreadEvent, enhanceFlowState, exists, find, forceTurn, generateImageDescription, getFileStats, getMessages, getMessagesToSummarize, getShortName, getThumbnail, getUnsummarizedImageAttachments, getVisibleAgentNames, getVisibleModelNames, getVisiblePromptNames, getVisibleToolNames, grep, hasImageAttachments, head, injectMessage, isAdminOnlyApiRoute, isHostedInstance, isPublicApiRoute, isQualifiedName, isSameOriginBrowserRequest, isTrustedLocalDevelopmentRequest, linkFile, mkdir, move, optimizeImageContext, parseQualifiedName, qualifyName, queueTool, readFile, readdir, reloadHistory, rename, replaceImagesWithDescriptions, resolveAgent, resolveHook, resolveModel, resolvePrompt, resolveTool, rmdir, runtimeCorsHeaders, runtimePreflightResponse, stat, tail, unlink, updateThread, writeFile, writeImage };
|
|
17
|
+
export { formatUpstreamTiming, withUpstreamTiming };
|