@pentoshi/clai 3.6.0 → 3.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/compaction-summary.d.ts +17 -0
- package/dist/agent/compaction-summary.js +64 -0
- package/dist/agent/compaction-summary.js.map +1 -0
- package/dist/agent/confirm-port.d.ts +3 -1
- package/dist/agent/confirm-port.js +5 -1
- package/dist/agent/confirm-port.js.map +1 -1
- package/dist/agent/context-manager.js +45 -22
- package/dist/agent/context-manager.js.map +1 -1
- package/dist/agent/events.d.ts +6 -0
- package/dist/agent/evidence-governor.d.ts +37 -0
- package/dist/agent/evidence-governor.js +70 -0
- package/dist/agent/evidence-governor.js.map +1 -0
- package/dist/agent/loop-guard.d.ts +29 -11
- package/dist/agent/loop-guard.js +93 -39
- package/dist/agent/loop-guard.js.map +1 -1
- package/dist/agent/must-continue.d.ts +56 -0
- package/dist/agent/must-continue.js +240 -0
- package/dist/agent/must-continue.js.map +1 -0
- package/dist/agent/outcomes.d.ts +101 -0
- package/dist/agent/outcomes.js +359 -0
- package/dist/agent/outcomes.js.map +1 -0
- package/dist/agent/plan-decision.d.ts +33 -0
- package/dist/agent/plan-decision.js +104 -0
- package/dist/agent/plan-decision.js.map +1 -0
- package/dist/agent/plan-tool.d.ts +12 -0
- package/dist/agent/plan-tool.js +309 -104
- package/dist/agent/plan-tool.js.map +1 -1
- package/dist/agent/project-root.js +3 -0
- package/dist/agent/project-root.js.map +1 -1
- package/dist/agent/prompt-composer.d.ts +21 -0
- package/dist/agent/prompt-composer.js +46 -0
- package/dist/agent/prompt-composer.js.map +1 -0
- package/dist/agent/runner.d.ts +11 -1
- package/dist/agent/runner.js +1115 -965
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/scope-context.d.ts +3 -0
- package/dist/agent/scope-context.js +24 -0
- package/dist/agent/scope-context.js.map +1 -0
- package/dist/agent/scratch-write.d.ts +4 -0
- package/dist/agent/scratch-write.js +54 -0
- package/dist/agent/scratch-write.js.map +1 -0
- package/dist/agent/session-policy.d.ts +7 -0
- package/dist/agent/session-policy.js +61 -0
- package/dist/agent/session-policy.js.map +1 -1
- package/dist/agent/session-state.d.ts +41 -0
- package/dist/agent/session-state.js +107 -0
- package/dist/agent/session-state.js.map +1 -0
- package/dist/agent/step-budget.d.ts +14 -0
- package/dist/agent/step-budget.js +26 -0
- package/dist/agent/step-budget.js.map +1 -0
- package/dist/agent/task-analyzer.d.ts +12 -3
- package/dist/agent/task-analyzer.js +263 -23
- package/dist/agent/task-analyzer.js.map +1 -1
- package/dist/agent/task-evidence.d.ts +99 -29
- package/dist/agent/task-evidence.js +480 -91
- package/dist/agent/task-evidence.js.map +1 -1
- package/dist/agent/task-plan.d.ts +57 -0
- package/dist/agent/task-plan.js +147 -1
- package/dist/agent/task-plan.js.map +1 -1
- package/dist/agent/tool-call-parser.d.ts +4 -12
- package/dist/agent/tool-call-parser.js +34 -67
- package/dist/agent/tool-call-parser.js.map +1 -1
- package/dist/agent/tool-history.d.ts +7 -0
- package/dist/agent/tool-history.js +50 -0
- package/dist/agent/tool-history.js.map +1 -1
- package/dist/agent/tool-output-formatting.d.ts +13 -1
- package/dist/agent/tool-output-formatting.js +75 -22
- package/dist/agent/tool-output-formatting.js.map +1 -1
- package/dist/agent/turn-outcome.d.ts +11 -0
- package/dist/agent/turn-outcome.js +17 -0
- package/dist/agent/turn-outcome.js.map +1 -0
- package/dist/agent/turn-state.d.ts +11 -0
- package/dist/agent/turn-state.js +28 -0
- package/dist/agent/turn-state.js.map +1 -0
- package/dist/agent/workspace-orient.d.ts +11 -0
- package/dist/agent/workspace-orient.js +103 -12
- package/dist/agent/workspace-orient.js.map +1 -1
- package/dist/app/adapters/agent-event-adapter.d.ts +2 -13
- package/dist/app/adapters/agent-event-adapter.js +63 -25
- package/dist/app/adapters/agent-event-adapter.js.map +1 -1
- package/dist/app/adapters/current-agent-adapter.d.ts +0 -5
- package/dist/app/adapters/current-agent-adapter.js +4 -7
- package/dist/app/adapters/current-agent-adapter.js.map +1 -1
- package/dist/app/adapters/current-jobs-adapter.js +1 -0
- package/dist/app/adapters/current-jobs-adapter.js.map +1 -1
- package/dist/app/adapters/current-terminal-adapter.d.ts +0 -7
- package/dist/app/adapters/current-terminal-adapter.js +0 -7
- package/dist/app/adapters/current-terminal-adapter.js.map +1 -1
- package/dist/app/adapters/current-updates-adapter.d.ts +0 -5
- package/dist/app/adapters/current-updates-adapter.js +0 -5
- package/dist/app/adapters/current-updates-adapter.js.map +1 -1
- package/dist/app/adapters/in-memory-clipboard-adapter.d.ts +0 -5
- package/dist/app/adapters/in-memory-clipboard-adapter.js +0 -5
- package/dist/app/adapters/in-memory-clipboard-adapter.js.map +1 -1
- package/dist/app/commands/command.d.ts +0 -5
- package/dist/app/commands/command.js.map +1 -1
- package/dist/app/commands/registry.d.ts +0 -14
- package/dist/app/commands/registry.js +0 -20
- package/dist/app/commands/registry.js.map +1 -1
- package/dist/app/controllers/disposable.d.ts +0 -5
- package/dist/app/controllers/disposable.js +0 -5
- package/dist/app/controllers/disposable.js.map +1 -1
- package/dist/app/controllers/job-controller.d.ts +1 -5
- package/dist/app/controllers/job-controller.js +0 -4
- package/dist/app/controllers/job-controller.js.map +1 -1
- package/dist/app/controllers/plan-controller.d.ts +5 -8
- package/dist/app/controllers/plan-controller.js +30 -12
- package/dist/app/controllers/plan-controller.js.map +1 -1
- package/dist/app/controllers/session-controller.d.ts +17 -32
- package/dist/app/controllers/session-controller.js +56 -35
- package/dist/app/controllers/session-controller.js.map +1 -1
- package/dist/app/controllers/turn-controller.d.ts +2 -6
- package/dist/app/controllers/turn-controller.js +8 -8
- package/dist/app/controllers/turn-controller.js.map +1 -1
- package/dist/app/events/app-event.d.ts +4 -7
- package/dist/app/events/app-event.js +0 -6
- package/dist/app/events/app-event.js.map +1 -1
- package/dist/app/events/event-buffer.d.ts +6 -17
- package/dist/app/events/event-buffer.js +27 -24
- package/dist/app/events/event-buffer.js.map +1 -1
- package/dist/app/events/sequencer.d.ts +0 -9
- package/dist/app/events/sequencer.js +0 -4
- package/dist/app/events/sequencer.js.map +1 -1
- package/dist/app/ports/agent-port.d.ts +13 -3
- package/dist/app/ports/clipboard-port.d.ts +0 -5
- package/dist/app/ports/confirm-port.d.ts +0 -7
- package/dist/app/ports/jobs-port.d.ts +2 -5
- package/dist/app/ports/persistence-port.d.ts +0 -4
- package/dist/app/ports/secret-port.d.ts +0 -5
- package/dist/app/ports/terminal-port.d.ts +0 -6
- package/dist/app/ports/updates-port.d.ts +0 -4
- package/dist/attachments/service.d.ts +29 -0
- package/dist/attachments/service.js +47 -0
- package/dist/attachments/service.js.map +1 -0
- package/dist/commands/providers.js +0 -3
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/search-providers.d.ts +0 -33
- package/dist/commands/search-providers.js +0 -33
- package/dist/commands/search-providers.js.map +1 -1
- package/dist/commands/update.js +1 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +22 -42
- package/dist/index.js.map +1 -1
- package/dist/llm/adapters/ollama-tools.d.ts +0 -4
- package/dist/llm/adapters/ollama-tools.js +0 -4
- package/dist/llm/adapters/ollama-tools.js.map +1 -1
- package/dist/llm/capabilities.d.ts +10 -10
- package/dist/llm/capabilities.js +43 -17
- package/dist/llm/capabilities.js.map +1 -1
- package/dist/llm/groq.js +0 -6
- package/dist/llm/groq.js.map +1 -1
- package/dist/llm/http.d.ts +0 -17
- package/dist/llm/http.js +0 -45
- package/dist/llm/http.js.map +1 -1
- package/dist/llm/router.d.ts +0 -6
- package/dist/llm/router.js +0 -15
- package/dist/llm/router.js.map +1 -1
- package/dist/llm/tool-protocol.d.ts +0 -6
- package/dist/llm/tool-protocol.js +3 -7
- package/dist/llm/tool-protocol.js.map +1 -1
- package/dist/modes/agent.d.ts +2 -1
- package/dist/modes/agent.js +4 -2
- package/dist/modes/agent.js.map +1 -1
- package/dist/modes/ask.d.ts +0 -18
- package/dist/modes/ask.js +0 -49
- package/dist/modes/ask.js.map +1 -1
- package/dist/os/cwd.d.ts +0 -21
- package/dist/os/cwd.js +0 -24
- package/dist/os/cwd.js.map +1 -1
- package/dist/os/pkgmgr.js +0 -6
- package/dist/os/pkgmgr.js.map +1 -1
- package/dist/prompts/index.d.ts +6 -18
- package/dist/prompts/index.js +67 -293
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/system.agent.md +242 -0
- package/dist/prompts/system.ask.md +56 -0
- package/dist/repl/prompt-line.js +0 -36
- package/dist/repl/prompt-line.js.map +1 -1
- package/dist/repl/slash-commands.d.ts +0 -9
- package/dist/repl/slash-commands.js +2 -23
- package/dist/repl/slash-commands.js.map +1 -1
- package/dist/repl.d.ts +5 -0
- package/dist/repl.js +169 -55
- package/dist/repl.js.map +1 -1
- package/dist/safety/classifier.js +17 -9
- package/dist/safety/classifier.js.map +1 -1
- package/dist/safety/engagement-policy.d.ts +46 -0
- package/dist/safety/engagement-policy.js +198 -0
- package/dist/safety/engagement-policy.js.map +1 -0
- package/dist/store/engagement.d.ts +115 -0
- package/dist/store/engagement.js +278 -0
- package/dist/store/engagement.js.map +1 -0
- package/dist/store/logs.d.ts +5 -0
- package/dist/store/logs.js +52 -2
- package/dist/store/logs.js.map +1 -1
- package/dist/store/plan.d.ts +57 -5
- package/dist/store/plan.js +182 -8
- package/dist/store/plan.js.map +1 -1
- package/dist/store/scope.d.ts +4 -1
- package/dist/store/scope.js +2 -2
- package/dist/store/scope.js.map +1 -1
- package/dist/tools/definitions.js +70 -1
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/elevated-shell.d.ts +60 -0
- package/dist/tools/elevated-shell.js +233 -0
- package/dist/tools/elevated-shell.js.map +1 -0
- package/dist/tools/file-diff.d.ts +125 -0
- package/dist/tools/file-diff.js +495 -0
- package/dist/tools/file-diff.js.map +1 -0
- package/dist/tools/fs.d.ts +11 -13
- package/dist/tools/fs.js +269 -78
- package/dist/tools/fs.js.map +1 -1
- package/dist/tools/http.d.ts +15 -0
- package/dist/tools/http.js +202 -61
- package/dist/tools/http.js.map +1 -1
- package/dist/tools/jobs.d.ts +71 -10
- package/dist/tools/jobs.js +403 -124
- package/dist/tools/jobs.js.map +1 -1
- package/dist/tools/nmap-runner.d.ts +11 -0
- package/dist/tools/nmap-runner.js +115 -74
- package/dist/tools/nmap-runner.js.map +1 -1
- package/dist/tools/pentest-workflows.d.ts +8 -0
- package/dist/tools/pentest-workflows.js +71 -0
- package/dist/tools/pentest-workflows.js.map +1 -0
- package/dist/tools/registry.d.ts +9 -0
- package/dist/tools/registry.js +227 -56
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/shell.d.ts +3 -0
- package/dist/tools/shell.js +35 -13
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/tool-types.d.ts +11 -0
- package/dist/tui-v2/app/App.js +25 -39
- package/dist/tui-v2/app/App.js.map +1 -1
- package/dist/tui-v2/app/command-handlers.js +20 -1
- package/dist/tui-v2/app/command-handlers.js.map +1 -1
- package/dist/tui-v2/app/commands/picker-commands.js +3 -0
- package/dist/tui-v2/app/commands/picker-commands.js.map +1 -1
- package/dist/tui-v2/app/commands/session-commands.js +5 -0
- package/dist/tui-v2/app/commands/session-commands.js.map +1 -1
- package/dist/tui-v2/app/plan-lifecycle.d.ts +25 -3
- package/dist/tui-v2/app/plan-lifecycle.js +87 -24
- package/dist/tui-v2/app/plan-lifecycle.js.map +1 -1
- package/dist/tui-v2/bootstrap/patch-opentui-text.d.ts +6 -0
- package/dist/tui-v2/bootstrap/patch-opentui-text.js +53 -0
- package/dist/tui-v2/bootstrap/patch-opentui-text.js.map +1 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js +7 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
- package/dist/tui-v2/components/jobs/jobs-panel.js +23 -14
- package/dist/tui-v2/components/jobs/jobs-panel.js.map +1 -1
- package/dist/tui-v2/components/modal/confirm-modal.d.ts +1 -1
- package/dist/tui-v2/components/modal/confirm-modal.js +18 -7
- package/dist/tui-v2/components/modal/confirm-modal.js.map +1 -1
- package/dist/tui-v2/components/overlay/overlay-host.js +1 -1
- package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
- package/dist/tui-v2/components/pager/pager.d.ts +6 -0
- package/dist/tui-v2/components/pager/pager.js +313 -67
- package/dist/tui-v2/components/pager/pager.js.map +1 -1
- package/dist/tui-v2/components/status/status-line.d.ts +9 -0
- package/dist/tui-v2/components/status/status-line.js +17 -3
- package/dist/tui-v2/components/status/status-line.js.map +1 -1
- package/dist/tui-v2/components/transcript/assistant-message.js +1 -1
- package/dist/tui-v2/components/transcript/assistant-message.js.map +1 -1
- package/dist/tui-v2/components/transcript/compacted-row.js +1 -1
- package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -1
- package/dist/tui-v2/components/transcript/tool-card.d.ts +9 -1
- package/dist/tui-v2/components/transcript/tool-card.js +114 -9
- package/dist/tui-v2/components/transcript/tool-card.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-row.js +2 -2
- package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
- package/dist/tui-v2/composer/composer-editor.js +16 -0
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/tui-v2/controllers/overlay-controller.d.ts +16 -2
- package/dist/tui-v2/controllers/overlay-controller.js +92 -12
- package/dist/tui-v2/controllers/overlay-controller.js.map +1 -1
- package/dist/tui-v2/rendering/artifact-pager-source.d.ts +19 -0
- package/dist/tui-v2/rendering/artifact-pager-source.js +103 -0
- package/dist/tui-v2/rendering/artifact-pager-source.js.map +1 -0
- package/dist/tui-v2/rendering/file-diff-view.d.ts +63 -0
- package/dist/tui-v2/rendering/file-diff-view.js +263 -0
- package/dist/tui-v2/rendering/file-diff-view.js.map +1 -0
- package/dist/tui-v2/rendering/open-tool-output.d.ts +9 -1
- package/dist/tui-v2/rendering/open-tool-output.js +65 -12
- package/dist/tui-v2/rendering/open-tool-output.js.map +1 -1
- package/dist/tui-v2/rendering/pager-chrome.d.ts +12 -0
- package/dist/tui-v2/rendering/pager-chrome.js +56 -0
- package/dist/tui-v2/rendering/pager-chrome.js.map +1 -0
- package/dist/tui-v2/rendering/plan-view.js +1 -1
- package/dist/tui-v2/rendering/plan-view.js.map +1 -1
- package/dist/tui-v2/rendering/syntax-highlight.d.ts +37 -0
- package/dist/tui-v2/rendering/syntax-highlight.js +1303 -0
- package/dist/tui-v2/rendering/syntax-highlight.js.map +1 -0
- package/dist/tui-v2/rendering/theme.d.ts +28 -0
- package/dist/tui-v2/rendering/theme.js +28 -0
- package/dist/tui-v2/rendering/theme.js.map +1 -1
- package/dist/tui-v2/rendering/tool-presenter.d.ts +5 -0
- package/dist/tui-v2/rendering/tool-presenter.js +35 -3
- package/dist/tui-v2/rendering/tool-presenter.js.map +1 -1
- package/dist/tui-v2/state/transcript-hydrate.js +5 -0
- package/dist/tui-v2/state/transcript-hydrate.js.map +1 -1
- package/dist/tui-v2/state/transcript-reducer.js +12 -2
- package/dist/tui-v2/state/transcript-reducer.js.map +1 -1
- package/dist/tui-v2/state/transcript-store.d.ts +7 -0
- package/dist/tui-v2/state/transcript-store.js +46 -0
- package/dist/tui-v2/state/transcript-store.js.map +1 -1
- package/dist/tui-v2/state/transcript-types.d.ts +12 -0
- package/dist/tui-v2/state/transcript-types.js +9 -0
- package/dist/tui-v2/state/transcript-types.js.map +1 -1
- package/dist/types.d.ts +17 -1
- package/dist/ui/mentions.d.ts +6 -0
- package/dist/ui/mentions.js +50 -12
- package/dist/ui/mentions.js.map +1 -1
- package/dist/ui/plan-pane.js +1 -1
- package/dist/ui/plan-pane.js.map +1 -1
- package/package.json +16 -11
|
@@ -5,11 +5,6 @@ export interface CommandHelpEntry {
|
|
|
5
5
|
readonly description: string;
|
|
6
6
|
readonly aliases: readonly string[];
|
|
7
7
|
}
|
|
8
|
-
/**
|
|
9
|
-
* One typed source of truth for slash commands. Registration is closed once
|
|
10
|
-
* seeded; handlers are attached by whichever frontend consumes the registry so
|
|
11
|
-
* UI-coupled handler bodies are not duplicated across legacy and v2.
|
|
12
|
-
*/
|
|
13
8
|
export declare class CommandRegistry {
|
|
14
9
|
private readonly byName;
|
|
15
10
|
private readonly aliasToName;
|
|
@@ -25,11 +20,6 @@ export declare class CommandRegistry {
|
|
|
25
20
|
help(): CommandHelpEntry[];
|
|
26
21
|
/** Parse a raw `/name args` line into a resolved invocation, or undefined. */
|
|
27
22
|
parse(line: string, context?: CommandContext): CommandInvocation | undefined;
|
|
28
|
-
/**
|
|
29
|
-
* True when a submitted line should be treated as a slash-command attempt
|
|
30
|
-
* (known name, unique prefix, or command-shaped word) rather than a prompt.
|
|
31
|
-
* Paths like `/Users/...` return false.
|
|
32
|
-
*/
|
|
33
23
|
looksLikeCommand(line: string): boolean;
|
|
34
24
|
/** Resolve + run the registered handler. Returns false if unknown/unhandled. */
|
|
35
25
|
dispatch(invocation: {
|
|
@@ -38,8 +28,4 @@ export declare class CommandRegistry {
|
|
|
38
28
|
context?: CommandContext | undefined;
|
|
39
29
|
}): Promise<boolean>;
|
|
40
30
|
}
|
|
41
|
-
/**
|
|
42
|
-
* Seed a registry from the shared legacy command catalogue so v2 and the
|
|
43
|
-
* classic REPL agree on the command set without a second hand-maintained list.
|
|
44
|
-
*/
|
|
45
31
|
export declare function buildDefaultCommandRegistry(): CommandRegistry;
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { slashCommands } from "../../repl/slash-commands.js";
|
|
2
2
|
import { normalizeCommandName, } from "./command.js";
|
|
3
|
-
/**
|
|
4
|
-
* Canonical command -> alias names. The legacy catalogue lists aliases as
|
|
5
|
-
* separate rows ("alias for /X"); here they collapse onto one canonical
|
|
6
|
-
* command so menus, help, keybindings, and dispatch all derive from a single
|
|
7
|
-
* definition (CMD-002, FEATURE_PARITY "aliases point to the same handler").
|
|
8
|
-
*/
|
|
9
3
|
const ALIAS_GROUPS = {
|
|
10
4
|
provider: ["use"],
|
|
11
5
|
search: ["search-provider"],
|
|
@@ -13,11 +7,6 @@ const ALIAS_GROUPS = {
|
|
|
13
7
|
think: ["thinking"],
|
|
14
8
|
exit: ["quit"],
|
|
15
9
|
};
|
|
16
|
-
/**
|
|
17
|
-
* One typed source of truth for slash commands. Registration is closed once
|
|
18
|
-
* seeded; handlers are attached by whichever frontend consumes the registry so
|
|
19
|
-
* UI-coupled handler bodies are not duplicated across legacy and v2.
|
|
20
|
-
*/
|
|
21
10
|
export class CommandRegistry {
|
|
22
11
|
byName = new Map();
|
|
23
12
|
aliasToName = new Map();
|
|
@@ -102,11 +91,6 @@ export class CommandRegistry {
|
|
|
102
91
|
}
|
|
103
92
|
return undefined;
|
|
104
93
|
}
|
|
105
|
-
/**
|
|
106
|
-
* True when a submitted line should be treated as a slash-command attempt
|
|
107
|
-
* (known name, unique prefix, or command-shaped word) rather than a prompt.
|
|
108
|
-
* Paths like `/Users/...` return false.
|
|
109
|
-
*/
|
|
110
94
|
looksLikeCommand(line) {
|
|
111
95
|
if (!line.startsWith("/") || line.length < 2)
|
|
112
96
|
return false;
|
|
@@ -136,10 +120,6 @@ export class CommandRegistry {
|
|
|
136
120
|
return true;
|
|
137
121
|
}
|
|
138
122
|
}
|
|
139
|
-
/**
|
|
140
|
-
* Seed a registry from the shared legacy command catalogue so v2 and the
|
|
141
|
-
* classic REPL agree on the command set without a second hand-maintained list.
|
|
142
|
-
*/
|
|
143
123
|
export function buildDefaultCommandRegistry() {
|
|
144
124
|
const registry = new CommandRegistry();
|
|
145
125
|
const aliasNames = new Set();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/app/commands/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EACL,oBAAoB,GAKrB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/app/commands/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
export interface Disposable {
|
|
2
2
|
dispose(): void;
|
|
3
3
|
}
|
|
4
|
-
/**
|
|
5
|
-
* Owns a set of disposables and tears them down in reverse creation order
|
|
6
|
-
* (ARCHITECTURE.md lifecycle). Disposal is idempotent (REL-001): a second call
|
|
7
|
-
* is a no-op, and one throwing disposer does not prevent the rest from running.
|
|
8
|
-
*/
|
|
9
4
|
export declare class CompositeDisposable implements Disposable {
|
|
10
5
|
private readonly items;
|
|
11
6
|
private disposed;
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Owns a set of disposables and tears them down in reverse creation order
|
|
3
|
-
* (ARCHITECTURE.md lifecycle). Disposal is idempotent (REL-001): a second call
|
|
4
|
-
* is a no-op, and one throwing disposer does not prevent the rest from running.
|
|
5
|
-
*/
|
|
6
1
|
export class CompositeDisposable {
|
|
7
2
|
items = [];
|
|
8
3
|
disposed = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disposable.js","sourceRoot":"","sources":["../../../src/app/controllers/disposable.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"disposable.js","sourceRoot":"","sources":["../../../src/app/controllers/disposable.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,mBAAmB;IACb,KAAK,GAAiB,EAAE,CAAC;IAClC,QAAQ,GAAG,KAAK,CAAC;IAEzB,GAAG,CAAuB,IAAO;QAC/B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;YAC3B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACtB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { ToolResult } from "../../types.js";
|
|
2
2
|
import type { BackgroundJob, JobsPort } from "../ports/jobs-port.js";
|
|
3
3
|
import type { Disposable } from "./disposable.js";
|
|
4
|
-
/**
|
|
5
|
-
* Thin lifecycle wrapper over `JobsPort` (CORE-004). Jobs live in the core
|
|
6
|
-
* manager and survive UI rerenders; this controller only observes and commands.
|
|
7
|
-
*/
|
|
8
4
|
export declare class JobController implements Disposable {
|
|
9
5
|
private readonly jobs;
|
|
10
6
|
constructor(jobs: JobsPort);
|
|
@@ -12,7 +8,7 @@ export declare class JobController implements Disposable {
|
|
|
12
8
|
running(): BackgroundJob[];
|
|
13
9
|
get(id: string): BackgroundJob | undefined;
|
|
14
10
|
tail(id: string, bytes?: number): Promise<ToolResult>;
|
|
15
|
-
stop(id: string): ToolResult
|
|
11
|
+
stop(id: string): Promise<ToolResult>;
|
|
16
12
|
start(command: string, options?: {
|
|
17
13
|
cwd?: string | undefined;
|
|
18
14
|
name?: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-controller.js","sourceRoot":"","sources":["../../../src/app/controllers/job-controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"job-controller.js","sourceRoot":"","sources":["../../../src/app/controllers/job-controller.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,aAAa;IACK;IAA7B,YAA6B,IAAc;QAAd,SAAI,GAAJ,IAAI,CAAU;IAAG,CAAC;IAE/C,IAAI;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,EAAU,EAAE,KAAc;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,EAAU;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CACH,OAAe,EACf,OAAiE;QAEjE,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,OAAO;QACL,gEAAgE;IAClE,CAAC;CACF"}
|
|
@@ -3,23 +3,20 @@ import type { AnyAppEvent } from "../events/app-event.js";
|
|
|
3
3
|
import type { PersistencePort } from "../ports/persistence-port.js";
|
|
4
4
|
import type { Disposable } from "./disposable.js";
|
|
5
5
|
export type PlanListener = () => void;
|
|
6
|
-
/**
|
|
7
|
-
* Holds the one current plan entity and keeps it in sync with the event stream
|
|
8
|
-
* (PLAN-003: mutate the existing plan, never append duplicates). Approval and
|
|
9
|
-
* discard mutate persisted status through the persistence port. Observable so
|
|
10
|
-
* the UI can bind reactively without polling (PLAN-002).
|
|
11
|
-
*/
|
|
12
6
|
export declare class PlanController implements Disposable {
|
|
13
7
|
private readonly persistence;
|
|
14
8
|
private plan;
|
|
9
|
+
private loadGeneration;
|
|
10
|
+
private activeSessionId;
|
|
15
11
|
private readonly listeners;
|
|
16
12
|
constructor(persistence: PersistencePort);
|
|
17
13
|
current(): SessionPlan | undefined;
|
|
18
14
|
subscribe(listener: PlanListener): () => void;
|
|
19
15
|
observe(event: AnyAppEvent): void;
|
|
20
16
|
/**
|
|
21
|
-
* Load the plan for `sessionId` from disk into memory.
|
|
22
|
-
*
|
|
17
|
+
* Load the plan for `sessionId` from disk into memory. The previous session's
|
|
18
|
+
* projection is cleared synchronously, and a generation token prevents a
|
|
19
|
+
* slower old-session load from repopulating the controller after /new.
|
|
23
20
|
*/
|
|
24
21
|
load(sessionId: string): Promise<SessionPlan | undefined>;
|
|
25
22
|
/** Drop the in-memory plan without touching disk. */
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Holds the one current plan entity and keeps it in sync with the event stream
|
|
3
|
-
* (PLAN-003: mutate the existing plan, never append duplicates). Approval and
|
|
4
|
-
* discard mutate persisted status through the persistence port. Observable so
|
|
5
|
-
* the UI can bind reactively without polling (PLAN-002).
|
|
6
|
-
*/
|
|
7
1
|
export class PlanController {
|
|
8
2
|
persistence;
|
|
9
3
|
plan;
|
|
4
|
+
loadGeneration = 0;
|
|
5
|
+
activeSessionId;
|
|
10
6
|
listeners = new Set();
|
|
11
7
|
constructor(persistence) {
|
|
12
8
|
this.persistence = persistence;
|
|
@@ -20,29 +16,48 @@ export class PlanController {
|
|
|
20
16
|
}
|
|
21
17
|
observe(event) {
|
|
22
18
|
if (event.type === "plan-updated") {
|
|
19
|
+
const eventSessionId = event.payload.plan.sessionId;
|
|
20
|
+
if (this.activeSessionId && eventSessionId !== this.activeSessionId) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
this.activeSessionId ??= eventSessionId;
|
|
24
|
+
// A live event is newer than any in-flight disk projection.
|
|
25
|
+
this.loadGeneration += 1;
|
|
23
26
|
this.plan = event.payload.plan;
|
|
24
27
|
this.notify();
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
/**
|
|
28
|
-
* Load the plan for `sessionId` from disk into memory.
|
|
29
|
-
*
|
|
31
|
+
* Load the plan for `sessionId` from disk into memory. The previous session's
|
|
32
|
+
* projection is cleared synchronously, and a generation token prevents a
|
|
33
|
+
* slower old-session load from repopulating the controller after /new.
|
|
30
34
|
*/
|
|
31
35
|
async load(sessionId) {
|
|
32
|
-
this.
|
|
36
|
+
this.activeSessionId = sessionId;
|
|
37
|
+
const generation = ++this.loadGeneration;
|
|
38
|
+
this.plan = undefined;
|
|
39
|
+
this.notify();
|
|
40
|
+
const loaded = await this.persistence.loadPlan(sessionId);
|
|
41
|
+
if (generation !== this.loadGeneration)
|
|
42
|
+
return this.plan;
|
|
43
|
+
this.plan = loaded;
|
|
33
44
|
this.notify();
|
|
34
45
|
return this.plan;
|
|
35
46
|
}
|
|
36
47
|
/** Drop the in-memory plan without touching disk. */
|
|
37
48
|
clear() {
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
// Always invalidate pending loads, even when the visible projection is
|
|
50
|
+
// already empty (a late promise must not resurrect it).
|
|
51
|
+
this.loadGeneration += 1;
|
|
52
|
+
const changed = this.plan !== undefined;
|
|
40
53
|
this.plan = undefined;
|
|
41
|
-
|
|
54
|
+
if (changed)
|
|
55
|
+
this.notify();
|
|
42
56
|
}
|
|
43
57
|
async approve() {
|
|
44
58
|
if (!this.plan)
|
|
45
59
|
return undefined;
|
|
60
|
+
this.loadGeneration += 1;
|
|
46
61
|
const next = { ...this.plan, status: "approved" };
|
|
47
62
|
this.plan = next;
|
|
48
63
|
await this.persistence.savePlan(next);
|
|
@@ -52,12 +67,15 @@ export class PlanController {
|
|
|
52
67
|
async discard() {
|
|
53
68
|
if (!this.plan)
|
|
54
69
|
return;
|
|
70
|
+
this.loadGeneration += 1;
|
|
55
71
|
const { sessionId } = this.plan;
|
|
56
72
|
this.plan = undefined;
|
|
57
73
|
await this.persistence.deletePlan(sessionId);
|
|
58
74
|
this.notify();
|
|
59
75
|
}
|
|
60
76
|
dispose() {
|
|
77
|
+
this.loadGeneration += 1;
|
|
78
|
+
this.activeSessionId = undefined;
|
|
61
79
|
this.plan = undefined;
|
|
62
80
|
this.listeners.clear();
|
|
63
81
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-controller.js","sourceRoot":"","sources":["../../../src/app/controllers/plan-controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plan-controller.js","sourceRoot":"","sources":["../../../src/app/controllers/plan-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,22 +37,10 @@ export interface SessionControllerDeps {
|
|
|
37
37
|
readonly idFactory?: IdFactory | undefined;
|
|
38
38
|
readonly clock?: Clock | undefined;
|
|
39
39
|
readonly mintTurnId?: (() => TurnId) | undefined;
|
|
40
|
-
/**
|
|
41
|
-
* Optional snapshot of the visual transcript for history.db (classic shape).
|
|
42
|
-
* When provided, completed turns upsert session + transcript so /history
|
|
43
|
-
* can restore tools and prompts, not only ChatMessage[].
|
|
44
|
-
*/
|
|
45
40
|
readonly getTranscriptSnapshot?: (() => ClassicTranscriptItem[] | undefined) | undefined;
|
|
46
41
|
/** When true, never persist sessions or generate AI titles (CLI --no-history). */
|
|
47
42
|
readonly noHistory?: boolean | undefined;
|
|
48
43
|
}
|
|
49
|
-
/**
|
|
50
|
-
* Owns session-level state (mode, provider/model, cumulative history, queued
|
|
51
|
-
* drafts) and runs turns through a single `TurnController`. Cumulative history
|
|
52
|
-
* follows the current runner contract: `onMessages` hands back the full
|
|
53
|
-
* conversation for the turn (prior context + this turn), which replaces the
|
|
54
|
-
* stored history and is persisted on completion.
|
|
55
|
-
*/
|
|
56
44
|
export type TurnEndListener = (result: TurnResult) => void;
|
|
57
45
|
export type SessionStateListener = () => void;
|
|
58
46
|
export declare class SessionController implements Disposable {
|
|
@@ -72,6 +60,12 @@ export declare class SessionController implements Disposable {
|
|
|
72
60
|
* settles, {@link continueQueue} runs this before any remaining queue items.
|
|
73
61
|
*/
|
|
74
62
|
private priorityPrompt;
|
|
63
|
+
/**
|
|
64
|
+
* Display override for the next turn only (`null` = hide YOU bubble).
|
|
65
|
+
* Used when implement/revision directives are queued while a turn is running.
|
|
66
|
+
*/
|
|
67
|
+
private nextTurnDisplayPrompt;
|
|
68
|
+
private nextTurnDisplayArmed;
|
|
75
69
|
/** Re-entrancy guard for {@link continueQueue}. */
|
|
76
70
|
private continuingQueue;
|
|
77
71
|
private provider;
|
|
@@ -115,46 +109,37 @@ export declare class SessionController implements Disposable {
|
|
|
115
109
|
compact(sessionTranscript?: string, keepRecent?: number, signal?: AbortSignal): Promise<CompactResult>;
|
|
116
110
|
/** Persist current messages (+ optional visual transcript) under this session id. */
|
|
117
111
|
persistNow(name?: string): Promise<void>;
|
|
118
|
-
/**
|
|
119
|
-
* Ask the model for a short conversation title and upsert it into history.
|
|
120
|
-
* Cadence matches classic TUI: first completed exchange, then every +2 user
|
|
121
|
-
* turns so the name tracks the evolving topic.
|
|
122
|
-
*/
|
|
123
112
|
maybeRefreshTitle(): Promise<void>;
|
|
124
113
|
estimateContext(): {
|
|
125
114
|
messages: number;
|
|
126
115
|
tokens: number;
|
|
127
116
|
};
|
|
128
|
-
enqueue(prompt: string): void;
|
|
129
|
-
queued(): readonly string[];
|
|
130
|
-
removeQueued(index: number): void;
|
|
131
117
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
118
|
+
* Queue a prompt while a turn is running. Optional displayPrompt is applied
|
|
119
|
+
* to the next dequeued turn (null hides the YOU bubble).
|
|
134
120
|
*/
|
|
121
|
+
enqueue(prompt: string, opts?: {
|
|
122
|
+
displayPrompt?: string | null | undefined;
|
|
123
|
+
}): void;
|
|
124
|
+
queued(): readonly string[];
|
|
125
|
+
removeQueued(index: number): void;
|
|
135
126
|
takeQueued(index: number): string | undefined;
|
|
136
127
|
/** Edit a queued draft in place before it runs (INPUT-007). */
|
|
137
128
|
editQueued(index: number, text: string): void;
|
|
138
129
|
/** Move a queued draft to a new position before it runs (INPUT-007). */
|
|
139
130
|
reorderQueued(fromIndex: number, toIndex: number): void;
|
|
140
|
-
/**
|
|
141
|
-
* Send a queued prompt immediately. If a turn is running, abort it first;
|
|
142
|
-
* the chosen prompt runs next (ahead of any remaining queue). If idle,
|
|
143
|
-
* submit it now.
|
|
144
|
-
*/
|
|
145
131
|
sendQueuedNow(index: number): void;
|
|
146
132
|
abort(): void;
|
|
147
|
-
/**
|
|
148
|
-
* After a turn settles, run any "send now" priority prompt, then drain the
|
|
149
|
-
* queue one-by-one. Safe to call from onTurnEnd (re-entrancy guarded).
|
|
150
|
-
*/
|
|
151
133
|
continueQueue(): Promise<void>;
|
|
134
|
+
private consumeNextTurnDisplay;
|
|
152
135
|
/** In-memory plan-approval flag consumed by the agent gate (CORE-005). */
|
|
153
136
|
setPlanApproved(value: boolean): void;
|
|
154
137
|
isPlanApproved(): boolean;
|
|
155
138
|
/** Fires after every turn settles (completed/aborted/error), including drain. */
|
|
156
139
|
onTurnEnd(listener: TurnEndListener): () => void;
|
|
157
|
-
submit(prompt: string
|
|
140
|
+
submit(prompt: string, opts?: {
|
|
141
|
+
displayPrompt?: string | null | undefined;
|
|
142
|
+
}): Promise<TurnResult>;
|
|
158
143
|
/**
|
|
159
144
|
* Runs queued prompts one at a time while idle; stops on first
|
|
160
145
|
* non-completion. Prefer {@link continueQueue} from the UI so priority
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { compactMessagesWithSummary, estimateMessagesTokens, } from "../../agent/context-manager.js";
|
|
2
2
|
import { createSessionPolicy } from "../../agent/session-policy.js";
|
|
3
|
+
import { resolveTurnInput } from "../../attachments/service.js";
|
|
3
4
|
import { generateSessionTitle } from "../../agent/session-title.js";
|
|
4
5
|
import { completeWithProvider } from "../../llm/router.js";
|
|
5
6
|
import { clearTextOnlyModels } from "../../llm/tool-protocol.js";
|
|
@@ -29,6 +30,12 @@ export class SessionController {
|
|
|
29
30
|
* settles, {@link continueQueue} runs this before any remaining queue items.
|
|
30
31
|
*/
|
|
31
32
|
priorityPrompt;
|
|
33
|
+
/**
|
|
34
|
+
* Display override for the next turn only (`null` = hide YOU bubble).
|
|
35
|
+
* Used when implement/revision directives are queued while a turn is running.
|
|
36
|
+
*/
|
|
37
|
+
nextTurnDisplayPrompt = undefined;
|
|
38
|
+
nextTurnDisplayArmed = false;
|
|
32
39
|
/** Re-entrancy guard for {@link continueQueue}. */
|
|
33
40
|
continuingQueue = false;
|
|
34
41
|
provider;
|
|
@@ -157,15 +164,9 @@ export class SessionController {
|
|
|
157
164
|
throw new Error("a turn is already running");
|
|
158
165
|
if (this.compactingFlag)
|
|
159
166
|
throw new Error("compaction already in progress");
|
|
160
|
-
// Fall back to config defaults so /compact works even before a turn sets
|
|
161
|
-
// the live provider/model on the session controller — including right after
|
|
162
|
-
// /history resume when no turn has run yet in this process.
|
|
163
167
|
const cfg = getConfig();
|
|
164
168
|
const provider = this.provider ?? cfg.defaultProvider;
|
|
165
169
|
const model = this.model ?? cfg.defaultModel;
|
|
166
|
-
// Snapshot history at start: includes /history resume + any new turns.
|
|
167
|
-
// compactMessagesWithSummary keeps the recent tail and summarizes the rest
|
|
168
|
-
// together with the visual session transcript (when provided).
|
|
169
170
|
const historySnapshot = [...this.history];
|
|
170
171
|
this.compactingFlag = true;
|
|
171
172
|
this.notifyState();
|
|
@@ -238,11 +239,6 @@ export class SessionController {
|
|
|
238
239
|
transcript,
|
|
239
240
|
});
|
|
240
241
|
}
|
|
241
|
-
/**
|
|
242
|
-
* Ask the model for a short conversation title and upsert it into history.
|
|
243
|
-
* Cadence matches classic TUI: first completed exchange, then every +2 user
|
|
244
|
-
* turns so the name tracks the evolving topic.
|
|
245
|
-
*/
|
|
246
242
|
async maybeRefreshTitle() {
|
|
247
243
|
if (this.deps.noHistory || getConfig().privateMode)
|
|
248
244
|
return;
|
|
@@ -290,7 +286,15 @@ export class SessionController {
|
|
|
290
286
|
tokens: estimateMessagesTokens(this.history),
|
|
291
287
|
};
|
|
292
288
|
}
|
|
293
|
-
|
|
289
|
+
/**
|
|
290
|
+
* Queue a prompt while a turn is running. Optional displayPrompt is applied
|
|
291
|
+
* to the next dequeued turn (null hides the YOU bubble).
|
|
292
|
+
*/
|
|
293
|
+
enqueue(prompt, opts) {
|
|
294
|
+
if (opts && "displayPrompt" in opts) {
|
|
295
|
+
this.nextTurnDisplayPrompt = opts.displayPrompt;
|
|
296
|
+
this.nextTurnDisplayArmed = true;
|
|
297
|
+
}
|
|
294
298
|
const text = prompt.trim();
|
|
295
299
|
if (!text)
|
|
296
300
|
return;
|
|
@@ -306,10 +310,6 @@ export class SessionController {
|
|
|
306
310
|
this.notifyState();
|
|
307
311
|
}
|
|
308
312
|
}
|
|
309
|
-
/**
|
|
310
|
-
* Remove a queued draft and return its text (for "Edit" → composer).
|
|
311
|
-
* Returns undefined when the index is out of range.
|
|
312
|
-
*/
|
|
313
313
|
takeQueued(index) {
|
|
314
314
|
if (index < 0 || index >= this.queue.length)
|
|
315
315
|
return undefined;
|
|
@@ -338,11 +338,6 @@ export class SessionController {
|
|
|
338
338
|
this.queue.splice(toIndex, 0, moved);
|
|
339
339
|
this.notifyState();
|
|
340
340
|
}
|
|
341
|
-
/**
|
|
342
|
-
* Send a queued prompt immediately. If a turn is running, abort it first;
|
|
343
|
-
* the chosen prompt runs next (ahead of any remaining queue). If idle,
|
|
344
|
-
* submit it now.
|
|
345
|
-
*/
|
|
346
341
|
sendQueuedNow(index) {
|
|
347
342
|
const text = this.takeQueued(index);
|
|
348
343
|
if (text === undefined)
|
|
@@ -358,10 +353,6 @@ export class SessionController {
|
|
|
358
353
|
abort() {
|
|
359
354
|
this.turn.abort();
|
|
360
355
|
}
|
|
361
|
-
/**
|
|
362
|
-
* After a turn settles, run any "send now" priority prompt, then drain the
|
|
363
|
-
* queue one-by-one. Safe to call from onTurnEnd (re-entrancy guarded).
|
|
364
|
-
*/
|
|
365
356
|
async continueQueue() {
|
|
366
357
|
if (this.continuingQueue || this.turn.running)
|
|
367
358
|
return;
|
|
@@ -382,13 +373,22 @@ export class SessionController {
|
|
|
382
373
|
}
|
|
383
374
|
if (next === undefined || !next.trim())
|
|
384
375
|
continue;
|
|
385
|
-
|
|
376
|
+
const displayOpts = this.consumeNextTurnDisplay();
|
|
377
|
+
await this.runTurn(next, displayOpts);
|
|
386
378
|
}
|
|
387
379
|
}
|
|
388
380
|
finally {
|
|
389
381
|
this.continuingQueue = false;
|
|
390
382
|
}
|
|
391
383
|
}
|
|
384
|
+
consumeNextTurnDisplay() {
|
|
385
|
+
if (!this.nextTurnDisplayArmed)
|
|
386
|
+
return undefined;
|
|
387
|
+
this.nextTurnDisplayArmed = false;
|
|
388
|
+
const displayPrompt = this.nextTurnDisplayPrompt;
|
|
389
|
+
this.nextTurnDisplayPrompt = undefined;
|
|
390
|
+
return { displayPrompt };
|
|
391
|
+
}
|
|
392
392
|
/** In-memory plan-approval flag consumed by the agent gate (CORE-005). */
|
|
393
393
|
setPlanApproved(value) {
|
|
394
394
|
this.policy.planApproved.value = value;
|
|
@@ -401,11 +401,18 @@ export class SessionController {
|
|
|
401
401
|
this.turnEndListeners.add(listener);
|
|
402
402
|
return () => this.turnEndListeners.delete(listener);
|
|
403
403
|
}
|
|
404
|
-
async submit(prompt) {
|
|
404
|
+
async submit(prompt, opts) {
|
|
405
405
|
if (this.turn.running) {
|
|
406
406
|
throw new Error("a turn is already running; enqueue() while busy");
|
|
407
407
|
}
|
|
408
|
-
|
|
408
|
+
// Explicit submit opts win over any armed queue display override.
|
|
409
|
+
if (opts && "displayPrompt" in opts) {
|
|
410
|
+
this.nextTurnDisplayArmed = false;
|
|
411
|
+
this.nextTurnDisplayPrompt = undefined;
|
|
412
|
+
return this.runTurn(prompt, opts);
|
|
413
|
+
}
|
|
414
|
+
const displayOpts = this.consumeNextTurnDisplay();
|
|
415
|
+
return this.runTurn(prompt, displayOpts ?? opts);
|
|
409
416
|
}
|
|
410
417
|
/**
|
|
411
418
|
* Runs queued prompts one at a time while idle; stops on first
|
|
@@ -426,12 +433,29 @@ export class SessionController {
|
|
|
426
433
|
}
|
|
427
434
|
return results;
|
|
428
435
|
}
|
|
429
|
-
async runTurn(prompt) {
|
|
430
|
-
const
|
|
436
|
+
async runTurn(prompt, opts) {
|
|
437
|
+
const config = getConfig();
|
|
438
|
+
const provider = this.provider ?? config.defaultProvider;
|
|
439
|
+
const model = this.model ?? getProviderModel(provider);
|
|
440
|
+
const resolved = resolveTurnInput({
|
|
431
441
|
prompt,
|
|
432
|
-
|
|
433
|
-
|
|
442
|
+
mode: this.mode,
|
|
443
|
+
provider,
|
|
444
|
+
model,
|
|
445
|
+
});
|
|
446
|
+
if (resolved.fallbackReason)
|
|
447
|
+
this.notice("info", resolved.fallbackReason);
|
|
448
|
+
const request = {
|
|
449
|
+
prompt: resolved.prompt,
|
|
450
|
+
mode: resolved.mode,
|
|
451
|
+
provider: resolved.provider,
|
|
452
|
+
model: resolved.model,
|
|
434
453
|
history: this.history,
|
|
454
|
+
attachments: resolved.attachments,
|
|
455
|
+
images: resolved.images,
|
|
456
|
+
...(opts?.displayPrompt !== undefined
|
|
457
|
+
? { displayPrompt: opts.displayPrompt }
|
|
458
|
+
: {}),
|
|
435
459
|
};
|
|
436
460
|
const pending = this.turn.run(request, {
|
|
437
461
|
confirm: this.deps.confirm,
|
|
@@ -442,9 +466,6 @@ export class SessionController {
|
|
|
442
466
|
this.notifyState();
|
|
443
467
|
},
|
|
444
468
|
});
|
|
445
|
-
// `TurnController.run` marks itself active synchronously before its first
|
|
446
|
-
// await, so this makes the RUNNING strip appear even before a provider
|
|
447
|
-
// emits its first status event.
|
|
448
469
|
this.notifyState();
|
|
449
470
|
const result = await pending;
|
|
450
471
|
if (result.status === "completed") {
|