@oh-my-pi/pi-coding-agent 15.12.4 → 15.13.0
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 +304 -6
- package/dist/cli.js +1015 -881
- package/dist/types/async/job-manager.d.ts +15 -0
- package/dist/types/autolearn/controller.d.ts +25 -0
- package/dist/types/autolearn/managed-skills.d.ts +45 -0
- package/dist/types/autoresearch/state.d.ts +1 -1
- package/dist/types/autoresearch/types.d.ts +1 -1
- package/dist/types/cli/args.d.ts +19 -1
- package/dist/types/cli/session-picker.d.ts +1 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/cli/setup-model-picker.d.ts +14 -0
- package/dist/types/collab/protocol.d.ts +1 -1
- package/dist/types/commands/say.d.ts +24 -0
- package/dist/types/config/keybindings.d.ts +3 -3
- package/dist/types/config/model-registry.d.ts +10 -0
- package/dist/types/config/models-config-schema.d.ts +12 -0
- package/dist/types/config/models-config.d.ts +8 -2
- package/dist/types/config/settings-schema.d.ts +261 -58
- package/dist/types/export/html/index.d.ts +2 -1
- package/dist/types/extensibility/extensions/model-api.d.ts +17 -0
- package/dist/types/extensibility/extensions/runner.d.ts +3 -1
- package/dist/types/extensibility/extensions/types.d.ts +47 -1
- package/dist/types/extensibility/hooks/index.d.ts +2 -1
- package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +9 -0
- package/dist/types/extensibility/plugins/loader.d.ts +11 -0
- package/dist/types/extensibility/shared-events.d.ts +1 -1
- package/dist/types/extensibility/skills.d.ts +10 -0
- package/dist/types/goals/guided-setup.d.ts +18 -0
- package/dist/types/goals/state.d.ts +1 -1
- package/dist/types/hindsight/transcript.d.ts +1 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/internal-urls/local-protocol.d.ts +4 -2
- package/dist/types/main.d.ts +4 -3
- package/dist/types/mcp/startup-events.d.ts +11 -0
- package/dist/types/memories/index.d.ts +7 -0
- package/dist/types/memory-backend/local-backend.d.ts +4 -3
- package/dist/types/mnemopi/config.d.ts +4 -4
- package/dist/types/modes/components/agent-hub.d.ts +6 -0
- package/dist/types/modes/components/assistant-message.d.ts +1 -2
- package/dist/types/modes/components/compaction-summary-message.d.ts +15 -1
- package/dist/types/modes/components/custom-editor.d.ts +39 -1
- package/dist/types/modes/components/custom-editor.test.d.ts +1 -0
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/tool-execution.d.ts +26 -16
- package/dist/types/modes/components/transcript-container.d.ts +23 -2
- package/dist/types/modes/components/tree-selector.d.ts +1 -1
- package/dist/types/modes/components/usage-row.d.ts +3 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -2
- package/dist/types/modes/controllers/input-controller.d.ts +14 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +3 -1
- package/dist/types/modes/gradient-highlight.d.ts +9 -4
- package/dist/types/modes/image-references.d.ts +6 -0
- package/dist/types/modes/interactive-mode.d.ts +27 -3
- package/dist/types/modes/magic-keywords.d.ts +13 -1
- package/dist/types/modes/rpc/rpc-mode.d.ts +35 -1
- package/dist/types/modes/rpc/rpc-types.d.ts +9 -1
- package/dist/types/modes/runtime-init.d.ts +4 -0
- package/dist/types/modes/theme/theme.d.ts +13 -2
- package/dist/types/modes/types.d.ts +8 -2
- package/dist/types/modes/utils/ui-helpers.d.ts +1 -1
- package/dist/types/registry/agent-registry.d.ts +17 -0
- package/dist/types/secrets/obfuscator.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +14 -2
- package/dist/types/session/indexed-session-storage.d.ts +3 -4
- package/dist/types/session/session-context.d.ts +39 -0
- package/dist/types/session/session-entries.d.ts +159 -0
- package/dist/types/session/session-listing.d.ts +69 -0
- package/dist/types/session/session-loader.d.ts +16 -0
- package/dist/types/session/session-manager.d.ts +82 -474
- package/dist/types/session/session-migrations.d.ts +12 -0
- package/dist/types/session/session-paths.d.ts +25 -0
- package/dist/types/session/session-persistence.d.ts +8 -0
- package/dist/types/session/session-storage.d.ts +11 -12
- package/dist/types/session/snapcompact-inline.d.ts +12 -1
- package/dist/types/session/snapcompact-savings-journal.d.ts +46 -0
- package/dist/types/session/tool-choice-queue.d.ts +6 -6
- package/dist/types/stt/asr-client.d.ts +90 -0
- package/dist/types/stt/asr-protocol.d.ts +97 -0
- package/dist/types/stt/asr-worker.d.ts +2 -0
- package/dist/types/stt/downloader.d.ts +38 -0
- package/dist/types/stt/endpointer.d.ts +59 -0
- package/dist/types/stt/index.d.ts +5 -1
- package/dist/types/stt/models.d.ts +120 -0
- package/dist/types/stt/recorder.d.ts +17 -0
- package/dist/types/stt/stt-controller.d.ts +6 -0
- package/dist/types/stt/transcriber.d.ts +5 -7
- package/dist/types/stt/wav.d.ts +29 -0
- package/dist/types/system-prompt.d.ts +4 -0
- package/dist/types/task/executor.d.ts +2 -0
- package/dist/types/task/index.d.ts +9 -1
- package/dist/types/task/types.d.ts +36 -0
- package/dist/types/tools/bash.d.ts +2 -2
- package/dist/types/tools/eval-render.d.ts +1 -1
- package/dist/types/tools/index.d.ts +11 -1
- package/dist/types/tools/irc.d.ts +1 -0
- package/dist/types/tools/learn.d.ts +51 -0
- package/dist/types/tools/manage-skill.d.ts +40 -0
- package/dist/types/tools/plan-mode-guard.d.ts +10 -0
- package/dist/types/tools/renderers.d.ts +7 -11
- package/dist/types/tools/ssh.d.ts +1 -1
- package/dist/types/tools/todo.d.ts +1 -1
- package/dist/types/tools/tts.d.ts +25 -0
- package/dist/types/tools/write.d.ts +1 -1
- package/dist/types/tts/downloader.d.ts +20 -0
- package/dist/types/tts/index.d.ts +8 -0
- package/dist/types/tts/models.d.ts +82 -0
- package/dist/types/tts/player.d.ts +32 -0
- package/dist/types/tts/runtime.d.ts +6 -0
- package/dist/types/tts/streaming-player.d.ts +41 -0
- package/dist/types/tts/tts-client.d.ts +93 -0
- package/dist/types/tts/tts-protocol.d.ts +95 -0
- package/dist/types/tts/tts-worker.d.ts +2 -0
- package/dist/types/tts/vocalizer.d.ts +41 -0
- package/dist/types/tts/wav.d.ts +8 -0
- package/dist/types/utils/tool-choice.d.ts +8 -0
- package/dist/types/utils/tools-manager.d.ts +2 -1
- package/dist/types/utils/tools-manager.test.d.ts +1 -0
- package/dist/types/web/scrapers/github.d.ts +1 -1
- package/package.json +15 -14
- package/src/async/job-manager.ts +49 -0
- package/src/autolearn/controller.ts +139 -0
- package/src/autolearn/managed-skills.ts +257 -0
- package/src/autoresearch/state.ts +1 -1
- package/src/autoresearch/types.ts +1 -1
- package/src/cli/args.ts +56 -2
- package/src/cli/session-picker.ts +2 -1
- package/src/cli/setup-cli.ts +148 -47
- package/src/cli/setup-model-picker.ts +43 -0
- package/src/cli-commands.ts +1 -0
- package/src/cli.ts +45 -13
- package/src/collab/host.ts +1 -1
- package/src/collab/protocol.ts +1 -1
- package/src/commands/say.ts +102 -0
- package/src/commands/setup.ts +1 -1
- package/src/commit/agentic/tools/analyze-file.ts +3 -0
- package/src/config/keybindings.ts +2 -2
- package/src/config/model-discovery.ts +11 -5
- package/src/config/model-registry.ts +64 -9
- package/src/config/models-config-schema.ts +4 -1
- package/src/config/models-config.ts +2 -1
- package/src/config/settings-schema.ts +248 -32
- package/src/config/settings.ts +10 -0
- package/src/discovery/builtin.ts +23 -1
- package/src/discovery/claude-plugins.ts +44 -5
- package/src/discovery/helpers.ts +41 -1
- package/src/eval/__tests__/budget-bridge.test.ts +1 -1
- package/src/eval/js/shared/prelude.txt +69 -17
- package/src/export/html/index.ts +3 -6
- package/src/extensibility/extensions/model-api.ts +41 -0
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +52 -1
- package/src/extensibility/extensions/wrapper.ts +41 -5
- package/src/extensibility/hooks/index.ts +2 -1
- package/src/extensibility/plugins/legacy-pi-compat.ts +43 -13
- package/src/extensibility/plugins/loader.ts +30 -19
- package/src/extensibility/plugins/manager.ts +221 -90
- package/src/extensibility/shared-events.ts +1 -1
- package/src/extensibility/skills.ts +96 -15
- package/src/goals/guided-setup.ts +133 -0
- package/src/goals/state.ts +1 -1
- package/src/hindsight/transcript.ts +1 -1
- package/src/index.ts +5 -0
- package/src/internal-urls/docs-index.generated.ts +10 -10
- package/src/internal-urls/history-protocol.ts +1 -1
- package/src/internal-urls/local-protocol.ts +29 -7
- package/src/main.ts +27 -7
- package/src/mcp/startup-events.ts +21 -0
- package/src/mcp/transports/stdio.ts +2 -1
- package/src/memories/index.ts +146 -11
- package/src/memory-backend/local-backend.ts +11 -5
- package/src/mnemopi/backend.ts +1 -0
- package/src/mnemopi/config.ts +26 -10
- package/src/modes/acp/acp-agent.ts +3 -5
- package/src/modes/components/agent-hub.ts +49 -4
- package/src/modes/components/assistant-message.ts +4 -37
- package/src/modes/components/compaction-summary-message.ts +125 -26
- package/src/modes/components/custom-editor.test.ts +96 -0
- package/src/modes/components/custom-editor.ts +164 -8
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/settings-defs.ts +7 -0
- package/src/modes/components/tool-execution.ts +82 -43
- package/src/modes/components/transcript-container.ts +70 -1
- package/src/modes/components/tree-selector.ts +1 -1
- package/src/modes/components/usage-row.ts +18 -0
- package/src/modes/components/user-message.ts +4 -2
- package/src/modes/controllers/command-controller.ts +14 -4
- package/src/modes/controllers/event-controller.ts +78 -11
- package/src/modes/controllers/extension-ui-controller.ts +6 -0
- package/src/modes/controllers/input-controller.ts +258 -27
- package/src/modes/controllers/selector-controller.ts +12 -2
- package/src/modes/gradient-highlight.ts +21 -9
- package/src/modes/image-references.ts +20 -0
- package/src/modes/interactive-mode.ts +286 -40
- package/src/modes/magic-keywords.ts +27 -5
- package/src/modes/rpc/rpc-mode.ts +146 -14
- package/src/modes/rpc/rpc-subagents.ts +2 -2
- package/src/modes/rpc/rpc-types.ts +8 -2
- package/src/modes/runtime-init.ts +28 -3
- package/src/modes/theme/theme.ts +98 -50
- package/src/modes/types.ts +6 -2
- package/src/modes/utils/hotkeys-markdown.ts +1 -1
- package/src/modes/utils/ui-helpers.ts +34 -6
- package/src/priority.json +5 -1
- package/src/prompts/agents/task.md +1 -0
- package/src/prompts/goals/guided-goal-interview.md +8 -0
- package/src/prompts/goals/guided-goal-system.md +12 -0
- package/src/prompts/memories/read-path.md +6 -0
- package/src/prompts/system/autolearn-guidance-learn.md +1 -0
- package/src/prompts/system/autolearn-guidance.md +7 -0
- package/src/prompts/system/autolearn-nudge.md +3 -0
- package/src/prompts/system/eager-task.md +7 -0
- package/src/prompts/system/eager-todo.md +11 -6
- package/src/prompts/system/subagent-system-prompt.md +4 -0
- package/src/prompts/system/system-prompt.md +10 -5
- package/src/prompts/system/title-marker-instruction.md +1 -0
- package/src/prompts/system/title-system-marker.md +16 -0
- package/src/prompts/tools/job.md +1 -0
- package/src/prompts/tools/learn.md +7 -0
- package/src/prompts/tools/manage-skill.md +9 -0
- package/src/prompts/tools/task.md +3 -0
- package/src/registry/agent-registry.ts +30 -0
- package/src/sdk.ts +88 -24
- package/src/secrets/obfuscator.ts +1 -1
- package/src/session/agent-session.ts +209 -87
- package/src/session/history-storage.ts +2 -2
- package/src/session/indexed-session-storage.ts +7 -17
- package/src/session/session-context.ts +352 -0
- package/src/session/session-entries.ts +194 -0
- package/src/session/session-listing.ts +588 -0
- package/src/session/session-loader.ts +106 -0
- package/src/session/session-manager.ts +933 -3145
- package/src/session/session-migrations.ts +78 -0
- package/src/session/session-paths.ts +193 -0
- package/src/session/session-persistence.ts +131 -0
- package/src/session/session-storage.ts +91 -50
- package/src/session/snapcompact-inline.ts +21 -1
- package/src/session/snapcompact-savings-journal.ts +113 -0
- package/src/session/tool-choice-queue.ts +23 -11
- package/src/slash-commands/builtin-registry.ts +25 -3
- package/src/stt/asr-client.ts +520 -0
- package/src/stt/asr-protocol.ts +65 -0
- package/src/stt/asr-worker.ts +790 -0
- package/src/stt/downloader.ts +107 -47
- package/src/stt/endpointer.ts +259 -0
- package/src/stt/index.ts +5 -1
- package/src/stt/models.ts +150 -0
- package/src/stt/recorder.ts +247 -60
- package/src/stt/stt-controller.ts +201 -22
- package/src/stt/transcriber.ts +37 -68
- package/src/stt/wav.ts +173 -0
- package/src/system-prompt.ts +8 -0
- package/src/task/agents.ts +1 -2
- package/src/task/executor.ts +49 -15
- package/src/task/index.ts +60 -6
- package/src/task/render.ts +83 -8
- package/src/task/types.ts +53 -0
- package/src/tools/ask.ts +8 -0
- package/src/tools/bash.ts +4 -3
- package/src/tools/eval-render.ts +4 -3
- package/src/tools/index.ts +40 -4
- package/src/tools/irc.ts +10 -2
- package/src/tools/job.ts +14 -2
- package/src/tools/learn.ts +144 -0
- package/src/tools/manage-skill.ts +104 -0
- package/src/tools/plan-mode-guard.ts +53 -19
- package/src/tools/renderers.ts +7 -11
- package/src/tools/ssh.ts +4 -3
- package/src/tools/todo.ts +1 -1
- package/src/tools/tts.ts +203 -92
- package/src/tools/write.ts +18 -2
- package/src/tts/downloader.ts +64 -0
- package/src/tts/index.ts +8 -0
- package/src/tts/models.ts +137 -0
- package/src/tts/player.ts +137 -0
- package/src/tts/runtime.ts +21 -0
- package/src/tts/streaming-player.ts +266 -0
- package/src/tts/tts-client.ts +647 -0
- package/src/tts/tts-protocol.ts +60 -0
- package/src/tts/tts-worker.ts +497 -0
- package/src/tts/vocalizer.ts +162 -0
- package/src/tts/wav.ts +58 -0
- package/src/utils/title-generator.ts +48 -5
- package/src/utils/tool-choice.ts +16 -0
- package/src/utils/tools-manager.test.ts +25 -0
- package/src/utils/tools-manager.ts +19 -1
- package/src/web/scrapers/github.ts +96 -0
- package/src/web/search/index.ts +13 -0
- package/src/web/search/providers/searxng.ts +13 -1
- package/dist/types/stt/setup.d.ts +0 -18
- package/src/stt/setup.ts +0 -52
- package/src/stt/transcribe.py +0 -70
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Append-only journal of snapcompact tool-result savings.
|
|
3
|
+
*
|
|
4
|
+
* Snapcompact frames are transient — built per provider request in
|
|
5
|
+
* `transformProviderContext` and never written to session.jsonl — so the tokens
|
|
6
|
+
* they keep off the wire would otherwise leave no trace. This records one line
|
|
7
|
+
* the FIRST time a tool result is imaged in a session:
|
|
8
|
+
*
|
|
9
|
+
* {"ts":<epochMs>,"session":<sessionFile>,"provider":..,"model":..,"toolCallId":..,"savedTokens":..}
|
|
10
|
+
*
|
|
11
|
+
* Newline-delimited JSON, opened with O_APPEND so concurrent appenders (parallel
|
|
12
|
+
* agents/subagents) never interleave a partial line. Writes are fire-and-forget;
|
|
13
|
+
* a failure is logged at debug and never propagates into the request hot path.
|
|
14
|
+
*
|
|
15
|
+
* Readers MUST dedup by (session, toolCallId): a session resumed in a fresh
|
|
16
|
+
* process re-images the same results and may append a second line. The savings
|
|
17
|
+
* for a given (session, toolCallId) are stable, so any-per-key is correct.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import * as fs from "node:fs/promises";
|
|
21
|
+
import * as path from "node:path";
|
|
22
|
+
import type { Model } from "@oh-my-pi/pi-ai";
|
|
23
|
+
import { getStatsDbPath, isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
24
|
+
|
|
25
|
+
export interface SnapcompactSavingsRecord {
|
|
26
|
+
/** Epoch milliseconds when the swap was applied. */
|
|
27
|
+
ts: number;
|
|
28
|
+
/** Session file path (matches the stats `messages.session_file` key). */
|
|
29
|
+
session: string;
|
|
30
|
+
provider: string;
|
|
31
|
+
model: string;
|
|
32
|
+
toolCallId: string;
|
|
33
|
+
savedTokens: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** `~/.omp/.../snapcompact-savings.jsonl`, colocated with stats.db. */
|
|
37
|
+
export function snapcompactSavingsJournalPath(): string {
|
|
38
|
+
return path.join(path.dirname(getStatsDbPath()), "snapcompact-savings.jsonl");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Appends savings to the journal, deduped by toolCallId for the recorder's
|
|
43
|
+
* lifetime (one per session). Returns the in-flight append so callers/tests can
|
|
44
|
+
* await durability; the production transform leaves it floating (fire-and-forget,
|
|
45
|
+
* and it never rejects — I/O errors are swallowed to debug). `getSession` is read
|
|
46
|
+
* at write time so a session file assigned late is still captured; a null session
|
|
47
|
+
* (in-memory / SDK embedding) or non-positive savings skip the write.
|
|
48
|
+
*/
|
|
49
|
+
export type SnapcompactSavingsRecorder = (
|
|
50
|
+
savings: ReadonlyArray<{ toolCallId: string; savedTokens: number }>,
|
|
51
|
+
model: Model,
|
|
52
|
+
) => Promise<void>;
|
|
53
|
+
|
|
54
|
+
export function createSnapcompactSavingsRecorder(
|
|
55
|
+
getSession: () => string | null,
|
|
56
|
+
journalPath: string = snapcompactSavingsJournalPath(),
|
|
57
|
+
): SnapcompactSavingsRecorder {
|
|
58
|
+
const seen = new Set<string>();
|
|
59
|
+
let dirEnsured = false;
|
|
60
|
+
return async (savings, model) => {
|
|
61
|
+
const session = getSession();
|
|
62
|
+
if (!session) return;
|
|
63
|
+
const ts = Date.now();
|
|
64
|
+
const lines: string[] = [];
|
|
65
|
+
for (const { toolCallId, savedTokens } of savings) {
|
|
66
|
+
if (savedTokens <= 0 || seen.has(toolCallId)) continue;
|
|
67
|
+
seen.add(toolCallId);
|
|
68
|
+
lines.push(
|
|
69
|
+
JSON.stringify({
|
|
70
|
+
ts,
|
|
71
|
+
session,
|
|
72
|
+
provider: model.provider,
|
|
73
|
+
model: model.id,
|
|
74
|
+
toolCallId,
|
|
75
|
+
savedTokens,
|
|
76
|
+
} satisfies SnapcompactSavingsRecord),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
if (lines.length === 0) return;
|
|
80
|
+
try {
|
|
81
|
+
if (!dirEnsured) {
|
|
82
|
+
await fs.mkdir(path.dirname(journalPath), { recursive: true });
|
|
83
|
+
dirEnsured = true;
|
|
84
|
+
}
|
|
85
|
+
await fs.appendFile(journalPath, `${lines.join("\n")}\n`);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
logger.debug("snapcompact savings journal append failed", { err: String(err) });
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Read all journal records. Malformed lines are skipped; a missing file is empty. */
|
|
93
|
+
export async function readSnapcompactSavingsJournal(
|
|
94
|
+
journalPath: string = snapcompactSavingsJournalPath(),
|
|
95
|
+
): Promise<SnapcompactSavingsRecord[]> {
|
|
96
|
+
let text: string;
|
|
97
|
+
try {
|
|
98
|
+
text = await Bun.file(journalPath).text();
|
|
99
|
+
} catch (err) {
|
|
100
|
+
if (isEnoent(err)) return [];
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
const records: SnapcompactSavingsRecord[] = [];
|
|
104
|
+
for (const line of text.split("\n")) {
|
|
105
|
+
if (!line.trim()) continue;
|
|
106
|
+
try {
|
|
107
|
+
records.push(JSON.parse(line) as SnapcompactSavingsRecord);
|
|
108
|
+
} catch {
|
|
109
|
+
/* skip malformed line */
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return records;
|
|
113
|
+
}
|
|
@@ -10,14 +10,14 @@ export interface ResolveInfo {
|
|
|
10
10
|
export interface RejectInfo {
|
|
11
11
|
/** The ToolChoice that was yielded but never (or unsuccessfully) served. */
|
|
12
12
|
choice: ToolChoice;
|
|
13
|
-
reason: "aborted" | "error" | "cleared" | "removed";
|
|
13
|
+
reason: "aborted" | "error" | "cleared" | "removed" | "unavailable" | "not_invoked";
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/** "requeue" replays the lost yield next turn; "drop" (or void/undefined) discards it. */
|
|
17
17
|
export type RejectOutcome = "requeue" | "drop";
|
|
18
18
|
|
|
19
19
|
export interface DirectiveCallbacks {
|
|
20
|
-
/** Fires when the yield
|
|
20
|
+
/** Fires when the yield completed; onInvoked directives require the requested tool to run first. */
|
|
21
21
|
onResolved?: (info: ResolveInfo) => void;
|
|
22
22
|
/**
|
|
23
23
|
* Fires when the yield is being discarded. Return "requeue" to replay the
|
|
@@ -62,6 +62,7 @@ export function* onceGen(choice: ToolChoice): Generator<ToolChoice, void, unknow
|
|
|
62
62
|
interface InFlight {
|
|
63
63
|
directive: ToolChoiceDirective;
|
|
64
64
|
yielded: ToolChoice;
|
|
65
|
+
invoked: boolean;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
// ── Queue ───────────────────────────────────────────────────────────────────
|
|
@@ -116,7 +117,7 @@ export class ToolChoiceQueue {
|
|
|
116
117
|
this.#queue.shift();
|
|
117
118
|
continue;
|
|
118
119
|
}
|
|
119
|
-
this.#inFlight = { directive: head, yielded: result.value };
|
|
120
|
+
this.#inFlight = { directive: head, yielded: result.value, invoked: false };
|
|
120
121
|
return result.value;
|
|
121
122
|
}
|
|
122
123
|
return undefined;
|
|
@@ -125,14 +126,18 @@ export class ToolChoiceQueue {
|
|
|
125
126
|
// ── Lifecycle ─────────────────────────────────────────────────────────
|
|
126
127
|
|
|
127
128
|
/**
|
|
128
|
-
* The in-flight yield
|
|
129
|
-
*
|
|
130
|
-
*
|
|
129
|
+
* The in-flight yield completed normally. Directives with onInvoked are only
|
|
130
|
+
* consumed after their requested tool ran; a normal text turn or a different
|
|
131
|
+
* tool call requeues/rejects the directive instead.
|
|
131
132
|
*/
|
|
132
133
|
resolve(): void {
|
|
133
134
|
const inFlight = this.#inFlight;
|
|
134
|
-
this.#inFlight = undefined;
|
|
135
135
|
if (!inFlight) return;
|
|
136
|
+
if (inFlight.directive.callbacks.onInvoked && !inFlight.invoked) {
|
|
137
|
+
this.reject("not_invoked");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.#inFlight = undefined;
|
|
136
141
|
|
|
137
142
|
this.#lastResolvedLabel = inFlight.directive.label;
|
|
138
143
|
inFlight.directive.callbacks.onResolved?.({ choice: inFlight.yielded });
|
|
@@ -155,12 +160,13 @@ export class ToolChoiceQueue {
|
|
|
155
160
|
|
|
156
161
|
if (outcome === "requeue") {
|
|
157
162
|
// Re-queue only the lost yield, not the rest of the sequence. Carry forward
|
|
158
|
-
//
|
|
159
|
-
// and can requeue itself again if the next turn also aborts.
|
|
163
|
+
// callbacks so the replayed yield still executes and finalizes correctly,
|
|
164
|
+
// and can requeue itself again if the next turn also aborts or skips it.
|
|
160
165
|
this.#queue.unshift({
|
|
161
166
|
generator: onceGen(inFlight.yielded),
|
|
162
167
|
label: `${inFlight.directive.label}-requeued`,
|
|
163
168
|
callbacks: {
|
|
169
|
+
onResolved: inFlight.directive.callbacks.onResolved,
|
|
164
170
|
onInvoked: inFlight.directive.callbacks.onInvoked,
|
|
165
171
|
onRejected: inFlight.directive.callbacks.onRejected,
|
|
166
172
|
},
|
|
@@ -173,9 +179,15 @@ export class ToolChoiceQueue {
|
|
|
173
179
|
return this.#inFlight !== undefined;
|
|
174
180
|
}
|
|
175
181
|
|
|
176
|
-
/**
|
|
182
|
+
/** Return the in-flight directive's onInvoked handler and mark it when called. */
|
|
177
183
|
peekInFlightInvoker(): ((input: unknown) => Promise<unknown> | unknown) | undefined {
|
|
178
|
-
|
|
184
|
+
const inFlight = this.#inFlight;
|
|
185
|
+
const onInvoked = inFlight?.directive.callbacks.onInvoked;
|
|
186
|
+
if (!inFlight || !onInvoked) return undefined;
|
|
187
|
+
return (input: unknown): Promise<unknown> | unknown => {
|
|
188
|
+
inFlight.invoked = true;
|
|
189
|
+
return onInvoked(input);
|
|
190
|
+
};
|
|
179
191
|
}
|
|
180
192
|
|
|
181
193
|
// ── Cleanup ───────────────────────────────────────────────────────────
|
|
@@ -62,6 +62,19 @@ function refreshStatusLine(ctx: InteractiveModeContext): void {
|
|
|
62
62
|
ctx.ui.requestRender();
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/** `/fast status` label: "off", "on", or scope-qualified "on (… only)". */
|
|
66
|
+
function formatFastModeStatus(session: AgentSession): string {
|
|
67
|
+
if (!session.isFastModeEnabled()) return "off";
|
|
68
|
+
switch (session.serviceTier) {
|
|
69
|
+
case "openai-only":
|
|
70
|
+
return "on (OpenAI only)";
|
|
71
|
+
case "claude-only":
|
|
72
|
+
return "on (Claude only)";
|
|
73
|
+
default:
|
|
74
|
+
return "on";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
65
78
|
/** Scheme-less display form of a browser deep link: accent + underline, OSC-8 linked to the full URL. */
|
|
66
79
|
function collabWebLinkClickable(webLink: string): string {
|
|
67
80
|
const display = theme.fg("accent", `\x1b[4m${webLink.replace(/^https?:\/\//, "")}\x1b[24m`);
|
|
@@ -271,6 +284,16 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
271
284
|
runtime.ctx.editor.setText("");
|
|
272
285
|
},
|
|
273
286
|
},
|
|
287
|
+
{
|
|
288
|
+
name: "guided-goal",
|
|
289
|
+
description: "Interview and refine a goal before enabling goal mode",
|
|
290
|
+
inlineHint: "[rough objective]",
|
|
291
|
+
allowArgs: true,
|
|
292
|
+
handleTui: async (command, runtime) => {
|
|
293
|
+
await runtime.ctx.handleGuidedGoalCommand(command.args || undefined);
|
|
294
|
+
runtime.ctx.editor.setText("");
|
|
295
|
+
},
|
|
296
|
+
},
|
|
274
297
|
{
|
|
275
298
|
name: "loop",
|
|
276
299
|
description:
|
|
@@ -359,7 +382,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
359
382
|
return commandConsumed();
|
|
360
383
|
}
|
|
361
384
|
if (arg === "status") {
|
|
362
|
-
await runtime.output(`Fast mode is ${runtime.session
|
|
385
|
+
await runtime.output(`Fast mode is ${formatFastModeStatus(runtime.session)}.`);
|
|
363
386
|
return commandConsumed();
|
|
364
387
|
}
|
|
365
388
|
return usage("Usage: /fast [on|off|status]", runtime);
|
|
@@ -388,8 +411,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
388
411
|
return;
|
|
389
412
|
}
|
|
390
413
|
if (arg === "status") {
|
|
391
|
-
|
|
392
|
-
runtime.ctx.showStatus(`Fast mode is ${enabled ? "on" : "off"}.`);
|
|
414
|
+
runtime.ctx.showStatus(`Fast mode is ${formatFastModeStatus(runtime.ctx.session)}.`);
|
|
393
415
|
runtime.ctx.editor.setText("");
|
|
394
416
|
return;
|
|
395
417
|
}
|