@oh-my-pi/pi-coding-agent 15.10.11 → 15.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +103 -2
- package/dist/cli.js +5790 -5731
- package/dist/types/async/index.d.ts +0 -1
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/cli/gallery-fixtures/types.d.ts +5 -0
- package/dist/types/cli-commands.d.ts +12 -0
- package/dist/types/commands/launch.d.ts +4 -0
- package/dist/types/config/api-key-resolver.d.ts +3 -0
- package/dist/types/config/keybindings.d.ts +6 -1
- package/dist/types/config/model-registry.d.ts +1 -0
- package/dist/types/config/model-resolver.d.ts +18 -0
- package/dist/types/config/settings-schema.d.ts +85 -34
- package/dist/types/config/settings.d.ts +7 -0
- package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
- package/dist/types/eval/py/executor.d.ts +5 -0
- package/dist/types/eval/py/kernel.d.ts +6 -1
- package/dist/types/eval/py/runtime.d.ts +9 -0
- package/dist/types/exec/bash-executor.d.ts +2 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
- package/dist/types/extensibility/extensions/runner.d.ts +3 -2
- package/dist/types/extensibility/extensions/types.d.ts +3 -0
- package/dist/types/extensibility/shared-events.d.ts +2 -2
- package/dist/types/internal-urls/history-protocol.d.ts +14 -0
- package/dist/types/internal-urls/index.d.ts +1 -0
- package/dist/types/internal-urls/types.d.ts +1 -1
- package/dist/types/irc/bus.d.ts +66 -0
- package/dist/types/memory-backend/index.d.ts +1 -0
- package/dist/types/memory-backend/runtime.d.ts +4 -0
- package/dist/types/memory-backend/types.d.ts +66 -1
- package/dist/types/modes/components/agent-hub.d.ts +30 -0
- package/dist/types/modes/components/compaction-summary-message.d.ts +10 -4
- package/dist/types/modes/components/custom-editor.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +8 -0
- package/dist/types/modes/components/ttsr-notification.d.ts +5 -1
- package/dist/types/modes/components/welcome.d.ts +3 -9
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
- package/dist/types/modes/index.d.ts +3 -3
- package/dist/types/modes/interactive-mode.d.ts +10 -4
- package/dist/types/modes/oauth-manual-input.d.ts +7 -0
- package/dist/types/modes/rpc/rpc-client.d.ts +39 -2
- package/dist/types/modes/rpc/rpc-mode.d.ts +31 -2
- package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +75 -1
- package/dist/types/modes/setup-wizard/index.d.ts +5 -1
- package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +2 -1
- package/dist/types/modes/types.d.ts +5 -2
- package/dist/types/modes/utils/ui-helpers.d.ts +1 -1
- package/dist/types/registry/agent-lifecycle.d.ts +51 -0
- package/dist/types/registry/agent-registry.d.ts +16 -5
- package/dist/types/secrets/index.d.ts +1 -1
- package/dist/types/secrets/obfuscator.d.ts +8 -2
- package/dist/types/session/agent-session.d.ts +49 -32
- package/dist/types/session/messages.d.ts +2 -4
- package/dist/types/session/session-history-format.d.ts +12 -0
- package/dist/types/session/session-manager.d.ts +21 -3
- package/dist/types/session/streaming-output.d.ts +46 -0
- package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
- package/dist/types/slash-commands/builtin-registry.d.ts +1 -0
- package/dist/types/slash-commands/types.d.ts +1 -1
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +12 -2
- package/dist/types/task/index.d.ts +13 -6
- package/dist/types/task/output-manager.d.ts +0 -7
- package/dist/types/task/repair-args.d.ts +8 -7
- package/dist/types/task/types.d.ts +63 -51
- package/dist/types/thinking.d.ts +4 -0
- package/dist/types/tiny/title-client.d.ts +11 -0
- package/dist/types/tiny/title-protocol.d.ts +1 -0
- package/dist/types/tools/browser/tab-worker.d.ts +3 -1
- package/dist/types/tools/find.d.ts +0 -11
- package/dist/types/tools/grouped-file-output.d.ts +0 -49
- package/dist/types/tools/index.d.ts +7 -3
- package/dist/types/tools/irc.d.ts +76 -38
- package/dist/types/tools/job.d.ts +7 -1
- package/dist/types/utils/git.d.ts +15 -2
- package/dist/types/utils/title-generator.d.ts +3 -2
- package/examples/extensions/with-deps/package.json +1 -0
- package/package.json +11 -10
- package/scripts/bundle-dist.ts +28 -19
- package/src/async/index.ts +0 -1
- package/src/auto-thinking/classifier.ts +1 -0
- package/src/cli/args.ts +3 -0
- package/src/cli/gallery-cli.ts +1 -1
- package/src/cli/gallery-fixtures/agentic.ts +230 -115
- package/src/cli/gallery-fixtures/types.ts +5 -0
- package/src/cli-commands.ts +29 -0
- package/src/cli.ts +28 -15
- package/src/commands/launch.ts +4 -0
- package/src/commit/agentic/tools/analyze-file.ts +38 -19
- package/src/commit/model-selection.ts +3 -2
- package/src/config/api-key-resolver.ts +8 -6
- package/src/config/keybindings.ts +6 -1
- package/src/config/model-registry.ts +97 -30
- package/src/config/model-resolver.ts +60 -0
- package/src/config/settings-schema.ts +99 -55
- package/src/config/settings.ts +68 -3
- package/src/edit/hashline/execute.ts +39 -2
- package/src/edit/hashline/noop-loop-guard.ts +99 -0
- package/src/eval/__tests__/agent-bridge.test.ts +5 -3
- package/src/eval/agent-bridge.ts +3 -16
- package/src/eval/completion-bridge.ts +1 -0
- package/src/eval/js/shared/prelude.txt +1 -1
- package/src/eval/py/executor.ts +29 -7
- package/src/eval/py/index.ts +6 -1
- package/src/eval/py/kernel.ts +31 -11
- package/src/eval/py/prelude.py +5 -6
- package/src/eval/py/runtime.ts +37 -0
- package/src/exec/bash-executor.ts +82 -3
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +38 -13
- package/src/extensibility/custom-tools/types.ts +2 -2
- package/src/extensibility/extensions/get-commands-handler.ts +2 -1
- package/src/extensibility/extensions/runner.ts +6 -1
- package/src/extensibility/extensions/types.ts +3 -0
- package/src/extensibility/shared-events.ts +2 -2
- package/src/hindsight/bank.ts +17 -2
- package/src/internal-urls/docs-index.generated.ts +11 -11
- package/src/internal-urls/history-protocol.ts +113 -0
- package/src/internal-urls/index.ts +1 -0
- package/src/internal-urls/router.ts +3 -1
- package/src/internal-urls/types.ts +1 -1
- package/src/irc/bus.ts +292 -0
- package/src/main.ts +26 -66
- package/src/memories/index.ts +2 -0
- package/src/memory-backend/index.ts +1 -0
- package/src/memory-backend/local-backend.ts +9 -0
- package/src/memory-backend/off-backend.ts +9 -0
- package/src/memory-backend/runtime.ts +66 -0
- package/src/memory-backend/types.ts +81 -1
- package/src/mnemopi/backend.ts +151 -4
- package/src/modes/acp/acp-agent.ts +119 -11
- package/src/modes/components/{session-observer-overlay.ts → agent-hub.ts} +586 -367
- package/src/modes/components/assistant-message.ts +19 -21
- package/src/modes/components/compaction-summary-message.ts +68 -32
- package/src/modes/components/custom-editor.ts +10 -0
- package/src/modes/components/footer.ts +3 -1
- package/src/modes/components/status-line/component.ts +118 -34
- package/src/modes/components/tool-execution.ts +31 -1
- package/src/modes/components/ttsr-notification.ts +72 -30
- package/src/modes/components/welcome.ts +9 -33
- package/src/modes/controllers/command-controller.ts +1 -1
- package/src/modes/controllers/event-controller.ts +65 -0
- package/src/modes/controllers/extension-ui-controller.ts +8 -8
- package/src/modes/controllers/input-controller.ts +19 -2
- package/src/modes/controllers/mcp-command-controller.ts +38 -3
- package/src/modes/controllers/selector-controller.ts +21 -17
- package/src/modes/index.ts +3 -21
- package/src/modes/interactive-mode.ts +47 -22
- package/src/modes/oauth-manual-input.ts +30 -3
- package/src/modes/rpc/rpc-client.ts +154 -3
- package/src/modes/rpc/rpc-mode.ts +97 -12
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +81 -1
- package/src/modes/setup-wizard/index.ts +12 -2
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/theme/theme.ts +18 -5
- package/src/modes/types.ts +5 -5
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +51 -49
- package/src/prompts/system/irc-incoming.md +3 -4
- package/src/prompts/system/orchestrate-notice.md +2 -2
- package/src/prompts/system/subagent-system-prompt.md +0 -5
- package/src/prompts/system/system-prompt.md +1 -0
- package/src/prompts/system/workflow-notice.md +2 -2
- package/src/prompts/tools/eval.md +3 -3
- package/src/prompts/tools/irc.md +29 -19
- package/src/prompts/tools/read.md +2 -2
- package/src/prompts/tools/task-summary.md +5 -16
- package/src/prompts/tools/task.md +38 -29
- package/src/registry/agent-lifecycle.ts +218 -0
- package/src/registry/agent-registry.ts +16 -5
- package/src/sdk.ts +37 -10
- package/src/secrets/index.ts +8 -1
- package/src/secrets/obfuscator.ts +39 -18
- package/src/session/agent-session.ts +422 -291
- package/src/session/messages.ts +11 -78
- package/src/session/session-history-format.ts +246 -0
- package/src/session/session-manager.ts +59 -5
- package/src/session/streaming-output.ts +226 -10
- package/src/slash-commands/acp-builtins.ts +24 -0
- package/src/slash-commands/builtin-registry.ts +20 -0
- package/src/slash-commands/types.ts +1 -1
- package/src/system-prompt.ts +14 -0
- package/src/task/executor.ts +851 -461
- package/src/task/index.ts +721 -796
- package/src/task/output-manager.ts +0 -11
- package/src/task/render.ts +148 -63
- package/src/task/repair-args.ts +21 -9
- package/src/task/types.ts +82 -66
- package/src/thinking.ts +7 -0
- package/src/tiny/title-client.ts +34 -5
- package/src/tiny/title-protocol.ts +1 -1
- package/src/tiny/worker.ts +6 -4
- package/src/tools/ask.ts +4 -2
- package/src/tools/bash.ts +61 -10
- package/src/tools/browser/tab-worker.ts +26 -7
- package/src/tools/browser.ts +28 -1
- package/src/tools/find.ts +2 -27
- package/src/tools/grouped-file-output.ts +1 -118
- package/src/tools/image-gen.ts +11 -4
- package/src/tools/index.ts +17 -13
- package/src/tools/inspect-image.ts +1 -0
- package/src/tools/irc.ts +596 -171
- package/src/tools/job.ts +41 -7
- package/src/tools/read.ts +57 -1
- package/src/tools/renderers.ts +2 -0
- package/src/tools/resolve.ts +4 -1
- package/src/utils/commit-message-generator.ts +1 -0
- package/src/utils/git.ts +267 -13
- package/src/utils/title-generator.ts +24 -5
- package/dist/types/async/support.d.ts +0 -2
- package/dist/types/modes/components/session-observer-overlay.d.ts +0 -11
- package/dist/types/task/simple-mode.d.ts +0 -8
- package/src/async/support.ts +0 -5
- package/src/task/simple-mode.ts +0 -27
|
@@ -1,62 +1,76 @@
|
|
|
1
|
-
// Gallery fixtures for the agentic orchestration tools (task, goal, job).
|
|
1
|
+
// Gallery fixtures for the agentic orchestration tools (task, irc, goal, job).
|
|
2
|
+
import type { Usage } from "@oh-my-pi/pi-ai";
|
|
3
|
+
import type { TaskToolDetails } from "../../task/types";
|
|
4
|
+
import type { IrcDetails } from "../../tools/irc";
|
|
2
5
|
import type { GalleryFixture } from "./types";
|
|
3
6
|
|
|
7
|
+
/** Message/activity timestamps are offsets from load time so gallery ages stay plausible. */
|
|
8
|
+
const FIXTURE_NOW = Date.now();
|
|
9
|
+
|
|
10
|
+
/** Plausible cumulative usage for a fixture subagent run. */
|
|
11
|
+
const fixtureUsage = (tokens: { input: number; output: number }, costTotal: number): Usage => ({
|
|
12
|
+
input: tokens.input,
|
|
13
|
+
output: tokens.output,
|
|
14
|
+
cacheRead: 0,
|
|
15
|
+
cacheWrite: 0,
|
|
16
|
+
totalTokens: tokens.input + tokens.output,
|
|
17
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: costTotal },
|
|
18
|
+
});
|
|
19
|
+
|
|
4
20
|
export const agenticFixtures: Record<string, GalleryFixture> = {
|
|
5
21
|
task: {
|
|
6
22
|
label: "Task",
|
|
7
23
|
customRendered: true,
|
|
8
|
-
// Streaming: agent chosen,
|
|
24
|
+
// Streaming: agent chosen, assignment still landing.
|
|
9
25
|
streamingArgs: {
|
|
10
26
|
agent: "task",
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
description: "Load auth middleware",
|
|
15
|
-
assignment: "Read packages/server/src/auth/*.ts and summarize the session-cookie flow.",
|
|
16
|
-
},
|
|
17
|
-
{ id: "RateLimiter", description: "Audit rate limiter" },
|
|
18
|
-
],
|
|
27
|
+
id: "AuthLoader",
|
|
28
|
+
description: "Load auth middleware",
|
|
29
|
+
assignment: "Read packages/server/src/auth/*.ts and summarize the session-cookie",
|
|
19
30
|
},
|
|
20
31
|
args: {
|
|
21
32
|
agent: "task",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"Touch only files under packages/server/src/auth/. Do not run gates.",
|
|
27
|
-
].join("\n"),
|
|
28
|
-
tasks: [
|
|
29
|
-
{
|
|
30
|
-
id: "AuthLoader",
|
|
31
|
-
description: "Load auth middleware",
|
|
32
|
-
assignment:
|
|
33
|
-
"Read packages/server/src/auth/session.ts and middleware.ts, then document the session-cookie validation flow and any TODOs.",
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
id: "RateLimiter",
|
|
37
|
-
description: "Audit rate limiter",
|
|
38
|
-
assignment:
|
|
39
|
-
"Inspect packages/server/src/auth/rate-limit.ts. Confirm the 429 path sets Retry-After and report gaps.",
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
id: "TokenRotation",
|
|
43
|
-
description: "Check token rotation",
|
|
44
|
-
assignment:
|
|
45
|
-
"Trace refresh-token rotation in packages/server/src/auth/tokens.ts and flag any reuse window.",
|
|
46
|
-
},
|
|
47
|
-
],
|
|
33
|
+
id: "AuthLoader",
|
|
34
|
+
description: "Load auth middleware",
|
|
35
|
+
assignment:
|
|
36
|
+
"Read packages/server/src/auth/session.ts and middleware.ts, then document the session-cookie validation flow and any TODOs.",
|
|
48
37
|
},
|
|
49
38
|
result: {
|
|
50
39
|
content: [
|
|
51
40
|
{
|
|
52
41
|
type: "text",
|
|
53
|
-
text: "
|
|
42
|
+
text: "Agent AuthLoader completed.",
|
|
54
43
|
},
|
|
55
44
|
],
|
|
56
45
|
details: {
|
|
57
46
|
projectAgentsDir: null,
|
|
58
47
|
totalDurationMs: 48_200,
|
|
59
|
-
usage: {
|
|
48
|
+
usage: fixtureUsage({ input: 52_600, output: 8_800 }, 0.12),
|
|
49
|
+
progress: [
|
|
50
|
+
{
|
|
51
|
+
index: 0,
|
|
52
|
+
id: "AuthLoader",
|
|
53
|
+
agent: "task",
|
|
54
|
+
agentSource: "bundled",
|
|
55
|
+
status: "completed",
|
|
56
|
+
task: "Read packages/server/src/auth/session.ts and middleware.ts",
|
|
57
|
+
description: "Load auth middleware",
|
|
58
|
+
lastIntent: "Documenting session-cookie flow",
|
|
59
|
+
recentTools: [
|
|
60
|
+
{ tool: "read", args: "packages/server/src/auth/session.ts", endMs: 1_749_200_040_000 },
|
|
61
|
+
{ tool: "read", args: "packages/server/src/auth/middleware.ts", endMs: 1_749_200_052_000 },
|
|
62
|
+
],
|
|
63
|
+
recentOutput: ["Session validation runs in middleware.ts:42 via verifySessionCookie()."],
|
|
64
|
+
toolCount: 9,
|
|
65
|
+
requests: 6,
|
|
66
|
+
tokens: 61_400,
|
|
67
|
+
contextTokens: 23_100,
|
|
68
|
+
contextWindow: 200_000,
|
|
69
|
+
cost: 0.12,
|
|
70
|
+
durationMs: 41_900,
|
|
71
|
+
resolvedModel: "anthropic/claude-sonnet",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
60
74
|
results: [
|
|
61
75
|
{
|
|
62
76
|
index: 0,
|
|
@@ -77,100 +91,31 @@ export const agenticFixtures: Record<string, GalleryFixture> = {
|
|
|
77
91
|
truncated: false,
|
|
78
92
|
durationMs: 41_900,
|
|
79
93
|
tokens: 61_400,
|
|
94
|
+
requests: 6,
|
|
80
95
|
contextTokens: 23_100,
|
|
81
96
|
contextWindow: 200_000,
|
|
82
97
|
resolvedModel: "anthropic/claude-sonnet",
|
|
83
|
-
usage: {
|
|
98
|
+
usage: fixtureUsage({ input: 52_600, output: 8_800 }, 0.12),
|
|
84
99
|
outputMeta: { lineCount: 3, charCount: 214 },
|
|
85
100
|
},
|
|
86
|
-
{
|
|
87
|
-
index: 1,
|
|
88
|
-
id: "RateLimiter",
|
|
89
|
-
agent: "task",
|
|
90
|
-
agentSource: "bundled",
|
|
91
|
-
description: "Audit rate limiter",
|
|
92
|
-
task: "Inspect packages/server/src/auth/rate-limit.ts",
|
|
93
|
-
assignment:
|
|
94
|
-
"Inspect packages/server/src/auth/rate-limit.ts. Confirm the 429 path sets Retry-After and report gaps.",
|
|
95
|
-
exitCode: 0,
|
|
96
|
-
output: [
|
|
97
|
-
"rate-limit.ts uses a fixed-window counter keyed by client IP.",
|
|
98
|
-
"429 responses set Retry-After (rate-limit.ts:57).",
|
|
99
|
-
"Gap: no per-account limit, so a botnet across IPs bypasses the cap.",
|
|
100
|
-
].join("\n"),
|
|
101
|
-
stderr: "",
|
|
102
|
-
truncated: false,
|
|
103
|
-
durationMs: 38_500,
|
|
104
|
-
tokens: 54_800,
|
|
105
|
-
contextTokens: 19_700,
|
|
106
|
-
contextWindow: 200_000,
|
|
107
|
-
resolvedModel: "anthropic/claude-sonnet",
|
|
108
|
-
usage: { cost: { total: 0.1 } },
|
|
109
|
-
outputMeta: { lineCount: 3, charCount: 198 },
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
index: 2,
|
|
113
|
-
id: "TokenRotation",
|
|
114
|
-
agent: "task",
|
|
115
|
-
agentSource: "bundled",
|
|
116
|
-
description: "Check token rotation",
|
|
117
|
-
task: "Trace refresh-token rotation in packages/server/src/auth/tokens.ts",
|
|
118
|
-
assignment:
|
|
119
|
-
"Trace refresh-token rotation in packages/server/src/auth/tokens.ts and flag any reuse window.",
|
|
120
|
-
exitCode: 0,
|
|
121
|
-
output: [
|
|
122
|
-
"Refresh tokens rotate on every use (tokens.ts:120) and the old jti is revoked.",
|
|
123
|
-
"Reuse of a rotated token triggers full-family revocation — no reuse window found.",
|
|
124
|
-
].join("\n"),
|
|
125
|
-
stderr: "",
|
|
126
|
-
truncated: false,
|
|
127
|
-
durationMs: 48_200,
|
|
128
|
-
tokens: 49_200,
|
|
129
|
-
contextTokens: 17_500,
|
|
130
|
-
contextWindow: 200_000,
|
|
131
|
-
resolvedModel: "anthropic/claude-sonnet",
|
|
132
|
-
usage: { cost: { total: 0.12 } },
|
|
133
|
-
outputMeta: { lineCount: 2, charCount: 160 },
|
|
134
|
-
},
|
|
135
101
|
],
|
|
136
|
-
},
|
|
102
|
+
} satisfies TaskToolDetails,
|
|
137
103
|
},
|
|
138
104
|
errorResult: {
|
|
139
105
|
isError: true,
|
|
140
106
|
content: [
|
|
141
107
|
{
|
|
142
108
|
type: "text",
|
|
143
|
-
text: "
|
|
109
|
+
text: "Agent RateLimiter failed.",
|
|
144
110
|
},
|
|
145
111
|
],
|
|
146
112
|
details: {
|
|
147
113
|
projectAgentsDir: null,
|
|
148
|
-
totalDurationMs:
|
|
149
|
-
usage: {
|
|
114
|
+
totalDurationMs: 9_800,
|
|
115
|
+
usage: fixtureUsage({ input: 10_900, output: 1_400 }, 0.1),
|
|
150
116
|
results: [
|
|
151
117
|
{
|
|
152
118
|
index: 0,
|
|
153
|
-
id: "AuthLoader",
|
|
154
|
-
agent: "task",
|
|
155
|
-
agentSource: "bundled",
|
|
156
|
-
description: "Load auth middleware",
|
|
157
|
-
task: "Read packages/server/src/auth/session.ts and middleware.ts",
|
|
158
|
-
assignment:
|
|
159
|
-
"Read packages/server/src/auth/session.ts and middleware.ts, then document the session-cookie validation flow and any TODOs.",
|
|
160
|
-
exitCode: 0,
|
|
161
|
-
output: "Session validation runs in middleware.ts:42 via verifySessionCookie().",
|
|
162
|
-
stderr: "",
|
|
163
|
-
truncated: false,
|
|
164
|
-
durationMs: 31_200,
|
|
165
|
-
tokens: 58_100,
|
|
166
|
-
contextTokens: 21_900,
|
|
167
|
-
contextWindow: 200_000,
|
|
168
|
-
resolvedModel: "anthropic/claude-sonnet",
|
|
169
|
-
usage: { cost: { total: 0.11 } },
|
|
170
|
-
outputMeta: { lineCount: 1, charCount: 70 },
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
index: 1,
|
|
174
119
|
id: "RateLimiter",
|
|
175
120
|
agent: "task",
|
|
176
121
|
agentSource: "bundled",
|
|
@@ -184,15 +129,185 @@ export const agenticFixtures: Record<string, GalleryFixture> = {
|
|
|
184
129
|
truncated: false,
|
|
185
130
|
durationMs: 9_800,
|
|
186
131
|
tokens: 12_300,
|
|
132
|
+
requests: 3,
|
|
187
133
|
contextTokens: 6_400,
|
|
188
134
|
contextWindow: 200_000,
|
|
189
135
|
resolvedModel: "anthropic/claude-sonnet",
|
|
190
|
-
usage: {
|
|
136
|
+
usage: fixtureUsage({ input: 10_900, output: 1_400 }, 0.1),
|
|
191
137
|
error: "Subagent exited 1: target file packages/server/src/auth/rate-limit.ts does not exist.",
|
|
192
138
|
outputMeta: { lineCount: 0, charCount: 0 },
|
|
193
139
|
},
|
|
194
140
|
],
|
|
195
|
-
},
|
|
141
|
+
} satisfies TaskToolDetails,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
irc: {
|
|
146
|
+
label: "IRC",
|
|
147
|
+
// Streaming: recipient known; the message body still arriving.
|
|
148
|
+
streamingArgs: { op: "send", to: "AuthLoader", message: "Are you still touching" },
|
|
149
|
+
args: {
|
|
150
|
+
op: "send",
|
|
151
|
+
to: "AuthLoader",
|
|
152
|
+
message: "Are you still touching src/server/auth.ts? I need to add a 401 path.",
|
|
153
|
+
await: true,
|
|
154
|
+
},
|
|
155
|
+
result: {
|
|
156
|
+
content: [
|
|
157
|
+
{
|
|
158
|
+
type: "text",
|
|
159
|
+
text: [
|
|
160
|
+
"Delivered to 1 peer(s):",
|
|
161
|
+
"- AuthLoader: revived",
|
|
162
|
+
"",
|
|
163
|
+
"Reply from AuthLoader:",
|
|
164
|
+
"Done with auth.ts — go ahead, just rebase past my session-store rename.",
|
|
165
|
+
].join("\n"),
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
details: {
|
|
169
|
+
op: "send",
|
|
170
|
+
from: "Main",
|
|
171
|
+
to: "AuthLoader",
|
|
172
|
+
receipts: [{ to: "AuthLoader", outcome: "revived" }],
|
|
173
|
+
waited: {
|
|
174
|
+
id: "7181122334455667789",
|
|
175
|
+
from: "AuthLoader",
|
|
176
|
+
to: "Main",
|
|
177
|
+
body: "Done with auth.ts — go ahead, just rebase past my session-store rename.",
|
|
178
|
+
ts: FIXTURE_NOW - 5_000,
|
|
179
|
+
replyTo: "7181122334455667788",
|
|
180
|
+
},
|
|
181
|
+
} satisfies IrcDetails,
|
|
182
|
+
},
|
|
183
|
+
errorResult: {
|
|
184
|
+
isError: true,
|
|
185
|
+
content: [
|
|
186
|
+
{
|
|
187
|
+
type: "text",
|
|
188
|
+
text: 'No recipients received the message.\n- RateLimiter: failed — unknown agent "RateLimiter"',
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
details: {
|
|
192
|
+
op: "send",
|
|
193
|
+
from: "Main",
|
|
194
|
+
to: "RateLimiter",
|
|
195
|
+
receipts: [{ to: "RateLimiter", outcome: "failed", error: 'unknown agent "RateLimiter"' }],
|
|
196
|
+
} satisfies IrcDetails,
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
irc_wait: {
|
|
201
|
+
label: "IRC (wait)",
|
|
202
|
+
customRendered: true,
|
|
203
|
+
renderer: "irc",
|
|
204
|
+
streamingArgs: { op: "wait", from: "AuthLoader" },
|
|
205
|
+
args: { op: "wait", from: "AuthLoader", timeoutMs: 60_000 },
|
|
206
|
+
result: {
|
|
207
|
+
content: [
|
|
208
|
+
{
|
|
209
|
+
type: "text",
|
|
210
|
+
text: "[7181122334455667790] AuthLoader: session-store rename is merged; auth.ts is yours.",
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
details: {
|
|
214
|
+
op: "wait",
|
|
215
|
+
from: "Main",
|
|
216
|
+
waited: {
|
|
217
|
+
id: "7181122334455667790",
|
|
218
|
+
from: "AuthLoader",
|
|
219
|
+
to: "Main",
|
|
220
|
+
body: "session-store rename is merged; auth.ts is yours.",
|
|
221
|
+
ts: FIXTURE_NOW - 30_000,
|
|
222
|
+
},
|
|
223
|
+
} satisfies IrcDetails,
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
irc_inbox: {
|
|
228
|
+
label: "IRC (inbox)",
|
|
229
|
+
customRendered: true,
|
|
230
|
+
renderer: "irc",
|
|
231
|
+
streamingArgs: { op: "inbox" },
|
|
232
|
+
args: { op: "inbox", peek: true },
|
|
233
|
+
result: {
|
|
234
|
+
content: [
|
|
235
|
+
{
|
|
236
|
+
type: "text",
|
|
237
|
+
text: [
|
|
238
|
+
"2 unread message(s):",
|
|
239
|
+
"- [7181122334455667791] AuthLoader: hub table reads unreadCount — ping me when the bus lands.",
|
|
240
|
+
"- [7181122334455667792] RateLimiter (reply to 7181122334455667791): bus is in; receipts carry outcome.",
|
|
241
|
+
].join("\n"),
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
details: {
|
|
245
|
+
op: "inbox",
|
|
246
|
+
from: "Main",
|
|
247
|
+
inbox: [
|
|
248
|
+
{
|
|
249
|
+
id: "7181122334455667791",
|
|
250
|
+
from: "AuthLoader",
|
|
251
|
+
to: "Main",
|
|
252
|
+
body: "hub table reads unreadCount — ping me when the bus lands.",
|
|
253
|
+
ts: FIXTURE_NOW - 4 * 60_000,
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: "7181122334455667792",
|
|
257
|
+
from: "RateLimiter",
|
|
258
|
+
to: "Main",
|
|
259
|
+
body: "bus is in; receipts carry outcome.",
|
|
260
|
+
ts: FIXTURE_NOW - 60_000,
|
|
261
|
+
replyTo: "7181122334455667791",
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
} satisfies IrcDetails,
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
irc_list: {
|
|
269
|
+
label: "IRC (list)",
|
|
270
|
+
customRendered: true,
|
|
271
|
+
renderer: "irc",
|
|
272
|
+
streamingArgs: { op: "list" },
|
|
273
|
+
args: { op: "list" },
|
|
274
|
+
result: {
|
|
275
|
+
content: [
|
|
276
|
+
{
|
|
277
|
+
type: "text",
|
|
278
|
+
text: [
|
|
279
|
+
"2 peer(s):",
|
|
280
|
+
"- AuthLoader [task · sub · idle] — parent Main, active 2m ago",
|
|
281
|
+
"- RateLimiter [task · sub · parked] — unread 2, parent Main, active 12m ago",
|
|
282
|
+
"",
|
|
283
|
+
"Parked agents are revived automatically when you message them.",
|
|
284
|
+
].join("\n"),
|
|
285
|
+
},
|
|
286
|
+
],
|
|
287
|
+
details: {
|
|
288
|
+
op: "list",
|
|
289
|
+
from: "Main",
|
|
290
|
+
peers: [
|
|
291
|
+
{
|
|
292
|
+
id: "AuthLoader",
|
|
293
|
+
displayName: "task",
|
|
294
|
+
kind: "sub",
|
|
295
|
+
status: "idle",
|
|
296
|
+
parentId: "Main",
|
|
297
|
+
unread: 0,
|
|
298
|
+
lastActivity: FIXTURE_NOW - 2 * 60_000,
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
id: "RateLimiter",
|
|
302
|
+
displayName: "task",
|
|
303
|
+
kind: "sub",
|
|
304
|
+
status: "parked",
|
|
305
|
+
parentId: "Main",
|
|
306
|
+
unread: 2,
|
|
307
|
+
lastActivity: FIXTURE_NOW - 12 * 60_000,
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
} satisfies IrcDetails,
|
|
196
311
|
},
|
|
197
312
|
},
|
|
198
313
|
|
|
@@ -36,6 +36,11 @@ export interface GalleryFixture {
|
|
|
36
36
|
* real one keeps the gallery honest for these tools.
|
|
37
37
|
*/
|
|
38
38
|
customRendered?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Renderer-registry key to use when the fixture key is a variant of a tool
|
|
41
|
+
* (e.g. `irc_wait` → `irc`). Defaults to the fixture key.
|
|
42
|
+
*/
|
|
43
|
+
renderer?: string;
|
|
39
44
|
/**
|
|
40
45
|
* Arguments shown during the streaming state — a partial view of {@link args}
|
|
41
46
|
* as if the tool-call JSON were still arriving. May include `__partialJson`
|
package/src/cli-commands.ts
CHANGED
|
@@ -38,6 +38,18 @@ export const commands: CommandEntry[] = [
|
|
|
38
38
|
{ name: "search", load: () => import("./commands/web-search").then(m => m.default), aliases: ["q"] },
|
|
39
39
|
];
|
|
40
40
|
|
|
41
|
+
const RESERVED_TOP_LEVEL_WORDS = new Map<string, string>([
|
|
42
|
+
[
|
|
43
|
+
"extensions",
|
|
44
|
+
'`omp extensions` is not a management command. Use `omp plugin list` / `omp plugin install`, or run `omp launch extensions` if you meant to send "extensions" as a prompt.',
|
|
45
|
+
],
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
export function reservedTopLevelWordMessage(first: string | undefined, argc = 1): string | undefined {
|
|
49
|
+
if (argc !== 1 || !first || first.startsWith("-") || first.startsWith("@")) return undefined;
|
|
50
|
+
return RESERVED_TOP_LEVEL_WORDS.get(first);
|
|
51
|
+
}
|
|
52
|
+
|
|
41
53
|
/**
|
|
42
54
|
* Return true when `first` matches a registered subcommand name or alias.
|
|
43
55
|
*
|
|
@@ -48,3 +60,20 @@ export function isSubcommand(first: string | undefined): boolean {
|
|
|
48
60
|
if (!first || first.startsWith("-") || first.startsWith("@")) return false;
|
|
49
61
|
return commands.some(entry => entry.name === first || entry.aliases?.includes(first));
|
|
50
62
|
}
|
|
63
|
+
|
|
64
|
+
export type ResolvedCliArgv = { argv: string[] } | { error: string };
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Decide what the CLI runner should do with raw argv: reject bare reserved
|
|
68
|
+
* management words, pass help/version through untouched, and route everything
|
|
69
|
+
* that is not a known subcommand to `launch`.
|
|
70
|
+
*/
|
|
71
|
+
export function resolveCliArgv(argv: string[]): ResolvedCliArgv {
|
|
72
|
+
const first = argv[0];
|
|
73
|
+
const reservedMessage = reservedTopLevelWordMessage(first, argv.length);
|
|
74
|
+
if (reservedMessage) return { error: reservedMessage };
|
|
75
|
+
if (first === "--help" || first === "-h" || first === "--version" || first === "-v" || first === "help") {
|
|
76
|
+
return { argv };
|
|
77
|
+
}
|
|
78
|
+
return { argv: isSubcommand(first) ? argv : ["launch", ...argv] };
|
|
79
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -43,19 +43,33 @@ async function showHelp(config: CliConfig): Promise<void> {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
/**
|
|
46
|
-
* Smoke-test entry. Spawns bundled workers,
|
|
46
|
+
* Smoke-test entry. Spawns bundled workers, serves the stats dashboard once,
|
|
47
|
+
* pings everything, then exits.
|
|
47
48
|
*
|
|
48
|
-
* Purpose: catch the silent worker-load regressions that hit
|
|
49
|
-
* binaries
|
|
50
|
-
* modules on a fresh install, so this probe is
|
|
51
|
-
*
|
|
49
|
+
* Purpose: catch the silent worker-load and bundled-asset regressions that hit
|
|
50
|
+
* compiled binaries and the npm CLI bundle. Version/help paths do not spawn
|
|
51
|
+
* worker modules or serve dashboard assets on a fresh install, so this probe is
|
|
52
|
+
* the minimal end-to-end test that proves those distribution-only paths work.
|
|
52
53
|
* Wired into `scripts/install-tests/run-ci.sh` so binary / source-link /
|
|
53
54
|
* tarball installs all exercise it on every CI run.
|
|
54
55
|
*/
|
|
55
56
|
async function runSmokeTest(): Promise<void> {
|
|
56
|
-
const { smokeTestSyncWorker } = await import("@oh-my-pi/omp-stats");
|
|
57
|
+
const { smokeTestSyncWorker, startServer } = await import("@oh-my-pi/omp-stats");
|
|
57
58
|
const { smokeTestTinyTitleWorker } = await import("./tiny/title-client");
|
|
58
59
|
await smokeTestSyncWorker();
|
|
60
|
+
|
|
61
|
+
const statsServer = await startServer(0);
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(`http://127.0.0.1:${statsServer.port}/`);
|
|
64
|
+
if (!response.ok) throw new Error(`stats dashboard smoke failed: HTTP ${response.status}`);
|
|
65
|
+
const html = await response.text();
|
|
66
|
+
if (!html.includes('<div id="root"></div>') || !html.includes("index.js")) {
|
|
67
|
+
throw new Error("stats dashboard smoke failed: dashboard HTML was not served");
|
|
68
|
+
}
|
|
69
|
+
} finally {
|
|
70
|
+
statsServer.stop();
|
|
71
|
+
}
|
|
72
|
+
|
|
59
73
|
await smokeTestTinyTitleWorker();
|
|
60
74
|
process.stdout.write("smoke-test: ok\n");
|
|
61
75
|
}
|
|
@@ -161,20 +175,19 @@ export async function runCli(argv: string[]): Promise<void> {
|
|
|
161
175
|
if (await runWorkerEntrypoint(argv[0])) {
|
|
162
176
|
return;
|
|
163
177
|
}
|
|
164
|
-
const [{ run }, { commands,
|
|
178
|
+
const [{ run }, { commands, resolveCliArgv }] = await Promise.all([
|
|
165
179
|
import("@oh-my-pi/pi-utils/cli"),
|
|
166
180
|
import("./cli-commands"),
|
|
167
181
|
]);
|
|
168
182
|
// --help and --version are handled by run() directly, don't rewrite those.
|
|
169
183
|
// Everything else that isn't a known subcommand routes to "launch".
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return run({ bin: APP_NAME, version: VERSION, argv: runArgv, commands, help: showHelp });
|
|
184
|
+
const resolved = resolveCliArgv(argv);
|
|
185
|
+
if ("error" in resolved) {
|
|
186
|
+
process.stderr.write(`error: ${resolved.error}\n`);
|
|
187
|
+
process.exitCode = 1;
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
return run({ bin: APP_NAME, version: VERSION, argv: resolved.argv, commands, help: showHelp });
|
|
178
191
|
}
|
|
179
192
|
|
|
180
193
|
// Floating call instead of top-level await: TLA forces `--bytecode` (CJS
|
package/src/commands/launch.ts
CHANGED
|
@@ -56,6 +56,10 @@ export default class Index extends Command {
|
|
|
56
56
|
description: "Output mode: text (default), json, rpc, or rpc-ui",
|
|
57
57
|
options: ["text", "json", "rpc", "acp", "rpc-ui"],
|
|
58
58
|
}),
|
|
59
|
+
config: Flags.string({
|
|
60
|
+
description: "Load an extra config.yml-style overlay for this run (repeatable)",
|
|
61
|
+
multiple: true,
|
|
62
|
+
}),
|
|
59
63
|
print: Flags.boolean({
|
|
60
64
|
char: "p",
|
|
61
65
|
description: "Non-interactive mode: process prompt and exit",
|
|
@@ -43,6 +43,9 @@ function buildToolSession(
|
|
|
43
43
|
settings: options.settings,
|
|
44
44
|
authStorage: options.authStorage,
|
|
45
45
|
modelRegistry: options.modelRegistry,
|
|
46
|
+
// The task tool no longer takes a per-call schema; the inherited session
|
|
47
|
+
// schema drives structured output for every spawn from this session.
|
|
48
|
+
outputSchema: analyzeFileOutputSchema,
|
|
46
49
|
};
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -59,29 +62,45 @@ export function createAnalyzeFileTool(options: {
|
|
|
59
62
|
label: "Analyze Files",
|
|
60
63
|
description: "Spawn quick_task agents to analyze files.",
|
|
61
64
|
parameters: analyzeFileSchema,
|
|
62
|
-
async execute(toolCallId, params,
|
|
65
|
+
async execute(toolCallId, params, _onUpdate, ctx, signal) {
|
|
63
66
|
const toolSession = buildToolSession(ctx, options);
|
|
67
|
+
// The hand-built ToolSession carries no asyncJobManager, so every
|
|
68
|
+
// execute() below takes the task tool's sync fallback and resolves
|
|
69
|
+
// with the subagent's result inline — exactly what this flow needs.
|
|
70
|
+
// The tool's session semaphore bounds the parallel fan-out.
|
|
64
71
|
const taskTool = await TaskTool.create(toolSession);
|
|
65
72
|
const numstat = options.state.overview?.numstat ?? [];
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
file,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
73
|
+
|
|
74
|
+
const analyses = await Promise.all(
|
|
75
|
+
params.files.map((file, index) => {
|
|
76
|
+
const relatedFiles = formatRelatedFiles(params.files, file, numstat);
|
|
77
|
+
const assignment = prompt.render(analyzeFilePrompt, {
|
|
78
|
+
file,
|
|
79
|
+
goal: params.goal,
|
|
80
|
+
related_files: relatedFiles,
|
|
81
|
+
});
|
|
82
|
+
const taskParams: TaskParams = {
|
|
83
|
+
agent: "quick_task",
|
|
84
|
+
id: `AnalyzeFile${index + 1}`,
|
|
85
|
+
description: `Analyze ${file}`,
|
|
86
|
+
assignment,
|
|
87
|
+
};
|
|
88
|
+
return taskTool.execute(`${toolCallId}-${index + 1}`, taskParams, signal);
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
91
|
+
const results = analyses.flatMap(analysis => analysis.details?.results ?? []);
|
|
92
|
+
const text = analyses
|
|
93
|
+
.map(analysis => analysis.content.find(part => part.type === "text")?.text ?? "")
|
|
94
|
+
.filter(Boolean)
|
|
95
|
+
.join("\n\n");
|
|
96
|
+
return {
|
|
97
|
+
content: [{ type: "text", text: text || "(no output)" }],
|
|
98
|
+
details: {
|
|
99
|
+
projectAgentsDir: null,
|
|
100
|
+
results,
|
|
101
|
+
totalDurationMs: analyses.reduce((sum, analysis) => sum + (analysis.details?.totalDurationMs ?? 0), 0),
|
|
102
|
+
},
|
|
83
103
|
};
|
|
84
|
-
return taskTool.execute(toolCallId, taskParams, signal, onUpdate);
|
|
85
104
|
},
|
|
86
105
|
};
|
|
87
106
|
}
|
|
@@ -48,7 +48,7 @@ export async function resolvePrimaryModel(
|
|
|
48
48
|
}
|
|
49
49
|
return {
|
|
50
50
|
model,
|
|
51
|
-
apiKey: modelRegistry.resolver(model.provider, { baseUrl: model.baseUrl }),
|
|
51
|
+
apiKey: modelRegistry.resolver(model.provider, { baseUrl: model.baseUrl, modelId: model.id }),
|
|
52
52
|
thinkingLevel: resolved?.thinkingLevel,
|
|
53
53
|
};
|
|
54
54
|
}
|
|
@@ -68,6 +68,7 @@ export async function resolveSmolModel(
|
|
|
68
68
|
model: resolvedSmol.model,
|
|
69
69
|
apiKey: modelRegistry.resolver(resolvedSmol.model.provider, {
|
|
70
70
|
baseUrl: resolvedSmol.model.baseUrl,
|
|
71
|
+
modelId: resolvedSmol.model.id,
|
|
71
72
|
}),
|
|
72
73
|
thinkingLevel: resolvedSmol.thinkingLevel,
|
|
73
74
|
};
|
|
@@ -82,7 +83,7 @@ export async function resolveSmolModel(
|
|
|
82
83
|
if (apiKey) {
|
|
83
84
|
return {
|
|
84
85
|
model: candidate,
|
|
85
|
-
apiKey: modelRegistry.resolver(candidate.provider, { baseUrl: candidate.baseUrl }),
|
|
86
|
+
apiKey: modelRegistry.resolver(candidate.provider, { baseUrl: candidate.baseUrl, modelId: candidate.id }),
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
89
|
}
|