indusagi-coding-agent 0.1.42 → 0.1.44
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/CHANGELOG.md +23 -3
- package/README.md +3 -0
- package/dist/command-line/args.js +1 -1
- package/dist/command-line/args.js.map +1 -1
- package/dist/command-line/list-models.js +1 -1
- package/dist/command-line/list-models.js.map +1 -1
- package/dist/command-line/login-handler.d.ts.map +1 -1
- package/dist/command-line/login-handler.js +39 -0
- package/dist/command-line/login-handler.js.map +1 -1
- package/dist/dev/observe-deep.d.ts +2 -0
- package/dist/dev/observe-deep.d.ts.map +1 -0
- package/dist/dev/observe-deep.js +333 -0
- package/dist/dev/observe-deep.js.map +1 -0
- package/dist/dev/observe-smoke.d.ts +2 -0
- package/dist/dev/observe-smoke.d.ts.map +1 -0
- package/dist/dev/observe-smoke.js +264 -0
- package/dist/dev/observe-smoke.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/induscode-ui-delegate.d.ts +3 -0
- package/dist/interfaces/induscode-ui-delegate.d.ts.map +1 -0
- package/dist/interfaces/induscode-ui-delegate.js +148 -0
- package/dist/interfaces/induscode-ui-delegate.js.map +1 -0
- package/dist/interfaces/terminal-ui/components/footer.d.ts.map +1 -1
- package/dist/interfaces/terminal-ui/components/footer.js +9 -15
- package/dist/interfaces/terminal-ui/components/footer.js.map +1 -1
- package/dist/interfaces/terminal-ui/components/model-selector.d.ts.map +1 -1
- package/dist/interfaces/terminal-ui/components/model-selector.js +1 -1
- package/dist/interfaces/terminal-ui/components/model-selector.js.map +1 -1
- package/dist/interfaces/terminal-ui/components/oauth-selector.d.ts.map +1 -1
- package/dist/interfaces/terminal-ui/components/oauth-selector.js +1 -0
- package/dist/interfaces/terminal-ui/components/oauth-selector.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +42 -18
- package/dist/main.js.map +1 -1
- package/dist/observe.d.ts +2 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +2 -0
- package/dist/observe.js.map +1 -0
- package/dist/runtime/agent-session.d.ts +15 -0
- package/dist/runtime/agent-session.d.ts.map +1 -1
- package/dist/runtime/agent-session.js +444 -223
- package/dist/runtime/agent-session.js.map +1 -1
- package/dist/runtime/index.d.ts +5 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +5 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/model-registry.d.ts +6 -0
- package/dist/runtime/model-registry.d.ts.map +1 -1
- package/dist/runtime/model-registry.js +71 -14
- package/dist/runtime/model-registry.js.map +1 -1
- package/dist/runtime/model-resolver.d.ts.map +1 -1
- package/dist/runtime/model-resolver.js +6 -3
- package/dist/runtime/model-resolver.js.map +1 -1
- package/dist/runtime/observe.d.ts +50 -0
- package/dist/runtime/observe.d.ts.map +1 -0
- package/dist/runtime/observe.js +233 -0
- package/dist/runtime/observe.js.map +1 -0
- package/dist/runtime/plugins/types.d.ts +3 -0
- package/dist/runtime/plugins/types.d.ts.map +1 -1
- package/dist/runtime/plugins/types.js.map +1 -1
- package/dist/runtime/providers/adapters/claude-cli-adapter.d.ts +19 -0
- package/dist/runtime/providers/adapters/claude-cli-adapter.d.ts.map +1 -0
- package/dist/runtime/providers/adapters/claude-cli-adapter.js +242 -0
- package/dist/runtime/providers/adapters/claude-cli-adapter.js.map +1 -0
- package/dist/runtime/providers/adapters/codex-cli-adapter.d.ts +18 -0
- package/dist/runtime/providers/adapters/codex-cli-adapter.d.ts.map +1 -0
- package/dist/runtime/providers/adapters/codex-cli-adapter.js +177 -0
- package/dist/runtime/providers/adapters/codex-cli-adapter.js.map +1 -0
- package/dist/runtime/providers/adapters/indusagi-cli-adapter.d.ts +21 -0
- package/dist/runtime/providers/adapters/indusagi-cli-adapter.d.ts.map +1 -0
- package/dist/runtime/providers/adapters/indusagi-cli-adapter.js +162 -0
- package/dist/runtime/providers/adapters/indusagi-cli-adapter.js.map +1 -0
- package/dist/runtime/providers/adapters/utils.d.ts +12 -0
- package/dist/runtime/providers/adapters/utils.d.ts.map +1 -0
- package/dist/runtime/providers/adapters/utils.js +122 -0
- package/dist/runtime/providers/adapters/utils.js.map +1 -0
- package/dist/runtime/providers/builtins.d.ts +3 -0
- package/dist/runtime/providers/builtins.d.ts.map +1 -0
- package/dist/runtime/providers/builtins.js +99 -0
- package/dist/runtime/providers/builtins.js.map +1 -0
- package/dist/runtime/providers/provider-adapter-registry.d.ts +11 -0
- package/dist/runtime/providers/provider-adapter-registry.d.ts.map +1 -0
- package/dist/runtime/providers/provider-adapter-registry.js +36 -0
- package/dist/runtime/providers/provider-adapter-registry.js.map +1 -0
- package/dist/runtime/providers/provider-adapter.d.ts +33 -0
- package/dist/runtime/providers/provider-adapter.d.ts.map +1 -0
- package/dist/runtime/providers/provider-adapter.js +2 -0
- package/dist/runtime/providers/provider-adapter.js.map +1 -0
- package/dist/runtime/providers/provider-service.d.ts +33 -0
- package/dist/runtime/providers/provider-service.d.ts.map +1 -0
- package/dist/runtime/providers/provider-service.js +157 -0
- package/dist/runtime/providers/provider-service.js.map +1 -0
- package/dist/runtime/providers/types.d.ts +29 -0
- package/dist/runtime/providers/types.d.ts.map +1 -0
- package/dist/runtime/providers/types.js +9 -0
- package/dist/runtime/providers/types.js.map +1 -0
- package/dist/runtime/sdk.d.ts +6 -0
- package/dist/runtime/sdk.d.ts.map +1 -1
- package/dist/runtime/sdk.js +55 -8
- package/dist/runtime/sdk.js.map +1 -1
- package/dist/telemetry/core/types.d.ts +1 -1
- package/dist/telemetry/core/types.js +1 -1
- package/dist/vendor/observe/adapters/agent-event-adapter.d.ts +28 -0
- package/dist/vendor/observe/adapters/agent-event-adapter.d.ts.map +1 -0
- package/dist/vendor/observe/adapters/agent-event-adapter.js +136 -0
- package/dist/vendor/observe/adapters/agent-event-adapter.js.map +1 -0
- package/dist/vendor/observe/adapters/ai-stream-adapter.d.ts +24 -0
- package/dist/vendor/observe/adapters/ai-stream-adapter.d.ts.map +1 -0
- package/dist/vendor/observe/adapters/ai-stream-adapter.js +118 -0
- package/dist/vendor/observe/adapters/ai-stream-adapter.js.map +1 -0
- package/dist/vendor/observe/artifacts/content-store.d.ts +12 -0
- package/dist/vendor/observe/artifacts/content-store.d.ts.map +1 -0
- package/dist/vendor/observe/artifacts/content-store.js +2 -0
- package/dist/vendor/observe/artifacts/content-store.js.map +1 -0
- package/dist/vendor/observe/artifacts/file-content-store.d.ts +16 -0
- package/dist/vendor/observe/artifacts/file-content-store.d.ts.map +1 -0
- package/dist/vendor/observe/artifacts/file-content-store.js +43 -0
- package/dist/vendor/observe/artifacts/file-content-store.js.map +1 -0
- package/dist/vendor/observe/batcher.d.ts +27 -0
- package/dist/vendor/observe/batcher.d.ts.map +1 -0
- package/dist/vendor/observe/batcher.js +66 -0
- package/dist/vendor/observe/batcher.js.map +1 -0
- package/dist/vendor/observe/client/artifacts-manager.d.ts +29 -0
- package/dist/vendor/observe/client/artifacts-manager.d.ts.map +1 -0
- package/dist/vendor/observe/client/artifacts-manager.js +120 -0
- package/dist/vendor/observe/client/artifacts-manager.js.map +1 -0
- package/dist/vendor/observe/client/datasets-manager.d.ts +16 -0
- package/dist/vendor/observe/client/datasets-manager.d.ts.map +1 -0
- package/dist/vendor/observe/client/datasets-manager.js +27 -0
- package/dist/vendor/observe/client/datasets-manager.js.map +1 -0
- package/dist/vendor/observe/client/experiments-manager.d.ts +61 -0
- package/dist/vendor/observe/client/experiments-manager.d.ts.map +1 -0
- package/dist/vendor/observe/client/experiments-manager.js +132 -0
- package/dist/vendor/observe/client/experiments-manager.js.map +1 -0
- package/dist/vendor/observe/client/index.d.ts +9 -0
- package/dist/vendor/observe/client/index.d.ts.map +1 -0
- package/dist/vendor/observe/client/index.js +9 -0
- package/dist/vendor/observe/client/index.js.map +1 -0
- package/dist/vendor/observe/client/observe-client.d.ts +30 -0
- package/dist/vendor/observe/client/observe-client.d.ts.map +1 -0
- package/dist/vendor/observe/client/observe-client.js +22 -0
- package/dist/vendor/observe/client/observe-client.js.map +1 -0
- package/dist/vendor/observe/client/prompts-manager.d.ts +17 -0
- package/dist/vendor/observe/client/prompts-manager.d.ts.map +1 -0
- package/dist/vendor/observe/client/prompts-manager.js +38 -0
- package/dist/vendor/observe/client/prompts-manager.js.map +1 -0
- package/dist/vendor/observe/client/scores-manager.d.ts +10 -0
- package/dist/vendor/observe/client/scores-manager.d.ts.map +1 -0
- package/dist/vendor/observe/client/scores-manager.js +15 -0
- package/dist/vendor/observe/client/scores-manager.js.map +1 -0
- package/dist/vendor/observe/client/sessions-manager.d.ts +15 -0
- package/dist/vendor/observe/client/sessions-manager.d.ts.map +1 -0
- package/dist/vendor/observe/client/sessions-manager.js +24 -0
- package/dist/vendor/observe/client/sessions-manager.js.map +1 -0
- package/dist/vendor/observe/client/traces-manager.d.ts +23 -0
- package/dist/vendor/observe/client/traces-manager.d.ts.map +1 -0
- package/dist/vendor/observe/client/traces-manager.js +39 -0
- package/dist/vendor/observe/client/traces-manager.js.map +1 -0
- package/dist/vendor/observe/console-exporter.d.ts +11 -0
- package/dist/vendor/observe/console-exporter.d.ts.map +1 -0
- package/dist/vendor/observe/console-exporter.js +18 -0
- package/dist/vendor/observe/console-exporter.js.map +1 -0
- package/dist/vendor/observe/context.d.ts +4 -0
- package/dist/vendor/observe/context.d.ts.map +1 -0
- package/dist/vendor/observe/context.js +9 -0
- package/dist/vendor/observe/context.js.map +1 -0
- package/dist/vendor/observe/entities/artifacts.d.ts +46 -0
- package/dist/vendor/observe/entities/artifacts.d.ts.map +1 -0
- package/dist/vendor/observe/entities/artifacts.js +2 -0
- package/dist/vendor/observe/entities/artifacts.js.map +1 -0
- package/dist/vendor/observe/entities/datasets.d.ts +37 -0
- package/dist/vendor/observe/entities/datasets.d.ts.map +1 -0
- package/dist/vendor/observe/entities/datasets.js +2 -0
- package/dist/vendor/observe/entities/datasets.js.map +1 -0
- package/dist/vendor/observe/entities/experiments.d.ts +66 -0
- package/dist/vendor/observe/entities/experiments.d.ts.map +1 -0
- package/dist/vendor/observe/entities/experiments.js +2 -0
- package/dist/vendor/observe/entities/experiments.js.map +1 -0
- package/dist/vendor/observe/entities/index.d.ts +9 -0
- package/dist/vendor/observe/entities/index.d.ts.map +1 -0
- package/dist/vendor/observe/entities/index.js +9 -0
- package/dist/vendor/observe/entities/index.js.map +1 -0
- package/dist/vendor/observe/entities/prompts.d.ts +25 -0
- package/dist/vendor/observe/entities/prompts.d.ts.map +1 -0
- package/dist/vendor/observe/entities/prompts.js +2 -0
- package/dist/vendor/observe/entities/prompts.js.map +1 -0
- package/dist/vendor/observe/entities/scores.d.ts +28 -0
- package/dist/vendor/observe/entities/scores.d.ts.map +1 -0
- package/dist/vendor/observe/entities/scores.js +2 -0
- package/dist/vendor/observe/entities/scores.js.map +1 -0
- package/dist/vendor/observe/entities/sessions.d.ts +36 -0
- package/dist/vendor/observe/entities/sessions.d.ts.map +1 -0
- package/dist/vendor/observe/entities/sessions.js +2 -0
- package/dist/vendor/observe/entities/sessions.js.map +1 -0
- package/dist/vendor/observe/entities/shared.d.ts +26 -0
- package/dist/vendor/observe/entities/shared.d.ts.map +1 -0
- package/dist/vendor/observe/entities/shared.js +2 -0
- package/dist/vendor/observe/entities/shared.js.map +1 -0
- package/dist/vendor/observe/entities/traces.d.ts +59 -0
- package/dist/vendor/observe/entities/traces.d.ts.map +1 -0
- package/dist/vendor/observe/entities/traces.js +2 -0
- package/dist/vendor/observe/entities/traces.js.map +1 -0
- package/dist/vendor/observe/exporter.d.ts +2 -0
- package/dist/vendor/observe/exporter.d.ts.map +1 -0
- package/dist/vendor/observe/exporter.js +2 -0
- package/dist/vendor/observe/exporter.js.map +1 -0
- package/dist/vendor/observe/file-exporter.d.ts +16 -0
- package/dist/vendor/observe/file-exporter.d.ts.map +1 -0
- package/dist/vendor/observe/file-exporter.js +39 -0
- package/dist/vendor/observe/file-exporter.js.map +1 -0
- package/dist/vendor/observe/global.d.ts +6 -0
- package/dist/vendor/observe/global.d.ts.map +1 -0
- package/dist/vendor/observe/global.js +17 -0
- package/dist/vendor/observe/global.js.map +1 -0
- package/dist/vendor/observe/index.d.ts +24 -0
- package/dist/vendor/observe/index.d.ts.map +1 -0
- package/dist/vendor/observe/index.js +24 -0
- package/dist/vendor/observe/index.js.map +1 -0
- package/dist/vendor/observe/noop.d.ts +17 -0
- package/dist/vendor/observe/noop.d.ts.map +1 -0
- package/dist/vendor/observe/noop.js +80 -0
- package/dist/vendor/observe/noop.js.map +1 -0
- package/dist/vendor/observe/privacy.d.ts +18 -0
- package/dist/vendor/observe/privacy.d.ts.map +1 -0
- package/dist/vendor/observe/privacy.js +160 -0
- package/dist/vendor/observe/privacy.js.map +1 -0
- package/dist/vendor/observe/query/simple-query-client.d.ts +11 -0
- package/dist/vendor/observe/query/simple-query-client.d.ts.map +1 -0
- package/dist/vendor/observe/query/simple-query-client.js +31 -0
- package/dist/vendor/observe/query/simple-query-client.js.map +1 -0
- package/dist/vendor/observe/replay/session-replay.d.ts +20 -0
- package/dist/vendor/observe/replay/session-replay.d.ts.map +1 -0
- package/dist/vendor/observe/replay/session-replay.js +180 -0
- package/dist/vendor/observe/replay/session-replay.js.map +1 -0
- package/dist/vendor/observe/runtime.d.ts +27 -0
- package/dist/vendor/observe/runtime.d.ts.map +1 -0
- package/dist/vendor/observe/runtime.js +177 -0
- package/dist/vendor/observe/runtime.js.map +1 -0
- package/dist/vendor/observe/server/dashboard-html.d.ts +6 -0
- package/dist/vendor/observe/server/dashboard-html.d.ts.map +1 -0
- package/dist/vendor/observe/server/dashboard-html.js +305 -0
- package/dist/vendor/observe/server/dashboard-html.js.map +1 -0
- package/dist/vendor/observe/server/http-observe-server.d.ts +62 -0
- package/dist/vendor/observe/server/http-observe-server.d.ts.map +1 -0
- package/dist/vendor/observe/server/http-observe-server.js +418 -0
- package/dist/vendor/observe/server/http-observe-server.js.map +1 -0
- package/dist/vendor/observe/server/in-memory-observe-server.d.ts +20 -0
- package/dist/vendor/observe/server/in-memory-observe-server.d.ts.map +1 -0
- package/dist/vendor/observe/server/in-memory-observe-server.js +76 -0
- package/dist/vendor/observe/server/in-memory-observe-server.js.map +1 -0
- package/dist/vendor/observe/span.d.ts +45 -0
- package/dist/vendor/observe/span.d.ts.map +1 -0
- package/dist/vendor/observe/span.js +110 -0
- package/dist/vendor/observe/span.js.map +1 -0
- package/dist/vendor/observe/store/contracts.d.ts +59 -0
- package/dist/vendor/observe/store/contracts.d.ts.map +1 -0
- package/dist/vendor/observe/store/contracts.js +2 -0
- package/dist/vendor/observe/store/contracts.js.map +1 -0
- package/dist/vendor/observe/store/file-control-plane-store.d.ts +33 -0
- package/dist/vendor/observe/store/file-control-plane-store.d.ts.map +1 -0
- package/dist/vendor/observe/store/file-control-plane-store.js +146 -0
- package/dist/vendor/observe/store/file-control-plane-store.js.map +1 -0
- package/dist/vendor/observe/store/in-memory-control-plane-store.d.ts +84 -0
- package/dist/vendor/observe/store/in-memory-control-plane-store.d.ts.map +1 -0
- package/dist/vendor/observe/store/in-memory-control-plane-store.js +447 -0
- package/dist/vendor/observe/store/in-memory-control-plane-store.js.map +1 -0
- package/dist/vendor/observe/store/index.d.ts +4 -0
- package/dist/vendor/observe/store/index.d.ts.map +1 -0
- package/dist/vendor/observe/store/index.js +4 -0
- package/dist/vendor/observe/store/index.js.map +1 -0
- package/dist/vendor/observe/types.d.ts +246 -0
- package/dist/vendor/observe/types.d.ts.map +1 -0
- package/dist/vendor/observe/types.js +152 -0
- package/dist/vendor/observe/types.js.map +1 -0
- package/dist/vendor/observe/worker/in-memory-observe-worker.d.ts +25 -0
- package/dist/vendor/observe/worker/in-memory-observe-worker.d.ts.map +1 -0
- package/dist/vendor/observe/worker/in-memory-observe-worker.js +82 -0
- package/dist/vendor/observe/worker/in-memory-observe-worker.js.map +1 -0
- package/guides/CLAUDE_CODEX_CLI_INTEGRATION_PLAN.md +321 -0
- package/guides/{PI_MONO_MIT_REMOVAL_GUIDE.md → INDUSAGI_MONO_MIT_REMOVAL_GUIDE.md} +29 -29
- package/guides/INDUSVX_OBSERVE_FULL_INTEGRATION_REPORT.md +543 -0
- package/guides/OBSERVE_DEEP_VALIDATION.md +252 -0
- package/guides/OBSERVE_LOCAL_TESTING.md +183 -0
- package/guides/OPTION3_PROVIDER_ADAPTER_RUNTIME_PLAN.md +370 -0
- package/package.json +11 -4
|
@@ -220,8 +220,10 @@
|
|
|
220
220
|
import { readFileSync } from "node:fs";
|
|
221
221
|
import { join } from "node:path";
|
|
222
222
|
import { isContextOverflow, modelsAreEqual, resetApiProviders, supportsXhigh } from "indusagi/ai";
|
|
223
|
+
import { AgentEventObserveAdapter } from "../observe.js";
|
|
223
224
|
import { getAgentDir, getDocsPath } from "../config.js";
|
|
224
225
|
import { theme } from "../interfaces/terminal-ui/theme/theme.js";
|
|
226
|
+
import { runObserveOperation } from "./observe.js";
|
|
225
227
|
import { stripFrontmatter } from "../helpers/frontmatter.js";
|
|
226
228
|
import { sleep } from "../helpers/sleep.js";
|
|
227
229
|
import { executeBash as executeBashCommand, executeBashWithOperations } from "./bash-executor.js";
|
|
@@ -333,6 +335,7 @@ export class AgentSession {
|
|
|
333
335
|
this._customTools = config.customTools ?? [];
|
|
334
336
|
this._cwd = config.cwd;
|
|
335
337
|
this._modelRegistry = config.modelRegistry;
|
|
338
|
+
this._providerService = config.providerService;
|
|
336
339
|
this._agentDir = config.agentDir ?? getAgentDir();
|
|
337
340
|
this._todoStore = createSessionTodoStore({
|
|
338
341
|
sessionManager: this.sessionManager,
|
|
@@ -342,6 +345,7 @@ export class AgentSession {
|
|
|
342
345
|
this._subagentStore = new SubagentStore({ cwd: this._cwd, agentDir: this._agentDir });
|
|
343
346
|
this._extensionRunnerRef = config.extensionRunnerRef;
|
|
344
347
|
this._hookRunnerRef = config.hookRunnerRef;
|
|
348
|
+
this._observe = config.observe;
|
|
345
349
|
this._initialActiveToolNames = config.initialActiveToolNames;
|
|
346
350
|
this._baseToolsOverride = config.baseToolsOverride;
|
|
347
351
|
this._wireAgentEventHandlers();
|
|
@@ -354,6 +358,27 @@ export class AgentSession {
|
|
|
354
358
|
get modelRegistry() {
|
|
355
359
|
return this._modelRegistry;
|
|
356
360
|
}
|
|
361
|
+
async initializeObserve() {
|
|
362
|
+
if (!this._observe)
|
|
363
|
+
return;
|
|
364
|
+
await this._observe.initializeSession(this._getObserveSessionSnapshot());
|
|
365
|
+
if (!this._observeAgentEventsUnsubscribe) {
|
|
366
|
+
const adapter = new AgentEventObserveAdapter({
|
|
367
|
+
sink: this._observe.sink,
|
|
368
|
+
includeMessageText: this._observe.captureAgentEventText,
|
|
369
|
+
});
|
|
370
|
+
this._observeAgentEventsUnsubscribe = adapter.attach(this.agent);
|
|
371
|
+
}
|
|
372
|
+
await this._observe.log({
|
|
373
|
+
sessionId: this.sessionId,
|
|
374
|
+
name: "session.initialize",
|
|
375
|
+
summary: "observe session initialized",
|
|
376
|
+
attributes: {
|
|
377
|
+
sessionFile: this.sessionFile,
|
|
378
|
+
activeToolCount: this.getActiveToolNames().length,
|
|
379
|
+
},
|
|
380
|
+
});
|
|
381
|
+
}
|
|
357
382
|
// =========================================================================
|
|
358
383
|
// Event Subscription
|
|
359
384
|
// =========================================================================
|
|
@@ -431,6 +456,42 @@ export class AgentSession {
|
|
|
431
456
|
this._retryPromise = undefined;
|
|
432
457
|
}
|
|
433
458
|
}
|
|
459
|
+
_getObserveSessionSnapshot() {
|
|
460
|
+
return {
|
|
461
|
+
id: this.sessionId,
|
|
462
|
+
cwd: this._cwd,
|
|
463
|
+
sessionFile: this.sessionFile,
|
|
464
|
+
model: this.model ? { provider: this.model.provider, id: this.model.id } : undefined,
|
|
465
|
+
activeToolNames: this.getActiveToolNames(),
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
async _refreshObserveSession() {
|
|
469
|
+
await this._observe?.initializeSession(this._getObserveSessionSnapshot());
|
|
470
|
+
}
|
|
471
|
+
async _endObserveSession(sessionId, status = "ended") {
|
|
472
|
+
await this._observe?.endSession(sessionId, status);
|
|
473
|
+
}
|
|
474
|
+
async _logObserve(options) {
|
|
475
|
+
await this._observe?.log({
|
|
476
|
+
sessionId: this.sessionId,
|
|
477
|
+
...options,
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
async _runObserveOperation(name, kind, fn, options = {}) {
|
|
481
|
+
return runObserveOperation(this._observe, {
|
|
482
|
+
sessionId: this.sessionId,
|
|
483
|
+
name,
|
|
484
|
+
kind,
|
|
485
|
+
input: options.input,
|
|
486
|
+
attributes: {
|
|
487
|
+
sessionFile: this.sessionFile,
|
|
488
|
+
modelId: this.model?.id,
|
|
489
|
+
provider: this.model?.provider,
|
|
490
|
+
...options.attributes,
|
|
491
|
+
},
|
|
492
|
+
output: options.output,
|
|
493
|
+
}, fn);
|
|
494
|
+
}
|
|
434
495
|
/** Extract text content from a message */
|
|
435
496
|
_getUserMessageText(message) {
|
|
436
497
|
if (message.role !== "user")
|
|
@@ -531,7 +592,12 @@ export class AgentSession {
|
|
|
531
592
|
* Call this when completely done with the session.
|
|
532
593
|
*/
|
|
533
594
|
dispose() {
|
|
595
|
+
if (this.model && this._providerService?.usesAdapter(this.model)) {
|
|
596
|
+
void this._providerService.stopCurrent(this.model).catch(() => { });
|
|
597
|
+
}
|
|
534
598
|
this._disconnectFromAgent();
|
|
599
|
+
this._observeAgentEventsUnsubscribe?.();
|
|
600
|
+
this._observeAgentEventsUnsubscribe = undefined;
|
|
535
601
|
this._eventListeners = [];
|
|
536
602
|
}
|
|
537
603
|
// =========================================================================
|
|
@@ -717,16 +783,18 @@ export class AgentSession {
|
|
|
717
783
|
"Then use /model to select a model.");
|
|
718
784
|
}
|
|
719
785
|
// Validate API key
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
786
|
+
if (this._modelRegistry.providerNeedsAuth(this.model.provider)) {
|
|
787
|
+
const apiKey = await this._modelRegistry.getApiKey(this.model);
|
|
788
|
+
if (!apiKey) {
|
|
789
|
+
const isOAuth = this._modelRegistry.isUsingOAuth(this.model);
|
|
790
|
+
if (isOAuth) {
|
|
791
|
+
throw new Error(`Authentication failed for "${this.model.provider}". ` +
|
|
792
|
+
`Credentials may have expired or network is unavailable. ` +
|
|
793
|
+
`Run '/login ${this.model.provider}' to re-authenticate.`);
|
|
794
|
+
}
|
|
795
|
+
throw new Error(`No API key found for ${this.model.provider}.\n\n` +
|
|
796
|
+
`Use /login or set an API key environment variable. See ${join(getDocsPath(), "authentication.md")}`);
|
|
727
797
|
}
|
|
728
|
-
throw new Error(`No API key found for ${this.model.provider}.\n\n` +
|
|
729
|
-
`Use /login or set an API key environment variable. See ${join(getDocsPath(), "authentication.md")}`);
|
|
730
798
|
}
|
|
731
799
|
// Check if we need to compact before sending (catches aborted responses)
|
|
732
800
|
const lastAssistant = this._findLastAssistantMessage();
|
|
@@ -786,8 +854,21 @@ export class AgentSession {
|
|
|
786
854
|
this.agent.setSystemPrompt(this._baseSystemPrompt);
|
|
787
855
|
}
|
|
788
856
|
}
|
|
857
|
+
await this._logObserve({
|
|
858
|
+
name: "session.prompt",
|
|
859
|
+
summary: "prompt submitted to agent",
|
|
860
|
+
attributes: {
|
|
861
|
+
textLength: expandedText.length,
|
|
862
|
+
imageCount: currentImages?.length ?? 0,
|
|
863
|
+
pendingNextTurnMessages: messages.length - 1,
|
|
864
|
+
},
|
|
865
|
+
data: {
|
|
866
|
+
imageCount: currentImages?.length ?? 0,
|
|
867
|
+
},
|
|
868
|
+
});
|
|
789
869
|
await this.agent.prompt(messages);
|
|
790
870
|
await this.waitForRetry();
|
|
871
|
+
await this._refreshObserveSession();
|
|
791
872
|
}
|
|
792
873
|
/**
|
|
793
874
|
* Try to execute an extension command. Returns true if command was found and executed.
|
|
@@ -1033,6 +1114,9 @@ export class AgentSession {
|
|
|
1033
1114
|
*/
|
|
1034
1115
|
async abort() {
|
|
1035
1116
|
this.abortRetry();
|
|
1117
|
+
if (this.model && this._providerService?.usesAdapter(this.model)) {
|
|
1118
|
+
await this._providerService.interruptCurrent(this.model);
|
|
1119
|
+
}
|
|
1036
1120
|
this.agent.abort();
|
|
1037
1121
|
await this.agent.waitForIdle();
|
|
1038
1122
|
}
|
|
@@ -1044,38 +1128,58 @@ export class AgentSession {
|
|
|
1044
1128
|
* @returns true if completed, false if cancelled by extension
|
|
1045
1129
|
*/
|
|
1046
1130
|
async newSession(options) {
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1131
|
+
return this._runObserveOperation("session.new", "session_switch", async () => {
|
|
1132
|
+
const previousSessionFile = this.sessionFile;
|
|
1133
|
+
const previousSessionId = this.sessionId;
|
|
1134
|
+
// Emit session_before_switch event with reason "new" (can be cancelled)
|
|
1135
|
+
if (this._extensionRunner?.hasHandlers("session_before_switch")) {
|
|
1136
|
+
const result = (await this._extensionRunner.emit({
|
|
1137
|
+
type: "session_before_switch",
|
|
1138
|
+
reason: "new",
|
|
1139
|
+
}));
|
|
1140
|
+
if (result?.cancel) {
|
|
1141
|
+
return false;
|
|
1142
|
+
}
|
|
1056
1143
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
await this.
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1144
|
+
this._disconnectFromAgent();
|
|
1145
|
+
await this.abort();
|
|
1146
|
+
if (this.model && this._providerService?.usesAdapter(this.model)) {
|
|
1147
|
+
await this._providerService.stopCurrent(this.model);
|
|
1148
|
+
}
|
|
1149
|
+
this.agent.reset();
|
|
1150
|
+
this.sessionManager.newSession(options);
|
|
1151
|
+
this._rebuildTodoStore();
|
|
1152
|
+
this.agent.sessionId = this.sessionManager.getSessionId();
|
|
1153
|
+
this._memoryThreadId = this.sessionManager.getSessionId();
|
|
1154
|
+
this._steeringMessages = [];
|
|
1155
|
+
this._followUpMessages = [];
|
|
1156
|
+
this._pendingNextTurnMessages = [];
|
|
1157
|
+
this._reconnectToAgent();
|
|
1158
|
+
await this._endObserveSession(previousSessionId);
|
|
1159
|
+
await this._refreshObserveSession();
|
|
1160
|
+
await this._logObserve({
|
|
1161
|
+
name: "session.new",
|
|
1162
|
+
summary: "created new session",
|
|
1163
|
+
attributes: {
|
|
1164
|
+
previousSessionId,
|
|
1165
|
+
previousSessionFile,
|
|
1166
|
+
},
|
|
1075
1167
|
});
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1168
|
+
// Emit session_switch event with reason "new" to extensions
|
|
1169
|
+
if (this._extensionRunner) {
|
|
1170
|
+
await this._extensionRunner.emit({
|
|
1171
|
+
type: "session_switch",
|
|
1172
|
+
reason: "new",
|
|
1173
|
+
previousSessionFile,
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
return true;
|
|
1177
|
+
}, {
|
|
1178
|
+
attributes: {
|
|
1179
|
+
previousSessionFile: this.sessionFile,
|
|
1180
|
+
},
|
|
1181
|
+
output: (completed) => ({ completed }),
|
|
1182
|
+
});
|
|
1079
1183
|
}
|
|
1080
1184
|
// =========================================================================
|
|
1081
1185
|
// Model Management
|
|
@@ -1098,11 +1202,16 @@ export class AgentSession {
|
|
|
1098
1202
|
* @throws Error if no API key available for the model
|
|
1099
1203
|
*/
|
|
1100
1204
|
async setModel(model) {
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1205
|
+
if (this._modelRegistry.providerNeedsAuth(model.provider)) {
|
|
1206
|
+
const apiKey = await this._modelRegistry.getApiKey(model);
|
|
1207
|
+
if (!apiKey) {
|
|
1208
|
+
throw new Error(`No API key for ${model.provider}/${model.id}`);
|
|
1209
|
+
}
|
|
1104
1210
|
}
|
|
1105
1211
|
const previousModel = this.model;
|
|
1212
|
+
if (previousModel && !modelsAreEqual(previousModel, model) && this._providerService?.usesAdapter(previousModel)) {
|
|
1213
|
+
await this._providerService.stopCurrent(previousModel);
|
|
1214
|
+
}
|
|
1106
1215
|
this.agent.setModel(model);
|
|
1107
1216
|
this.sessionManager.appendModelChange(model.provider, model.id);
|
|
1108
1217
|
this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
|
|
@@ -1132,10 +1241,14 @@ export class AgentSession {
|
|
|
1132
1241
|
const len = this._scopedModels.length;
|
|
1133
1242
|
const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
|
|
1134
1243
|
const next = this._scopedModels[nextIndex];
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1244
|
+
if (this._modelRegistry.providerNeedsAuth(next.model.provider)) {
|
|
1245
|
+
const apiKey = await this._modelRegistry.getApiKey(next.model);
|
|
1246
|
+
if (!apiKey) {
|
|
1247
|
+
throw new Error(`No API key for ${next.model.provider}/${next.model.id}`);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
if (currentModel && !modelsAreEqual(currentModel, next.model) && this._providerService?.usesAdapter(currentModel)) {
|
|
1251
|
+
await this._providerService.stopCurrent(currentModel);
|
|
1139
1252
|
}
|
|
1140
1253
|
// Apply model
|
|
1141
1254
|
this.agent.setModel(next.model);
|
|
@@ -1157,9 +1270,14 @@ export class AgentSession {
|
|
|
1157
1270
|
const len = availableModels.length;
|
|
1158
1271
|
const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
|
|
1159
1272
|
const nextModel = availableModels[nextIndex];
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1273
|
+
if (this._modelRegistry.providerNeedsAuth(nextModel.provider)) {
|
|
1274
|
+
const apiKey = await this._modelRegistry.getApiKey(nextModel);
|
|
1275
|
+
if (!apiKey) {
|
|
1276
|
+
throw new Error(`No API key for ${nextModel.provider}/${nextModel.id}`);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
if (currentModel && !modelsAreEqual(currentModel, nextModel) && this._providerService?.usesAdapter(currentModel)) {
|
|
1280
|
+
await this._providerService.stopCurrent(currentModel);
|
|
1163
1281
|
}
|
|
1164
1282
|
this.agent.setModel(nextModel);
|
|
1165
1283
|
this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
|
|
@@ -1631,9 +1749,11 @@ export class AgentSession {
|
|
|
1631
1749
|
getAllTools: () => this.getAllTools(),
|
|
1632
1750
|
setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
|
|
1633
1751
|
setModel: async (model) => {
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1752
|
+
if (this.modelRegistry.providerNeedsAuth(model.provider)) {
|
|
1753
|
+
const key = await this.modelRegistry.getApiKey(model);
|
|
1754
|
+
if (!key)
|
|
1755
|
+
return false;
|
|
1756
|
+
}
|
|
1637
1757
|
await this.setModel(model);
|
|
1638
1758
|
return true;
|
|
1639
1759
|
},
|
|
@@ -1905,31 +2025,57 @@ export class AgentSession {
|
|
|
1905
2025
|
* @param options.operations Custom BashOperations for remote execution
|
|
1906
2026
|
*/
|
|
1907
2027
|
async executeBash(command, onChunk, options) {
|
|
1908
|
-
this.
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
2028
|
+
return this._runObserveOperation("session.execute_bash", "command_execution", async () => {
|
|
2029
|
+
this._bashAbortController = new AbortController();
|
|
2030
|
+
// Apply command prefix if configured (e.g., "shopt -s expand_aliases" for alias support)
|
|
2031
|
+
const prefix = this.settingsManager.getShellCommandPrefix();
|
|
2032
|
+
const resolvedCommand = prefix ? `${prefix}\n${command}` : command;
|
|
2033
|
+
const hookEnv = this._hookRunner?.hasHandlers("shell.env")
|
|
2034
|
+
? (await this._hookRunner.trigger("shell.env", { cwd: process.cwd() }, { env: {} })).env
|
|
2035
|
+
: undefined;
|
|
2036
|
+
try {
|
|
2037
|
+
const result = options?.operations
|
|
2038
|
+
? await executeBashWithOperations(resolvedCommand, process.cwd(), options.operations, {
|
|
2039
|
+
onChunk,
|
|
2040
|
+
signal: this._bashAbortController.signal,
|
|
2041
|
+
env: hookEnv,
|
|
2042
|
+
})
|
|
2043
|
+
: await executeBashCommand(resolvedCommand, {
|
|
2044
|
+
onChunk,
|
|
2045
|
+
signal: this._bashAbortController.signal,
|
|
2046
|
+
env: hookEnv,
|
|
2047
|
+
});
|
|
2048
|
+
this.recordBashResult(command, result, options);
|
|
2049
|
+
await this._logObserve({
|
|
2050
|
+
name: "session.execute_bash",
|
|
2051
|
+
summary: "bash command completed",
|
|
2052
|
+
attributes: {
|
|
2053
|
+
commandLength: command.length,
|
|
2054
|
+
exitCode: result.exitCode,
|
|
2055
|
+
cancelled: result.cancelled,
|
|
2056
|
+
truncated: result.truncated,
|
|
2057
|
+
excludeFromContext: options?.excludeFromContext ?? false,
|
|
2058
|
+
},
|
|
1926
2059
|
});
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
}
|
|
2060
|
+
return result;
|
|
2061
|
+
}
|
|
2062
|
+
finally {
|
|
2063
|
+
this._bashAbortController = undefined;
|
|
2064
|
+
}
|
|
2065
|
+
}, {
|
|
2066
|
+
input: {
|
|
2067
|
+
commandLength: command.length,
|
|
2068
|
+
excludeFromContext: options?.excludeFromContext ?? false,
|
|
2069
|
+
},
|
|
2070
|
+
attributes: {
|
|
2071
|
+
hasCustomOperations: !!options?.operations,
|
|
2072
|
+
},
|
|
2073
|
+
output: (result) => ({
|
|
2074
|
+
exitCode: result.exitCode,
|
|
2075
|
+
cancelled: result.cancelled,
|
|
2076
|
+
truncated: result.truncated,
|
|
2077
|
+
}),
|
|
2078
|
+
});
|
|
1933
2079
|
}
|
|
1934
2080
|
/**
|
|
1935
2081
|
* Record a bash execution result in session history.
|
|
@@ -1998,56 +2144,75 @@ export class AgentSession {
|
|
|
1998
2144
|
* @returns true if switch completed, false if cancelled by extension
|
|
1999
2145
|
*/
|
|
2000
2146
|
async switchSession(sessionPath) {
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2147
|
+
return this._runObserveOperation("session.switch", "session_switch", async () => {
|
|
2148
|
+
const previousSessionFile = this.sessionManager.getSessionFile();
|
|
2149
|
+
const previousSessionId = this.sessionId;
|
|
2150
|
+
// Emit session_before_switch event (can be cancelled)
|
|
2151
|
+
if (this._extensionRunner?.hasHandlers("session_before_switch")) {
|
|
2152
|
+
const result = (await this._extensionRunner.emit({
|
|
2153
|
+
type: "session_before_switch",
|
|
2154
|
+
reason: "resume",
|
|
2155
|
+
targetSessionFile: sessionPath,
|
|
2156
|
+
}));
|
|
2157
|
+
if (result?.cancel) {
|
|
2158
|
+
return false;
|
|
2159
|
+
}
|
|
2011
2160
|
}
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
this._followUpMessages = [];
|
|
2017
|
-
this._pendingNextTurnMessages = [];
|
|
2018
|
-
// Set new session
|
|
2019
|
-
this.sessionManager.setSessionFile(sessionPath);
|
|
2020
|
-
this._rebuildTodoStore();
|
|
2021
|
-
this.agent.sessionId = this.sessionManager.getSessionId();
|
|
2022
|
-
this._memoryThreadId = this.sessionManager.getSessionId();
|
|
2023
|
-
// Reload messages
|
|
2024
|
-
const sessionContext = this.sessionManager.buildSessionContext();
|
|
2025
|
-
// Emit session_switch event to extensions
|
|
2026
|
-
if (this._extensionRunner) {
|
|
2027
|
-
await this._extensionRunner.emit({
|
|
2028
|
-
type: "session_switch",
|
|
2029
|
-
reason: "resume",
|
|
2030
|
-
previousSessionFile,
|
|
2031
|
-
});
|
|
2032
|
-
}
|
|
2033
|
-
// Emit session event to custom tools
|
|
2034
|
-
this.agent.replaceMessages(sessionContext.messages);
|
|
2035
|
-
// Restore model if saved
|
|
2036
|
-
if (sessionContext.model) {
|
|
2037
|
-
const previousModel = this.model;
|
|
2038
|
-
const availableModels = await this._modelRegistry.getAvailable();
|
|
2039
|
-
const match = availableModels.find((m) => m.provider === sessionContext.model.provider && m.id === sessionContext.model.modelId);
|
|
2040
|
-
if (match) {
|
|
2041
|
-
this.agent.setModel(match);
|
|
2042
|
-
await this._emitModelSelect(match, previousModel, "restore");
|
|
2161
|
+
this._disconnectFromAgent();
|
|
2162
|
+
await this.abort();
|
|
2163
|
+
if (this.model && this._providerService?.usesAdapter(this.model)) {
|
|
2164
|
+
await this._providerService.stopCurrent(this.model);
|
|
2043
2165
|
}
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2166
|
+
this._steeringMessages = [];
|
|
2167
|
+
this._followUpMessages = [];
|
|
2168
|
+
this._pendingNextTurnMessages = [];
|
|
2169
|
+
// Set new session
|
|
2170
|
+
this.sessionManager.setSessionFile(sessionPath);
|
|
2171
|
+
this._rebuildTodoStore();
|
|
2172
|
+
this.agent.sessionId = this.sessionManager.getSessionId();
|
|
2173
|
+
this._memoryThreadId = this.sessionManager.getSessionId();
|
|
2174
|
+
// Reload messages
|
|
2175
|
+
const sessionContext = this.sessionManager.buildSessionContext();
|
|
2176
|
+
// Emit session_switch event to extensions
|
|
2177
|
+
if (this._extensionRunner) {
|
|
2178
|
+
await this._extensionRunner.emit({
|
|
2179
|
+
type: "session_switch",
|
|
2180
|
+
reason: "resume",
|
|
2181
|
+
previousSessionFile,
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2184
|
+
this.agent.replaceMessages(sessionContext.messages);
|
|
2185
|
+
// Restore model if saved
|
|
2186
|
+
if (sessionContext.model) {
|
|
2187
|
+
const previousModel = this.model;
|
|
2188
|
+
const availableModels = await this._modelRegistry.getAvailable();
|
|
2189
|
+
const match = availableModels.find((m) => m.provider === sessionContext.model.provider && m.id === sessionContext.model.modelId);
|
|
2190
|
+
if (match) {
|
|
2191
|
+
this.agent.setModel(match);
|
|
2192
|
+
await this._emitModelSelect(match, previousModel, "restore");
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
// Restore thinking level if saved (setThinkingLevel clamps to model capabilities)
|
|
2196
|
+
if (sessionContext.thinkingLevel) {
|
|
2197
|
+
this.setThinkingLevel(sessionContext.thinkingLevel);
|
|
2198
|
+
}
|
|
2199
|
+
this._reconnectToAgent();
|
|
2200
|
+
await this._endObserveSession(previousSessionId);
|
|
2201
|
+
await this._refreshObserveSession();
|
|
2202
|
+
await this._logObserve({
|
|
2203
|
+
name: "session.switch",
|
|
2204
|
+
summary: "switched session",
|
|
2205
|
+
attributes: {
|
|
2206
|
+
previousSessionId,
|
|
2207
|
+
previousSessionFile,
|
|
2208
|
+
targetSessionFile: sessionPath,
|
|
2209
|
+
},
|
|
2210
|
+
});
|
|
2211
|
+
return true;
|
|
2212
|
+
}, {
|
|
2213
|
+
input: { targetSessionFile: sessionPath },
|
|
2214
|
+
output: (completed) => ({ completed }),
|
|
2215
|
+
});
|
|
2051
2216
|
}
|
|
2052
2217
|
/**
|
|
2053
2218
|
* Create a fork from a specific entry.
|
|
@@ -2059,49 +2224,66 @@ export class AgentSession {
|
|
|
2059
2224
|
* - cancelled: True if an extension cancelled the fork
|
|
2060
2225
|
*/
|
|
2061
2226
|
async fork(entryId) {
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
let skipConversationRestore = false;
|
|
2069
|
-
// Emit session_before_fork event (can be cancelled)
|
|
2070
|
-
if (this._extensionRunner?.hasHandlers("session_before_fork")) {
|
|
2071
|
-
const result = (await this._extensionRunner.emit({
|
|
2072
|
-
type: "session_before_fork",
|
|
2073
|
-
entryId,
|
|
2074
|
-
}));
|
|
2075
|
-
if (result?.cancel) {
|
|
2076
|
-
return { selectedText, cancelled: true };
|
|
2227
|
+
return this._runObserveOperation("session.fork", "session_fork", async () => {
|
|
2228
|
+
const previousSessionFile = this.sessionFile;
|
|
2229
|
+
const previousSessionId = this.sessionId;
|
|
2230
|
+
const selectedEntry = this.sessionManager.getEntry(entryId);
|
|
2231
|
+
if (!selectedEntry || selectedEntry.type !== "message" || selectedEntry.message.role !== "user") {
|
|
2232
|
+
throw new Error("Invalid entry ID for forking");
|
|
2077
2233
|
}
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2234
|
+
const selectedText = this._extractUserMessageText(selectedEntry.message.content);
|
|
2235
|
+
let skipConversationRestore = false;
|
|
2236
|
+
// Emit session_before_fork event (can be cancelled)
|
|
2237
|
+
if (this._extensionRunner?.hasHandlers("session_before_fork")) {
|
|
2238
|
+
const result = (await this._extensionRunner.emit({
|
|
2239
|
+
type: "session_before_fork",
|
|
2240
|
+
entryId,
|
|
2241
|
+
}));
|
|
2242
|
+
if (result?.cancel) {
|
|
2243
|
+
return { selectedText, cancelled: true };
|
|
2244
|
+
}
|
|
2245
|
+
skipConversationRestore = result?.skipConversationRestore ?? false;
|
|
2246
|
+
}
|
|
2247
|
+
// Clear pending messages (bound to old session state)
|
|
2248
|
+
this._pendingNextTurnMessages = [];
|
|
2249
|
+
if (!selectedEntry.parentId) {
|
|
2250
|
+
this.sessionManager.newSession();
|
|
2251
|
+
}
|
|
2252
|
+
else {
|
|
2253
|
+
this.sessionManager.createBranchedSession(selectedEntry.parentId);
|
|
2254
|
+
}
|
|
2255
|
+
this.agent.sessionId = this.sessionManager.getSessionId();
|
|
2256
|
+
this._memoryThreadId = this.sessionManager.getSessionId();
|
|
2257
|
+
this._rebuildTodoStore();
|
|
2258
|
+
// Reload messages from entries (works for both file and in-memory mode)
|
|
2259
|
+
const sessionContext = this.sessionManager.buildSessionContext();
|
|
2260
|
+
// Emit session_fork event to extensions (after fork completes)
|
|
2261
|
+
if (this._extensionRunner) {
|
|
2262
|
+
await this._extensionRunner.emit({
|
|
2263
|
+
type: "session_fork",
|
|
2264
|
+
previousSessionFile,
|
|
2265
|
+
});
|
|
2266
|
+
}
|
|
2267
|
+
if (!skipConversationRestore) {
|
|
2268
|
+
this.agent.replaceMessages(sessionContext.messages);
|
|
2269
|
+
}
|
|
2270
|
+
await this._endObserveSession(previousSessionId);
|
|
2271
|
+
await this._refreshObserveSession();
|
|
2272
|
+
await this._logObserve({
|
|
2273
|
+
name: "session.fork",
|
|
2274
|
+
summary: "forked session branch",
|
|
2275
|
+
attributes: {
|
|
2276
|
+
entryId,
|
|
2277
|
+
previousSessionId,
|
|
2278
|
+
previousSessionFile,
|
|
2279
|
+
skipConversationRestore,
|
|
2280
|
+
},
|
|
2098
2281
|
});
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
}
|
|
2104
|
-
return { selectedText, cancelled: false };
|
|
2282
|
+
return { selectedText, cancelled: false };
|
|
2283
|
+
}, {
|
|
2284
|
+
input: { entryId },
|
|
2285
|
+
output: (result) => ({ cancelled: result.cancelled, selectedTextLength: result.selectedText.length }),
|
|
2286
|
+
});
|
|
2105
2287
|
}
|
|
2106
2288
|
// =========================================================================
|
|
2107
2289
|
// Tree Navigation
|
|
@@ -2451,13 +2633,22 @@ export class AgentSession {
|
|
|
2451
2633
|
}
|
|
2452
2634
|
// Rebuild active tools to include MCP tools
|
|
2453
2635
|
const currentActive = this.getActiveToolNames();
|
|
2454
|
-
const mcpToolNames = tools.map(t => t.name);
|
|
2636
|
+
const mcpToolNames = tools.map((t) => t.name);
|
|
2455
2637
|
this.setActiveToolsByName([...currentActive, ...mcpToolNames]);
|
|
2456
2638
|
// Rebuild runtime to include MCP tools in agent
|
|
2457
2639
|
this._rebuildRuntimeState({
|
|
2458
2640
|
activeToolNames: [...currentActive, ...mcpToolNames],
|
|
2459
2641
|
includeAllExtensionTools: true,
|
|
2460
2642
|
});
|
|
2643
|
+
void this._refreshObserveSession();
|
|
2644
|
+
void this._logObserve({
|
|
2645
|
+
name: "mcp.register_tools",
|
|
2646
|
+
summary: "registered MCP tools",
|
|
2647
|
+
attributes: {
|
|
2648
|
+
toolCount: tools.length,
|
|
2649
|
+
toolNames: tools.map((tool) => tool.name),
|
|
2650
|
+
},
|
|
2651
|
+
});
|
|
2461
2652
|
}
|
|
2462
2653
|
/**
|
|
2463
2654
|
* Get MCP server status.
|
|
@@ -2499,16 +2690,22 @@ export class AgentSession {
|
|
|
2499
2690
|
* @returns Promise resolving to the number of tools loaded
|
|
2500
2691
|
*/
|
|
2501
2692
|
async reconnectMCP(configPath) {
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2693
|
+
return this._runObserveOperation("mcp.reconnect", "mcp_call", async () => {
|
|
2694
|
+
// First disconnect existing connections
|
|
2695
|
+
await this.disconnectMCP();
|
|
2696
|
+
// Load new tools
|
|
2697
|
+
const { createMCPTools } = await import("./tooling/index.js");
|
|
2698
|
+
const result = await createMCPTools(configPath);
|
|
2699
|
+
// Register tools
|
|
2700
|
+
if (result.tools.length > 0) {
|
|
2701
|
+
this.registerMCPTools(result.tools, result.pool);
|
|
2702
|
+
}
|
|
2703
|
+
await this._refreshObserveSession();
|
|
2704
|
+
return result.tools.length;
|
|
2705
|
+
}, {
|
|
2706
|
+
input: { configPath },
|
|
2707
|
+
output: (toolCount) => ({ toolCount }),
|
|
2708
|
+
});
|
|
2512
2709
|
}
|
|
2513
2710
|
// =========================================================================
|
|
2514
2711
|
// Memory System
|
|
@@ -2529,73 +2726,97 @@ export class AgentSession {
|
|
|
2529
2726
|
}
|
|
2530
2727
|
// Rebuild active tools to include memory tools
|
|
2531
2728
|
const currentActive = this.getActiveToolNames();
|
|
2532
|
-
const memoryToolNames = tools.map(t => t.name);
|
|
2729
|
+
const memoryToolNames = tools.map((t) => t.name);
|
|
2533
2730
|
this.setActiveToolsByName([...currentActive, ...memoryToolNames]);
|
|
2534
2731
|
// Rebuild runtime to include memory tools in agent
|
|
2535
2732
|
this._rebuildRuntimeState({
|
|
2536
2733
|
activeToolNames: [...currentActive, ...memoryToolNames],
|
|
2537
2734
|
includeAllExtensionTools: true,
|
|
2538
2735
|
});
|
|
2736
|
+
void this._refreshObserveSession();
|
|
2737
|
+
void this._logObserve({
|
|
2738
|
+
name: "memory.register_tools",
|
|
2739
|
+
summary: "registered memory tools",
|
|
2740
|
+
attributes: {
|
|
2741
|
+
toolCount: tools.length,
|
|
2742
|
+
toolNames: tools.map((tool) => tool.name),
|
|
2743
|
+
},
|
|
2744
|
+
});
|
|
2539
2745
|
}
|
|
2540
2746
|
/**
|
|
2541
2747
|
* Enable memory for the current and future sessions.
|
|
2542
2748
|
* Optionally persists an OpenAI API key before initializing memory.
|
|
2543
2749
|
*/
|
|
2544
2750
|
async enableMemory(options) {
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2751
|
+
await this._runObserveOperation("memory.enable", "custom", async () => {
|
|
2752
|
+
const persistSettings = options?.persistSettings ?? true;
|
|
2753
|
+
if (this._memory) {
|
|
2754
|
+
await this.disableMemory({ persistSettings: false });
|
|
2755
|
+
}
|
|
2756
|
+
if (options?.apiKey) {
|
|
2757
|
+
this._modelRegistry.authStorage.set("openai", "default", {
|
|
2758
|
+
type: "api_key",
|
|
2759
|
+
key: options.apiKey,
|
|
2760
|
+
accountName: "Default",
|
|
2761
|
+
});
|
|
2762
|
+
}
|
|
2763
|
+
const openaiKey = options?.apiKey ?? (await this._modelRegistry.getApiKeyForProvider("openai"));
|
|
2764
|
+
if (!openaiKey) {
|
|
2765
|
+
throw new Error("OpenAI API key not found. Run /memory setup <OPENAI_API_KEY> first.");
|
|
2766
|
+
}
|
|
2767
|
+
const memory = await createMemory({
|
|
2768
|
+
apiKey: openaiKey,
|
|
2769
|
+
lastMessages: this.settingsManager.getMemoryLastMessages(),
|
|
2770
|
+
workingMemory: this.settingsManager.getMemoryWorkingMemoryEnabled()
|
|
2771
|
+
? { enabled: true, scope: "resource", template: DEFAULT_WORKING_MEMORY_TEMPLATE }
|
|
2772
|
+
: undefined,
|
|
2773
|
+
semanticRecall: this.settingsManager.getMemorySemanticRecallEnabled()
|
|
2774
|
+
? { topK: 5, messageRange: 2 }
|
|
2775
|
+
: undefined,
|
|
2776
|
+
observationalMemory: this.settingsManager.getMemoryObservationalMemoryEnabled()
|
|
2777
|
+
? { enabled: true, scope: "thread" }
|
|
2778
|
+
: undefined,
|
|
2554
2779
|
});
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
observationalMemory: this.settingsManager.getMemoryObservationalMemoryEnabled()
|
|
2570
|
-
? { enabled: true, scope: "thread" }
|
|
2571
|
-
: undefined,
|
|
2572
|
-
});
|
|
2573
|
-
const memoryTools = createMemoryTools(memory, {
|
|
2574
|
-
threadId: this.sessionManager.getSessionId(),
|
|
2575
|
-
resourceId: this._memoryResourceId,
|
|
2780
|
+
const memoryTools = createMemoryTools(memory, {
|
|
2781
|
+
threadId: this.sessionManager.getSessionId(),
|
|
2782
|
+
resourceId: this._memoryResourceId,
|
|
2783
|
+
});
|
|
2784
|
+
this.registerMemoryTools(memoryTools, memory);
|
|
2785
|
+
if (persistSettings) {
|
|
2786
|
+
this.settingsManager.setMemorySettings({ enabled: true, autoConnect: true });
|
|
2787
|
+
}
|
|
2788
|
+
await this._refreshObserveSession();
|
|
2789
|
+
}, {
|
|
2790
|
+
attributes: {
|
|
2791
|
+
persistSettings: options?.persistSettings ?? true,
|
|
2792
|
+
hasApiKeyOverride: !!options?.apiKey,
|
|
2793
|
+
},
|
|
2576
2794
|
});
|
|
2577
|
-
this.registerMemoryTools(memoryTools, memory);
|
|
2578
|
-
if (persistSettings) {
|
|
2579
|
-
this.settingsManager.setMemorySettings({ enabled: true, autoConnect: true });
|
|
2580
|
-
}
|
|
2581
2795
|
}
|
|
2582
2796
|
/**
|
|
2583
2797
|
* Disable memory for the current and future sessions.
|
|
2584
2798
|
*/
|
|
2585
2799
|
async disableMemory(options) {
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2800
|
+
await this._runObserveOperation("memory.disable", "custom", async () => {
|
|
2801
|
+
const persistSettings = options?.persistSettings ?? true;
|
|
2802
|
+
const memoryToolNames = new Set(this._memoryTools.map((tool) => tool.name));
|
|
2803
|
+
const activeWithoutMemory = this.getActiveToolNames().filter((name) => !memoryToolNames.has(name));
|
|
2804
|
+
this._memory = undefined;
|
|
2805
|
+
this._memoryTools = [];
|
|
2806
|
+
this._memoryThreadId = "";
|
|
2807
|
+
this._rebuildRuntimeState({
|
|
2808
|
+
activeToolNames: activeWithoutMemory,
|
|
2809
|
+
includeAllExtensionTools: true,
|
|
2810
|
+
});
|
|
2811
|
+
if (persistSettings) {
|
|
2812
|
+
this.settingsManager.setMemorySettings({ enabled: false, autoConnect: false });
|
|
2813
|
+
}
|
|
2814
|
+
await this._refreshObserveSession();
|
|
2815
|
+
}, {
|
|
2816
|
+
attributes: {
|
|
2817
|
+
persistSettings: options?.persistSettings ?? true,
|
|
2818
|
+
},
|
|
2595
2819
|
});
|
|
2596
|
-
if (persistSettings) {
|
|
2597
|
-
this.settingsManager.setMemorySettings({ enabled: false, autoConnect: false });
|
|
2598
|
-
}
|
|
2599
2820
|
}
|
|
2600
2821
|
/**
|
|
2601
2822
|
* Get the memory instance.
|