@standardagents/builder 0.31.0 → 0.33.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 +35 -1
- package/dist/built-in-routes.js.map +1 -1
- package/dist/client/{ApiKeysView-wfApkZad.js → ApiKeysView-CxNw8yvZ.js} +1 -1
- package/dist/client/{CenteredContentView-JFIi6iAA.js → CenteredContentView-D4G91Thq.js} +1 -1
- package/dist/client/{CompositionView-CIm8Kt1I.js → CompositionView-BaWfyUW6.js} +1 -1
- package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-DO1fUxUR.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-CVzMoEOi.js} +1 -1
- package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-DfEFB4ze.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-4XH4cxYM.js → DataTable.vue_vue_type_script_setup_true_lang-CQwcIXyb.js} +1 -1
- package/dist/client/{JsonViewer-md2l5DdY.js → JsonViewer-Dsl-e2IH.js} +1 -1
- package/dist/client/{LoginView-BJSfZpgw.js → LoginView-CX0lmKUS.js} +1 -1
- package/dist/client/{MarketplaceView-DXE7ys3s.js → MarketplaceView-BJAG7kej.js} +1 -1
- package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-FiL__HMg.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-BIBHjNB0.js → ModelModal.vue_vue_type_script_setup_true_lang-CCH8VxwI.js} +1 -1
- package/dist/client/{ModelsView-BhtR_WPG.js → ModelsView-CGgNBkY-.js} +1 -1
- package/dist/client/{PromptEditView-DadQ9eJ0.js → PromptEditView-CL2LEH80.js} +1 -1
- package/dist/client/{PromptModal-BMBKSmJC.js → PromptModal-DHHy53-v.js} +1 -1
- package/dist/client/{PromptsView-F1l2HocI.js → PromptsView-BcTfvJdH.js} +1 -1
- package/dist/client/{ProvidersView-DFWGCJwN.js → ProvidersView-B2yy_Kbe.js} +1 -1
- package/dist/client/{ThreadInspectorPane.vue_vue_type_script_setup_true_lang-C7JV15r3.js → ThreadInspectorPane.vue_vue_type_script_setup_true_lang-BCiZyZu-.js} +13 -13
- package/dist/client/{ThreadsView-CMb05n9d.js → ThreadsView-BKSAJipV.js} +1 -1
- package/dist/client/{ToolsView-7F2ybb1x.js → ToolsView-DBkare-6.js} +1 -1
- package/dist/client/{UsersView-Badppc4K.js → UsersView-yBnliXIU.js} +1 -1
- package/dist/client/{VariablesView-E45rU9bc.js → VariablesView-N-VgGqPg.js} +1 -1
- package/dist/client/assets/{ThreadInspectorPane-Bha1aVZZ.css → ThreadInspectorPane-DSQsKyG6.css} +1 -1
- package/dist/client/{index-BYdncvi0.js → index-DANZMMwO.js} +2 -2
- package/dist/client/index.html +1 -1
- package/dist/{index-CL7q3PuW.d.ts → index-CqhPhqAI.d.ts} +10 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +117 -17
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +2 -0
- package/dist/plugin.js.map +1 -1
- package/dist/runtime.d.ts +23 -2
- package/dist/runtime.js +115 -17
- package/dist/runtime.js.map +1 -1
- package/dist/test.d.ts +1 -1
- package/package.json +5 -5
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-CqhPhqAI.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-CqhPhqAI.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';
|
|
@@ -1248,6 +1248,12 @@ declare class DurableThread<Env extends ThreadEnv = ThreadEnv> extends DurableOb
|
|
|
1248
1248
|
* turn that triggered it.
|
|
1249
1249
|
*/
|
|
1250
1250
|
private recordRegistryActivity;
|
|
1251
|
+
/**
|
|
1252
|
+
* The newest non-empty user message on this thread, for thread-list previews.
|
|
1253
|
+
* Returns null when the thread has none. The Durable Object does not know its
|
|
1254
|
+
* own thread id, so the caller is the one that stamps the registry.
|
|
1255
|
+
*/
|
|
1256
|
+
getLatestUserMessagePreview(): Promise<string | null>;
|
|
1251
1257
|
/** Arm the standing watchdog for an execution start. One pending row max. */
|
|
1252
1258
|
private armExecutionWatchdog;
|
|
1253
1259
|
/** Disarm on clean execution end. Completed check rows are noise, not history. */
|
|
@@ -1813,6 +1819,8 @@ interface ThreadRegistryEntry {
|
|
|
1813
1819
|
last_activity_at?: number | null;
|
|
1814
1820
|
/** True while the thread is executing a flow (stale markers read as false). */
|
|
1815
1821
|
executing?: boolean;
|
|
1822
|
+
/** Short excerpt of the most recent user message, for thread-list rows. */
|
|
1823
|
+
last_message_preview?: string | null;
|
|
1816
1824
|
}
|
|
1817
1825
|
interface PendingSubagentAttachmentRef {
|
|
1818
1826
|
path: string;
|
|
@@ -2070,7 +2078,20 @@ declare class DurableAgentBuilder<Env extends AgentBuilderEnv = AgentBuilderEnv>
|
|
|
2070
2078
|
*/
|
|
2071
2079
|
recordThreadActivity(threadId: string, options?: {
|
|
2072
2080
|
executing?: boolean;
|
|
2081
|
+
messagePreview?: string | null;
|
|
2073
2082
|
}): Promise<void>;
|
|
2083
|
+
/**
|
|
2084
|
+
* Fill in previews for threads that predate preview tracking. Callers read
|
|
2085
|
+
* each thread's newest user message and stamp the results here in one batch.
|
|
2086
|
+
*
|
|
2087
|
+
* A thread with no user message is stamped with an empty string rather than
|
|
2088
|
+
* left NULL: NULL means "not looked at yet", so without the sentinel an
|
|
2089
|
+
* empty thread would be re-read on every list request forever.
|
|
2090
|
+
*/
|
|
2091
|
+
backfillThreadPreviews(entries: Array<{
|
|
2092
|
+
id: string;
|
|
2093
|
+
preview: string | null;
|
|
2094
|
+
}>): Promise<void>;
|
|
2074
2095
|
/**
|
|
2075
2096
|
* Delete a thread from the registry.
|
|
2076
2097
|
*/
|
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 migration50 of migrations) {
|
|
17794
|
+
if (migration50.version > fromVersion) {
|
|
17795
|
+
await migration50.up(this.ctx.storage.sql);
|
|
17796
17796
|
}
|
|
17797
17797
|
}
|
|
17798
17798
|
}
|
|
@@ -21192,12 +21192,15 @@ ${resultContent}${attachmentSummary}`;
|
|
|
21192
21192
|
* bookkeeping is presentation state: a failure here must never take down the
|
|
21193
21193
|
* turn that triggered it.
|
|
21194
21194
|
*/
|
|
21195
|
-
async recordRegistryActivity(threadId, executing) {
|
|
21195
|
+
async recordRegistryActivity(threadId, executing, messagePreview) {
|
|
21196
21196
|
try {
|
|
21197
21197
|
const namespace = this.env.AGENT_BUILDER;
|
|
21198
21198
|
if (!namespace || typeof namespace.idFromName !== "function") return;
|
|
21199
21199
|
const agentBuilder = namespace.get(namespace.idFromName("singleton"));
|
|
21200
|
-
await agentBuilder.recordThreadActivity?.(threadId, {
|
|
21200
|
+
await agentBuilder.recordThreadActivity?.(threadId, {
|
|
21201
|
+
executing,
|
|
21202
|
+
...messagePreview !== void 0 ? { messagePreview } : {}
|
|
21203
|
+
});
|
|
21201
21204
|
} catch (error) {
|
|
21202
21205
|
console.error(
|
|
21203
21206
|
"[DurableThread] Failed to record thread activity (non-fatal):",
|
|
@@ -21205,6 +21208,27 @@ ${resultContent}${attachmentSummary}`;
|
|
|
21205
21208
|
);
|
|
21206
21209
|
}
|
|
21207
21210
|
}
|
|
21211
|
+
/**
|
|
21212
|
+
* The newest non-empty user message on this thread, for thread-list previews.
|
|
21213
|
+
* Returns null when the thread has none. The Durable Object does not know its
|
|
21214
|
+
* own thread id, so the caller is the one that stamps the registry.
|
|
21215
|
+
*/
|
|
21216
|
+
async getLatestUserMessagePreview() {
|
|
21217
|
+
await this.ensureMigrated();
|
|
21218
|
+
try {
|
|
21219
|
+
const rows = this.ctx.storage.sql.exec(
|
|
21220
|
+
`SELECT content FROM messages
|
|
21221
|
+
WHERE role = 'user'
|
|
21222
|
+
AND content IS NOT NULL AND content != ''
|
|
21223
|
+
AND subagent_id IS NULL
|
|
21224
|
+
AND (silent IS NULL OR silent = 0)
|
|
21225
|
+
ORDER BY created_at DESC LIMIT 1`
|
|
21226
|
+
).toArray();
|
|
21227
|
+
return rows[0]?.content ?? null;
|
|
21228
|
+
} catch {
|
|
21229
|
+
return null;
|
|
21230
|
+
}
|
|
21231
|
+
}
|
|
21208
21232
|
/** Arm the standing watchdog for an execution start. One pending row max. */
|
|
21209
21233
|
async armExecutionWatchdog(threadId) {
|
|
21210
21234
|
try {
|
|
@@ -21788,7 +21812,11 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
|
|
|
21788
21812
|
this.isExecuting = true;
|
|
21789
21813
|
this.currentAbortController = new AbortController();
|
|
21790
21814
|
await this.armExecutionWatchdog(threadId);
|
|
21791
|
-
await this.recordRegistryActivity(
|
|
21815
|
+
await this.recordRegistryActivity(
|
|
21816
|
+
threadId,
|
|
21817
|
+
true,
|
|
21818
|
+
role === "user" ? content : void 0
|
|
21819
|
+
);
|
|
21792
21820
|
try {
|
|
21793
21821
|
const agentBuilderId = this.env.AGENT_BUILDER.idFromName("singleton");
|
|
21794
21822
|
const agentBuilder = this.env.AGENT_BUILDER.get(agentBuilderId);
|
|
@@ -23166,9 +23194,41 @@ var migration47 = {
|
|
|
23166
23194
|
}
|
|
23167
23195
|
};
|
|
23168
23196
|
|
|
23197
|
+
// src/durable-objects/agentbuilder-migrations/0014_thread_activity_scale.ts
|
|
23198
|
+
var migration48 = {
|
|
23199
|
+
version: 14,
|
|
23200
|
+
async up(sql) {
|
|
23201
|
+
sql.exec(`ALTER TABLE threads ADD COLUMN last_message_preview TEXT`);
|
|
23202
|
+
sql.exec(
|
|
23203
|
+
`CREATE INDEX IF NOT EXISTS idx_threads_executing_since
|
|
23204
|
+
ON threads(executing_since) WHERE executing_since IS NOT NULL`
|
|
23205
|
+
);
|
|
23206
|
+
sql.exec(
|
|
23207
|
+
`UPDATE threads SET last_activity_at = created_at WHERE last_activity_at IS NULL`
|
|
23208
|
+
);
|
|
23209
|
+
sql.exec(`
|
|
23210
|
+
INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '14')
|
|
23211
|
+
`);
|
|
23212
|
+
}
|
|
23213
|
+
};
|
|
23214
|
+
|
|
23215
|
+
// src/durable-objects/agentbuilder-migrations/0015_clear_envelope_previews.ts
|
|
23216
|
+
var migration49 = {
|
|
23217
|
+
version: 15,
|
|
23218
|
+
async up(sql) {
|
|
23219
|
+
sql.exec(
|
|
23220
|
+
`UPDATE threads SET last_message_preview = NULL
|
|
23221
|
+
WHERE last_message_preview LIKE 'Subagent (reference: %'`
|
|
23222
|
+
);
|
|
23223
|
+
sql.exec(`
|
|
23224
|
+
INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '15')
|
|
23225
|
+
`);
|
|
23226
|
+
}
|
|
23227
|
+
};
|
|
23228
|
+
|
|
23169
23229
|
// src/durable-objects/agentbuilder-migrations/index.ts
|
|
23170
|
-
var migrations2 = [migration35, migration36, migration37, migration38, migration39, migration40, migration41, migration42, migration43, migration44, migration45, migration46, migration47];
|
|
23171
|
-
var LATEST_SCHEMA_VERSION2 =
|
|
23230
|
+
var migrations2 = [migration35, migration36, migration37, migration38, migration39, migration40, migration41, migration42, migration43, migration44, migration45, migration46, migration47, migration48, migration49];
|
|
23231
|
+
var LATEST_SCHEMA_VERSION2 = 15;
|
|
23172
23232
|
|
|
23173
23233
|
// src/utils/crypto.ts
|
|
23174
23234
|
var CryptoUtil = class {
|
|
@@ -23368,6 +23428,13 @@ function parseStoredPermissions(value) {
|
|
|
23368
23428
|
}
|
|
23369
23429
|
}
|
|
23370
23430
|
var EXECUTING_STALE_AFTER_SECONDS = 15 * 60;
|
|
23431
|
+
var THREAD_PREVIEW_MAX_CHARS = 140;
|
|
23432
|
+
var isRuntimeSubagentEnvelope = (content) => /^Subagent \(reference: /.test(content.trimStart());
|
|
23433
|
+
var buildThreadPreview = (content) => {
|
|
23434
|
+
const collapsed = content.replace(/\s+/g, " ").trim();
|
|
23435
|
+
if (!collapsed) return null;
|
|
23436
|
+
return collapsed.length > THREAD_PREVIEW_MAX_CHARS ? `${collapsed.slice(0, THREAD_PREVIEW_MAX_CHARS - 1)}\u2026` : collapsed;
|
|
23437
|
+
};
|
|
23371
23438
|
var isThreadExecuting = (executingSince, nowSeconds) => executingSince != null && nowSeconds - executingSince < EXECUTING_STALE_AFTER_SECONDS;
|
|
23372
23439
|
var DurableAgentBuilder = class extends DurableObject {
|
|
23373
23440
|
migratedToVersion = null;
|
|
@@ -23937,9 +24004,9 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
23937
24004
|
}
|
|
23938
24005
|
}
|
|
23939
24006
|
async runMigrations(fromVersion) {
|
|
23940
|
-
for (const
|
|
23941
|
-
if (
|
|
23942
|
-
await
|
|
24007
|
+
for (const migration50 of migrations2) {
|
|
24008
|
+
if (migration50.version > fromVersion) {
|
|
24009
|
+
await migration50.up(this.ctx.storage.sql);
|
|
23943
24010
|
}
|
|
23944
24011
|
}
|
|
23945
24012
|
}
|
|
@@ -24064,7 +24131,7 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24064
24131
|
async getThread(id) {
|
|
24065
24132
|
await this.ensureMigrated();
|
|
24066
24133
|
const cursor = await this.ctx.storage.sql.exec(
|
|
24067
|
-
`SELECT id, agent_name, user_id, tags, env, tenvs, properties, parent, terminated, created_at, last_activity_at, executing_since FROM threads WHERE id = ?`,
|
|
24134
|
+
`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 = ?`,
|
|
24068
24135
|
id
|
|
24069
24136
|
);
|
|
24070
24137
|
const rows = cursor.toArray();
|
|
@@ -24091,7 +24158,8 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24091
24158
|
executing: isThreadExecuting(
|
|
24092
24159
|
row.executing_since,
|
|
24093
24160
|
Math.floor(Date.now() / 1e3)
|
|
24094
|
-
)
|
|
24161
|
+
),
|
|
24162
|
+
last_message_preview: row.last_message_preview
|
|
24095
24163
|
};
|
|
24096
24164
|
}
|
|
24097
24165
|
/**
|
|
@@ -24188,9 +24256,9 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24188
24256
|
const total = countCursor.one().count;
|
|
24189
24257
|
const limit = params?.limit ?? 100;
|
|
24190
24258
|
const offset = params?.offset ?? 0;
|
|
24191
|
-
const orderByClause = params?.sort === "created" ? "created_at DESC" : params?.sort === "oldest" ? "created_at ASC" : "
|
|
24259
|
+
const orderByClause = params?.sort === "created" ? "created_at DESC" : params?.sort === "oldest" ? "created_at ASC" : "last_activity_at DESC, created_at DESC";
|
|
24192
24260
|
const cursor = await this.ctx.storage.sql.exec(
|
|
24193
|
-
`SELECT id, agent_name, user_id, tags, properties, parent, terminated, created_at, last_activity_at, executing_since FROM threads
|
|
24261
|
+
`SELECT id, agent_name, user_id, tags, properties, parent, terminated, created_at, last_activity_at, executing_since, last_message_preview FROM threads
|
|
24194
24262
|
${whereClause}
|
|
24195
24263
|
ORDER BY ${orderByClause}
|
|
24196
24264
|
LIMIT ? OFFSET ?`,
|
|
@@ -24214,7 +24282,8 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24214
24282
|
terminated: row.terminated,
|
|
24215
24283
|
created_at: row.created_at,
|
|
24216
24284
|
last_activity_at: row.last_activity_at ?? row.created_at,
|
|
24217
|
-
executing: isThreadExecuting(row.executing_since, nowSeconds)
|
|
24285
|
+
executing: isThreadExecuting(row.executing_since, nowSeconds),
|
|
24286
|
+
last_message_preview: row.last_message_preview
|
|
24218
24287
|
}));
|
|
24219
24288
|
return { threads, total };
|
|
24220
24289
|
}
|
|
@@ -24253,6 +24322,7 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24253
24322
|
await this.ensureMigrated();
|
|
24254
24323
|
const now = Math.floor(Date.now() / 1e3);
|
|
24255
24324
|
const executing = options?.executing;
|
|
24325
|
+
const preview = typeof options?.messagePreview === "string" && !isRuntimeSubagentEnvelope(options.messagePreview) ? buildThreadPreview(options.messagePreview) : void 0;
|
|
24256
24326
|
await this.ctx.storage.sql.exec(
|
|
24257
24327
|
`UPDATE threads
|
|
24258
24328
|
SET last_activity_at = ?
|
|
@@ -24279,13 +24349,41 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
24279
24349
|
threadId
|
|
24280
24350
|
);
|
|
24281
24351
|
}
|
|
24352
|
+
if (preview !== void 0) {
|
|
24353
|
+
await this.ctx.storage.sql.exec(
|
|
24354
|
+
`UPDATE threads SET last_message_preview = ? WHERE id = ?`,
|
|
24355
|
+
preview,
|
|
24356
|
+
threadId
|
|
24357
|
+
);
|
|
24358
|
+
}
|
|
24282
24359
|
this.broadcastEvent({
|
|
24283
24360
|
type: "thread_activity",
|
|
24284
24361
|
threadId,
|
|
24285
24362
|
last_activity_at: now,
|
|
24286
|
-
executing: executing === true
|
|
24363
|
+
executing: executing === true,
|
|
24364
|
+
...preview !== void 0 ? { last_message_preview: preview } : {}
|
|
24287
24365
|
});
|
|
24288
24366
|
}
|
|
24367
|
+
/**
|
|
24368
|
+
* Fill in previews for threads that predate preview tracking. Callers read
|
|
24369
|
+
* each thread's newest user message and stamp the results here in one batch.
|
|
24370
|
+
*
|
|
24371
|
+
* A thread with no user message is stamped with an empty string rather than
|
|
24372
|
+
* left NULL: NULL means "not looked at yet", so without the sentinel an
|
|
24373
|
+
* empty thread would be re-read on every list request forever.
|
|
24374
|
+
*/
|
|
24375
|
+
async backfillThreadPreviews(entries) {
|
|
24376
|
+
if (entries.length === 0) return;
|
|
24377
|
+
await this.ensureMigrated();
|
|
24378
|
+
for (const entry of entries) {
|
|
24379
|
+
const preview = typeof entry.preview === "string" && !isRuntimeSubagentEnvelope(entry.preview) ? buildThreadPreview(entry.preview) ?? "" : "";
|
|
24380
|
+
await this.ctx.storage.sql.exec(
|
|
24381
|
+
`UPDATE threads SET last_message_preview = ? WHERE id = ? AND last_message_preview IS NULL`,
|
|
24382
|
+
preview,
|
|
24383
|
+
entry.id
|
|
24384
|
+
);
|
|
24385
|
+
}
|
|
24386
|
+
}
|
|
24289
24387
|
/**
|
|
24290
24388
|
* Delete a thread from the registry.
|
|
24291
24389
|
*/
|