@oh-my-pi/pi-coding-agent 15.0.0 → 15.0.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.
Files changed (165) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/examples/extensions/plan-mode.ts +0 -1
  3. package/package.json +10 -10
  4. package/scripts/build-binary.ts +5 -0
  5. package/src/autoresearch/helpers.ts +17 -0
  6. package/src/autoresearch/tools/log-experiment.ts +9 -17
  7. package/src/autoresearch/tools/run-experiment.ts +2 -17
  8. package/src/capability/skill.ts +7 -0
  9. package/src/cli/list-models.ts +1 -1
  10. package/src/cli/shell-cli.ts +3 -13
  11. package/src/cli/update-cli.ts +1 -1
  12. package/src/cli.ts +10 -29
  13. package/src/commands/commit.ts +10 -0
  14. package/src/commit/agentic/tools/propose-changelog.ts +8 -1
  15. package/src/commit/analysis/conventional.ts +8 -66
  16. package/src/commit/map-reduce/reduce-phase.ts +6 -65
  17. package/src/commit/pipeline.ts +2 -2
  18. package/src/commit/shared-llm.ts +89 -0
  19. package/src/config/config-file.ts +210 -0
  20. package/src/config/model-equivalence.ts +8 -11
  21. package/src/config/model-registry.ts +44 -3
  22. package/src/config/model-resolver.ts +1 -4
  23. package/src/config/settings-schema.ts +82 -1
  24. package/src/config/settings.ts +1 -1
  25. package/src/config.ts +3 -219
  26. package/src/discovery/claude-plugins.ts +19 -7
  27. package/src/edit/renderer.ts +7 -1
  28. package/src/eval/js/executor.ts +3 -0
  29. package/src/eval/js/shared/rewrite-imports.ts +2 -2
  30. package/src/eval/py/executor.ts +5 -0
  31. package/src/eval/py/runner.py +42 -11
  32. package/src/eval/py/runtime.ts +1 -0
  33. package/src/exa/factory.ts +2 -2
  34. package/src/exa/mcp-client.ts +74 -1
  35. package/src/exec/bash-executor.ts +5 -1
  36. package/src/export/html/template.generated.ts +1 -1
  37. package/src/export/html/template.js +0 -11
  38. package/src/extensibility/extensions/get-commands-handler.ts +77 -0
  39. package/src/extensibility/extensions/runner.ts +1 -1
  40. package/src/extensibility/extensions/types.ts +89 -223
  41. package/src/extensibility/hooks/types.ts +89 -314
  42. package/src/extensibility/plugins/legacy-pi-compat.ts +48 -31
  43. package/src/extensibility/shared-events.ts +343 -0
  44. package/src/extensibility/skills.ts +9 -0
  45. package/src/goals/index.ts +3 -0
  46. package/src/goals/runtime.ts +500 -0
  47. package/src/goals/state.ts +37 -0
  48. package/src/goals/tools/goal-tool.ts +237 -0
  49. package/src/hashline/anchors.ts +2 -2
  50. package/src/hashline/input.ts +2 -1
  51. package/src/hashline/parser.ts +27 -3
  52. package/src/hindsight/mental-models.ts +1 -1
  53. package/src/internal-urls/agent-protocol.ts +1 -20
  54. package/src/internal-urls/artifact-protocol.ts +1 -19
  55. package/src/internal-urls/docs-index.generated.ts +11 -12
  56. package/src/internal-urls/registry-helpers.ts +25 -0
  57. package/src/internal-urls/router.ts +8 -0
  58. package/src/internal-urls/types.ts +21 -0
  59. package/src/lsp/config.ts +15 -6
  60. package/src/lsp/defaults.json +6 -2
  61. package/src/main.ts +11 -2
  62. package/src/mcp/oauth-flow.ts +20 -0
  63. package/src/modes/acp/acp-agent.ts +327 -95
  64. package/src/modes/components/assistant-message.ts +14 -8
  65. package/src/modes/components/bash-execution.ts +24 -63
  66. package/src/modes/components/custom-message.ts +14 -40
  67. package/src/modes/components/eval-execution.ts +27 -57
  68. package/src/modes/components/execution-shared.ts +102 -0
  69. package/src/modes/components/hook-message.ts +17 -49
  70. package/src/modes/components/mcp-add-wizard.ts +26 -5
  71. package/src/modes/components/message-frame.ts +88 -0
  72. package/src/modes/components/model-selector.ts +1 -1
  73. package/src/modes/components/session-observer-overlay.ts +6 -2
  74. package/src/modes/components/session-selector.ts +1 -1
  75. package/src/modes/components/status-line/segments.ts +93 -8
  76. package/src/modes/components/status-line/types.ts +4 -0
  77. package/src/modes/components/status-line.ts +28 -10
  78. package/src/modes/components/tool-execution.ts +7 -8
  79. package/src/modes/controllers/command-controller-shared.ts +108 -0
  80. package/src/modes/controllers/command-controller.ts +13 -4
  81. package/src/modes/controllers/event-controller.ts +36 -7
  82. package/src/modes/controllers/extension-ui-controller.ts +3 -2
  83. package/src/modes/controllers/input-controller.ts +13 -0
  84. package/src/modes/controllers/mcp-command-controller.ts +56 -61
  85. package/src/modes/controllers/ssh-command-controller.ts +18 -57
  86. package/src/modes/interactive-mode.ts +624 -52
  87. package/src/modes/print-mode.ts +16 -86
  88. package/src/modes/rpc/host-uris.ts +235 -0
  89. package/src/modes/rpc/rpc-mode.ts +41 -88
  90. package/src/modes/rpc/rpc-types.ts +57 -0
  91. package/src/modes/runtime-init.ts +116 -0
  92. package/src/modes/theme/defaults/dark-poimandres.json +3 -0
  93. package/src/modes/theme/defaults/light-poimandres.json +3 -0
  94. package/src/modes/theme/theme.ts +24 -6
  95. package/src/modes/types.ts +14 -3
  96. package/src/modes/utils/context-usage.ts +13 -13
  97. package/src/modes/utils/ui-helpers.ts +10 -3
  98. package/src/plan-mode/approved-plan.ts +35 -1
  99. package/src/prompts/goals/goal-budget-limit.md +16 -0
  100. package/src/prompts/goals/goal-continuation.md +28 -0
  101. package/src/prompts/goals/goal-mode-active.md +23 -0
  102. package/src/prompts/system/plan-mode-active.md +5 -5
  103. package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
  104. package/src/prompts/tools/bash.md +6 -0
  105. package/src/prompts/tools/github.md +4 -4
  106. package/src/prompts/tools/goal.md +13 -0
  107. package/src/prompts/tools/hashline.md +101 -117
  108. package/src/prompts/tools/read.md +55 -36
  109. package/src/prompts/tools/resolve.md +6 -5
  110. package/src/sdk.ts +12 -5
  111. package/src/session/agent-session.ts +428 -106
  112. package/src/session/blob-store.ts +36 -3
  113. package/src/session/messages.ts +67 -2
  114. package/src/session/session-manager.ts +131 -12
  115. package/src/session/session-storage.ts +33 -15
  116. package/src/session/streaming-output.ts +309 -13
  117. package/src/slash-commands/builtin-registry.ts +18 -0
  118. package/src/ssh/ssh-executor.ts +5 -0
  119. package/src/system-prompt.ts +4 -2
  120. package/src/task/discovery.ts +5 -2
  121. package/src/task/executor.ts +19 -8
  122. package/src/task/index.ts +3 -0
  123. package/src/task/render.ts +21 -15
  124. package/src/task/types.ts +4 -0
  125. package/src/tools/ast-edit.ts +21 -120
  126. package/src/tools/ast-grep.ts +21 -119
  127. package/src/tools/bash-command-fixup.ts +47 -0
  128. package/src/tools/bash-interactive.ts +9 -1
  129. package/src/tools/bash.ts +66 -19
  130. package/src/tools/browser/attach.ts +3 -3
  131. package/src/tools/browser/launch.ts +81 -18
  132. package/src/tools/browser/registry.ts +1 -5
  133. package/src/tools/browser/render.ts +2 -2
  134. package/src/tools/browser/tab-supervisor.ts +51 -14
  135. package/src/tools/conflict-detect.ts +15 -4
  136. package/src/tools/eval.ts +12 -2
  137. package/src/tools/find.ts +20 -38
  138. package/src/tools/gh.ts +44 -10
  139. package/src/tools/index.ts +22 -11
  140. package/src/tools/inspect-image.ts +3 -10
  141. package/src/tools/job.ts +16 -7
  142. package/src/tools/output-meta.ts +202 -37
  143. package/src/tools/path-utils.ts +125 -2
  144. package/src/tools/read.ts +548 -237
  145. package/src/tools/render-utils.ts +92 -0
  146. package/src/tools/renderers.ts +2 -0
  147. package/src/tools/resolve.ts +72 -44
  148. package/src/tools/search.ts +120 -186
  149. package/src/tools/ssh.ts +3 -2
  150. package/src/tools/write.ts +64 -9
  151. package/src/utils/file-mentions.ts +1 -1
  152. package/src/utils/image-loading.ts +7 -3
  153. package/src/utils/image-resize.ts +32 -43
  154. package/src/vim/parser.ts +0 -17
  155. package/src/vim/render.ts +1 -1
  156. package/src/vim/types.ts +1 -1
  157. package/src/web/search/providers/anthropic.ts +5 -0
  158. package/src/web/search/providers/exa.ts +3 -0
  159. package/src/web/search/providers/gemini.ts +40 -95
  160. package/src/web/search/providers/jina.ts +5 -2
  161. package/src/web/search/providers/zai.ts +5 -2
  162. package/src/prompts/tools/exit-plan-mode.md +0 -6
  163. package/src/tools/exit-plan-mode.ts +0 -97
  164. package/src/utils/fuzzy.ts +0 -108
  165. package/src/utils/image-convert.ts +0 -27
