@standardagents/builder 0.40.5 → 0.40.7
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 +46 -76
- package/dist/built-in-routes.js.map +1 -1
- package/dist/client/{ApiKeysView-DoYvZZ7e.js → ApiKeysView-BxzKL9jO.js} +1 -1
- package/dist/client/{CenteredContentView-53PY0cqY.js → CenteredContentView-CV4-cE9D.js} +1 -1
- package/dist/client/{CompositionView-fp-0YnPt.js → CompositionView-DUqt-Wt6.js} +1 -1
- package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-Cvcagja2.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-Byhp8Dqp.js} +1 -1
- package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-jYvO2v1K.js → CopyButton.vue_vue_type_script_setup_true_lang-CRIQcs5M.js} +1 -1
- package/dist/client/{DataTable.vue_vue_type_script_setup_true_lang-DQ3Ufa7y.js → DataTable.vue_vue_type_script_setup_true_lang-CF8Rkus3.js} +1 -1
- package/dist/client/{JsonViewer-6aaGzutE.js → JsonViewer-DTVICtSp.js} +1 -1
- package/dist/client/{LoginView-DwpCmNw9.js → LoginView-ZH47dgDr.js} +1 -1
- package/dist/client/{MarketplaceView-Da02L0J5.js → MarketplaceView-BZjX33dc.js} +1 -1
- package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-Bi8OjiBf.js → Modal.vue_vue_type_script_setup_true_lang-BWSRc4ps.js} +1 -1
- package/dist/client/{ModelModal.vue_vue_type_script_setup_true_lang-cYZLOYY7.js → ModelModal.vue_vue_type_script_setup_true_lang-BHxhT6vM.js} +1 -1
- package/dist/client/{ModelsView-BLlHO9Ud.js → ModelsView-2apBcrqz.js} +1 -1
- package/dist/client/{PromptEditView-EeNwTDtT.js → PromptEditView-Cx086YBJ.js} +1 -1
- package/dist/client/{PromptModal-BkwrKJ2d.js → PromptModal-BMsTD8dU.js} +1 -1
- package/dist/client/{PromptsView-D1r7tsLu.js → PromptsView-l_FfpOuf.js} +1 -1
- package/dist/client/{ProvidersView-CmUDl5nM.js → ProvidersView-PEV9VV4X.js} +1 -1
- package/dist/client/{ThreadInspectorPane.vue_vue_type_script_setup_true_lang-cRs3tApQ.js → ThreadInspectorPane.vue_vue_type_script_setup_true_lang-Cu2SwqZ1.js} +1 -1
- package/dist/client/{ThreadsView-Bl5fSIO1.js → ThreadsView-CPStu4IQ.js} +1 -1
- package/dist/client/{ToolsView-DlVEF8-7.js → ToolsView-spgLDP4C.js} +1 -1
- package/dist/client/{UsersView-CGlA7a7R.js → UsersView-BznU6bH2.js} +1 -1
- package/dist/client/{VariablesView-BpYmJL4V.js → VariablesView-No5zHXK8.js} +1 -1
- package/dist/client/{index-CKtIkI0N.js → index-9HZDcx7i.js} +6 -6
- package/dist/client/index.html +1 -1
- package/dist/{index-0NI3m5DR.d.ts → index-DYhbT5Eq.d.ts} +44 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +256 -154
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +17 -17
- package/dist/runtime.js +256 -154
- package/dist/runtime.js.map +1 -1
- package/dist/test.d.ts +1 -1
- package/package.json +5 -5
package/dist/client/index.html
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
27
27
|
<link rel="icon" type="image/svg+xml" href="/agents/assets/img/favicon-9uH1rb2F.svg">
|
|
28
28
|
<title>AgentBuilder Admin</title>
|
|
29
|
-
<script type="module" crossorigin src="/agents/index-
|
|
29
|
+
<script type="module" crossorigin src="/agents/index-9HZDcx7i.js"></script>
|
|
30
30
|
<link rel="modulepreload" crossorigin href="/agents/formkit-DJxUzqRQ.js">
|
|
31
31
|
<link rel="modulepreload" crossorigin href="/agents/vendor-c_uwtQ-S.js">
|
|
32
32
|
<link rel="modulepreload" crossorigin href="/agents/syntax-D68HCEYm.js">
|
|
@@ -164,6 +164,41 @@ interface ClientDuplex {
|
|
|
164
164
|
error?: string;
|
|
165
165
|
}>;
|
|
166
166
|
}
|
|
167
|
+
/** Builder-internal destination for an event-driven cross-thread stream. */
|
|
168
|
+
interface ProxyStreamTarget {
|
|
169
|
+
/** Thread Durable Object that owns the receiver. */
|
|
170
|
+
threadId: string;
|
|
171
|
+
/** In-memory receiver registered before the ancestor opens the client stream. */
|
|
172
|
+
receiverId: string;
|
|
173
|
+
}
|
|
174
|
+
/** Builder-internal stream event delivered from an ancestor to a child thread. */
|
|
175
|
+
type ProxyStreamFrame = {
|
|
176
|
+
type: "data";
|
|
177
|
+
data: string;
|
|
178
|
+
} | {
|
|
179
|
+
type: "end";
|
|
180
|
+
} | {
|
|
181
|
+
type: "abort";
|
|
182
|
+
error?: string;
|
|
183
|
+
};
|
|
184
|
+
/** Local handle returned when a child thread registers a proxy receiver. */
|
|
185
|
+
interface ProxyStreamReceiver {
|
|
186
|
+
id: string;
|
|
187
|
+
readable: ReadableStream<Uint8Array>;
|
|
188
|
+
done: Promise<{
|
|
189
|
+
ok: boolean;
|
|
190
|
+
error?: string;
|
|
191
|
+
}>;
|
|
192
|
+
}
|
|
193
|
+
/** Result of asking an ancestor to open an event-driven proxy stream. */
|
|
194
|
+
interface ProxyStreamOpenResult {
|
|
195
|
+
ok: boolean;
|
|
196
|
+
id?: string;
|
|
197
|
+
error?: string;
|
|
198
|
+
noClient?: boolean;
|
|
199
|
+
eventDriven?: boolean;
|
|
200
|
+
code?: "unsupported" | "unavailable" | "refused" | "timeout";
|
|
201
|
+
}
|
|
167
202
|
type ClientStreamResponse = {
|
|
168
203
|
ok: true;
|
|
169
204
|
duplex: ClientDuplex;
|
|
@@ -406,6 +441,8 @@ interface ThreadInstance {
|
|
|
406
441
|
side: "a" | "b";
|
|
407
442
|
}): Promise<ClientToolResponse>;
|
|
408
443
|
openClientStream?(request: ClientStreamRequest): Promise<ClientStreamResponse>;
|
|
444
|
+
createProxyStreamReceiver?(onCancel: (error?: string) => void): ProxyStreamReceiver;
|
|
445
|
+
proxyStreamReceive?(receiverId: string, frame: ProxyStreamFrame): Promise<boolean>;
|
|
409
446
|
dispatchClientTool?(request: ClientToolRequest, toolCallId: string, side: "a" | "b"): Promise<{
|
|
410
447
|
dispatched: boolean;
|
|
411
448
|
}>;
|
|
@@ -1363,6 +1400,12 @@ interface DurableThreadRpc {
|
|
|
1363
1400
|
releaseForensicHold?: boolean;
|
|
1364
1401
|
}): Promise<unknown>;
|
|
1365
1402
|
getRuntimeSafetyStatus?(): Promise<unknown>;
|
|
1403
|
+
proxyStreamReceiverExists(receiverId: string): Promise<boolean>;
|
|
1404
|
+
proxyStreamReceive(receiverId: string, frame: ProxyStreamFrame): Promise<boolean>;
|
|
1405
|
+
proxyStreamOpen(request: ClientStreamRequest, target: ProxyStreamTarget): Promise<ProxyStreamOpenResult>;
|
|
1406
|
+
proxyStreamWrite(id: string, data: string): Promise<void>;
|
|
1407
|
+
proxyStreamEnd(id: string): Promise<void>;
|
|
1408
|
+
proxyStreamAbort(id: string): Promise<void>;
|
|
1366
1409
|
/** Newest non-empty user message on the thread, for thread-list previews. */
|
|
1367
1410
|
getLatestUserMessagePreview(): Promise<string | null>;
|
|
1368
1411
|
executeBlocking?(threadId: string, agentId: string, initial_messages?: unknown[], data?: unknown): Promise<{
|
|
@@ -1934,4 +1977,4 @@ declare function defineController<Env extends ThreadEnv = ThreadEnv>(controller:
|
|
|
1934
1977
|
*/
|
|
1935
1978
|
declare function createThreadEndpointHandler<Env extends ThreadEnv = ThreadEnv>(handler: ThreadEndpointHandler): BuilderController<Env>;
|
|
1936
1979
|
|
|
1937
|
-
export { type AuthUser as A, type BuilderController as B, CLIENT_STREAM_CHUNK_BYTES as C, type FlowResult as D, type TelemetryEvent as E, type FlowState as F, type Env as G, type FileRecord as H, type ImageMetadata as I, type AttachmentRef as J, type GrepResult as K, type LLMResponse as L, type Message as M, type FileStats as N, type TextContentPart as O, type ImageContentPart as P, type MultimodalContent as Q, type RequestContext as R, type StorageBackend as S, type ToolCall as T, type MessageContent as U, type
|
|
1980
|
+
export { type AuthUser as A, type BuilderController as B, CLIENT_STREAM_CHUNK_BYTES as C, type FlowResult as D, type TelemetryEvent as E, type FlowState as F, type Env as G, type FileRecord as H, type ImageMetadata as I, type AttachmentRef as J, type GrepResult as K, type LLMResponse as L, type Message as M, type FileStats as N, type TextContentPart as O, type ImageContentPart as P, type MultimodalContent as Q, type RequestContext as R, type StorageBackend as S, type ToolCall as T, type MessageContent as U, type ProxyStreamReceiver as V, type ProxyStreamFrame as W, type ProxyStreamTarget as X, type ProxyStreamOpenResult as Y, type SkillStorageScope as Z, type BuilderControllerContext as a, type ThreadEndpointContext as b, createThreadEndpointHandler as c, defineController as d, type ThreadEnv as e, type BuilderThreadEndpointHandler as f, authenticate as g, requireAdmin as h, endpointCallerFromAuth as i, type AuthContext as j, callClient as k, callClientStream as l, encodeStreamChunk as m, decodeStreamChunk as n, type ClientToolRequest as o, type ClientToolResponse as p, type ClientStreamRequest as q, requireAuth as r, supportsClientForwarding as s, type ClientStreamResponse as t, type ClientDuplex as u, type ClientForwarding as v, type Agent as w, type ThreadInstance as x, type ThreadMetadata as y, type ToolResult as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ModelDefinition, AgentDefinition } from './runtime.js';
|
|
2
2
|
export { AgentBuilderEnv, AgentBuilderEvent, BroadcastOptions, CodeExecutionBridge, DurableAgentBuilder, DurableThread, DurableUserHub, FlowStateSdk, FlowStateWithSdk, HubClientInfo, ImageContextConfig, InjectMessageOptions, LLMProviderInterface, NamespaceResolutionError, PromptContent, PromptDefinition, PromptIncludePart, PromptPart, PromptToolConfig, Provider, ProviderContentPart, ProviderFilePart, ProviderImagePart, ProviderRegistry, ProviderTextPart, SessionToolBinding, SessionToolConfig, SideConfig, SubagentToolConfig, SubpromptConfig, ThreadEventPayload, ThreadRegistryEntry, ThreadWatchdog, ThreadWatchdogState, ToolConfig, UpdateThreadParams, User, WatchdogCheckin, 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 } from './runtime.js';
|
|
3
3
|
export { AgentPluginOptions, agentbuilder, builder } from './plugin.js';
|
|
4
|
-
export { w as Agent, J as AttachmentRef, j as AuthContext, A as AuthUser, f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, u as ClientDuplex, v as ClientForwarding, q as ClientStreamRequest, t as ClientStreamResponse, o as ClientToolRequest, p 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, b as ThreadEndpointContext, e as ThreadEnv, x as ThreadInstance, y as ThreadMetadata, T as ToolCall, z as ToolResult, g as authenticate, k as callClient, l as callClientStream, c as createThreadEndpointHandler, n as decodeStreamChunk, d as defineController, m as encodeStreamChunk, i as endpointCallerFromAuth, h as requireAdmin, r as requireAuth, s as supportsClientForwarding } from './index-
|
|
4
|
+
export { w as Agent, J as AttachmentRef, j as AuthContext, A as AuthUser, f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, u as ClientDuplex, v as ClientForwarding, q as ClientStreamRequest, t as ClientStreamResponse, o as ClientToolRequest, p 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, b as ThreadEndpointContext, e as ThreadEnv, x as ThreadInstance, y as ThreadMetadata, T as ToolCall, z as ToolResult, g as authenticate, k as callClient, l as callClientStream, c as createThreadEndpointHandler, n as decodeStreamChunk, d as defineController, m as encodeStreamChunk, i as endpointCallerFromAuth, h as requireAdmin, r as requireAuth, s as supportsClientForwarding } from './index-DYhbT5Eq.js';
|
|
5
5
|
export { AgentType, DefinitionLoader, GlobalNamespaceContext, HookExecutionContext, HookExecutionSource, HookSignatures, ImageContent, ModelCapabilities, ModelProvider, NamespaceContext, PackageSignature, PackedExports, PackedMeta, PackedMetadata, PackedNamespaceContext, ParentHookRequirement, ParentHookStage, PromptInput, PromptTextPart, ProviderAssistantMessage, ProviderConfigSlot, ProviderConfigSlots, ProviderConfigValueSource, ProviderDefinition, ProviderError, ProviderErrorCode, ProviderFactory, ProviderFactoryConfig, ProviderFinishReason, ProviderGeneratedImage, ProviderMessage, ProviderMessageContent, ProviderMethodOverrides, ModelCapabilities as ProviderModelCapabilities, ProviderOverride, ProviderOverrideContext, ProviderReasoningDetail, ProviderRequest, ProviderResponse, ProviderStreamChunk, ProviderSyncOverride, ProviderSystemMessage, ProviderTool, ProviderToolCallPart, ProviderToolMessage, ProviderToolResultContent, ProviderUsage, ProviderUserMessage, ReasoningConfig, StructuredPrompt, TextContent, ThreadHookName, Tool, ToolArgs, ToolArgsNode, ToolArgsRawShape, ToolContent, belongsToPackage, defineAgent, defineHook, defineModel, definePrompt, defineProvider, defineTool, isPacked, isVisibleInNamespace, mapReasoningLevel, providerConst, providerEnv, providerValue } from '@standardagents/spec';
|
|
6
6
|
export { C as ConstituentItem, D as DiscoveredPackage, N as NamespacedRegistry, P as PackingAnalysis, a as PackingOptions, b as PackingResult, c as UnpackOptions, d as UnpackResult } from './types-BMnBYNwn.js';
|
|
7
7
|
export { D as DiscoveryConfig, P as PackageDiscoveryService, d as discoverPackages } from './discovery-DZ7fv-b4.js';
|
package/dist/index.js
CHANGED
|
@@ -14722,27 +14722,51 @@ var init_ThreadStateImpl = __esm({
|
|
|
14722
14722
|
const withWake = (threadId) => wakeUserId ? { ...request, wake: { threadId, userId: wakeUserId } } : request;
|
|
14723
14723
|
const local = await instance.openClientStream(withWake(this._metadata.id));
|
|
14724
14724
|
if (local.ok || !this.isNoClient(local)) return local;
|
|
14725
|
-
|
|
14726
|
-
|
|
14725
|
+
if (typeof instance.createProxyStreamReceiver !== "function" || typeof instance.proxyStreamReceive !== "function") {
|
|
14726
|
+
return local;
|
|
14727
|
+
}
|
|
14728
|
+
let abortRemote = null;
|
|
14729
|
+
const receiver = instance.createProxyStreamReceiver((error) => abortRemote?.(error));
|
|
14730
|
+
const discardReceiver = async (error) => {
|
|
14731
|
+
await instance.proxyStreamReceive(receiver.id, { type: "abort", error });
|
|
14732
|
+
};
|
|
14733
|
+
const namespace = instance.env.AGENT_BUILDER_THREAD;
|
|
14727
14734
|
const seen = /* @__PURE__ */ new Set([this._metadata.id]);
|
|
14728
14735
|
let parentId = await this.resolveParentThreadId(this._metadata.id);
|
|
14729
14736
|
while (parentId && !seen.has(parentId)) {
|
|
14730
14737
|
seen.add(parentId);
|
|
14731
14738
|
try {
|
|
14732
|
-
const stub =
|
|
14739
|
+
const stub = namespace.get(namespace.idFromName(parentId));
|
|
14733
14740
|
if (typeof stub.proxyStreamOpen === "function") {
|
|
14734
|
-
const opened = await stub.proxyStreamOpen(withWake(parentId)
|
|
14741
|
+
const opened = await stub.proxyStreamOpen(withWake(parentId), {
|
|
14742
|
+
threadId: this._metadata.id,
|
|
14743
|
+
receiverId: receiver.id
|
|
14744
|
+
});
|
|
14735
14745
|
if (opened.ok && opened.id) {
|
|
14746
|
+
if (opened.eventDriven !== true) {
|
|
14747
|
+
await stub.proxyStreamAbort(opened.id).catch(() => {
|
|
14748
|
+
});
|
|
14749
|
+
await discardReceiver("The ancestor runtime does not support event-driven streams.");
|
|
14750
|
+
return {
|
|
14751
|
+
ok: false,
|
|
14752
|
+
error: "The ancestor runtime does not support event-driven streams.",
|
|
14753
|
+
data: { code: "unsupported" }
|
|
14754
|
+
};
|
|
14755
|
+
}
|
|
14756
|
+
abortRemote = (error) => {
|
|
14757
|
+
void stub.proxyStreamAbort(opened.id).catch(() => {
|
|
14758
|
+
});
|
|
14759
|
+
if (error) {
|
|
14760
|
+
void instance.proxyStreamReceive(receiver.id, { type: "abort", error });
|
|
14761
|
+
}
|
|
14762
|
+
};
|
|
14736
14763
|
return {
|
|
14737
14764
|
ok: true,
|
|
14738
|
-
duplex: this.
|
|
14739
|
-
stub,
|
|
14740
|
-
opened.id,
|
|
14741
|
-
opened.parkedPull === true
|
|
14742
|
-
)
|
|
14765
|
+
duplex: this.buildEventProxyDuplex(stub, opened.id, receiver, instance)
|
|
14743
14766
|
};
|
|
14744
14767
|
}
|
|
14745
14768
|
if (opened.error && !opened.noClient) {
|
|
14769
|
+
await discardReceiver(opened.error);
|
|
14746
14770
|
return {
|
|
14747
14771
|
ok: false,
|
|
14748
14772
|
error: opened.error,
|
|
@@ -14754,69 +14778,21 @@ var init_ThreadStateImpl = __esm({
|
|
|
14754
14778
|
}
|
|
14755
14779
|
parentId = await this.resolveParentThreadId(parentId);
|
|
14756
14780
|
}
|
|
14781
|
+
await discardReceiver(local.error ?? "No execution-owner bridge is available.");
|
|
14757
14782
|
return local;
|
|
14758
14783
|
}
|
|
14759
14784
|
/**
|
|
14760
14785
|
* Build a client duplex that bridges to a stream opened on an ancestor DO
|
|
14761
|
-
* (the bridge holder)
|
|
14762
|
-
*
|
|
14763
|
-
* error, or abort, so an idle open stream performs zero repeated pulls.
|
|
14764
|
-
* Older ancestors use the bounded long-pull compatibility path. `writable`
|
|
14765
|
-
* forwards each chunk with `proxyStreamWrite`; teardown calls
|
|
14766
|
-
* `proxyStreamAbort`.
|
|
14786
|
+
* (the bridge holder). The readable is the receiver registered on this DO;
|
|
14787
|
+
* writes and terminal actions are the only child-to-ancestor RPCs.
|
|
14767
14788
|
*/
|
|
14768
|
-
|
|
14769
|
-
buildProxyDuplex(stub, id, supportsParkedPull = false) {
|
|
14770
|
-
let settleDone;
|
|
14771
|
-
const done = new Promise((r) => settleDone = r);
|
|
14789
|
+
buildEventProxyDuplex(stub, id, receiver, instance) {
|
|
14772
14790
|
let closed = false;
|
|
14773
|
-
|
|
14774
|
-
|
|
14775
|
-
|
|
14776
|
-
|
|
14777
|
-
settleDone(result);
|
|
14791
|
+
const settleLocal = (error) => {
|
|
14792
|
+
if (typeof instance.proxyStreamReceive !== "function") return;
|
|
14793
|
+
const frame = error ? { type: "abort", error } : { type: "end" };
|
|
14794
|
+
void instance.proxyStreamReceive(receiver.id, frame);
|
|
14778
14795
|
};
|
|
14779
|
-
const readable = new ReadableStream({
|
|
14780
|
-
async pull(controller) {
|
|
14781
|
-
while (!closed) {
|
|
14782
|
-
const pullStartedAt = Date.now();
|
|
14783
|
-
let res;
|
|
14784
|
-
try {
|
|
14785
|
-
res = await stub.proxyStreamPull(
|
|
14786
|
-
id,
|
|
14787
|
-
supportsParkedPull ? void 0 : _ThreadStateImpl.PROXY_PULL_MAX_WAIT_MS
|
|
14788
|
-
);
|
|
14789
|
-
} catch (error) {
|
|
14790
|
-
controller.error(error instanceof Error ? error : new Error(String(error)));
|
|
14791
|
-
settle({ ok: false, error: "proxy stream pull failed" });
|
|
14792
|
-
return;
|
|
14793
|
-
}
|
|
14794
|
-
for (const chunk of res.chunks) {
|
|
14795
|
-
controller.enqueue(decodeStreamChunk(chunk));
|
|
14796
|
-
}
|
|
14797
|
-
if (res.done) {
|
|
14798
|
-
controller.close();
|
|
14799
|
-
settle(res.error ? { ok: false, error: res.error } : { ok: true });
|
|
14800
|
-
return;
|
|
14801
|
-
}
|
|
14802
|
-
if (res.chunks.length > 0) return;
|
|
14803
|
-
if (supportsParkedPull) {
|
|
14804
|
-
controller.error(new Error("parked proxy pull returned without data"));
|
|
14805
|
-
settle({ ok: false, error: "parked proxy pull returned without data" });
|
|
14806
|
-
return;
|
|
14807
|
-
}
|
|
14808
|
-
if (Date.now() - pullStartedAt < 250) {
|
|
14809
|
-
await new Promise((r) => setTimeout(r, 250));
|
|
14810
|
-
}
|
|
14811
|
-
}
|
|
14812
|
-
},
|
|
14813
|
-
cancel() {
|
|
14814
|
-
closed = true;
|
|
14815
|
-
void stub.proxyStreamAbort(id).catch(() => {
|
|
14816
|
-
});
|
|
14817
|
-
settle({ ok: false, error: "proxy stream reader canceled" });
|
|
14818
|
-
}
|
|
14819
|
-
});
|
|
14820
14796
|
const writable = new WritableStream({
|
|
14821
14797
|
async write(chunk) {
|
|
14822
14798
|
await stub.proxyStreamWrite(id, encodeStreamChunk(chunk));
|
|
@@ -14829,20 +14805,20 @@ var init_ThreadStateImpl = __esm({
|
|
|
14829
14805
|
closed = true;
|
|
14830
14806
|
void stub.proxyStreamAbort(id).catch(() => {
|
|
14831
14807
|
});
|
|
14832
|
-
|
|
14808
|
+
settleLocal("The proxy stream writer was aborted.");
|
|
14833
14809
|
}
|
|
14834
14810
|
});
|
|
14835
14811
|
return {
|
|
14836
|
-
readable,
|
|
14812
|
+
readable: receiver.readable,
|
|
14837
14813
|
writable,
|
|
14838
14814
|
close: (error) => {
|
|
14839
14815
|
if (closed) return;
|
|
14840
14816
|
closed = true;
|
|
14841
14817
|
void stub.proxyStreamAbort(id).catch(() => {
|
|
14842
14818
|
});
|
|
14843
|
-
|
|
14819
|
+
settleLocal(error);
|
|
14844
14820
|
},
|
|
14845
|
-
done
|
|
14821
|
+
done: receiver.done
|
|
14846
14822
|
};
|
|
14847
14823
|
}
|
|
14848
14824
|
isNoClient(res) {
|
|
@@ -31096,6 +31072,8 @@ var DurableThread = class _DurableThread extends DurableObject {
|
|
|
31096
31072
|
// opened on and dies with it. Streams are in-memory only — they exist solely
|
|
31097
31073
|
// while the client is attached and never park durably.
|
|
31098
31074
|
clientStreams = /* @__PURE__ */ new Map();
|
|
31075
|
+
proxyStreamReceivers = /* @__PURE__ */ new Map();
|
|
31076
|
+
eventProxyStreams = /* @__PURE__ */ new Map();
|
|
31099
31077
|
alarmQueue;
|
|
31100
31078
|
runtimeSafety;
|
|
31101
31079
|
alarmQueueRearmed = false;
|
|
@@ -31207,6 +31185,10 @@ var DurableThread = class _DurableThread extends DurableObject {
|
|
|
31207
31185
|
clientName: typeof attachment.clientName === "string" ? attachment.clientName : null,
|
|
31208
31186
|
clientKind: typeof attachment.clientKind === "string" ? attachment.clientKind : null
|
|
31209
31187
|
});
|
|
31188
|
+
const interrupted = this.parseProxyStreamAttachments(attachment.proxyStreams);
|
|
31189
|
+
if (interrupted.length > 0) {
|
|
31190
|
+
this.recoverInterruptedProxyStreams(ws, interrupted);
|
|
31191
|
+
}
|
|
31210
31192
|
}
|
|
31211
31193
|
}
|
|
31212
31194
|
}
|
|
@@ -35462,8 +35444,138 @@ ${resultContent}${attachmentSummary}`;
|
|
|
35462
35444
|
});
|
|
35463
35445
|
}
|
|
35464
35446
|
}
|
|
35447
|
+
parseProxyStreamAttachments(value) {
|
|
35448
|
+
if (!Array.isArray(value)) return [];
|
|
35449
|
+
const parsed = [];
|
|
35450
|
+
for (const item of value) {
|
|
35451
|
+
if (!item || typeof item !== "object") continue;
|
|
35452
|
+
const candidate = item;
|
|
35453
|
+
if (typeof candidate.id === "string" && candidate.target && typeof candidate.target.threadId === "string" && typeof candidate.target.receiverId === "string") {
|
|
35454
|
+
parsed.push({
|
|
35455
|
+
id: candidate.id,
|
|
35456
|
+
target: {
|
|
35457
|
+
threadId: candidate.target.threadId,
|
|
35458
|
+
receiverId: candidate.target.receiverId
|
|
35459
|
+
}
|
|
35460
|
+
});
|
|
35461
|
+
}
|
|
35462
|
+
}
|
|
35463
|
+
return parsed;
|
|
35464
|
+
}
|
|
35465
|
+
/** Keep live proxy routes on the hibernating bridge socket for restart cleanup. */
|
|
35466
|
+
updateBridgeProxyAttachment(socket) {
|
|
35467
|
+
if (typeof socket.serializeAttachment !== "function") return;
|
|
35468
|
+
let attachment = { type: "bridge" };
|
|
35469
|
+
try {
|
|
35470
|
+
const current = socket.deserializeAttachment();
|
|
35471
|
+
if (current && typeof current === "object") {
|
|
35472
|
+
attachment = { ...current };
|
|
35473
|
+
}
|
|
35474
|
+
} catch {
|
|
35475
|
+
}
|
|
35476
|
+
const proxyStreams = Array.from(this.clientStreams.entries()).filter(([, state]) => state.socket === socket && state.proxyTarget !== null).map(([id, state]) => ({ id, target: state.proxyTarget }));
|
|
35477
|
+
try {
|
|
35478
|
+
socket.serializeAttachment({ ...attachment, proxyStreams });
|
|
35479
|
+
} catch {
|
|
35480
|
+
}
|
|
35481
|
+
}
|
|
35482
|
+
async deliverProxyStreamFrame(target, frame) {
|
|
35483
|
+
try {
|
|
35484
|
+
const namespace = this.env.AGENT_BUILDER_THREAD;
|
|
35485
|
+
const stub = namespace.get(namespace.idFromName(target.threadId));
|
|
35486
|
+
return await stub.proxyStreamReceive(target.receiverId, frame);
|
|
35487
|
+
} catch {
|
|
35488
|
+
return false;
|
|
35489
|
+
}
|
|
35490
|
+
}
|
|
35491
|
+
/** Abort live proxy routes restored without their in-memory stream state. */
|
|
35492
|
+
recoverInterruptedProxyStreams(socket, streams) {
|
|
35493
|
+
const error = "The stream ended because its runtime restarted.";
|
|
35494
|
+
for (const stream of streams) {
|
|
35495
|
+
try {
|
|
35496
|
+
if (socket.readyState === WebSocket.OPEN) {
|
|
35497
|
+
socket.send(JSON.stringify({ type: "stream_abort", id: stream.id, error }));
|
|
35498
|
+
}
|
|
35499
|
+
} catch {
|
|
35500
|
+
}
|
|
35501
|
+
this.ctx.waitUntil(
|
|
35502
|
+
this.deliverProxyStreamFrame(stream.target, { type: "abort", error }).then(() => {
|
|
35503
|
+
})
|
|
35504
|
+
);
|
|
35505
|
+
}
|
|
35506
|
+
this.updateBridgeProxyAttachment(socket);
|
|
35507
|
+
}
|
|
35508
|
+
/** Register the child side before any ancestor opens an owner stream. */
|
|
35509
|
+
createProxyStreamReceiver(onCancel) {
|
|
35510
|
+
const id = crypto.randomUUID();
|
|
35511
|
+
let controller = null;
|
|
35512
|
+
let settleDone;
|
|
35513
|
+
const done = new Promise((resolve3) => {
|
|
35514
|
+
settleDone = resolve3;
|
|
35515
|
+
});
|
|
35516
|
+
const readable = new ReadableStream({
|
|
35517
|
+
start(value) {
|
|
35518
|
+
controller = value;
|
|
35519
|
+
},
|
|
35520
|
+
cancel: (reason) => {
|
|
35521
|
+
const receiver2 = this.proxyStreamReceivers.get(id);
|
|
35522
|
+
if (!receiver2 || receiver2.settled) return;
|
|
35523
|
+
const error = reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "The proxy stream reader was canceled.";
|
|
35524
|
+
receiver2.settle({ ok: false, error });
|
|
35525
|
+
receiver2.onCancel(error);
|
|
35526
|
+
}
|
|
35527
|
+
});
|
|
35528
|
+
const receiver = {
|
|
35529
|
+
controller,
|
|
35530
|
+
settle: (result) => {
|
|
35531
|
+
if (receiver.settled) return;
|
|
35532
|
+
receiver.settled = true;
|
|
35533
|
+
this.proxyStreamReceivers.delete(id);
|
|
35534
|
+
settleDone(result);
|
|
35535
|
+
},
|
|
35536
|
+
onCancel,
|
|
35537
|
+
settled: false
|
|
35538
|
+
};
|
|
35539
|
+
this.proxyStreamReceivers.set(id, receiver);
|
|
35540
|
+
return { id, readable, done };
|
|
35541
|
+
}
|
|
35542
|
+
async proxyStreamReceiverExists(receiverId) {
|
|
35543
|
+
return this.proxyStreamReceivers.has(receiverId);
|
|
35544
|
+
}
|
|
35545
|
+
async proxyStreamReceive(receiverId, frame) {
|
|
35546
|
+
const receiver = this.proxyStreamReceivers.get(receiverId);
|
|
35547
|
+
if (!receiver || receiver.settled) return false;
|
|
35548
|
+
if (frame.type === "data") {
|
|
35549
|
+
try {
|
|
35550
|
+
receiver.controller?.enqueue(decodeStreamChunk(frame.data));
|
|
35551
|
+
} catch (error2) {
|
|
35552
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
35553
|
+
try {
|
|
35554
|
+
receiver.controller?.error(error2 instanceof Error ? error2 : new Error(message));
|
|
35555
|
+
} catch {
|
|
35556
|
+
}
|
|
35557
|
+
receiver.settle({ ok: false, error: message });
|
|
35558
|
+
}
|
|
35559
|
+
return true;
|
|
35560
|
+
}
|
|
35561
|
+
if (frame.type === "end") {
|
|
35562
|
+
try {
|
|
35563
|
+
receiver.controller?.close();
|
|
35564
|
+
} catch {
|
|
35565
|
+
}
|
|
35566
|
+
receiver.settle({ ok: true });
|
|
35567
|
+
return true;
|
|
35568
|
+
}
|
|
35569
|
+
const error = frame.error ?? "The proxied client stream was aborted.";
|
|
35570
|
+
try {
|
|
35571
|
+
receiver.controller?.error(new Error(error));
|
|
35572
|
+
} catch {
|
|
35573
|
+
}
|
|
35574
|
+
receiver.settle({ ok: false, error });
|
|
35575
|
+
return true;
|
|
35576
|
+
}
|
|
35465
35577
|
/** Open a bidirectional byte stream to the connected owner client. */
|
|
35466
|
-
async openClientStream(request) {
|
|
35578
|
+
async openClientStream(request, proxyTarget = null) {
|
|
35467
35579
|
const owner = await this.getExecutionOwner();
|
|
35468
35580
|
let socket = this.getOpenBridgeSocket(owner?.client_id ?? null);
|
|
35469
35581
|
if (!socket && owner) {
|
|
@@ -35496,9 +35608,12 @@ ${resultContent}${attachmentSummary}`;
|
|
|
35496
35608
|
opened: null,
|
|
35497
35609
|
openTimer: null,
|
|
35498
35610
|
settleDone,
|
|
35499
|
-
settled: false
|
|
35611
|
+
settled: false,
|
|
35612
|
+
proxyTarget,
|
|
35613
|
+
delivery: Promise.resolve()
|
|
35500
35614
|
};
|
|
35501
35615
|
this.clientStreams.set(id, state);
|
|
35616
|
+
this.updateBridgeProxyAttachment(socket);
|
|
35502
35617
|
this.bridgeLastSeen.set(socket, Date.now());
|
|
35503
35618
|
const openResult = await new Promise((resolve3) => {
|
|
35504
35619
|
state.opened = resolve3;
|
|
@@ -35534,6 +35649,7 @@ ${resultContent}${attachmentSummary}`;
|
|
|
35534
35649
|
}
|
|
35535
35650
|
if (!openResult.ok) {
|
|
35536
35651
|
this.clientStreams.delete(id);
|
|
35652
|
+
this.updateBridgeProxyAttachment(socket);
|
|
35537
35653
|
state.settled = true;
|
|
35538
35654
|
settleDone({ ok: false, error: openResult.error });
|
|
35539
35655
|
return {
|
|
@@ -35575,14 +35691,28 @@ ${resultContent}${attachmentSummary}`;
|
|
|
35575
35691
|
};
|
|
35576
35692
|
return { ok: true, duplex };
|
|
35577
35693
|
}
|
|
35578
|
-
// ───
|
|
35579
|
-
// A
|
|
35580
|
-
//
|
|
35581
|
-
//
|
|
35582
|
-
//
|
|
35583
|
-
|
|
35584
|
-
|
|
35585
|
-
|
|
35694
|
+
// ─── Event-driven subagent stream proxy ──────────────────────────────────
|
|
35695
|
+
// A child registers a local receiver before the bridge-holding ancestor
|
|
35696
|
+
// opens the client stream. The ancestor invokes that receiver only for real
|
|
35697
|
+
// data/end/abort events; there is no pull loop or permanently outstanding
|
|
35698
|
+
// cross-DO RPC while the stream is idle.
|
|
35699
|
+
async proxyStreamOpen(request, target) {
|
|
35700
|
+
const namespace = this.env.AGENT_BUILDER_THREAD;
|
|
35701
|
+
let receiverExists = false;
|
|
35702
|
+
try {
|
|
35703
|
+
const destination = namespace.get(namespace.idFromName(target.threadId));
|
|
35704
|
+
receiverExists = await destination.proxyStreamReceiverExists(target.receiverId);
|
|
35705
|
+
} catch {
|
|
35706
|
+
receiverExists = false;
|
|
35707
|
+
}
|
|
35708
|
+
if (!receiverExists) {
|
|
35709
|
+
return {
|
|
35710
|
+
ok: false,
|
|
35711
|
+
error: "The destination stream receiver is unavailable.",
|
|
35712
|
+
code: "unavailable"
|
|
35713
|
+
};
|
|
35714
|
+
}
|
|
35715
|
+
const opened = await this.openClientStream(request, target);
|
|
35586
35716
|
if (!opened.ok) {
|
|
35587
35717
|
const failureData = opened.data;
|
|
35588
35718
|
const noClient = failureData?.noClient === true;
|
|
@@ -35594,82 +35724,23 @@ ${resultContent}${attachmentSummary}`;
|
|
|
35594
35724
|
};
|
|
35595
35725
|
}
|
|
35596
35726
|
const id = crypto.randomUUID();
|
|
35597
|
-
|
|
35598
|
-
|
|
35599
|
-
|
|
35600
|
-
|
|
35601
|
-
writer,
|
|
35602
|
-
reader,
|
|
35603
|
-
buffer: [],
|
|
35604
|
-
done: false,
|
|
35605
|
-
error: void 0,
|
|
35606
|
-
pump: Promise.resolve(),
|
|
35607
|
-
close: (error) => duplex.close(error),
|
|
35608
|
-
waiter: null,
|
|
35609
|
-
notify: () => {
|
|
35610
|
-
const waiter = entry.waiter;
|
|
35611
|
-
entry.waiter = null;
|
|
35612
|
-
waiter?.();
|
|
35613
|
-
}
|
|
35614
|
-
};
|
|
35615
|
-
entry.pump = (async () => {
|
|
35616
|
-
try {
|
|
35617
|
-
while (true) {
|
|
35618
|
-
const { value, done } = await reader.read();
|
|
35619
|
-
if (done) break;
|
|
35620
|
-
if (value) {
|
|
35621
|
-
entry.buffer.push(value);
|
|
35622
|
-
entry.notify();
|
|
35623
|
-
}
|
|
35624
|
-
}
|
|
35625
|
-
} catch (error) {
|
|
35626
|
-
entry.error = error instanceof Error ? error.message : String(error);
|
|
35627
|
-
} finally {
|
|
35628
|
-
entry.done = true;
|
|
35629
|
-
entry.notify();
|
|
35630
|
-
}
|
|
35631
|
-
})();
|
|
35632
|
-
void duplex.done.then((d) => {
|
|
35633
|
-
entry.done = true;
|
|
35634
|
-
if (!d.ok && !entry.error) entry.error = d.error;
|
|
35635
|
-
entry.notify();
|
|
35727
|
+
this.eventProxyStreams.set(id, {
|
|
35728
|
+
writer: opened.duplex.writable.getWriter(),
|
|
35729
|
+
close: (error) => opened.duplex.close(error),
|
|
35730
|
+
target
|
|
35636
35731
|
});
|
|
35637
|
-
|
|
35638
|
-
return { ok: true, id, parkedPull: true };
|
|
35732
|
+
return { ok: true, id, eventDriven: true };
|
|
35639
35733
|
}
|
|
35640
35734
|
async proxyStreamWrite(id, dataB64) {
|
|
35641
|
-
const entry = this.
|
|
35735
|
+
const entry = this.eventProxyStreams.get(id);
|
|
35642
35736
|
if (!entry) return;
|
|
35643
35737
|
try {
|
|
35644
35738
|
await entry.writer.write(decodeStreamChunk(dataB64));
|
|
35645
35739
|
} catch {
|
|
35646
35740
|
}
|
|
35647
35741
|
}
|
|
35648
|
-
async proxyStreamPull(id, maxWaitMs) {
|
|
35649
|
-
const entry = this.proxyStreams.get(id);
|
|
35650
|
-
if (!entry) return { chunks: [], done: true, error: "unknown proxy stream" };
|
|
35651
|
-
if (entry.buffer.length === 0 && !entry.done) {
|
|
35652
|
-
await new Promise((resolve3) => {
|
|
35653
|
-
const deadline = typeof maxWaitMs === "number" && maxWaitMs > 0 ? setTimeout(() => {
|
|
35654
|
-
if (entry.waiter === wake) entry.waiter = null;
|
|
35655
|
-
resolve3();
|
|
35656
|
-
}, maxWaitMs) : null;
|
|
35657
|
-
const wake = () => {
|
|
35658
|
-
if (deadline) clearTimeout(deadline);
|
|
35659
|
-
resolve3();
|
|
35660
|
-
};
|
|
35661
|
-
entry.waiter = wake;
|
|
35662
|
-
});
|
|
35663
|
-
}
|
|
35664
|
-
const chunks = entry.buffer.splice(0).map((b) => encodeStreamChunk(b));
|
|
35665
|
-
if (entry.done && entry.buffer.length === 0) {
|
|
35666
|
-
this.proxyStreams.delete(id);
|
|
35667
|
-
return { chunks, done: true, error: entry.error };
|
|
35668
|
-
}
|
|
35669
|
-
return { chunks, done: false };
|
|
35670
|
-
}
|
|
35671
35742
|
async proxyStreamEnd(id) {
|
|
35672
|
-
const entry = this.
|
|
35743
|
+
const entry = this.eventProxyStreams.get(id);
|
|
35673
35744
|
if (!entry) return;
|
|
35674
35745
|
try {
|
|
35675
35746
|
await entry.writer.close();
|
|
@@ -35677,30 +35748,49 @@ ${resultContent}${attachmentSummary}`;
|
|
|
35677
35748
|
}
|
|
35678
35749
|
}
|
|
35679
35750
|
async proxyStreamAbort(id) {
|
|
35680
|
-
const entry = this.
|
|
35751
|
+
const entry = this.eventProxyStreams.get(id);
|
|
35681
35752
|
if (!entry) return;
|
|
35682
|
-
this.
|
|
35683
|
-
entry.done = true;
|
|
35684
|
-
if (!entry.error) entry.error = "aborted";
|
|
35685
|
-
entry.notify();
|
|
35753
|
+
this.eventProxyStreams.delete(id);
|
|
35686
35754
|
try {
|
|
35687
35755
|
entry.close("aborted");
|
|
35688
35756
|
} catch {
|
|
35689
35757
|
}
|
|
35690
35758
|
}
|
|
35759
|
+
forgetEventProxyStream(clientStreamId, target) {
|
|
35760
|
+
const matchesTarget = (candidate) => candidate.threadId === target.threadId && candidate.receiverId === target.receiverId;
|
|
35761
|
+
for (const [id, entry] of Array.from(this.eventProxyStreams.entries())) {
|
|
35762
|
+
if (id !== clientStreamId && !matchesTarget(entry.target)) continue;
|
|
35763
|
+
this.eventProxyStreams.delete(id);
|
|
35764
|
+
try {
|
|
35765
|
+
entry.writer.releaseLock();
|
|
35766
|
+
} catch {
|
|
35767
|
+
}
|
|
35768
|
+
}
|
|
35769
|
+
}
|
|
35691
35770
|
/** Settle and remove a client stream exactly once. */
|
|
35692
35771
|
settleClientStream(id, result, openCode) {
|
|
35693
35772
|
const state = this.clientStreams.get(id);
|
|
35694
35773
|
if (!state) return;
|
|
35695
35774
|
this.clientStreams.delete(id);
|
|
35775
|
+
this.updateBridgeProxyAttachment(state.socket);
|
|
35696
35776
|
if (state.openTimer) clearTimeout(state.openTimer);
|
|
35697
35777
|
if (state.opened) state.opened({ ok: false, error: result.error ?? "Stream closed.", code: openCode });
|
|
35698
35778
|
if (!state.settled) {
|
|
35699
35779
|
state.settled = true;
|
|
35700
|
-
|
|
35701
|
-
|
|
35702
|
-
|
|
35703
|
-
|
|
35780
|
+
if (state.proxyTarget) {
|
|
35781
|
+
const target = state.proxyTarget;
|
|
35782
|
+
const frame = result.ok ? { type: "end" } : { type: "abort", error: result.error ?? "Client stream aborted." };
|
|
35783
|
+
state.delivery = state.delivery.then(async () => {
|
|
35784
|
+
await this.deliverProxyStreamFrame(target, frame);
|
|
35785
|
+
});
|
|
35786
|
+
this.ctx.waitUntil(state.delivery);
|
|
35787
|
+
this.forgetEventProxyStream(id, target);
|
|
35788
|
+
} else {
|
|
35789
|
+
try {
|
|
35790
|
+
if (result.ok) state.controller?.close();
|
|
35791
|
+
else state.controller?.error(new Error(result.error ?? "Client stream aborted."));
|
|
35792
|
+
} catch {
|
|
35793
|
+
}
|
|
35704
35794
|
}
|
|
35705
35795
|
state.settleDone(result);
|
|
35706
35796
|
}
|
|
@@ -35743,6 +35833,18 @@ ${resultContent}${attachmentSummary}`;
|
|
|
35743
35833
|
}
|
|
35744
35834
|
case "stream_data": {
|
|
35745
35835
|
if (typeof parsed.data !== "string") return;
|
|
35836
|
+
if (state.proxyTarget) {
|
|
35837
|
+
const target = state.proxyTarget;
|
|
35838
|
+
const frame = { type: "data", data: parsed.data };
|
|
35839
|
+
state.delivery = state.delivery.then(async () => {
|
|
35840
|
+
const delivered = await this.deliverProxyStreamFrame(target, frame);
|
|
35841
|
+
if (!delivered && this.clientStreams.get(id) === state) {
|
|
35842
|
+
this.abortClientStream(id, "The destination stream receiver is unavailable.");
|
|
35843
|
+
}
|
|
35844
|
+
});
|
|
35845
|
+
this.ctx.waitUntil(state.delivery);
|
|
35846
|
+
return;
|
|
35847
|
+
}
|
|
35746
35848
|
try {
|
|
35747
35849
|
state.controller?.enqueue(decodeStreamChunk(parsed.data));
|
|
35748
35850
|
} catch {
|