@oh-my-pi/pi-coding-agent 16.4.6 → 16.5.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 +88 -0
- package/dist/cli.js +3312 -3254
- package/dist/types/cli/args.d.ts +5 -0
- package/dist/types/cli/gallery-fixtures/shell.d.ts +1 -1
- package/dist/types/commands/launch.d.ts +15 -0
- package/dist/types/config/model-resolver.d.ts +4 -3
- package/dist/types/config/model-roles.d.ts +8 -0
- package/dist/types/config/settings-schema.d.ts +46 -14
- package/dist/types/extensibility/extensions/types.d.ts +1 -1
- package/dist/types/launch/broker.d.ts +2 -0
- package/dist/types/launch/client.d.ts +22 -0
- package/dist/types/launch/paths.d.ts +4 -0
- package/dist/types/launch/presence.d.ts +8 -0
- package/dist/types/launch/protocol.d.ts +170 -0
- package/dist/types/launch/terminal-output.d.ts +7 -0
- package/dist/types/modes/components/agent-hub.d.ts +1 -1
- package/dist/types/modes/components/index.d.ts +1 -0
- package/dist/types/modes/components/model-browser.d.ts +28 -3
- package/dist/types/modes/components/model-hub.d.ts +0 -10
- package/dist/types/modes/components/model-picker.d.ts +44 -0
- package/dist/types/modes/components/plan-review-overlay.d.ts +2 -0
- package/dist/types/modes/components/status-line/types.d.ts +3 -0
- package/dist/types/modes/components/welcome.d.ts +4 -0
- package/dist/types/modes/print-mode.d.ts +14 -8
- package/dist/types/modes/print-mode.test.d.ts +1 -0
- package/dist/types/modes/theme/theme.d.ts +2 -1
- package/dist/types/sdk.d.ts +5 -1
- package/dist/types/session/agent-session.d.ts +42 -0
- package/dist/types/session/session-context.d.ts +9 -0
- package/dist/types/session/session-entries.d.ts +6 -0
- package/dist/types/thinking.d.ts +2 -2
- package/dist/types/tiny/models.d.ts +1 -1
- package/dist/types/tools/browser/launch.d.ts +1 -0
- package/dist/types/tools/browser/run-cancellation.d.ts +28 -2
- package/dist/types/tools/browser/tab-protocol.d.ts +6 -0
- package/dist/types/tools/browser/tab-worker.d.ts +6 -0
- package/dist/types/tools/builtin-names.d.ts +1 -1
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/launch.d.ts +121 -0
- package/dist/types/tools/render-utils.d.ts +2 -0
- package/dist/types/tools/terminal-output.d.ts +5 -0
- package/dist/types/vibe/runtime.d.ts +2 -2
- package/dist/types/web/search/types.d.ts +0 -8
- package/package.json +20 -20
- package/src/cli/args.ts +11 -0
- package/src/cli/flag-tables.ts +9 -0
- package/src/cli/gallery-fixtures/shell.ts +82 -1
- package/src/cli.ts +10 -0
- package/src/commands/launch.ts +17 -0
- package/src/config/model-resolver.ts +110 -31
- package/src/config/model-roles.ts +14 -0
- package/src/config/settings-schema.ts +71 -7
- package/src/edit/renderer.ts +13 -10
- package/src/eval/__tests__/agent-bridge.test.ts +2 -2
- package/src/eval/__tests__/completion-bridge.test.ts +1 -1
- package/src/eval/completion-bridge.ts +4 -4
- package/src/eval/js/shared/rewrite-imports.ts +31 -13
- package/src/export/ttsr.ts +0 -3
- package/src/extensibility/extensions/model-api.ts +1 -1
- package/src/extensibility/extensions/types.ts +1 -1
- package/src/internal-urls/docs-index.ts +4 -4
- package/src/launch/broker.ts +1017 -0
- package/src/launch/client.ts +344 -0
- package/src/launch/paths.ts +17 -0
- package/src/launch/presence.ts +82 -0
- package/src/launch/protocol.ts +386 -0
- package/src/launch/terminal-output.ts +46 -0
- package/src/main.ts +50 -1
- package/src/modes/acp/acp-agent.ts +8 -1
- package/src/modes/components/agent-hub.ts +101 -31
- package/src/modes/components/compaction-summary-message.ts +8 -2
- package/src/modes/components/index.ts +1 -0
- package/src/modes/components/model-browser.ts +152 -49
- package/src/modes/components/model-hub.ts +55 -142
- package/src/modes/components/model-picker.ts +233 -0
- package/src/modes/components/plan-review-overlay.ts +7 -0
- package/src/modes/components/snapcompact-shape-preview-doc.md +7 -11
- package/src/modes/components/status-line/component.test.ts +41 -2
- package/src/modes/components/status-line/component.ts +4 -0
- package/src/modes/components/status-line/segments.ts +6 -0
- package/src/modes/components/status-line/types.ts +3 -0
- package/src/modes/components/tips.txt +2 -1
- package/src/modes/components/welcome.ts +13 -14
- package/src/modes/controllers/command-controller.ts +9 -1
- package/src/modes/controllers/event-controller.ts +31 -32
- package/src/modes/controllers/selector-controller.ts +96 -22
- package/src/modes/controllers/tan-command-controller.ts +40 -1
- package/src/modes/interactive-mode.ts +20 -3
- package/src/modes/print-mode.test.ts +71 -0
- package/src/modes/print-mode.ts +51 -2
- package/src/modes/theme/theme.ts +9 -0
- package/src/modes/utils/ui-helpers.ts +25 -4
- package/src/prompts/agents/designer.md +1 -1
- package/src/prompts/agents/librarian.md +1 -1
- package/src/prompts/agents/reviewer.md +1 -1
- package/src/prompts/agents/scout.md +1 -1
- package/src/prompts/system/plan-yolo-handoff.md +5 -0
- package/src/prompts/system/prewalk-checklist.md +7 -0
- package/src/prompts/system/prewalk-continue.md +1 -0
- package/src/prompts/system/prewalk-plan.md +13 -0
- package/src/prompts/system/system-prompt.md +9 -7
- package/src/prompts/system/tan-context-switch.md +17 -0
- package/src/prompts/tools/bash.md +6 -4
- package/src/prompts/tools/browser.md +4 -4
- package/src/prompts/tools/launch.md +25 -0
- package/src/sdk.ts +8 -2
- package/src/session/agent-session.ts +550 -87
- package/src/session/session-context.test.ts +10 -5
- package/src/session/session-context.ts +25 -8
- package/src/session/session-entries.ts +6 -0
- package/src/slash-commands/builtin-registry.ts +25 -0
- package/src/task/agents.ts +2 -2
- package/src/thinking.ts +10 -3
- package/src/tiny/models.ts +7 -7
- package/src/tools/bash-interactive.ts +5 -8
- package/src/tools/bash.ts +38 -24
- package/src/tools/browser/cmux/cmux-tab.ts +17 -2
- package/src/tools/browser/launch.ts +8 -4
- package/src/tools/browser/run-cancellation.ts +66 -6
- package/src/tools/browser/tab-protocol.ts +6 -0
- package/src/tools/browser/tab-supervisor.ts +17 -1
- package/src/tools/browser/tab-worker.ts +140 -21
- package/src/tools/builtin-names.ts +1 -0
- package/src/tools/eval-render.ts +16 -14
- package/src/tools/index.ts +5 -0
- package/src/tools/inspect-image.ts +2 -2
- package/src/tools/launch.ts +643 -0
- package/src/tools/render-utils.ts +3 -0
- package/src/tools/renderers.ts +2 -0
- package/src/tools/terminal-output.ts +141 -0
- package/src/tts/speech-enhancer.ts +2 -2
- package/src/utils/image-vision-fallback.ts +3 -3
- package/src/vibe/runtime.ts +2 -2
- package/src/web/search/provider.ts +0 -10
- package/src/web/search/providers/perplexity.ts +18 -2
- package/src/web/search/providers/public.ts +2 -4
- package/src/web/search/types.ts +0 -10
- package/dist/types/web/search/providers/bing.d.ts +0 -14
- package/dist/types/web/search/providers/yahoo.d.ts +0 -14
- package/src/web/search/providers/bing.ts +0 -197
- package/src/web/search/providers/yahoo.ts +0 -179
|
@@ -120,6 +120,7 @@ import { formatPhaseDisplayName, todoMatchesAnyDescription } from "../tools/todo
|
|
|
120
120
|
import { ToolError } from "../tools/tool-errors";
|
|
121
121
|
import { vocalizer } from "../tts/vocalizer";
|
|
122
122
|
import { renderTreeList } from "../tui/tree-list";
|
|
123
|
+
import { copyToClipboard } from "../utils/clipboard";
|
|
123
124
|
import type { EventBus } from "../utils/event-bus";
|
|
124
125
|
import { getEditorCommand, openInEditor } from "../utils/external-editor";
|
|
125
126
|
import { getSessionAccentAnsi, getSessionAccentHex } from "../utils/session-color";
|
|
@@ -664,6 +665,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
664
665
|
setMarkdownMermaidRendering(settings.get("tui.renderMermaid"));
|
|
665
666
|
this.ui = new TUI(new ProcessTerminal(), settings.get("showHardwareCursor"));
|
|
666
667
|
this.ui.setMaxInlineImages(settings.get("tui.maxInlineImages"));
|
|
668
|
+
this.ui.setScrollbackRebuild(settings.get("tui.scrollbackRebuild"));
|
|
667
669
|
// OSC 66 text-sizing is Kitty-only; resolve the setting against the terminal's
|
|
668
670
|
// capability (`TERMINAL.textSizing` defaults on for Kitty) so it stays off
|
|
669
671
|
// unless the user opts in, and never emits raw escapes on other terminals.
|
|
@@ -1613,9 +1615,12 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1613
1615
|
}
|
|
1614
1616
|
}
|
|
1615
1617
|
this.chatContainer.clear();
|
|
1616
|
-
// Live display
|
|
1617
|
-
//
|
|
1618
|
-
|
|
1618
|
+
// Live display collapses to the compacted transcript tail unless the
|
|
1619
|
+
// user opted into the full inline history; export/resume callers choose
|
|
1620
|
+
// their own mode.
|
|
1621
|
+
const context = this.viewSession.buildTranscriptSessionContext({
|
|
1622
|
+
collapseCompactedHistory: settings.get("display.collapseCompacted"),
|
|
1623
|
+
});
|
|
1619
1624
|
this.renderSessionContext(context);
|
|
1620
1625
|
for (const child of liveComponents) {
|
|
1621
1626
|
this.chatContainer.addChild(child);
|
|
@@ -2517,6 +2522,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
2517
2522
|
{
|
|
2518
2523
|
onPick: choice => finish(choice),
|
|
2519
2524
|
onCancel: () => finish(undefined),
|
|
2525
|
+
onCopyPlan: content => void this.#copyPlanToClipboard(content),
|
|
2520
2526
|
onExternalEditor: dialogOptions?.onExternalEditor,
|
|
2521
2527
|
onAnnotationExternalEditor: (draft, commit) => void this.#openPlanAnnotationInExternalEditor(draft, commit),
|
|
2522
2528
|
onPlanEdited: dialogOptions?.onPlanEdited,
|
|
@@ -2583,6 +2589,17 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
2583
2589
|
return contextUsage !== undefined && contextUsage.percent > PLAN_KEEP_CONTEXT_DISABLE_THRESHOLD_PERCENT;
|
|
2584
2590
|
}
|
|
2585
2591
|
|
|
2592
|
+
async #copyPlanToClipboard(content: string): Promise<void> {
|
|
2593
|
+
try {
|
|
2594
|
+
await copyToClipboard(content);
|
|
2595
|
+
this.showStatus("Copied plan to clipboard");
|
|
2596
|
+
} catch (error) {
|
|
2597
|
+
this.showWarning(
|
|
2598
|
+
`Failed to copy plan to clipboard: ${error instanceof Error ? error.message : String(error)}`,
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2586
2603
|
async #openPlanInExternalEditor(planFilePath: string): Promise<void> {
|
|
2587
2604
|
const editorCmd = getEditorCommand();
|
|
2588
2605
|
if (!editorCmd) {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract: `--mode json` output stays linear in conversation size. Streaming
|
|
3
|
+
* `message_update` events must not re-serialize the in-progress message, and
|
|
4
|
+
* printed messages must not carry provider-opaque replay payloads (encrypted
|
|
5
|
+
* reasoning history), which previously produced multi-GB transcripts.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, expect, it } from "bun:test";
|
|
8
|
+
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
9
|
+
import type { AgentSessionEvent } from "../session/agent-session";
|
|
10
|
+
import { printableEvent } from "./print-mode";
|
|
11
|
+
|
|
12
|
+
const assistant: AssistantMessage = {
|
|
13
|
+
role: "assistant",
|
|
14
|
+
content: [{ type: "text", text: "hello" }],
|
|
15
|
+
api: "openai-responses",
|
|
16
|
+
provider: "openai",
|
|
17
|
+
model: "gpt-test",
|
|
18
|
+
usage: {} as AssistantMessage["usage"],
|
|
19
|
+
stopReason: "stop",
|
|
20
|
+
timestamp: 1,
|
|
21
|
+
providerPayload: { type: "openaiResponsesHistory", provider: "openai", dt: true, items: [{ big: "blob" }] },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
describe("printableEvent", () => {
|
|
25
|
+
it("emits only the incremental delta for message_update", () => {
|
|
26
|
+
const event: AgentSessionEvent = {
|
|
27
|
+
type: "message_update",
|
|
28
|
+
message: assistant,
|
|
29
|
+
assistantMessageEvent: { type: "text_delta", contentIndex: 0, delta: "hel", partial: assistant },
|
|
30
|
+
};
|
|
31
|
+
const printed = JSON.parse(JSON.stringify(printableEvent(event)));
|
|
32
|
+
expect(printed).toEqual({
|
|
33
|
+
type: "message_update",
|
|
34
|
+
assistantMessageEvent: { type: "text_delta", contentIndex: 0, delta: "hel" },
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("drops the done-variant message snapshot from message_update", () => {
|
|
39
|
+
const event: AgentSessionEvent = {
|
|
40
|
+
type: "message_update",
|
|
41
|
+
message: assistant,
|
|
42
|
+
assistantMessageEvent: { type: "done", reason: "stop", message: assistant },
|
|
43
|
+
};
|
|
44
|
+
const printed = JSON.parse(JSON.stringify(printableEvent(event)));
|
|
45
|
+
expect(printed).toEqual({ type: "message_update", assistantMessageEvent: { type: "done", reason: "stop" } });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("strips providerPayload from message_end but keeps the message content", () => {
|
|
49
|
+
const event: AgentSessionEvent = { type: "message_end", message: assistant };
|
|
50
|
+
const printed = JSON.parse(JSON.stringify(printableEvent(event))) as {
|
|
51
|
+
message: Record<string, unknown>;
|
|
52
|
+
};
|
|
53
|
+
expect(printed.message.providerPayload).toBeUndefined();
|
|
54
|
+
expect(printed.message.content).toEqual([{ type: "text", text: "hello" }]);
|
|
55
|
+
expect(printed.message.model).toBe("gpt-test");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("strips providerPayload from every message in agent_end", () => {
|
|
59
|
+
const event: AgentSessionEvent = { type: "agent_end", messages: [assistant, assistant] };
|
|
60
|
+
const printed = JSON.parse(JSON.stringify(printableEvent(event))) as {
|
|
61
|
+
messages: Array<Record<string, unknown>>;
|
|
62
|
+
};
|
|
63
|
+
expect(printed.messages).toHaveLength(2);
|
|
64
|
+
for (const message of printed.messages) expect(message.providerPayload).toBeUndefined();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("passes unrelated events through untouched", () => {
|
|
68
|
+
const event: AgentSessionEvent = { type: "notice", level: "info", message: "hi" };
|
|
69
|
+
expect(printableEvent(event)).toBe(event);
|
|
70
|
+
});
|
|
71
|
+
});
|
package/src/modes/print-mode.ts
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* - `omp -p "prompt"` - text output
|
|
6
6
|
* - `omp --mode json "prompt"` - JSON event stream
|
|
7
7
|
*/
|
|
8
|
+
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
8
9
|
import type { AssistantMessage, ImageContent } from "@oh-my-pi/pi-ai";
|
|
9
10
|
import { logger, sanitizeText } from "@oh-my-pi/pi-utils";
|
|
10
|
-
import type { AgentSession } from "../session/agent-session";
|
|
11
|
+
import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
|
|
11
12
|
import { isSilentAbort } from "../session/messages";
|
|
12
13
|
import { flushTelemetryExport } from "../telemetry-export";
|
|
13
14
|
import { initializeExtensions } from "./runtime-init";
|
|
@@ -28,6 +29,54 @@ export interface PrintModeOptions {
|
|
|
28
29
|
printThoughts?: boolean;
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
/** Drop the provider-opaque replay payload (e.g. encrypted reasoning items) before printing. */
|
|
33
|
+
function stripProviderPayload<T extends AgentMessage>(message: T): T {
|
|
34
|
+
if (!("providerPayload" in message) || message.providerPayload === undefined) return message;
|
|
35
|
+
const { providerPayload: _providerPayload, ...rest } = message;
|
|
36
|
+
return rest as T;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Shape an event for `--mode json` output.
|
|
41
|
+
*
|
|
42
|
+
* Removes two classes of bloat so transcripts grow linearly with conversation
|
|
43
|
+
* size instead of quadratically (a single long turn used to re-serialize its
|
|
44
|
+
* whole in-progress message on every streamed delta, producing multi-GB logs):
|
|
45
|
+
* - `message_update` snapshots (`message`, `assistantMessageEvent.partial`,
|
|
46
|
+
* and the `done`/`error` payloads) are dropped; only the incremental delta
|
|
47
|
+
* is printed. The authoritative message follows in `message_end`.
|
|
48
|
+
* - `providerPayload` is transport-native replay state, opaque and useless
|
|
49
|
+
* outside this process.
|
|
50
|
+
*/
|
|
51
|
+
export function printableEvent(event: AgentSessionEvent): unknown {
|
|
52
|
+
switch (event.type) {
|
|
53
|
+
case "message_update": {
|
|
54
|
+
const streamEvent = event.assistantMessageEvent;
|
|
55
|
+
if (streamEvent.type === "done" || streamEvent.type === "error") {
|
|
56
|
+
return {
|
|
57
|
+
type: "message_update",
|
|
58
|
+
assistantMessageEvent: { type: streamEvent.type, reason: streamEvent.reason },
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const { partial: _partial, ...rest } = streamEvent;
|
|
62
|
+
return { type: "message_update", assistantMessageEvent: rest };
|
|
63
|
+
}
|
|
64
|
+
case "message_start":
|
|
65
|
+
case "message_end":
|
|
66
|
+
return { ...event, message: stripProviderPayload(event.message) };
|
|
67
|
+
case "turn_end":
|
|
68
|
+
return {
|
|
69
|
+
...event,
|
|
70
|
+
message: stripProviderPayload(event.message),
|
|
71
|
+
toolResults: event.toolResults.map(stripProviderPayload),
|
|
72
|
+
};
|
|
73
|
+
case "agent_end":
|
|
74
|
+
return { ...event, messages: event.messages.map(stripProviderPayload) };
|
|
75
|
+
default:
|
|
76
|
+
return event;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
31
80
|
/**
|
|
32
81
|
* Run in print (single-shot) mode.
|
|
33
82
|
* Sends prompts to the agent and outputs the result.
|
|
@@ -58,7 +107,7 @@ export async function runPrintMode(session: AgentSession, options: PrintModeOpti
|
|
|
58
107
|
session.subscribe(event => {
|
|
59
108
|
// In JSON mode, output all events
|
|
60
109
|
if (mode === "json") {
|
|
61
|
-
process.stdout.write(`${JSON.stringify(event)}\n`);
|
|
110
|
+
process.stdout.write(`${JSON.stringify(printableEvent(event))}\n`);
|
|
62
111
|
}
|
|
63
112
|
});
|
|
64
113
|
|
package/src/modes/theme/theme.ts
CHANGED
|
@@ -92,6 +92,7 @@ export type SymbolKey =
|
|
|
92
92
|
// Icons
|
|
93
93
|
| "icon.model"
|
|
94
94
|
| "icon.plan"
|
|
95
|
+
| "icon.prewalk"
|
|
95
96
|
| "icon.goal"
|
|
96
97
|
| "icon.pause"
|
|
97
98
|
| "icon.loop"
|
|
@@ -225,6 +226,7 @@ export type SymbolKey =
|
|
|
225
226
|
| "tool.debug"
|
|
226
227
|
| "tool.mcp"
|
|
227
228
|
| "tool.job"
|
|
229
|
+
| "tool.launch"
|
|
228
230
|
| "tool.task"
|
|
229
231
|
| "tool.todo"
|
|
230
232
|
| "tool.memory"
|
|
@@ -300,6 +302,7 @@ const UNICODE_SYMBOLS: SymbolMap = {
|
|
|
300
302
|
// Icons
|
|
301
303
|
"icon.model": "⬢",
|
|
302
304
|
"icon.plan": "🗺",
|
|
305
|
+
"icon.prewalk": "🏃",
|
|
303
306
|
"icon.goal": "🎯",
|
|
304
307
|
"icon.pause": "⏸",
|
|
305
308
|
"icon.loop": "↻",
|
|
@@ -433,6 +436,7 @@ const UNICODE_SYMBOLS: SymbolMap = {
|
|
|
433
436
|
"tool.debug": "🐞",
|
|
434
437
|
"tool.mcp": "🔌",
|
|
435
438
|
"tool.job": "⚙",
|
|
439
|
+
"tool.launch": "🚀",
|
|
436
440
|
"tool.task": "⇶",
|
|
437
441
|
"tool.todo": "☑",
|
|
438
442
|
"tool.memory": "🧠",
|
|
@@ -560,6 +564,7 @@ const NERD_SYMBOLS: SymbolMap = {
|
|
|
560
564
|
"icon.model": "\uec19",
|
|
561
565
|
// pick: | alt:
|
|
562
566
|
"icon.plan": "\uf2d2",
|
|
567
|
+
"icon.prewalk": "\uf29d",
|
|
563
568
|
// pick: (nf-fa-bullseye) | alt: (nf-md-target) ◎ ⌖
|
|
564
569
|
"icon.goal": "\uf140",
|
|
565
570
|
// pick: (nf-fa-pause) | alt: ⏸ ||
|
|
@@ -742,6 +747,7 @@ const NERD_SYMBOLS: SymbolMap = {
|
|
|
742
747
|
"tool.debug": "\uEAD8",
|
|
743
748
|
"tool.mcp": "\uEB2D",
|
|
744
749
|
"tool.job": "\uEBA2",
|
|
750
|
+
"tool.launch": "\uF135",
|
|
745
751
|
"tool.task": "\uf4a0",
|
|
746
752
|
"tool.todo": "\uEAB3",
|
|
747
753
|
"tool.memory": "\uEACE",
|
|
@@ -816,6 +822,7 @@ const ASCII_SYMBOLS: SymbolMap = {
|
|
|
816
822
|
// Icons
|
|
817
823
|
"icon.model": "[M]",
|
|
818
824
|
"icon.plan": "plan",
|
|
825
|
+
"icon.prewalk": "prewalk",
|
|
819
826
|
"icon.goal": "goal",
|
|
820
827
|
"icon.pause": "||",
|
|
821
828
|
"icon.loop": "loop",
|
|
@@ -946,6 +953,7 @@ const ASCII_SYMBOLS: SymbolMap = {
|
|
|
946
953
|
"tool.debug": "dbg",
|
|
947
954
|
"tool.mcp": "<>",
|
|
948
955
|
"tool.job": "job",
|
|
956
|
+
"tool.launch": "run",
|
|
949
957
|
"tool.task": ">>>",
|
|
950
958
|
"tool.todo": "[x]",
|
|
951
959
|
"tool.memory": "mem",
|
|
@@ -1815,6 +1823,7 @@ export class Theme {
|
|
|
1815
1823
|
return {
|
|
1816
1824
|
model: this.#symbols["icon.model"],
|
|
1817
1825
|
plan: this.#symbols["icon.plan"],
|
|
1826
|
+
prewalk: this.#symbols["icon.prewalk"],
|
|
1818
1827
|
goal: this.#symbols["icon.goal"],
|
|
1819
1828
|
pause: this.#symbols["icon.pause"],
|
|
1820
1829
|
loop: this.#symbols["icon.loop"],
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
SKILL_PROMPT_MESSAGE_TYPE,
|
|
46
46
|
type SkillPromptDetails,
|
|
47
47
|
} from "../../session/messages";
|
|
48
|
-
import type { SessionContext } from "../../session/session-context";
|
|
48
|
+
import type { SessionContext, StrippedToolCallsMarker } from "../../session/session-context";
|
|
49
49
|
import { replaceTabs } from "../../tools/render-utils";
|
|
50
50
|
import { buildSkillCommandPrompt, invokeSkillCommandFromText, isKnownSkillCommand } from "../skill-command";
|
|
51
51
|
import { createAssistantMessageComponent } from "./interactive-context-helpers";
|
|
@@ -465,6 +465,26 @@ export class UiHelpers {
|
|
|
465
465
|
this.ctx.pendingTools.set(content.id, component);
|
|
466
466
|
}
|
|
467
467
|
}
|
|
468
|
+
// Dangling toolCalls (no result on the resolved path — failed or
|
|
469
|
+
// retried turns, results on sibling branches) were stripped by the
|
|
470
|
+
// context build; surface a placeholder so the turn's activity is
|
|
471
|
+
// visibly elided instead of silently vanishing (the "bare thinking
|
|
472
|
+
// lines" transcript trap).
|
|
473
|
+
const strippedToolCalls = (message as AgentMessage & StrippedToolCallsMarker).strippedToolCalls ?? 0;
|
|
474
|
+
if (strippedToolCalls > 0) {
|
|
475
|
+
this.ctx.chatContainer.addChild(
|
|
476
|
+
new Text(
|
|
477
|
+
theme.fg(
|
|
478
|
+
"dim",
|
|
479
|
+
theme.italic(
|
|
480
|
+
`${strippedToolCalls} tool call${strippedToolCalls === 1 ? "" : "s"} elided — no result on this branch`,
|
|
481
|
+
),
|
|
482
|
+
),
|
|
483
|
+
1,
|
|
484
|
+
0,
|
|
485
|
+
),
|
|
486
|
+
);
|
|
487
|
+
}
|
|
468
488
|
pendingUsage =
|
|
469
489
|
this.ctx.settings.get("display.showTokenUsage") && assistantUsageIsBilled(message.usage)
|
|
470
490
|
? message.usage
|
|
@@ -607,13 +627,14 @@ export class UiHelpers {
|
|
|
607
627
|
this.ctx.pendingBashComponents = [];
|
|
608
628
|
this.ctx.pendingPythonComponents = [];
|
|
609
629
|
|
|
610
|
-
// Live display
|
|
611
|
-
//
|
|
630
|
+
// Live display collapses to the compacted transcript tail unless the
|
|
631
|
+
// user opted into the full inline history; export/resume callers can
|
|
632
|
+
// still request either mode. Mid-turn rebuilds
|
|
612
633
|
// (focus attach/unfocus while a tool executes) keep dangling toolCalls so
|
|
613
634
|
// the in-flight call re-renders as pending instead of vanishing;
|
|
614
635
|
// renderSessionContext then keeps it in `pendingTools` for live routing.
|
|
615
636
|
const context = this.ctx.viewSession.buildTranscriptSessionContext({
|
|
616
|
-
collapseCompactedHistory:
|
|
637
|
+
collapseCompactedHistory: settings.get("display.collapseCompacted"),
|
|
617
638
|
keepDanglingToolCalls: this.ctx.viewSession.isStreaming,
|
|
618
639
|
});
|
|
619
640
|
this.ctx.renderSessionContext(context, {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: librarian
|
|
3
3
|
description: Researches external libraries and APIs by reading source code. Returns definitive, source-verified answers.
|
|
4
4
|
tools: read, grep, glob, bash, lsp, web_search, ast_grep
|
|
5
|
-
model:
|
|
5
|
+
model: "@smol"
|
|
6
6
|
thinking-level: minimal
|
|
7
7
|
read-summarize: false
|
|
8
8
|
output:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: scout
|
|
3
3
|
description: MUST be used for exploratory codebase research, rapid code analysis, and broad pattern searches. Fast read-only scout returning compressed context for handoff.
|
|
4
4
|
tools: read, grep, glob, web_search
|
|
5
|
-
model:
|
|
5
|
+
model: "@smol"
|
|
6
6
|
thinking-level: medium
|
|
7
7
|
read-summarize: false
|
|
8
8
|
output:
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Plan approved: **{{title}}**.
|
|
2
|
+
|
|
3
|
+
Read `{{planFilePath}}` and implement it now — full tool access is restored. Execute the plan top to bottom exactly as written; you were not part of drafting it, so treat every choice in it as already made. Do not ask for further approval and do not re-plan.
|
|
4
|
+
|
|
5
|
+
When finished, re-read the plan and confirm every step was completed before ending your turn.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Before you consider this task finished, verify:
|
|
2
|
+
|
|
3
|
+
- Consistency: if you changed a pattern, signature, or check in one place, grep for every other call site or duplicate copy that needs the identical change. A fix applied to only some of the matching sites is still a failure.
|
|
4
|
+
- Scope: if your diff does more than the minimal change needed to resolve the issue, confirm you have not altered behavior for any case outside the reported issue. Prefer the smallest correct diff over a broader rewrite.
|
|
5
|
+
- Verification: run the full test module or file the issue lives in, not just the one test you expect to flip. A change that breaks a sibling test is not a fix.
|
|
6
|
+
|
|
7
|
+
Do not claim the task is complete until you have done these three checks.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Continue the task now — do not end your turn here.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Stop and write the complete plan in your NEXT reply — before any further exploration. You have already seen enough to commit to a plan; do not defer this.
|
|
2
|
+
|
|
3
|
+
First, state the plan itself, explicitly and comprehensively:
|
|
4
|
+
|
|
5
|
+
- Every remaining step in execution order, with the exact files, symbols, commands, and checks involved.
|
|
6
|
+
- Known risks, edge cases, and how you will verify each step actually landed (specific commands, expected outputs). Never modify tests or verification assets to make checks pass.
|
|
7
|
+
- What is already done, stated briefly, so no step gets repeated.
|
|
8
|
+
|
|
9
|
+
Be thorough and concrete — this plan is the reference for the remainder of the run. You may verify details with tools after the plan is written, never before.
|
|
10
|
+
|
|
11
|
+
Then, only once the plan above is complete, in the SAME reply, capture it as a todo list (the todo tool): 5-9 items, one per MEANINGFUL step, each naming its concrete target and its verification. Only steps that change or verify code belong on the list — no reporting, bookkeeping, cleanup-ceremony, or release-note items. The todo list serves the task, never the reverse: when reality disagrees with an item, fix the actual problem rather than working the checklist.
|
|
12
|
+
|
|
13
|
+
This is a checkpoint, not a final answer: do not end your turn on the plan alone — after recording the todo list, continue the task; do not stop here.
|
|
@@ -192,7 +192,7 @@ EXECUTION WORKFLOW
|
|
|
192
192
|
|
|
193
193
|
# 3. Decompose
|
|
194
194
|
- Update todos as you go; skip them for trivial requests. Marking a todo done is a transition: start the next in the same turn.
|
|
195
|
-
- Plan only what makes the request work. Cleanup—changelog,
|
|
195
|
+
- Plan only what makes the request work. Cleanup—changelog, docs, removing scaffolding—is NOT planned up front; it belongs to the final phase below. Tests are cleanup only for permanent feature/bug-fix work (see Cleanup).
|
|
196
196
|
|
|
197
197
|
# 4. Implement
|
|
198
198
|
- Fix problems at the source. Remove obsolete code—no leftover comments, aliases, or re-exports.
|
|
@@ -202,14 +202,16 @@ EXECUTION WORKFLOW
|
|
|
202
202
|
{{#has tools "ask"}}- Ask before destructive commands or deleting code you didn't write.{{else}}- Don't run destructive git commands or delete code you didn't write.{{/has}}
|
|
203
203
|
|
|
204
204
|
# 5. Verify
|
|
205
|
-
- NEVER yield non-trivial work without proof
|
|
206
|
-
-
|
|
207
|
-
-
|
|
208
|
-
-
|
|
209
|
-
-
|
|
205
|
+
- NEVER yield non-trivial work without proof that the deliverable works. The proof method depends on the ask:
|
|
206
|
+
- **Experiment / investigation** → run it. The output IS the proof. No tests.
|
|
207
|
+
- **UI change** → drive it in browser. Visual confirmation IS the proof. No tests unless the existing suite breaks and the break is real.
|
|
208
|
+
- **Bug fix** → reproduce the bug, apply the fix, confirm the reproduction no longer triggers.
|
|
209
|
+
- **Permanent feature / API change** → existing tests that cover the changed contract. Add a test only when the change introduces a new observable contract not already covered, or the user asked for one.
|
|
210
|
+
- Smoke test: run the thing, not a test file. Launch it, exercise the changed path, observe the result.
|
|
211
|
+
- When you ARE writing tests (not the default): every test MUST defend an observable contract and fail on a plausible bug. Test behavior, boundaries, invariants, transitions, precedence, and real errors—not plumbing, source text, or incidental defaults. Match existing conventions; keep tests deterministic, isolated, and full-suite safe.
|
|
210
212
|
|
|
211
213
|
# 6. Cleanup
|
|
212
|
-
Changelog
|
|
214
|
+
Changelog and removing scaffolding are the LAST phase—NEVER skipped, but gated on the request demonstrably working. Tests and docs are cleanup ONLY when the work is a permanent feature change or bug fix, not for experiments or one-off investigations.
|
|
213
215
|
|
|
214
216
|
- NEVER start, pre-plan, or pre-allocate todos for cleanup before you've made the request work and smoke-tested it. Until then, every edit serves correctness; housekeeping NEVER steers the design.
|
|
215
217
|
- Once your smoke test confirms “it works,” do the cleanup in full before yielding.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<system-notice cause="fork">
|
|
2
|
+
The conversation above belongs to your parent session.
|
|
3
|
+
You are a fork created solely to handle the user's request below.
|
|
4
|
+
|
|
5
|
+
Your parent agent is still working on the original task — that responsibility is
|
|
6
|
+
NOT yours. You have no obligations from the prior conversation.
|
|
7
|
+
|
|
8
|
+
- Focus EXCLUSIVELY on the user's immediate request. Nothing else.
|
|
9
|
+
- NEVER continue, follow up on, or intervene in anything discussed before this
|
|
10
|
+
message. Those belong to the parent session.
|
|
11
|
+
- Your parent is CONCURRENTLY editing this same working directory. Files may
|
|
12
|
+
change between your reads, look mid-refactor, or fail to compile. That is the
|
|
13
|
+
parent's live work — NEVER fix, audit, or build on it, even if it looks broken.
|
|
14
|
+
- Any todo list, plan, or unfinished checklist from the prior conversation is
|
|
15
|
+
the parent's. NEVER resume or update it.
|
|
16
|
+
- After addressing the user's request, STOP. Do not work on ANY OTHER TASK.
|
|
17
|
+
</system-notice>
|
|
@@ -5,6 +5,7 @@ Runs commands in the embedded shell — terminal ops: git, bun, cargo, python.
|
|
|
5
5
|
The shell invokes **real binaries** with simple args. It is NOT full GNU Bash.
|
|
6
6
|
|
|
7
7
|
Use bash ONLY for: a single binary call, or one short pipeline that COMPUTES a fact and does not depend on shell-specific regex/quoting (`wc -l`, `sort | uniq -c`, `comm`, `diff`, a checksum, `git status`).
|
|
8
|
+
{{#if hasLaunch}}Long-running service, watcher, debugger, REPL, or process needing later input? MUST use `launch`, not bash.{{/if}}
|
|
8
9
|
|
|
9
10
|
{{#if hasEval}}Anything below → `eval` cell, not bash:
|
|
10
11
|
- Inline interpreter scripts (`-e`/`-c`/`--eval`) when an eval runtime exists for that language
|
|
@@ -33,7 +34,7 @@ Use bash ONLY for: a single binary call, or one short pipeline that COMPUTES a f
|
|
|
33
34
|
- Internal URIs (`skill://`, `agent://`, …) auto-resolve to FS paths
|
|
34
35
|
{{#if hasEval}}- Need exact pipeline semantics (`cmd | head`, multi-stage filtering) or output truncation? Prefer `eval` and process the stream directly.{{else}}- Need exact pipeline semantics (`cmd | head`, multi-stage filtering) or output truncation? Use a checked-in script, purpose-built tool, or single command that owns the output shape.{{/if}}
|
|
35
36
|
{{#if asyncEnabled}}
|
|
36
|
-
- `async: true` for
|
|
37
|
+
- `async: true` defers reporting for finite commands that need no later input; completion arrives as a follow-up.
|
|
37
38
|
{{/if}}
|
|
38
39
|
</instruction>
|
|
39
40
|
|
|
@@ -42,6 +43,7 @@ Use bash ONLY for: a single binary call, or one short pipeline that COMPUTES a f
|
|
|
42
43
|
{{#if hasGrep}}- NEVER shell out to search content or files: `grep/rg` → `grep`.{{else}}- Avoid shelling out for broad content search; use an active search/read tool when one is available.{{/if}}
|
|
43
44
|
{{#if hasRead}}{{#if hasGlob}}- NEVER use `ls` or `find` to list or locate files — `ls` → `read` (a directory path lists entries), `find` → the `glob` tool (globbing). This is non-negotiable, even for a single quick listing.{{else}}- Prefer `read` for known file and directory reads. Only use shell listing when no file-listing tool is active.{{/if}}{{else}}{{#if hasGlob}}- Prefer `glob` for file discovery; avoid `find` when `glob` is active.{{else}}- If no file read/listing tool is active, keep shell inspection narrow and state that limitation.{{/if}}{{/if}}
|
|
44
45
|
- Avoid head/tail/redirections: stderr already merged; long output auto-truncated, FULL capture kept at `artifact://<id>`.
|
|
46
|
+
{{#if hasLaunch}}- NEVER launch daemons, watchers, dev servers, debuggers, or REPLs through bash/background shell syntax — use `launch`.{{/if}}
|
|
45
47
|
</critical>
|
|
46
48
|
|
|
47
49
|
<output>
|
|
@@ -52,9 +54,9 @@ Use bash ONLY for: a single binary call, or one short pipeline that COMPUTES a f
|
|
|
52
54
|
{{#if asyncEnabled}}
|
|
53
55
|
# Timeout and async
|
|
54
56
|
|
|
55
|
-
- `timeout` is seconds; nonzero values are clamped to `1..3600` and the process is killed on elapse. Set `timeout: 0` only for commands
|
|
56
|
-
- `async: true` defers only reporting
|
|
57
|
-
- Need a
|
|
57
|
+
- `timeout` is seconds; nonzero values are clamped to `1..3600` and the process is killed on elapse. Set `timeout: 0` only for finite commands whose completion is cancellation-owned.
|
|
58
|
+
- `async: true` defers only reporting; it does NOT extend a nonzero timeout.
|
|
59
|
+
{{#if hasLaunch}}- Need a service, watcher, debugger, REPL, or later stdin? MUST use `launch`. NEVER use `cmd &`, `nohup`, or async bash as a process supervisor.{{else}}- Need a long-running process or >3600s run? Use an external process supervisor; avoid detached shell jobs you cannot later observe or stop.{{/if}}
|
|
58
60
|
{{/if}}
|
|
59
61
|
{{#if autoBackgroundEnabled}}
|
|
60
62
|
|
|
@@ -5,7 +5,7 @@ Drives real Chromium tab; full puppeteer access via JS.
|
|
|
5
5
|
- Three actions:
|
|
6
6
|
- `open` — acquire/reuse named tab (`name` defaults `"main"`). Optional `url` (navigate once ready), `viewport`, `dialogs: "accept" | "dismiss"` (auto-handle `alert`/`confirm`/`beforeunload`; else page hangs till you wire `page.on('dialog', …)`).
|
|
7
7
|
- `close` — release tab by `name`, or all with `all: true`. `kill: true` also kills spawned-app process trees.
|
|
8
|
-
- `run` — execute JS in existing tab. `code` = async function body; `page`, `browser`, `tab`, `display`, `assert`, `wait` in scope. Return value JSON-stringified into result; `display(value)` accumulates text/images.
|
|
8
|
+
- `run` — execute JS in existing tab. `code` = async function body; `page`, `browser`, `tab`, `display`, `assert`, `wait` in scope. Return value JSON-stringified into result; `display(value)` accumulates text/images. `wait(ms)` sleeps; `wait(fn, { timeout?, interval? })` polls `fn` (sync or async) until truthy and resolves with that value (default 100ms interval; deadline min(30s, cell budget − 1s), named error on timeout) — use it instead of in-page polling Promises inside `tab.evaluate`.
|
|
9
9
|
- Tabs survive `run` calls and in-process subagents — open once, reuse.
|
|
10
10
|
- Browser kinds (`app` on `open`):
|
|
11
11
|
- default (no `app`) → headless Chromium with stealth patches.
|
|
@@ -13,7 +13,7 @@ Drives real Chromium tab; full puppeteer access via JS.
|
|
|
13
13
|
- `app.cdp_url` → connect to existing CDP endpoint (e.g. `http://127.0.0.1:9222`).
|
|
14
14
|
- `app.target` (with `path`/`cdp_url`) — substring on url+title picks BrowserWindow.
|
|
15
15
|
- `tab` helpers; drop to raw puppeteer `page` for anything uncovered:
|
|
16
|
-
- `tab.goto(url, { waitUntil? })` — navigate.
|
|
16
|
+
- `tab.goto(url, { waitUntil? })` — navigate. A hung load fails ~1s before the cell budget with a named, catchable error and the pending navigation is stopped; for slow pages raise `timeout` or use `waitUntil: "domcontentloaded"`.
|
|
17
17
|
- `tab.observe({ includeAll?, viewportOnly? })` — accessibility snapshot: `{ url, title, viewport, scroll, elements: [{ id, role, name, value, states, … }] }`. Ids stable until next observe/goto.
|
|
18
18
|
- `tab.ariaSnapshot(selector?, { depth?, boxes? })` — Playwright-format ARIA-tree YAML (nested roles + accessible names + `/url`/`/placeholder`), scoped to `selector` or the whole document. Every node carries a `[ref=eN]` id; `[cursor=pointer]` flags clickables. Captures dense, hierarchical structure/text that `observe()`'s flat list flattens away. Refs renumber from e1 each call and stay valid until the next `ariaSnapshot()`.
|
|
19
19
|
- `tab.ref("e5")` — `[ref=eN]` from the last ariaSnapshot → element handle with the common action methods (`.click()`, `.type()`, `.fill()`, `.hover()`, `.evaluate()`, …); the primary way to act on a ref. For convenience `aria-ref=e5` also works inline in `tab.click`/`type`/`fill`/`waitFor`/`scrollIntoView` (e.g. `tab.click("aria-ref=e5")`).
|
|
@@ -27,10 +27,10 @@ Drives real Chromium tab; full puppeteer access via JS.
|
|
|
27
27
|
- `tab.waitForUrl(pattern, { timeout? })` — substring or `RegExp` (matches SPA pushState nav); returns matched URL.
|
|
28
28
|
- `tab.waitForResponse(pattern, { timeout? })` — substring, `RegExp`, or `(response) => boolean`; returns puppeteer `HTTPResponse` (`.text()`/`.json()`/`.status()`/`.headers()`).
|
|
29
29
|
- `tab.waitForNavigation({ waitUntil?, timeout? })` — resolves on the next navigation. Start it BEFORE the click/submit that triggers it; after `tab.goto` (which already waits) use `tab.waitForUrl`/`tab.waitForSelector` instead.
|
|
30
|
-
- `tab.evaluate(fn, …args)` —
|
|
30
|
+
- `tab.evaluate(fn, …args)` — run ad-hoc code in the page's MAIN world. DOM and page-defined globals (`window.myFlag`) are visible; mutations affect the page.
|
|
31
31
|
- `tab.screenshot({ selector?, fullPage?, save?, silent? })` — capture + attach for viewing (`silent: true` skips). Pass `save` only when a later step needs the file.
|
|
32
32
|
- `tab.extract(format = "markdown")` — readable page content (`"markdown"` | `"text"`); throws when nothing readable.
|
|
33
|
-
- Selectors: CSS + puppeteer handlers `aria/Sign in`, `text/Continue`, `xpath/…`, `pierce/…`; also Playwright-style `p-aria/…`, `p-text/…`. Playwright-only engines/pseudos (`:has-text()`, `:visible`, …) are rejected — use `text/…` or `aria/…`. A stalled action/wait fails fast with a named `tab.<op>` error carrying a match-count diagnosis, never the whole-cell timeout; a selector matching nothing fails in ~2s (pass an explicit `{ timeout }` to `waitFor`/`waitForSelector` to wait out slow-appearing elements).
|
|
33
|
+
- Selectors: CSS + puppeteer handlers `aria/Sign in`, `text/Continue`, `xpath/…`, `pierce/…`; also Playwright-style `p-aria/…`, `p-text/…`. Playwright-only engines/pseudos (`:has-text()`, `:visible`, …) are rejected — use `text/…` or `aria/…`. A stalled action/wait fails fast with a named `tab.<op>` error carrying a match-count diagnosis, never the whole-cell timeout; a selector matching nothing fails in ~2s (pass an explicit `{ timeout }` to `waitFor`/`waitForSelector` to wait out slow-appearing elements). A whole-cell timeout names the stalled op (including `wait(…)`) and any unhandled dialog blocking the page.
|
|
34
34
|
</instruction>
|
|
35
35
|
|
|
36
36
|
<critical>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Launches and controls project-scoped long-running processes shared by every omp instance in the same directory.
|
|
2
|
+
|
|
3
|
+
<instruction>
|
|
4
|
+
- Long-running service, watcher, debugger, REPL, or process needing later input? MUST use `launch`, not `bash`.
|
|
5
|
+
- `start` launches `application` + `args` directly. `cwd` defaults to the session directory; `pty` defaults true.
|
|
6
|
+
- `ready.log` is a regex; `ready.port` is a TCP port. Both supplied? BOTH MUST pass. `ready.timeout` is seconds.
|
|
7
|
+
- Names are unique per project directory. A completed name MAY be started again; a live name MUST be stopped or restarted.
|
|
8
|
+
- `list`, `logs`, `wait`, `send`, `stop`, `restart`, and `describe` address the stable `name`.
|
|
9
|
+
- `logs` defaults to the last 100 lines. `head: true` reads the beginning. `grep` is a regex.
|
|
10
|
+
- `logs` with `follow: true` waits for output after `cursor`; reuse the returned cursor on the next call.
|
|
11
|
+
- `wait` blocks until readiness/exit/pattern or timeout. Use it only when blocked; do useful work instead of tight polling.
|
|
12
|
+
- `send.text` writes stdin; `enter` defaults true. `keys` supports ENTER, TAB, ESCAPE, CTRL_C, CTRL_D, UP, DOWN, LEFT, RIGHT.
|
|
13
|
+
- `send.signal` supports SIGINT, SIGTERM, SIGHUP, SIGQUIT, SIGKILL. PTY input is serialized; many clients MAY observe, but writes share one input stream.
|
|
14
|
+
- `stop` performs graceful process-tree termination before hard-kill. `restart` reuses the retained launch spec.
|
|
15
|
+
- `restart` policy defaults `no`; `on-failure` and `always` use bounded backoff.
|
|
16
|
+
- `persist: true` opts out of last-omp teardown. Otherwise the broker stops every non-persistent supervised process after the last omp in this directory exits.
|
|
17
|
+
- `detached: true` survives broker shutdown and all omp exits. It implies `persist` and disables PTY/stdin.
|
|
18
|
+
</instruction>
|
|
19
|
+
|
|
20
|
+
<critical>
|
|
21
|
+
- Long-running work MUST use `launch`, not async/background bash.
|
|
22
|
+
- Readiness MUST be observed; process creation alone is not readiness.
|
|
23
|
+
- Omit `persist` and `detached` unless their survival guarantees are required.
|
|
24
|
+
- Use `stop`; NEVER kill an unverified PID through bash.
|
|
25
|
+
</critical>
|
package/src/sdk.ts
CHANGED
|
@@ -109,7 +109,7 @@ import {
|
|
|
109
109
|
obfuscateProviderContext,
|
|
110
110
|
SecretObfuscator,
|
|
111
111
|
} from "./secrets";
|
|
112
|
-
import { AgentSession } from "./session/agent-session";
|
|
112
|
+
import { AgentSession, type PlanYolo, type Prewalk } from "./session/agent-session";
|
|
113
113
|
import { discoverAuthStorage as discoverAuthStorageFromConfig } from "./session/auth-broker-config";
|
|
114
114
|
import type { AuthStorage } from "./session/auth-storage";
|
|
115
115
|
import {
|
|
@@ -407,6 +407,10 @@ export interface CreateAgentSessionOptions {
|
|
|
407
407
|
thinkingLevel?: ConfiguredThinkingLevel;
|
|
408
408
|
/** Models available for cycling (Ctrl+P in interactive mode) */
|
|
409
409
|
scopedModels?: Array<{ model: Model; thinkingLevel?: ThinkingLevel }>;
|
|
410
|
+
/** Prewalk from the starting model to a fast/cheap target at the first edit/write once the todo list exists. */
|
|
411
|
+
prewalk?: Prewalk;
|
|
412
|
+
/** Force read-only plan mode at start, auto-approve on the model's first resolve call, then switch to execute. */
|
|
413
|
+
planYolo?: PlanYolo;
|
|
410
414
|
|
|
411
415
|
/** Provider-facing system prompt override. Replaces the fully rendered default blocks. */
|
|
412
416
|
systemPrompt?: string | string[] | ((defaultPrompt: string[]) => string | string[]);
|
|
@@ -1983,7 +1987,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1983
1987
|
}
|
|
1984
1988
|
}
|
|
1985
1989
|
// Resolve deferred --model/subagent patterns now that extension models are
|
|
1986
|
-
// registered. Expand role aliases (
|
|
1990
|
+
// registered. Expand role aliases (`@smol`) and comma chains to concrete
|
|
1987
1991
|
// selectors first so deferred resolution accepts everything the immediate
|
|
1988
1992
|
// path (resolveModelOverride → resolveModelRoleValue) accepts.
|
|
1989
1993
|
if (!model && deferredModelPatterns.length > 0) {
|
|
@@ -2863,6 +2867,8 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2863
2867
|
agent,
|
|
2864
2868
|
pruneToolDescriptions: inlineToolDescriptors,
|
|
2865
2869
|
thinkingLevel: autoThinking ? AUTO_THINKING : effectiveThinkingLevel,
|
|
2870
|
+
prewalk: options.prewalk,
|
|
2871
|
+
planYolo: options.planYolo,
|
|
2866
2872
|
serviceTierByFamily: initialServiceTierByFamily,
|
|
2867
2873
|
sessionManager,
|
|
2868
2874
|
settings,
|