@@ -4,159 +4,143 @@ A patch contains one or more file sections. The first non-blank line of every ed
4
4
  Operations reference lines in the file by their line number and hash, called "Anchors", e.g. `5th`, `123ab`.
5
5
  You MUST copy them verbatim from the latest output for the file you're editing.
6
6
 
7
- Purely textual format. The tool has NO awareness of language, indentation, brackets, fences, or table widths. Emit valid syntax in replacements/insertions.
7
+ Purely textual format. The tool has NO awareness of language, indentation, brackets, fences, or table widths. You MUST emit valid syntax in replacements/insertions.
8
8
 
9
9
  <ops>
10
10
  @@ PATH header: subsequent ops apply to PATH
11
+ Each op line is ONE of:
11
12
  + ANCHOR insert lines AFTER the anchored line (or EOF); payload follows as `{{hsep}}TEXT` lines
12
13
  < ANCHOR insert lines BEFORE the anchored line (or BOF); payload follows as `{{hsep}}TEXT` lines
13
14
  - A..B delete the line range (inclusive).
14
15
  = A..B replace the range with payload `{{hsep}}TEXT` lines, or with one blank line if no payload follows.
15
16
  </ops>
16
17
 
18
+ <format-reminder>
19
+ Op lines carry no content — payload goes on the next line.
20
+
21
+ WRONG: + 5pg| some code
22
+ RIGHT: + 5pg
23
+ {{hsep}} some code
24
+
25
+ A single `+`/`<`/`=` op accepts MANY `{{hsep}}` payload lines. To insert N consecutive lines, write ONE op followed by N payload lines — NEVER N ops with one payload each.
26
+
27
+ WRONG (one op per inserted line, with fabricated anchors):
28
+ + 5pg
29
+ {{hsep}}first new line
30
+ + 6xx ← FABRICATED
31
+ {{hsep}}second new line
32
+
33
+ RIGHT (one op, many payload lines):
34
+ + 5pg
35
+ {{hsep}}first new line
36
+ {{hsep}}second new line
37
+ </format-reminder>
38
+
17
39
  <rules>
