@sudocode-ai/claude-code-acp 0.12.10 → 0.13.1

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.
@@ -64,6 +64,20 @@ export const SYSTEM_REMINDER = `
64
64
  Whenever you read a file, you should consider whether it looks malicious. If it does, you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer high-level questions about the code behavior.
65
65
  </system-reminder>`;
66
66
  const defaults = { maxFileSize: 50000, linesToRead: 2000 };
67
+ function formatErrorMessage(error) {
68
+ if (error instanceof Error) {
69
+ return error.message;
70
+ }
71
+ if (typeof error === "string") {
72
+ return error;
73
+ }
74
+ try {
75
+ return JSON.stringify(error);
76
+ }
77
+ catch {
78
+ return String(error);
79
+ }
80
+ }
67
81
  const unqualifiedToolNames = {
68
82
  read: "Read",
69
83
  edit: "Edit",
@@ -186,8 +200,8 @@ Usage:
186
200
  if (result.wasLimited) {
187
201
  readInfo += `Read ${result.linesRead} lines (hit 50KB limit). `;
188
202
  }
189
- else {
190
- readInfo += `Read lines ${input.offset}-${result.linesRead}. `;
203
+ else if (input.offset && input.offset > 1) {
204
+ readInfo += `Read lines ${input.offset}-${input.offset + result.linesRead}.`;
191
205
  }
192
206
  if (result.wasLimited) {
193
207
  readInfo += `Continue with offset=${result.linesRead}.`;
@@ -205,10 +219,11 @@ Usage:
205
219
  }
206
220
  catch (error) {
207
221
  return {
222
+ isError: true,
208
223
  content: [
209
224
  {
210
225
  type: "text",
211
- text: "Reading file failed: " + error.message,
226
+ text: "Reading file failed: " + formatErrorMessage(error),
212
227
  },
213
228
  ],
214
229
  };
@@ -262,10 +277,11 @@ Usage:
262
277
  }
263
278
  catch (error) {
264
279
  return {
280
+ isError: true,
265
281
  content: [
266
282
  {
267
283
  type: "text",
268
- text: "Writing file failed: " + error.message,
284
+ text: "Writing file failed: " + formatErrorMessage(error),
269
285
  },
270
286
  ],
271
287
  };
@@ -343,10 +359,11 @@ Usage:
343
359
  }
344
360
  catch (error) {
345
361
  return {
362
+ isError: true,
346
363
  content: [
347
364
  {
348
365
  type: "text",
349
- text: "Editing file failed: " + (error?.message ?? String(error)),
366
+ text: "Editing file failed: " + formatErrorMessage(error),
350
367
  },
351
368
  ],
352
369
  };
@@ -381,114 +398,127 @@ Output: Create directory 'foo'`),
381
398
  .describe(`Set to true to run this command in the background. The tool returns an \`id\` that can be used with the \`${acpToolNames.bashOutput}\` tool to retrieve the current output, or the \`${acpToolNames.killShell}\` tool to stop it early.`),
382
399
  },
383
400
  }, async (input, extra) => {
384
- const env_1 = { stack: [], error: void 0, hasError: false };
385
401
  try {
386
- const session = agent.sessions[sessionId];
387
- if (!session) {
388
- return {
389
- content: [
390
- {
391
- type: "text",
392
- text: "The user has left the building",
393
- },
394
- ],
395
- };
396
- }
397
- const toolCallId = extra._meta?.["claudecode/toolUseId"];
398
- if (typeof toolCallId !== "string") {
399
- throw new Error("No tool call ID found");
400
- }
401
- if (!agent.clientCapabilities?.terminal || !agent.client.createTerminal) {
402
- throw new Error("unreachable");
403
- }
404
- const handle = await agent.client.createTerminal({
405
- command: input.command,
406
- env: [{ name: "CLAUDECODE", value: "1" }],
407
- sessionId,
408
- outputByteLimit: 32000,
409
- });
410
- await agent.client.sessionUpdate({
411
- sessionId,
412
- update: {
413
- sessionUpdate: "tool_call_update",
414
- toolCallId,
415
- status: "in_progress",
416
- title: input.description,
417
- content: [{ type: "terminal", terminalId: handle.id }],
418
- },
419
- });
420
- const abortPromise = new Promise((resolve) => {
421
- if (extra.signal.aborted) {
422
- resolve(null);
402
+ const env_1 = { stack: [], error: void 0, hasError: false };
403
+ try {
404
+ const session = agent.sessions[sessionId];
405
+ if (!session) {
406
+ return {
407
+ content: [
408
+ {
409
+ type: "text",
410
+ text: "The user has left the building",
411
+ },
412
+ ],
413
+ };
423
414
  }
424
- else {
425
- extra.signal.addEventListener("abort", () => {
426
- resolve(null);
427
- });
415
+ const toolCallId = extra._meta?.["claudecode/toolUseId"];
416
+ if (typeof toolCallId !== "string") {
417
+ throw new Error("No tool call ID found");
428
418
  }
429
- });
430
- const statusPromise = Promise.race([
431
- handle.waitForExit().then((exitStatus) => ({ status: "exited", exitStatus })),
432
- abortPromise.then(() => ({ status: "aborted", exitStatus: null })),
433
- sleep(input.timeout ?? 2 * 60 * 1000).then(async () => {
434
- if (agent.backgroundTerminals[handle.id]?.status === "started") {
435
- await handle.kill();
419
+ if (!agent.clientCapabilities?.terminal || !agent.client.createTerminal) {
420
+ throw new Error("unreachable");
421
+ }
422
+ const handle = await agent.client.createTerminal({
423
+ command: input.command,
424
+ env: [{ name: "CLAUDECODE", value: "1" }],
425
+ sessionId,
426
+ outputByteLimit: 32000,
427
+ });
428
+ await agent.client.sessionUpdate({
429
+ sessionId,
430
+ update: {
431
+ sessionUpdate: "tool_call_update",
432
+ toolCallId,
433
+ status: "in_progress",
434
+ title: input.description,
435
+ content: [{ type: "terminal", terminalId: handle.id }],
436
+ },
437
+ });
438
+ const abortPromise = new Promise((resolve) => {
439
+ if (extra.signal.aborted) {
440
+ resolve(null);
436
441
  }
437
- return { status: "timedOut", exitStatus: null };
438
- }),
439
- ]);
440
- if (input.run_in_background) {
441
- agent.backgroundTerminals[handle.id] = {
442
- handle,
443
- lastOutput: null,
444
- status: "started",
445
- };
446
- statusPromise.then(async ({ status, exitStatus }) => {
447
- const bgTerm = agent.backgroundTerminals[handle.id];
448
- if (bgTerm.status !== "started") {
449
- return;
442
+ else {
443
+ extra.signal.addEventListener("abort", () => {
444
+ resolve(null);
445
+ });
450
446
  }
451
- const currentOutput = await handle.currentOutput();
447
+ });
448
+ const statusPromise = Promise.race([
449
+ handle.waitForExit().then((exitStatus) => ({ status: "exited", exitStatus })),
450
+ abortPromise.then(() => ({ status: "aborted", exitStatus: null })),
451
+ sleep(input.timeout ?? 2 * 60 * 1000).then(async () => {
452
+ if (agent.backgroundTerminals[handle.id]?.status === "started") {
453
+ await handle.kill();
454
+ }
455
+ return { status: "timedOut", exitStatus: null };
456
+ }),
457
+ ]);
458
+ if (input.run_in_background) {
452
459
  agent.backgroundTerminals[handle.id] = {
453
- status,
454
- pendingOutput: {
455
- ...currentOutput,
456
- output: stripCommonPrefix(bgTerm.lastOutput?.output ?? "", currentOutput.output),
457
- exitStatus: exitStatus ?? currentOutput.exitStatus,
458
- },
460
+ handle,
461
+ lastOutput: null,
462
+ status: "started",
459
463
  };
460
- return handle.release();
461
- });
464
+ statusPromise.then(async ({ status, exitStatus }) => {
465
+ const bgTerm = agent.backgroundTerminals[handle.id];
466
+ if (bgTerm.status !== "started") {
467
+ return;
468
+ }
469
+ const currentOutput = await handle.currentOutput();
470
+ agent.backgroundTerminals[handle.id] = {
471
+ status,
472
+ pendingOutput: {
473
+ ...currentOutput,
474
+ output: stripCommonPrefix(bgTerm.lastOutput?.output ?? "", currentOutput.output),
475
+ exitStatus: exitStatus ?? currentOutput.exitStatus,
476
+ },
477
+ };
478
+ return handle.release();
479
+ });
480
+ return {
481
+ content: [
482
+ {
483
+ type: "text",
484
+ text: `Command started in background with id: ${handle.id}`,
485
+ },
486
+ ],
487
+ };
488
+ }
489
+ const terminal = __addDisposableResource(env_1, handle, true);
490
+ const { status } = await statusPromise;
491
+ if (status === "aborted") {
492
+ return {
493
+ content: [{ type: "text", text: "Tool cancelled by user" }],
494
+ };
495
+ }
496
+ const output = await terminal.currentOutput();
462
497
  return {
463
- content: [
464
- {
465
- type: "text",
466
- text: `Command started in background with id: ${handle.id}`,
467
- },
468
- ],
498
+ content: [{ type: "text", text: toolCommandOutput(status, output) }],
469
499
  };
470
500
  }
471
- const terminal = __addDisposableResource(env_1, handle, true);
472
- const { status } = await statusPromise;
473
- if (status === "aborted") {
474
- return {
475
- content: [{ type: "text", text: "Tool cancelled by user" }],
476
- };
501
+ catch (e_1) {
502
+ env_1.error = e_1;
503
+ env_1.hasError = true;
477
504
  }
478
- const output = await terminal.currentOutput();
505
+ finally {
506
+ const result_1 = __disposeResources(env_1);
507
+ if (result_1)
508
+ await result_1;
509
+ }
510
+ }
511
+ catch (error) {
479
512
  return {
480
- content: [{ type: "text", text: toolCommandOutput(status, output) }],
513
+ isError: true,
514
+ content: [
515
+ {
516
+ type: "text",
517
+ text: "Running bash command failed: " + formatErrorMessage(error),
518
+ },
519
+ ],
481
520
  };
482
521
  }
483
- catch (e_1) {
484
- env_1.error = e_1;
485
- env_1.hasError = true;
486
- }
487
- finally {
488
- const result_1 = __disposeResources(env_1);
489
- if (result_1)
490
- await result_1;
491
- }
492
522
  });
493
523
  server.registerTool(unqualifiedToolNames.bashOutput, {
494
524
  title: unqualifiedToolNames.bashOutput,
@@ -505,32 +535,45 @@ In sessions with ${acpToolNames.bashOutput} always use it for output from Bash c
505
535
  .describe(`The id of the background bash command as returned by \`${acpToolNames.bash}\``),
506
536
  },
507
537
  }, async (input) => {
508
- const bgTerm = agent.backgroundTerminals[input.bash_id];
509
- if (!bgTerm) {
510
- throw new Error(`Unknown shell ${input.bash_id}`);
511
- }
512
- if (bgTerm.status === "started") {
513
- const newOutput = await bgTerm.handle.currentOutput();
514
- const strippedOutput = stripCommonPrefix(bgTerm.lastOutput?.output ?? "", newOutput.output);
515
- bgTerm.lastOutput = newOutput;
516
- return {
517
- content: [
518
- {
519
- type: "text",
520
- text: toolCommandOutput(bgTerm.status, {
521
- ...newOutput,
522
- output: strippedOutput,
523
- }),
524
- },
525
- ],
526
- };
538
+ try {
539
+ const bgTerm = agent.backgroundTerminals[input.bash_id];
540
+ if (!bgTerm) {
541
+ throw new Error(`Unknown shell ${input.bash_id}`);
542
+ }
543
+ if (bgTerm.status === "started") {
544
+ const newOutput = await bgTerm.handle.currentOutput();
545
+ const strippedOutput = stripCommonPrefix(bgTerm.lastOutput?.output ?? "", newOutput.output);
546
+ bgTerm.lastOutput = newOutput;
547
+ return {
548
+ content: [
549
+ {
550
+ type: "text",
551
+ text: toolCommandOutput(bgTerm.status, {
552
+ ...newOutput,
553
+ output: strippedOutput,
554
+ }),
555
+ },
556
+ ],
557
+ };
558
+ }
559
+ else {
560
+ return {
561
+ content: [
562
+ {
563
+ type: "text",
564
+ text: toolCommandOutput(bgTerm.status, bgTerm.pendingOutput),
565
+ },
566
+ ],
567
+ };
568
+ }
527
569
  }
528
- else {
570
+ catch (error) {
529
571
  return {
572
+ isError: true,
530
573
  content: [
531
574
  {
532
575
  type: "text",
533
- text: toolCommandOutput(bgTerm.status, bgTerm.pendingOutput),
576
+ text: "Retrieving bash output failed: " + formatErrorMessage(error),
534
577
  },
535
578
  ],
536
579
  };
@@ -550,47 +593,60 @@ In sessions with ${acpToolNames.killShell} always use it instead of KillShell.`,
550
593
  .describe(`The id of the background bash command as returned by \`${acpToolNames.bash}\``),
551
594
  },
552
595
  }, async (input) => {
553
- const bgTerm = agent.backgroundTerminals[input.shell_id];
554
- if (!bgTerm) {
555
- throw new Error(`Unknown shell ${input.shell_id}`);
556
- }
557
- switch (bgTerm.status) {
558
- case "started": {
559
- await bgTerm.handle.kill();
560
- const currentOutput = await bgTerm.handle.currentOutput();
561
- agent.backgroundTerminals[bgTerm.handle.id] = {
562
- status: "killed",
563
- pendingOutput: {
564
- ...currentOutput,
565
- output: stripCommonPrefix(bgTerm.lastOutput?.output ?? "", currentOutput.output),
566
- },
567
- };
568
- await bgTerm.handle.release();
569
- return {
570
- content: [{ type: "text", text: "Command killed successfully." }],
571
- };
596
+ try {
597
+ const bgTerm = agent.backgroundTerminals[input.shell_id];
598
+ if (!bgTerm) {
599
+ throw new Error(`Unknown shell ${input.shell_id}`);
572
600
  }
573
- case "aborted":
574
- return {
575
- content: [{ type: "text", text: "Command aborted by user." }],
576
- };
577
- case "exited":
578
- return {
579
- content: [{ type: "text", text: "Command had already exited." }],
580
- };
581
- case "killed":
582
- return {
583
- content: [{ type: "text", text: "Command was already killed." }],
584
- };
585
- case "timedOut":
586
- return {
587
- content: [{ type: "text", text: "Command killed by timeout." }],
588
- };
589
- default: {
590
- unreachable(bgTerm);
591
- throw new Error("Unexpected background terminal status");
601
+ switch (bgTerm.status) {
602
+ case "started": {
603
+ await bgTerm.handle.kill();
604
+ const currentOutput = await bgTerm.handle.currentOutput();
605
+ agent.backgroundTerminals[bgTerm.handle.id] = {
606
+ status: "killed",
607
+ pendingOutput: {
608
+ ...currentOutput,
609
+ output: stripCommonPrefix(bgTerm.lastOutput?.output ?? "", currentOutput.output),
610
+ },
611
+ };
612
+ await bgTerm.handle.release();
613
+ return {
614
+ content: [{ type: "text", text: "Command killed successfully." }],
615
+ };
616
+ }
617
+ case "aborted":
618
+ return {
619
+ content: [{ type: "text", text: "Command aborted by user." }],
620
+ };
621
+ case "exited":
622
+ return {
623
+ content: [{ type: "text", text: "Command had already exited." }],
624
+ };
625
+ case "killed":
626
+ return {
627
+ content: [{ type: "text", text: "Command was already killed." }],
628
+ };
629
+ case "timedOut":
630
+ return {
631
+ content: [{ type: "text", text: "Command killed by timeout." }],
632
+ };
633
+ default: {
634
+ unreachable(bgTerm);
635
+ throw new Error("Unexpected background terminal status");
636
+ }
592
637
  }
593
638
  }
639
+ catch (error) {
640
+ return {
641
+ isError: true,
642
+ content: [
643
+ {
644
+ type: "text",
645
+ text: "Killing shell failed: " + formatErrorMessage(error),
646
+ },
647
+ ],
648
+ };
649
+ }
594
650
  });
595
651
  }
596
652
  return server;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Permission rule format examples:
3
+ * - "Read" - matches all Read tool calls
4
+ * - "Read(./.env)" - matches specific path
5
+ * - "Read(./.env.*)" - glob pattern
6
+ * - "Read(./secrets/**)" - recursive glob
7
+ * - "Bash(npm run lint)" - exact command prefix
8
+ * - "Bash(npm run:*)" - command prefix with wildcard
9
+ *
10
+ * Docs: https://code.claude.com/docs/en/iam#tool-specific-permission-rules
11
+ */
12
+ export interface PermissionSettings {
13
+ allow?: string[];
14
+ deny?: string[];
15
+ ask?: string[];
16
+ additionalDirectories?: string[];
17
+ defaultMode?: string;
18
+ }
19
+ export interface ClaudeCodeSettings {
20
+ permissions?: PermissionSettings;
21
+ env?: Record<string, string>;
22
+ }
23
+ export type PermissionDecision = "allow" | "deny" | "ask";
24
+ export interface PermissionCheckResult {
25
+ decision: PermissionDecision;
26
+ rule?: string;
27
+ source?: "allow" | "deny" | "ask";
28
+ }
29
+ /**
30
+ * Gets the enterprise settings path based on the current platform
31
+ */
32
+ export declare function getManagedSettingsPath(): string;
33
+ export interface SettingsManagerOptions {
34
+ onChange?: () => void;
35
+ logger?: {
36
+ log: (...args: any[]) => void;
37
+ error: (...args: any[]) => void;
38
+ };
39
+ }
40
+ /**
41
+ * Manages Claude Code settings from multiple sources with proper precedence.
42
+ *
43
+ * Settings are loaded from (in order of increasing precedence):
44
+ * 1. User settings (~/.claude/settings.json)
45
+ * 2. Project settings (<cwd>/.claude/settings.json)
46
+ * 3. Local project settings (<cwd>/.claude/settings.local.json)
47
+ * 4. Enterprise managed settings (platform-specific path)
48
+ *
49
+ * The manager watches all settings files for changes and automatically reloads.
50
+ */
51
+ export declare class SettingsManager {
52
+ private cwd;
53
+ private userSettings;
54
+ private projectSettings;
55
+ private localSettings;
56
+ private enterpriseSettings;
57
+ private mergedSettings;
58
+ private watchers;
59
+ private onChange?;
60
+ private logger;
61
+ private initialized;
62
+ private debounceTimer;
63
+ constructor(cwd: string, options?: SettingsManagerOptions);
64
+ /**
65
+ * Initialize the settings manager by loading all settings and setting up file watchers
66
+ */
67
+ initialize(): Promise<void>;
68
+ /**
69
+ * Returns the path to the user settings file
70
+ */
71
+ private getUserSettingsPath;
72
+ /**
73
+ * Returns the path to the project settings file
74
+ */
75
+ private getProjectSettingsPath;
76
+ /**
77
+ * Returns the path to the local project settings file
78
+ */
79
+ private getLocalSettingsPath;
80
+ /**
81
+ * Loads settings from all sources
82
+ */
83
+ private loadAllSettings;
84
+ /**
85
+ * Merges all settings sources with proper precedence.
86
+ * For permissions, rules from all sources are combined.
87
+ * Deny rules always take precedence during permission checks.
88
+ */
89
+ private mergeSettings;
90
+ /**
91
+ * Sets up file watchers for all settings files
92
+ */
93
+ private setupWatchers;
94
+ /**
95
+ * Handles settings file changes with debouncing to avoid rapid reloads
96
+ */
97
+ private handleSettingsChange;
98
+ /**
99
+ * Checks if a tool invocation is allowed based on the loaded settings.
100
+ *
101
+ * @param toolName - The tool name (can be ACP-prefixed like mcp__acp__Read or plain like Read)
102
+ * @param toolInput - The tool input object
103
+ * @returns The permission decision and matching rule info
104
+ */
105
+ checkPermission(toolName: string, toolInput: unknown): PermissionCheckResult;
106
+ /**
107
+ * Returns the current merged settings
108
+ */
109
+ getSettings(): ClaudeCodeSettings;
110
+ /**
111
+ * Returns the current working directory
112
+ */
113
+ getCwd(): string;
114
+ /**
115
+ * Updates the working directory and reloads project-specific settings
116
+ */
117
+ setCwd(cwd: string): Promise<void>;
118
+ /**
119
+ * Disposes of file watchers and cleans up resources
120
+ */
121
+ dispose(): void;
122
+ }
123
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAE1D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;CACnC;AAuLD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAW/C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7E;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,QAAQ,CAAC,CAAa;IAC9B,OAAO,CAAC,MAAM,CAAqE;IACnF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAA8C;gBAEvD,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB;IAMzD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAUjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAI9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;YACW,eAAe;IAgB7B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IA8CrB;;OAEG;IACH,OAAO,CAAC,aAAa;IAkCrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAgB5B;;;;;;OAMG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,qBAAqB;IAuC5E;;OAEG;IACH,WAAW,IAAI,kBAAkB;IAIjC;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxC;;OAEG;IACH,OAAO,IAAI,IAAI;CAYhB"}
@@ -0,0 +1,50 @@
1
+ import { PlanEntry, ToolCallContent, ToolCallLocation, ToolKind } from "@agentclientprotocol/sdk";
2
+ import { ToolResultBlockParam, WebSearchToolResultBlockParam } from "@anthropic-ai/sdk/resources";
3
+ export declare const ACP_TOOL_NAME_PREFIX = "mcp__acp__";
4
+ export declare const acpToolNames: {
5
+ read: string;
6
+ edit: string;
7
+ write: string;
8
+ bash: string;
9
+ killShell: string;
10
+ bashOutput: string;
11
+ };
12
+ export declare const EDIT_TOOL_NAMES: string[];
13
+ import { BetaBashCodeExecutionToolResultBlockParam, BetaCodeExecutionToolResultBlockParam, BetaRequestMCPToolResultBlockParam, BetaTextEditorCodeExecutionToolResultBlockParam, BetaToolSearchToolResultBlockParam, BetaWebFetchToolResultBlockParam, BetaWebSearchToolResultBlockParam } from "@anthropic-ai/sdk/resources/beta.mjs";
14
+ import { HookCallback } from "@anthropic-ai/claude-agent-sdk";
15
+ import { Logger } from "./acp-agent.js";
16
+ import { SettingsManager } from "./settings.js";
17
+ interface ToolInfo {
18
+ title: string;
19
+ kind: ToolKind;
20
+ content: ToolCallContent[];
21
+ locations?: ToolCallLocation[];
22
+ }
23
+ interface ToolUpdate {
24
+ title?: string;
25
+ content?: ToolCallContent[];
26
+ locations?: ToolCallLocation[];
27
+ }
28
+ export declare function toolInfoFromToolUse(toolUse: any): ToolInfo;
29
+ export declare function toolUpdateFromToolResult(toolResult: ToolResultBlockParam | BetaWebSearchToolResultBlockParam | BetaWebFetchToolResultBlockParam | WebSearchToolResultBlockParam | BetaCodeExecutionToolResultBlockParam | BetaBashCodeExecutionToolResultBlockParam | BetaTextEditorCodeExecutionToolResultBlockParam | BetaRequestMCPToolResultBlockParam | BetaToolSearchToolResultBlockParam, toolUse: any | undefined): ToolUpdate;
30
+ export type ClaudePlanEntry = {
31
+ content: string;
32
+ status: "pending" | "in_progress" | "completed";
33
+ activeForm: string;
34
+ };
35
+ export declare function planEntries(input: {
36
+ todos: ClaudePlanEntry[];
37
+ }): PlanEntry[];
38
+ export declare function markdownEscape(text: string): string;
39
+ export declare const registerHookCallback: (toolUseID: string, { onPostToolUseHook, }: {
40
+ onPostToolUseHook?: (toolUseID: string, toolInput: unknown, toolResponse: unknown) => Promise<void>;
41
+ }) => void;
42
+ export declare const createPostToolUseHook: (logger?: Logger) => HookCallback;
43
+ /**
44
+ * Creates a PreToolUse hook that checks permissions using the SettingsManager.
45
+ * This runs before the SDK's built-in permission rules, allowing us to enforce
46
+ * our own permission settings for ACP-prefixed tools.
47
+ */
48
+ export declare const createPreToolUseHook: (settingsManager: SettingsManager, logger?: Logger) => HookCallback;
49
+ export {};
50
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGlG,OAAO,EAAE,oBAAoB,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAWlG,eAAO,MAAM,oBAAoB,eAAe,CAAC;AACjD,eAAO,MAAM,YAAY;;;;;;;CAOxB,CAAC;AAEF,eAAO,MAAM,eAAe,UAA0C,CAAC;AAEvE,OAAO,EACL,yCAAyC,EACzC,qCAAqC,EACrC,kCAAkC,EAClC,+CAA+C,EAC/C,kCAAkC,EAClC,gCAAgC,EAChC,iCAAiC,EAClC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,UAAU,UAAU;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,GAAG,QAAQ,CA+V1D;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EACN,oBAAoB,GACpB,iCAAiC,GACjC,gCAAgC,GAChC,6BAA6B,GAC7B,qCAAqC,GACrC,yCAAyC,GACzC,+CAA+C,GAC/C,kCAAkC,GAClC,kCAAkC,EACtC,OAAO,EAAE,GAAG,GAAG,SAAS,GACvB,UAAU,CA4HZ;AAmCD,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,eAAe,EAAE,CAAA;CAAE,GAAG,SAAS,EAAE,CAM5E;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAcD,eAAO,MAAM,oBAAoB,GAC/B,WAAW,MAAM,EACjB,wBAEG;IACD,iBAAiB,CAAC,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,YAAY,EAAE,OAAO,KAClB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,SAKF,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAC/B,SAAQ,MAAgB,KAAG,YAa3B,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAC9B,iBAAiB,eAAe,EAAE,SAAQ,MAAgB,KAAG,YA2C7D,CAAC"}
package/dist/tools.js CHANGED
@@ -247,7 +247,9 @@ export function toolInfoFromToolUse(toolUse) {
247
247
  if (input.multiline) {
248
248
  label += " -P";
249
249
  }
250
- label += ` "${input.pattern}"`;
250
+ if (input.pattern) {
251
+ label += ` "${input.pattern}"`;
252
+ }
251
253
  if (input.path) {
252
254
  label += ` ${input.path}`;
253
255
  }