pikiloom 0.4.61 → 0.4.63

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 (36) hide show
  1. package/README.md +1 -1
  2. package/dist/browser-profile.js +3 -2
  3. package/dist/core/constants.js +4 -0
  4. package/package.json +2 -1
  5. package/packages/kernel/README.md +20 -7
  6. package/packages/kernel/dist/contracts/driver.d.ts +1 -0
  7. package/packages/kernel/dist/drivers/acp.js +30 -163
  8. package/packages/kernel/dist/drivers/claude.d.ts +2 -21
  9. package/packages/kernel/dist/drivers/claude.js +61 -57
  10. package/packages/kernel/dist/drivers/codex.d.ts +0 -10
  11. package/packages/kernel/dist/drivers/codex.js +47 -144
  12. package/packages/kernel/dist/drivers/gemini.js +9 -27
  13. package/packages/kernel/dist/drivers/hermes.d.ts +1 -2
  14. package/packages/kernel/dist/drivers/hermes.js +1 -4
  15. package/packages/kernel/dist/drivers/index.d.ts +5 -4
  16. package/packages/kernel/dist/drivers/index.js +8 -4
  17. package/packages/kernel/dist/{workspace → drivers}/native.d.ts +0 -1
  18. package/packages/kernel/dist/{workspace → drivers}/native.js +212 -45
  19. package/packages/kernel/dist/drivers/rpc.d.ts +45 -0
  20. package/packages/kernel/dist/drivers/rpc.js +130 -0
  21. package/packages/kernel/dist/drivers/shared.d.ts +21 -0
  22. package/packages/kernel/dist/drivers/shared.js +66 -0
  23. package/packages/kernel/dist/index.d.ts +2 -1
  24. package/packages/kernel/dist/index.js +10 -2
  25. package/packages/kernel/dist/protocol/index.d.ts +5 -0
  26. package/packages/kernel/dist/protocol/index.js +10 -0
  27. package/packages/kernel/dist/runtime/hub.js +10 -8
  28. package/packages/kernel/dist/workspace/index.d.ts +1 -2
  29. package/packages/kernel/dist/workspace/index.js +3 -2
  30. package/packages/kernel/dist/workspace/mcp.js +6 -16
  31. package/packages/kernel/dist/workspace/npm-search.d.ts +9 -0
  32. package/packages/kernel/dist/workspace/npm-search.js +21 -0
  33. package/packages/kernel/dist/workspace/sessions.d.ts +3 -0
  34. package/packages/kernel/dist/workspace/sessions.js +28 -14
  35. package/packages/kernel/dist/workspace/skills.d.ts +11 -0
  36. package/packages/kernel/dist/workspace/skills.js +14 -20
package/README.md CHANGED
@@ -368,7 +368,7 @@ Questions, feedback, or want to compare notes on agent orchestration? Add me on
368
368
  ## Star History
369
369
 
370
370
  <a href="https://www.star-history.com/#xiaotonng/pikiloom&Date">
371
- <img src="https://api.star-history.com/svg?repos=xiaotonng/pikiloom&type=Date" alt="Star History" width="640">
371
+ <img src="https://raw.githubusercontent.com/xiaotonng/pikiloom/main/docs/star-history.svg" alt="Star History" width="640">
372
372
  </a>
373
373
 
374
374
  ---
@@ -3,7 +3,7 @@ import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { createRequire } from 'node:module';
5
5
  import { spawn, spawnSync } from 'node:child_process';
6
- import { MANAGED_BROWSER_PROFILE_SUBPATH, PIKILOOM_BROWSER_CDP_URL_ENV, PLAYWRIGHT_MCP_PACKAGE_NAME, PLAYWRIGHT_MCP_PACKAGE_SPEC, PLAYWRIGHT_MCP_BROWSER_ARGS, } from './core/constants.js';
6
+ import { MANAGED_BROWSER_PROFILE_SUBPATH, MANAGED_BROWSER_STEALTH_ARGS, PIKILOOM_BROWSER_CDP_URL_ENV, PLAYWRIGHT_MCP_PACKAGE_NAME, PLAYWRIGHT_MCP_PACKAGE_SPEC, PLAYWRIGHT_MCP_BROWSER_ARGS, } from './core/constants.js';
7
7
  const MANAGED_BROWSER_SETUP_STATE_FILENAME = 'managed-browser-setup.json';