18
- - Every line of inserted/replacement content MUST be emitted as a payload line starting with `{{hsep}}`.
19
- - `{{hsep}}` is syntax, not content. The inserted text begins after the first `{{hsep}}`; use a bare `{{hsep}}` to insert a blank line.
20
- - Payload is verbatim — don't escape unicode (write `—`, not `\u2014`).
21
- - `< A` inserts before line A; `+ A` inserts after line A. `< BOF` / `+ BOF` both prepend; `< EOF` / `+ EOF` both append.
22
- - `= A..B` replaces the inclusive range with the following payload lines. `= A..B` with no payload blanks the range to a single empty line.
23
- - `- A..B` deletes the inclusive range; `A..A` for one line.
24
- - **Choose a self-contained syntactic unit first.** If the change touches part of a multiline call, destructuring assignment, control-flow header, wrapper, or other construct, widen the range to include the whole construct before optimizing for size.
25
- - Only after the range is self-contained, pick the smallest op for the change: pure addition → `+`/`<`; pure deletion → `-`; `= A..B` ONLY when content inside `A..B` is actually being modified or removed.
40
+ - Every payload line MUST start with `{{hsep}}`.
41
+ - Payload is verbatim NEVER escape unicode.
42
+ - **Payload is only what's NEW relative to your range:**
43
+ - `=` replaces inside; NEVER include lines outside.
44
+ - `+`/`<` adds at the anchor; NEVER repeat line A or neighbors.
45
+ - Payload matching nearby content duplicates drop it or widen.
46
+ - **Pick a self-contained unit first.** Touching a multiline construct? Widen to the whole thing.
47
+ - Then smallest op: add → `+`/`<`; delete → `-`; `=` ONLY when modifying inside.
26
48
  </rules>
27
49
 
28
50
  <brace-shapes>
29
- When your edit involves brace boundaries (`{` / `}`), prefer these shapes:
30
- - **Whole block replace/delete**: pick the range so it spans both halves of the brace pair — start on the line that ends with `{`, end on the matching `}`. For pure removal use `-` with empty payload; for replacement, the payload's first line ends with `{` and last line is the matching `}`.
31
- - **Signature-only edit**: if you are only changing the line that ends with `{` (function signature, control statement, etc.), use a one-line `=` on that opener; the body and matching `}` are untouched and stay outside the range.
32
- - **Insert inside a block**: anchor on the opener (`+ ANCHOR` after the `{` line) or just above the closer (`+ ANCHOR` after the last interior line); emit only the new interior lines. Do not include the surrounding `{` or `}` in the payload — they're already there.
33
- - **Range ending on `}`**: only end on `}` when that `}` is itself part of what you're changing. The line at B+1 should be blank, an opener (next block), or a signature — not another `}`. Otherwise extend B past the closer or stop one line earlier.
51
+ When braces bound your edit, you SHOULD prefer these shapes:
52
+ - **Whole block**: range spans `{` through matching `}`.
53
+ - **Signature only**: one-line `=` on the opener; body untouched.
54
+ - **Insert inside**: anchor on `{` or last interior line; NEVER repeat the braces.
55
+ - **End on `}`**: only when that `}` is part of the change. Otherwise extend or stop earlier.
34
56
  </brace-shapes>
35
57
 
36
58
  <common-failures>
