neoctl 0.2.35 → 0.2.36
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/agents/agent-tool-persistence.test.d.ts +1 -0
- package/dist/agents/agent-tool-persistence.test.js +313 -0
- package/dist/agents/agent-tool-persistence.test.js.map +1 -0
- package/dist/agents/agent-tool.js +137 -60
- package/dist/agents/agent-tool.js.map +1 -1
- package/dist/agents/local-agent-task.d.ts +41 -0
- package/dist/agents/local-agent-task.js +3 -0
- package/dist/agents/local-agent-task.js.map +1 -1
- package/dist/agents/no-nested-delegation.test.d.ts +1 -0
- package/dist/agents/no-nested-delegation.test.js +38 -0
- package/dist/agents/no-nested-delegation.test.js.map +1 -0
- package/dist/agents/smoke-agent-lifecycle.d.ts +1 -0
- package/dist/agents/smoke-agent-lifecycle.js +188 -0
- package/dist/agents/smoke-agent-lifecycle.js.map +1 -0
- package/dist/core/query-engine.js +1 -1
- package/dist/core/query-engine.js.map +1 -1
- package/dist/core/query.d.ts +3 -1
- package/dist/core/query.js +16 -3
- package/dist/core/query.js.map +1 -1
- package/dist/core/run-agent-pause.test.d.ts +1 -0
- package/dist/core/run-agent-pause.test.js +52 -0
- package/dist/core/run-agent-pause.test.js.map +1 -0
- package/dist/core/run-agent-persistence.test.d.ts +1 -0
- package/dist/core/run-agent-persistence.test.js +222 -0
- package/dist/core/run-agent-persistence.test.js.map +1 -0
- package/dist/core/run-agent.d.ts +11 -0
- package/dist/core/run-agent.js +56 -11
- package/dist/core/run-agent.js.map +1 -1
- package/dist/core/smoke-core-loop.js +8 -7
- package/dist/core/smoke-core-loop.js.map +1 -1
- package/dist/model/model-metadata.json +99 -99
- package/dist/repl/index.js +20 -26
- package/dist/repl/index.js.map +1 -1
- package/dist/session/session-store-safety.test.d.ts +1 -0
- package/dist/session/session-store-safety.test.js +107 -0
- package/dist/session/session-store-safety.test.js.map +1 -0
- package/dist/session/session-store.d.ts +1 -0
- package/dist/session/session-store.js +64 -5
- package/dist/session/session-store.js.map +1 -1
- package/dist/session/tool-result-memory.d.ts +3 -1
- package/dist/session/tool-result-memory.js.map +1 -1
- package/dist/tasks/subagent-tools.d.ts +4 -1
- package/dist/tasks/subagent-tools.js +85 -24
- package/dist/tasks/subagent-tools.js.map +1 -1
- package/dist/tasks/subagent-tools.test.d.ts +1 -0
- package/dist/tasks/subagent-tools.test.js +158 -0
- package/dist/tasks/subagent-tools.test.js.map +1 -0
- package/dist/tasks/task-ack-size.test.d.ts +1 -0
- package/dist/tasks/task-ack-size.test.js +100 -0
- package/dist/tasks/task-ack-size.test.js.map +1 -0
- package/dist/tasks/task-persistence.d.ts +22 -0
- package/dist/tasks/task-persistence.js +194 -0
- package/dist/tasks/task-persistence.js.map +1 -0
- package/dist/tasks/task-persistence.test.d.ts +1 -0
- package/dist/tasks/task-persistence.test.js +331 -0
- package/dist/tasks/task-persistence.test.js.map +1 -0
- package/dist/tasks/task-store.d.ts +45 -3
- package/dist/tasks/task-store.js +292 -16
- package/dist/tasks/task-store.js.map +1 -1
- package/dist/tools/tool.d.ts +5 -0
- package/dist/tools/tool.js.map +1 -1
- package/dist/web/index.d.ts +99 -6
- package/dist/web/index.js +93 -56
- package/dist/web/index.js.map +1 -1
- package/dist/web/smoke-task-session-entrypoints.d.ts +1 -0
- package/dist/web/smoke-task-session-entrypoints.js +75 -0
- package/dist/web/smoke-task-session-entrypoints.js.map +1 -0
- package/dist/web/smoke-web-agent-tasks.d.ts +1 -0
- package/dist/web/smoke-web-agent-tasks.js +50 -0
- package/dist/web/smoke-web-agent-tasks.js.map +1 -0
- package/package.json +4 -4
package/dist/web/index.d.ts
CHANGED
|
@@ -6,11 +6,12 @@ import { type ModelProviderName } from "../model/config.js";
|
|
|
6
6
|
import { CommunicationLogger, LoggingModelGateway } from "../model/communication-logger.js";
|
|
7
7
|
import type { ModelUsage, ReasoningConfig } from "../model/model-gateway.js";
|
|
8
8
|
import { ToolRegistry } from "../tools/registry.js";
|
|
9
|
-
import type { Tool } from "../tools/tool.js";
|
|
9
|
+
import type { Tool, ToolUseContext } from "../tools/tool.js";
|
|
10
10
|
import { type ToolPresentation } from "../tools/tool-catalog.js";
|
|
11
11
|
import { ExecProcessManager } from "../tools/builtins/exec-process-manager.js";
|
|
12
12
|
import { type AgentToolRuntime } from "../agents/agent-tool.js";
|
|
13
13
|
import { TaskStore } from "../tasks/task-store.js";
|
|
14
|
+
import type { TaskNotificationSource } from "../core/query.js";
|
|
14
15
|
import type { CompactionReport } from "../context/compaction.js";
|
|
15
16
|
import type { PromptSection } from "../context/prompts.js";
|
|
16
17
|
import type { NeoPluginResource } from "../plugins/plugin-system.js";
|
|
@@ -302,6 +303,11 @@ type WebLineOperation = {
|
|
|
302
303
|
};
|
|
303
304
|
export declare function runWebServer(argv?: string[], runtimeOptions?: RunWebServerOptions): Promise<void>;
|
|
304
305
|
export declare function createWebRuntime(options?: CreateWebRuntimeOptions): Promise<WebRuntime>;
|
|
306
|
+
/** Bind only the foreground view; never stop work owned by another session. */
|
|
307
|
+
export declare function activateSession(runtime: Pick<WebRuntime, "engine" | "taskStore">): void;
|
|
308
|
+
export declare function sessionAgentTasks(runtime: Pick<WebRuntime, "engine" | "taskStore">): import("../index.js").LocalAgentTask[];
|
|
309
|
+
export declare function createResumeParentContext(engine: QueryEngine, tools: ToolUseContext["tools"], cwd?: string): ToolUseContext;
|
|
310
|
+
export declare function createTaskNotificationSource(taskStore: TaskStore): TaskNotificationSource;
|
|
305
311
|
export declare class WebRuntimeRouter {
|
|
306
312
|
private readonly repls;
|
|
307
313
|
private readonly createRuntime;
|
|
@@ -358,7 +364,6 @@ export declare class WebRepl {
|
|
|
358
364
|
private pendingUserImageEchoMessageId;
|
|
359
365
|
private runtimeContextRevision;
|
|
360
366
|
private runtimeContextPublishQueue;
|
|
361
|
-
private pendingRuntimeConfiguration;
|
|
362
367
|
private readonly backgroundSessionRuns;
|
|
363
368
|
private readonly suppressReattachedStreaming;
|
|
364
369
|
constructor(runtime: WebRuntime);
|
|
@@ -379,11 +384,48 @@ export declare class WebRepl {
|
|
|
379
384
|
type: import("../index.js").LocalAgentTaskType;
|
|
380
385
|
status: import("../index.js").LocalAgentTaskStatus;
|
|
381
386
|
description: string;
|
|
382
|
-
|
|
383
|
-
progress:
|
|
384
|
-
|
|
387
|
+
runGeneration: number;
|
|
388
|
+
progress: {
|
|
389
|
+
lastActivity: string | undefined;
|
|
390
|
+
currentAction: string | undefined;
|
|
391
|
+
totalToolUseCount: number;
|
|
392
|
+
steps: {
|
|
393
|
+
id: string;
|
|
394
|
+
title: string;
|
|
395
|
+
status: "completed" | "running" | "failed";
|
|
396
|
+
}[] | undefined;
|
|
397
|
+
};
|
|
398
|
+
pendingMessageCount: number;
|
|
399
|
+
deliveredRetainedThisRun: number | undefined;
|
|
400
|
+
messageReceipts: {
|
|
401
|
+
id: string;
|
|
402
|
+
status: "queued" | "delivered";
|
|
403
|
+
queuedAt: string;
|
|
404
|
+
deliveredAt: string | undefined;
|
|
405
|
+
runGeneration: number;
|
|
406
|
+
}[];
|
|
407
|
+
result: {
|
|
408
|
+
content: string;
|
|
409
|
+
truncated: boolean;
|
|
410
|
+
status: "completed" | "incomplete" | undefined;
|
|
411
|
+
} | undefined;
|
|
412
|
+
error: string | undefined;
|
|
413
|
+
errorTruncated: boolean;
|
|
414
|
+
runHistory: {
|
|
415
|
+
runGeneration: number;
|
|
416
|
+
status: import("../index.js").LocalAgentTaskStatus;
|
|
417
|
+
completedAt: string | undefined;
|
|
418
|
+
result: {
|
|
419
|
+
content: string;
|
|
420
|
+
truncated: boolean;
|
|
421
|
+
status: "completed" | "incomplete" | undefined;
|
|
422
|
+
} | undefined;
|
|
423
|
+
error: string | undefined;
|
|
424
|
+
errorTruncated: boolean;
|
|
425
|
+
}[];
|
|
385
426
|
createdAt: string;
|
|
386
427
|
updatedAt: string;
|
|
428
|
+
completedAt: string | undefined;
|
|
387
429
|
} | {
|
|
388
430
|
kind: "terminal";
|
|
389
431
|
taskId: string;
|
|
@@ -409,6 +451,57 @@ export declare class WebRepl {
|
|
|
409
451
|
createdAt: number;
|
|
410
452
|
sessionId: string;
|
|
411
453
|
})[];
|
|
454
|
+
agentTaskHistory: {
|
|
455
|
+
kind: "agent";
|
|
456
|
+
taskId: string;
|
|
457
|
+
agentId: string;
|
|
458
|
+
agentType: string | undefined;
|
|
459
|
+
type: import("../index.js").LocalAgentTaskType;
|
|
460
|
+
status: import("../index.js").LocalAgentTaskStatus;
|
|
461
|
+
description: string;
|
|
462
|
+
runGeneration: number;
|
|
463
|
+
progress: {
|
|
464
|
+
lastActivity: string | undefined;
|
|
465
|
+
currentAction: string | undefined;
|
|
466
|
+
totalToolUseCount: number;
|
|
467
|
+
steps: {
|
|
468
|
+
id: string;
|
|
469
|
+
title: string;
|
|
470
|
+
status: "completed" | "running" | "failed";
|
|
471
|
+
}[] | undefined;
|
|
472
|
+
};
|
|
473
|
+
pendingMessageCount: number;
|
|
474
|
+
deliveredRetainedThisRun: number | undefined;
|
|
475
|
+
messageReceipts: {
|
|
476
|
+
id: string;
|
|
477
|
+
status: "queued" | "delivered";
|
|
478
|
+
queuedAt: string;
|
|
479
|
+
deliveredAt: string | undefined;
|
|
480
|
+
runGeneration: number;
|
|
481
|
+
}[];
|
|
482
|
+
result: {
|
|
483
|
+
content: string;
|
|
484
|
+
truncated: boolean;
|
|
485
|
+
status: "completed" | "incomplete" | undefined;
|
|
486
|
+
} | undefined;
|
|
487
|
+
error: string | undefined;
|
|
488
|
+
errorTruncated: boolean;
|
|
489
|
+
runHistory: {
|
|
490
|
+
runGeneration: number;
|
|
491
|
+
status: import("../index.js").LocalAgentTaskStatus;
|
|
492
|
+
completedAt: string | undefined;
|
|
493
|
+
result: {
|
|
494
|
+
content: string;
|
|
495
|
+
truncated: boolean;
|
|
496
|
+
status: "completed" | "incomplete" | undefined;
|
|
497
|
+
} | undefined;
|
|
498
|
+
error: string | undefined;
|
|
499
|
+
errorTruncated: boolean;
|
|
500
|
+
}[];
|
|
501
|
+
createdAt: string;
|
|
502
|
+
updatedAt: string;
|
|
503
|
+
completedAt: string | undefined;
|
|
504
|
+
}[];
|
|
412
505
|
backgroundSessionRunCount: number;
|
|
413
506
|
runningSessionIds: string[];
|
|
414
507
|
session: import("../index.js").SessionStoreSnapshot | undefined;
|
|
@@ -480,7 +573,6 @@ export declare class WebRepl {
|
|
|
480
573
|
private parseToolModes;
|
|
481
574
|
private applySessionToolOverrides;
|
|
482
575
|
private syncPluginToolRegistration;
|
|
483
|
-
private applyRuntimeConfiguration;
|
|
484
576
|
private refreshToolConfiguration;
|
|
485
577
|
private applySessionPluginOverrides;
|
|
486
578
|
submit(text: string, attachments?: WebAttachmentPayload[]): Promise<{
|
|
@@ -545,6 +637,7 @@ export declare class WebRepl {
|
|
|
545
637
|
private setStatus;
|
|
546
638
|
private finalizeForegroundView;
|
|
547
639
|
private stopForegroundRun;
|
|
640
|
+
private agentTaskSnapshot;
|
|
548
641
|
private backgroundTasks;
|
|
549
642
|
private detachRunningForeground;
|
|
550
643
|
private reattachRunningSession;
|
package/dist/web/index.js
CHANGED
|
@@ -167,14 +167,10 @@ export async function createWebRuntime(options = {}) {
|
|
|
167
167
|
tools.register(tool);
|
|
168
168
|
const agentRuntime = { modelGateway, tools, taskStore };
|
|
169
169
|
registerTool(createAgentTool(agentRuntime), { source: "builtin" });
|
|
170
|
+
let runtime;
|
|
170
171
|
const resumeHandler = async (taskId, directive) => {
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
tools,
|
|
174
|
-
appState: new InMemoryAppState("main", options.cwd),
|
|
175
|
-
emit: () => undefined,
|
|
176
|
-
};
|
|
177
|
-
return resumeAgentTask(taskId, directive, agentRuntime, taskStore, dummyContext);
|
|
172
|
+
const parentContext = createResumeParentContext(runtime.engine, tools, options.cwd);
|
|
173
|
+
return resumeAgentTask(taskId, directive, agentRuntime, taskStore, parentContext);
|
|
178
174
|
};
|
|
179
175
|
for (const tool of createSubagentTools(taskStore, resumeHandler))
|
|
180
176
|
registerTool(tool, { source: "builtin" });
|
|
@@ -210,8 +206,9 @@ export async function createWebRuntime(options = {}) {
|
|
|
210
206
|
},
|
|
211
207
|
});
|
|
212
208
|
await engine.initialize();
|
|
209
|
+
activateSession({ engine, taskStore });
|
|
213
210
|
const initialMetrics = await engine.contextMetrics();
|
|
214
|
-
|
|
211
|
+
runtime = {
|
|
215
212
|
engine,
|
|
216
213
|
appPromptStore,
|
|
217
214
|
communicationLogger,
|
|
@@ -242,6 +239,7 @@ export async function createWebRuntime(options = {}) {
|
|
|
242
239
|
resolveSession: options.resolveSessionToolOverrides,
|
|
243
240
|
},
|
|
244
241
|
};
|
|
242
|
+
return runtime;
|
|
245
243
|
}
|
|
246
244
|
function normalizeWebRuntimePlugins(value) {
|
|
247
245
|
if (!Array.isArray(value))
|
|
@@ -274,10 +272,38 @@ function applyToolOverrides(registry, catalog, globalOverrides, sessionOverrides
|
|
|
274
272
|
for (const tool of catalog)
|
|
275
273
|
registry.setEnabled(tool.name, sessionOverrides[tool.name] ?? globalOverrides[tool.name] ?? true);
|
|
276
274
|
}
|
|
277
|
-
|
|
275
|
+
/** Bind only the foreground view; never stop work owned by another session. */
|
|
276
|
+
export function activateSession(runtime) {
|
|
277
|
+
runtime.taskStore.bindSession?.(runtime.engine.snapshot().session?.sessionDir || undefined);
|
|
278
|
+
}
|
|
279
|
+
export function sessionAgentTasks(runtime) {
|
|
280
|
+
const dir = runtime.engine.snapshot().session?.sessionDir || undefined;
|
|
281
|
+
// Older embedders provide minimal TaskStore mocks with no persistence API.
|
|
282
|
+
return runtime.taskStore.list().filter((task) => !runtime.taskStore.bindSession
|
|
283
|
+
|| task.ownerSessionDir === (dir ? path.resolve(dir) : undefined));
|
|
284
|
+
}
|
|
285
|
+
export function createResumeParentContext(engine, tools, cwd) {
|
|
286
|
+
const snapshot = engine.snapshot();
|
|
287
|
+
const session = snapshot.session;
|
|
288
|
+
return {
|
|
289
|
+
agentId: snapshot.agentId ?? "main",
|
|
290
|
+
tools,
|
|
291
|
+
appState: new InMemoryAppState(snapshot.agentId ?? "main", cwd),
|
|
292
|
+
session: session?.sessionDir ? {
|
|
293
|
+
sessionId: session.sessionId,
|
|
294
|
+
sessionDir: session.sessionDir,
|
|
295
|
+
rootDir: path.dirname(session.sessionDir),
|
|
296
|
+
} : undefined,
|
|
297
|
+
options: { mainLoopModel: snapshot.model, reasoning: snapshot.reasoning,
|
|
298
|
+
contextWindowTokensOverride: snapshot.contextWindowTokensOverride },
|
|
299
|
+
emit: () => undefined,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
export function createTaskNotificationSource(taskStore) {
|
|
278
303
|
return {
|
|
279
|
-
collectUnnotifiedCompletions() {
|
|
280
|
-
return taskStore.collectUnnotifiedCompletions().
|
|
304
|
+
collectUnnotifiedCompletions(sessionDir) {
|
|
305
|
+
return taskStore.collectUnnotifiedCompletions(sessionDir).filter((task) => !taskStore.bindSession
|
|
306
|
+
|| task.ownerSessionDir === (sessionDir ? path.resolve(sessionDir) : undefined)).map((task) => ({
|
|
281
307
|
taskId: task.taskId,
|
|
282
308
|
agentId: task.agentId,
|
|
283
309
|
status: task.status,
|
|
@@ -389,7 +415,6 @@ export class WebRepl {
|
|
|
389
415
|
pendingUserImageEchoMessageId;
|
|
390
416
|
runtimeContextRevision = 0;
|
|
391
417
|
runtimeContextPublishQueue = Promise.resolve();
|
|
392
|
-
pendingRuntimeConfiguration = false;
|
|
393
418
|
backgroundSessionRuns = new Map();
|
|
394
419
|
suppressReattachedStreaming = new Set();
|
|
395
420
|
constructor(runtime) {
|
|
@@ -442,6 +467,7 @@ export class WebRepl {
|
|
|
442
467
|
queuedInput: this.queuedInput,
|
|
443
468
|
backgroundTaskCount: backgroundTasks.length,
|
|
444
469
|
backgroundTasks,
|
|
470
|
+
agentTaskHistory: sessionAgentTasks(this.runtime).filter((task) => this.runtime.taskStore.isTerminal(task)).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)).slice(0, 20).map((task) => this.agentTaskSnapshot(task)),
|
|
445
471
|
backgroundSessionRunCount: this.backgroundSessionRuns.size,
|
|
446
472
|
runningSessionIds: [...this.backgroundSessionRuns.keys()],
|
|
447
473
|
session: this.runtime.engine.snapshot().session,
|
|
@@ -514,6 +540,8 @@ export class WebRepl {
|
|
|
514
540
|
};
|
|
515
541
|
}
|
|
516
542
|
async setGlobalTools(value) {
|
|
543
|
+
if (this.busy)
|
|
544
|
+
return actionFailure("TOOL_UPDATE_BLOCKED", "cannot change global tools while a response is running");
|
|
517
545
|
if (!isRecord(value))
|
|
518
546
|
return actionFailure("INVALID_REQUEST", "tool overrides must be an object");
|
|
519
547
|
const support = this.runtime.toolSupport;
|
|
@@ -524,12 +552,10 @@ export class WebRepl {
|
|
|
524
552
|
return normalized;
|
|
525
553
|
try {
|
|
526
554
|
support.globalOverrides = normalized.value;
|
|
555
|
+
this.syncPluginToolRegistration();
|
|
556
|
+
applyToolOverrides(this.runtime.tools, support.catalog, support.globalOverrides, support.sessionOverrides);
|
|
527
557
|
if (support.persistGlobal)
|
|
528
558
|
await support.persistGlobal(support.globalOverrides);
|
|
529
|
-
if (this.busy)
|
|
530
|
-
this.pendingRuntimeConfiguration = true;
|
|
531
|
-
else
|
|
532
|
-
await this.applyRuntimeConfiguration();
|
|
533
559
|
await this.refreshToolConfiguration();
|
|
534
560
|
return { ok: true, state: this.globalTools() };
|
|
535
561
|
}
|
|
@@ -538,6 +564,8 @@ export class WebRepl {
|
|
|
538
564
|
}
|
|
539
565
|
}
|
|
540
566
|
async setSessionTools(value) {
|
|
567
|
+
if (this.busy)
|
|
568
|
+
return actionFailure("TOOL_UPDATE_BLOCKED", "cannot change session tools while a response is running");
|
|
541
569
|
if (!isRecord(value))
|
|
542
570
|
return actionFailure("INVALID_REQUEST", "tool overrides must be an object");
|
|
543
571
|
const support = this.runtime.toolSupport;
|
|
@@ -561,6 +589,8 @@ export class WebRepl {
|
|
|
561
589
|
await this.applySessionToolOverrides(await support.resolveSession(sessionId), false);
|
|
562
590
|
}
|
|
563
591
|
async setSessionPlugins(value) {
|
|
592
|
+
if (this.busy)
|
|
593
|
+
return actionFailure("PLUGIN_UPDATE_BLOCKED", "cannot change session plugins while a response is running");
|
|
564
594
|
if (!isRecord(value))
|
|
565
595
|
return actionFailure("INVALID_REQUEST", "plugin overrides must be an object");
|
|
566
596
|
const support = this.runtime.pluginSupport;
|
|
@@ -624,13 +654,11 @@ export class WebRepl {
|
|
|
624
654
|
if (!support)
|
|
625
655
|
return;
|
|
626
656
|
support.sessionOverrides = normalizeToolOverrides(overrides, support.catalog);
|
|
657
|
+
this.syncPluginToolRegistration();
|
|
658
|
+
applyToolOverrides(this.runtime.tools, support.catalog, support.globalOverrides, support.sessionOverrides);
|
|
627
659
|
const sessionId = this.runtime.engine.snapshot().session?.sessionId;
|
|
628
660
|
if (persist && sessionId && support.persistSession)
|
|
629
661
|
await support.persistSession(sessionId, support.sessionOverrides);
|
|
630
|
-
if (this.busy)
|
|
631
|
-
this.pendingRuntimeConfiguration = true;
|
|
632
|
-
else
|
|
633
|
-
await this.applyRuntimeConfiguration();
|
|
634
662
|
await this.refreshToolConfiguration();
|
|
635
663
|
}
|
|
636
664
|
syncPluginToolRegistration() {
|
|
@@ -645,18 +673,6 @@ export class WebRepl {
|
|
|
645
673
|
this.runtime.tools.register(tool);
|
|
646
674
|
}
|
|
647
675
|
}
|
|
648
|
-
async applyRuntimeConfiguration() {
|
|
649
|
-
this.syncPluginToolRegistration();
|
|
650
|
-
const pluginSupport = this.runtime.pluginSupport;
|
|
651
|
-
if (pluginSupport) {
|
|
652
|
-
const activePlugins = activeWebRuntimePlugins(pluginSupport.catalog, pluginSupport.overrides);
|
|
653
|
-
this.runtime.engine.setRuntimePlugins([...pluginSupport.basePluginIds, ...activePlugins.map((plugin) => plugin.id)], [...pluginSupport.basePromptSections, ...activePlugins.flatMap((plugin) => plugin.promptSections ?? [])]);
|
|
654
|
-
}
|
|
655
|
-
const toolSupport = this.runtime.toolSupport;
|
|
656
|
-
if (toolSupport)
|
|
657
|
-
applyToolOverrides(this.runtime.tools, toolSupport.catalog, toolSupport.globalOverrides, toolSupport.sessionOverrides);
|
|
658
|
-
this.pendingRuntimeConfiguration = false;
|
|
659
|
-
}
|
|
660
676
|
async refreshToolConfiguration() {
|
|
661
677
|
const metrics = await this.runtime.engine.contextMetrics();
|
|
662
678
|
this.runtime.initialMetrics = metrics;
|
|
@@ -669,14 +685,21 @@ export class WebRepl {
|
|
|
669
685
|
if (!support)
|
|
670
686
|
return;
|
|
671
687
|
const normalized = normalizePluginOverrides(overrides, support.catalog);
|
|
688
|
+
for (const plugin of support.catalog)
|
|
689
|
+
for (const tool of plugin.tools)
|
|
690
|
+
this.runtime.tools.unregister(tool.name);
|
|
691
|
+
const activePlugins = activeWebRuntimePlugins(support.catalog, normalized);
|
|
692
|
+
for (const plugin of activePlugins)
|
|
693
|
+
for (const tool of plugin.tools)
|
|
694
|
+
this.runtime.tools.register(tool);
|
|
672
695
|
support.overrides = normalized;
|
|
696
|
+
const toolSupport = this.runtime.toolSupport;
|
|
697
|
+
if (toolSupport)
|
|
698
|
+
applyToolOverrides(this.runtime.tools, toolSupport.catalog, toolSupport.globalOverrides, toolSupport.sessionOverrides);
|
|
699
|
+
this.runtime.engine.setRuntimePlugins([...support.basePluginIds, ...activePlugins.map((plugin) => plugin.id)], [...support.basePromptSections, ...activePlugins.flatMap((plugin) => plugin.promptSections ?? [])]);
|
|
673
700
|
const sessionId = this.runtime.engine.snapshot().session?.sessionId;
|
|
674
701
|
if (persist && sessionId && support.persist)
|
|
675
702
|
await support.persist(sessionId, normalized);
|
|
676
|
-
if (this.busy)
|
|
677
|
-
this.pendingRuntimeConfiguration = true;
|
|
678
|
-
else
|
|
679
|
-
await this.applyRuntimeConfiguration();
|
|
680
703
|
const metrics = await this.runtime.engine.contextMetrics();
|
|
681
704
|
this.runtime.initialMetrics = metrics;
|
|
682
705
|
this.setStatus({ ...this.status, metrics, activityTick: this.status.activityTick + 1 });
|
|
@@ -727,11 +750,7 @@ export class WebRepl {
|
|
|
727
750
|
this.queuedAttachments = [...(this.queuedAttachments ?? []), ...attachments].slice(0, 20);
|
|
728
751
|
}
|
|
729
752
|
startRun(text, attachments = []) {
|
|
730
|
-
const run = (
|
|
731
|
-
if (this.pendingRuntimeConfiguration)
|
|
732
|
-
await this.applyRuntimeConfiguration();
|
|
733
|
-
await this.handleCommandOrPrompt(text, attachments);
|
|
734
|
-
})().catch((error) => {
|
|
753
|
+
const run = this.handleCommandOrPrompt(text, attachments).catch((error) => {
|
|
735
754
|
this.append({ kind: "error", text: error instanceof Error ? error.message : String(error) });
|
|
736
755
|
this.setBusy(false);
|
|
737
756
|
this.setStatus({ ...this.status, phase: "ready", detail: undefined });
|
|
@@ -759,6 +778,7 @@ export class WebRepl {
|
|
|
759
778
|
await this.detachRunningForeground("session switch");
|
|
760
779
|
this.runtime.engine = this.runtime.engine.forkForSession(sessionId, true);
|
|
761
780
|
await this.runtime.engine.initialize();
|
|
781
|
+
activateSession(this.runtime);
|
|
762
782
|
const snapshot = this.runtime.engine.snapshot().session;
|
|
763
783
|
if (!snapshot)
|
|
764
784
|
throw new Error("session transcripts are disabled");
|
|
@@ -776,6 +796,7 @@ export class WebRepl {
|
|
|
776
796
|
await this.detachRunningForeground("new session");
|
|
777
797
|
this.runtime.engine = this.runtime.engine.forkForSession(undefined, false);
|
|
778
798
|
await this.runtime.engine.initialize();
|
|
799
|
+
activateSession(this.runtime);
|
|
779
800
|
const snapshot = this.runtime.engine.snapshot().session;
|
|
780
801
|
if (!snapshot)
|
|
781
802
|
throw new Error("session transcripts are disabled");
|
|
@@ -892,6 +913,8 @@ export class WebRepl {
|
|
|
892
913
|
}
|
|
893
914
|
}
|
|
894
915
|
async setContextWindowK(value) {
|
|
916
|
+
if (this.busy)
|
|
917
|
+
return actionFailure("CONTEXT_WINDOW_UPDATE_BLOCKED", "cannot change context window while a response is running");
|
|
895
918
|
if (typeof value !== "string" || !/^\d+$/u.test(value) || Number(value) <= 0) {
|
|
896
919
|
return actionFailure("CONTEXT_WINDOW_INVALID", "context window must be a positive integer in k");
|
|
897
920
|
}
|
|
@@ -1017,23 +1040,28 @@ export class WebRepl {
|
|
|
1017
1040
|
this.broadcastSync();
|
|
1018
1041
|
return runWasActive;
|
|
1019
1042
|
}
|
|
1043
|
+
agentTaskSnapshot(task) {
|
|
1044
|
+
const terminal = this.runtime.taskStore.isTerminal(task);
|
|
1045
|
+
const result = (value, limit = 1500) => value ? { content: value.content.slice(0, limit), truncated: value.content.length > limit, status: value.status } : undefined;
|
|
1046
|
+
return {
|
|
1047
|
+
kind: "agent", taskId: task.taskId, agentId: task.agentId,
|
|
1048
|
+
agentType: task.agentType, type: task.type, status: task.status,
|
|
1049
|
+
description: task.description, runGeneration: task.runGeneration ?? 1,
|
|
1050
|
+
progress: { lastActivity: task.progress.lastActivity, currentAction: task.progress.currentAction, totalToolUseCount: task.progress.totalToolUseCount, steps: task.progress.steps?.slice(-8).map((step) => ({ id: step.id, title: step.title, status: step.status })) },
|
|
1051
|
+
pendingMessageCount: task.pendingMessages.length,
|
|
1052
|
+
deliveredRetainedThisRun: task.messageReceipts?.filter((receipt) => receipt.status === "delivered" && receipt.runGeneration === task.runGeneration).length,
|
|
1053
|
+
messageReceipts: (task.messageReceipts ?? []).slice(-20).map(({ id, status, queuedAt, deliveredAt, runGeneration }) => ({ id, status, queuedAt, deliveredAt, runGeneration })),
|
|
1054
|
+
result: terminal ? result(task.result) : undefined,
|
|
1055
|
+
error: terminal ? task.error?.slice(0, 1500) : undefined,
|
|
1056
|
+
errorTruncated: terminal && (task.error?.length ?? 0) > 1500,
|
|
1057
|
+
runHistory: (task.runHistory ?? []).slice(-3).map((run) => ({ runGeneration: run.runGeneration, status: run.status, completedAt: run.completedAt, result: result(run.result, 600), error: run.error?.slice(0, 600), errorTruncated: (run.error?.length ?? 0) > 600 })),
|
|
1058
|
+
createdAt: task.createdAt, updatedAt: task.updatedAt, completedAt: task.completedAt,
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1020
1061
|
backgroundTasks() {
|
|
1021
|
-
const agentTasks = this.runtime
|
|
1062
|
+
const agentTasks = sessionAgentTasks(this.runtime)
|
|
1022
1063
|
.filter((task) => !this.runtime.taskStore.isTerminal(task))
|
|
1023
|
-
.map((task) => (
|
|
1024
|
-
kind: "agent",
|
|
1025
|
-
taskId: task.taskId,
|
|
1026
|
-
agentId: task.agentId,
|
|
1027
|
-
agentType: task.agentType,
|
|
1028
|
-
type: task.type,
|
|
1029
|
-
status: task.status,
|
|
1030
|
-
description: task.description,
|
|
1031
|
-
prompt: task.prompt,
|
|
1032
|
-
progress: task.progress,
|
|
1033
|
-
outputFile: task.outputFile,
|
|
1034
|
-
createdAt: task.createdAt,
|
|
1035
|
-
updatedAt: task.updatedAt,
|
|
1036
|
-
}));
|
|
1064
|
+
.map((task) => this.agentTaskSnapshot(task));
|
|
1037
1065
|
const terminalTasks = this.runtime.execProcessManager.list()
|
|
1038
1066
|
.filter((terminal) => terminal.status === "running" && terminal.backgrounded)
|
|
1039
1067
|
.map((terminal) => ({
|
|
@@ -1108,6 +1136,7 @@ export class WebRepl {
|
|
|
1108
1136
|
await this.detachRunningForeground("session switch");
|
|
1109
1137
|
this.backgroundSessionRuns.delete(run.sessionId);
|
|
1110
1138
|
this.runtime.engine = run.engine;
|
|
1139
|
+
activateSession(this.runtime);
|
|
1111
1140
|
this.activeAbortController = run.abortController;
|
|
1112
1141
|
this.interruptArmed = false;
|
|
1113
1142
|
this.foregroundRun = run.promise;
|
|
@@ -1430,6 +1459,7 @@ export class WebRepl {
|
|
|
1430
1459
|
return void this.append({ kind: "system", text: formatUsageTotals(this.runtime.usage.snapshot()), previewStyle: "summary" });
|
|
1431
1460
|
if (command.type === "reset") {
|
|
1432
1461
|
this.runtime.engine.reset();
|
|
1462
|
+
activateSession(this.runtime);
|
|
1433
1463
|
this.runtime.usage.reset();
|
|
1434
1464
|
this.status = await resetStatus(this.runtime);
|
|
1435
1465
|
this.append(systemLine("transcript reset"));
|
|
@@ -3026,6 +3056,13 @@ function buildToolResultDisplay(toolName, output, ok) {
|
|
|
3026
3056
|
}
|
|
3027
3057
|
else if (toolName.startsWith("subagent_") || toolName === "subagent_run") {
|
|
3028
3058
|
subject = stringValue(data.description) || stringValue(data.task_id) || stringValue(data.agent_id);
|
|
3059
|
+
pushToolFact(facts, "任务状态", data.status);
|
|
3060
|
+
pushToolFact(facts, "轮次", data.run_generation);
|
|
3061
|
+
pushToolFact(facts, "待交付", data.pending_messages);
|
|
3062
|
+
if (toolName === "subagent_message")
|
|
3063
|
+
pushToolFact(facts, "交付说明", "仅入队,不代表已交付或完成");
|
|
3064
|
+
if (data.requires_resume === true)
|
|
3065
|
+
pushToolFact(facts, "后续", "需要显式续跑");
|
|
3029
3066
|
}
|
|
3030
3067
|
else if (toolName === "subagent_message") {
|
|
3031
3068
|
subject = stringValue(data.target);
|