@oh-my-pi/pi-coding-agent 15.11.3 → 15.11.6
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 +107 -0
- package/dist/cli.js +692 -607
- package/dist/types/cli/usage-cli.d.ts +10 -1
- package/dist/types/commands/usage.d.ts +9 -0
- package/dist/types/config/api-key-resolver.d.ts +9 -3
- package/dist/types/config/keybindings.d.ts +1 -1
- package/dist/types/config/model-discovery.d.ts +6 -4
- package/dist/types/config/model-registry.d.ts +7 -4
- package/dist/types/config/settings-schema.d.ts +508 -155
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/mnemopi/config.d.ts +3 -1
- package/dist/types/modes/components/reset-usage-selector.d.ts +12 -0
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/settings-defs.d.ts +9 -2
- package/dist/types/modes/components/settings-selector.d.ts +9 -4
- package/dist/types/modes/components/tool-execution.d.ts +26 -1
- package/dist/types/modes/components/transcript-container.d.ts +12 -0
- package/dist/types/modes/controllers/input-controller.d.ts +9 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +10 -0
- package/dist/types/modes/session-observer-registry.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +23 -3
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/modes/utils/context-usage.d.ts +6 -1
- package/dist/types/session/agent-session.d.ts +28 -8
- package/dist/types/session/auth-storage.d.ts +1 -1
- package/dist/types/session/codex-auto-reset.d.ts +107 -0
- package/dist/types/session/snapcompact-inline.d.ts +129 -0
- package/dist/types/slash-commands/helpers/active-oauth-account.d.ts +14 -0
- package/dist/types/slash-commands/helpers/reset-usage.d.ts +27 -0
- package/dist/types/system-prompt.d.ts +3 -1
- package/dist/types/task/render.d.ts +17 -6
- package/dist/types/tools/gh.d.ts +3 -0
- package/dist/types/tools/render-utils.d.ts +8 -16
- package/dist/types/tools/todo.d.ts +0 -11
- package/dist/types/utils/session-color.d.ts +15 -3
- package/dist/types/web/kagi.d.ts +1 -2
- package/dist/types/web/search/providers/codex.d.ts +1 -1
- package/dist/types/web/search/providers/gemini.d.ts +9 -6
- package/package.json +11 -11
- package/src/auto-thinking/classifier.ts +1 -5
- package/src/cli/usage-cli.ts +187 -16
- package/src/commands/usage.ts +8 -0
- package/src/commit/model-selection.ts +3 -6
- package/src/config/api-key-resolver.ts +10 -3
- package/src/config/keybindings.ts +1 -1
- package/src/config/model-discovery.ts +60 -46
- package/src/config/model-registry.ts +21 -8
- package/src/config/model-resolver.ts +57 -3
- package/src/config/settings-schema.ts +654 -153
- package/src/config/settings.ts +9 -0
- package/src/eval/completion-bridge.ts +1 -5
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +13 -6
- package/src/internal-urls/docs-index.generated.ts +6 -6
- package/src/internal-urls/issue-pr-protocol.ts +10 -4
- package/src/memories/index.ts +2 -10
- package/src/mnemopi/backend.ts +30 -8
- package/src/mnemopi/config.ts +6 -1
- package/src/mnemopi/state.ts +6 -0
- package/src/modes/components/extensions/inspector-panel.ts +6 -2
- package/src/modes/components/plan-review-overlay.ts +15 -17
- package/src/modes/components/plugin-settings.ts +22 -5
- package/src/modes/components/reset-usage-selector.ts +161 -0
- package/src/modes/components/session-selector.ts +8 -2
- package/src/modes/components/settings-defs.ts +19 -4
- package/src/modes/components/settings-selector.ts +510 -95
- package/src/modes/components/status-line/component.ts +3 -1
- package/src/modes/components/status-line/segments.ts +3 -1
- package/src/modes/components/tool-execution.ts +87 -12
- package/src/modes/components/transcript-container.ts +49 -1
- package/src/modes/components/tree-selector.ts +16 -6
- package/src/modes/controllers/command-controller.ts +61 -8
- package/src/modes/controllers/event-controller.ts +1 -0
- package/src/modes/controllers/input-controller.ts +68 -6
- package/src/modes/controllers/selector-controller.ts +149 -61
- package/src/modes/interactive-mode.ts +63 -2
- package/src/modes/rpc/rpc-mode.ts +2 -1
- package/src/modes/session-observer-registry.ts +61 -3
- package/src/modes/shared.ts +2 -0
- package/src/modes/theme/theme.ts +102 -9
- package/src/modes/types.ts +2 -0
- package/src/modes/utils/context-usage.ts +78 -2
- package/src/modes/utils/hotkeys-markdown.ts +1 -1
- package/src/modes/utils/ui-helpers.ts +9 -5
- package/src/prompts/system/personalities/default.md +26 -0
- package/src/prompts/system/personalities/friendly.md +17 -0
- package/src/prompts/system/personalities/pragmatic.md +15 -0
- package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
- package/src/prompts/system/snapcompact-context-stub.md +1 -0
- package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
- package/src/prompts/system/snapcompact-system-stub.md +1 -0
- package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
- package/src/prompts/system/system-prompt.md +5 -22
- package/src/prompts/tools/browser.md +33 -43
- package/src/prompts/tools/eval.md +27 -50
- package/src/prompts/tools/irc.md +29 -31
- package/src/prompts/tools/read.md +31 -37
- package/src/prompts/tools/task.md +3 -3
- package/src/prompts/tools/todo.md +1 -2
- package/src/sdk.ts +23 -1
- package/src/session/agent-session.ts +221 -29
- package/src/session/auth-storage.ts +4 -0
- package/src/session/codex-auto-reset.ts +190 -0
- package/src/session/session-dump-format.ts +8 -1
- package/src/session/session-manager.ts +5 -5
- package/src/session/snapcompact-inline.ts +524 -0
- package/src/slash-commands/builtin-registry.ts +145 -8
- package/src/slash-commands/helpers/active-oauth-account.ts +44 -0
- package/src/slash-commands/helpers/context-report.ts +28 -1
- package/src/slash-commands/helpers/reset-usage.ts +66 -0
- package/src/slash-commands/helpers/usage-report.ts +36 -3
- package/src/system-prompt.ts +15 -1
- package/src/task/index.ts +30 -7
- package/src/task/render.ts +57 -32
- package/src/tool-discovery/tool-index.ts +2 -0
- package/src/tools/bash.ts +10 -3
- package/src/tools/eval-render.ts +13 -8
- package/src/tools/gh.ts +39 -1
- package/src/tools/image-gen.ts +114 -78
- package/src/tools/inspect-image.ts +1 -5
- package/src/tools/job.ts +25 -5
- package/src/tools/read.ts +1 -57
- package/src/tools/render-utils.ts +29 -31
- package/src/tools/ssh.ts +3 -3
- package/src/tools/todo.ts +8 -128
- package/src/tools/tts.ts +40 -20
- package/src/utils/clipboard.ts +56 -4
- package/src/utils/commit-message-generator.ts +1 -5
- package/src/utils/session-color.ts +83 -9
- package/src/utils/title-generator.ts +1 -1
- package/src/web/kagi.ts +26 -27
- package/src/web/search/providers/codex.ts +42 -40
- package/src/web/search/providers/gemini.ts +42 -22
- package/src/web/search/providers/perplexity.ts +22 -10
|
@@ -1,92 +1,69 @@
|
|
|
1
1
|
Run code in a persistent kernel using a list of cells.
|
|
2
2
|
|
|
3
3
|
<instruction>
|
|
4
|
-
|
|
4
|
+
Cells run in array order. State persists per language — across cells, tool calls, and `task` subagents: variables either side defines are visible to the other. Stage helpers, datasets, or live clients once; subagents use them directly — no re-importing or serializing across the boundary.
|
|
5
5
|
|
|
6
6
|
Cell fields:
|
|
7
7
|
|
|
8
8
|
- `language` — {{#if py}}`"py"` for the IPython kernel{{/if}}{{#ifAll py js}}, {{/ifAll}}{{#if js}}`"js"` for the persistent JavaScript VM{{/if}}.
|
|
9
|
-
- `code` — cell body, verbatim. Newlines
|
|
10
|
-
- `title` (optional) — short label
|
|
11
|
-
- `timeout` (optional) — per-cell
|
|
12
|
-
- `reset` (optional) — wipe this cell's language kernel
|
|
9
|
+
- `code` — cell body, verbatim. Newlines and quotes JSON-encoded; no fences, no headers.
|
|
10
|
+
- `title` (optional) — short transcript label (e.g. `"imports"`).
|
|
11
|
+
- `timeout` (optional) — per-cell seconds (1-3600, default 30). Bounds the cell's own work only; the clock pauses while `agent()`/`parallel()`/`completion()` calls are in flight, so fanouts never need a raise. Raise only for heavy local compute or long non-agent tool calls.
|
|
12
|
+
- `reset` (optional) — wipe this cell's language kernel first.{{#ifAll py js}} Per-language: a `py` reset never touches the JS VM.{{/ifAll}}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- Pass multiple small cells in one call.
|
|
18
|
-
- Define small reusable functions for individual debugging.
|
|
19
|
-
- Put workflow explanations in the assistant message or `title` — never inside cell code.
|
|
20
|
-
{{#if py}}- Python cells run inside an IPython kernel with a live event loop. Use top-level `await` directly (e.g. `await main()`); `asyncio.run(…)` raises "cannot be called from a running event loop".{{/if}}
|
|
21
|
-
**On failure:** errors identify the failing cell (e.g., "Cell 3 failed"). Resubmit only the fixed cell (or fixed cell + remaining cells).
|
|
14
|
+
Work incrementally: one logical step per cell (imports, define, test, use); pass multiple small cells per call; define small reusable functions for individual debugging. Workflow explanations go in the assistant message or `title`, never inside cell code.
|
|
15
|
+
{{#if py}}Python runs in IPython with a live event loop: use top-level `await` directly; `asyncio.run(…)` raises "cannot be called from a running event loop".{{/if}}
|
|
16
|
+
On failure, errors name the failing cell ("Cell 3 failed") — resubmit only the fixed cell (plus any remaining).
|
|
22
17
|
</instruction>
|
|
23
18
|
|
|
24
19
|
<prelude>
|
|
25
|
-
{{#ifAll py js}}Same helpers in both runtimes
|
|
20
|
+
{{#ifAll py js}}Same helpers in both runtimes, same positional order. Python: helpers run synchronously; trailing options are keyword args. JavaScript: helpers are async and `await`able; trailing options are ONE trailing object literal, never positional (extra positional args throw).{{else}}{{#if py}}Helpers run synchronously. Trailing options are keyword arguments.{{/if}}{{#if js}}Helpers are async and `await`able. Trailing options are ONE trailing object literal, never positional (extra positional args throw).{{/if}}{{/ifAll}}
|
|
26
21
|
```
|
|
27
22
|
display(value) → None
|
|
28
|
-
Render
|
|
23
|
+
Render value in cell output, shows presentable values natively (figures, images, dataframes)
|
|
29
24
|
print(value, ...) → None
|
|
30
|
-
Print to
|
|
25
|
+
Print to text output.
|
|
31
26
|
read(path, offset?=1, limit?=None) → str
|
|
32
|
-
Read file
|
|
27
|
+
Read file as text; offset/limit are 1-indexed lines. Accepts `local://…`.
|
|
33
28
|
write(path, content) → str
|
|
34
|
-
Write
|
|
29
|
+
Write file (creates parents); returns resolved path. `local://…` persists across turns / subagents.
|
|
35
30
|
append(path, content) → str
|
|
36
|
-
Append
|
|
31
|
+
Append to file; returns resolved path. Accepts `local://…`.
|
|
37
32
|
tree(path?=".", max_depth?=3, show_hidden?=False) → str
|
|
38
|
-
|
|
33
|
+
Directory tree.
|
|
39
34
|
diff(a, b) → str
|
|
40
|
-
Unified diff
|
|
35
|
+
Unified diff of two files.
|
|
41
36
|
env(key?=None, value?=None) → str | None | dict
|
|
42
|
-
No args → full
|
|
37
|
+
No args → full env dict; one → value of `key`; two → set `key=value`, return value.
|
|
43
38
|
output(*ids, format?="raw", query?=None, offset?=None, limit?=None) → str | dict | list[dict]
|
|
44
|
-
Read task/agent output by
|
|
39
|
+
Read task/agent output by id; one id → text/dict, multiple → list.
|
|
45
40
|
tool.<name>(args) → unknown
|
|
46
|
-
Invoke any session tool
|
|
41
|
+
Invoke any session tool; `args` is its parameter object.
|
|
47
42
|
completion(prompt, model?="default", system?=None, schema?=None) → str | dict
|
|
48
|
-
Oneshot
|
|
43
|
+
Oneshot stateless completion (no history, no tools). `model` tier: "smol" (fast) | "default" (session model) | "slow" (most capable). JSON-Schema `schema` forces structured output, returns parsed object.
|
|
49
44
|
{{#if spawns}}agent(prompt, agent_type?="task", model?=None, label?=None, schema?=None) → str | dict
|
|
50
|
-
Run a subagent
|
|
51
|
-
{{#if js}}
|
|
45
|
+
Run a subagent, return its final output. `agent_type`/`agentType` picks another discovered agent; `schema` as in completion(). Share background via `local://` files referenced in the prompt.
|
|
46
|
+
{{#if js}} JS: options are ONE trailing object — agent(prompt, { agentType, schema }).
|
|
52
47
|
{{/if}}
|
|
53
48
|
{{/if}}
|
|
54
49
|
parallel(thunks) → list
|
|
55
|
-
Run thunks
|
|
50
|
+
Run thunks through a bounded pool (as wide as a `task` batch — don't pre-shrink), preserving input order. Barrier: returns when all finish; a throwing thunk propagates.
|
|
56
51
|
pipeline(items, ...stages) → list
|
|
57
|
-
Map
|
|
52
|
+
Map items through one-arg stages left-to-right, barrier between stages; stage 1 gets the item, later stages the previous result. Same pool width as parallel().
|
|
58
53
|
log(message) → None
|
|
59
|
-
|
|
54
|
+
Progress line above the status tree.
|
|
60
55
|
phase(title) → None
|
|
61
|
-
Start a phase
|
|
56
|
+
Start a phase grouping subsequent status lines.
|
|
62
57
|
budget → per-turn token budget
|
|
63
|
-
{{#if py}}`budget.total` (ceiling or None), `budget.spent()
|
|
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.
|
|
64
59
|
```
|
|
65
60
|
</prelude>
|
|
66
61
|
|
|
67
|
-
<output>
|
|
68
|
-
Cells render like a Jupyter notebook. `display(value)` renders non-presentable data as an interactive JSON tree. Presentable values (figures, images, dataframes, etc.) use their native representation.
|
|
69
|
-
</output>
|
|
70
|
-
|
|
71
|
-
<caution>
|
|
72
|
-
{{#if js}}- **js**: the VM exposes a selective `process` subset, Web APIs, `Buffer`, `fs/promises`, and the `Bun` global.
|
|
73
|
-
{{/if}}</caution>
|
|
74
|
-
|
|
75
62
|
<example>
|
|
76
|
-
{{#if py}}```json
|
|
77
63
|
{
|
|
78
64
|
"cells": [
|
|
79
65
|
{ "language": "py", "title": "imports", "timeout": 10, "code": "import json\nfrom pathlib import Path" },
|
|
80
66
|
{ "language": "py", "title": "load config", "code": "data = json.loads(read('package.json'))\ndisplay(data)" }
|
|
81
67
|
]
|
|
82
68
|
}
|
|
83
|
-
```{{/if}}{{#ifAll py js}}
|
|
84
|
-
|
|
85
|
-
{{/ifAll}}{{#if js}}```json
|
|
86
|
-
{
|
|
87
|
-
"cells": [
|
|
88
|
-
{ "language": "js", "title": "summary", "reset": true, "code": "const data = JSON.parse(await read('package.json'));\ndisplay(data);\nreturn data.name;" }
|
|
89
|
-
]
|
|
90
|
-
}
|
|
91
|
-
```{{/if}}
|
|
92
69
|
</example>
|
package/src/prompts/tools/irc.md
CHANGED
|
@@ -1,55 +1,53 @@
|
|
|
1
1
|
Sends short text messages to other agents in this process and receives theirs.
|
|
2
2
|
|
|
3
3
|
<instruction>
|
|
4
|
-
-
|
|
5
|
-
- `op: "list"` —
|
|
6
|
-
- `op: "send"` — fire-and-forget
|
|
7
|
-
- Messaging an `idle
|
|
8
|
-
- `send`
|
|
9
|
-
- `op: "wait"` — block until a message arrives (optionally only `from`
|
|
10
|
-
- `op: "inbox"` — drain pending messages without blocking (`peek: true`
|
|
11
|
-
- `replyTo` —
|
|
12
|
-
-
|
|
4
|
+
- Main agent is `Main`; subagents reuse their task id (`AuthLoader`, or `AuthLoader-2` when the name repeats).
|
|
5
|
+
- `op: "list"` — peers with status (`running` | `idle` | `parked`), unread count, parent, last activity. Use when unsure who exists.
|
|
6
|
+
- `op: "send"` — fire-and-forget `message` to `to` (peer id, or `"all"` to broadcast to live peers). Returns per-recipient receipts immediately; NEVER waits for the recipient to act. Outcomes: `injected` (mid-turn; folded in at next step boundary), `woken` (idle peer started a turn), `revived` (parked peer brought back and woken), `failed`.
|
|
7
|
+
- Messaging an `idle`/`parked` peer is how you wake it — there is no separate revive call.
|
|
8
|
+
- `send` + `await: true` — round-trip: send, then block until that peer's next message (or timeout). Invalid with `to: "all"`.
|
|
9
|
+
- `op: "wait"` — block until a message arrives (optionally only `from` one peer); consumes and returns it. Timeout = clean "no message", not an error.
|
|
10
|
+
- `op: "inbox"` — drain pending messages without blocking (`peek: true` leaves them unread).
|
|
11
|
+
- `replyTo` — id of the message you are answering, so the sender can correlate.
|
|
12
|
+
- Replies arrive only when the recipient sends one. Exception: `await: true` to a peer stuck mid-turn (async execution disabled, e.g. blocked in a synchronous task spawn) gets a side-channel auto-reply from its context. For background on a peer, `read` `history://<id>` instead of interrogating it.
|
|
13
13
|
</instruction>
|
|
14
14
|
|
|
15
15
|
<when_to_use>
|
|
16
|
-
|
|
17
|
-
- **Unexpected state
|
|
18
|
-
- **Blocked by another agent
|
|
19
|
-
- **Decision
|
|
20
|
-
- **Coordination
|
|
16
|
+
Reach for `irc` proactively when continuing alone is wasteful or wrong; when in doubt, message.
|
|
17
|
+
- **Unexpected state** — missing file, config contradicting the assignment, API/tool behaving differently than told. DM `Main` (or your spawner) instead of guessing.
|
|
18
|
+
- **Blocked by another agent** — a peer holds the file/branch/resource or decision you need, or started the change you're about to make. DM them (or broadcast to discover who) before duplicating work.
|
|
19
|
+
- **Decision outside your scope** — a genuine fork the assignment didn't pre-decide. Ask the requester rather than picking unilaterally.
|
|
20
|
+
- **Coordination** — a peer's in-flight work would benefit from yours, or vice-versa.
|
|
21
21
|
|
|
22
|
-
NEVER
|
|
22
|
+
NEVER for: routine progress updates, things a tool call can verify, questions your assignment/repo/docs already answer.
|
|
23
23
|
</when_to_use>
|
|
24
24
|
|
|
25
25
|
<etiquette>
|
|
26
|
-
|
|
27
|
-
- **Plain prose only.** NEVER
|
|
28
|
-
- **NEVER quote the message you
|
|
29
|
-
- **
|
|
30
|
-
- **Send, then keep working.** `
|
|
31
|
-
- **Answer
|
|
32
|
-
- **Stay terse.**
|
|
33
|
-
- **Address peers by
|
|
34
|
-
- **NEVER IRC
|
|
26
|
+
Applies to sending and replying.
|
|
27
|
+
- **Plain prose only.** NEVER JSON status payloads like `{"type":"task_completed",…}` — write a normal sentence.
|
|
28
|
+
- **NEVER quote the message you answer.** Lead with the answer; set `replyTo`.
|
|
29
|
+
- **Learn about peers via IRC** — NEVER grep artifacts, read other sessions' JSONL, or shell-poke. DM them, or `read` `history://<id>`.
|
|
30
|
+
- **Send, then keep working.** `wait`/`await: true` only when you genuinely cannot proceed. NEVER "did you get my message?". A `failed` receipt = peer unreachable — move on; NEVER retry in a loop.
|
|
31
|
+
- **Answer expected questions** via `irc send` to the sender (finishing your current step first is fine).
|
|
32
|
+
- **Stay terse.** One question per send; share files via `local://`/`memory://`/`artifact://` URLs, never pasted blobs.
|
|
33
|
+
- **Address peers by exact id** from `op: "list"` (e.g. `AuthLoader`, `Main`). NEVER invent friendly names.
|
|
34
|
+
- **NEVER IRC what a tool answers.** A `read`, grep, or build resolves it? Do that first.
|
|
35
35
|
</etiquette>
|
|
36
36
|
|
|
37
37
|
<output>
|
|
38
|
-
- `send`: per-recipient
|
|
38
|
+
- `send`: per-recipient receipts; with `await: true`, also the reply (or timeout notice).
|
|
39
39
|
- `wait`: the consumed message, or a clean timeout notice.
|
|
40
40
|
- `inbox`: pending messages, oldest first.
|
|
41
|
-
- `list`: peers with status, unread count, parent,
|
|
41
|
+
- `list`: peers with status, unread count, parent, last activity.
|
|
42
42
|
</output>
|
|
43
43
|
|
|
44
44
|
<examples>
|
|
45
45
|
# List peers
|
|
46
46
|
`{"op": "list"}`
|
|
47
|
-
# Fire-and-forget DM —
|
|
48
|
-
`{"op": "send", "to": "AuthLoader", "message": "
|
|
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
49
|
# Round-trip when you cannot proceed without the answer
|
|
50
|
-
`{"op": "send", "to": "Main", "message": "
|
|
51
|
-
# Wake a parked agent (same send — the bus revives it)
|
|
52
|
-
`{"op": "send", "to": "SchemaMigrator", "message": "The users table changed again; please re-check your migration."}`
|
|
50
|
+
`{"op": "send", "to": "Main", "message": "JWT or session cookies for the auth flow?", "await": true}`
|
|
53
51
|
# Block until a specific peer answers
|
|
54
52
|
`{"op": "wait", "from": "AuthLoader", "timeoutMs": 60000}`
|
|
55
53
|
# Drain pending messages
|
|
@@ -1,84 +1,78 @@
|
|
|
1
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
|
-
- 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
4
|
- You SHOULD parallelize independent reads when exploring related files.
|
|
6
|
-
- You SHOULD reach for `read` — not a browser/puppeteer tool — for
|
|
5
|
+
- You SHOULD reach for `read` — not a browser/puppeteer tool — for web content; browser only when `read` cannot deliver it.
|
|
7
6
|
</instruction>
|
|
8
7
|
|
|
9
8
|
## Parameters
|
|
10
9
|
|
|
11
|
-
- `path` — required. Local path, internal URI (`skill://`, `agent://`, `artifact://`, `history://`, `memory://`, `rule://`, `local://`, `vault://`, `mcp://`, `omp://`, `issue://`, `pr://`), or URL. Append `:<sel>` for line ranges
|
|
10
|
+
- `path` — required. Local path, internal URI (`skill://`, `agent://`, `artifact://`, `history://`, `memory://`, `rule://`, `local://`, `vault://`, `mcp://`, `omp://`, `issue://`, `pr://`), or URL. Append `:<sel>` for line ranges or special modes (e.g. `src/foo.ts:50-200`, `src/foo.ts:raw`, `db.sqlite:users:42`).
|
|
12
11
|
|
|
13
12
|
## Selectors
|
|
14
13
|
|
|
15
|
-
Append `:<sel>` to `path
|
|
14
|
+
Append `:<sel>` to `path`; bare path = default mode.
|
|
16
15
|
|
|
17
|
-
- _(none)_ — parseable code → structural summary
|
|
18
|
-
- `:50` / `:50-` —
|
|
16
|
+
- _(none)_ — parseable code → structural summary; other files → from start (up to {{DEFAULT_LIMIT}} lines).
|
|
17
|
+
- `:50` / `:50-` — from line 50 onward.
|
|
19
18
|
- `:50-200` — lines 50–200 inclusive.
|
|
20
|
-
- `:50+150` — 150 lines starting at
|
|
21
|
-
- `:20+1` — anchor
|
|
22
|
-
- `:5-16,960-973` — multiple ranges in one call (sorted, overlaps merged)
|
|
23
|
-
- `:raw` — verbatim
|
|
24
|
-
- `:2-4:raw`
|
|
25
|
-
- `:conflicts` — one
|
|
19
|
+
- `:50+150` — 150 lines starting at 50.
|
|
20
|
+
- `:20+1` — anchor line 20 (single-range reads pad ≤1 leading / ≤3 trailing context lines).
|
|
21
|
+
- `:5-16,960-973` — multiple ranges in one call (sorted, overlaps merged); exact bounds, no padding.
|
|
22
|
+
- `:raw` — verbatim; no anchors, no summary, no line prefixes.
|
|
23
|
+
- `:2-4:raw` / `:raw:2-4` — range AND verbatim; compose in either order.
|
|
24
|
+
- `:conflicts` — one line per unresolved git merge conflict block.
|
|
26
25
|
|
|
27
26
|
# Files
|
|
28
27
|
|
|
29
|
-
-
|
|
28
|
+
- Directory path → depth-limited dirent listing.
|
|
30
29
|
{{#if IS_HL_MODE}}
|
|
31
|
-
-
|
|
30
|
+
- File with explicit selector → snapshot tag header + numbered lines: `[src/foo.ts#1A2B]` then `41:def alpha():`. Copy the `[PATH#TAG]` header for anchored edits; ops use bare line numbers. NEVER fabricate the tag.
|
|
32
31
|
{{else}}
|
|
33
32
|
{{#if IS_LINE_NUMBER_MODE}}
|
|
34
|
-
-
|
|
33
|
+
- File with explicit selector → lines prefixed with numbers: `41|def alpha():`.
|
|
35
34
|
{{/if}}
|
|
36
35
|
{{/if}}
|
|
37
|
-
- Parseable code without
|
|
38
|
-
|
|
39
|
-
`[NN lines elided; re-read needed ranges, e.g. <path>:5-16,40-80]`
|
|
40
|
-
|
|
41
|
-
Re-issue **only the relevant range(s)** using the multi-range selector (e.g. `<path>:5-16,120-200`). NEVER guess what's inside `..` / `…` — those markers carry no content. NEVER re-read the whole file or use `:raw` when targeted ranges suffice.
|
|
36
|
+
- Parseable code without selector → **structural summary**: declarations kept, bodies collapsed to `..` (merged brace pair) or `…` (standalone). The footer shows the recovery selector: `[NN lines elided; re-read needed ranges, e.g. <path>:5-16,40-80]`. Re-issue ONLY the ranges you need via the multi-range selector. `..`/`…` carry no content — NEVER guess what's inside; NEVER re-read the whole file or `:raw` when ranges suffice.
|
|
42
37
|
|
|
43
38
|
# Documents & Notebooks
|
|
44
39
|
|
|
45
|
-
|
|
40
|
+
PDF, Word, PowerPoint, Excel, RTF, EPUB → extracted text. Notebooks (`.ipynb`) → editable `# %% [type] cell:N` text; edits round-trip to the underlying JSON preserving metadata. `:raw` bypasses the converter.
|
|
46
41
|
|
|
47
42
|
# Images
|
|
48
43
|
|
|
49
44
|
{{#if INSPECT_IMAGE_ENABLED}}
|
|
50
|
-
|
|
45
|
+
Image path → metadata (mime, bytes, dimensions, channels, alpha). For visual analysis, call `inspect_image` with the path and a question.
|
|
51
46
|
{{else}}
|
|
52
|
-
|
|
47
|
+
Image path → decoded image inline (PNG, JPEG, GIF, WEBP) for direct visual analysis.
|
|
53
48
|
{{/if}}
|
|
54
49
|
|
|
55
50
|
# Archives
|
|
56
51
|
|
|
57
|
-
|
|
52
|
+
`.tar`, `.tar.gz`, `.tgz`, `.zip`. `archive.ext:path/inside/archive` reads a member; inner paths take normal selectors: `archive.zip:dir/file.ts:50-60`.
|
|
58
53
|
|
|
59
54
|
# SQLite
|
|
60
55
|
|
|
61
56
|
For `.sqlite`, `.sqlite3`, `.db`, `.db3`:
|
|
62
|
-
- `file.db` —
|
|
57
|
+
- `file.db` — tables with row counts
|
|
63
58
|
- `file.db:table` — schema + sample rows
|
|
64
|
-
- `file.db:table:key` —
|
|
65
|
-
- `file.db:table?limit=50&offset=100` —
|
|
66
|
-
- `file.db:table?where=status='active'&order=created:desc` —
|
|
67
|
-
- `file.db?q=SELECT …` — read-only SELECT
|
|
59
|
+
- `file.db:table:key` — row by primary key
|
|
60
|
+
- `file.db:table?limit=50&offset=100` — pagination
|
|
61
|
+
- `file.db:table?where=status='active'&order=created:desc` — filter/order
|
|
62
|
+
- `file.db?q=SELECT …` — read-only SELECT
|
|
68
63
|
|
|
69
64
|
# URLs
|
|
70
65
|
|
|
71
|
-
-
|
|
72
|
-
- `:raw`
|
|
73
|
-
- Bare `host:port`
|
|
66
|
+
- Reader-mode by default: HTML, GitHub issues/PRs, Stack Overflow, Wikipedia, Reddit, NPM, arXiv, RSS/Atom, JSON endpoints, PDFs → clean text/markdown.
|
|
67
|
+
- `:raw` → untouched HTML; line selectors (`:50`, `:50-100`, `:50+150`) paginate the cached fetch.
|
|
68
|
+
- Bare `host:port` collides with the selector grammar — add a trailing slash: `https://example.com/:80`.
|
|
74
69
|
|
|
75
70
|
# Internal URIs
|
|
76
71
|
|
|
77
|
-
|
|
72
|
+
All `path` URI schemes resolve transparently and take the same line selectors. `artifact://<id>` recovers full output a previous bash/eval/tool result spilled or truncated. `history://<agentId>` is an agent's transcript as concise markdown; bare `history://` lists agents.
|
|
78
73
|
|
|
79
74
|
<critical>
|
|
80
|
-
- You MUST use `read` for every file, directory, archive, and URL inspection. `cat`, `head`, `tail`, `less`, `more`, `ls`, `tar`, `unzip`, `curl`, `wget` are FORBIDDEN
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
- Summary footer names ranges to re-read? Re-issue ONLY the ranges you need via the multi-range selector. NEVER guess what's inside `..` / `…` markers — they carry no content.
|
|
75
|
+
- You MUST use `read` for every file, directory, archive, and URL inspection. `cat`, `head`, `tail`, `less`, `more`, `ls`, `tar`, `unzip`, `curl`, `wget` are FORBIDDEN bash calls, however short or convenient.
|
|
76
|
+
- Line ranges go in the selector (`path="src/foo.ts:50-200"`) — NEVER `sed -n`, `awk NR`, or `head`/`tail` pipelines.
|
|
77
|
+
- Summary footer names elided ranges? Re-issue ONLY those ranges. NEVER guess `..`/`…` content.
|
|
84
78
|
</critical>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{{#if asyncEnabled}}{{#if batchEnabled}}Spawns subagents to work in the background — one per `tasks[]` item; a single spawn is a one-item batch.{{else}}Spawns ONE subagent per call to work in the background.{{/if}}
|
|
2
2
|
|
|
3
3
|
- Spawning is non-blocking: the call returns immediately with the agent id{{#if batchEnabled}}s{{/if}} and job id{{#if batchEnabled}}s{{/if}}; each result is delivered automatically when that agent yields.
|
|
4
|
-
- Parallelism = {{#if batchEnabled}}`tasks[]` items in
|
|
4
|
+
- Parallelism = {{#if batchEnabled}}multiple `tasks[]` items in ONE call. To launch several subagents, you MUST batch them into a single call's `tasks[]` — they share `context` once instead of duplicating it. Separate `task` calls in one message are ONLY for spawns needing a different `agent` type or unrelated `context`{{else}}multiple `task` calls in one assistant message{{/if}}. Concurrency is bounded at {{MAX_CONCURRENCY}} running subagents per session.
|
|
5
5
|
- If genuinely blocked on a result, wait with `job poll`; otherwise keep working. `job cancel` terminates a task and **cannot carry a message** — only for stalled/abandoned work.
|
|
6
6
|
{{else}}{{#if batchEnabled}}Runs subagents synchronously — one per `tasks[]` item; a single spawn is a one-item batch.{{else}}Runs ONE subagent synchronously per call.{{/if}}
|
|
7
7
|
|
|
8
8
|
- Spawning is blocking: the call returns only after the agent{{#if batchEnabled}}s{{/if}} finish; results arrive inline.
|
|
9
|
-
- Parallelism = {{#if batchEnabled}}`tasks[]` items in
|
|
9
|
+
- Parallelism = {{#if batchEnabled}}multiple `tasks[]` items in ONE call. To launch several subagents, you MUST batch them into a single call's `tasks[]` — they share `context` once instead of duplicating it. Separate `task` calls in one message are ONLY for spawns needing a different `agent` type or unrelated `context`{{else}}multiple `task` calls in one assistant message{{/if}}. Concurrency is bounded at {{MAX_CONCURRENCY}} running subagents per session.
|
|
10
10
|
{{/if}}
|
|
11
11
|
{{#if ircEnabled}}
|
|
12
12
|
- Coordinate with agents via `irc` using their ids. Agents reach you and their siblings live the same way.
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
</parameters>
|
|
40
40
|
|
|
41
41
|
<rules>
|
|
42
|
-
- **Maximize fan-out.** Issue the widest {{#if batchEnabled}}`tasks[]` batch
|
|
42
|
+
- **Maximize fan-out.** Issue the widest {{#if batchEnabled}}`tasks[]` batch{{else}}set of parallel `task` calls{{/if}} the work decomposes into. NEVER serialize work that could run concurrently.
|
|
43
43
|
- **Subagents do not verify, lint, or format.** Every assignment MUST instruct the subagent to skip all gates, formatters, and project-wide build/test/lint. You run them once at the end across the union of changed files.
|
|
44
44
|
- No globs, no "update all", no package-wide scope. Fan out.
|
|
45
45
|
- NEVER slow down or serialize because tasks might overlap on some files. Agents resolve collisions among themselves in real time.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Manages a phased task list. Pass `ops`: a flat array of operations.
|
|
4
4
|
The next pending task is auto-promoted to `in_progress` after each completion.
|
|
5
|
-
Allowed `op` values are only `init`, `start`, `done`, `drop`, `rm`, `append`,
|
|
5
|
+
Allowed `op` values are only `init`, `start`, `done`, `drop`, `rm`, `append`, and `view`. `pending` is a task status, not an `op`; leave not-yet-started tasks implicit in `init`/`append` lists.
|
|
6
6
|
|
|
7
7
|
## Operations
|
|
8
8
|
|
|
@@ -14,7 +14,6 @@ Allowed `op` values are only `init`, `start`, `done`, `drop`, `rm`, `append`, `n
|
|
|
14
14
|
|`drop`|`task` or `phase`|Mark abandoned|
|
|
15
15
|
|`rm`|`task` or `phase` (optional)|Remove task or phase's tasks; omit both to clear the entire list|
|
|
16
16
|
|`append`|`phase`, `items: string[]`|Append tasks to `phase`; lazily creates phase|
|
|
17
|
-
|`note`|`task`, `text`|Append a note to a task. Reminders for future-you only.|
|
|
18
17
|
|`view`|—|Read-only: echo the current list without modifying it|
|
|
19
18
|
|
|
20
19
|
## Anatomy
|
package/src/sdk.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type ThinkingLevel,
|
|
10
10
|
} from "@oh-my-pi/pi-agent-core";
|
|
11
11
|
import {
|
|
12
|
+
type Context,
|
|
12
13
|
type CredentialDisabledEvent,
|
|
13
14
|
type Message,
|
|
14
15
|
type Model,
|
|
@@ -121,6 +122,7 @@ import {
|
|
|
121
122
|
wrapSteeringForModel,
|
|
122
123
|
} from "./session/messages";
|
|
123
124
|
import { getRestorableSessionModels, SessionManager } from "./session/session-manager";
|
|
125
|
+
import { SnapcompactInlineTransformer } from "./session/snapcompact-inline";
|
|
124
126
|
import { closeAllConnections } from "./ssh/connection-manager";
|
|
125
127
|
import { unmountAll } from "./ssh/sshfs-mount";
|
|
126
128
|
import {
|
|
@@ -1977,6 +1979,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1977
1979
|
workspaceTree: workspaceTreePromise,
|
|
1978
1980
|
memoryRootEnabled: memoryBackend.id === "local",
|
|
1979
1981
|
model: settings.get("includeModelInPrompt") ? getActiveModelString() : undefined,
|
|
1982
|
+
personality: agentKind === "sub" ? "none" : settings.get("personality"),
|
|
1980
1983
|
});
|
|
1981
1984
|
|
|
1982
1985
|
if (options.systemPrompt === undefined) {
|
|
@@ -2156,6 +2159,25 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2156
2159
|
const withContext = await extensionRunner.emitContext(messages);
|
|
2157
2160
|
return wrapSteeringForModel(withContext);
|
|
2158
2161
|
};
|
|
2162
|
+
// Per-request provider-context transforms. Obfuscate FIRST so secrets are
|
|
2163
|
+
// redacted from text before snapcompact rasterizes it into PNG frames.
|
|
2164
|
+
// Both operate on the transient outgoing Context only — never persisted.
|
|
2165
|
+
const snapcompactSystemPromptMode = settings.get("snapcompact.systemPrompt");
|
|
2166
|
+
const snapcompactInline =
|
|
2167
|
+
snapcompactSystemPromptMode !== "none" || settings.get("snapcompact.toolResults")
|
|
2168
|
+
? new SnapcompactInlineTransformer({
|
|
2169
|
+
renderSystemPrompt: snapcompactSystemPromptMode,
|
|
2170
|
+
renderToolResults: settings.get("snapcompact.toolResults"),
|
|
2171
|
+
})
|
|
2172
|
+
: undefined;
|
|
2173
|
+
const transformProviderContext =
|
|
2174
|
+
obfuscator || snapcompactInline
|
|
2175
|
+
? (context: Context, transformModel: Model): Context => {
|
|
2176
|
+
let transformed = obfuscator ? obfuscateProviderContext(obfuscator, context) : context;
|
|
2177
|
+
if (snapcompactInline) transformed = snapcompactInline.transform(transformed, transformModel);
|
|
2178
|
+
return transformed;
|
|
2179
|
+
}
|
|
2180
|
+
: undefined;
|
|
2159
2181
|
const onPayload = async (payload: unknown, _model?: Model) => {
|
|
2160
2182
|
return await extensionRunner.emitBeforeProviderRequest(payload);
|
|
2161
2183
|
};
|
|
@@ -2196,7 +2218,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2196
2218
|
sessionId: providerSessionId,
|
|
2197
2219
|
promptCacheKey: options.providerPromptCacheKey,
|
|
2198
2220
|
transformContext,
|
|
2199
|
-
transformProviderContext
|
|
2221
|
+
transformProviderContext,
|
|
2200
2222
|
steeringMode: settings.get("steeringMode") ?? "one-at-a-time",
|
|
2201
2223
|
followUpMode: settings.get("followUpMode") ?? "one-at-a-time",
|
|
2202
2224
|
interruptMode: settings.get("interruptMode") ?? "immediate",
|