37
- - **Do not replay the line past your range.** For `= A..B`, never end the payload with content that already exists at B+1. Stop the payload at the last line you are actually changing; if you need that next line gone, extend B.
38
- - **Do not duplicate chunks inside one payload.** When emitting a long `=` payload, never paste the same multi-line block twice. If you catch yourself re-emitting an earlier run of lines, stop and rewrite the op.
39
- - **Anchor only inside the visible region.** If the read output around your `=`/`-` end anchor is truncated (you cannot see the line at B+1), issue a fresh `read` before editing — anchoring blind drops or duplicates the boundary line.
40
- - **Prefer the narrowest self-contained edit.** Once your range cleanly contains the construct you are changing, a `+`/`<` insert plus a small `-` delete is almost always clearer and safer than a single wide `= A..B` that re-emits unchanged context.
41
- - **Anchors always reference the file as you last read it.** When stacking multiple `+`/`<`/`-`/`=` ops in one patch, NEVER mentally shift line numbers to account for prior ops in the same patch. Every op resolves against the original line numbering.
59
+ - **NEVER replay past your range.** Stop before B+1; extend B if it must go.
60
+ - **NEVER duplicate chunks inside one payload.** Caught re-emitting? Rewrite.
61
+ - **Anchor only inside the visible region.** B+1 truncated? Re-`read` first.
62
+ - **You SHOULD prefer the narrowest self-contained edit.** Small `+`/`-` beats wide `=`.
63
+ - **Anchors reference the file as last read.** NEVER shift for prior ops.
64
+ - **One `+`/`<` op per block, NOT per line.** N lines = ONE op, N payloads. Collapse adjacent ops.
65
+ - **NEVER fabricate anchor hashes.** Missing? Re-`read`.
42
66
  </common-failures>
43
67
 
44
- <case file="a.ts">
45
- {{hline 1 "const DEF = \"guest\";"}}
46
- {{hline 2 ""}}
47
- {{hline 3 "export function label(name) {"}}
48
- {{hline 4 "\tconst clean = name || DEF;"}}
49
- {{hline 5 "\treturn clean.trim();"}}
50
- {{hline 6 "}"}}
51
- </case>
52
-
53
- <case file="b.ts">
54
- {{hline 1 "const {"}}
55
- {{hline 2 "\tevents,"}}
56
- {{hline 3 "\tresponse,"}}
57
- {{hline 4 "\trequestId,"}}
58
- {{hline 5 "} = await getStreamResponse("}}
59
- {{hline 6 "\trequest,"}}
60
- {{hline 7 "\tsignal,"}}
61
- {{hline 8 ");"}}
62
- {{hline 9 "await notify(requestId);"}}
68
+ <case file="mod.ts">
69
+ {{hline 1 "const TITLE = \"Mr\";"}}
70
+ {{hline 2 "export function greet(name) {"}}
71
+ {{hline 3 "\treturn ["}}
72
+ {{hline 4 "\t\tTITLE,"}}
73
+ {{hline 5 "\t\tname?.trim() || \"guest\","}}
74
+ {{hline 6 "\t].join(\" \");"}}
75
+ {{hline 7 "}"}}
63
76
  </case>
64
77
 
65
78
  <examples>
66
- # Replace one line (preserve the leading tab from the original)
67
- @@ a.ts
68
- = {{hrefr 5}}..{{hrefr 5}}
69
- {{hsep}} return clean.trim().toUpperCase();
70
-
71
- # Replace a contiguous range with multiple lines
72
- @@ a.ts
73
- = {{hrefr 4}}..{{hrefr 5}}
74
- {{hsep}} const clean = (name || DEF).trim();
75
- {{hsep}} return clean.length === 0 ? DEF : clean.toUpperCase();
76
-
77
- # Replace a full multiline destructuring/call statement
78
- @@ b.ts
79
- = {{hrefr 1}}..{{hrefr 8}}
80
- {{hsep}}const {
81
- {{hsep}} events,
82
- {{hsep}} response,
83
- {{hsep}} requestId,
84
- {{hsep}}} = await getStreamResponse(
85
- {{hsep}} request,
86
- {{hsep}} signal,
87
- {{hsep}} onEvent,
88
- {{hsep}});
89
-
90
- # Insert BEFORE a line
91
- @@ a.ts
92
- < {{hrefr 5}}
93
- {{hsep}} const debug = false;
94
-
95
- # Insert AFTER a line
96
- @@ a.ts
79
+ # Replace one line (the payload must re-emit the original indentation)
80
+ @@ mod.ts
81
+ = {{hrefr 1}}..{{hrefr 1}}
82
+ {{hsep}}const TITLE = "Mrs";
83
+
84
+ # Replace a full multiline statement (widen to a self-contained boundary)
85
+ @@ mod.ts
86
+ = {{hrefr 3}}..{{hrefr 6}}
87
+ {{hsep}} return [
88
+ {{hsep}} "Mrs",
89
+ {{hsep}} name?.trim() || "guest",
90
+ {{hsep}} ].join(" ");
91
+
92
+ # Insert AFTER/BEFORE a line
93
+ @@ mod.ts
97
94
  + {{hrefr 4}}