8
8
  const MANAGED_BROWSER_SHUTDOWN_TIMEOUT_MS = 5_000;
9
9
  const MANAGED_BROWSER_SHUTDOWN_POLL_MS = 100;
@@ -148,7 +148,7 @@ export function ensurePlaywrightMcpConfigFile(outputDir = path.dirname(getManage
148
148
  const desired = JSON.stringify({
149
149
  browser: {
150
150
  launchOptions: {
151
- ignoreDefaultArgs: ['--disable-blink-features=AutomationControlled'],
151
+ args: [...MANAGED_BROWSER_STEALTH_ARGS],
152
152
  },
153
153
  },
154
154
  }, null, 2);
@@ -211,6 +211,7 @@ export function getManagedBrowserLaunchArgs(profileDir = getManagedBrowserProfil
211
211
  return [
212
212
  `--user-data-dir=${profileDir}`,
213
213
  '--remote-debugging-port=0',
214
+ ...MANAGED_BROWSER_STEALTH_ARGS,
214
215
  '--no-first-run',
215
216
  '--no-default-browser-check',
216
217
  '--new-window',
@@ -26,6 +26,10 @@ export const PLAYWRIGHT_MCP_PACKAGE_NAME = '@playwright/mcp';
26
26
  export const PLAYWRIGHT_MCP_PACKAGE_VERSION = '0.0.75';
27
27
  export const PLAYWRIGHT_MCP_PACKAGE_SPEC = `${PLAYWRIGHT_MCP_PACKAGE_NAME}@${PLAYWRIGHT_MCP_PACKAGE_VERSION}`;
28
28
  export const PLAYWRIGHT_MCP_BROWSER_ARGS = ['--browser', 'chrome', '--viewport-size', '1920x1080'];
29
+ // Chrome 150+ sets navigator.webdriver=true whenever remote debugging is on, which trips
30
+ // Google's "This browser or app may not be secure" sign-in block; --test-type suppresses
31
+ // the "unsupported command-line flag" infobar that the first flag would otherwise trigger.
32
+ export const MANAGED_BROWSER_STEALTH_ARGS = ['--disable-blink-features=AutomationControlled', '--test-type'];
29
33
  export const PIKILOOM_BROWSER_CDP_URL_ENV = 'PIKILOOM_BROWSER_CDP_URL';
30
34
  export const DASHBOARD_PAGINATION = {
31
35
  defaultPageSize: 6,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pikiloom",
3
- "version": "0.4.61",
3
+ "version": "0.4.63",
4
4
  "description": "Put the world's smartest AI agents in your pocket. Command local Claude & Gemini via IM. | 让最好用的 IM 变成你电脑上的顶级 Agent 控制台",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,6 +10,7 @@
10
10
  "dist/",
11
11
  "dashboard/dist/",
12
12
  "packages/kernel/dist/",
13
+ "packages/kernel/examples/console.html",
13
14
  "LICENSE",
14
15
  "README.md"
15
16
  ],
@@ -205,7 +205,8 @@ interrupts only the current turn and the next queued task promotes.
205
205
  | `ClaudeDriver` | `claude` | `claude` CLI, stream-json (+ `--effort`, partial messages) | ✓ | — | ✓ | ✓ |
206
206
  | `CodexDriver` | `codex` | `codex app-server` JSON-RPC (HITL via `requestUserInput`) | ✓ | via askUser | ✓ | ✓ |
207
207
  | `GeminiDriver` | `gemini` | `gemini --output-format stream-json` | — | — | ✓ | ✓ |
208
- | `HermesDriver` | `hermes` | ACP `session/update` | — | | ✓ | — |
208
+ | `AcpDriver` | *(config)* | generic ACP ndjson JSON-RPC — any ACP CLI: `new AcpDriver({ id, command, args })` | — | via askUser | ✓ | — |
209
+ | `HermesDriver` | `hermes` | ACP preset over `AcpDriver` (`hermes acp`) | — | via askUser | ✓ | — |
209
210
  | `EchoDriver` | `echo` | none (hermetic, in-process) | ✓ | ✓ | ✓ | ✓ |
210
211
 
211
212
  Write your own by implementing `AgentDriver` and passing it to `createLoom({ drivers })` (or
@@ -311,16 +312,28 @@ node-builtins-only and additive — every existing port/default is unchanged.
311
312
 
312
313
  ## Exports
313
314
 
314
- Main entry `@pikiloom/kernel` re-exports everything. Subpaths: `@pikiloom/kernel/drivers`,
315
- `@pikiloom/kernel/surfaces`, `@pikiloom/kernel/protocol`.
315
+ Main entry `@pikiloom/kernel` is the public API, pinned by `test/api-surface.test.ts`.
316
+ Subpaths: `@pikiloom/kernel/drivers`, `@pikiloom/kernel/surfaces`, `@pikiloom/kernel/protocol`.
317
+ Driver-internal parser/settle helpers are exported only from their modules (for white-box
318
+ tests) and are NOT part of the public surface.
316
319
 
317
320
  - Runtime: `createLoom`, `Loom`, `Hub`, `SessionRunner`, `runTurn`, `PtyBridge`, `ptyAvailable`, `attachTui`
318
- - Drivers: `EchoDriver`, `ClaudeDriver`, `CodexDriver`, `GeminiDriver`, `HermesDriver`
321
+ - Drivers: `EchoDriver`, `ClaudeDriver`, `CodexDriver`, `GeminiDriver`, `AcpDriver` (+ `AcpDriverConfig`), `HermesDriver`
322
+ - Native discovery (driver-axis): `discover{Claude,Codex,Gemini}NativeSessions`, `encodeClaudeProjectDir` + type `DiscoverOptions`
319
323
  - Surfaces: `WebSurface`, `CliSurface`
320
324
  - Ports/defaults: `FsSessionStore`, `NullModelResolver`, `NoopToolProvider`, `PassthroughSystemPromptBuilder`, `AutoCancelInteractionHandler`, `DeferToTerminalInteractionHandler`, `NoopCatalog`, `defaultBaseDir`
321
- - Workspace: `resolveLoomPaths`, `SessionsManager`, `SkillsManager`, `McpRegistry`, `ensureDirSymlink`, `discover{Claude,Codex,Gemini}NativeSessions` + types `LoomPaths`, `LoomScope`, `ManagedSessionInfo`, `NativeSessionInfo`, `SkillInfo`, `McpCatalogEntry`
322
- - Protocol: `UniversalSnapshot`, `diffSnapshot`, `applySnapshotPatch`, `emptySnapshot`, `PROTOCOL_VERSION`, all wire/`Client*`/`Server*` message types
323
- - Types: `AgentDriver`, `AgentTurnInput`, `DriverContext`, `DriverEvent`, `DriverResult`, `LoomIO`, `PromptInput`, `Surface`, `Plugin`, `SpawnContribution`, `SessionStore`, `ModelResolver`, `ToolProvider`, `SystemPromptBuilder`, `InteractionHandler`, `Catalog`, …
325
+ - Workspace: `resolveLoomPaths`, `normalizeStateDirName`, `SessionsManager`, `SkillsManager`, `McpRegistry`, `ensureDirSymlink`, `parseSkillMeta` + types `LoomPaths`, `LoomScope`, `ManagedSessionInfo`, `SkillInfo`, `SkillMeta`, `McpCatalogEntry`
326
+ - Multi-account: `accountTokenSupported`, `accountTokenEnvVar`, `accountTokenEnv` — which env var carries an agent's auth token, so an app can inject a selected account's token per spawn (claude: `CLAUDE_CODE_OAUTH_TOKEN`; storage/selection stay app-side)
327
+ - Protocol: `UniversalSnapshot`, `diffSnapshot`, `applySnapshotPatch`, `emptySnapshot`, `PROTOCOL_VERSION`, `makeSessionKey`, `splitSessionKey`, all wire/`Client*`/`Server*` message types
328
+ - Types: `AgentDriver`, `AgentTurnInput`, `DriverContext`, `DriverEvent`, `DriverResult`, `NativeSessionInfo`, `LoomIO`, `PromptInput`, `Surface`, `Plugin`, `SpawnContribution`, `SessionStore`, `ModelResolver`, `ToolProvider`, `SystemPromptBuilder`, `InteractionHandler`, `Catalog`, …
329
+
330
+ ### Claude driver tuning (env)
331
+
332
+ The claude driver's background-hold / stall / recovery heuristics ship sane defaults and can
333
+ be tuned per deployment: `PIKILOOM_CLAUDE_BG_HOLD_MS`, `PIKILOOM_CLAUDE_BG_AGENT_HOLD_MS`,
334
+ `PIKILOOM_CLAUDE_BG_HOLD_RECHECK_MS`, `PIKILOOM_CLAUDE_BG_SETTLE_QUIET_MS`,
335
+ `PIKILOOM_CLAUDE_MODEL_STALL_MS`, `PIKILOOM_CLAUDE_TRUNCATED_RECOVERY` (=0 disables),
336
+ `PIKILOOM_CLAUDE_RESUME_NOOP_RETRIES`.
324
337
 
325
338
  ---
326
339
 
@@ -88,6 +88,7 @@ export interface NativeSessionInfo {
88
88
  preview: string | null;
89
89
  cwd: string | null;
90
90
  model: string | null;
91
+ effort?: string | null;
91
92
  createdAt: string | null;
92
93
  updatedAt: string | null;
93
94
  running: boolean;
@@ -1,132 +1,7 @@
1
- import { spawn } from 'node:child_process';
2
- import { createInterface } from 'node:readline';
3
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
4
- import { dirname, extname } from 'node:path';
5
- class AcpRpcError extends Error {
6
- code;
7
- constructor(code, message) {
8
- super(message);
9
- this.code = code;
10
- }
11
- }
12
- // ── ACP JSON-RPC client over a child process' stdio (ndjson framing) ───────────
13
- class AcpClient {
14
- bin;
15
- args;
16
- env;
17
- cwd;
18
- proc = null;
19
- nextId = 1;
20
- pending = new Map();
21
- notifyCb;
22
- requestCb;
23
- stderrTail = [];
24
- constructor(bin, args, env, cwd) {
25
- this.bin = bin;
26
- this.args = args;
27
- this.env = env;
28
- this.cwd = cwd;
29
- }
30
- onNotification(cb) { this.notifyCb = cb; }
31
- onRequest(cb) { this.requestCb = cb; }
32
- stderrText() { return this.stderrTail.join('\n'); }
33
- start() {
34
- try {
35
- this.proc = spawn(this.bin, this.args, {
36
- cwd: this.cwd,
37
- stdio: ['pipe', 'pipe', 'pipe'],
38
- env: this.env ? { ...process.env, ...this.env } : process.env,
39
- });
40
- }
41
- catch {
42
- return false;
43
- }
44
- const rl = createInterface({ input: this.proc.stdout, crlfDelay: Infinity });
45
- rl.on('line', (line) => this.onLine(line));
46
- this.proc.stderr.on('data', (chunk) => {
47
- for (const ln of chunk.toString('utf8').split('\n')) {
48
- const t = ln.trim();
49
- if (!t)
50
- continue;
51
- this.stderrTail.push(t.slice(0, 240));
52
- if (this.stderrTail.length > 20)
53
- this.stderrTail.shift();
54
- }
55
- });
56
- this.proc.on('close', () => { for (const cb of this.pending.values())
57
- cb({ error: { message: 'acp process exited' } }); this.pending.clear(); });
58
- this.proc.on('error', () => { });
59
- return true;
60
- }
61
- onLine(line) {
62
- const t = line.trim();
63
- if (!t)
64
- return;
65
- let m;
66
- try {
67
- m = JSON.parse(t);
68
- }
69
- catch {
70
- return;
71
- } // non-JSON stdout noise
72
- if (m.method && m.id != null) {
73
- void this.handleRequest(m);
74
- return;
75
- } // agent -> client request
76
- if (m.id != null) { // response to one of our requests
77
- const cb = this.pending.get(m.id);
78
- if (cb) {
79
- this.pending.delete(m.id);
80
- cb(m);
81
- }
82
- return;
83
- }
84
- if (m.method)
85
- this.notifyCb?.(m.method, m.params ?? {}); // notification (session/update)
86
- }
87
- async handleRequest(m) {
88
- const id = m.id;
89
- if (!this.requestCb) {
90
- this.respondError(id, -32601, `Method not implemented: ${m.method}`);
91
- return;
92
- }
93
- try {
94
- const result = await this.requestCb(m.method, m.params ?? {});
95
- this.respond(id, result ?? null);
96
- }
97
- catch (e) {
98
- const code = e instanceof AcpRpcError ? e.code : -32603;
99
- this.respondError(id, code, e?.message || 'handler error');
100
- }
101
- }
102
- request(method, params, timeoutMs = 60_000) {
103
- return new Promise((resolve) => {
104
- if (!this.proc || this.proc.killed) {
105
- resolve({ error: { message: 'not connected' } });
106
- return;
107
- }
108
- const id = this.nextId++;
109
- const timer = setTimeout(() => { this.pending.delete(id); resolve({ error: { message: `ACP '${method}' timed out` } }); }, timeoutMs);
110
- this.pending.set(id, (m) => { clearTimeout(timer); resolve(m); });
111
- this.write({ jsonrpc: '2.0', id, method, params });
112
- });
113
- }
114
- notify(method, params) { this.write({ jsonrpc: '2.0', method, params }); }
115
- respond(id, result) { this.write({ jsonrpc: '2.0', id, result }); }
116
- respondError(id, code, message) { this.write({ jsonrpc: '2.0', id, error: { code, message } }); }
117
- write(msg) {
118
- if (!this.proc || this.proc.killed)
119
- return;
120
- try {
121
- this.proc.stdin.write(JSON.stringify(msg) + '\n');
122
- }
123
- catch { /* stream closed */ }
124
- }
125
- kill() { try {
126
- this.proc?.kill('SIGTERM');
127
- }
128
- catch { /* ignore */ } this.proc = null; }
129
- }
2
+ import { dirname } from 'node:path';
3
+ import { RpcError, StdioRpcClient } from './rpc.js';
4
+ import { attachedFileNote, contextPercent, imageMimeForFile, wireAbort } from './shared.js';
130
5
  // ── pikiloom McpServerSpec[] -> ACP mcpServers[] ───────────────────────────────
131
6
  export function toAcpMcpServers(servers) {
132
7
  if (!servers || !servers.length)
@@ -145,29 +20,19 @@ export function toAcpMcpServers(servers) {
145
20
  }
146
21
  return out;
147
22
  }
148
- const IMAGE_EXTS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.webp']);
149
- function mimeForExt(ext) {
150
- if (ext === '.jpg' || ext === '.jpeg')
151
- return 'image/jpeg';
152
- if (ext === '.gif')
153
- return 'image/gif';
154
- if (ext === '.webp')
155
- return 'image/webp';
156
- return 'image/png';
157
- }
158
23
  // ACP prompt content blocks: text + inline base64 images; other attachments noted as text.
159
24
  export function buildAcpPromptBlocks(prompt, attachments) {
160
25
  const blocks = [];
161
26
  for (const f of attachments) {
162
- const ext = extname(f).toLowerCase();
163
- if (IMAGE_EXTS.has(ext)) {
27
+ const mime = imageMimeForFile(f);
28
+ if (mime) {
164
29
  try {
165
- blocks.push({ type: 'image', mimeType: mimeForExt(ext), data: readFileSync(f).toString('base64') });
30
+ blocks.push({ type: 'image', mimeType: mime, data: readFileSync(f).toString('base64') });
166
31
  continue;
167
32
  }
168
33
  catch { /* fall through to a text note */ }
169
34
  }
170
- blocks.push({ type: 'text', text: `[Attached file: ${f}]` });
35
+ blocks.push({ type: 'text', text: attachedFileNote(f) });
171
36
  }
172
37
  blocks.push({ type: 'text', text: prompt });
173
38
  return blocks;
@@ -260,12 +125,13 @@ export function applyAcpUpdate(update, s, tools, emit) {
260
125
  case 'usage_update': {
261
126
  if (typeof update.size === 'number')
262
127
  s.contextWindow = update.size;
263
- if (typeof update.used === 'number')
264
- s.contextUsed = update.used;
265
128
  if (typeof update.used === 'number') {
266
- const window = s.contextWindow;
267
- const contextPercent = window && update.used > 0 ? Math.min(99.9, Math.round((update.used / window) * 1000) / 10) : null;
268
- emit({ type: 'usage', usage: { inputTokens: null, outputTokens: null, cachedInputTokens: null, contextUsedTokens: update.used, contextPercent } });
129
+ s.contextUsed = update.used;
130
+ emit({ type: 'usage', usage: {
131
+ inputTokens: null, outputTokens: null, cachedInputTokens: null,
132
+ contextUsedTokens: update.used,
133
+ contextPercent: contextPercent(update.used > 0 ? update.used : null, s.contextWindow),
134
+ } });
269
135
  }
270
136
  return;
271
137
  }
@@ -321,7 +187,7 @@ function fallbackOptionId(options, fallback) {
321
187
  function readAcpTextFile(params) {
322
188
  const p = String(params?.path || '');
323
189
  if (!p || !existsSync(p))
324
- throw new AcpRpcError(-32602, `file not found: ${p}`);
190
+ throw new RpcError(-32602, `file not found: ${p}`);
325
191
  let content = readFileSync(p, 'utf8');
326
192
  const line = typeof params?.line === 'number' ? params.line : null;
327
193
  const limit = typeof params?.limit === 'number' ? params.limit : null;
@@ -335,7 +201,7 @@ function readAcpTextFile(params) {
335
201
  function writeAcpTextFile(params) {
336
202
  const p = String(params?.path || '');
337
203
  if (!p)
338
- throw new AcpRpcError(-32602, 'path required');
204
+ throw new RpcError(-32602, 'path required');
339
205
  try {
340
206
  mkdirSync(dirname(p), { recursive: true });
341
207
  }
@@ -351,9 +217,11 @@ function acpUsage(s, raw) {
351
217
  output = n(raw.outputTokens ?? raw.output_tokens);
352
218
  cached = n(raw.cachedReadTokens ?? raw.cached_read_tokens ?? raw.cachedInputTokens);
353
219
  }
354
- const window = s.contextWindow, used = s.contextUsed;
355
- const contextPercent = window && used ? Math.min(99.9, Math.round((used / window) * 1000) / 10) : null;
356
- return { inputTokens: input, outputTokens: output, cachedInputTokens: cached, contextUsedTokens: used, contextPercent, turnOutputTokens: output };
220
+ const used = s.contextUsed;
221
+ return {
222
+ inputTokens: input, outputTokens: output, cachedInputTokens: cached, contextUsedTokens: used,
223
+ contextPercent: contextPercent(used || null, s.contextWindow), turnOutputTokens: output,
224
+ };
357
225
  }
358
226
  export class AcpDriver {
359
227
  id;
@@ -376,19 +244,18 @@ export class AcpDriver {
376
244
  }
377
245
  async run(input, ctx) {
378
246
  const env = { ...(this.cfg.env || {}), ...(input.env || {}) };
379
- const client = new AcpClient(this.cfg.command, this.cfg.args, env, input.workdir);
247
+ const client = new StdioRpcClient({ command: this.cfg.command, args: this.cfg.args, env, cwd: input.workdir, label: this.id });
380
248
  const state = { text: '', reasoning: '', contextWindow: null, contextUsed: null };
381
249
  const tools = new Set();
382
250
  let sessionId = input.sessionId ?? null;
383
251
  let permSeq = 0;
384
252
  if (!client.start())
385
253
  return { ok: false, text: '', error: `failed to start ${this.cfg.command}`, stopReason: 'error' };
386
- const onAbort = () => { if (sessionId)
387
- client.notify('session/cancel', { sessionId }); client.kill(); };
388
- if (ctx.signal.aborted)
389
- onAbort();
390
- else
391
- ctx.signal.addEventListener('abort', onAbort, { once: true });
254
+ const unwireAbort = wireAbort(ctx.signal, () => {
255
+ if (sessionId)
256
+ client.notify('session/cancel', { sessionId });
257
+ client.kill();
258
+ });
392
259
  client.onNotification((method, params) => {
393
260
  if (method === 'session/update')
394
261
  applyAcpUpdate(params?.update ?? params, state, tools, ctx.emit);
@@ -398,14 +265,14 @@ export class AcpDriver {
398
265
  case 'session/request_permission': return this.resolvePermission(params, ctx, `${this.id}-perm-${++permSeq}`);
399
266
  case 'fs/read_text_file':
400
267
  if (!this.cfg.fsAccess)
401
- throw new AcpRpcError(-32601, 'fs/read_text_file not supported');
268
+ throw new RpcError(-32601, 'fs/read_text_file not supported');
402
269
  return readAcpTextFile(params);
403
270
  case 'fs/write_text_file':
404
271
  if (!this.cfg.fsAccess)
405
- throw new AcpRpcError(-32601, 'fs/write_text_file not supported');
272
+ throw new RpcError(-32601, 'fs/write_text_file not supported');
406
273
  return writeAcpTextFile(params);
407
274
  default:
408
- throw new AcpRpcError(-32601, `Method not implemented: ${method}`);
275
+ throw new RpcError(-32601, `Method not implemented: ${method}`);
409
276
  }
410
277
  });
411
278
  try {
@@ -447,7 +314,7 @@ export class AcpDriver {
447
314
  return { ok: true, text: state.text, reasoning: state.reasoning || undefined, error: null, stopReason, sessionId, usage };
448
315
  }
449
316
  finally {
450
- ctx.signal.removeEventListener('abort', onAbort);
317
+ unwireAbort();
451
318
  client.kill();
452
319
  }
453
320
  }
@@ -1,5 +1,5 @@
1
1
  import type { AgentDriver, AgentTurnInput, DriverContext, DriverResult, DriverEvent, TuiInput, TuiSpec, NativeSessionInfo } from '../contracts/driver.js';
2
- import type { UniversalUsage, UniversalPlan } from '../protocol/index.js';
2
+ import type { UniversalPlan } from '../protocol/index.js';
3
3
  export declare class ClaudeDriver implements AgentDriver {
4
4
  private readonly bin;
5
5
  readonly id = "claude";
@@ -18,19 +18,6 @@ export declare class ClaudeDriver implements AgentDriver {
18
18
  run(input: AgentTurnInput, ctx: DriverContext): Promise<DriverResult>;
19
19
  private usage;
20
20
  }
21
- export interface ClaudeUsageState {
22
- input: number | null;
23
- output: number | null;
24
- cached: number | null;
25
- cacheCreation?: number | null;
26
- contextWindow?: number | null;
27
- turnOutputTokensBase?: number | null;
28
- thinkingEstTokens?: number | null;
29
- }
30
- export declare function claudeUsageOf(s: ClaudeUsageState): UniversalUsage;
31
- export declare function applyClaudeThinkingEstimate(s: any, ev: any): boolean;
32
- export declare function claudeContextWindowFromModel(model: unknown): number | null;
33
- export declare function claudeEffectiveContextWindow(advertised: number | null): number | null;
34
21
  export declare function handleClaudeEvent(ev: any, s: any, emit: (e: DriverEvent) => void): void;
35
22
  export declare function claudeBgHoldCapMs(): number;
36
23
  export declare function claudeBgAgentHoldCapMs(): number;
@@ -41,6 +28,7 @@ export declare function claudeModelStallMs(): number;
41
28
  export declare const CLAUDE_TRUNCATED_RECOVERY_PROMPT: string;
42
29
  export declare function claudeTruncatedRecoveryEnabled(): boolean;
43
30
  export declare function isClaudeSyntheticResumeNoise(text: string): boolean;
31
+ export declare function isClaudeSlashCommand(prompt: string): boolean;
44
32
  export declare function claudeProducedRealOutput(s: any): boolean;
45
33
  export declare function claudeResumeNoopRetryLimit(): number;
46
34
  export declare function claudeUserEventHasToolResult(ev: any): boolean;
@@ -56,11 +44,4 @@ export declare function decideClaudeResultSettle(input: {
56
44
  sawBackground: boolean;
57
45
  }): ClaudeResultSettleDecision;
58
46
  export declare function claudeUserMessage(text: string, attachments?: string[]): string;
59
- export declare function emitClaudeImages(blocks: any[], s: any, emit: (e: DriverEvent) => void): void;
60
47
  export declare function todoWriteToPlan(input: any): UniversalPlan | null;
61
- export declare function readClaudeTaskCreateId(ev: any, block: any): string | null;
62
- export declare function rebuildClaudeTaskPlan(s: any): UniversalPlan | null;
63
- export declare function applyTaskUpdateToTodoPlan(plan: UniversalPlan | null | undefined, taskId: string, rawStatus: string): UniversalPlan | null;
64
- export declare function shortToolValue(value: unknown, max?: number): string;
65
- export declare function summarizeToolUse(name: string, input: any): string;
66
- export declare function firstResultLine(content: any): string;