@oh-my-pi/pi-coding-agent 17.2.10 → 17.2.12
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 +53 -0
- package/dist/{CHANGELOG-rhwzpexa.md → CHANGELOG-k9ghy5sn.md} +53 -0
- package/dist/cli.js +10775 -10762
- package/dist/types/advisor/runtime.d.ts +1 -1
- package/dist/types/capability/mcp.d.ts +11 -0
- package/dist/types/capability/skill.d.ts +6 -0
- package/dist/types/cli/command-help.d.ts +3 -0
- package/dist/types/commands/share.d.ts +25 -0
- package/dist/types/commit/agentic/index.d.ts +3 -1
- package/dist/types/commit/execute.d.ts +32 -0
- package/dist/types/commit/index.d.ts +2 -1
- package/dist/types/commit/pipeline.d.ts +7 -1
- package/dist/types/config/custom-models.d.ts +31 -0
- package/dist/types/config/model-config-values.d.ts +19 -0
- package/dist/types/config/model-patch.d.ts +93 -0
- package/dist/types/config/model-provider-discovery.d.ts +51 -0
- package/dist/types/config/model-registry.d.ts +9 -52
- package/dist/types/config/settings-schema.d.ts +1 -34
- package/dist/types/config/settings.d.ts +5 -3
- package/dist/types/debug/raw-sse-buffer.d.ts +9 -0
- package/dist/types/discovery/agent-plugin-format.d.ts +136 -0
- package/dist/types/discovery/agent-plugins.d.ts +1 -0
- package/dist/types/discovery/contained-path.d.ts +33 -0
- package/dist/types/discovery/index.d.ts +1 -0
- package/dist/types/eval/executor-base.d.ts +8 -2
- package/dist/types/eval/kernel-session-registry.d.ts +60 -0
- package/dist/types/export/share.d.ts +1 -1
- package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
- package/dist/types/extensibility/extensions/loader.d.ts +7 -0
- package/dist/types/extensibility/extensions/types.d.ts +11 -0
- package/dist/types/extensibility/shared-events.d.ts +3 -2
- package/dist/types/extensibility/skills.d.ts +5 -0
- package/dist/types/lsp/diagnostics.d.ts +96 -0
- package/dist/types/lsp/index.d.ts +7 -128
- package/dist/types/lsp/servers.d.ts +72 -0
- package/dist/types/lsp/tool.d.ts +42 -0
- package/dist/types/lsp/workspace-diagnostics.d.ts +12 -0
- package/dist/types/lsp/writethrough.d.ts +33 -0
- package/dist/types/mcp/transports/header-policy.d.ts +46 -0
- package/dist/types/mcp/types.d.ts +15 -0
- package/dist/types/modes/components/agent-hub-projection.d.ts +2 -7
- package/dist/types/modes/components/agent-hub-renderer.d.ts +0 -7
- package/dist/types/modes/components/agent-hub.d.ts +2 -0
- package/dist/types/modes/components/agent-transcript-viewer.d.ts +2 -0
- package/dist/types/modes/components/chat-transcript-builder.d.ts +2 -0
- package/dist/types/modes/components/custom-editor.d.ts +1 -2
- package/dist/types/modes/components/status-line/types.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +2 -0
- package/dist/types/modes/theme/color.d.ts +19 -0
- package/dist/types/modes/theme/loader.d.ts +19 -0
- package/dist/types/modes/theme/schema.d.ts +175 -0
- package/dist/types/modes/theme/symbols.d.ts +28 -0
- package/dist/types/modes/theme/theme-class.d.ts +244 -0
- package/dist/types/modes/theme/theme.d.ts +9 -280
- package/dist/types/modes/theme/tui-adapters.d.ts +13 -0
- package/dist/types/modes/utils/transcript-render-helpers.d.ts +3 -2
- package/dist/types/registry/agent-registry.d.ts +1 -3
- package/dist/types/secrets/index.d.ts +26 -2
- package/dist/types/secrets/message-transform.d.ts +40 -0
- package/dist/types/secrets/obfuscator.d.ts +0 -108
- package/dist/types/secrets/placeholder-scan.d.ts +95 -0
- package/dist/types/secrets/placeholder.d.ts +94 -0
- package/dist/types/secrets/replacement.d.ts +82 -0
- package/dist/types/session/agent-session-events.d.ts +2 -2
- package/dist/types/session/agent-session-types.d.ts +6 -0
- package/dist/types/session/agent-session.d.ts +2 -2
- package/dist/types/session/messages.d.ts +1 -0
- package/dist/types/session/prewalk.d.ts +3 -1
- package/dist/types/session/session-handoff.d.ts +3 -3
- package/dist/types/session/session-manager.d.ts +32 -0
- package/dist/types/session/session-provider-boundary.d.ts +1 -1
- package/dist/types/session/session-tools.d.ts +8 -0
- package/dist/types/session/turn-recovery.d.ts +9 -4
- package/dist/types/slash-commands/builtin-collaboration.d.ts +2 -0
- package/dist/types/slash-commands/builtin-completions.d.ts +36 -0
- package/dist/types/slash-commands/builtin-control.d.ts +2 -0
- package/dist/types/slash-commands/builtin-lifecycle.d.ts +3 -0
- package/dist/types/slash-commands/builtin-marketplace.d.ts +11 -0
- package/dist/types/slash-commands/builtin-modes.d.ts +5 -0
- package/dist/types/slash-commands/builtin-registry.d.ts +1 -1
- package/dist/types/slash-commands/builtin-session.d.ts +2 -0
- package/dist/types/task/index.d.ts +2 -0
- package/dist/types/tools/gh-common.d.ts +69 -0
- package/dist/types/tools/gh-pr-checkout.d.ts +84 -0
- package/dist/types/tools/gh-pr-diff.d.ts +102 -0
- package/dist/types/tools/gh-run-watch.d.ts +78 -0
- package/dist/types/tools/gh-search.d.ts +61 -0
- package/dist/types/tools/gh-types.d.ts +340 -0
- package/dist/types/tools/gh-view.d.ts +88 -0
- package/dist/types/tools/gh.d.ts +4 -201
- package/dist/types/tools/read-archive.d.ts +16 -0
- package/dist/types/tools/read-format.d.ts +104 -0
- package/dist/types/tools/read-path-resolution.d.ts +19 -0
- package/dist/types/tools/read-pdf-images.d.ts +12 -0
- package/dist/types/tools/read-renderer.d.ts +24 -0
- package/dist/types/tools/read-selector.d.ts +27 -0
- package/dist/types/tools/read-sqlite.d.ts +16 -0
- package/dist/types/tools/read-summary.d.ts +19 -0
- package/dist/types/tools/read.d.ts +1 -23
- package/dist/types/tools/shell-tokenize.d.ts +18 -1
- package/dist/types/utils/changelog.d.ts +0 -5
- package/package.json +13 -13
- package/scripts/legacy-pi-virtual-module.ts +4 -1
- package/src/advisor/runtime.ts +12 -7
- package/src/capability/mcp.ts +11 -0
- package/src/capability/skill.ts +6 -0
- package/src/cli/command-help.ts +4 -0
- package/src/cli/gallery-cli.ts +1 -1
- package/src/cli-commands.ts +5 -0
- package/src/commands/commit.ts +16 -3
- package/src/commands/share.ts +71 -0
- package/src/commit/agentic/index.ts +39 -21
- package/src/commit/execute.ts +56 -0
- package/src/commit/index.ts +2 -1
- package/src/commit/pipeline.ts +20 -7
- package/src/config/custom-models.ts +188 -0
- package/src/config/model-config-values.ts +128 -0
- package/src/config/model-discovery.ts +1 -1
- package/src/config/model-patch.ts +252 -0
- package/src/config/model-provider-discovery.ts +132 -0
- package/src/config/model-registry.ts +84 -704
- package/src/config/settings-schema.ts +2 -33
- package/src/config/settings.ts +53 -3
- package/src/debug/raw-sse-buffer.ts +20 -0
- package/src/discovery/agent-plugin-format.ts +551 -0
- package/src/discovery/agent-plugins.ts +341 -0
- package/src/discovery/claude-plugins.ts +21 -5
- package/src/discovery/contained-path.ts +75 -0
- package/src/discovery/helpers.ts +23 -9
- package/src/discovery/index.ts +1 -0
- package/src/discovery/omp-plugins.ts +20 -7
- package/src/edit/hashline/diff.ts +5 -1
- package/src/eval/executor-base.ts +39 -6
- package/src/eval/jl/executor.ts +82 -371
- package/src/eval/kernel-session-registry.ts +398 -0
- package/src/eval/py/executor.ts +53 -261
- package/src/eval/rb/executor.ts +36 -279
- package/src/exec/non-interactive-env.ts +1 -0
- package/src/export/share.ts +2 -1
- package/src/extensibility/custom-tools/types.ts +2 -2
- package/src/extensibility/extensions/loader.ts +78 -14
- package/src/extensibility/extensions/runner.ts +6 -0
- package/src/extensibility/extensions/types.ts +12 -0
- package/src/extensibility/plugins/marketplace/manager.ts +2 -1
- package/src/extensibility/shared-events.ts +3 -2
- package/src/extensibility/skills.ts +9 -0
- package/src/internal-urls/skill-protocol.ts +14 -0
- package/src/internal-urls/vault-protocol.ts +2 -2
- package/src/launch/client.ts +11 -1
- package/src/launch/protocol.ts +7 -2
- package/src/lsp/diagnostics.ts +516 -0
- package/src/lsp/index.ts +20 -2819
- package/src/lsp/servers.ts +296 -0
- package/src/lsp/tool.ts +1352 -0
- package/src/lsp/workspace-diagnostics.ts +170 -0
- package/src/lsp/writethrough.ts +561 -0
- package/src/main.ts +3 -2
- package/src/mcp/config.ts +3 -0
- package/src/mcp/manager.ts +12 -9
- package/src/mcp/transports/header-policy.ts +95 -0
- package/src/mcp/transports/http.ts +35 -52
- package/src/mcp/transports/sse.ts +20 -27
- package/src/mcp/types.ts +15 -0
- package/src/modes/acp/acp-agent.ts +15 -4
- package/src/modes/components/agent-dashboard.ts +2 -0
- package/src/modes/components/agent-hub-projection.ts +2 -2
- package/src/modes/components/agent-hub-renderer.ts +3 -7
- package/src/modes/components/agent-hub.ts +5 -0
- package/src/modes/components/agent-transcript-viewer.ts +3 -0
- package/src/modes/components/chat-transcript-builder.ts +3 -0
- package/src/modes/components/custom-editor.ts +0 -9
- package/src/modes/components/status-line/component.ts +1 -0
- package/src/modes/components/status-line/segments.ts +6 -4
- package/src/modes/components/status-line/types.ts +2 -0
- package/src/modes/components/tool-execution.ts +13 -16
- package/src/modes/components/tree-selector.ts +62 -3
- package/src/modes/controllers/command-controller.ts +8 -2
- package/src/modes/controllers/event-controller.ts +15 -15
- package/src/modes/controllers/input-controller.ts +20 -2
- package/src/modes/controllers/selector-controller.ts +1 -0
- package/src/modes/theme/color.ts +133 -0
- package/src/modes/theme/loader.ts +178 -0
- package/src/modes/theme/schema.ts +263 -0
- package/src/modes/theme/symbols.ts +1000 -0
- package/src/modes/theme/theme-class.ts +611 -0
- package/src/modes/theme/theme.ts +27 -2453
- package/src/modes/theme/tui-adapters.ts +279 -0
- package/src/modes/utils/transcript-render-helpers.ts +4 -2
- package/src/modes/utils/ui-helpers.ts +1 -0
- package/src/registry/agent-registry.ts +2 -2
- package/src/sdk.ts +6 -49
- package/src/secrets/index.ts +51 -6
- package/src/secrets/message-transform.ts +287 -0
- package/src/secrets/obfuscator.ts +39 -1303
- package/src/secrets/placeholder-scan.ts +506 -0
- package/src/secrets/placeholder.ts +309 -0
- package/src/secrets/replacement.ts +216 -0
- package/src/session/agent-session-events.ts +2 -2
- package/src/session/agent-session-types.ts +6 -0
- package/src/session/agent-session.ts +146 -21
- package/src/session/indexed-session-storage.ts +7 -2
- package/src/session/messages.ts +1 -0
- package/src/session/prewalk.ts +57 -17
- package/src/session/session-advisors.ts +32 -34
- package/src/session/session-context.ts +3 -5
- package/src/session/session-handoff.ts +39 -16
- package/src/session/session-manager.ts +67 -3
- package/src/session/session-provider-boundary.ts +3 -6
- package/src/session/session-tools.ts +37 -3
- package/src/session/todo-tracker.ts +11 -1
- package/src/session/turn-recovery.ts +115 -84
- package/src/slash-commands/builtin-collaboration.ts +504 -0
- package/src/slash-commands/builtin-completions.ts +291 -0
- package/src/slash-commands/builtin-control.ts +78 -0
- package/src/slash-commands/builtin-lifecycle.ts +506 -0
- package/src/slash-commands/builtin-marketplace.ts +567 -0
- package/src/slash-commands/builtin-modes.ts +518 -0
- package/src/slash-commands/builtin-registry.ts +21 -2996
- package/src/slash-commands/builtin-session.ts +592 -0
- package/src/task/executor.ts +17 -14
- package/src/task/index.ts +21 -6
- package/src/tools/bash-skill-urls.ts +15 -0
- package/src/tools/bash.ts +10 -11
- package/src/tools/debug.ts +1 -1
- package/src/tools/gh-common.ts +288 -0
- package/src/tools/gh-pr-checkout.ts +679 -0
- package/src/tools/gh-pr-diff.ts +473 -0
- package/src/tools/gh-run-watch.ts +1015 -0
- package/src/tools/gh-search.ts +500 -0
- package/src/tools/gh-types.ts +379 -0
- package/src/tools/gh-view.ts +612 -0
- package/src/tools/gh.ts +109 -3821
- package/src/tools/jtd-to-json-schema.ts +123 -21
- package/src/tools/read-archive.ts +209 -0
- package/src/tools/read-format.ts +593 -0
- package/src/tools/read-path-resolution.ts +36 -0
- package/src/tools/read-pdf-images.ts +250 -0
- package/src/tools/read-renderer.ts +289 -0
- package/src/tools/read-selector.ts +84 -0
- package/src/tools/read-sqlite.ts +215 -0
- package/src/tools/read-summary.ts +199 -0
- package/src/tools/read.ts +82 -1824
- package/src/tools/shell-tokenize.ts +99 -1
- package/src/utils/changelog.ts +1 -1
- package/src/utils/title-generator.ts +3 -1
- package/src/web/search/providers/exa.ts +1 -1
- package/src/web/search/providers/zai.ts +12 -3
|
@@ -468,6 +468,8 @@ export class SessionManager {
|
|
|
468
468
|
|
|
469
469
|
/** The single open append writer; the manager only ever writes one file at a time. */
|
|
470
470
|
#writer: SessionStorageWriter | undefined;
|
|
471
|
+
/** Sealed by {@link releaseRetainedEntries}: every later append/title/rewrite is a dropped no-op. */
|
|
472
|
+
#released = false;
|
|
471
473
|
/** Serializes async disk work (flush/close/atomic rewrite). Appends are synchronous and bypass it. */
|
|
472
474
|
#diskTail: Promise<void> = Promise.resolve();
|
|
473
475
|
#diskFailure: Error | undefined;
|
|
@@ -641,6 +643,16 @@ export class SessionManager {
|
|
|
641
643
|
}
|
|
642
644
|
|
|
643
645
|
async #authoritativelyRewriteCurrentStateLocked(operationError: Error): Promise<void> {
|
|
646
|
+
if (this.#released) {
|
|
647
|
+
// Terminal seal: repair would reset the disk tail (escaping the
|
|
648
|
+
// close() serialization) and atomically publish #fileBody() — after
|
|
649
|
+
// release that truncates, and a revival may already own the file.
|
|
650
|
+
// The original operation error still propagates to the caller.
|
|
651
|
+
logger.warn("Skipped authoritative session repair after terminal release", {
|
|
652
|
+
error: String(operationError),
|
|
653
|
+
});
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
644
656
|
if (!this.#persist || !this.#sessionFile) return;
|
|
645
657
|
const previousDiskTail = this.#diskTail;
|
|
646
658
|
const writer = this.#writer;
|
|
@@ -687,7 +699,7 @@ export class SessionManager {
|
|
|
687
699
|
const body = this.#fileBody();
|
|
688
700
|
try {
|
|
689
701
|
await this.#storage.writeTextAtomic(sessionFile, body, {
|
|
690
|
-
commitGuard: () => this.#diskEpoch === epoch,
|
|
702
|
+
commitGuard: () => !this.#released && this.#diskEpoch === epoch,
|
|
691
703
|
});
|
|
692
704
|
} catch (error) {
|
|
693
705
|
const recoveryErrors = [toError(error)];
|
|
@@ -791,6 +803,7 @@ export class SessionManager {
|
|
|
791
803
|
* concurrent completed entries are durable without recreating a vacated source.
|
|
792
804
|
*/
|
|
793
805
|
#rewriteSynchronously(): void {
|
|
806
|
+
if (this.#released) return;
|
|
794
807
|
if (!this.#persist || !this.#shouldHaveSessionFile()) return;
|
|
795
808
|
const targetPath = this.#liveRelocationWritePath() ?? this.#sessionFile;
|
|
796
809
|
if (!targetPath) return;
|
|
@@ -833,6 +846,7 @@ export class SessionManager {
|
|
|
833
846
|
*/
|
|
834
847
|
async #rewriteAtomically(): Promise<void> {
|
|
835
848
|
if (!this.#persist || !this.#sessionFile) return;
|
|
849
|
+
if (this.#released) return;
|
|
836
850
|
|
|
837
851
|
const startEpoch = this.#diskEpoch;
|
|
838
852
|
await this.#scheduleDiskWork(
|
|
@@ -858,6 +872,7 @@ export class SessionManager {
|
|
|
858
872
|
* their post-publish state updates.
|
|
859
873
|
*/
|
|
860
874
|
async #runFencedAtomicRewrite(epoch: number): Promise<boolean> {
|
|
875
|
+
if (this.#released) return false;
|
|
861
876
|
this.#atomicRewriteFenceEpoch = epoch;
|
|
862
877
|
try {
|
|
863
878
|
do {
|
|
@@ -867,7 +882,7 @@ export class SessionManager {
|
|
|
867
882
|
if (!sessionFile) return false;
|
|
868
883
|
if (this.#diskEpoch !== epoch) return false;
|
|
869
884
|
await this.#storage.writeTextAtomic(sessionFile, this.#fileBody(), {
|
|
870
|
-
commitGuard: () => this.#diskEpoch === epoch,
|
|
885
|
+
commitGuard: () => !this.#released && this.#diskEpoch === epoch,
|
|
871
886
|
});
|
|
872
887
|
if (this.#diskEpoch !== epoch) return false;
|
|
873
888
|
} while (this.#atomicRewriteDirty);
|
|
@@ -884,7 +899,7 @@ export class SessionManager {
|
|
|
884
899
|
}
|
|
885
900
|
|
|
886
901
|
#appendToSessionFile(entry: SessionEntry): void {
|
|
887
|
-
if (!this.#persist || !this.#sessionFile) return;
|
|
902
|
+
if (this.#released || !this.#persist || !this.#sessionFile) return;
|
|
888
903
|
if (this.#atomicEntryBatch) {
|
|
889
904
|
this.#fileIsCurrent = false;
|
|
890
905
|
this.#rewriteRequired = true;
|
|
@@ -979,6 +994,7 @@ export class SessionManager {
|
|
|
979
994
|
const line = this.#lineFor(entry);
|
|
980
995
|
await this.#scheduleDiskWork(
|
|
981
996
|
async () => {
|
|
997
|
+
if (this.#released) return;
|
|
982
998
|
const sessionFile = this.#sessionFile;
|
|
983
999
|
if (!sessionFile) return;
|
|
984
1000
|
try {
|
|
@@ -1093,6 +1109,10 @@ export class SessionManager {
|
|
|
1093
1109
|
}
|
|
1094
1110
|
|
|
1095
1111
|
#recordEntry(entry: SessionEntry): void {
|
|
1112
|
+
if (this.#released) {
|
|
1113
|
+
logger.warn("Dropped session entry appended after terminal release", { type: entry.type });
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1096
1116
|
this.#entries.push(entry);
|
|
1097
1117
|
this.#index.insert(entry);
|
|
1098
1118
|
const batch = this.#atomicEntryBatch;
|
|
@@ -1707,6 +1727,49 @@ export class SessionManager {
|
|
|
1707
1727
|
if (this.#diskFailure) throw this.#diskFailure;
|
|
1708
1728
|
}
|
|
1709
1729
|
|
|
1730
|
+
/**
|
|
1731
|
+
* Raise the terminal write barrier ahead of the final {@link close}. Once
|
|
1732
|
+
* sealed:
|
|
1733
|
+
* - every later append, title change, and rewrite is a dropped no-op —
|
|
1734
|
+
* including work an event handler tries to enqueue while dispose is
|
|
1735
|
+
* awaiting `close()` on the disk tail;
|
|
1736
|
+
* - the disk epoch is bumped, so queued-but-unexecuted tail work is
|
|
1737
|
+
* superseded and an ALREADY-RUNNING fenced/repair rewrite (awaiting the
|
|
1738
|
+
* tail, drain, writer close, or the atomic stage) fails its commit guard
|
|
1739
|
+
* at the rename fence instead of publishing over a revived file.
|
|
1740
|
+
* The final `close()` itself is scheduled after the bump and still runs;
|
|
1741
|
+
* pre-seal hot-path appends are already in the page cache. Idempotent;
|
|
1742
|
+
* terminal.
|
|
1743
|
+
*/
|
|
1744
|
+
seal(): void {
|
|
1745
|
+
if (this.#released) return;
|
|
1746
|
+
this.#released = true;
|
|
1747
|
+
this.#diskEpoch++;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
/**
|
|
1751
|
+
* Terminal release: drop the in-memory transcript and complete the
|
|
1752
|
+
* {@link seal}. The entry journal and its index mirror the agent's message
|
|
1753
|
+
* array (tool results, file contents, base64 frame images); on a disposed
|
|
1754
|
+
* session — e.g. a parked subagent still referenced by the lifecycle
|
|
1755
|
+
* adoption record — they would otherwise stay pinned for the process
|
|
1756
|
+
* lifetime.
|
|
1757
|
+
*
|
|
1758
|
+
* Closes the append writer; with the seal up, nothing can reopen it. A
|
|
1759
|
+
* revival may reopen the same JSONL through a NEW manager the moment
|
|
1760
|
+
* dispose returns; a late event handler resuming on THIS manager must
|
|
1761
|
+
* never race that writer — and a post-release rewrite would persist the
|
|
1762
|
+
* now-empty entry list, truncating the transcript. Reads after this point
|
|
1763
|
+
* reopen from disk (revival, `history://`). Only call from session
|
|
1764
|
+
* dispose, after the final `close()`; idempotent.
|
|
1765
|
+
*/
|
|
1766
|
+
releaseRetainedEntries(): void {
|
|
1767
|
+
this.seal();
|
|
1768
|
+
this.#entries = [];
|
|
1769
|
+
this.#index.clear();
|
|
1770
|
+
this.#closeWriterEventually();
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1710
1773
|
getCwd(): string {
|
|
1711
1774
|
return this.#cwd;
|
|
1712
1775
|
}
|
|
@@ -1924,6 +1987,7 @@ export class SessionManager {
|
|
|
1924
1987
|
* Auto titles are ignored once the user has set a name.
|
|
1925
1988
|
*/
|
|
1926
1989
|
async setSessionName(name: string, source: SessionTitleSource = "auto", trigger?: string): Promise<boolean> {
|
|
1990
|
+
if (this.#released) return false;
|
|
1927
1991
|
if (this.#titleSource === "user" && source === "auto") return false;
|
|
1928
1992
|
|
|
1929
1993
|
const title = SessionManager.#cleanTitle(name);
|
|
@@ -10,12 +10,9 @@ import { formatModelString } from "../config/model-resolver";
|
|
|
10
10
|
import type { Settings } from "../config/settings";
|
|
11
11
|
import { validateProviderMaxInFlightRequests } from "../config/settings";
|
|
12
12
|
import type { LocalProtocolOptions } from "../internal-urls";
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
type SecretObfuscator,
|
|
17
|
-
stripPendingSecretPlaceholderSuffix,
|
|
18
|
-
} from "../secrets/obfuscator";
|
|
13
|
+
import { deobfuscateSessionContext, obfuscateMessages } from "../secrets/message-transform";
|
|
14
|
+
import type { SecretObfuscator } from "../secrets/obfuscator";
|
|
15
|
+
import { stripPendingSecretPlaceholderSuffix } from "../secrets/placeholder";
|
|
19
16
|
import { normalizeModelContextImages } from "../utils/image-loading";
|
|
20
17
|
import { describeAttachedImagesForTextModel } from "../utils/image-vision-fallback";
|
|
21
18
|
import { type CustomMessage, convertToLlm } from "./messages";
|
|
@@ -198,6 +198,15 @@ export class SessionTools {
|
|
|
198
198
|
#presentationPinnedToolNames: ReadonlySet<string> | undefined;
|
|
199
199
|
#runtimeSelectedToolNames: ReadonlySet<string> | undefined;
|
|
200
200
|
#baseSystemPrompt: string[];
|
|
201
|
+
/**
|
|
202
|
+
* Per-turn system prompt returned by a `before_agent_start` extension hook
|
|
203
|
+
* ("replace the system prompt for this turn"). While set, base-prompt
|
|
204
|
+
* rebuilds keep this override on the agent instead of the rebuilt base, so a
|
|
205
|
+
* rebuild landing in the prompt window (compaction/promotion, memory
|
|
206
|
+
* promotion, MCP/RPC tool refresh, hindsight MM-TTL refresh) cannot silently
|
|
207
|
+
* drop it before the request. Cleared when the turn ends.
|
|
208
|
+
*/
|
|
209
|
+
#turnSystemPromptOverride: string[] | undefined;
|
|
201
210
|
#lastAppliedToolSignature: string | undefined;
|
|
202
211
|
/**
|
|
203
212
|
* `xd://` device names the current base system prompt renders in its catalog
|
|
@@ -262,6 +271,31 @@ export class SessionTools {
|
|
|
262
271
|
this.#baseSystemPrompt = prompt;
|
|
263
272
|
}
|
|
264
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Pushes `base` to the agent as the effective system prompt, unless an active
|
|
276
|
+
* per-turn {@link #turnSystemPromptOverride} takes precedence. Every base
|
|
277
|
+
* rebuild applies its result through here so a mid-turn rebuild preserves the
|
|
278
|
+
* override.
|
|
279
|
+
*/
|
|
280
|
+
#applyAgentSystemPrompt(base: string[]): void {
|
|
281
|
+
this.#host.agent.setSystemPrompt(this.#turnSystemPromptOverride ?? base);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Registers the per-turn `before_agent_start` system-prompt override and
|
|
286
|
+
* applies it to the agent. Base rebuilds during the turn preserve it until
|
|
287
|
+
* {@link clearTurnSystemPromptOverride}.
|
|
288
|
+
*/
|
|
289
|
+
setTurnSystemPromptOverride(prompt: string[]): void {
|
|
290
|
+
this.#turnSystemPromptOverride = prompt;
|
|
291
|
+
this.#host.agent.setSystemPrompt(prompt);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** Drops the active per-turn override; later rebuilds fall back to the base prompt. */
|
|
295
|
+
clearTurnSystemPromptOverride(): void {
|
|
296
|
+
this.#turnSystemPromptOverride = undefined;
|
|
297
|
+
}
|
|
298
|
+
|
|
265
299
|
/** Skills currently rendered into the system prompt. */
|
|
266
300
|
get skills(): Skill[] {
|
|
267
301
|
return this.#skills;
|
|
@@ -690,7 +724,7 @@ export class SessionTools {
|
|
|
690
724
|
if (this.#lastAppliedToolSignature !== undefined) this.#host.clearInheritedProviderPromptCacheKey();
|
|
691
725
|
this.#baseSystemPrompt = rebuiltSystemPrompt;
|
|
692
726
|
this.#host.clearMemoryPromotionSnapshot();
|
|
693
|
-
this.#
|
|
727
|
+
this.#applyAgentSystemPrompt(this.#baseSystemPrompt);
|
|
694
728
|
this.#lastAppliedToolSignature = rebuiltSignature;
|
|
695
729
|
this.#promptModelKey = this.#currentPromptModelKey();
|
|
696
730
|
this.#basePromptXdevNames = new Set(rebuiltXdevCatalogNames);
|
|
@@ -1130,7 +1164,7 @@ export class SessionTools {
|
|
|
1130
1164
|
) {
|
|
1131
1165
|
this.#host.clearInheritedProviderPromptCacheKey();
|
|
1132
1166
|
}
|
|
1133
|
-
this.#
|
|
1167
|
+
this.#applyAgentSystemPrompt(this.#baseSystemPrompt);
|
|
1134
1168
|
this.#promptModelKey = this.#currentPromptModelKey();
|
|
1135
1169
|
// Refresh the cached signature so a subsequent `applyActiveToolsByName` with
|
|
1136
1170
|
// the same tool set does not re-rebuild on top of the explicit refresh we
|
|
@@ -1170,7 +1204,7 @@ export class SessionTools {
|
|
|
1170
1204
|
this.#host.captureMemoryPromotionSnapshot(previousBaseSystemPrompt);
|
|
1171
1205
|
const stablePrompt = [...previousBaseSystemPrompt, injected];
|
|
1172
1206
|
this.#baseSystemPrompt = stablePrompt;
|
|
1173
|
-
this.#
|
|
1207
|
+
this.#applyAgentSystemPrompt(stablePrompt);
|
|
1174
1208
|
return stablePrompt;
|
|
1175
1209
|
} catch (err) {
|
|
1176
1210
|
logger.debug("Memory backend beforeAgentStartPrompt failed", {
|
|
@@ -27,6 +27,15 @@ const QUESTION_PROMPT_RE =
|
|
|
27
27
|
const USER_DIRECTED_PROMPT_RE = /\b(?:you|your|we|our)\b/i;
|
|
28
28
|
const USER_RESPONSE_CUE_RE =
|
|
29
29
|
/^(?:please\s+)?(?:confirm|reply|choose|pick|decide|advise)\b|^(?:please\s+)?answer\b|^(?:please\s+)?(?:let\s+me\s+know|tell\s+me)\b/i;
|
|
30
|
+
/**
|
|
31
|
+
* A trailing question mark is the universal signal that a line is a question, but
|
|
32
|
+
* the English word/pronoun gates above exist to filter incidental "?" out of prose
|
|
33
|
+
* (e.g. a TypeScript `foo?: string` tail). Non-English text has no cheap word list,
|
|
34
|
+
* yet any non-ASCII character in a "?"/"?"-terminated line reliably marks it as
|
|
35
|
+
* genuine prose — CJK/Japanese/Korean, Spanish `¿…?`, accented Latin — so treat it
|
|
36
|
+
* as a real user-directed question. Fixes non-Latin prompts going undetected (#7803).
|
|
37
|
+
*/
|
|
38
|
+
const NON_ASCII_TEXT_RE = /[^\x00-\x7F]/;
|
|
30
39
|
|
|
31
40
|
interface PromptLine {
|
|
32
41
|
text: string;
|
|
@@ -361,7 +370,8 @@ function isQuestionPromptLine(line: string): boolean {
|
|
|
361
370
|
return (
|
|
362
371
|
candidate.hadPromptLabel ||
|
|
363
372
|
QUESTION_PROMPT_RE.test(candidate.text) ||
|
|
364
|
-
USER_DIRECTED_PROMPT_RE.test(candidate.text)
|
|
373
|
+
USER_DIRECTED_PROMPT_RE.test(candidate.text) ||
|
|
374
|
+
NON_ASCII_TEXT_RE.test(candidate.text)
|
|
365
375
|
);
|
|
366
376
|
}
|
|
367
377
|
|