98
- {{hsep}} if (clean.length === 0) return DEF;
95
+ {{hsep}} "Dr",
96
+ < {{hrefr 5}}
97
+ {{hsep}} "Dr",
99
98
 
100
- # Append to end of file
101
- @@ a.ts
99
+ # Append to file
100
+ @@ mod.ts
102
101
  + EOF
103
102
  {{hsep}}export const done = true;
104
103
 
105
- # Delete a single line
106
- @@ a.ts
107
- - {{hrefr 2}}..{{hrefr 2}}
104
+ # Delete a line
105
+ @@ mod.ts
106
+ - {{hrefr 5}}..{{hrefr 5}}
108
107
 
109
- # Blank a line in place (no payload required)
110
- @@ a.ts
111
- = {{hrefr 2}}..{{hrefr 2}}
108
+ # Blank a line (replace with LF)
109
+ @@ mod.ts
110
+ = {{hrefr 5}}..{{hrefr 5}}
112
111
  </examples>
113
112
 
114
113
  <anti-pattern>
115
- # WRONG — replaces 5 lines just to add one. Use `+` at the boundary instead.
116
- @@ a.ts
117
- = {{hrefr 1}}..{{hrefr 5}}
118
- {{hsep}}const DEF = "guest";
114
+ # WRONG — replaces 2 lines just to add one.
115
+ @@ mod.ts
116
+ = {{hrefr 1}}..{{hrefr 2}}
117
+ {{hsep}}const TITLE = "Mr";
119
118
  {{hsep}}const DEBUG = false;
