@standardagents/builder 0.30.2 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/built-in-routes.js +45 -3
- package/dist/built-in-routes.js.map +1 -1
- package/dist/client/{ApiKeysView-jhfg43UH.js → ApiKeysView-CxNw8yvZ.js} +1 -1
- package/dist/client/CenteredContentView-D4G91Thq.js +1 -0
- package/dist/client/{CompositionView-DhkLWmtE.js → CompositionView-BaWfyUW6.js} +1 -1
- package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-D-WToRMy.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-CVzMoEOi.js} +1 -1
- package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-Dhq0t0dd.js → CopyButton.vue_vue_type_script_setup_true_lang-Cz_ZrOAS.js} +1 -1
- package/dist/client/{DataTable.vue_vue_type_script_setup_true_lang-D1MDCns-.js → DataTable.vue_vue_type_script_setup_true_lang-CQwcIXyb.js} +1 -1
- package/dist/client/{JsonViewer-BoHrE76S.js → JsonViewer-Dsl-e2IH.js} +1 -1
- package/dist/client/{LoginView-BpR2nMNf.js → LoginView-CX0lmKUS.js} +1 -1
- package/dist/client/{MarketplaceView-uUf1JYla.js → MarketplaceView-BJAG7kej.js} +1 -1
- package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-D-SDVFQI.js → Modal.vue_vue_type_script_setup_true_lang-B2Yd_pvh.js} +1 -1
- package/dist/client/{ModelModal.vue_vue_type_script_setup_true_lang-DE57Zr0r.js → ModelModal.vue_vue_type_script_setup_true_lang-CCH8VxwI.js} +1 -1
- package/dist/client/{ModelsView-CuM_OieH.js → ModelsView-CGgNBkY-.js} +1 -1
- package/dist/client/{PromptEditView-BWjrA2zr.js → PromptEditView-CL2LEH80.js} +1 -1
- package/dist/client/{PromptModal-BFxhuG0Z.js → PromptModal-DHHy53-v.js} +1 -1
- package/dist/client/{PromptsView-AlGsRB6k.js → PromptsView-BcTfvJdH.js} +1 -1
- package/dist/client/{ProvidersView-CbXBs3SH.js → ProvidersView-B2yy_Kbe.js} +1 -1
- package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-BCiZyZu-.js +22 -0
- package/dist/client/{ThreadsView-rN9rzJi1.js → ThreadsView-BKSAJipV.js} +1 -1
- package/dist/client/{ToolsView-0Gpo_RFg.js → ToolsView-DBkare-6.js} +1 -1
- package/dist/client/{UiCodeBlock.vue_vue_type_script_setup_true_lang-CNncALQo.js → UiCodeBlock.vue_vue_type_script_setup_true_lang-QytRm7Ql.js} +1 -1
- package/dist/client/{UsersView-iXPbcguY.js → UsersView-yBnliXIU.js} +1 -1
- package/dist/client/{VariablesView-C9BB9h34.js → VariablesView-N-VgGqPg.js} +1 -1
- package/dist/client/assets/ThreadInspectorPane-DSQsKyG6.css +1 -0
- package/dist/client/assets/index-C4KCxdCv.css +1 -0
- package/dist/client/{check-BdJVlUmI.js → check-pGlck8qX.js} +1 -1
- package/dist/client/{chevron-right-D49O3XLU.js → chevron-right-FpPE1Obh.js} +1 -1
- package/dist/client/{copy-40uDyTgY.js → copy-Dt1FLh3s.js} +1 -1
- package/dist/client/{formkit-Bl-sERnF.js → formkit-DcZQH9-p.js} +1 -1
- package/dist/client/{index-BCoE48be.js → index-DANZMMwO.js} +3 -3
- package/dist/client/index.html +4 -4
- package/dist/client/{package-1UgoERpx.js → package-DSNwOrcN.js} +1 -1
- package/dist/client/{plus-BzCjfYs0.js → plus-D0GkkdA7.js} +1 -1
- package/dist/client/{timeAgo-cFwldMu-.js → timeAgo-X3Xeq5Kz.js} +1 -1
- package/dist/client/{useActionFeedback-BVifffYQ.js → useActionFeedback-Dxh_Xp0q.js} +1 -1
- package/dist/client/vue-KXHVRwln.js +1 -0
- package/dist/{index-CcnGEkPh.d.ts → index-1AMgutkG.d.ts} +27 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +203 -16
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +6 -0
- package/dist/plugin.js.map +1 -1
- package/dist/runtime.d.ts +48 -2
- package/dist/runtime.js +197 -16
- package/dist/runtime.js.map +1 -1
- package/dist/test.d.ts +1 -1
- package/package.json +5 -5
- package/dist/client/CenteredContentView-CS0mV2EJ.js +0 -1
- package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-Dm3d37hz.js +0 -22
- package/dist/client/assets/ThreadInspectorPane-CfpdDnUQ.css +0 -1
- package/dist/client/assets/index-BTPsPULO.css +0 -1
- package/dist/client/vue-CmmJuziT.js +0 -1
package/dist/runtime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { e as ThreadEnv, A as Agent, r as ThreadMetadata, t as ToolResult, M as Message, k as ClientToolRequest, l as ClientToolResponse, m as ClientStreamRequest, n as ClientStreamResponse, w as FileRecord, F as FlowState, y as FileStats, G as GrepResult, x as AttachmentRef, J as MessageContent, E as Env, q as ThreadInstance } from './index-
|
|
2
|
-
export { f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, o as ClientDuplex, p as ClientForwarding, B as Controller, a as ControllerContext, u as FlowResult, D as ImageContentPart, I as ImageMetadata, L as LLMResponse, H as MultimodalContent, R as RequestContext, S as StorageBackend, v as TelemetryEvent, z as TextContentPart, b as ThreadEndpointContext, T as ToolCall, g as callClient, h as callClientStream, c as createThreadEndpointHandler, j as decodeStreamChunk, d as defineController, i as encodeStreamChunk, s as supportsClientForwarding } from './index-
|
|
1
|
+
import { e as ThreadEnv, A as Agent, r as ThreadMetadata, t as ToolResult, M as Message, k as ClientToolRequest, l as ClientToolResponse, m as ClientStreamRequest, n as ClientStreamResponse, w as FileRecord, F as FlowState, y as FileStats, G as GrepResult, x as AttachmentRef, J as MessageContent, E as Env, q as ThreadInstance } from './index-1AMgutkG.js';
|
|
2
|
+
export { f as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, o as ClientDuplex, p as ClientForwarding, B as Controller, a as ControllerContext, u as FlowResult, D as ImageContentPart, I as ImageMetadata, L as LLMResponse, H as MultimodalContent, R as RequestContext, S as StorageBackend, v as TelemetryEvent, z as TextContentPart, b as ThreadEndpointContext, T as ToolCall, g as callClient, h as callClientStream, c as createThreadEndpointHandler, j as decodeStreamChunk, d as defineController, i as encodeStreamChunk, s as supportsClientForwarding } from './index-1AMgutkG.js';
|
|
3
3
|
import { CodeExecutionOptions, CodeExecutionResult, SubagentRegistryEntry, InjectMessageInput, QueueMessageInput, CredentialGrant, SkillMetadata, SkillFileInput, ModelDefinition as ModelDefinition$1, ToolArgs, PromptTextPart, PromptEnvPart, VariableDefinition, SubpromptConfig as SubpromptConfig$1, PromptToolConfig as PromptToolConfig$1, SubagentToolConfig as SubagentToolConfig$1, ReasoningConfig, SideConfig as SideConfig$1, LLMProviderInterface, ContentPart, TextPart, ImagePart, FilePart, ThreadState, NamespaceContext, DefinitionLoader } from '@standardagents/spec';
|
|
4
4
|
export { AgentType, DefinitionLoader, GlobalNamespaceContext, HookSignatures, ImageContent, ModelCapabilities, ModelProvider, NamespaceContext, PackageSignature, PackedExports, PackedMeta, PackedMetadata, PackedNamespaceContext, PromptInput, PromptTextPart, ProviderAssistantMessage, ProviderError, ProviderErrorCode, ProviderFactory, ProviderFactoryConfig, ProviderFinishReason, ProviderGeneratedImage, ProviderMessage, ProviderMessageContent, ModelCapabilities as ProviderModelCapabilities, ProviderReasoningDetail, ProviderRequest, ProviderResponse, ProviderStreamChunk, ProviderSystemMessage, ProviderTool, ProviderToolCallPart, ProviderToolMessage, ProviderToolResultContent, ProviderUsage, ProviderUserMessage, ReasoningConfig, StructuredPrompt, TextContent, Tool, ToolArgs, ToolArgsNode, ToolArgsRawShape, ToolContent, belongsToPackage, defineAgent, defineHook, defineModel, definePrompt, defineTool, isPacked, isVisibleInNamespace, mapReasoningLevel } from '@standardagents/spec';
|
|
5
5
|
import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
|
|
@@ -1241,6 +1241,13 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
|
|
|
1241
1241
|
* Returns null on deployments whose generated config predates the binding.
|
|
1242
1242
|
*/
|
|
1243
1243
|
private watchdogCompanion;
|
|
1244
|
+
/**
|
|
1245
|
+
* Stamp thread activity on the registry so thread lists can sort by recency
|
|
1246
|
+
* of real work and show which threads are executing right now. Registry
|
|
1247
|
+
* bookkeeping is presentation state: a failure here must never take down the
|
|
1248
|
+
* turn that triggered it.
|
|
1249
|
+
*/
|
|
1250
|
+
private recordRegistryActivity;
|
|
1244
1251
|
/** Arm the standing watchdog for an execution start. One pending row max. */
|
|
1245
1252
|
private armExecutionWatchdog;
|
|
1246
1253
|
/** Disarm on clean execution end. Completed check rows are noise, not history. */
|
|
@@ -1802,6 +1809,12 @@ interface ThreadRegistryEntry {
|
|
|
1802
1809
|
parent: string | null;
|
|
1803
1810
|
terminated: number | null;
|
|
1804
1811
|
created_at: number;
|
|
1812
|
+
/** Unix seconds of the last message or execution on this thread (or a descendant). */
|
|
1813
|
+
last_activity_at?: number | null;
|
|
1814
|
+
/** True while the thread is executing a flow (stale markers read as false). */
|
|
1815
|
+
executing?: boolean;
|
|
1816
|
+
/** Short excerpt of the most recent user message, for thread-list rows. */
|
|
1817
|
+
last_message_preview?: string | null;
|
|
1805
1818
|
}
|
|
1806
1819
|
interface PendingSubagentAttachmentRef {
|
|
1807
1820
|
path: string;
|
|
@@ -1910,6 +1923,8 @@ interface Provider$1 {
|
|
|
1910
1923
|
sdk: string;
|
|
1911
1924
|
api_key: string;
|
|
1912
1925
|
}
|
|
1926
|
+
/** Sort orders supported by `listThreads`. */
|
|
1927
|
+
type ThreadListSort = 'activity' | 'created' | 'oldest';
|
|
1913
1928
|
declare class DurableAgentBuilder<Env extends AgentBuilderEnv = AgentBuilderEnv> extends DurableObject<Env> {
|
|
1914
1929
|
private migratedToVersion;
|
|
1915
1930
|
private eventSockets;
|
|
@@ -2024,10 +2039,41 @@ declare class DurableAgentBuilder<Env extends AgentBuilderEnv = AgentBuilderEnv>
|
|
|
2024
2039
|
limit?: number;
|
|
2025
2040
|
offset?: number;
|
|
2026
2041
|
include_children?: boolean;
|
|
2042
|
+
/** Default `activity`: most recently worked-on threads first. */
|
|
2043
|
+
sort?: ThreadListSort;
|
|
2044
|
+
/** `true` → only threads currently executing; `false` → only idle ones. */
|
|
2045
|
+
executing?: boolean;
|
|
2046
|
+
/** `false` hides terminated threads; `true` shows only terminated ones. */
|
|
2047
|
+
terminated?: boolean;
|
|
2027
2048
|
}): Promise<{
|
|
2028
2049
|
threads: ThreadRegistryEntry[];
|
|
2029
2050
|
total: number;
|
|
2030
2051
|
}>;
|
|
2052
|
+
/**
|
|
2053
|
+
* Distinct owners of threads visible to the caller, with counts, so a thread
|
|
2054
|
+
* list can offer an "owner" filter without exposing the admin-only user
|
|
2055
|
+
* directory (which is unavailable on hosted instances).
|
|
2056
|
+
*/
|
|
2057
|
+
listThreadOwners(params?: {
|
|
2058
|
+
user_id?: string;
|
|
2059
|
+
}): Promise<Array<{
|
|
2060
|
+
user_id: string | null;
|
|
2061
|
+
username: string | null;
|
|
2062
|
+
display_name: string | null;
|
|
2063
|
+
email: string | null;
|
|
2064
|
+
thread_count: number;
|
|
2065
|
+
}>>;
|
|
2066
|
+
/**
|
|
2067
|
+
* Record that a thread did work: stamp `last_activity_at` and flip the
|
|
2068
|
+
* executing marker. Activity bubbles up the parent chain so a root thread
|
|
2069
|
+
* sorts by the freshest work anywhere in its subagent tree — otherwise a
|
|
2070
|
+
* long-running subagent would let its parent sink down an activity-sorted
|
|
2071
|
+
* list.
|
|
2072
|
+
*/
|
|
2073
|
+
recordThreadActivity(threadId: string, options?: {
|
|
2074
|
+
executing?: boolean;
|
|
2075
|
+
messagePreview?: string | null;
|
|
2076
|
+
}): Promise<void>;
|
|
2031
2077
|
/**
|
|
2032
2078
|
* Delete a thread from the registry.
|
|
2033
2079
|
*/
|
package/dist/runtime.js
CHANGED
|
@@ -17790,9 +17790,9 @@ var DurableThread = class _DurableThread extends DurableObject {
|
|
|
17790
17790
|
* Each migration is run in order, starting from the current version + 1.
|
|
17791
17791
|
*/
|
|
17792
17792
|
async runMigrations(fromVersion) {
|
|
17793
|
-
for (const
|
|
17794
|
-
if (
|
|
17795
|
-
await
|
|
17793
|
+
for (const migration49 of migrations) {
|
|
17794
|
+
if (migration49.version > fromVersion) {
|
|
17795
|
+
await migration49.up(this.ctx.storage.sql);
|
|
17796
17796
|
}
|
|
17797
17797
|
}
|
|
17798
17798
|
}
|
|
@@ -21186,6 +21186,28 @@ ${resultContent}${attachmentSummary}`;
|
|
|
21186
21186
|
if (!namespace || typeof namespace.idFromName !== "function") return null;
|
|
21187
21187
|
return namespace.get(namespace.idFromName(threadId));
|
|
21188
21188
|
}
|
|
21189
|
+
/**
|
|
21190
|
+
* Stamp thread activity on the registry so thread lists can sort by recency
|
|
21191
|
+
* of real work and show which threads are executing right now. Registry
|
|
21192
|
+
* bookkeeping is presentation state: a failure here must never take down the
|
|
21193
|
+
* turn that triggered it.
|
|
21194
|
+
*/
|
|
21195
|
+
async recordRegistryActivity(threadId, executing, messagePreview) {
|
|
21196
|
+
try {
|
|
21197
|
+
const namespace = this.env.AGENT_BUILDER;
|
|
21198
|
+
if (!namespace || typeof namespace.idFromName !== "function") return;
|
|
21199
|
+
const agentBuilder = namespace.get(namespace.idFromName("singleton"));
|
|
21200
|
+
await agentBuilder.recordThreadActivity?.(threadId, {
|
|
21201
|
+
executing,
|
|
21202
|
+
...messagePreview !== void 0 ? { messagePreview } : {}
|
|
21203
|
+
});
|
|
21204
|
+
} catch (error) {
|
|
21205
|
+
console.error(
|
|
21206
|
+
"[DurableThread] Failed to record thread activity (non-fatal):",
|
|
21207
|
+
error
|
|
21208
|
+
);
|
|
21209
|
+
}
|
|
21210
|
+
}
|
|
21189
21211
|
/** Arm the standing watchdog for an execution start. One pending row max. */
|
|
21190
21212
|
async armExecutionWatchdog(threadId) {
|
|
21191
21213
|
try {
|
|
@@ -21372,6 +21394,7 @@ ${resultContent}${attachmentSummary}`;
|
|
|
21372
21394
|
}
|
|
21373
21395
|
this.isExecuting = false;
|
|
21374
21396
|
this.currentAbortController = null;
|
|
21397
|
+
await this.recordRegistryActivity(threadId, false);
|
|
21375
21398
|
tookOver = true;
|
|
21376
21399
|
} else if (incomplete.length > 0 && silenceMs <= ceiling) {
|
|
21377
21400
|
return report("observing", "none");
|
|
@@ -21575,6 +21598,7 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
|
|
|
21575
21598
|
this.isExecuting = true;
|
|
21576
21599
|
this.currentAbortController = new AbortController();
|
|
21577
21600
|
await this.armExecutionWatchdog(threadId);
|
|
21601
|
+
await this.recordRegistryActivity(threadId, true);
|
|
21578
21602
|
try {
|
|
21579
21603
|
const agentDef = await this.loadAgent(agentName);
|
|
21580
21604
|
const packageId = agentDef.__package?.packageId;
|
|
@@ -21706,6 +21730,7 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
|
|
|
21706
21730
|
this.isExecuting = false;
|
|
21707
21731
|
this.currentAbortController = null;
|
|
21708
21732
|
await this.disarmExecutionWatchdog(threadId);
|
|
21733
|
+
await this.recordRegistryActivity(threadId, false);
|
|
21709
21734
|
}
|
|
21710
21735
|
}
|
|
21711
21736
|
/**
|
|
@@ -21766,6 +21791,11 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
|
|
|
21766
21791
|
this.isExecuting = true;
|
|
21767
21792
|
this.currentAbortController = new AbortController();
|
|
21768
21793
|
await this.armExecutionWatchdog(threadId);
|
|
21794
|
+
await this.recordRegistryActivity(
|
|
21795
|
+
threadId,
|
|
21796
|
+
true,
|
|
21797
|
+
role === "user" ? content : void 0
|
|
21798
|
+
);
|
|
21769
21799
|
try {
|
|
21770
21800
|
const agentBuilderId = this.env.AGENT_BUILDER.idFromName("singleton");
|
|
21771
21801
|
const agentBuilder = this.env.AGENT_BUILDER.get(agentBuilderId);
|
|
@@ -21905,6 +21935,7 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
|
|
|
21905
21935
|
this.isExecuting = false;
|
|
21906
21936
|
this.currentAbortController = null;
|
|
21907
21937
|
await this.disarmExecutionWatchdog(threadId);
|
|
21938
|
+
await this.recordRegistryActivity(threadId, false);
|
|
21908
21939
|
}
|
|
21909
21940
|
}
|
|
21910
21941
|
/**
|
|
@@ -21922,6 +21953,7 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
|
|
|
21922
21953
|
this.isExecuting = true;
|
|
21923
21954
|
this.currentAbortController = new AbortController();
|
|
21924
21955
|
await this.armExecutionWatchdog(threadId);
|
|
21956
|
+
await this.recordRegistryActivity(threadId, true);
|
|
21925
21957
|
try {
|
|
21926
21958
|
const agentBuilderId = this.env.AGENT_BUILDER.idFromName("singleton");
|
|
21927
21959
|
const agentBuilder = this.env.AGENT_BUILDER.get(agentBuilderId);
|
|
@@ -22031,6 +22063,7 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
|
|
|
22031
22063
|
this.isExecuting = false;
|
|
22032
22064
|
this.currentAbortController = null;
|
|
22033
22065
|
await this.disarmExecutionWatchdog(threadId);
|
|
22066
|
+
await this.recordRegistryActivity(threadId, false);
|
|
22034
22067
|
const latestQueuedSide = await this.getLatestQueuedMessageSide();
|
|
22035
22068
|
if (latestQueuedSide) {
|
|
22036
22069
|
await this.ensureQueuedMessageExecution(threadId, latestQueuedSide);
|
|
@@ -23124,9 +23157,43 @@ var migration46 = {
|
|
|
23124
23157
|
}
|
|
23125
23158
|
};
|
|
23126
23159
|
|
|
23160
|
+
// src/durable-objects/agentbuilder-migrations/0013_add_thread_activity.ts
|
|
23161
|
+
var migration47 = {
|
|
23162
|
+
version: 13,
|
|
23163
|
+
async up(sql) {
|
|
23164
|
+
sql.exec(`ALTER TABLE threads ADD COLUMN last_activity_at INTEGER`);
|
|
23165
|
+
sql.exec(`ALTER TABLE threads ADD COLUMN executing_since INTEGER`);
|
|
23166
|
+
sql.exec(
|
|
23167
|
+
`CREATE INDEX IF NOT EXISTS idx_threads_last_activity_at ON threads(last_activity_at)`
|
|
23168
|
+
);
|
|
23169
|
+
sql.exec(`UPDATE threads SET last_activity_at = created_at`);
|
|
23170
|
+
sql.exec(`
|
|
23171
|
+
INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '13')
|
|
23172
|
+
`);
|
|
23173
|
+
}
|
|
23174
|
+
};
|
|
23175
|
+
|
|
23176
|
+
// src/durable-objects/agentbuilder-migrations/0014_thread_activity_scale.ts
|
|
23177
|
+
var migration48 = {
|
|
23178
|
+
version: 14,
|
|
23179
|
+
async up(sql) {
|
|
23180
|
+
sql.exec(`ALTER TABLE threads ADD COLUMN last_message_preview TEXT`);
|
|
23181
|
+
sql.exec(
|
|
23182
|
+
`CREATE INDEX IF NOT EXISTS idx_threads_executing_since
|
|
23183
|
+
ON threads(executing_since) WHERE executing_since IS NOT NULL`
|
|
23184
|
+
);
|
|
23185
|
+
sql.exec(
|
|
23186
|
+
`UPDATE threads SET last_activity_at = created_at WHERE last_activity_at IS NULL`
|
|
23187
|
+
);
|
|
23188
|
+
sql.exec(`
|
|
23189
|
+
INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '14')
|
|
23190
|
+
`);
|
|
23191
|
+
}
|
|
23192
|
+
};
|
|
23193
|
+
|
|
23127
23194
|
// src/durable-objects/agentbuilder-migrations/index.ts
|
|
23128
|
-
var migrations2 = [migration35, migration36, migration37, migration38, migration39, migration40, migration41, migration42, migration43, migration44, migration45, migration46];
|
|
23129
|
-
var LATEST_SCHEMA_VERSION2 =
|
|
23195
|
+
var migrations2 = [migration35, migration36, migration37, migration38, migration39, migration40, migration41, migration42, migration43, migration44, migration45, migration46, migration47, migration48];
|
|
23196
|
+
var LATEST_SCHEMA_VERSION2 = 14;
|
|
23130
23197
|
|
|
23131
23198
|
// src/utils/crypto.ts
|
|
23132
23199
|
var CryptoUtil = class {
|
|
@@ -23325,6 +23392,14 @@ function parseStoredPermissions(value) {
|
|
|
23325
23392
|
return null;
|
|
23326
23393
|
}
|
|
23327
23394
|
}
|
|
23395
|
+
var EXECUTING_STALE_AFTER_SECONDS = 15 * 60;
|
|
23396
|
+
var THREAD_PREVIEW_MAX_CHARS = 140;
|
|
23397
|
+
var buildThreadPreview = (content) => {
|
|
23398
|
+
const collapsed = content.replace(/\s+/g, " ").trim();
|
|
23399
|
+
if (!collapsed) return null;
|
|
23400
|
+
return collapsed.length > THREAD_PREVIEW_MAX_CHARS ? `${collapsed.slice(0, THREAD_PREVIEW_MAX_CHARS - 1)}\u2026` : collapsed;
|
|
23401
|
+
};
|
|
23402
|
+
var isThreadExecuting = (executingSince, nowSeconds) => executingSince != null && nowSeconds - executingSince < EXECUTING_STALE_AFTER_SECONDS;
|
|
23328
23403
|
var DurableAgentBuilder = class extends DurableObject {
|
|
23329
23404
|
migratedToVersion = null;
|
|
23330
23405
|
eventSockets = /* @__PURE__ */ new Set();
|
|
@@ -23893,9 +23968,9 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
23893
23968
|
}
|
|
23894
23969
|
}
|
|
23895
23970
|
async runMigrations(fromVersion) {
|
|
23896
|
-
for (const
|
|
23897
|
-
if (
|
|
23898
|
-
await
|
|
23971
|
+
for (const migration49 of migrations2) {
|
|
23972
|
+
if (migration49.version > fromVersion) {
|
|
23973
|
+
await migration49.up(this.ctx.storage.sql);
|
|
23899
23974
|
}
|
|
23900
23975
|
}
|
|
23901
23976
|
}
|
|
@@ -23937,8 +24012,8 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
23937
24012
|
const encryptedEnv = await this.encryptEnvRecord(env);
|
|
23938
24013
|
const properties = this.withEnvTypeRecord(params.properties ?? null, envTypes);
|
|
23939
24014
|
await this.ctx.storage.sql.exec(
|
|
23940
|
-
`INSERT INTO threads (id, agent_name, user_id, tags, env, tenvs, properties, parent, terminated, created_at)
|
|
23941
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, ?)`,
|
|
24015
|
+
`INSERT INTO threads (id, agent_name, user_id, tags, env, tenvs, properties, parent, terminated, created_at, last_activity_at)
|
|
24016
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)`,
|
|
23942
24017
|
id,
|
|
23943
24018
|
params.agent_name,
|
|
23944
24019
|
params.user_id || null,
|
|
@@ -23947,6 +24022,7 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
23947
24022
|
encryptedEnv,
|
|
23948
24023
|
properties ? JSON.stringify(properties) : null,
|
|
23949
24024
|
params.parent ?? null,
|
|
24025
|
+
now,
|
|
23950
24026
|
now
|
|
23951
24027
|
);
|
|
23952
24028
|
const thread = {
|
|
@@ -23960,7 +24036,9 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
23960
24036
|
properties,
|
|
23961
24037
|
parent: params.parent ?? null,
|
|
23962
24038
|
terminated: null,
|
|
23963
|
-
created_at: now
|
|
24039
|
+
created_at: now,
|
|
24040
|
+
last_activity_at: now,
|
|
24041
|
+
executing: false
|
|
23964
24042
|
};
|
|
23965
24043
|
const eventThread = await this.toThreadEventPayload(thread);
|
|
23966
24044
|
this.broadcastEvent({ type: "thread_created", thread: eventThread });
|
|
@@ -24016,7 +24094,10 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24016
24094
|
*/
|
|
24017
24095
|
async getThread(id) {
|
|
24018
24096
|
await this.ensureMigrated();
|
|
24019
|
-
const cursor = await this.ctx.storage.sql.exec(
|
|
24097
|
+
const cursor = await this.ctx.storage.sql.exec(
|
|
24098
|
+
`SELECT id, agent_name, user_id, tags, env, tenvs, properties, parent, terminated, created_at, last_activity_at, executing_since, last_message_preview FROM threads WHERE id = ?`,
|
|
24099
|
+
id
|
|
24100
|
+
);
|
|
24020
24101
|
const rows = cursor.toArray();
|
|
24021
24102
|
if (rows.length === 0) {
|
|
24022
24103
|
return null;
|
|
@@ -24036,7 +24117,13 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24036
24117
|
properties,
|
|
24037
24118
|
parent: row.parent,
|
|
24038
24119
|
terminated: row.terminated,
|
|
24039
|
-
created_at: row.created_at
|
|
24120
|
+
created_at: row.created_at,
|
|
24121
|
+
last_activity_at: row.last_activity_at ?? row.created_at,
|
|
24122
|
+
executing: isThreadExecuting(
|
|
24123
|
+
row.executing_since,
|
|
24124
|
+
Math.floor(Date.now() / 1e3)
|
|
24125
|
+
),
|
|
24126
|
+
last_message_preview: row.last_message_preview
|
|
24040
24127
|
};
|
|
24041
24128
|
}
|
|
24042
24129
|
/**
|
|
@@ -24077,6 +24164,7 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24077
24164
|
*/
|
|
24078
24165
|
async listThreads(params) {
|
|
24079
24166
|
await this.ensureMigrated();
|
|
24167
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
24080
24168
|
const whereClauses = [];
|
|
24081
24169
|
const args = [];
|
|
24082
24170
|
if (params?.agent_name) {
|
|
@@ -24112,6 +24200,18 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24112
24200
|
whereClauses.push("created_at <= ?");
|
|
24113
24201
|
args.push(params.endDate);
|
|
24114
24202
|
}
|
|
24203
|
+
if (params?.executing === true) {
|
|
24204
|
+
whereClauses.push("executing_since IS NOT NULL AND executing_since > ?");
|
|
24205
|
+
args.push(nowSeconds - EXECUTING_STALE_AFTER_SECONDS);
|
|
24206
|
+
} else if (params?.executing === false) {
|
|
24207
|
+
whereClauses.push("(executing_since IS NULL OR executing_since <= ?)");
|
|
24208
|
+
args.push(nowSeconds - EXECUTING_STALE_AFTER_SECONDS);
|
|
24209
|
+
}
|
|
24210
|
+
if (params?.terminated === true) {
|
|
24211
|
+
whereClauses.push("terminated IS NOT NULL");
|
|
24212
|
+
} else if (params?.terminated === false) {
|
|
24213
|
+
whereClauses.push("terminated IS NULL");
|
|
24214
|
+
}
|
|
24115
24215
|
const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
|
|
24116
24216
|
const countCursor = await this.ctx.storage.sql.exec(
|
|
24117
24217
|
`SELECT COUNT(*) as count FROM threads ${whereClause}`,
|
|
@@ -24120,10 +24220,11 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24120
24220
|
const total = countCursor.one().count;
|
|
24121
24221
|
const limit = params?.limit ?? 100;
|
|
24122
24222
|
const offset = params?.offset ?? 0;
|
|
24223
|
+
const orderByClause = params?.sort === "created" ? "created_at DESC" : params?.sort === "oldest" ? "created_at ASC" : "last_activity_at DESC, created_at DESC";
|
|
24123
24224
|
const cursor = await this.ctx.storage.sql.exec(
|
|
24124
|
-
`SELECT id, agent_name, user_id, tags, properties, parent, terminated, created_at FROM threads
|
|
24225
|
+
`SELECT id, agent_name, user_id, tags, properties, parent, terminated, created_at, last_activity_at, executing_since, last_message_preview FROM threads
|
|
24125
24226
|
${whereClause}
|
|
24126
|
-
ORDER BY
|
|
24227
|
+
ORDER BY ${orderByClause}
|
|
24127
24228
|
LIMIT ? OFFSET ?`,
|
|
24128
24229
|
...args,
|
|
24129
24230
|
limit,
|
|
@@ -24143,10 +24244,90 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24143
24244
|
properties: row.properties ? JSON.parse(row.properties) : null,
|
|
24144
24245
|
parent: row.parent,
|
|
24145
24246
|
terminated: row.terminated,
|
|
24146
|
-
created_at: row.created_at
|
|
24247
|
+
created_at: row.created_at,
|
|
24248
|
+
last_activity_at: row.last_activity_at ?? row.created_at,
|
|
24249
|
+
executing: isThreadExecuting(row.executing_since, nowSeconds),
|
|
24250
|
+
last_message_preview: row.last_message_preview
|
|
24147
24251
|
}));
|
|
24148
24252
|
return { threads, total };
|
|
24149
24253
|
}
|
|
24254
|
+
/**
|
|
24255
|
+
* Distinct owners of threads visible to the caller, with counts, so a thread
|
|
24256
|
+
* list can offer an "owner" filter without exposing the admin-only user
|
|
24257
|
+
* directory (which is unavailable on hosted instances).
|
|
24258
|
+
*/
|
|
24259
|
+
async listThreadOwners(params) {
|
|
24260
|
+
await this.ensureMigrated();
|
|
24261
|
+
const whereClause = params?.user_id ? "WHERE t.user_id = ?" : "";
|
|
24262
|
+
const args = params?.user_id ? [params.user_id] : [];
|
|
24263
|
+
const cursor = await this.ctx.storage.sql.exec(
|
|
24264
|
+
`SELECT t.user_id AS user_id,
|
|
24265
|
+
u.username AS username,
|
|
24266
|
+
u.display_name AS display_name,
|
|
24267
|
+
u.email AS email,
|
|
24268
|
+
COUNT(*) AS thread_count
|
|
24269
|
+
FROM threads t
|
|
24270
|
+
LEFT JOIN users u ON u.id = t.user_id
|
|
24271
|
+
${whereClause}
|
|
24272
|
+
GROUP BY t.user_id
|
|
24273
|
+
ORDER BY thread_count DESC`,
|
|
24274
|
+
...args
|
|
24275
|
+
);
|
|
24276
|
+
return cursor.toArray();
|
|
24277
|
+
}
|
|
24278
|
+
/**
|
|
24279
|
+
* Record that a thread did work: stamp `last_activity_at` and flip the
|
|
24280
|
+
* executing marker. Activity bubbles up the parent chain so a root thread
|
|
24281
|
+
* sorts by the freshest work anywhere in its subagent tree — otherwise a
|
|
24282
|
+
* long-running subagent would let its parent sink down an activity-sorted
|
|
24283
|
+
* list.
|
|
24284
|
+
*/
|
|
24285
|
+
async recordThreadActivity(threadId, options) {
|
|
24286
|
+
await this.ensureMigrated();
|
|
24287
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
24288
|
+
const executing = options?.executing;
|
|
24289
|
+
const preview = typeof options?.messagePreview === "string" ? buildThreadPreview(options.messagePreview) : void 0;
|
|
24290
|
+
await this.ctx.storage.sql.exec(
|
|
24291
|
+
`UPDATE threads
|
|
24292
|
+
SET last_activity_at = ?
|
|
24293
|
+
WHERE id IN (
|
|
24294
|
+
WITH RECURSIVE ancestry(id, parent) AS (
|
|
24295
|
+
SELECT id, parent FROM threads WHERE id = ?
|
|
24296
|
+
UNION ALL
|
|
24297
|
+
SELECT t.id, t.parent FROM threads t JOIN ancestry a ON t.id = a.parent
|
|
24298
|
+
)
|
|
24299
|
+
SELECT id FROM ancestry
|
|
24300
|
+
)`,
|
|
24301
|
+
now,
|
|
24302
|
+
threadId
|
|
24303
|
+
);
|
|
24304
|
+
if (executing === true) {
|
|
24305
|
+
await this.ctx.storage.sql.exec(
|
|
24306
|
+
`UPDATE threads SET executing_since = ? WHERE id = ? AND executing_since IS NULL`,
|
|
24307
|
+
now,
|
|
24308
|
+
threadId
|
|
24309
|
+
);
|
|
24310
|
+
} else if (executing === false) {
|
|
24311
|
+
await this.ctx.storage.sql.exec(
|
|
24312
|
+
`UPDATE threads SET executing_since = NULL WHERE id = ?`,
|
|
24313
|
+
threadId
|
|
24314
|
+
);
|
|
24315
|
+
}
|
|
24316
|
+
if (preview !== void 0) {
|
|
24317
|
+
await this.ctx.storage.sql.exec(
|
|
24318
|
+
`UPDATE threads SET last_message_preview = ? WHERE id = ?`,
|
|
24319
|
+
preview,
|
|
24320
|
+
threadId
|
|
24321
|
+
);
|
|
24322
|
+
}
|
|
24323
|
+
this.broadcastEvent({
|
|
24324
|
+
type: "thread_activity",
|
|
24325
|
+
threadId,
|
|
24326
|
+
last_activity_at: now,
|
|
24327
|
+
executing: executing === true,
|
|
24328
|
+
...preview !== void 0 ? { last_message_preview: preview } : {}
|
|
24329
|
+
});
|
|
24330
|
+
}
|
|
24150
24331
|
/**
|
|
24151
24332
|
* Delete a thread from the registry.
|
|
24152
24333
|
*/
|