@getpaseo/server 0.1.100 → 0.1.102-beta.2
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/scripts/supervisor.js +26 -8
- package/dist/server/executable-resolution/windows.js +3 -0
- package/dist/server/server/agent/activity-curator.d.ts +17 -0
- package/dist/server/server/agent/activity-curator.js +101 -24
- package/dist/server/server/agent/agent-manager.d.ts +10 -0
- package/dist/server/server/agent/agent-manager.js +69 -27
- package/dist/server/server/agent/agent-sdk-types.d.ts +15 -2
- package/dist/server/server/agent/mcp-server.d.ts +2 -45
- package/dist/server/server/agent/mcp-server.js +45 -1985
- package/dist/server/server/agent/prompt-attachments.js +6 -2
- package/dist/server/server/agent/provider-snapshot-manager.d.ts +12 -1
- package/dist/server/server/agent/provider-snapshot-manager.js +132 -42
- package/dist/server/server/agent/providers/acp-agent.d.ts +27 -1
- package/dist/server/server/agent/providers/acp-agent.js +178 -27
- package/dist/server/server/agent/providers/claude/agent.js +111 -24
- package/dist/server/server/agent/providers/claude/query.d.ts +3 -0
- package/dist/server/server/agent/providers/claude/query.js +4 -2
- package/dist/server/server/agent/providers/codex-app-server-agent.js +6 -57
- package/dist/server/server/agent/providers/diagnostic-utils.d.ts +1 -0
- package/dist/server/server/agent/providers/diagnostic-utils.js +1 -1
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts +3 -0
- package/dist/server/server/agent/providers/generic-acp-agent.js +41 -23
- package/dist/server/server/agent/providers/mock-load-test-agent.js +12 -2
- package/dist/server/server/agent/providers/opencode/paths.d.ts +2 -0
- package/dist/server/server/agent/providers/opencode/paths.js +7 -0
- package/dist/server/server/agent/providers/opencode/server-manager.d.ts +2 -0
- package/dist/server/server/agent/providers/opencode/server-manager.js +34 -5
- package/dist/server/server/agent/providers/opencode-agent.d.ts +4 -0
- package/dist/server/server/agent/providers/opencode-agent.js +14 -2
- package/dist/server/server/agent/providers/pi/agent.d.ts +5 -1
- package/dist/server/server/agent/providers/pi/agent.js +12 -3
- package/dist/server/server/agent/providers/provider-image-output.d.ts +5 -0
- package/dist/server/server/agent/providers/provider-image-output.js +61 -1
- package/dist/server/server/agent/tools/paseo-tools.d.ts +48 -0
- package/dist/server/server/agent/tools/paseo-tools.js +2119 -0
- package/dist/server/server/agent/tools/types.d.ts +36 -0
- package/dist/server/server/agent/tools/types.js +2 -0
- package/dist/server/server/bootstrap.d.ts +7 -1
- package/dist/server/server/bootstrap.js +89 -62
- package/dist/server/server/config.d.ts +2 -0
- package/dist/server/server/config.js +57 -1
- package/dist/server/server/daemon-worker.js +19 -7
- package/dist/server/server/lifecycle-reasons.d.ts +4 -0
- package/dist/server/server/lifecycle-reasons.js +6 -0
- package/dist/server/server/persisted-config.d.ts +12 -0
- package/dist/server/server/persisted-config.js +18 -2
- package/dist/server/server/process-diagnostics.d.ts +17 -0
- package/dist/server/server/process-diagnostics.js +22 -0
- package/dist/server/server/relay-transport.js +1 -0
- package/dist/server/server/resolve-worktree-creation-intent.js +3 -1
- package/dist/server/server/session/agent-updates/agent-updates-service.d.ts +59 -0
- package/dist/server/server/session/agent-updates/agent-updates-service.js +220 -0
- package/dist/server/server/session/checkout/checkout-session.d.ts +13 -15
- package/dist/server/server/session/checkout/checkout-session.js +18 -16
- package/dist/server/server/session/checkout/git-metadata-generator.d.ts +53 -0
- package/dist/server/server/session/checkout/git-metadata-generator.js +159 -0
- package/dist/server/server/session/daemon/daemon-self-update-session-controller.d.ts +32 -0
- package/dist/server/server/session/daemon/daemon-self-update-session-controller.js +88 -0
- package/dist/server/server/session/daemon/daemon-self-updater.d.ts +32 -0
- package/dist/server/server/session/daemon/daemon-self-updater.js +56 -0
- package/dist/server/server/session/daemon/daemon-session.d.ts +26 -0
- package/dist/server/server/session/daemon/daemon-session.js +50 -0
- package/dist/server/server/session/daemon/diagnostics.d.ts +41 -0
- package/dist/server/server/session/daemon/diagnostics.js +431 -0
- package/dist/server/server/session/daemon/install-origin.d.ts +7 -0
- package/dist/server/server/session/daemon/install-origin.js +64 -0
- package/dist/server/server/session/daemon/npm-global-cli.d.ts +29 -0
- package/dist/server/server/session/daemon/npm-global-cli.js +98 -0
- package/dist/server/server/session/git-mutation/git-mutation-service.d.ts +34 -0
- package/dist/server/server/session/git-mutation/git-mutation-service.js +71 -0
- package/dist/server/server/session/provider/provider-catalog-session.js +8 -4
- package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.d.ts +36 -0
- package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.js +134 -0
- package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.d.ts +34 -0
- package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.js +190 -0
- package/dist/server/server/session/workspace-scripts/workspace-scripts-service.d.ts +41 -0
- package/dist/server/server/session/workspace-scripts/workspace-scripts-service.js +100 -0
- package/dist/server/server/session.d.ts +12 -54
- package/dist/server/server/session.js +187 -970
- package/dist/server/server/speech/providers/openai/config.d.ts +1 -2
- package/dist/server/server/speech/providers/openai/config.js +13 -9
- package/dist/server/server/speech/providers/openai/runtime.js +2 -16
- package/dist/server/server/speech/providers/openai/stt.d.ts +1 -0
- package/dist/server/server/speech/providers/openai/stt.js +4 -2
- package/dist/server/server/speech/providers/openai/tts.d.ts +1 -0
- package/dist/server/server/speech/providers/openai/tts.js +1 -0
- package/dist/server/server/web-ui.d.ts +10 -0
- package/dist/server/server/web-ui.js +205 -0
- package/dist/server/server/websocket/runtime-metrics.d.ts +23 -0
- package/dist/server/server/websocket-server.d.ts +4 -2
- package/dist/server/server/websocket-server.js +215 -52
- package/dist/server/server/worktree-bootstrap.d.ts +1 -1
- package/dist/server/server/worktree-branch-name-generator.js +3 -1
- package/dist/server/services/quota-fetcher/manifest.js +5 -0
- package/dist/server/services/quota-fetcher/providers/minimax.d.ts +29 -0
- package/dist/server/services/quota-fetcher/providers/minimax.js +227 -0
- package/dist/server/terminal/agent-hooks/agent-hook-installer.js +2 -2
- package/dist/server/utils/checkout-git.js +203 -25
- package/dist/server/utils/directory-suggestions.js +1 -4
- package/dist/server/utils/path.d.ts +2 -0
- package/dist/server/utils/path.js +13 -0
- package/dist/server/utils/worktree.d.ts +1 -0
- package/dist/server/utils/worktree.js +92 -11
- package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +1 -0
- package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
- package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js +1 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js +1 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js +16157 -0
- package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js +1 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js +3 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js.gz +0 -0
- package/dist/server/web-ui/apple-touch-icon.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/antigravity.6e91a685c33435e0b466a56db86cf141.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/cursor.c31d6bce4fe9aadc3fe59962f4c4fcf3.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/file-explorer.3e15e8f72c825c85ce336bcb0cdef776.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/finder.7f68fc2c475621a672e1be09309d5567.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/vscode.832bdb4c685d930f1c864c793703600b.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/webstorm.aa5dc2cd8c20cc0a155c4c5c5ab3c5f5.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/zed.f3a670b7f9aa226da4fe53fb86f1abbd.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-dark-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-dark-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-dark.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-light-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-light-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-light.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
- package/dist/server/web-ui/assets/assets/images/notification-icon.3bf81d33ddbf380606bdd248ba83e158.png +0 -0
- package/dist/server/web-ui/favicon.ico +0 -0
- package/dist/server/web-ui/index.html +90 -0
- package/dist/server/web-ui/index.html.br +0 -0
- package/dist/server/web-ui/index.html.gz +0 -0
- package/dist/server/web-ui/manifest.json +27 -0
- package/dist/server/web-ui/manifest.json.br +0 -0
- package/dist/server/web-ui/manifest.json.gz +0 -0
- package/dist/server/web-ui/metadata.json +1 -0
- package/dist/server/web-ui/metadata.json.br +1 -0
- package/dist/server/web-ui/metadata.json.gz +0 -0
- package/dist/server/web-ui/pwa-icon-192.png +0 -0
- package/dist/server/web-ui/pwa-icon-512.png +0 -0
- package/dist/server/web-ui/robots.txt +2 -0
- package/dist/src/executable-resolution/windows.js +3 -0
- package/dist/src/server/persisted-config.js +18 -2
- package/package.json +7 -7
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts +0 -42
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +0 -168
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { Readable, Writable } from "node:stream";
|
|
5
6
|
import { terminateWithTreeKill } from "../../../utils/tree-kill.js";
|
|
@@ -10,6 +11,8 @@ import { checkProviderLaunchAvailable, createProviderEnvSpec, resolveProviderLau
|
|
|
10
11
|
import { renderPromptAttachmentAsText } from "../prompt-attachments.js";
|
|
11
12
|
import { appendOrReplaceGrowingAssistantMessage, runProviderTurn } from "./provider-runner.js";
|
|
12
13
|
import { platformShell, spawnProcess } from "../../../utils/spawn.js";
|
|
14
|
+
import { toDiagnosticErrorMessage, truncateForDiagnostic, } from "./diagnostic-utils.js";
|
|
15
|
+
import { withTimeout } from "../../../utils/promise-timeout.js";
|
|
13
16
|
function assertChildWithPipes(child) {
|
|
14
17
|
if (!child.stdin || !child.stdout || !child.stderr) {
|
|
15
18
|
throw new Error("Child process did not expose stdio pipes");
|
|
@@ -70,6 +73,19 @@ function resolveTerminalCommand(command, args) {
|
|
|
70
73
|
const shell = platformShell();
|
|
71
74
|
return { command: shell.command, args: [...shell.flag, command] };
|
|
72
75
|
}
|
|
76
|
+
function formatDurationMs(startedAt) {
|
|
77
|
+
return `${Math.max(0, Date.now() - startedAt)}ms`;
|
|
78
|
+
}
|
|
79
|
+
function pushACPStderrRow(rows, stderrChunks) {
|
|
80
|
+
const stderr = stderrChunks.join("").trim();
|
|
81
|
+
if (!stderr) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
rows.push({
|
|
85
|
+
label: "ACP stderr",
|
|
86
|
+
value: truncateForDiagnostic(stderr),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
73
89
|
export const DEFAULT_ACP_CAPABILITIES = {
|
|
74
90
|
supportsStreaming: true,
|
|
75
91
|
supportsSessionPersistence: true,
|
|
@@ -96,6 +112,8 @@ const ACP_CLIENT_CAPABILITIES = {
|
|
|
96
112
|
// sign-in URL in the browser) when probing an ACP agent for models/modes.
|
|
97
113
|
// NO_BROWSER is honored by Gemini CLI; other ACP agents ignore it.
|
|
98
114
|
const PROBE_ENV = { NO_BROWSER: "true" };
|
|
115
|
+
const ACP_CATALOG_TIMEOUT_MS = 60000;
|
|
116
|
+
const ACP_DIAGNOSTIC_PHASE_TIMEOUT_MS = 20000;
|
|
99
117
|
function summarizeMalformedACPStdoutError(error) {
|
|
100
118
|
return {
|
|
101
119
|
type: error instanceof Error ? error.name : typeof error,
|
|
@@ -368,23 +386,36 @@ export class ACPAgentClient {
|
|
|
368
386
|
return session;
|
|
369
387
|
}
|
|
370
388
|
async fetchCatalog(options) {
|
|
371
|
-
const
|
|
372
|
-
const
|
|
389
|
+
const cwd = options.scope === "global" ? homedir() : options.cwd;
|
|
390
|
+
const timeoutMs = options.timeoutMs ?? ACP_CATALOG_TIMEOUT_MS;
|
|
391
|
+
let probe = null;
|
|
373
392
|
try {
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
393
|
+
const catalogProbe = (async () => {
|
|
394
|
+
const initializedProbe = await this.spawnProcess(PROBE_ENV, {
|
|
395
|
+
initializeTimeoutMs: timeoutMs,
|
|
396
|
+
onSpawned: (spawned) => {
|
|
397
|
+
probe = spawned;
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
probe = initializedProbe;
|
|
401
|
+
const response = await this.runACPRequest(() => initializedProbe.connection.newSession({
|
|
402
|
+
cwd,
|
|
403
|
+
mcpServers: [],
|
|
404
|
+
}));
|
|
405
|
+
const transformed = this.transformSessionResponse(response);
|
|
406
|
+
const models = deriveModelDefinitionsFromACP(this.provider, transformed.models, transformed.configOptions);
|
|
407
|
+
const modeInfo = deriveModesFromACP(this.defaultModes, transformed.modes, transformed.configOptions);
|
|
408
|
+
return {
|
|
409
|
+
models: this.modelTransformer ? this.modelTransformer(models) : models,
|
|
410
|
+
modes: modeInfo.modes,
|
|
411
|
+
};
|
|
412
|
+
})();
|
|
413
|
+
return await withTimeout(catalogProbe, timeoutMs, `ACP catalog probe timed out after ${timeoutMs}ms`);
|
|
385
414
|
}
|
|
386
415
|
finally {
|
|
387
|
-
|
|
416
|
+
if (probe) {
|
|
417
|
+
await this.closeProbe(probe);
|
|
418
|
+
}
|
|
388
419
|
}
|
|
389
420
|
}
|
|
390
421
|
async listFeatures(config) {
|
|
@@ -461,6 +492,28 @@ export class ACPAgentClient {
|
|
|
461
492
|
}
|
|
462
493
|
}
|
|
463
494
|
async spawnProcess(launchEnv, options) {
|
|
495
|
+
const transport = await this.spawnTransport(launchEnv);
|
|
496
|
+
const probe = {
|
|
497
|
+
child: transport.child,
|
|
498
|
+
connection: transport.connection,
|
|
499
|
+
stderrChunks: transport.stderrChunks,
|
|
500
|
+
};
|
|
501
|
+
options?.onSpawned?.(probe);
|
|
502
|
+
try {
|
|
503
|
+
const initialize = await this.initializeTransport(transport, options?.initializeTimeoutMs);
|
|
504
|
+
const initializedProbe = {
|
|
505
|
+
...probe,
|
|
506
|
+
initialize,
|
|
507
|
+
};
|
|
508
|
+
probe.initialize = initialize;
|
|
509
|
+
return initializedProbe;
|
|
510
|
+
}
|
|
511
|
+
catch (error) {
|
|
512
|
+
await terminateChildProcess(transport.child, 2000, this.terminateProcess);
|
|
513
|
+
throw error;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
async spawnTransport(launchEnv) {
|
|
464
517
|
const { command, args } = await this.resolveLaunchCommand();
|
|
465
518
|
const child = spawnProcess(command, args, {
|
|
466
519
|
cwd: process.cwd(),
|
|
@@ -481,38 +534,46 @@ export class ACPAgentClient {
|
|
|
481
534
|
reject(new Error(stderr ? `${String(error)}\n${stderr}` : String(error)));
|
|
482
535
|
});
|
|
483
536
|
});
|
|
537
|
+
const spawnReadyPromise = new Promise((resolve) => {
|
|
538
|
+
child.once("spawn", () => {
|
|
539
|
+
resolve();
|
|
540
|
+
});
|
|
541
|
+
});
|
|
484
542
|
const stream = createLoggedNdJsonStream(Writable.toWeb(child.stdin), Readable.toWeb(child.stdout), { logger: this.logger, provider: this.provider });
|
|
485
543
|
const connection = new ClientSideConnection(() => this.buildProbeClient(), stream);
|
|
544
|
+
return {
|
|
545
|
+
child,
|
|
546
|
+
connection,
|
|
547
|
+
stderrChunks,
|
|
548
|
+
spawnReady: spawnReadyPromise,
|
|
549
|
+
spawnError: spawnErrorPromise,
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
async initializeTransport(transport, initializeTimeoutMs) {
|
|
486
553
|
let timeout = null;
|
|
487
|
-
const initializeTimeoutPromise =
|
|
554
|
+
const initializeTimeoutPromise = initializeTimeoutMs
|
|
488
555
|
? new Promise((_, reject) => {
|
|
489
556
|
timeout = setTimeout(() => {
|
|
490
|
-
reject(new Error(`ACP initialize timed out after ${
|
|
491
|
-
},
|
|
557
|
+
reject(new Error(`ACP initialize timed out after ${initializeTimeoutMs}ms`));
|
|
558
|
+
}, initializeTimeoutMs);
|
|
492
559
|
})
|
|
493
560
|
: null;
|
|
494
|
-
let initialize;
|
|
495
561
|
try {
|
|
496
|
-
|
|
497
|
-
connection.initialize({
|
|
562
|
+
return await this.runACPRequest(() => Promise.race([
|
|
563
|
+
transport.connection.initialize({
|
|
498
564
|
protocolVersion: PROTOCOL_VERSION,
|
|
499
565
|
clientCapabilities: ACP_CLIENT_CAPABILITIES,
|
|
500
566
|
clientInfo: { name: "Paseo", version: "dev" },
|
|
501
567
|
}),
|
|
502
|
-
|
|
568
|
+
transport.spawnError,
|
|
503
569
|
...(initializeTimeoutPromise ? [initializeTimeoutPromise] : []),
|
|
504
570
|
]));
|
|
505
571
|
}
|
|
506
|
-
catch (error) {
|
|
507
|
-
await terminateChildProcess(child, 2000, this.terminateProcess);
|
|
508
|
-
throw error;
|
|
509
|
-
}
|
|
510
572
|
finally {
|
|
511
573
|
if (timeout) {
|
|
512
574
|
clearTimeout(timeout);
|
|
513
575
|
}
|
|
514
576
|
}
|
|
515
|
-
return { child, connection, initialize };
|
|
516
577
|
}
|
|
517
578
|
buildProbeClient() {
|
|
518
579
|
return {
|
|
@@ -536,7 +597,7 @@ export class ACPAgentClient {
|
|
|
536
597
|
}
|
|
537
598
|
async closeProbe(probe) {
|
|
538
599
|
try {
|
|
539
|
-
if (probe.initialize
|
|
600
|
+
if (probe.initialize?.agentCapabilities?.sessionCapabilities?.close) {
|
|
540
601
|
// No active session to close here; ignore capability.
|
|
541
602
|
}
|
|
542
603
|
}
|
|
@@ -552,6 +613,89 @@ export class ACPAgentClient {
|
|
|
552
613
|
throw toACPRequestError(error);
|
|
553
614
|
}
|
|
554
615
|
}
|
|
616
|
+
async buildACPProbeDiagnosticRows(options = {}) {
|
|
617
|
+
const rows = [];
|
|
618
|
+
const phaseTimeoutMs = options.phaseTimeoutMs ?? ACP_DIAGNOSTIC_PHASE_TIMEOUT_MS;
|
|
619
|
+
const cwd = options.cwd ?? homedir();
|
|
620
|
+
let transport = null;
|
|
621
|
+
try {
|
|
622
|
+
const spawnStartedAt = Date.now();
|
|
623
|
+
try {
|
|
624
|
+
transport = await this.spawnTransport(PROBE_ENV);
|
|
625
|
+
await withTimeout(Promise.race([transport.spawnReady, transport.spawnError]), phaseTimeoutMs, `ACP spawn timed out after ${phaseTimeoutMs}ms`);
|
|
626
|
+
rows.push({
|
|
627
|
+
label: "ACP spawn",
|
|
628
|
+
value: `ok (${formatDurationMs(spawnStartedAt)})`,
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
catch (error) {
|
|
632
|
+
rows.push({
|
|
633
|
+
label: "ACP spawn",
|
|
634
|
+
value: `error: ${toDiagnosticErrorMessage(error)}`,
|
|
635
|
+
});
|
|
636
|
+
return rows;
|
|
637
|
+
}
|
|
638
|
+
const activeTransport = transport;
|
|
639
|
+
const initializeStartedAt = Date.now();
|
|
640
|
+
try {
|
|
641
|
+
await this.initializeTransport(activeTransport, phaseTimeoutMs);
|
|
642
|
+
rows.push({
|
|
643
|
+
label: "ACP initialize",
|
|
644
|
+
value: `ok (${formatDurationMs(initializeStartedAt)})`,
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
catch (error) {
|
|
648
|
+
rows.push({
|
|
649
|
+
label: "ACP initialize",
|
|
650
|
+
value: `error: ${toDiagnosticErrorMessage(error)}`,
|
|
651
|
+
});
|
|
652
|
+
pushACPStderrRow(rows, activeTransport.stderrChunks);
|
|
653
|
+
return rows;
|
|
654
|
+
}
|
|
655
|
+
const sessionStartedAt = Date.now();
|
|
656
|
+
try {
|
|
657
|
+
const response = await withTimeout(this.runACPRequest(() => activeTransport.connection.newSession({
|
|
658
|
+
cwd,
|
|
659
|
+
mcpServers: [],
|
|
660
|
+
})), phaseTimeoutMs, `ACP session/new timed out after ${phaseTimeoutMs}ms`);
|
|
661
|
+
const transformed = this.transformSessionResponse(response);
|
|
662
|
+
const models = deriveModelDefinitionsFromACP(this.provider, transformed.models, transformed.configOptions);
|
|
663
|
+
const modeInfo = deriveModesFromACP(this.defaultModes, transformed.modes, transformed.configOptions);
|
|
664
|
+
rows.push({
|
|
665
|
+
label: "ACP session/new",
|
|
666
|
+
value: `ok (${formatDurationMs(sessionStartedAt)}; models=${models.length}; modes=${modeInfo.modes.length})`,
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
catch (error) {
|
|
670
|
+
rows.push({
|
|
671
|
+
label: "ACP session/new",
|
|
672
|
+
value: `error: ${toDiagnosticErrorMessage(error)}`,
|
|
673
|
+
});
|
|
674
|
+
pushACPStderrRow(rows, activeTransport.stderrChunks);
|
|
675
|
+
return rows;
|
|
676
|
+
}
|
|
677
|
+
pushACPStderrRow(rows, activeTransport.stderrChunks);
|
|
678
|
+
return rows;
|
|
679
|
+
}
|
|
680
|
+
finally {
|
|
681
|
+
if (transport) {
|
|
682
|
+
const cleanupStartedAt = Date.now();
|
|
683
|
+
try {
|
|
684
|
+
await terminateChildProcess(transport.child, 2000, this.terminateProcess);
|
|
685
|
+
rows.push({
|
|
686
|
+
label: "ACP cleanup",
|
|
687
|
+
value: `ok (${formatDurationMs(cleanupStartedAt)})`,
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
catch (error) {
|
|
691
|
+
rows.push({
|
|
692
|
+
label: "ACP cleanup",
|
|
693
|
+
value: `error: ${toDiagnosticErrorMessage(error)}`,
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
555
699
|
async resolveLaunchCommand() {
|
|
556
700
|
const prefix = await resolveProviderLaunch({
|
|
557
701
|
commandConfig: this.runtimeSettings?.command,
|
|
@@ -658,6 +802,13 @@ export class ACPAgentSession {
|
|
|
658
802
|
this.applySessionState(response);
|
|
659
803
|
await this.applyConfiguredOverrides();
|
|
660
804
|
}
|
|
805
|
+
/**
|
|
806
|
+
* IMPORTANT: Some ACP providers (e.g., Devin CLI) require all three params
|
|
807
|
+
* (sessionId, cwd, mcpServers) to be present in session/load or
|
|
808
|
+
* unstable_resumeSession — even when mcpServers is an empty array — and
|
|
809
|
+
* return "Invalid params" if any are omitted. Never drop cwd or mcpServers
|
|
810
|
+
* from these calls regardless of capabilities.
|
|
811
|
+
*/
|
|
661
812
|
async initializeResumedSession() {
|
|
662
813
|
const handle = this.initialHandle;
|
|
663
814
|
if (!handle) {
|
|
@@ -17,10 +17,12 @@ import { realClaudeRewindSdk, revertClaudeConversation, revertClaudeFiles } from
|
|
|
17
17
|
import { normalizeProviderReplayTimestamp } from "../../provider-history-timestamps.js";
|
|
18
18
|
import { claudeProjectDirSync } from "./project-dir.js";
|
|
19
19
|
import { SETTING_APPLIES_NEXT_TURN_NOTICE } from "../../provider-notices.js";
|
|
20
|
+
import { isProviderImageMarkdown, materializeProviderImage, renderProviderImageOutputAsAssistantMarkdown, } from "../provider-image-output.js";
|
|
20
21
|
import { getAgentStreamEventTurnId, } from "../../agent-sdk-types.js";
|
|
21
22
|
import { importSessionFromPersistence } from "../../provider-session-import.js";
|
|
22
23
|
import { checkProviderLaunchAvailable, createProviderEnv, createProviderEnvSpec, resolveProviderLaunch, } from "../../provider-launch-config.js";
|
|
23
24
|
import { withTimeout } from "../../../../utils/promise-timeout.js";
|
|
25
|
+
import { terminateWithTreeKill } from "../../../../utils/tree-kill.js";
|
|
24
26
|
import { execCommand } from "../../../../utils/spawn.js";
|
|
25
27
|
import { composeSystemPromptParts } from "../../system-prompt.js";
|
|
26
28
|
const fsPromises = promises;
|
|
@@ -370,6 +372,39 @@ function coerceToolResultContentToString(content) {
|
|
|
370
372
|
}
|
|
371
373
|
return deterministicStringify(content);
|
|
372
374
|
}
|
|
375
|
+
function toBase64ImageOutput(block) {
|
|
376
|
+
const record = toObjectRecord(block);
|
|
377
|
+
if (!record || record.type !== "image") {
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
const source = toObjectRecord(record.source);
|
|
381
|
+
if (!source || source.type !== "base64" || typeof source.data !== "string") {
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
data: source.data,
|
|
386
|
+
mimeType: typeof source.media_type === "string" ? source.media_type : null,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
// Claude returns images inside tool_result content as base64 Anthropic blocks. Left in place they
|
|
390
|
+
// reach coerceToolResultContentToString, which JSON.stringifies the whole array — dumping base64
|
|
391
|
+
// into the tool output. We pull those blocks out to render them as image markdown and leave a
|
|
392
|
+
// "[image]" placeholder so image-only results still produce non-empty output.
|
|
393
|
+
function splitClaudeToolResultImages(content) {
|
|
394
|
+
if (!Array.isArray(content)) {
|
|
395
|
+
return { images: [], text: content };
|
|
396
|
+
}
|
|
397
|
+
const images = [];
|
|
398
|
+
const text = content.map((block) => {
|
|
399
|
+
const image = toBase64ImageOutput(block);
|
|
400
|
+
if (image) {
|
|
401
|
+
images.push(image);
|
|
402
|
+
return { type: "text", text: "[image]" };
|
|
403
|
+
}
|
|
404
|
+
return block;
|
|
405
|
+
});
|
|
406
|
+
return { images, text };
|
|
407
|
+
}
|
|
373
408
|
function normalizeClaudeTranscriptText(value) {
|
|
374
409
|
if (typeof value !== "string") {
|
|
375
410
|
return null;
|
|
@@ -1255,6 +1290,13 @@ function readLegacyResultUsageTokens(usage) {
|
|
|
1255
1290
|
function isClaudeSubagentToolName(name) {
|
|
1256
1291
|
return name === "Task" || name === "Agent";
|
|
1257
1292
|
}
|
|
1293
|
+
function readClaudeParentToolUseId(message) {
|
|
1294
|
+
if (!("parent_tool_use_id" in message)) {
|
|
1295
|
+
return null;
|
|
1296
|
+
}
|
|
1297
|
+
const parentToolUseId = message.parent_tool_use_id;
|
|
1298
|
+
return typeof parentToolUseId === "string" && parentToolUseId.length > 0 ? parentToolUseId : null;
|
|
1299
|
+
}
|
|
1258
1300
|
class ClaudeContextUsageState {
|
|
1259
1301
|
constructor(initialContextWindowMaxTokens) {
|
|
1260
1302
|
this.completedResultTurns = 0;
|
|
@@ -1380,6 +1422,7 @@ class ClaudeAgentSession {
|
|
|
1380
1422
|
this.provider = "claude";
|
|
1381
1423
|
this.capabilities = CLAUDE_CAPABILITIES;
|
|
1382
1424
|
this.query = null;
|
|
1425
|
+
this.childProcess = null;
|
|
1383
1426
|
this.input = null;
|
|
1384
1427
|
this.planResumeMode = null;
|
|
1385
1428
|
this.availableModes = DEFAULT_MODES;
|
|
@@ -1853,6 +1896,19 @@ class ClaudeAgentSession {
|
|
|
1853
1896
|
await this.awaitWithTimeout(this.query?.return?.(), "close query return");
|
|
1854
1897
|
this.query = null;
|
|
1855
1898
|
this.input = null;
|
|
1899
|
+
// Terminate the entire process tree (claude + MCP children) to prevent
|
|
1900
|
+
// orphan accumulation. The SDK's internal cleanup may only kill the
|
|
1901
|
+
// direct child process.
|
|
1902
|
+
if (this.childProcess) {
|
|
1903
|
+
const result = await terminateWithTreeKill(this.childProcess, {
|
|
1904
|
+
gracefulTimeoutMs: 2000,
|
|
1905
|
+
forceTimeoutMs: 2000,
|
|
1906
|
+
});
|
|
1907
|
+
if (result === "kill-timeout") {
|
|
1908
|
+
this.logger.warn({ pid: this.childProcess.pid, agentId: this.agentId }, "Claude process tree did not report exit after SIGKILL");
|
|
1909
|
+
}
|
|
1910
|
+
this.childProcess = null;
|
|
1911
|
+
}
|
|
1856
1912
|
if (this.persistSession === false && this.claudeSessionId) {
|
|
1857
1913
|
// Claude Code currently ignores --no-session-persistence outside --print mode
|
|
1858
1914
|
// (see `claude --help`), so the SDK's persistSession=false is silently dropped
|
|
@@ -2191,6 +2247,18 @@ class ClaudeAgentSession {
|
|
|
2191
2247
|
catch {
|
|
2192
2248
|
/* ignore */
|
|
2193
2249
|
}
|
|
2250
|
+
// Tree-kill the old process tree now that the SDK has cleaned up.
|
|
2251
|
+
// If we skip this, MCP children of the previous claude process can
|
|
2252
|
+
// survive as orphans when the session spawns a replacement query.
|
|
2253
|
+
if (this.childProcess) {
|
|
2254
|
+
await terminateWithTreeKill(this.childProcess, {
|
|
2255
|
+
gracefulTimeoutMs: 2000,
|
|
2256
|
+
forceTimeoutMs: 2000,
|
|
2257
|
+
}).catch(() => {
|
|
2258
|
+
/* process may already be dead */
|
|
2259
|
+
});
|
|
2260
|
+
this.childProcess = null;
|
|
2261
|
+
}
|
|
2194
2262
|
}
|
|
2195
2263
|
// Preserve claudeSessionId across query recreation so buildOptions() passes
|
|
2196
2264
|
// resume: sessionId and the new query continues the existing conversation.
|
|
@@ -2203,6 +2271,9 @@ class ClaudeAgentSession {
|
|
|
2203
2271
|
runtimeSettings: this.runtimeSettings,
|
|
2204
2272
|
launchEnv: this.launchEnv,
|
|
2205
2273
|
queryFactory: this.queryFactory,
|
|
2274
|
+
onChildProcess: (child) => {
|
|
2275
|
+
this.childProcess = child;
|
|
2276
|
+
},
|
|
2206
2277
|
});
|
|
2207
2278
|
const fastMode = this.resolveFastModeSetting();
|
|
2208
2279
|
if (fastMode !== null) {
|
|
@@ -2775,17 +2846,19 @@ class ClaudeAgentSession {
|
|
|
2775
2846
|
suppressAssistantText: true,
|
|
2776
2847
|
suppressReasoning: true,
|
|
2777
2848
|
});
|
|
2778
|
-
const assistantTimelineEvents =
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2849
|
+
const assistantTimelineEvents = readClaudeParentToolUseId(message)
|
|
2850
|
+
? []
|
|
2851
|
+
: this.timelineAssembler
|
|
2852
|
+
.consume({
|
|
2853
|
+
message,
|
|
2854
|
+
runId: turnId,
|
|
2855
|
+
messageIdHint,
|
|
2856
|
+
})
|
|
2857
|
+
.map((item) => ({
|
|
2858
|
+
type: "timeline",
|
|
2859
|
+
item,
|
|
2860
|
+
provider: "claude",
|
|
2861
|
+
}));
|
|
2789
2862
|
return [...messageEvents, ...assistantTimelineEvents];
|
|
2790
2863
|
}
|
|
2791
2864
|
async handleMissingResumedConversation(message, activeQuery) {
|
|
@@ -2833,9 +2906,7 @@ class ClaudeAgentSession {
|
|
|
2833
2906
|
}
|
|
2834
2907
|
}
|
|
2835
2908
|
translateMessageToEvents(message, options) {
|
|
2836
|
-
const parentToolUseId =
|
|
2837
|
-
? message.parent_tool_use_id
|
|
2838
|
-
: null;
|
|
2909
|
+
const parentToolUseId = readClaudeParentToolUseId(message);
|
|
2839
2910
|
if (parentToolUseId) {
|
|
2840
2911
|
return this.sidechainTracker.handleMessage(message, parentToolUseId);
|
|
2841
2912
|
}
|
|
@@ -3472,15 +3543,17 @@ class ClaudeAgentSession {
|
|
|
3472
3543
|
const callId = typeof block.tool_use_id === "string" && block.tool_use_id.length > 0
|
|
3473
3544
|
? block.tool_use_id
|
|
3474
3545
|
: (entry?.id ?? null);
|
|
3475
|
-
//
|
|
3476
|
-
|
|
3546
|
+
// Pull image blocks out of the result so base64 never reaches the tool output, and render each
|
|
3547
|
+
// one as an assistant_message markdown image after the tool_call (matching how Codex emits).
|
|
3548
|
+
const { images, text } = splitClaudeToolResultImages(block.content);
|
|
3549
|
+
const output = this.buildToolOutput(text, block, entry);
|
|
3477
3550
|
if (block.is_error) {
|
|
3478
3551
|
this.pushToolCall(mapClaudeFailedToolCall({
|
|
3479
3552
|
name: toolName,
|
|
3480
3553
|
callId,
|
|
3481
3554
|
input: entry?.input ?? null,
|
|
3482
3555
|
output: output ?? null,
|
|
3483
|
-
error: block,
|
|
3556
|
+
error: { ...block, content: text },
|
|
3484
3557
|
}), items);
|
|
3485
3558
|
}
|
|
3486
3559
|
else {
|
|
@@ -3491,12 +3564,20 @@ class ClaudeAgentSession {
|
|
|
3491
3564
|
output: output ?? null,
|
|
3492
3565
|
}), items);
|
|
3493
3566
|
}
|
|
3567
|
+
for (const image of images) {
|
|
3568
|
+
const imageItem = renderProviderImageOutputAsAssistantMarkdown(image, {
|
|
3569
|
+
materialize: materializeProviderImage,
|
|
3570
|
+
});
|
|
3571
|
+
if (imageItem) {
|
|
3572
|
+
items.push(imageItem);
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3494
3575
|
if (typeof block.tool_use_id === "string") {
|
|
3495
3576
|
this.toolUseCache.delete(block.tool_use_id);
|
|
3496
3577
|
this.sidechainTracker.delete(block.tool_use_id);
|
|
3497
3578
|
}
|
|
3498
3579
|
}
|
|
3499
|
-
buildToolOutput(block, entry) {
|
|
3580
|
+
buildToolOutput(content, block, entry) {
|
|
3500
3581
|
if (block.is_error) {
|
|
3501
3582
|
return undefined;
|
|
3502
3583
|
}
|
|
@@ -3504,23 +3585,23 @@ class ClaudeAgentSession {
|
|
|
3504
3585
|
const blockToolName = typeof block.tool_name === "string" ? block.tool_name : undefined;
|
|
3505
3586
|
const server = entry?.server ?? blockServer ?? "tool";
|
|
3506
3587
|
const tool = entry?.name ?? blockToolName ?? "tool";
|
|
3507
|
-
const
|
|
3588
|
+
const coercedContent = coerceToolResultContentToString(content);
|
|
3508
3589
|
const input = entry?.input;
|
|
3509
3590
|
// Build structured result based on tool type
|
|
3510
|
-
const structured = this.buildStructuredToolResult(server, tool,
|
|
3591
|
+
const structured = this.buildStructuredToolResult(server, tool, coercedContent, input);
|
|
3511
3592
|
if (structured) {
|
|
3512
3593
|
return structured;
|
|
3513
3594
|
}
|
|
3514
3595
|
// Fallback format - try to parse JSON first
|
|
3515
3596
|
const result = {};
|
|
3516
|
-
if (
|
|
3597
|
+
if (coercedContent.length > 0) {
|
|
3517
3598
|
try {
|
|
3518
3599
|
// If content is a JSON string, parse it
|
|
3519
|
-
result.output = JSON.parse(
|
|
3600
|
+
result.output = JSON.parse(coercedContent);
|
|
3520
3601
|
}
|
|
3521
3602
|
catch {
|
|
3522
3603
|
// If not JSON, return unchanged (no extra wrapping)
|
|
3523
|
-
result.output =
|
|
3604
|
+
result.output = coercedContent;
|
|
3524
3605
|
}
|
|
3525
3606
|
}
|
|
3526
3607
|
// Preserve file changes tracked during tool execution
|
|
@@ -3945,6 +4026,9 @@ function convertClaudeHistoryEntryPreamble(entry) {
|
|
|
3945
4026
|
}
|
|
3946
4027
|
return { proceed: { content } };
|
|
3947
4028
|
}
|
|
4029
|
+
function isProviderImageMessage(item) {
|
|
4030
|
+
return item.type === "assistant_message" && isProviderImageMarkdown(item.text);
|
|
4031
|
+
}
|
|
3948
4032
|
export function convertClaudeHistoryEntry(entry, mapBlocks) {
|
|
3949
4033
|
const preamble = convertClaudeHistoryEntryPreamble(entry);
|
|
3950
4034
|
if ("shortCircuit" in preamble) {
|
|
@@ -3980,7 +4064,10 @@ export function convertClaudeHistoryEntry(entry, mapBlocks) {
|
|
|
3980
4064
|
if (hasToolBlock && normalizedBlocks) {
|
|
3981
4065
|
const mapped = mapBlocks(normalizedBlocks);
|
|
3982
4066
|
if (entry.type === "user") {
|
|
3983
|
-
|
|
4067
|
+
// tool_result handling (handleToolResult) emits image markdown as an assistant_message
|
|
4068
|
+
// alongside the tool_call. User-entry text blocks also map to assistant_message in this path
|
|
4069
|
+
// and must stay suppressed, so keep tool_calls plus only the image assistant_messages.
|
|
4070
|
+
const toolItems = mapped.filter((item) => item.type === "tool_call" || isProviderImageMessage(item));
|
|
3984
4071
|
return timeline.length ? [...timeline, ...toolItems] : toolItems;
|
|
3985
4072
|
}
|
|
3986
4073
|
return mapped;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ChildProcess } from "node:child_process";
|
|
1
2
|
import { query, type Options, type Query } from "@anthropic-ai/claude-agent-sdk";
|
|
2
3
|
import { type ProviderRuntimeSettings } from "../../provider-launch-config.js";
|
|
3
4
|
export type ClaudeOptions = Options;
|
|
@@ -9,6 +10,8 @@ export interface ClaudeQueryContext {
|
|
|
9
10
|
runtimeSettings?: ProviderRuntimeSettings;
|
|
10
11
|
launchEnv?: Record<string, string>;
|
|
11
12
|
queryFactory?: ClaudeQueryFactory;
|
|
13
|
+
/** Called with the spawned child process so the caller can tree-kill it on close. */
|
|
14
|
+
onChildProcess?: (child: ChildProcess) => void;
|
|
12
15
|
}
|
|
13
16
|
export declare function claudeQuery(input: ClaudeQueryInput, context?: ClaudeQueryContext): Query;
|
|
14
17
|
//# sourceMappingURL=query.d.ts.map
|
|
@@ -24,7 +24,8 @@ function resolveClaudeSpawnCommand(spawnOptions, runtimeSettings) {
|
|
|
24
24
|
args: [...commandConfig.argv.slice(1), ...spawnOptions.args],
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
-
function applyRuntimeSettingsToClaudeOptions(options,
|
|
27
|
+
function applyRuntimeSettingsToClaudeOptions(options, context) {
|
|
28
|
+
const { runtimeSettings, launchEnv, onChildProcess } = context;
|
|
28
29
|
return {
|
|
29
30
|
...options,
|
|
30
31
|
spawnClaudeCodeProcess: (spawnOptions) => {
|
|
@@ -62,6 +63,7 @@ function applyRuntimeSettingsToClaudeOptions(options, runtimeSettings, launchEnv
|
|
|
62
63
|
// The command is always a resolved binary path, so shell routing is unnecessary.
|
|
63
64
|
shell: false,
|
|
64
65
|
});
|
|
66
|
+
onChildProcess?.(child);
|
|
65
67
|
if (typeof options.stderr === "function") {
|
|
66
68
|
child.stderr?.on("data", (chunk) => {
|
|
67
69
|
options.stderr?.(chunk.toString());
|
|
@@ -78,7 +80,7 @@ export function claudeQuery(input, context = {}) {
|
|
|
78
80
|
const launchQuery = context.queryFactory ?? query;
|
|
79
81
|
return launchQuery({
|
|
80
82
|
...input,
|
|
81
|
-
options: applyRuntimeSettingsToClaudeOptions(input.options, context
|
|
83
|
+
options: applyRuntimeSettingsToClaudeOptions(input.options, context),
|
|
82
84
|
});
|
|
83
85
|
}
|
|
84
86
|
//# sourceMappingURL=query.js.map
|