120
- {{hsep}}
121
- {{hsep}}export function label(name) {
122
- {{hsep}} const clean = name || DEF;
123
- {{hsep}} return clean.trim();
124
-
119
+ {{hsep}}export function greet(name) {
125
120
  # RIGHT — same effect, one-line insert
126
- @@ a.ts
121
+ @@ mod.ts
127
122
  + {{hrefr 1}}
128
123
  {{hsep}}const DEBUG = false;
129
124
 
130
- # WRONG — continuation-fragment payload from the middle of a larger statement.
131
- @@ b.ts
132
- = {{hrefr 5}}..{{hrefr 7}}
133
- {{hsep}}} = await getStreamResponse(
134
- {{hsep}} request,
135
- {{hsep}} signal,
136
- {{hsep}} onEvent,
137
-
138
- # RIGHT — widen to the full statement so the payload starts at a self-contained boundary.
139
- @@ b.ts
140
- = {{hrefr 1}}..{{hrefr 8}}
141
- {{hsep}}const {
142
- {{hsep}} events,
143
- {{hsep}} response,
144
- {{hsep}} requestId,
145
- {{hsep}}} = await getStreamResponse(
146
- {{hsep}} request,
147
- {{hsep}} signal,
148
- {{hsep}} onEvent,
149
- {{hsep}});
150
-
151
- If your replacement payload would render with even one unchanged line in the diff, or if the first or last payload line is only a continuation fragment from a larger construct (`} =`, `);`, `,`, `.method(`), you have the wrong op or range. Stop and widen to a self-contained boundary before minimizing the edit.
125
+ # WRONG — replace from the middle of a larger statement (error-prone)
126
+ @@ mod.ts
127
+ = {{hrefr 4}}..{{hrefr 5}}
128
+ {{hsep}} "Dr",
129
+ {{hsep}} name?.trim() || "guest",
130
+ # RIGHT — widen to the full statement
131
+ @@ mod.ts
132
+ = {{hrefr 3}}..{{hrefr 6}}
133
+ {{hsep}} return [
134
+ {{hsep}} "Dr",
135
+ {{hsep}} name?.trim() || "guest",
136
+ {{hsep}} ].join(" ");
152
137
  </anti-pattern>
153
138
 
154
139
  <critical>
155
- - Always copy anchors exactly from tool output, but NEVER include line content after the `{{hsep}}` separator in the op line.
156
- - Every inserted/replacement content line MUST start with `{{hsep}}`; raw content lines are invalid.
157
- - Do not write unified diff syntax (`@@ -X,Y +X,Y @@`, `-OLD`, `+NEW`). The header is `@@ PATH`; line ops are `<`/`+`/`-`/`=`.
158
- - `= A..B` deletes the range; payload is what's written. If a payload edge line already exists immediately outside `A..B`, widen the range to cover it — otherwise it duplicates.
159
- - Multiple ops in one patch are cheap. Prefer two narrow ops over one wide `=`.
160
- - Before choosing a `= A..B` range, mentally delete lines A through B. If that would split an unclosed bracket, paren, brace, or string/template from a line above A, or orphan a closing delimiter that belongs to an opener inside the range, you are bisecting a syntactic construct. Widen the range to a self-contained boundary, or use `+`/`-` instead.
161
- - `= A..B` removes the range as a unit; the lines immediately outside it remain. If those outside lines form a wrapper (`try {`, `catch`, `if`, `else`, loop delimiters) you do not intend to delete, your payload is inserted inside that wrapper. Make sure the payload remains valid and preserves required behavior like error handling. If you need to change the wrapper itself, include it in the range and reproduce it.
140
+ - Copy anchors verbatim (line number + 2-char hash); NEVER include the `|TEXT` body.
141
+ - Every payload line MUST start with `{{hsep}}`; raw content is invalid.
142
+ - NEVER write unified diff syntax. Header is `@@ PATH`; ops are `<`/`+`/`-`/`=`.
143
+ - `= A..B` deletes the range; payload is what's written. Edge line matches just outside? Widen, or it duplicates.
144
+ - Multiple ops are cheap. SHOULD prefer two narrow ops over one wide `=`.
145
+ - Before `= A..B`, mentally delete A..B. Splits an unclosed bracket/brace/string from above, or orphans a closer inside? You're bisecting a construct.
162
146
  </critical>
@@ -1,45 +1,58 @@
1
- Reads the content at the specified path or URL.
1
+ Read files, directories, archives, SQLite databases, images, documents, internal resources, and web URLs through a single `path` string.
2
2
 
3
3
  <instruction>
4
- The `read` tool is multi-purpose and more capable than it looks — inspects files, directories, archives, SQLite databases, images, documents (PDF/DOCX/PPTX/XLSX/RTF/EPUB/ipynb), **and URLs**.
5
- - You MUST parallelize reads when exploring related files
6
- - For URLs, `read` fetches the page and returns clean extracted text/markdown by default (reader-mode). It handles HTML pages, GitHub issues/PRs, Stack Overflow, Wikipedia, Reddit, NPM, arXiv, RSS/Atom, JSON endpoints, PDFs, etc. You SHOULD reach for `read` — not a browser/puppeteer tool — for fetching and inspecting web content.
4
+ - One tool for filesystem, archives, SQLite, images, documents (PDF/DOCX/PPTX/XLSX/RTF/EPUB/ipynb), internal URIs, and web URLs (reader-mode by default).
5
+ - You SHOULD parallelize independent reads when exploring related files.
6
+ - You SHOULD reach for `read` — not a browser/puppeteer tool — for fetching web content.
7
+ </instruction>
7
8
 
8
9
  ## Parameters
9
- - `path` — file path or URL (required). Append `:<sel>` for line ranges or raw mode (for example `src/foo.ts:50-200` or `src/foo.ts:raw`).
10
+
11
+ - `path` — required. Local path, internal URI (`skill://`, `agent://`, `artifact://`, `memory://`, `rule://`, `local://`, `mcp://`), or URL. Append `:<sel>` for line ranges, raw mode, or special modes (e.g. `src/foo.ts:50-200`, `src/foo.ts:raw`, `db.sqlite:users:42`).
10
12
 
11
13
  ## Selectors
12
14
 
13
- |`path` suffix|Behavior|
14
- |---|---|
15
- |_(omitted)_|For parseable code files, return a structural summary. Otherwise read from the start (up to {{DEFAULT_LIMIT}} lines).|
16
- |`:50`|Read from line 50 onward|
17
- |`:50-200`|Read lines 50-200|
18
- |`:50+150`|Read 150 lines starting at line 50|
19
- |`:20+1`|Read exactly one line|
20
- |`:raw`|Read verbatim text without anchors or summarization|
21
- |`:conflicts`|Return a one-line-per-block index of every merge conflict in the file|
15
+ Append `:<sel>` to `path`. The bare path falls back to the default mode.
16
+
17
+ - _(none)_ parseable code → structural summary (signatures kept, bodies elided); other files read from the start (up to {{DEFAULT_LIMIT}} lines).
18
+ - `:50` — read from line 50 onward.
19
+ - `:50-200` lines 50200 inclusive.
20
+ - `:50+150` 150 lines starting at line 50.
21
+ - `:20+1` exactly one line.
22
+ - `:5-16,960-973` multiple ranges in one call (sorted, overlaps merged).
23
+ - `:raw` verbatim text; no anchors, no summary, no line prefixes.
24
+ - `:2-4:raw` or `:raw:2-4` — range AND verbatim; the two compose in either order.
25
+ - `:conflicts` — one-line-per-block index of every unresolved git merge conflict.
26
+
27
+ # Files
28
+
29
+ - Reading a directory path returns a depth-limited dirent listing.
30
+ {{#if IS_HL_MODE}}
31
+ - Reading a file with an explicit selector returns lines prefixed with `line+hash` anchors: `41th|def alpha():`. The 2-char hash is a content fingerprint that `edit` / `apply_patch` consume — copy it verbatim, NEVER fabricate.
32
+ {{else}}
33
+ {{#if IS_LINE_NUMBER_MODE}}
34
+ - Reading a file with an explicit selector returns lines prefixed with line numbers: `41|def alpha():`.
35
+ {{/if}}
36
+ {{/if}}
37
+ - Parseable code without a selector returns a **structural summary**: declarations kept, large bodies collapsed to `..` (merged brace pair) or `…` (standalone). Summarized output ends with a footer of the form:
38
+
39
+ `[NN lines across MM elided regions; read <path>:raw or a line range like <path>:1-9999 for verbatim content]`
22
40
 
23
- # Filesystem
24
- - Reading a directory path returns a list of dirents.
25
- {{#if IS_HL_MODE}}
26
- - Reading a file with an explicit selector returns lines prefixed with anchors (line+hash): `41th|def alpha():`
27
- {{else}}
28
- {{#if IS_LINE_NUMBER_MODE}}
29
- - Reading a file with an explicit selector returns lines prefixed with line numbers: `41|def alpha():`
30
- {{/if}}
31
- {{/if}}
32
- - Reading a parseable code file without a selector returns a structural summary with signatures/declarations kept and large bodies collapsed to `…`. Use `:raw` or an explicit range such as `:1-9999` for verbatim content.
41
+ If the elided body is what you actually need, re-issue the **exact selector the footer names**. NEVER guess what's inside `..` / `…` — those markers carry no content.
33
42
 
34
- # Inspection
43
+ # Documents & Notebooks
35
44
 
36
- Extracts text from PDF, Word, PowerPoint, Excel, RTF, EPUB, and Jupyter notebook files. Notebooks are shown as editable `# %% [type] cell:N` text; edits to that text are applied back to the underlying `.ipynb` JSON while preserving notebook metadata where possible. Can inspect images.
45
+ Extracts text from PDF, Word, PowerPoint, Excel, RTF, and EPUB. Notebooks (`.ipynb`) are shown as editable `# %% [type] cell:N` text; edits round-trip back to the underlying JSON preserving notebook metadata. Add `:raw` to a notebook to bypass the converter and read the JSON directly.
37
46
 
38
- # Directories & Archives
47
+ # Images
39
48
 
40
- Directories and archive roots return a list of entries. Supports `.tar`, `.tar.gz`, `.tgz`, `.zip`. Use `archive.ext:path/inside/archive` to read contents, and append a selector to the archive entry such as `archive.zip:dir/file.ts:50-60`.
49
+ Reading an image path returns metadata (mime, bytes, dimensions, channels, alpha). For actual visual analysis, call `inspect_image` with the path and a question describing what to inspect.
41
50
 
42
- # SQLite Databases
51
+ # Archives
52
+
53
+ Supports `.tar`, `.tar.gz`, `.tgz`, `.zip`. Use `archive.ext:path/inside/archive` to read a member, and append a normal selector to the inner path: `archive.zip:dir/file.ts:50-60`.
54
+
55
+ # SQLite
43
56
 
44
57
  For `.sqlite`, `.sqlite3`, `.db`, `.db3`:
45
58
  - `file.db` — list tables with row counts
@@ -51,13 +64,19 @@ For `.sqlite`, `.sqlite3`, `.db`, `.db3`:
51
64
 
52
65
  # URLs
53
66
 
54
- Extracts content from web pages, GitHub issues/PRs, Stack Overflow, Wikipedia, Reddit, NPM, arXiv, RSS/Atom feeds, JSON endpoints, PDFs at URLs, and similar text-based resources. Returns clean reader-mode text/markdown — no browser required. Use a `:raw` suffix for untouched HTML. URL line selectors mirror the file form (`:50`, `:50-100`, `:50+150`, `:raw`). If a URL would otherwise look like `host:port`, add a trailing slash before the selector (e.g. `https://example.com/:80`).
55
- </instruction>
67
+ - Default reader-mode: HTML pages, GitHub issues/PRs, Stack Overflow, Wikipedia, Reddit, NPM, arXiv, RSS/Atom, JSON endpoints, PDFs clean text/markdown.
68
+ - `:raw` returns untouched HTML; line selectors (`:50`, `:50-100`, `:50+150`) paginate the cached fetched output.
69
+ - Bare `host:port` URLs collide with the selector grammar — add a trailing slash before the selector: `https://example.com/:80`.
70
+
71
+ # Internal URIs
72
+
73
+ `skill://<name>`, `agent://<id>`, `artifact://<id>`, `memory://root`, `rule://<name>`, `local://<name>.md`, `mcp://<uri>` resolve transparently and accept the same line selectors as filesystem paths. Use `artifact://<id>` to recover full output that a previous bash/eval/tool result spilled or truncated.
56
74
 
57
75
  <critical>
58
- - You MUST use `read` for every file, directory, archive, and URL read. `cat`, `head`, `tail`, `less`, `more`, `ls`, `tar`, `unzip`, `curl`, and `wget` are **FORBIDDEN** for inspection — any such Bash call is a bug, regardless of how short or convenient it looks.
59
- - You MUST prefer `read` over a browser/puppeteer tool for fetching URL content; only use a browser if `read` fails to deliver reasonable content.
60
- - You MUST always include the `path` parameter — never call `read` with an empty argument object `{}`.
61
- - For specific line ranges, append the selector to `path` (e.g. `path="src/foo.ts:50-200"`, `path="src/foo.ts:50+150"`) NEVER reach for `sed -n`, `awk NR`, or `head`/`tail` pipelines.
62
- - You MAY use path suffix selectors with URL reads; the tool paginates cached fetched output.
76
+ - You MUST use `read` for every file, directory, archive, and URL inspection. `cat`, `head`, `tail`, `less`, `more`, `ls`, `tar`, `unzip`, `curl`, `wget` are FORBIDDEN — any such bash call is a bug, regardless of how short or convenient it looks.
77
+ - You MUST prefer `read` over a browser/puppeteer tool for URL content; only reach for a browser when `read` cannot deliver reasonable content.
78
+ - You MUST always include `path`. NEVER call `read` with `{}`.
79
+ - For line ranges, append the selector to `path` (`path="src/foo.ts:50-200"`, `path="src/foo.ts:50+150"`). NEVER substitute `sed -n`, `awk NR`, or `head`/`tail` pipelines.
80
+ - Summary footer says `read <path>:raw …`? Re-issue the exact selector it names. NEVER guess what's inside `..` / `…` markers — they carry no content.
81
+ - You MAY combine selectors with URL reads and internal URIs; both paginate the cached resolved output.
63
82
  </critical>
@@ -1,8 +1,9 @@
1
- Resolves a pending preview action by either applying or discarding it.
1
+ Resolves a pending action by either applying or discarding it.
2
2
  - `action` is required:
3
- - `"apply"` persists the pending changes.
4
- - `"discard"` rejects the pending changes.
5
- - `reason` is required and must explain why you chose to apply or discard.
3
+ - `"apply"` persists / submits the pending action.
4
+ - `"discard"` rejects the pending action.
5
+ - `reason` is required and must briefly explain why you chose to apply or discard.
6
+ - `extra` (optional) is free-form metadata passed to the resolving tool. Schema depends on context:
6
7
 
7
- Only valid when a pending action exists (typically after a preview step).
8
+ Valid whenever a pending action exists either a preview-style staging (e.g. `ast_edit`) or a long-lived approval gate.
8
9
  Call fails with an error when no pending action exists.
package/src/sdk.ts CHANGED
@@ -1044,7 +1044,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
1044
1044
  getSessionSpawns: () => options.spawns ?? "*",
1045
1045
  getModelString: () => (hasExplicitModel && model ? formatModelString(model) : undefined),
1046
1046
  getActiveModelString,
1047
- getPlanModeState: () => session.getPlanModeState(),
1047
+ getPlanModeState: () => session?.getPlanModeState(),
1048
+ getGoalModeState: () => session?.getGoalModeState(),
1049
+ getGoalRuntime: () => session?.goalRuntime,
1048
1050
  getClientBridge: () => session?.clientBridge,
1049
1051
  getCompactContext: () => session.formatCompactContext(),
1050
1052
  getTodoPhases: () => session.getTodoPhases(),
@@ -1078,6 +1080,8 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
1078
1080
  timestamp: Date.now(),
1079
1081
  }),
1080
1082
  peekQueueInvoker: () => session.peekQueueInvoker(),
1083
+ peekStandingResolveHandler: () => session.peekStandingResolveHandler(),
1084
+ setStandingResolveHandler: handler => session.setStandingResolveHandler(handler),
1081
1085
  allocateOutputArtifact: async toolType => {
1082
1086
  try {
1083
1087
  return await sessionManager.allocateArtifactPath(toolType);
@@ -1377,6 +1381,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
1377
1381
  for (const tool of builtinTools) {
1378
1382
  toolRegistry.set(tool.name, tool);
1379
1383
  }
1384
+ if (!toolRegistry.has("goal") && settings.get("goal.enabled")) {
1385
+ const goalTool = await logger.time("createTools:goal:session", HIDDEN_TOOLS.goal, toolSession);
1386
+ if (goalTool) {
1387
+ toolRegistry.set(goalTool.name, wrapToolWithMetaNotice(goalTool));
1388
+ }
1389
+ }
1380
1390
  for (const tool of wrappedExtensionTools) {
1381
1391
  toolRegistry.set(tool.name, tool);
1382
1392
  }
@@ -1503,7 +1513,6 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
1503
1513
  (options.toolNames ? [...new Set(options.toolNames.map(name => name.toLowerCase()))] : undefined) ??
1504
1514
  toolNamesFromRegistry;
1505
1515
  const normalizedRequested = requestedToolNames.filter(name => toolRegistry.has(name));
1506
- const includeExitPlanMode = requestedToolNames.includes("exit_plan_mode");
1507
1516
  // Effective discovery mode: tools.discoveryMode takes precedence; mcp.discoveryMode is back-compat alias.
1508
1517
  const toolsDiscoveryModeSetting = settings.get("tools.discoveryMode");
1509
1518
  const effectiveDiscoveryMode: "off" | "mcp-only" | "all" =
@@ -1516,9 +1525,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
1516
1525
  const defaultInactiveToolNames = new Set(
1517
1526
  registeredTools.filter(tool => tool.definition.defaultInactive).map(tool => tool.definition.name),
1518
1527
  );
1519
- const requestedActiveToolNames = includeExitPlanMode
1520
- ? normalizedRequested
1521
- : normalizedRequested.filter(name => name !== "exit_plan_mode");
1528
+ const requestedActiveToolNames = normalizedRequested.filter(name => name !== "goal");
1522
1529
  const initialRequestedActiveToolNames = options.toolNames
1523
1530
  ? requestedActiveToolNames
1524
1531
  : requestedActiveToolNames.filter(name => !defaultInactiveToolNames.has(name));