@oh-my-pi/pi-coding-agent 17.0.9 → 17.1.1
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 +78 -0
- package/README.md +1 -1
- package/dist/cli.js +4685 -4614
- package/dist/types/async/job-manager.d.ts +37 -1
- package/dist/types/cli/args.d.ts +2 -0
- package/dist/types/cli/bench-cli.d.ts +41 -0
- package/dist/types/commands/bench.d.ts +15 -3
- package/dist/types/commands/launch.d.ts +4 -0
- package/dist/types/config/model-registry.d.ts +3 -1
- package/dist/types/config/models-config-schema.d.ts +18 -6
- package/dist/types/config/models-config.d.ts +14 -5
- package/dist/types/config/provider-globals.d.ts +2 -2
- package/dist/types/config/service-tier.d.ts +5 -1
- package/dist/types/config/settings-schema.d.ts +374 -47
- package/dist/types/config/settings.d.ts +7 -0
- package/dist/types/dap/client.d.ts +20 -0
- package/dist/types/exec/bash-executor.d.ts +38 -0
- package/dist/types/exec/direnv.d.ts +33 -0
- package/dist/types/export/html/args.d.ts +15 -0
- package/dist/types/export/html/index.d.ts +11 -26
- package/dist/types/export/html/web-palette.d.ts +55 -116
- package/dist/types/extensibility/extensions/loader.d.ts +3 -0
- package/dist/types/extensibility/extensions/types.d.ts +17 -2
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +3 -0
- package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +13 -0
- package/dist/types/live/attestation.d.ts +2 -0
- package/dist/types/live/controller.d.ts +48 -0
- package/dist/types/live/protocol.d.ts +85 -0
- package/dist/types/live/protocol.test.d.ts +1 -0
- package/dist/types/live/transport.d.ts +35 -0
- package/dist/types/live/visualizer.d.ts +30 -0
- package/dist/types/lsp/client.d.ts +16 -1
- package/dist/types/mcp/config-writer.test.d.ts +1 -0
- package/dist/types/mcp/oauth-discovery.d.ts +2 -0
- package/dist/types/mcp/smithery-auth.d.ts +1 -1
- package/dist/types/mcp/smithery-auth.test.d.ts +1 -0
- package/dist/types/memory-backend/tool-names.d.ts +2 -0
- package/dist/types/modes/components/assistant-message.d.ts +1 -0
- package/dist/types/modes/components/custom-message.d.ts +1 -1
- package/dist/types/modes/components/login-dialog.d.ts +2 -2
- package/dist/types/modes/components/message-frame.d.ts +8 -4
- package/dist/types/modes/components/plan-review-overlay.d.ts +26 -0
- package/dist/types/modes/components/session-account-selector.d.ts +11 -0
- package/dist/types/modes/components/settings-defs.d.ts +7 -1
- package/dist/types/modes/components/status-line/component.jj-cache.test.d.ts +1 -0
- package/dist/types/modes/components/tool-execution.d.ts +9 -1
- package/dist/types/modes/controllers/command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/event-controller.d.ts +6 -1
- package/dist/types/modes/controllers/live-command-controller.d.ts +14 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +6 -0
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +4 -1
- package/dist/types/modes/utils/context-usage.d.ts +12 -2
- package/dist/types/plan-mode/plan-files.d.ts +10 -0
- package/dist/types/registry/agent-lifecycle.d.ts +21 -9
- package/dist/types/registry/agent-registry.d.ts +11 -4
- package/dist/types/sdk.d.ts +15 -1
- package/dist/types/secrets/index.d.ts +15 -2
- package/dist/types/secrets/obfuscator.d.ts +113 -15
- package/dist/types/session/acp-permission-gate.d.ts +19 -0
- package/dist/types/session/agent-session-events.d.ts +84 -0
- package/dist/types/session/agent-session-types.d.ts +321 -0
- package/dist/types/session/agent-session.d.ts +135 -753
- package/dist/types/session/async-job-delivery.d.ts +28 -0
- package/dist/types/session/auth-storage.d.ts +1 -1
- package/dist/types/session/bash-runner.d.ts +75 -0
- package/dist/types/session/blob-store.d.ts +11 -1
- package/dist/types/session/blob-store.test.d.ts +1 -0
- package/dist/types/session/checkpoint-entries.d.ts +28 -0
- package/dist/types/session/eval-runner.d.ts +51 -0
- package/dist/types/session/irc-bridge.d.ts +46 -0
- package/dist/types/session/messages.d.ts +24 -0
- package/dist/types/session/model-controls.d.ts +180 -0
- package/dist/types/session/prewalk.d.ts +46 -0
- package/dist/types/session/queued-messages.d.ts +22 -0
- package/dist/types/session/redis-session-storage.d.ts +1 -0
- package/dist/types/session/retry-fallback-chains.d.ts +74 -0
- package/dist/types/session/role-models.d.ts +15 -0
- package/dist/types/session/session-advisors.d.ts +228 -0
- package/dist/types/session/session-entries.d.ts +8 -0
- package/dist/types/session/session-handoff.d.ts +70 -0
- package/dist/types/session/session-history-format.d.ts +6 -1
- package/dist/types/session/session-maintenance.d.ts +246 -0
- package/dist/types/session/session-manager.d.ts +41 -0
- package/dist/types/session/session-memory.d.ts +56 -0
- package/dist/types/session/session-provider-boundary.d.ts +62 -0
- package/dist/types/session/session-stats.d.ts +48 -0
- package/dist/types/session/session-tools.d.ts +158 -0
- package/dist/types/session/session-workspace.d.ts +32 -0
- package/dist/types/session/stream-guards.d.ts +44 -0
- package/dist/types/session/streaming-output.d.ts +8 -0
- package/dist/types/session/todo-tracker.d.ts +56 -0
- package/dist/types/session/ttsr-coordinator.d.ts +51 -0
- package/dist/types/session/turn-recovery.d.ts +225 -0
- package/dist/types/slash-commands/helpers/session-pin.d.ts +9 -0
- package/dist/types/stt/index.d.ts +0 -2
- package/dist/types/stt/stt-controller.d.ts +7 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +4 -1
- package/dist/types/task/output-manager.d.ts +3 -1
- package/dist/types/tiny/title-client.d.ts +10 -0
- package/dist/types/tools/approval.d.ts +1 -0
- package/dist/types/tools/browser/launch.d.ts +5 -0
- package/dist/types/tools/builtin-names.d.ts +1 -1
- package/dist/types/tools/computer/protocol.d.ts +43 -0
- package/dist/types/tools/computer/supervisor.d.ts +32 -0
- package/dist/types/tools/computer/worker-entry.d.ts +1 -0
- package/dist/types/tools/computer/worker.d.ts +15 -0
- package/dist/types/tools/computer-renderer.d.ts +22 -0
- package/dist/types/tools/computer.d.ts +71 -0
- package/dist/types/tools/context.d.ts +2 -0
- package/dist/types/tools/default-renderer.d.ts +21 -0
- package/dist/types/tools/image-gen.d.ts +4 -4
- package/dist/types/tools/image-providers.d.ts +38 -0
- package/dist/types/tools/index.d.ts +7 -0
- package/dist/types/tools/path-utils.d.ts +8 -0
- package/dist/types/tools/todo.d.ts +10 -4
- package/dist/types/tools/xdev.d.ts +5 -1
- package/dist/types/tts/streaming-player.d.ts +10 -29
- package/dist/types/tts/vocalizer.d.ts +5 -0
- package/dist/types/utils/jj.d.ts +29 -0
- package/dist/types/utils/lang-from-path.d.ts +1 -0
- package/dist/types/utils/title-generator.d.ts +30 -0
- package/dist/types/utils/tools-manager.d.ts +1 -2
- package/dist/types/vibe/runtime.d.ts +36 -8
- package/dist/types/web/search/index.d.ts +1 -1
- package/dist/types/web/search/provider.d.ts +15 -5
- package/dist/types/web/search/types.d.ts +94 -0
- package/package.json +12 -12
- package/scripts/generate-share-viewer.ts +4 -6
- package/src/advisor/__tests__/advisor.test.ts +643 -0
- package/src/advisor/runtime.ts +144 -43
- package/src/async/job-manager.ts +90 -2
- package/src/cli/args.ts +3 -0
- package/src/cli/auth-gateway-cli.ts +18 -3
- package/src/cli/bench-cli.ts +395 -29
- package/src/cli/flag-tables.ts +3 -0
- package/src/cli/gc-cli.ts +2 -2
- package/src/cli/setup-cli.ts +2 -14
- package/src/cli/usage-cli.ts +10 -1
- package/src/cli.ts +8 -0
- package/src/collab/host.ts +3 -2
- package/src/commands/bench.ts +18 -4
- package/src/commands/launch.ts +4 -0
- package/src/config/model-registry.ts +16 -2
- package/src/config/models-config-schema.ts +15 -4
- package/src/config/provider-globals.ts +9 -9
- package/src/config/service-tier.ts +26 -1
- package/src/config/settings-schema.ts +270 -51
- package/src/config/settings.ts +81 -2
- package/src/dap/client.ts +37 -4
- package/src/edit/index.ts +49 -12
- package/src/eval/executor-base.ts +1 -0
- package/src/eval/js/executor.ts +2 -0
- package/src/eval/py/executor.ts +103 -33
- package/src/exec/bash-executor.ts +90 -6
- package/src/exec/direnv.ts +145 -0
- package/src/export/html/args.ts +20 -0
- package/src/export/html/index.ts +45 -47
- package/src/export/html/template.css +19 -1
- package/src/export/html/template.html +6 -0
- package/src/export/html/template.js +21 -0
- package/src/export/html/tool-views.generated.js +31 -31
- package/src/export/html/web-palette.ts +116 -132
- package/src/export/share.ts +249 -49
- package/src/extensibility/extensions/loader.ts +29 -1
- package/src/extensibility/extensions/runner.ts +6 -0
- package/src/extensibility/extensions/types.ts +33 -2
- package/src/extensibility/extensions/wrapper.ts +68 -12
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +7 -1
- package/src/extensibility/plugins/legacy-pi-compat.ts +19 -1
- package/src/hindsight/state.ts +64 -6
- package/src/internal-urls/local-protocol.ts +2 -1
- package/src/internal-urls/memory-protocol.ts +2 -2
- package/src/internal-urls/skill-protocol.ts +2 -2
- package/src/internal-urls/ssh-protocol.ts +2 -1
- package/src/internal-urls/vault-protocol.ts +2 -1
- package/src/live/attestation.ts +91 -0
- package/src/live/controller.ts +517 -0
- package/src/live/prompts/agent-final-message.md +3 -0
- package/src/live/prompts/live-instructions.md +23 -0
- package/src/live/protocol.test.ts +140 -0
- package/src/live/protocol.ts +233 -0
- package/src/live/transport.ts +422 -0
- package/src/live/visualizer.ts +214 -0
- package/src/lsp/client.ts +29 -9
- package/src/lsp/index.ts +19 -4
- package/src/main.ts +8 -1
- package/src/mcp/config-writer.test.ts +43 -0
- package/src/mcp/config-writer.ts +109 -82
- package/src/mcp/oauth-discovery.ts +10 -2
- package/src/mcp/smithery-auth.test.ts +29 -0
- package/src/mcp/smithery-auth.ts +3 -2
- package/src/memories/index.ts +40 -20
- package/src/memory-backend/tool-names.ts +2 -0
- package/src/mnemopi/backend.ts +24 -7
- package/src/modes/acp/acp-agent.ts +56 -10
- package/src/modes/acp/acp-event-mapper.ts +8 -1
- package/src/modes/components/agent-hub.ts +1 -1
- package/src/modes/components/assistant-message.ts +7 -2
- package/src/modes/components/custom-message.ts +4 -1
- package/src/modes/components/login-dialog.ts +14 -4
- package/src/modes/components/message-frame.ts +14 -8
- package/src/modes/components/plan-review-overlay.ts +350 -35
- package/src/modes/components/session-account-selector.ts +62 -0
- package/src/modes/components/settings-defs.ts +23 -1
- package/src/modes/components/settings-selector.ts +169 -1
- package/src/modes/components/status-line/component.jj-cache.test.ts +229 -0
- package/src/modes/components/status-line/component.ts +123 -2
- package/src/modes/components/tool-execution.ts +28 -112
- package/src/modes/controllers/command-controller.ts +56 -15
- package/src/modes/controllers/event-controller.ts +111 -16
- package/src/modes/controllers/extension-ui-controller.test.ts +1 -0
- package/src/modes/controllers/extension-ui-controller.ts +20 -4
- package/src/modes/controllers/input-controller.ts +47 -39
- package/src/modes/controllers/live-command-controller.ts +255 -0
- package/src/modes/controllers/mcp-command-controller.ts +10 -1
- package/src/modes/controllers/omfg-controller.ts +44 -40
- package/src/modes/controllers/selector-controller.ts +80 -10
- package/src/modes/controllers/session-focus-controller.ts +6 -1
- package/src/modes/interactive-mode.ts +176 -38
- package/src/modes/runtime-init.ts +2 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +17 -9
- package/src/modes/theme/theme.ts +1 -1
- package/src/modes/types.ts +4 -1
- package/src/modes/utils/context-usage.ts +23 -7
- package/src/modes/utils/ui-helpers.ts +10 -5
- package/src/plan-mode/plan-files.ts +40 -0
- package/src/prompts/bench/cache-prefix-chunk.md +1 -0
- package/src/prompts/bench/cache-prefix.md +3 -0
- package/src/prompts/bench/cache-suffix.md +1 -0
- package/src/prompts/system/computer-safety.md +14 -0
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/project-prompt.md +8 -1
- package/src/prompts/system/subagent-async-pending.md +6 -0
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/prompts/system/workflow-notice.md +48 -40
- package/src/prompts/system/xdev-mount-notice.md +4 -0
- package/src/prompts/tools/computer.md +26 -0
- package/src/prompts/tools/todo.md +3 -1
- package/src/registry/agent-lifecycle.ts +116 -46
- package/src/registry/agent-registry.ts +35 -8
- package/src/registry/persisted-agents.ts +26 -2
- package/src/sdk.ts +215 -136
- package/src/secrets/index.ts +127 -4
- package/src/secrets/obfuscator.ts +2328 -105
- package/src/session/acp-permission-gate.ts +165 -0
- package/src/session/agent-session-error-log.test.ts +1 -1
- package/src/session/agent-session-events.ts +66 -0
- package/src/session/agent-session-types.ts +343 -0
- package/src/session/agent-session.ts +1940 -12218
- package/src/session/artifacts.ts +6 -5
- package/src/session/async-job-delivery.ts +74 -0
- package/src/session/auth-storage.ts +1 -0
- package/src/session/bash-runner.ts +326 -0
- package/src/session/blob-store.test.ts +56 -0
- package/src/session/blob-store.ts +18 -2
- package/src/session/checkpoint-entries.ts +81 -0
- package/src/session/eval-runner.ts +217 -0
- package/src/session/indexed-session-storage.ts +9 -2
- package/src/session/irc-bridge.ts +203 -0
- package/src/session/messages.ts +266 -1
- package/src/session/model-controls.ts +714 -0
- package/src/session/prewalk.ts +252 -0
- package/src/session/queued-messages.ts +93 -0
- package/src/session/redis-session-storage.ts +51 -11
- package/src/session/retry-fallback-chains.ts +455 -0
- package/src/session/role-models.ts +85 -0
- package/src/session/session-advisors.ts +1679 -0
- package/src/session/session-context.ts +6 -3
- package/src/session/session-entries.ts +8 -0
- package/src/session/session-handoff.ts +308 -0
- package/src/session/session-history-format.ts +20 -9
- package/src/session/session-loader.ts +0 -46
- package/src/session/session-maintenance.ts +2983 -0
- package/src/session/session-manager.ts +390 -30
- package/src/session/session-memory.ts +222 -0
- package/src/session/session-provider-boundary.ts +307 -0
- package/src/session/session-stats.ts +293 -0
- package/src/session/session-tools.ts +980 -0
- package/src/session/session-workspace.ts +53 -0
- package/src/session/stream-guards.ts +417 -0
- package/src/session/streaming-output.ts +52 -5
- package/src/session/todo-tracker.ts +380 -0
- package/src/session/ttsr-coordinator.ts +496 -0
- package/src/session/turn-recovery.ts +1629 -0
- package/src/slash-commands/builtin-registry.ts +257 -20
- package/src/slash-commands/helpers/session-pin.ts +44 -0
- package/src/slash-commands/helpers/usage-report.ts +22 -3
- package/src/stt/downloader.ts +0 -2
- package/src/stt/index.ts +0 -2
- package/src/stt/stt-controller.ts +57 -146
- package/src/system-prompt.ts +45 -17
- package/src/task/executor.ts +285 -70
- package/src/task/index.ts +98 -105
- package/src/task/output-manager.ts +25 -3
- package/src/task/persisted-revive.ts +4 -3
- package/src/task/structured-subagent.ts +1 -0
- package/src/tiny/title-client.ts +22 -0
- package/src/tools/approval.ts +55 -10
- package/src/tools/bash-interactive.ts +116 -86
- package/src/tools/bash-skill-urls.ts +28 -2
- package/src/tools/bash.ts +339 -123
- package/src/tools/browser/launch.ts +9 -1
- package/src/tools/browser/tab-supervisor.ts +8 -5
- package/src/tools/browser.ts +94 -47
- package/src/tools/builtin-names.ts +1 -0
- package/src/tools/computer/protocol.ts +28 -0
- package/src/tools/computer/supervisor.ts +258 -0
- package/src/tools/computer/worker-entry.ts +25 -0
- package/src/tools/computer/worker.ts +135 -0
- package/src/tools/computer-renderer.ts +108 -0
- package/src/tools/computer.ts +433 -0
- package/src/tools/context.ts +2 -0
- package/src/tools/default-renderer.ts +139 -0
- package/src/tools/essential-tools.ts +1 -0
- package/src/tools/image-gen.ts +20 -28
- package/src/tools/image-providers.ts +50 -0
- package/src/tools/index.ts +14 -0
- package/src/tools/path-utils.ts +49 -2
- package/src/tools/read.ts +156 -88
- package/src/tools/renderers.ts +9 -1
- package/src/tools/todo.ts +101 -11
- package/src/tools/vibe.ts +1 -2
- package/src/tools/write.ts +51 -1
- package/src/tools/xdev.ts +121 -29
- package/src/tts/streaming-player.ts +82 -283
- package/src/tts/vocalizer.ts +18 -1
- package/src/utils/clipboard.ts +1 -30
- package/src/utils/jj.ts +125 -4
- package/src/utils/lang-from-path.ts +7 -0
- package/src/utils/mac-file-urls.applescript +37 -0
- package/src/utils/title-generator.ts +137 -1
- package/src/utils/tool-choice.ts +14 -0
- package/src/utils/tools-manager.ts +1 -19
- package/src/vibe/runtime.ts +852 -72
- package/src/web/search/index.ts +3 -6
- package/src/web/search/provider.ts +31 -16
- package/src/web/search/providers/xai.ts +7 -1
- package/src/web/search/types.ts +3 -0
- package/dist/types/stt/recorder.d.ts +0 -30
- package/dist/types/stt/transcriber.d.ts +0 -14
- package/dist/types/stt/wav.d.ts +0 -29
- package/dist/types/tts/player.d.ts +0 -32
- package/src/stt/recorder.ts +0 -551
- package/src/stt/transcriber.ts +0 -60
- package/src/stt/wav.ts +0 -173
- package/src/tts/player.ts +0 -137
package/src/advisor/runtime.ts
CHANGED
|
@@ -5,7 +5,12 @@ import * as AIError from "@oh-my-pi/pi-ai/error";
|
|
|
5
5
|
import { type CursorExecResolvedCarrier, kCursorExecResolved } from "@oh-my-pi/pi-ai/utils/block-symbols";
|
|
6
6
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
7
7
|
import { obfuscateToolArguments, type SecretObfuscator } from "../secrets/obfuscator";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
formatExecutionSourcePreview,
|
|
10
|
+
formatSessionHistoryMarkdown,
|
|
11
|
+
formatToolResultErrorPreview,
|
|
12
|
+
PRIMARY_CONTEXT_CUSTOM_TYPES,
|
|
13
|
+
} from "../session/session-history-format";
|
|
9
14
|
|
|
10
15
|
/**
|
|
11
16
|
* Minimal slice of `Agent` the runtime drives — satisfied by pi-agent-core
|
|
@@ -267,6 +272,8 @@ export class AdvisorRuntime {
|
|
|
267
272
|
#seenContext = new Map<string, string>();
|
|
268
273
|
/** Incremented whenever the advisor loses context so queued raw deltas are re-rendered against fresh dedupe state. */
|
|
269
274
|
#renderRevision = 0;
|
|
275
|
+
/** Regex secret values observed in primary deltas and retained until advisor context resets. */
|
|
276
|
+
#advisorRegexSecretValues = new Set<string>();
|
|
270
277
|
#pending: PendingDelta[] = [];
|
|
271
278
|
#busy = false;
|
|
272
279
|
#backlog = 0;
|
|
@@ -428,6 +435,7 @@ export class AdvisorRuntime {
|
|
|
428
435
|
this.#backlog = 0;
|
|
429
436
|
this.#consecutiveFailures = 0;
|
|
430
437
|
this.#failureNotified = false;
|
|
438
|
+
this.#advisorRegexSecretValues.clear();
|
|
431
439
|
this.#wakeAllWaiters();
|
|
432
440
|
try {
|
|
433
441
|
this.agent.abort("advisor disposed");
|
|
@@ -436,6 +444,7 @@ export class AdvisorRuntime {
|
|
|
436
444
|
|
|
437
445
|
#clearSeenContext(): void {
|
|
438
446
|
this.#seenContext.clear();
|
|
447
|
+
this.#advisorRegexSecretValues.clear();
|
|
439
448
|
this.#renderRevision++;
|
|
440
449
|
}
|
|
441
450
|
|
|
@@ -527,9 +536,44 @@ export class AdvisorRuntime {
|
|
|
527
536
|
.map(message => this.#dedupContextMessage(message));
|
|
528
537
|
if (delta.length === 0) return null;
|
|
529
538
|
const obfuscator = this.host.obfuscator;
|
|
530
|
-
|
|
531
|
-
const md = formatSessionHistoryMarkdown(formattedDelta, ADVISOR_RENDER_OPTIONS);
|
|
539
|
+
let md = formatSessionHistoryMarkdown(delta, ADVISOR_RENDER_OPTIONS);
|
|
532
540
|
if (!md.trim()) return null;
|
|
541
|
+
if (obfuscator?.hasSecrets()) {
|
|
542
|
+
let discoveredNewRegexSecretValue = false;
|
|
543
|
+
const addRegexValues = (text: string): void => {
|
|
544
|
+
for (const secretValue of obfuscator.collectRegexSecretValuesForObfuscation(text)) {
|
|
545
|
+
if (this.#advisorRegexSecretValues.has(secretValue)) continue;
|
|
546
|
+
this.#advisorRegexSecretValues.add(secretValue);
|
|
547
|
+
discoveredNewRegexSecretValue = true;
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
for (const message of delta) {
|
|
551
|
+
if (
|
|
552
|
+
message.role === "custom" &&
|
|
553
|
+
PRIMARY_CONTEXT_CUSTOM_TYPES.has(message.customType) &&
|
|
554
|
+
typeof message.content === "string"
|
|
555
|
+
) {
|
|
556
|
+
addRegexValues(message.content);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
addRegexValues(md);
|
|
560
|
+
scrubAdvisorHistory(obfuscator, this.agent.state.messages, this.#advisorRegexSecretValues);
|
|
561
|
+
if (discoveredNewRegexSecretValue) {
|
|
562
|
+
this.#pending = this.#pending.map(delta => ({
|
|
563
|
+
...delta,
|
|
564
|
+
text: obfuscator.stripUnsafeFriendlyPlaceholderPrefixes(delta.text, this.#advisorRegexSecretValues),
|
|
565
|
+
}));
|
|
566
|
+
}
|
|
567
|
+
md = formatSessionHistoryMarkdown(
|
|
568
|
+
delta.map(message =>
|
|
569
|
+
message.role === "custom" && PRIMARY_CONTEXT_CUSTOM_TYPES.has(message.customType)
|
|
570
|
+
? obfuscateAdvisorMessage(obfuscator, message, this.#advisorRegexSecretValues)
|
|
571
|
+
: message,
|
|
572
|
+
),
|
|
573
|
+
ADVISOR_RENDER_OPTIONS,
|
|
574
|
+
);
|
|
575
|
+
md = obfuscator.obfuscate(md, this.#advisorRegexSecretValues);
|
|
576
|
+
}
|
|
533
577
|
const heading = wip ? "### Session update [in progress — more steps follow]" : "### Session update";
|
|
534
578
|
return `${heading}\n\n${md}`;
|
|
535
579
|
}
|
|
@@ -731,6 +775,10 @@ export class AdvisorRuntime {
|
|
|
731
775
|
wip = late.at(-1)!.wip;
|
|
732
776
|
}
|
|
733
777
|
|
|
778
|
+
const batchObfuscator = this.host.obfuscator;
|
|
779
|
+
if (batchObfuscator?.hasSecrets()) {
|
|
780
|
+
batchText = batchObfuscator.stripUnsafeFriendlyPlaceholderPrefixes(batchText, this.#advisorRegexSecretValues);
|
|
781
|
+
}
|
|
734
782
|
return { batch: batchText || null, rawMessages, finalTurns: turns, wip, resetContext: false };
|
|
735
783
|
}
|
|
736
784
|
|
|
@@ -987,12 +1035,16 @@ function getAdvisorTurnError(messages: readonly AgentMessage[]): Error | undefin
|
|
|
987
1035
|
|
|
988
1036
|
type TextualContent = string | readonly (TextContent | ImageContent)[];
|
|
989
1037
|
|
|
990
|
-
function obfuscateTextualContent(
|
|
991
|
-
|
|
1038
|
+
function obfuscateTextualContent(
|
|
1039
|
+
obfuscator: SecretObfuscator,
|
|
1040
|
+
content: TextualContent,
|
|
1041
|
+
sharedRegexSecretValues: ReadonlySet<string>,
|
|
1042
|
+
): TextualContent {
|
|
1043
|
+
if (typeof content === "string") return obfuscator.obfuscate(content, sharedRegexSecretValues);
|
|
992
1044
|
let changed = false;
|
|
993
1045
|
const result = content.map((block): TextContent | ImageContent => {
|
|
994
1046
|
if (block.type !== "text") return block;
|
|
995
|
-
const text = obfuscator.obfuscate(block.text);
|
|
1047
|
+
const text = obfuscator.obfuscate(block.text, sharedRegexSecretValues);
|
|
996
1048
|
if (text === block.text) return block;
|
|
997
1049
|
changed = true;
|
|
998
1050
|
return { ...block, text };
|
|
@@ -1000,17 +1052,50 @@ function obfuscateTextualContent(obfuscator: SecretObfuscator, content: TextualC
|
|
|
1000
1052
|
return changed ? result : content;
|
|
1001
1053
|
}
|
|
1002
1054
|
|
|
1003
|
-
function
|
|
1055
|
+
function firstAdvisorToolResultErrorLine(content: TextualContent): string | undefined {
|
|
1056
|
+
if (typeof content === "string") return content.split("\n", 1)[0];
|
|
1057
|
+
const first = content[0];
|
|
1058
|
+
if (first?.type !== "text") return undefined;
|
|
1059
|
+
return first.text.split("\n", 1)[0];
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
function obfuscateAdvisorToolResultErrorContent(
|
|
1063
|
+
obfuscator: SecretObfuscator,
|
|
1064
|
+
content: TextualContent,
|
|
1065
|
+
sharedRegexSecretValues: ReadonlySet<string>,
|
|
1066
|
+
): TextualContent {
|
|
1067
|
+
const firstLine = firstAdvisorToolResultErrorLine(content);
|
|
1068
|
+
if (firstLine === undefined) return content;
|
|
1069
|
+
const preview = formatToolResultErrorPreview(content);
|
|
1070
|
+
const obfuscatedPreview = obfuscator.obfuscate(preview, sharedRegexSecretValues);
|
|
1071
|
+
if (obfuscatedPreview === firstLine) return content;
|
|
1072
|
+
if (typeof content === "string") return obfuscatedPreview + content.slice(firstLine.length);
|
|
1073
|
+
const first = content[0]!;
|
|
1074
|
+
if (first.type !== "text") return content;
|
|
1075
|
+
return [{ ...first, text: obfuscatedPreview + first.text.slice(firstLine.length) }, ...content.slice(1)];
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
function obfuscateAssistantMessage(
|
|
1079
|
+
obfuscator: SecretObfuscator,
|
|
1080
|
+
message: AssistantMessage,
|
|
1081
|
+
sharedRegexSecretValues: ReadonlySet<string>,
|
|
1082
|
+
): AssistantMessage {
|
|
1004
1083
|
let changed = false;
|
|
1005
1084
|
const content = message.content.map((block): AssistantMessage["content"][number] => {
|
|
1006
1085
|
if (block.type === "text") {
|
|
1007
|
-
const text = obfuscator.obfuscate(block.text);
|
|
1086
|
+
const text = obfuscator.obfuscate(block.text, sharedRegexSecretValues);
|
|
1008
1087
|
if (text === block.text) return block;
|
|
1009
1088
|
changed = true;
|
|
1010
1089
|
return { ...block, text };
|
|
1011
1090
|
}
|
|
1091
|
+
if (block.type === "thinking") {
|
|
1092
|
+
const thinking = obfuscator.obfuscate(block.thinking, sharedRegexSecretValues);
|
|
1093
|
+
if (thinking === block.thinking) return block;
|
|
1094
|
+
changed = true;
|
|
1095
|
+
return { ...block, thinking, thinkingSignature: undefined };
|
|
1096
|
+
}
|
|
1012
1097
|
if (block.type === "toolCall") {
|
|
1013
|
-
const args = obfuscateToolArguments(obfuscator, block.arguments);
|
|
1098
|
+
const args = obfuscateToolArguments(obfuscator, block.arguments, sharedRegexSecretValues);
|
|
1014
1099
|
if (args === block.arguments) return block;
|
|
1015
1100
|
changed = true;
|
|
1016
1101
|
return { ...block, arguments: args };
|
|
@@ -1023,68 +1108,83 @@ function obfuscateAssistantMessage(obfuscator: SecretObfuscator, message: Assist
|
|
|
1023
1108
|
function obfuscateDetails(
|
|
1024
1109
|
obfuscator: SecretObfuscator,
|
|
1025
1110
|
details: Record<string, unknown> | undefined,
|
|
1111
|
+
sharedRegexSecretValues: ReadonlySet<string>,
|
|
1026
1112
|
): Record<string, unknown> | undefined {
|
|
1027
1113
|
if (!details) return details;
|
|
1028
1114
|
// Walk strings at every depth: `customOneLiner` renders nested fields
|
|
1029
1115
|
// (e.g. `async-result` reads `details.jobs[].label`/`jobId`), so a shallow
|
|
1030
1116
|
// pass leaks any secret a background job's label happens to contain.
|
|
1031
|
-
return obfuscateToolArguments(obfuscator, details);
|
|
1117
|
+
return obfuscateToolArguments(obfuscator, details, sharedRegexSecretValues);
|
|
1032
1118
|
}
|
|
1033
1119
|
|
|
1034
|
-
function obfuscateAdvisorMessage(
|
|
1120
|
+
function obfuscateAdvisorMessage(
|
|
1121
|
+
obfuscator: SecretObfuscator,
|
|
1122
|
+
message: AgentMessage,
|
|
1123
|
+
sharedRegexSecretValues: ReadonlySet<string>,
|
|
1124
|
+
): AgentMessage {
|
|
1035
1125
|
switch (message.role) {
|
|
1036
1126
|
case "user":
|
|
1037
1127
|
case "developer": {
|
|
1038
|
-
const content = obfuscateTextualContent(
|
|
1128
|
+
const content = obfuscateTextualContent(
|
|
1129
|
+
obfuscator,
|
|
1130
|
+
message.content as TextualContent,
|
|
1131
|
+
sharedRegexSecretValues,
|
|
1132
|
+
);
|
|
1039
1133
|
return content === message.content ? message : ({ ...(message as object), content } as AgentMessage);
|
|
1040
1134
|
}
|
|
1041
1135
|
case "toolResult": {
|
|
1042
1136
|
const msg = message as AgentMessage & {
|
|
1043
1137
|
content: TextualContent;
|
|
1044
1138
|
details?: Record<string, unknown>;
|
|
1139
|
+
isError?: boolean;
|
|
1045
1140
|
};
|
|
1046
|
-
const content =
|
|
1047
|
-
|
|
1141
|
+
const content = msg.isError
|
|
1142
|
+
? obfuscateAdvisorToolResultErrorContent(obfuscator, msg.content, sharedRegexSecretValues)
|
|
1143
|
+
: msg.content;
|
|
1144
|
+
let details = msg.details;
|
|
1145
|
+
if (typeof details?.diff === "string") {
|
|
1146
|
+
const diff = obfuscator.obfuscate(details.diff, sharedRegexSecretValues);
|
|
1147
|
+
if (diff !== details.diff) details = { ...details, diff };
|
|
1148
|
+
}
|
|
1048
1149
|
if (content === msg.content && details === msg.details) return message;
|
|
1049
1150
|
return { ...(message as object), content, details } as AgentMessage;
|
|
1050
1151
|
}
|
|
1051
1152
|
case "assistant":
|
|
1052
|
-
return obfuscateAssistantMessage(
|
|
1153
|
+
return obfuscateAssistantMessage(
|
|
1154
|
+
obfuscator,
|
|
1155
|
+
message as AssistantMessage,
|
|
1156
|
+
sharedRegexSecretValues,
|
|
1157
|
+
) as AgentMessage;
|
|
1053
1158
|
case "custom":
|
|
1054
1159
|
case "hookMessage": {
|
|
1160
|
+
if (!formatSessionHistoryMarkdown([message], { expandPrimaryContext: true }).trim()) return message;
|
|
1055
1161
|
const msg = message as AgentMessage & {
|
|
1056
1162
|
content: TextualContent;
|
|
1057
1163
|
details?: Record<string, unknown>;
|
|
1058
1164
|
};
|
|
1059
|
-
const content = obfuscateTextualContent(obfuscator, msg.content);
|
|
1060
|
-
const details = obfuscateDetails(obfuscator, msg.details);
|
|
1165
|
+
const content = obfuscateTextualContent(obfuscator, msg.content, sharedRegexSecretValues);
|
|
1166
|
+
const details = obfuscateDetails(obfuscator, msg.details, sharedRegexSecretValues);
|
|
1061
1167
|
if (content === msg.content && details === msg.details) return message;
|
|
1062
1168
|
return { ...(message as object), content, details } as AgentMessage;
|
|
1063
1169
|
}
|
|
1064
1170
|
case "bashExecution": {
|
|
1065
|
-
const msg = message as AgentMessage & { command: string
|
|
1066
|
-
const command = obfuscator.obfuscate(msg.command);
|
|
1067
|
-
|
|
1068
|
-
return command === msg.command && output === msg.output
|
|
1069
|
-
? message
|
|
1070
|
-
: ({ ...(message as object), command, output } as AgentMessage);
|
|
1171
|
+
const msg = message as AgentMessage & { command: string };
|
|
1172
|
+
const command = obfuscator.obfuscate(formatExecutionSourcePreview(msg.command), sharedRegexSecretValues);
|
|
1173
|
+
return command === msg.command ? message : ({ ...(message as object), command } as AgentMessage);
|
|
1071
1174
|
}
|
|
1072
1175
|
case "pythonExecution": {
|
|
1073
|
-
const msg = message as AgentMessage & { code: string
|
|
1074
|
-
const code = obfuscator.obfuscate(msg.code);
|
|
1075
|
-
|
|
1076
|
-
return code === msg.code && output === msg.output
|
|
1077
|
-
? message
|
|
1078
|
-
: ({ ...(message as object), code, output } as AgentMessage);
|
|
1176
|
+
const msg = message as AgentMessage & { code: string };
|
|
1177
|
+
const code = obfuscator.obfuscate(formatExecutionSourcePreview(msg.code), sharedRegexSecretValues);
|
|
1178
|
+
return code === msg.code ? message : ({ ...(message as object), code } as AgentMessage);
|
|
1079
1179
|
}
|
|
1080
1180
|
case "branchSummary": {
|
|
1081
1181
|
const msg = message as AgentMessage & { summary: string };
|
|
1082
|
-
const summary = obfuscator.obfuscate(msg.summary);
|
|
1182
|
+
const summary = obfuscator.obfuscate(msg.summary, sharedRegexSecretValues);
|
|
1083
1183
|
return summary === msg.summary ? message : ({ ...(message as object), summary } as AgentMessage);
|
|
1084
1184
|
}
|
|
1085
1185
|
case "compactionSummary": {
|
|
1086
1186
|
const msg = message as AgentMessage & { summary: string };
|
|
1087
|
-
const summary = obfuscator.obfuscate(msg.summary);
|
|
1187
|
+
const summary = obfuscator.obfuscate(msg.summary, sharedRegexSecretValues);
|
|
1088
1188
|
return summary === msg.summary ? message : ({ ...(message as object), summary } as AgentMessage);
|
|
1089
1189
|
}
|
|
1090
1190
|
case "fileMention": {
|
|
@@ -1093,11 +1193,10 @@ function obfuscateAdvisorMessage(obfuscator: SecretObfuscator, message: AgentMes
|
|
|
1093
1193
|
};
|
|
1094
1194
|
let changed = false;
|
|
1095
1195
|
const files = msg.files.map(file => {
|
|
1096
|
-
const path = obfuscator.obfuscate(file.path);
|
|
1097
|
-
|
|
1098
|
-
if (path === file.path && content === file.content) return file;
|
|
1196
|
+
const path = obfuscator.obfuscate(file.path, sharedRegexSecretValues);
|
|
1197
|
+
if (path === file.path) return file;
|
|
1099
1198
|
changed = true;
|
|
1100
|
-
return { ...file, path
|
|
1199
|
+
return { ...file, path };
|
|
1101
1200
|
});
|
|
1102
1201
|
return changed ? ({ ...(message as object), files } as AgentMessage) : message;
|
|
1103
1202
|
}
|
|
@@ -1106,12 +1205,14 @@ function obfuscateAdvisorMessage(obfuscator: SecretObfuscator, message: AgentMes
|
|
|
1106
1205
|
}
|
|
1107
1206
|
}
|
|
1108
1207
|
|
|
1109
|
-
function
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1208
|
+
function scrubAdvisorHistory(
|
|
1209
|
+
obfuscator: SecretObfuscator,
|
|
1210
|
+
messages: AgentMessage[],
|
|
1211
|
+
sharedRegexSecretValues: ReadonlySet<string>,
|
|
1212
|
+
): void {
|
|
1213
|
+
for (let index = 0; index < messages.length; index++) {
|
|
1214
|
+
const message = messages[index]!;
|
|
1215
|
+
const next = obfuscateAdvisorMessage(obfuscator, message, sharedRegexSecretValues);
|
|
1216
|
+
if (next !== message) messages[index] = next;
|
|
1217
|
+
}
|
|
1117
1218
|
}
|
package/src/async/job-manager.ts
CHANGED
|
@@ -60,8 +60,19 @@ export interface AsyncJob {
|
|
|
60
60
|
queued?: boolean;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/** Delivery callback for a settled job's result text. */
|
|
64
|
+
export type AsyncJobDeliverySink = (jobId: string, text: string, job?: AsyncJob) => void | Promise<void>;
|
|
65
|
+
|
|
63
66
|
export interface AsyncJobManagerOptions {
|
|
64
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Delivery sink for UNOWNED completions (jobs registered without an
|
|
69
|
+
* `ownerId`). Owned deliveries route exclusively through
|
|
70
|
+
* {@link AsyncJobManager.registerDeliverySink}; when the owner has no live
|
|
71
|
+
* sink they are dead-lettered (dropped with a warning; the job row keeps
|
|
72
|
+
* the result text until retention eviction) — never routed here, which
|
|
73
|
+
* would leak one agent's result into another session.
|
|
74
|
+
*/
|
|
75
|
+
onJobComplete?: AsyncJobDeliverySink;
|
|
65
76
|
maxRunningJobs?: number;
|
|
66
77
|
retentionMs?: number;
|
|
67
78
|
}
|
|
@@ -128,6 +139,7 @@ export class AsyncJobManager {
|
|
|
128
139
|
readonly #watchedJobs = new Set<string>();
|
|
129
140
|
readonly #evictionTimers = new Map<string, NodeJS.Timeout>();
|
|
130
141
|
readonly #pollEscalation = new Map<string | undefined, PollEscalationState>();
|
|
142
|
+
readonly #deliverySinks = new Map<string, AsyncJobDeliverySink>();
|
|
131
143
|
readonly #onJobComplete: AsyncJobManagerOptions["onJobComplete"];
|
|
132
144
|
readonly #maxRunningJobs: number;
|
|
133
145
|
readonly #retentionMs: number;
|
|
@@ -409,6 +421,55 @@ export class AsyncJobManager {
|
|
|
409
421
|
await Promise.all(Array.from(this.#jobs.values()).map(job => job.promise));
|
|
410
422
|
}
|
|
411
423
|
|
|
424
|
+
/**
|
|
425
|
+
* Route completions for jobs owned by `ownerId` to `sink`. Sessions register
|
|
426
|
+
* their own sink at construction and unregister on dispose. Owned deliveries
|
|
427
|
+
* with no live sink are dead-lettered — `onJobComplete` serves only unowned
|
|
428
|
+
* deliveries.
|
|
429
|
+
*
|
|
430
|
+
* Last registration wins for an owner id; the returned unregister clears the
|
|
431
|
+
* mapping only while it still points at `sink`, so a revived session's fresh
|
|
432
|
+
* registration survives its parked predecessor's late cleanup.
|
|
433
|
+
*/
|
|
434
|
+
registerDeliverySink(ownerId: string, sink: AsyncJobDeliverySink): () => void {
|
|
435
|
+
this.#deliverySinks.set(ownerId, sink);
|
|
436
|
+
return () => {
|
|
437
|
+
if (this.#deliverySinks.get(ownerId) === sink) this.#deliverySinks.delete(ownerId);
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Wait until every job owned by `ownerId` has settled — its run promise
|
|
443
|
+
* resolved, which for cancelled jobs means the underlying process actually
|
|
444
|
+
* exited. Jobs registered while waiting (e.g. by a follow-up turn) are
|
|
445
|
+
* awaited too. Returns false when `timeoutMs` elapses first.
|
|
446
|
+
*
|
|
447
|
+
* `excludeSuppressed` skips jobs whose delivery is suppressed (acknowledged
|
|
448
|
+
* or `hub`-watched): those can never re-wake a run, so quiescence barriers
|
|
449
|
+
* pass it to share one contract with the pending-async-wake predicate.
|
|
450
|
+
* Teardown reaps omit it — worktree safety concerns every owner process.
|
|
451
|
+
*/
|
|
452
|
+
async waitForOwnerJobs(
|
|
453
|
+
ownerId: string,
|
|
454
|
+
options?: { timeoutMs?: number; excludeSuppressed?: boolean },
|
|
455
|
+
): Promise<boolean> {
|
|
456
|
+
const deadline =
|
|
457
|
+
options?.timeoutMs === undefined ? Number.POSITIVE_INFINITY : Date.now() + Math.max(0, options.timeoutMs);
|
|
458
|
+
const awaited = new Set<string>();
|
|
459
|
+
for (;;) {
|
|
460
|
+
const pending = this.#filterJobs(this.#jobs.values(), { ownerId }).filter(
|
|
461
|
+
job => !awaited.has(job.id) && (options?.excludeSuppressed !== true || !this.isDeliverySuppressed(job.id)),
|
|
462
|
+
);
|
|
463
|
+
if (pending.length === 0) return true;
|
|
464
|
+
for (const job of pending) awaited.add(job.id);
|
|
465
|
+
const settled = await this.#waitForDeliveryPromise(
|
|
466
|
+
Promise.all(pending.map(job => job.promise)).then(() => {}),
|
|
467
|
+
deadline,
|
|
468
|
+
);
|
|
469
|
+
if (!settled) return false;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
412
473
|
async #waitForAllUntil(deadline: number): Promise<boolean> {
|
|
413
474
|
const promises = Array.from(this.#jobs.values()).map(job => job.promise);
|
|
414
475
|
if (promises.length === 0) return true;
|
|
@@ -489,6 +550,7 @@ export class AsyncJobManager {
|
|
|
489
550
|
this.#suppressedDeliveries.clear();
|
|
490
551
|
this.#watchedJobs.clear();
|
|
491
552
|
this.#pollEscalation.clear();
|
|
553
|
+
this.#deliverySinks.clear();
|
|
492
554
|
return jobsSettled && drained;
|
|
493
555
|
}
|
|
494
556
|
|
|
@@ -655,11 +717,37 @@ export class AsyncJobManager {
|
|
|
655
717
|
}
|
|
656
718
|
}
|
|
657
719
|
|
|
720
|
+
/**
|
|
721
|
+
* Resolve the sink for one delivery attempt: owned deliveries route ONLY to
|
|
722
|
+
* their owner's registered sink (a missing sink dead-letters — never the
|
|
723
|
+
* default, which would misroute a dead owner's result into another
|
|
724
|
+
* session); unowned deliveries use the constructor default. Resolved per
|
|
725
|
+
* attempt so a sink registered between retries (e.g. a revived session)
|
|
726
|
+
* picks up the retry.
|
|
727
|
+
*/
|
|
728
|
+
#resolveDeliverySink(ownerId: string | undefined): AsyncJobDeliverySink | undefined {
|
|
729
|
+
if (ownerId !== undefined) return this.#deliverySinks.get(ownerId);
|
|
730
|
+
return this.#onJobComplete;
|
|
731
|
+
}
|
|
732
|
+
|
|
658
733
|
#deliverDelivery(delivery: AsyncJobDelivery): Promise<void> {
|
|
734
|
+
const sink = this.#resolveDeliverySink(delivery.ownerId);
|
|
735
|
+
if (!sink) {
|
|
736
|
+
// Dead-letter: owned delivery with no live sink (session disposed or
|
|
737
|
+
// parked), or unowned delivery with no default sink. Drop it — the
|
|
738
|
+
// job row keeps its result/error text until retention eviction, so
|
|
739
|
+
// the outcome stays inspectable via job queries and agent:// reads.
|
|
740
|
+
logger.warn("Async job delivery dead-lettered: no delivery sink", {
|
|
741
|
+
jobId: delivery.jobId,
|
|
742
|
+
ownerId: delivery.ownerId,
|
|
743
|
+
});
|
|
744
|
+
delivery.promise = Promise.resolve();
|
|
745
|
+
return delivery.promise;
|
|
746
|
+
}
|
|
659
747
|
const promise = (async () => {
|
|
660
748
|
this.#inFlightDeliveries.push(delivery);
|
|
661
749
|
try {
|
|
662
|
-
await
|
|
750
|
+
await sink(delivery.jobId, delivery.text, this.#jobs.get(delivery.jobId));
|
|
663
751
|
} catch (error) {
|
|
664
752
|
delivery.attempt += 1;
|
|
665
753
|
delivery.lastError = error instanceof Error ? error.message : String(error);
|
package/src/cli/args.ts
CHANGED
|
@@ -19,6 +19,8 @@ export type Mode = "text" | "json" | "rpc" | "acp" | "rpc-ui";
|
|
|
19
19
|
|
|
20
20
|
export interface Args {
|
|
21
21
|
cwd?: string;
|
|
22
|
+
/** Workspace directories beyond cwd for this session (repeatable `--add-dir`). */
|
|
23
|
+
addDir?: string[];
|
|
22
24
|
profile?: string;
|
|
23
25
|
alias?: string;
|
|
24
26
|
allowHome?: boolean;
|
|
@@ -394,6 +396,7 @@ ${chalk.bold("Available Tools (default-enabled unless noted):")}
|
|
|
394
396
|
notebook - Edit Jupyter notebooks
|
|
395
397
|
inspect_image - Analyze images with a vision model
|
|
396
398
|
browser - Browser automation (Puppeteer)
|
|
399
|
+
computer - Native host desktop capture and input (disabled by default)
|
|
397
400
|
task - Launch sub-agents for parallel tasks
|
|
398
401
|
todo - Manage todo/task lists
|
|
399
402
|
web_search - Search the web
|
|
@@ -24,7 +24,12 @@ import {
|
|
|
24
24
|
completeSimple,
|
|
25
25
|
type Model,
|
|
26
26
|
} from "@oh-my-pi/pi-ai";
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
AuthBrokerClient,
|
|
29
|
+
loadAuthBrokerAccountPool,
|
|
30
|
+
RemoteAuthCredentialStore,
|
|
31
|
+
type SnapshotResponse,
|
|
32
|
+
} from "@oh-my-pi/pi-ai/auth-broker";
|
|
28
33
|
import { DEFAULT_AUTH_GATEWAY_BIND, startAuthGateway } from "@oh-my-pi/pi-ai/auth-gateway";
|
|
29
34
|
import { type GeneratedProvider, getBundledModels, getBundledProviders } from "@oh-my-pi/pi-catalog/models";
|
|
30
35
|
import { getConfigRootDir, isEnoent, VERSION } from "@oh-my-pi/pi-utils";
|
|
@@ -147,9 +152,14 @@ async function runServe(flags: AuthGatewayCommandArgs["flags"]): Promise<void> {
|
|
|
147
152
|
|
|
148
153
|
// Build a broker-backed AuthStorage — same pattern as discoverAuthStorage()
|
|
149
154
|
// in sdk.ts. The gateway never touches local SQLite.
|
|
155
|
+
const accountPool = await loadAuthBrokerAccountPool();
|
|
150
156
|
const client = createBrokerClient(brokerConfig);
|
|
151
157
|
const initialSnapshot = await fetchBrokerSnapshot(client);
|
|
152
|
-
const store = new RemoteAuthCredentialStore({
|
|
158
|
+
const store = new RemoteAuthCredentialStore({
|
|
159
|
+
client,
|
|
160
|
+
initialSnapshot,
|
|
161
|
+
accountPool,
|
|
162
|
+
});
|
|
153
163
|
// Refresh + usage both flow through the store's broker hooks automatically —
|
|
154
164
|
// `RemoteAuthCredentialStore.refreshOAuthCredential` and `.fetchUsageReports`.
|
|
155
165
|
// AuthStorage discovers them when no explicit option overrides them, so the
|
|
@@ -538,9 +548,14 @@ async function runCheck(flags: AuthGatewayCommandArgs["flags"]): Promise<void> {
|
|
|
538
548
|
);
|
|
539
549
|
}
|
|
540
550
|
|
|
551
|
+
const accountPool = await loadAuthBrokerAccountPool();
|
|
541
552
|
const client = createBrokerClient(brokerConfig);
|
|
542
553
|
const initialSnapshot = await fetchBrokerSnapshot(client);
|
|
543
|
-
const store = new RemoteAuthCredentialStore({
|
|
554
|
+
const store = new RemoteAuthCredentialStore({
|
|
555
|
+
client,
|
|
556
|
+
initialSnapshot,
|
|
557
|
+
accountPool,
|
|
558
|
+
});
|
|
544
559
|
const storage = new AuthStorage(store, { sourceLabel: `broker ${brokerConfig.url}` });
|
|
545
560
|
try {
|
|
546
561
|
await storage.reload();
|