@oh-my-pi/pi-coding-agent 15.9.3 → 15.9.67
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 +74 -1
- package/dist/types/cli/classify-install-target.d.ts +5 -1
- package/dist/types/config/keybindings.d.ts +4 -1
- package/dist/types/config/settings-schema.d.ts +24 -5
- package/dist/types/edit/file-snapshot-store.d.ts +1 -1
- package/dist/types/eval/__tests__/kernel-spawn.test.d.ts +1 -0
- package/dist/types/eval/backend.d.ts +6 -6
- package/dist/types/eval/bridge-timeout.d.ts +27 -0
- package/dist/types/eval/idle-timeout.d.ts +16 -14
- package/dist/types/eval/js/executor.d.ts +3 -3
- package/dist/types/eval/py/executor.d.ts +2 -2
- package/dist/types/eval/py/spawn-options.d.ts +58 -0
- package/dist/types/modes/components/assistant-message.d.ts +16 -0
- package/dist/types/modes/components/copy-selector.d.ts +22 -0
- package/dist/types/modes/components/custom-editor.d.ts +3 -1
- package/dist/types/modes/components/error-banner.d.ts +11 -0
- package/dist/types/modes/components/model-selector.d.ts +1 -0
- package/dist/types/modes/components/tool-execution.d.ts +15 -0
- package/dist/types/modes/components/transcript-container.d.ts +1 -0
- package/dist/types/modes/components/user-message.d.ts +1 -1
- package/dist/types/modes/controllers/command-controller.d.ts +0 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/image-references.d.ts +17 -0
- package/dist/types/modes/interactive-mode.d.ts +8 -1
- package/dist/types/modes/types.d.ts +8 -1
- package/dist/types/modes/utils/copy-targets.d.ts +53 -0
- package/dist/types/modes/utils/ui-helpers.d.ts +1 -0
- package/dist/types/session/blob-store.d.ts +12 -11
- package/dist/types/session/session-manager.d.ts +5 -3
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/tiny/title-client.d.ts +16 -1
- package/dist/types/tool-discovery/mode.d.ts +8 -0
- package/dist/types/tools/archive-reader.d.ts +5 -1
- package/dist/types/tools/eval-render.d.ts +8 -0
- package/dist/types/tools/render-utils.d.ts +25 -0
- package/dist/types/tui/code-cell.d.ts +6 -0
- package/dist/types/tui/hyperlink.d.ts +12 -0
- package/dist/types/tui/output-block.d.ts +11 -0
- package/dist/types/web/search/render.d.ts +1 -2
- package/package.json +9 -9
- package/src/autoresearch/dashboard.ts +11 -21
- package/src/cli/classify-install-target.ts +31 -5
- package/src/cli/claude-trace-cli.ts +13 -1
- package/src/cli/plugin-cli.ts +45 -0
- package/src/cli/web-search-cli.ts +0 -1
- package/src/config/keybindings.ts +58 -1
- package/src/config/model-registry.ts +54 -4
- package/src/config/settings-schema.ts +25 -5
- package/src/debug/raw-sse.ts +18 -4
- package/src/edit/file-snapshot-store.ts +1 -1
- package/src/edit/index.ts +1 -1
- package/src/edit/renderer.ts +7 -7
- package/src/edit/streaming.ts +1 -1
- package/src/eval/__tests__/agent-bridge.test.ts +100 -27
- package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
- package/src/eval/__tests__/idle-timeout.test.ts +26 -12
- package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
- package/src/eval/__tests__/llm-bridge.test.ts +10 -10
- package/src/eval/__tests__/shared-executors.test.ts +2 -2
- package/src/eval/agent-bridge.ts +4 -5
- package/src/eval/backend.ts +6 -6
- package/src/eval/bridge-timeout.ts +44 -0
- package/src/eval/idle-timeout.ts +33 -15
- package/src/eval/js/executor.ts +10 -10
- package/src/eval/llm-bridge.ts +4 -5
- package/src/eval/py/executor.ts +6 -6
- package/src/eval/py/kernel.ts +11 -1
- package/src/eval/py/spawn-options.ts +126 -0
- package/src/eval/py/tool-bridge.ts +43 -5
- package/src/export/ttsr.ts +9 -0
- package/src/extensibility/custom-commands/bundled/ci-green/index.ts +31 -2
- package/src/extensibility/extensions/runner.ts +2 -0
- package/src/internal-urls/docs-index.generated.ts +9 -8
- package/src/lsp/client.ts +80 -2
- package/src/lsp/index.ts +38 -4
- package/src/lsp/render.ts +3 -3
- package/src/main.ts +8 -2
- package/src/modes/components/agent-dashboard.ts +13 -4
- package/src/modes/components/assistant-message.ts +44 -1
- package/src/modes/components/copy-selector.ts +249 -0
- package/src/modes/components/custom-editor.ts +14 -2
- package/src/modes/components/error-banner.ts +33 -0
- package/src/modes/components/extensions/extension-list.ts +17 -8
- package/src/modes/components/history-search.ts +19 -11
- package/src/modes/components/model-selector.ts +125 -29
- package/src/modes/components/oauth-selector.ts +28 -12
- package/src/modes/components/session-observer-overlay.ts +13 -15
- package/src/modes/components/session-selector.ts +24 -13
- package/src/modes/components/tool-execution.ts +71 -13
- package/src/modes/components/transcript-container.ts +93 -32
- package/src/modes/components/tree-selector.ts +19 -7
- package/src/modes/components/user-message-selector.ts +25 -14
- package/src/modes/components/user-message.ts +9 -2
- package/src/modes/controllers/command-controller.ts +0 -116
- package/src/modes/controllers/event-controller.ts +67 -12
- package/src/modes/controllers/input-controller.ts +33 -1
- package/src/modes/controllers/selector-controller.ts +38 -1
- package/src/modes/image-references.ts +111 -0
- package/src/modes/interactive-mode.ts +52 -17
- package/src/modes/theme/theme.ts +46 -10
- package/src/modes/types.ts +11 -2
- package/src/modes/utils/copy-targets.ts +254 -0
- package/src/modes/utils/ui-helpers.ts +23 -2
- package/src/prompts/ci-green-request.md +5 -3
- package/src/prompts/system/project-prompt.md +1 -0
- package/src/prompts/tools/ast-edit.md +1 -1
- package/src/prompts/tools/ast-grep.md +1 -1
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/search.md +1 -1
- package/src/sdk.ts +17 -9
- package/src/session/agent-session.ts +43 -14
- package/src/session/blob-store.ts +96 -9
- package/src/session/session-manager.ts +19 -10
- package/src/slash-commands/builtin-registry.ts +3 -11
- package/src/system-prompt.ts +4 -0
- package/src/task/render.ts +38 -11
- package/src/tiny/title-client.ts +7 -1
- package/src/tool-discovery/mode.ts +24 -0
- package/src/tools/archive-reader.ts +339 -31
- package/src/tools/bash.ts +18 -8
- package/src/tools/browser/render.ts +5 -4
- package/src/tools/debug.ts +3 -3
- package/src/tools/eval-render.ts +24 -9
- package/src/tools/eval.ts +14 -19
- package/src/tools/fetch.ts +34 -14
- package/src/tools/gh.ts +65 -11
- package/src/tools/index.ts +6 -8
- package/src/tools/read.ts +65 -19
- package/src/tools/render-utils.ts +46 -0
- package/src/tools/search-tool-bm25.ts +4 -6
- package/src/tools/search.ts +60 -11
- package/src/tools/ssh.ts +21 -8
- package/src/tools/write.ts +17 -8
- package/src/tui/code-cell.ts +19 -4
- package/src/tui/hyperlink.ts +42 -7
- package/src/tui/output-block.ts +14 -0
- package/src/web/search/index.ts +2 -2
- package/src/web/search/render.ts +23 -55
- package/dist/types/eval/heartbeat.d.ts +0 -45
- package/src/eval/__tests__/heartbeat.test.ts +0 -84
- package/src/eval/heartbeat.ts +0 -74
- /package/dist/types/eval/__tests__/{heartbeat.test.d.ts → bridge-timeout.test.d.ts} +0 -0
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it } from "bun:test";
|
|
2
|
-
import { EVAL_HEARTBEAT_OP, setBridgeHeartbeatIntervalMs, withBridgeHeartbeat } from "../heartbeat";
|
|
3
|
-
import type { JsStatusEvent } from "../js/shared/types";
|
|
4
|
-
|
|
5
|
-
describe("withBridgeHeartbeat", () => {
|
|
6
|
-
afterEach(() => {
|
|
7
|
-
setBridgeHeartbeatIntervalMs();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it("pumps heartbeat events on cadence while the operation is pending, then stops", async () => {
|
|
11
|
-
setBridgeHeartbeatIntervalMs(20);
|
|
12
|
-
const events: JsStatusEvent[] = [];
|
|
13
|
-
|
|
14
|
-
const value = await withBridgeHeartbeat(
|
|
15
|
-
event => events.push(event),
|
|
16
|
-
async () => {
|
|
17
|
-
await Bun.sleep(130);
|
|
18
|
-
return "done";
|
|
19
|
-
},
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
expect(value).toBe("done");
|
|
23
|
-
// ~6 ticks fit in 130ms at a 20ms cadence; assert it ticked repeatedly
|
|
24
|
-
// without pinning the exact count (scheduler jitter).
|
|
25
|
-
expect(events.length).toBeGreaterThanOrEqual(3);
|
|
26
|
-
expect(events.every(event => event.op === EVAL_HEARTBEAT_OP)).toBe(true);
|
|
27
|
-
|
|
28
|
-
// The interval is cleared once the operation settles: no further ticks.
|
|
29
|
-
const settledCount = events.length;
|
|
30
|
-
await Bun.sleep(80);
|
|
31
|
-
expect(events.length).toBe(settledCount);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("emits a heartbeat immediately so a bridge call extends the budget at once", async () => {
|
|
35
|
-
// Interval far longer than the operation: the only beat that can fire is
|
|
36
|
-
// the immediate one at call start. It must still reach the sink.
|
|
37
|
-
setBridgeHeartbeatIntervalMs(10_000);
|
|
38
|
-
const events: JsStatusEvent[] = [];
|
|
39
|
-
|
|
40
|
-
await withBridgeHeartbeat(
|
|
41
|
-
event => events.push(event),
|
|
42
|
-
async () => {
|
|
43
|
-
await Bun.sleep(30);
|
|
44
|
-
return "done";
|
|
45
|
-
},
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
expect(events.length).toBe(1);
|
|
49
|
-
expect(events[0]?.op).toBe(EVAL_HEARTBEAT_OP);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("runs the operation without emitting when no status sink is wired", async () => {
|
|
53
|
-
setBridgeHeartbeatIntervalMs(5);
|
|
54
|
-
let ran = 0;
|
|
55
|
-
|
|
56
|
-
const value = await withBridgeHeartbeat(undefined, async () => {
|
|
57
|
-
ran++;
|
|
58
|
-
await Bun.sleep(40);
|
|
59
|
-
return 42;
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
expect(value).toBe(42);
|
|
63
|
-
expect(ran).toBe(1);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("clears the heartbeat even when the operation throws", async () => {
|
|
67
|
-
setBridgeHeartbeatIntervalMs(15);
|
|
68
|
-
const events: JsStatusEvent[] = [];
|
|
69
|
-
|
|
70
|
-
await expect(
|
|
71
|
-
withBridgeHeartbeat(
|
|
72
|
-
event => events.push(event),
|
|
73
|
-
async () => {
|
|
74
|
-
await Bun.sleep(60);
|
|
75
|
-
throw new Error("boom");
|
|
76
|
-
},
|
|
77
|
-
),
|
|
78
|
-
).rejects.toThrow("boom");
|
|
79
|
-
|
|
80
|
-
const afterThrow = events.length;
|
|
81
|
-
await Bun.sleep(60);
|
|
82
|
-
expect(events.length).toBe(afterThrow);
|
|
83
|
-
});
|
|
84
|
-
});
|
package/src/eval/heartbeat.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Keepalive for in-flight host-side eval bridge calls.
|
|
3
|
-
*
|
|
4
|
-
* The eval watchdog ({@link ../tools/eval IdleTimeout}) caps a cell's `timeout`
|
|
5
|
-
* as a wall-clock budget on the cell's *own* work, but pauses that budget while
|
|
6
|
-
* a host-side `agent()`/`parallel()` (via `runSubprocess`) or `llm()` (a single
|
|
7
|
-
* completion) call is in flight. Those calls are the only thing that re-arms the
|
|
8
|
-
* watchdog — and they can run for long stretches with **no** status of their own
|
|
9
|
-
* (a subagent's time-to-first-token on a reasoning model, a long quiet nested
|
|
10
|
-
* tool, or the entire body of a oneshot `llm()` call). Without a keepalive the
|
|
11
|
-
* watchdog would mistake that delegated work for the cell stalling and abort it
|
|
12
|
-
* mid-flight, killing the subagent.
|
|
13
|
-
*
|
|
14
|
-
* {@link withBridgeHeartbeat} bridges that gap by emitting a synthetic
|
|
15
|
-
* {@link EVAL_HEARTBEAT_OP} status event immediately when the call begins and
|
|
16
|
-
* then on a fixed cadence until it settles. The event rides the same
|
|
17
|
-
* `emitStatus → onStatus` channel both runtimes already forward, so it re-arms
|
|
18
|
-
* the watchdog without any new plumbing. The heartbeat is the *sole* signal that
|
|
19
|
-
* extends the budget: consumers MUST treat it as a pure keepalive — bump the
|
|
20
|
-
* watchdog and drop it (never persist or render it) — see the executor display
|
|
21
|
-
* sinks and the eval tool's `onStatus` handler. Every other status event
|
|
22
|
-
* (compute helpers, `log()`/`phase()`, tool results) counts against the budget.
|
|
23
|
-
*/
|
|
24
|
-
import type { JsStatusEvent } from "./js/shared/types";
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Synthetic status op emitted purely to keep the eval idle watchdog alive while
|
|
28
|
-
* a host-side bridge call is in flight. Carries no payload.
|
|
29
|
-
*/
|
|
30
|
-
export const EVAL_HEARTBEAT_OP = "heartbeat";
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Heartbeat cadence. Comfortably below the default 30s idle budget (and the
|
|
34
|
-
* larger budgets long fanouts run under), so a working bridge call always bumps
|
|
35
|
-
* the watchdog before it expires, while a genuine stall is still bounded once
|
|
36
|
-
* the call settles and the heartbeat stops.
|
|
37
|
-
*/
|
|
38
|
-
const HEARTBEAT_INTERVAL_MS = 5_000;
|
|
39
|
-
|
|
40
|
-
let heartbeatIntervalMs = HEARTBEAT_INTERVAL_MS;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Test seam: override the heartbeat cadence so integration tests can exercise
|
|
44
|
-
* the keepalive within a sub-second idle budget. Pass no value to restore the
|
|
45
|
-
* production default.
|
|
46
|
-
*/
|
|
47
|
-
export function setBridgeHeartbeatIntervalMs(ms?: number): void {
|
|
48
|
-
heartbeatIntervalMs = ms === undefined ? HEARTBEAT_INTERVAL_MS : Math.max(1, Math.floor(ms));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Run {@link operation}, pumping {@link EVAL_HEARTBEAT_OP} status events through
|
|
53
|
-
* {@link emitStatus} — one immediately, then on a fixed cadence — until it
|
|
54
|
-
* settles. The immediate beat pauses the watchdog the instant the call begins,
|
|
55
|
-
* so a bridge call that starts close to the budget edge (after the cell already
|
|
56
|
-
* spent most of it computing) is not aborted before the first interval tick. A
|
|
57
|
-
* no-op wrapper when no `emitStatus` sink is wired (the heartbeat would reach
|
|
58
|
-
* nobody).
|
|
59
|
-
*/
|
|
60
|
-
export async function withBridgeHeartbeat<T>(
|
|
61
|
-
emitStatus: ((event: JsStatusEvent) => void) | undefined,
|
|
62
|
-
operation: () => Promise<T>,
|
|
63
|
-
): Promise<T> {
|
|
64
|
-
if (!emitStatus) return operation();
|
|
65
|
-
emitStatus({ op: EVAL_HEARTBEAT_OP });
|
|
66
|
-
const timer = setInterval(() => emitStatus({ op: EVAL_HEARTBEAT_OP }), heartbeatIntervalMs);
|
|
67
|
-
// Never keep the event loop alive for the heartbeat alone.
|
|
68
|
-
timer.unref?.();
|
|
69
|
-
try {
|
|
70
|
-
return await operation();
|
|
71
|
-
} finally {
|
|
72
|
-
clearInterval(timer);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
File without changes
|