@oh-my-pi/pi-coding-agent 15.13.1 → 15.13.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/CHANGELOG.md +25 -0
- package/dist/cli.js +957 -214
- package/dist/types/config/model-registry.d.ts +1 -0
- package/dist/types/config/models-config-schema.d.ts +3 -0
- package/dist/types/config/models-config.d.ts +3 -0
- package/dist/types/config/settings-schema.d.ts +66 -0
- package/dist/types/edit/hashline/block-resolver.d.ts +1 -1
- package/dist/types/edit/index.d.ts +2 -0
- package/dist/types/modes/components/welcome.d.ts +1 -0
- package/dist/types/modes/controllers/input-controller.d.ts +4 -4
- package/dist/types/modes/rpc/rpc-types.d.ts +2 -1
- package/dist/types/sdk.d.ts +3 -0
- package/dist/types/session/session-dump-format.d.ts +2 -1
- package/dist/types/system-prompt.d.ts +11 -0
- package/dist/types/tools/ask.d.ts +2 -0
- package/dist/types/tools/ast-edit.d.ts +2 -0
- package/dist/types/tools/ast-grep.d.ts +2 -0
- package/dist/types/tools/browser.d.ts +2 -0
- package/dist/types/tools/debug.d.ts +2 -0
- package/dist/types/tools/eval.d.ts +2 -0
- package/dist/types/tools/find.d.ts +2 -0
- package/dist/types/tools/inspect-image.d.ts +2 -1
- package/dist/types/tools/irc.d.ts +2 -0
- package/dist/types/tools/ssh.d.ts +2 -0
- package/dist/types/tools/todo.d.ts +2 -0
- package/dist/types/tui/tree-list.d.ts +1 -0
- package/package.json +12 -12
- package/src/config/model-registry.ts +10 -0
- package/src/config/models-config-schema.ts +2 -0
- package/src/config/models-config.ts +1 -0
- package/src/config/settings-schema.ts +53 -0
- package/src/edit/hashline/block-resolver.ts +1 -1
- package/src/edit/hashline/execute.ts +1 -6
- package/src/edit/index.ts +48 -0
- package/src/eval/__tests__/js-context-manager.test.ts +41 -1
- package/src/eval/js/context-manager.ts +92 -26
- package/src/eval/js/worker-core.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +9 -2
- package/src/modes/components/welcome.ts +14 -4
- package/src/modes/controllers/input-controller.ts +21 -38
- package/src/modes/rpc/rpc-mode.ts +1 -0
- package/src/modes/rpc/rpc-types.ts +2 -2
- package/src/prompts/system/system-prompt.md +17 -21
- package/src/prompts/tools/ask.md +0 -8
- package/src/prompts/tools/ast-edit.md +0 -15
- package/src/prompts/tools/ast-grep.md +0 -13
- package/src/prompts/tools/browser.md +0 -21
- package/src/prompts/tools/debug.md +0 -13
- package/src/prompts/tools/eval.md +0 -9
- package/src/prompts/tools/find.md +0 -13
- package/src/prompts/tools/inspect-image.md +0 -9
- package/src/prompts/tools/irc.md +0 -15
- package/src/prompts/tools/patch.md +0 -13
- package/src/prompts/tools/ssh.md +0 -9
- package/src/prompts/tools/todo.md +1 -19
- package/src/sdk.ts +19 -0
- package/src/session/agent-session.ts +125 -19
- package/src/session/session-dump-format.ts +10 -31
- package/src/system-prompt.ts +31 -0
- package/src/tools/ask.ts +41 -0
- package/src/tools/ast-edit.ts +46 -0
- package/src/tools/ast-grep.ts +24 -0
- package/src/tools/browser.ts +52 -0
- package/src/tools/debug.ts +17 -0
- package/src/tools/eval.ts +20 -1
- package/src/tools/find.ts +24 -0
- package/src/tools/inspect-image.ts +27 -1
- package/src/tools/irc.ts +41 -0
- package/src/tools/ssh.ts +16 -0
- package/src/tools/todo.ts +82 -3
- package/src/tui/tree-list.ts +68 -19
|
@@ -70,8 +70,7 @@ export interface LspServerInfo {
|
|
|
70
70
|
export class WelcomeComponent implements Component {
|
|
71
71
|
#animStart: number | null = null;
|
|
72
72
|
#animTimer: ReturnType<typeof setInterval> | null = null;
|
|
73
|
-
|
|
74
|
-
readonly #tip: string | undefined = TIPS.length > 0 ? TIPS[Math.floor(Math.random() * TIPS.length)] : undefined;
|
|
73
|
+
#selectedTip: string | undefined;
|
|
75
74
|
// Render cache: the welcome box is the first transcript-area component, so
|
|
76
75
|
// returning a stable array reference keeps the whole frame prefix stable.
|
|
77
76
|
// Bypassed while the intro animation runs (every frame differs).
|
|
@@ -85,6 +84,16 @@ export class WelcomeComponent implements Component {
|
|
|
85
84
|
private recentSessions: RecentSession[] = [],
|
|
86
85
|
private lspServers: LspServerInfo[] = [],
|
|
87
86
|
) {}
|
|
87
|
+
get tip(): string | undefined {
|
|
88
|
+
if (this.#selectedTip === undefined) {
|
|
89
|
+
if (theme.getSymbolPreset() === "unicode" && Math.random() < 0.1) {
|
|
90
|
+
this.#selectedTip = "Please use nerdfont 😭.";
|
|
91
|
+
} else {
|
|
92
|
+
this.#selectedTip = TIPS.length > 0 ? TIPS[Math.floor(Math.random() * TIPS.length)] : "";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return this.#selectedTip || undefined;
|
|
96
|
+
}
|
|
88
97
|
|
|
89
98
|
invalidate(): void {
|
|
90
99
|
this.#cachedWidth = -1;
|
|
@@ -316,8 +325,9 @@ export class WelcomeComponent implements Component {
|
|
|
316
325
|
* when no tip is available or the box is too narrow to be useful.
|
|
317
326
|
*/
|
|
318
327
|
#renderTip(boxWidth: number): string[] {
|
|
319
|
-
|
|
320
|
-
|
|
328
|
+
const tip = this.tip;
|
|
329
|
+
if (!tip) return [];
|
|
330
|
+
return renderWelcomeTip(tip, boxWidth);
|
|
321
331
|
}
|
|
322
332
|
|
|
323
333
|
/** Center text within a given width */
|
|
@@ -44,26 +44,9 @@ function hasPasteText(value: unknown): value is PasteTarget {
|
|
|
44
44
|
return typeof value === "object" && value !== null && typeof (value as PasteTarget).pasteText === "function";
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
/** Wrap pasted text in
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
let longestRun = 0;
|
|
51
|
-
let run = 0;
|
|
52
|
-
for (let i = 0; i < content.length; i++) {
|
|
53
|
-
if (content.charCodeAt(i) === 96 /* backtick */) {
|
|
54
|
-
run++;
|
|
55
|
-
if (run > longestRun) longestRun = run;
|
|
56
|
-
} else {
|
|
57
|
-
run = 0;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const fence = "`".repeat(Math.max(3, longestRun + 1));
|
|
61
|
-
return `${fence}\n${content}\n${fence}`;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** Wrap pasted text in `<pasted_text>` tags so the model treats it as one quoted block. */
|
|
65
|
-
function wrapPasteInXml(content: string): string {
|
|
66
|
-
return `<pasted_text>\n${content}\n</pasted_text>`;
|
|
47
|
+
/** Wrap pasted text in `<attachment>` tags so the model treats it as one quoted block. */
|
|
48
|
+
function wrapPasteInAttachmentBlock(content: string): string {
|
|
49
|
+
return `<attachment>\n${content}\n</attachment>`;
|
|
67
50
|
}
|
|
68
51
|
|
|
69
52
|
const TINY_TITLE_PROGRESS_DONE_TTL_MS = 3_000;
|
|
@@ -99,8 +82,8 @@ export class InputController {
|
|
|
99
82
|
// (>= LEFT_DOUBLE_TAP_MAX_GAP_MS) starts a fresh sequence. See
|
|
100
83
|
// #detectLeftDoubleTap.
|
|
101
84
|
#leftTapCount = 0;
|
|
102
|
-
// Sequential index for `local://attachment-N` references created by the large-paste
|
|
103
|
-
//
|
|
85
|
+
// Sequential index for `local://attachment-N` references created by the large-paste local-file
|
|
86
|
+
// action. Seeded from 0 and bumped past any existing attachment files in #attachPasteAsFile.
|
|
104
87
|
#attachmentCounter = 0;
|
|
105
88
|
|
|
106
89
|
#showTinyTitleDownloadProgress(modelKey: string): void {
|
|
@@ -1282,24 +1265,24 @@ export class InputController {
|
|
|
1282
1265
|
}
|
|
1283
1266
|
|
|
1284
1267
|
/**
|
|
1285
|
-
* Present the large-paste menu and apply the chosen action: wrap in
|
|
1286
|
-
*
|
|
1287
|
-
*
|
|
1288
|
-
*
|
|
1268
|
+
* Present the large-paste menu and apply the chosen action: wrap in `<attachment>` tags (collapsed
|
|
1269
|
+
* to a `[Paste]` marker that expands on submit), save the text to a file and reference its path so
|
|
1270
|
+
* the agent can `read` it on demand, or paste inline. Cancelling (Esc) falls back to the default
|
|
1271
|
+
* inline paste marker, so the pasted content is never lost.
|
|
1289
1272
|
*/
|
|
1290
1273
|
async presentLargePasteMenu(text: string, lineCount: number): Promise<void> {
|
|
1291
|
-
const
|
|
1292
|
-
const
|
|
1293
|
-
const
|
|
1274
|
+
const WRAPPED_BLOCK = "Attach as a wrapped block";
|
|
1275
|
+
const LOCAL_FILE = "Attach as local file";
|
|
1276
|
+
const INLINE = "Paste inline";
|
|
1294
1277
|
|
|
1295
1278
|
let choice: string | undefined;
|
|
1296
1279
|
try {
|
|
1297
1280
|
choice = await this.ctx.showHookSelector(
|
|
1298
1281
|
`Pasted ${lineCount} lines`,
|
|
1299
1282
|
[
|
|
1300
|
-
{ label:
|
|
1301
|
-
{ label:
|
|
1302
|
-
{ label:
|
|
1283
|
+
{ label: WRAPPED_BLOCK, description: "Wrap the text in <attachment> tags, collapsed to a marker" },
|
|
1284
|
+
{ label: LOCAL_FILE, description: "Save the text to a local://attachment file" },
|
|
1285
|
+
{ label: INLINE, description: "Collapse the text to an inline paste marker" },
|
|
1303
1286
|
],
|
|
1304
1287
|
{ helpText: "Esc to paste inline" },
|
|
1305
1288
|
);
|
|
@@ -1309,15 +1292,15 @@ export class InputController {
|
|
|
1309
1292
|
}
|
|
1310
1293
|
|
|
1311
1294
|
switch (choice) {
|
|
1312
|
-
case
|
|
1313
|
-
this.ctx.editor.insertPaste(
|
|
1314
|
-
break;
|
|
1315
|
-
case XML:
|
|
1316
|
-
this.ctx.editor.insertPaste(wrapPasteInXml(text));
|
|
1295
|
+
case WRAPPED_BLOCK:
|
|
1296
|
+
this.ctx.editor.insertPaste(wrapPasteInAttachmentBlock(text));
|
|
1317
1297
|
break;
|
|
1318
|
-
case
|
|
1298
|
+
case LOCAL_FILE:
|
|
1319
1299
|
await this.#attachPasteAsFile(text, lineCount);
|
|
1320
1300
|
break;
|
|
1301
|
+
case INLINE:
|
|
1302
|
+
this.ctx.editor.insertPaste(text);
|
|
1303
|
+
break;
|
|
1321
1304
|
default:
|
|
1322
1305
|
// Esc / cancel: keep the original behavior — collapse to an inline paste marker.
|
|
1323
1306
|
this.ctx.editor.insertPaste(text);
|
|
@@ -796,6 +796,7 @@ export async function runRpcMode(
|
|
|
796
796
|
name: tool.name,
|
|
797
797
|
description: tool.description,
|
|
798
798
|
parameters: isZodSchema(tool.parameters) ? zodToWireSchema(tool.parameters) : tool.parameters,
|
|
799
|
+
examples: tool.examples,
|
|
799
800
|
})),
|
|
800
801
|
contextUsage: session.getContextUsage(),
|
|
801
802
|
};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { AgentMessage, AgentToolResult, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
8
8
|
import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
|
|
9
|
-
import type { Effort, ImageContent, Model } from "@oh-my-pi/pi-ai";
|
|
9
|
+
import type { Effort, ImageContent, Model, ToolExample } from "@oh-my-pi/pi-ai";
|
|
10
10
|
import type { BashResult } from "../../exec/bash-executor";
|
|
11
11
|
import type { ContextUsage } from "../../extensibility/extensions/types";
|
|
12
12
|
import type { AgentSessionEvent, SessionStats } from "../../session/agent-session";
|
|
@@ -107,7 +107,7 @@ export interface RpcSessionState {
|
|
|
107
107
|
todoPhases: TodoPhase[];
|
|
108
108
|
/** For session dump / export (plain-text parity with /dump). */
|
|
109
109
|
systemPrompt?: string[];
|
|
110
|
-
dumpTools?: Array<{ name: string; description: string; parameters: unknown }>;
|
|
110
|
+
dumpTools?: Array<{ name: string; description: string; parameters: unknown; examples?: readonly ToolExample[] }>;
|
|
111
111
|
/** Current context window usage. Null tokens/percent when unknown (e.g. right after compaction). */
|
|
112
112
|
contextUsage?: ContextUsage;
|
|
113
113
|
}
|
|
@@ -24,27 +24,6 @@ Use tools whenever they materially improve correctness, completeness, or groundi
|
|
|
24
24
|
- SHOULD parallelize calls when possible.
|
|
25
25
|
{{#has tools "task"}}- User says `parallel`/`parallelize` → MUST use `{{toolRefs.task}}` subagents; parallel tool calls alone do not satisfy.{{/has}}
|
|
26
26
|
|
|
27
|
-
{{#if toolInfo.length}}
|
|
28
|
-
# Inventory
|
|
29
|
-
{{#if mcpDiscoveryMode}}
|
|
30
|
-
<discovery-notice>
|
|
31
|
-
{{#if hasMCPDiscoveryServers}}Discoverable MCP servers in this session: {{#list mcpDiscoveryServerSummaries join=", "}}{{this}}{{/list}}.{{/if}}
|
|
32
|
-
If the task may involve external systems, SaaS APIs, chat, tickets, databases, deployments, or other non-local integrations, you SHOULD call `{{toolRefs.search_tool_bm25}}` before concluding no such tool exists.
|
|
33
|
-
</discovery-notice>
|
|
34
|
-
{{/if}}
|
|
35
|
-
{{#if repeatToolDescriptions}}
|
|
36
|
-
{{#each toolInfo}}
|
|
37
|
-
<tool name={{name}}>
|
|
38
|
-
{{description}}
|
|
39
|
-
</tool>
|
|
40
|
-
{{/each}}
|
|
41
|
-
{{else}}
|
|
42
|
-
{{#each toolInfo}}
|
|
43
|
-
- {{#if label}}{{label}}: `{{name}}`{{else}}`{{name}}`{{/if}}
|
|
44
|
-
{{/each}}
|
|
45
|
-
{{/if}}
|
|
46
|
-
{{/if}}
|
|
47
|
-
|
|
48
27
|
# I/O
|
|
49
28
|
- For tools taking `path` or path-like fields, prefer relative paths.
|
|
50
29
|
{{#if intentTracing}}- Most tools have a `{{intentField}}` parameter. Fill it with a concise intent in present participle form, 2-6 words, no period, capitalized.{{/if}}
|
|
@@ -115,6 +94,23 @@ Delegation is preferred here. Once the design is settled, you SHOULD fan substan
|
|
|
115
94
|
{{/has}}
|
|
116
95
|
{{/if}}
|
|
117
96
|
|
|
97
|
+
{{#if toolInfo.length}}
|
|
98
|
+
# Inventory
|
|
99
|
+
{{#if mcpDiscoveryMode}}
|
|
100
|
+
<discovery-notice>
|
|
101
|
+
{{#if hasMCPDiscoveryServers}}Discoverable MCP servers in this session: {{#list mcpDiscoveryServerSummaries join=", "}}{{this}}{{/list}}.{{/if}}
|
|
102
|
+
If the task may involve external systems, SaaS APIs, chat, tickets, databases, deployments, or other non-local integrations, you SHOULD call `{{toolRefs.search_tool_bm25}}` before concluding no such tool exists.
|
|
103
|
+
</discovery-notice>
|
|
104
|
+
{{/if}}
|
|
105
|
+
{{#if toolListMode}}
|
|
106
|
+
{{#each toolInfo}}
|
|
107
|
+
- {{#if label}}{{label}}: `{{name}}`{{else}}`{{name}}`{{/if}}
|
|
108
|
+
{{/each}}
|
|
109
|
+
{{else}}
|
|
110
|
+
{{toolInventory}}
|
|
111
|
+
{{/if}}
|
|
112
|
+
{{/if}}
|
|
113
|
+
|
|
118
114
|
ENV
|
|
119
115
|
===================================
|
|
120
116
|
|
package/src/prompts/tools/ask.md
CHANGED
|
@@ -20,11 +20,3 @@ Asks user when you need clarification or input during task execution.
|
|
|
20
20
|
- **If multiple choices are acceptable**, pick the most conservative/standard option and proceed; state the choice.
|
|
21
21
|
- **Do NOT include "Other" option** — UI automatically adds "Other (type your own)" to every question.
|
|
22
22
|
</critical>
|
|
23
|
-
|
|
24
|
-
<examples>
|
|
25
|
-
# Single question
|
|
26
|
-
questions: [{"id": "auth_method", "question": "Which authentication method should this API use?", "options": [{"label": "JWT", "description": "Bearer tokens for stateless API clients."}, {"label": "OAuth2", "description": "Delegated authorization with external identity providers."}, {"label": "Session cookies", "description": "Browser-first authentication backed by server-side sessions."}], "recommended": 0}]
|
|
27
|
-
|
|
28
|
-
# Multiple questions
|
|
29
|
-
questions: [{"id": "storage_type", "question": "Which storage backend?", "options": [{"label": "SQLite"}, {"label": "PostgreSQL"}]}, {"id": "auth_method", "question": "Which auth method?", "options": [{"label": "JWT"}, {"label": "Session cookies"}]}]
|
|
30
|
-
</examples>
|
|
@@ -18,21 +18,6 @@ Performs structural AST-aware rewrites via native ast-grep.
|
|
|
18
18
|
- Parse issues when files cannot be processed
|
|
19
19
|
</output>
|
|
20
20
|
|
|
21
|
-
<examples>
|
|
22
|
-
# Rename a call site across TypeScript files
|
|
23
|
-
`{"ops":[{"pat":"oldApi($$$ARGS)","out":"newApi($$$ARGS)"}],"paths":["src/**/*.ts"]}`
|
|
24
|
-
# Delete matching calls
|
|
25
|
-
`{"ops":[{"pat":"console.log($$$ARGS)","out":""}],"paths":["src/**/*.ts"]}`
|
|
26
|
-
# Rewrite import source path
|
|
27
|
-
`{"ops":[{"pat":"import { $$$IMPORTS } from \"old-package\"","out":"import { $$$IMPORTS } from \"new-package\""}],"paths":["src/**/*.ts"]}`
|
|
28
|
-
# Modernize to optional chaining (same metavariable enforces identity)
|
|
29
|
-
`{"ops":[{"pat":"$A && $A()","out":"$A?.()"}],"paths":["src/**/*.ts"]}`
|
|
30
|
-
# Swap two arguments using captures
|
|
31
|
-
`{"ops":[{"pat":"assertEqual($A, $B)","out":"assertEqual($B, $A)"}],"paths":["tests/**/*.ts"]}`
|
|
32
|
-
# Python — convert print calls to logging
|
|
33
|
-
`{"ops":[{"pat":"print($$$ARGS)","out":"logger.info($$$ARGS)"}],"paths":["src/**/*.py"]}`
|
|
34
|
-
</examples>
|
|
35
|
-
|
|
36
21
|
<critical>
|
|
37
22
|
- Parse issues mean the rewrite is malformed or mis-scoped — fix the pattern before assuming a clean no-op
|
|
38
23
|
- For one-off local text edits, you SHOULD prefer the Edit tool
|
|
@@ -22,19 +22,6 @@ Performs structural code search using AST matching via native ast-grep.
|
|
|
22
22
|
- Summary counts (`totalMatches`, `filesWithMatches`, `filesSearched`) and parse issues when present
|
|
23
23
|
</output>
|
|
24
24
|
|
|
25
|
-
<examples>
|
|
26
|
-
# Search TypeScript files under src
|
|
27
|
-
`{"pat":"console.log($$$)","paths":["src/**/*.ts"]}`
|
|
28
|
-
# Named imports from a specific package
|
|
29
|
-
`{"pat":"import { $$$IMPORTS } from \"react\"","paths":["src/**/*.ts"]}`
|
|
30
|
-
# Arrow functions assigned to a const
|
|
31
|
-
`{"pat":"const $NAME = ($$$ARGS) => $BODY","paths":["src/utils/**/*.ts"]}`
|
|
32
|
-
# Method call on any object, ignoring method name with `$_`
|
|
33
|
-
`{"pat":"logger.$_($$$ARGS)","paths":["src/**/*.ts"]}`
|
|
34
|
-
# Loosest existence check for a symbol in one file
|
|
35
|
-
`{"pat":"processItems","paths":["src/worker.ts"]}`
|
|
36
|
-
</examples>
|
|
37
|
-
|
|
38
25
|
<critical>
|
|
39
26
|
- AVOID repo-root scans — narrow `paths` first
|
|
40
27
|
- Parse issues are query failure, not evidence of absence: repair the pattern or tighten `paths` before concluding "no matches"
|
|
@@ -37,27 +37,6 @@ Drives real Chromium tab; full puppeteer access via JS execution.
|
|
|
37
37
|
- `code` runs with full Node access. Treat as your code, not sandboxed code.
|
|
38
38
|
</critical>
|
|
39
39
|
|
|
40
|
-
<examples>
|
|
41
|
-
# Open a tab and read structured page data
|
|
42
|
-
`{"action":"open","name":"docs","url":"https://example.com"}`
|
|
43
|
-
`{"action":"run","name":"docs","code":"const obs = await tab.observe(); display(obs); return obs.elements.length;"}`
|
|
44
|
-
|
|
45
|
-
# Click an observed element by id
|
|
46
|
-
`{"action":"run","name":"docs","code":"const obs = await tab.observe(); const link = obs.elements.find(e => e.role === 'link' && e.name === 'Sign in'); assert(link, 'Sign in link missing'); await (await tab.id(link.id)).click();"}`
|
|
47
|
-
|
|
48
|
-
# Fill and submit a form via selectors
|
|
49
|
-
`{"action":"run","name":"docs","code":"await tab.fill('input[name=email]', 'me@example.com'); await tab.click('text/Continue');"}`
|
|
50
|
-
|
|
51
|
-
# Screenshot to look at the page — no save path
|
|
52
|
-
`{"action":"run","name":"docs","code":"await tab.screenshot();"}`
|
|
53
|
-
|
|
54
|
-
# Attach to an existing Electron app
|
|
55
|
-
`{"action":"open","name":"cursor","app":{"path":"/Applications/Cursor.app/Contents/MacOS/Cursor"}}`
|
|
56
|
-
|
|
57
|
-
# Close every tab and kill spawned-app processes
|
|
58
|
-
`{"action":"close","all":true,"kill":true}`
|
|
59
|
-
</examples>
|
|
60
|
-
|
|
61
40
|
<output>
|
|
62
41
|
Per call: `display(value)` outputs (text/images), then the JSON-stringified return value of `code`. `run` always produces at least a status line.
|
|
63
42
|
</output>
|
|
@@ -19,16 +19,3 @@ Use for launching or attaching debuggers, setting breakpoints, stepping through
|
|
|
19
19
|
- `program` must be an executable file or debug target, not a directory or interpreter name that resolves to a workspace directory.
|
|
20
20
|
- Python debugging requires `debugpy`; install with `pip install debugpy` if the adapter is unavailable.
|
|
21
21
|
</caution>
|
|
22
|
-
|
|
23
|
-
<examples>
|
|
24
|
-
# Launch and inspect hang
|
|
25
|
-
1. `debug(action: "launch", program: "./my_app")`
|
|
26
|
-
2. `debug(action: "set_breakpoint", file: "src/main.c", line: 42)`
|
|
27
|
-
3. `debug(action: "continue")`
|
|
28
|
-
4. If the program appears hung: `debug(action: "pause")`
|
|
29
|
-
5. Inspect state with `threads`, `stack_trace`, `scopes`, and `variables`
|
|
30
|
-
# Launch a Python script with debugpy
|
|
31
|
-
`debug(action: "launch", adapter: "debugpy", program: "scripts/job.py", args: ["--flag"])`
|
|
32
|
-
# Raw debugger command through repl
|
|
33
|
-
`debug(action: "evaluate", expression: "info registers", context: "repl")`
|
|
34
|
-
</examples>
|
|
@@ -58,12 +58,3 @@ budget → per-turn token budget
|
|
|
58
58
|
{{#if py}}`budget.total` (ceiling or None), `budget.spent()`, `budget.remaining()` (math.inf when no ceiling), `budget.hard` (bool).{{/if}}{{#if js}}`await budget.total()` (ceiling or null), `await budget.spent()`, `await budget.remaining()` (Infinity when no ceiling), `await budget.hard()`.{{/if}} Ceiling comes from a `+Nk` directive (advisory) or `+Nk!`/Goal Mode (hard — `agent()` refuses to spawn past it); otherwise None/null, spend still tracked across the turn.
|
|
59
59
|
```
|
|
60
60
|
</prelude>
|
|
61
|
-
|
|
62
|
-
<example>
|
|
63
|
-
{
|
|
64
|
-
"cells": [
|
|
65
|
-
{ "language": "py", "title": "imports", "timeout": 10, "code": "import json\nfrom pathlib import Path" },
|
|
66
|
-
{ "language": "py", "title": "load config", "code": "data = json.loads(read('package.json'))\ndisplay(data)" }
|
|
67
|
-
]
|
|
68
|
-
}
|
|
69
|
-
</example>
|
|
@@ -14,19 +14,6 @@ Finds files and directories using fast pattern matching that works with any code
|
|
|
14
14
|
Matching file and directory paths sorted by modification time (most recent first), grouped by directory to reduce token usage. Each group starts with `# <dir>/` followed by basenames (one per line); directory entries get a trailing `/`. Root-level entries have no header. Truncated at 200 entries or 50KB.
|
|
15
15
|
</output>
|
|
16
16
|
|
|
17
|
-
<examples>
|
|
18
|
-
# Find files
|
|
19
|
-
`{"paths": ["src/**/*.ts"]}`
|
|
20
|
-
# Multiple targets — separate array elements
|
|
21
|
-
`{"paths": ["src/**/*.ts", "test/**/*.ts"]}`
|
|
22
|
-
# Find gitignored files like .env
|
|
23
|
-
`{"paths": [".env*"], "gitignore": false}`
|
|
24
|
-
# Find directories matching a name (returns both files and dirs; directories are suffixed with `/`)
|
|
25
|
-
`{"paths": ["**/tests"]}`
|
|
26
|
-
# Long-running search on a slow volume
|
|
27
|
-
`{"paths": ["/Volumes/Storage/**/*.py"], "timeout": 30}`
|
|
28
|
-
</examples>
|
|
29
|
-
|
|
30
17
|
<avoid>
|
|
31
18
|
For open-ended searches requiring multiple rounds of globbing and searching, you MUST use Task tool instead.
|
|
32
19
|
</avoid>
|
|
@@ -11,15 +11,6 @@ Inspects an image file with a vision-capable model and returns compact text anal
|
|
|
11
11
|
- Use this tool over `read` when the goal is image analysis
|
|
12
12
|
</instruction>
|
|
13
13
|
|
|
14
|
-
<examples>
|
|
15
|
-
# OCR with strict formatting
|
|
16
|
-
`{"path":"screenshots/error.png","question":"Extract all visible text verbatim. Return as bullet list in reading order."}`
|
|
17
|
-
# Screenshot debugging
|
|
18
|
-
`{"path":"screenshots/settings.png","question":"Identify the likely cause of the disabled Save button. Return: (1) observations, (2) likely cause, (3) confidence."}`
|
|
19
|
-
# Scene/object question
|
|
20
|
-
`{"path":"photos/shelf.jpg","question":"List all clearly visible product labels and their shelf positions (top/middle/bottom). If unreadable, say unreadable."}`
|
|
21
|
-
</examples>
|
|
22
|
-
|
|
23
14
|
<output>
|
|
24
15
|
- Returns text-only analysis from the vision model
|
|
25
16
|
- No image content blocks are returned in tool output
|
package/src/prompts/tools/irc.md
CHANGED
|
@@ -40,18 +40,3 @@ Applies to sending and replying.
|
|
|
40
40
|
- `inbox`: pending messages, oldest first.
|
|
41
41
|
- `list`: peers with status, unread count, parent, last activity.
|
|
42
42
|
</output>
|
|
43
|
-
|
|
44
|
-
<examples>
|
|
45
|
-
# List peers
|
|
46
|
-
`{"op": "list"}`
|
|
47
|
-
# Fire-and-forget DM — same send wakes idle/parked peers
|
|
48
|
-
`{"op": "send", "to": "AuthLoader", "message": "Still touching src/server/auth.ts? I need to add a 401 path."}`
|
|
49
|
-
# Round-trip when you cannot proceed without the answer
|
|
50
|
-
`{"op": "send", "to": "Main", "message": "JWT or session cookies for the auth flow?", "await": true}`
|
|
51
|
-
# Block until a specific peer answers
|
|
52
|
-
`{"op": "wait", "from": "AuthLoader", "timeoutMs": 60000}`
|
|
53
|
-
# Drain pending messages
|
|
54
|
-
`{"op": "inbox"}`
|
|
55
|
-
# Broadcast to live peers (no replies expected)
|
|
56
|
-
`{"op": "send", "to": "all", "message": "About to refactor src/server/middleware/*. Anyone already in there?"}`
|
|
57
|
-
</examples>
|
|
@@ -50,19 +50,6 @@ Returns success/failure; on failure, error message indicates:
|
|
|
50
50
|
- NEVER use edit to fix indentation, whitespace, or reformat code. Formatting is a single command run once at the end (`bun fmt`, `cargo fmt`, `prettier --write`, etc.) — not N individual edits. If you see inconsistent indentation after an edit, leave it; the formatter will fix all of it in one pass.
|
|
51
51
|
</critical>
|
|
52
52
|
|
|
53
|
-
<examples>
|
|
54
|
-
# Create
|
|
55
|
-
`edit {"path":"hello.txt","edits":[{"op":"create","diff":"Hello\n"}]}`
|
|
56
|
-
# Update
|
|
57
|
-
`edit {"path":"src/app.py","edits":[{"op":"update","diff":"@@ def greet():\n def greet():\n-print('Hi')\n+print('Hello')\n"}]}`
|
|
58
|
-
# Rename
|
|
59
|
-
`edit {"path":"src/app.py","edits":[{"op":"update","rename":"src/main.py","diff":"@@\n …\n"}]}`
|
|
60
|
-
# Delete
|
|
61
|
-
`edit {"path":"obsolete.txt","edits":[{"op":"delete"}]}`
|
|
62
|
-
# Multiple entries
|
|
63
|
-
All entries in one call apply to the top-level `path`; use separate calls for different files.
|
|
64
|
-
</examples>
|
|
65
|
-
|
|
66
53
|
<avoid>
|
|
67
54
|
- Generic anchors: `import`, `export`, `describe`, `function`, `const`
|
|
68
55
|
- Repeating same addition in multiple hunks (duplicate blocks)
|
package/src/prompts/tools/ssh.md
CHANGED
|
@@ -20,12 +20,3 @@ Runs commands on remote hosts.
|
|
|
20
20
|
<critical>
|
|
21
21
|
You MUST verify the shell type from "Available hosts" and use matching commands.
|
|
22
22
|
</critical>
|
|
23
|
-
|
|
24
|
-
<examples>
|
|
25
|
-
# List files: Linux
|
|
26
|
-
Host: server1 (10.0.0.1) | linux/bash. Command: `ls -la /home/user`
|
|
27
|
-
# Show running processes: Windows cmd
|
|
28
|
-
Host: winbox (192.168.1.5) | windows/cmd. Command: `tasklist /v`
|
|
29
|
-
# Get system info: macOS
|
|
30
|
-
Host: macbook (10.0.0.20) | macos/zsh. Command: `uname -a && sw_vers`
|
|
31
|
-
</examples>
|
|
@@ -9,6 +9,7 @@ Allowed `op` values are only `init`, `start`, `done`, `drop`, `rm`, `append`, an
|
|
|
9
9
|
|`op`|Required fields|Effect|
|
|
10
10
|
|---|---|---|
|
|
11
11
|
|`init`|`list: [{phase, items: string[]}]`|Initialize the full list (replaces any existing list)|
|
|
12
|
+
|`init`|`items: string[]`|Flattened single-phase init|
|
|
12
13
|
|`start`|`task`|Mark in progress|
|
|
13
14
|
|`done`|`task` or `phase`|Mark completed|
|
|
14
15
|
|`drop`|`task` or `phase`|Mark abandoned|
|
|
@@ -33,25 +34,6 @@ Allowed `op` values are only `init`, `start`, `done`, `drop`, `rm`, `append`, an
|
|
|
33
34
|
- User provides a set of tasks to complete
|
|
34
35
|
- New instructions arrive mid-task — capture before proceeding
|
|
35
36
|
|
|
36
|
-
<examples>
|
|
37
|
-
# Initial setup (multi-phase)
|
|
38
|
-
`{"ops":[{"op":"init","list":[{"phase":"Foundation","items":["Scaffold crate","Wire workspace"]},{"phase":"Auth","items":["Port credential store","Wire OAuth providers"]},{"phase":"Verification","items":["Run cargo test"]}]}]}`
|
|
39
|
-
# View current state (read-only)
|
|
40
|
-
`{"ops":[{"op":"view"}]}`
|
|
41
|
-
# Initial setup (single phase)
|
|
42
|
-
`{"ops":[{"op":"init","list":[{"phase":"Implementation","items":["Apply fix","Run tests"]}]}]}`
|
|
43
|
-
# Complete one task
|
|
44
|
-
`{"ops":[{"op":"done","task":"Wire workspace"}]}`
|
|
45
|
-
# Complete a whole phase
|
|
46
|
-
`{"ops":[{"op":"done","phase":"Auth"}]}`
|
|
47
|
-
# Remove all tasks
|
|
48
|
-
`{"ops":[{"op":"rm"}]}`
|
|
49
|
-
# Drop one task
|
|
50
|
-
`{"ops":[{"op":"drop","task":"Run cargo test"}]}`
|
|
51
|
-
# Append tasks to a phase
|
|
52
|
-
`{"ops":[{"op":"append","phase":"Auth","items":["Handle retries","Run tests"]}]}`
|
|
53
|
-
</examples>
|
|
54
|
-
|
|
55
37
|
<critical>
|
|
56
38
|
When the user hands you a multi-step plan — a phased todo, a numbered or bulleted checklist, or "N bugs/items/tasks" to work through:
|
|
57
39
|
- You MUST `init` the list with EVERY item as its own task before doing the work.
|
package/src/sdk.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
type SimpleStreamOptions,
|
|
17
17
|
streamSimple,
|
|
18
18
|
} from "@oh-my-pi/pi-ai";
|
|
19
|
+
import type { ToolCallSyntax } from "@oh-my-pi/pi-ai/grammar";
|
|
19
20
|
import {
|
|
20
21
|
getOpenAICodexTransportDetails,
|
|
21
22
|
prewarmOpenAICodexResponses,
|
|
@@ -550,6 +551,17 @@ export interface CreateAgentSessionResult {
|
|
|
550
551
|
eventBus: EventBus;
|
|
551
552
|
}
|
|
552
553
|
|
|
554
|
+
export type ToolCallFormat = "auto" | "native" | ToolCallSyntax;
|
|
555
|
+
|
|
556
|
+
export function resolveToolCallSyntax(
|
|
557
|
+
format: ToolCallFormat,
|
|
558
|
+
model: Pick<Model, "supportsTools"> | undefined,
|
|
559
|
+
): ToolCallSyntax | undefined {
|
|
560
|
+
if (format === "native") return undefined;
|
|
561
|
+
if (format === "auto") return model?.supportsTools === false ? "glm" : undefined;
|
|
562
|
+
return format;
|
|
563
|
+
}
|
|
564
|
+
|
|
553
565
|
// Re-exports
|
|
554
566
|
|
|
555
567
|
export type { PromptTemplate } from "./config/prompt-templates";
|
|
@@ -2149,6 +2161,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2149
2161
|
}
|
|
2150
2162
|
appendPrompt = parts.join("\n\n");
|
|
2151
2163
|
}
|
|
2164
|
+
// Owned/in-band tool syntax (non-native) repeats the catalog as `# Tool:`
|
|
2165
|
+
// sections; native tool calling lets the compact name list suffice.
|
|
2166
|
+
const nativeTools =
|
|
2167
|
+
resolveToolCallSyntax(settings.get("tools.format"), agent?.state.model ?? model) === undefined;
|
|
2152
2168
|
const defaultPrompt = await buildSystemPromptInternal({
|
|
2153
2169
|
cwd,
|
|
2154
2170
|
skills,
|
|
@@ -2160,6 +2176,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2160
2176
|
skillsSettings: settings.getGroup("skills"),
|
|
2161
2177
|
appendSystemPrompt: appendPrompt,
|
|
2162
2178
|
repeatToolDescriptions,
|
|
2179
|
+
nativeTools,
|
|
2163
2180
|
intentField,
|
|
2164
2181
|
mcpDiscoveryMode: hasDiscoverableTools,
|
|
2165
2182
|
mcpDiscoveryServerSummaries: discoverableToolSummary.servers.map(formatDiscoverableToolServerSummary),
|
|
@@ -2489,6 +2506,8 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2489
2506
|
return result;
|
|
2490
2507
|
},
|
|
2491
2508
|
intentTracing: !!intentField,
|
|
2509
|
+
toolCallSyntax: resolveToolCallSyntax(settings.get("tools.format"), model),
|
|
2510
|
+
abortOnFabricatedToolResult: settings.get("tools.abortOnFabricatedResult"),
|
|
2492
2511
|
getToolChoice: () => session?.nextToolChoice(),
|
|
2493
2512
|
telemetry: options.telemetry,
|
|
2494
2513
|
appendOnlyContext: model
|