@borgee/agents-host 0.2.29 → 0.2.31

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/README.md CHANGED
@@ -84,7 +84,7 @@ Codex now ships on the same default hosted-provider surface as Claude and Copilo
84
84
 
85
85
  The current shipped internal compatibility surface resolves gates in this order:
86
86
 
87
- 1. start from the shipped defaults: `claude-provider-v2`, `copilot-provider-v2`, `codex-provider`, `managed-runtime-convergence`, and `policy-audit-enforcement`
87
+ 1. start from the shipped defaults: `copilot-provider-v2`, `codex-provider`, `managed-runtime-convergence`, and `policy-audit-enforcement`
88
88
  2. add any explicit entries from `AGENTS_HOST_INTERNAL_COMPATIBILITY_GATES`
89
89
  3. subtract any explicit entries from `AGENTS_HOST_INTERNAL_DISABLED_COMPATIBILITY_GATES`
90
90
 
@@ -98,7 +98,7 @@ Legacy managed roots created before `managed-runtime-settings.json` existed need
98
98
  Rollback and hardening controls stay explicit:
99
99
 
100
100
  - `AGENTS_HOST_INTERNAL_DISABLED_COMPATIBILITY_GATES=<comma-list>` disables shipped gates for rollback
101
- - `AGENTS_HOST_INTERNAL_PROVIDER_IMPLEMENTATIONS=claude:v1,copilot:v1` forces Claude and/or Copilot back to the v1 adapters while their v2 gates stay enabled
101
+ - `AGENTS_HOST_INTERNAL_PROVIDER_IMPLEMENTATIONS=copilot:v1` forces Copilot back to the v1 adapter while its v2 gate stays enabled; stale `claude:v1|v2` entries are tolerated as no-ops for compatibility
102
102
  - `AGENTS_HOST_INTERNAL_POLICY_MODE=enforce` hardens the shipped `policy-audit-enforcement` gate beyond its default `audit-only` mode
103
103
 
104
104
  Or with the CLI:
@@ -234,7 +234,7 @@ Notes:
234
234
  | `AGENTS_HOST_DEBUG` | `--debug` | no | off | Extra host/provider lifecycle logs. Set `AGENTS_HOST_DEBUG=1` to enable without the CLI flag. |
235
235
  | `BORGEE_AGENT_NAME` | `--name` | no | `Assistant` | Display name used in prompts |
236
236
  | `RUNTIME_PROVIDER` | `--provider` | no | `claude` | `claude`, `copilot`, or `codex` |
237
- | `CLAUDE_COMMAND` / `CLAUDE_ARGS` | `--claude-command` / `--claude-args` | no | `claude` / `--print --permission-mode bypassPermissions` | Local Claude CLI command + args |
237
+ | `CLAUDE_COMMAND` / `CLAUDE_ARGS` | `--claude-command` / `--claude-args` | no | `claude-agent-acp` / empty | Local Claude ACP adapter command + args. The shipped bundled `claude-agent-acp` path requires empty `CLAUDE_ARGS`; non-empty args are only valid when `CLAUDE_COMMAND` points at a custom ACP adapter command. Legacy `claude --print --permission-mode bypassPermissions` is tolerated as a compatibility alias. |
238
238
  | `CODEX_COMMAND` / `CODEX_ARGS` | `--codex-command` / `--codex-args` | no | `codex-acp` / empty | Local Codex ACP adapter command + args. The default launch resolves the bundled `@agentclientprotocol/codex-acp` entrypoint. |
239
239
  | `COPILOT_COMMAND` / `COPILOT_ARGS` | `--copilot-command` / `--copilot-args` | no | `copilot` / parsed but ignored by ACP runtime | Local Copilot CLI command. The persistent Copilot ACP prototype always launches `copilot --acp`. |
240
240
  | `COPILOT_SESSION_TTL_MINUTES` | `--copilot-session-ttl-minutes` | no | `2880` | Idle TTL for per-channel Copilot ACP sessions |
@@ -317,8 +317,8 @@ The spec shape is:
317
317
  "host": {
318
318
  "borgeeBaseUrl": "https://borgee.example.com",
319
319
  "defaults": {
320
- "claudeCommand": "claude",
321
- "claudeArgs": ["--print", "--permission-mode", "bypassPermissions"],
320
+ "claudeCommand": "claude-agent-acp",
321
+ "claudeArgs": [],
322
322
  "codexCommand": "codex-acp",
323
323
  "codexArgs": [],
324
324
  "copilotCommand": "copilot",
@@ -384,11 +384,8 @@ paths are also allowed.
384
384
  borgeeBaseUrl: https://borgee.example.com
385
385
  agentsDir: ./agents
386
386
  defaults:
387
- claudeCommand: claude
388
- claudeArgs:
389
- - --print
390
- - --permission-mode
391
- - bypassPermissions
387
+ claudeCommand: claude-agent-acp
388
+ claudeArgs: []
392
389
  codexCommand: codex-acp
393
390
  codexArgs: []
394
391
  copilotCommand: copilot
@@ -424,12 +421,6 @@ name: Support Bot
424
421
  apiKey: bgr_support_xxxxxxxx
425
422
  provider: claude
426
423
  enabled: true
427
- claudeArgs:
428
- - --print
429
- - --permission-mode
430
- - bypassPermissions
431
- - --model
432
- - sonnet
433
424
  ```
434
425
 
435
426
  Agent config fields:
@@ -439,6 +430,7 @@ Agent config fields:
439
430
  - `apiKey` (**required**)
440
431
  - `provider` (**required**): `claude`, `copilot`, or `codex` (roll back Codex only with `AGENTS_HOST_INTERNAL_DISABLED_COMPATIBILITY_GATES=codex-provider`)
441
432
  - `enabled` (optional, default `true`)
433
+ - `claudeCommand` / `claudeArgs` (optional): leave unset to use the shipped bundled `claude-agent-acp` path. On that bundled path `claudeArgs` must stay empty. Non-empty `claudeArgs` are only supported when `claudeCommand` points at a custom ACP adapter command.
442
434
  - optional overrides for `claudeCommand`, `claudeArgs`, `codexCommand`,
443
435
  `codexArgs`, `copilotCommand`, `copilotArgs`, and
444
436
  `copilotSessionTtlMinutes`
@@ -478,10 +470,16 @@ successfully applied snapshot running.
478
470
  Each Borgee channel is mapped 1:1 to a provider-native session while it stays
479
471
  active:
480
472
 
481
- - **Claude**: first turn for a channel uses `--session-id <uuid>`; every turn
482
- after uses `-r/--resume <uuid>`. The host persists the channel→session map in
483
- its state root, serializes cross-channel map rewrites, and retries once with a
484
- fresh session immediately if Claude reports a stale `--resume` target.
473
+ - **Claude**: one persistent `@agentclientprotocol/claude-agent-acp` subprocess
474
+ is shared by a single `AgentsHost`, with one ACP session per Borgee channel.
475
+ Same-channel turns are serialized; different channels keep isolated ACP
476
+ sessions. Ordinary threads keep the shared runtime workspace cwd, while
477
+ eligible `task_assignment` threads switch the real ACP session cwd to that
478
+ same hidden local task-scoped workspace. The host persists the
479
+ channel→ACP-session map in its state root, restores same-host continuity with
480
+ ACP `session/resume` when available, retries stale restores with a fresh
481
+ session immediately, and injects the per-channel local context paths through
482
+ Claude ACP `_meta.systemPrompt.append`.
485
483
  - **Codex**: one persistent `@agentclientprotocol/codex-acp` subprocess is
486
484
  shared by a single `AgentsHost`, with one ACP session per Borgee channel. When
487
485
  the current turn has a materialized channel context payload, Codex refreshes a
@@ -504,13 +502,6 @@ active:
504
502
  state root and restores same-host continuity with ACP `session/resume` when
505
503
  available, otherwise `session/load` plus local replay cleanup on runtimes
506
504
  that advertise only load support.
507
- - **Claude**: Claude still keeps one provider-native session mapping per Borgee
508
- channel, but unlike the ACP-backed adapters it spawns a fresh CLI process for
509
- each turn. Ordinary threads inherit the host runtime cwd; eligible
510
- `task_assignment` threads run the CLI process with the hidden local
511
- task-scoped workspace as the process cwd, again without implying that the
512
- target repository is already checked out there.
513
-
514
505
  There is no separate transcript/history store on our side. Claude, Codex, and
515
506
  Copilot only persist the native session ids they should try to resume later;
516
507
  cross-host continuity still does not exist in this runtime.
@@ -128,7 +128,7 @@ export declare class AgentsHost {
128
128
  private resolveVisibleTurnBody;
129
129
  private shouldRelayProtocolReply;
130
130
  private normalizeMessage;
131
- private markAssignedTaskInProgress;
131
+ private resolveTaskAssignmentDelivery;
132
132
  private ensureSelfAgentId;
133
133
  private classifyAuthor;
134
134
  private refreshParticipantDirectory;
@@ -527,6 +527,11 @@ export class AgentsHost {
527
527
  if (!normalized) {
528
528
  return;
529
529
  }
530
+ const effective = await this.resolveTaskAssignmentDelivery(msg, normalized);
531
+ if (!effective) {
532
+ return;
533
+ }
534
+ msg = effective;
530
535
  let taskThreadContext = { state: 'inactive' };
531
536
  let attentionSnapshot;
532
537
  if (this.attentionFollowSemanticsEnabled
@@ -542,9 +547,6 @@ export class AgentsHost {
542
547
  }
543
548
  }
544
549
  }
545
- if (msg.message_type === 'task_assignment') {
546
- await this.markAssignedTaskInProgress(msg.channel_id, normalized.content);
547
- }
548
550
  await this.runUngatedTurn(msg, normalized.authorId, normalized.content, taskThreadContext, attentionSnapshot);
549
551
  }
550
552
  async handleCollaborationMessage(msg) {
@@ -552,9 +554,11 @@ export class AgentsHost {
552
554
  if (!normalized) {
553
555
  return;
554
556
  }
555
- if (msg.message_type === 'task_assignment') {
556
- await this.markAssignedTaskInProgress(msg.channel_id, normalized.content);
557
+ const effective = await this.resolveTaskAssignmentDelivery(msg, normalized);
558
+ if (!effective) {
559
+ return;
557
560
  }
561
+ msg = effective;
558
562
  const channelState = this.ensureCollaborationChannelState(msg.channel_id);
559
563
  await this.ensureProtocolStateLoaded(msg.channel_id, channelState);
560
564
  await this.ensureAttentionSnapshotLoaded(msg.channel_id, channelState);
@@ -2640,28 +2644,51 @@ export class AgentsHost {
2640
2644
  content,
2641
2645
  };
2642
2646
  }
2643
- async markAssignedTaskInProgress(threadId, content) {
2647
+ // Only a task assigned to this agent drives a task-assignment turn: it keeps the message a
2648
+ // task_assignment (and best-effort flips an open task to in_progress). An unassigned or
2649
+ // other-assigned task_assignment degrades to an ordinary message, and this agent's own echo of
2650
+ // it drops, so the creator never auto-starts work it was not assigned.
2651
+ async resolveTaskAssignmentDelivery(msg, normalized) {
2652
+ if (msg.message_type !== 'task_assignment') {
2653
+ return msg;
2654
+ }
2655
+ const selfAgentId = await this.ensureSelfAgentId();
2656
+ let task;
2644
2657
  try {
2645
- const selfAgentId = await this.ensureSelfAgentId();
2646
- const task = await waitForTaskForThread(this.borgee, threadId, {
2647
- preferredTaskId: extractTaskIdFromTaskAssignmentContent(content),
2658
+ task = await waitForTaskForThread(this.borgee, msg.channel_id, {
2659
+ preferredTaskId: extractTaskIdFromTaskAssignmentContent(normalized.content),
2648
2660
  attempts: 10,
2649
2661
  delayMs: 250,
2650
2662
  });
2651
- if (!task || task.status !== 'open' || task.assigneeId !== selfAgentId) {
2652
- return;
2653
- }
2654
- await this.borgee.updateTask({
2655
- taskId: task.id,
2656
- status: 'in_progress',
2657
- });
2658
2663
  }
2659
2664
  catch (error) {
2660
- this.logger.debugError('best-effort task auto-start failed', {
2661
- channelId: threadId,
2665
+ this.logger.debugError('task-assignment resolution failed', {
2666
+ channelId: msg.channel_id,
2662
2667
  error,
2663
2668
  });
2669
+ task = null;
2670
+ }
2671
+ if (task && task.assigneeId === selfAgentId) {
2672
+ if (task.status === 'open') {
2673
+ try {
2674
+ await this.borgee.updateTask({
2675
+ taskId: task.id,
2676
+ status: 'in_progress',
2677
+ });
2678
+ }
2679
+ catch (error) {
2680
+ this.logger.debugError('best-effort task auto-start failed', {
2681
+ channelId: msg.channel_id,
2682
+ error,
2683
+ });
2684
+ }
2685
+ }
2686
+ return msg;
2687
+ }
2688
+ if (normalized.authorId === selfAgentId) {
2689
+ return null;
2664
2690
  }
2691
+ return { ...msg, message_type: 'default' };
2665
2692
  }
2666
2693
  async ensureSelfAgentId() {
2667
2694
  if (this.selfAgentId) {
@@ -83,4 +83,4 @@ export declare function parseLogArgs(argv: string[]): ParsedLogArgs;
83
83
  export declare function parseDescribeManagedArgs(argv: string[]): ParsedDescribeManagedArgs;
84
84
  export declare function parseCleanupManagedArgs(argv: string[]): ParsedCleanupManagedArgs;
85
85
  export declare function parseApplyManagedArgs(argv: string[]): ParsedApplyManagedArgs;
86
- export declare const USAGE = "Usage:\n agents-host start <serverUrl> <apiKey> [options]\n agents-host start-managed <serverUrl>\n agents-host start-managed <serverUrl> <apiKey> [agent-options]\n agents-host describe-managed <serverUrl>\n agents-host cleanup-managed <serverUrl> [--purge]\n agents-host apply-managed <serverUrl> --stdin\n agents-host apply-managed <serverUrl> --spec-json <json>\n agents-host log <serverUrl> [--lines <n>] [--follow]\n agents-host log <serverUrl> --path\n agents-host start --config <path-to-host-config> [--debug]\n agents-host validate --config <path-to-host-config>\n agents-host describe --config <path-to-host-config>\n agents-host print-layout --root <dir>\n agents-host generate-config --root <dir> --stdin\n agents-host generate-config --root <dir> --spec-json <json>\n\nForeground start options:\n --debug Enable host/provider debug logs (or set AGENTS_HOST_DEBUG=1)\n\nSingle-agent agent options:\n --name <name> Display name (default: Assistant)\n --provider <claude|codex|copilot>\n Runtime provider (default: claude)\n --claude-command <cmd> Local Claude CLI command (default: claude)\n --claude-args <args> Local Claude CLI args (default: --print --permission-mode bypassPermissions)\n --codex-command <cmd> Local Codex ACP adapter command (default: codex-acp)\n --codex-args <args> Local Codex ACP adapter args\n --copilot-command <cmd> Local Copilot CLI command (default: copilot)\n --copilot-args <args> Ignored by the Copilot ACP prototype\n --copilot-session-ttl-minutes <minutes>\n Idle session TTL for Copilot ACP sessions (default: 2880)\n\nCommand summary:\n start <serverUrl> <apiKey> Start one foreground hosted agent (legacy-compatible behavior)\n start --config <path> Start agents + supervisor + watchers from a host config file\n start-managed <serverUrl> Restart or resume an existing per-serverUrl managed daemon\n start-managed <serverUrl> <apiKey>\n Upsert one agent into the per-serverUrl local daemon and exit after reconcile\n describe-managed <serverUrl> Print managed-runtime spec JSON for machine callers\n cleanup-managed <serverUrl> Stop one managed-runtime daemon locally; --purge also removes its runtime root\n apply-managed <serverUrl> Apply one managed-runtime full-set spec for machine callers\n log <serverUrl> Print the managed daemon log tail for one server runtime\n validate --config <path> Validate local-config files without starting agents or watchers\n describe --config <path> Print the current managed full-set spec as JSON\n print-layout --root <dir> Print the canonical default local-config layout as JSON\n generate-config --root <dir> --stdin Materialize canonical local-config files from stdin\n generate-config --root <dir> --spec-json <json>\n Compatibility input; JSON is exposed in process arguments\n\nExamples:\n agents-host start https://borgee.example.com bgr_xxxxxxxx --provider copilot --debug\n agents-host start-managed https://borgee.example.com\n agents-host start-managed https://borgee.example.com bgr_xxxxxxxx --provider copilot\n agents-host describe-managed https://borgee.example.com\n agents-host cleanup-managed https://borgee.example.com --purge\n printf '%s' '{\"host\":{\"borgeeBaseUrl\":\"https://borgee.example.com\"},\"agents\":[{\"key\":\"cp1\",\"name\":\"Copilot\",\"apiKey\":\"bgr_xxx\",\"provider\":\"copilot\"}]}' | agents-host apply-managed https://borgee.example.com --stdin\n agents-host log https://borgee.example.com --lines 200 --follow\n agents-host log https://borgee.example.com --path\n agents-host start --config ./agents-host.yaml --debug\n agents-host validate --config ./agents-host.yaml\n agents-host describe --config ./agents-host.yaml\n agents-host print-layout --root ./runtime-root\n printf '%s' '{\"host\":{\"borgeeBaseUrl\":\"https://borgee.example.com\"},\"agents\":[{\"key\":\"cp1\",\"name\":\"Copilot\",\"apiKey\":\"bgr_xxx\",\"provider\":\"copilot\"}]}' | agents-host generate-config --root ./runtime-root --stdin\n";
86
+ export declare const USAGE = "Usage:\n agents-host start <serverUrl> <apiKey> [options]\n agents-host start-managed <serverUrl>\n agents-host start-managed <serverUrl> <apiKey> [agent-options]\n agents-host describe-managed <serverUrl>\n agents-host cleanup-managed <serverUrl> [--purge]\n agents-host apply-managed <serverUrl> --stdin\n agents-host apply-managed <serverUrl> --spec-json <json>\n agents-host log <serverUrl> [--lines <n>] [--follow]\n agents-host log <serverUrl> --path\n agents-host start --config <path-to-host-config> [--debug]\n agents-host validate --config <path-to-host-config>\n agents-host describe --config <path-to-host-config>\n agents-host print-layout --root <dir>\n agents-host generate-config --root <dir> --stdin\n agents-host generate-config --root <dir> --spec-json <json>\n\nForeground start options:\n --debug Enable host/provider debug logs (or set AGENTS_HOST_DEBUG=1)\n\nSingle-agent agent options:\n --name <name> Display name (default: Assistant)\n --provider <claude|codex|copilot>\n Runtime provider (default: claude)\n --claude-command <cmd> Local Claude ACP adapter command (default: claude-agent-acp)\n --claude-args <args> Local Claude ACP adapter args (empty on the shipped bundled path)\n --codex-command <cmd> Local Codex ACP adapter command (default: codex-acp)\n --codex-args <args> Local Codex ACP adapter args\n --copilot-command <cmd> Local Copilot CLI command (default: copilot)\n --copilot-args <args> Ignored by the Copilot ACP prototype\n --copilot-session-ttl-minutes <minutes>\n Idle session TTL for Copilot ACP sessions (default: 2880)\n\nCommand summary:\n start <serverUrl> <apiKey> Start one foreground hosted agent (legacy-compatible behavior)\n start --config <path> Start agents + supervisor + watchers from a host config file\n start-managed <serverUrl> Restart or resume an existing per-serverUrl managed daemon\n start-managed <serverUrl> <apiKey>\n Upsert one agent into the per-serverUrl local daemon and exit after reconcile\n describe-managed <serverUrl> Print managed-runtime spec JSON for machine callers\n cleanup-managed <serverUrl> Stop one managed-runtime daemon locally; --purge also removes its runtime root\n apply-managed <serverUrl> Apply one managed-runtime full-set spec for machine callers\n log <serverUrl> Print the managed daemon log tail for one server runtime\n validate --config <path> Validate local-config files without starting agents or watchers\n describe --config <path> Print the current managed full-set spec as JSON\n print-layout --root <dir> Print the canonical default local-config layout as JSON\n generate-config --root <dir> --stdin Materialize canonical local-config files from stdin\n generate-config --root <dir> --spec-json <json>\n Compatibility input; JSON is exposed in process arguments\n\nExamples:\n agents-host start https://borgee.example.com bgr_xxxxxxxx --provider copilot --debug\n agents-host start-managed https://borgee.example.com\n agents-host start-managed https://borgee.example.com bgr_xxxxxxxx --provider copilot\n agents-host describe-managed https://borgee.example.com\n agents-host cleanup-managed https://borgee.example.com --purge\n printf '%s' '{\"host\":{\"borgeeBaseUrl\":\"https://borgee.example.com\"},\"agents\":[{\"key\":\"cp1\",\"name\":\"Copilot\",\"apiKey\":\"bgr_xxx\",\"provider\":\"copilot\"}]}' | agents-host apply-managed https://borgee.example.com --stdin\n agents-host log https://borgee.example.com --lines 200 --follow\n agents-host log https://borgee.example.com --path\n agents-host start --config ./agents-host.yaml --debug\n agents-host validate --config ./agents-host.yaml\n agents-host describe --config ./agents-host.yaml\n agents-host print-layout --root ./runtime-root\n printf '%s' '{\"host\":{\"borgeeBaseUrl\":\"https://borgee.example.com\"},\"agents\":[{\"key\":\"cp1\",\"name\":\"Copilot\",\"apiKey\":\"bgr_xxx\",\"provider\":\"copilot\"}]}' | agents-host generate-config --root ./runtime-root --stdin\n";
package/dist/cli-args.js CHANGED
@@ -494,8 +494,8 @@ Single-agent agent options:
494
494
  --name <name> Display name (default: Assistant)
495
495
  --provider <claude|codex|copilot>
496
496
  Runtime provider (default: claude)
497
- --claude-command <cmd> Local Claude CLI command (default: claude)
498
- --claude-args <args> Local Claude CLI args (default: --print --permission-mode bypassPermissions)
497
+ --claude-command <cmd> Local Claude ACP adapter command (default: claude-agent-acp)
498
+ --claude-args <args> Local Claude ACP adapter args (empty on the shipped bundled path)
499
499
  --codex-command <cmd> Local Codex ACP adapter command (default: codex-acp)
500
500
  --codex-args <args> Local Codex ACP adapter args
501
501
  --copilot-command <cmd> Local Copilot CLI command (default: copilot)
@@ -21,7 +21,6 @@ export const INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV = 'AGENTS_HOST_INTERNAL_PROVI
21
21
  export const MANAGED_RUNTIME_SETTINGS_SCHEMA_VERSION = 1;
22
22
  const VALID_PROVIDER_IMPLEMENTATION_ENTRIES = '"claude:v1", "claude:v2", "copilot:v1", or "copilot:v2"';
23
23
  export const DEFAULT_INTERNAL_COMPATIBILITY_GATES = Object.freeze([
24
- CLAUDE_PROVIDER_V2_COMPATIBILITY_GATE,
25
24
  COLLABORATION_CAPABILITIES_DIAGNOSTICS_COMPATIBILITY_GATE,
26
25
  COLLABORATION_OUTCOME_MODEL_COMPATIBILITY_GATE,
27
26
  CONNECTIONS_STATE_LAYER_COMPATIBILITY_GATE,
@@ -118,11 +117,15 @@ export function resolveManagedRuntimeProviderImplementationOverrides(env = proce
118
117
  const enabledGates = new Set(compatibilityGates);
119
118
  return normalizeInternalProviderImplementationOverrides(env[INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV]).filter((assignment) => {
120
119
  const [provider] = assignment.split(':');
120
+ if (provider === 'claude') {
121
+ return false;
122
+ }
121
123
  return enabledGates.has(PROVIDER_IMPLEMENTATION_COMPATIBILITY_GATES[provider]);
122
124
  });
123
125
  }
124
126
  export function resolveManagedRuntimeCompatibilityGates(env = process.env) {
125
127
  const compatibilityGates = new Set(resolveInternalCompatibilityGates(env));
128
+ compatibilityGates.delete(CLAUDE_PROVIDER_V2_COMPATIBILITY_GATE);
126
129
  const explicitlyEnabledGates = parseCompatibilityGates(env[COMPATIBILITY_GATES_ENV]);
127
130
  if (compatibilityGates.has(MANAGED_RUNTIME_CONVERGENCE_COMPATIBILITY_GATE)) {
128
131
  compatibilityGates.add(CONNECTIONS_STATE_LAYER_COMPATIBILITY_GATE);
package/dist/config.d.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  import type { AgentsHostConfig, ProviderCommandConfig, ProviderKind } from './types.js';
2
2
  export declare const MAX_COPILOT_SESSION_TTL_MINUTES: number;
3
3
  export declare const DEFAULT_COPILOT_SESSION_TTL_MINUTES: number;
4
+ export declare const DEFAULT_CLAUDE_COMMAND = "claude-agent-acp";
5
+ export declare const LEGACY_CLAUDE_COMMAND = "claude";
6
+ export declare const LEGACY_CLAUDE_ONE_SHOT_ARGS: readonly ["--print", "--permission-mode", "bypassPermissions"];
4
7
  export declare const DEFAULT_PROVIDER_COMMAND_CONFIG: ProviderCommandConfig;
5
8
  export declare function requireNonEmptyString(value: unknown, message: string): string;
6
9
  export declare function optionalNonEmptyString(value: unknown, fieldName: string, sourceLabel: string): string | undefined;
@@ -9,5 +12,10 @@ export declare function optionalStringArray(value: unknown, fieldName: string, s
9
12
  export declare function parseCopilotSessionTtlMinutesValue(value: unknown, sourceLabel: string): number;
10
13
  export declare function resolveProvider(rawValue: string, sourceLabel: string): ProviderKind;
11
14
  export declare function assertProviderCompatibility(provider: ProviderKind, sourceLabel: string, env?: NodeJS.ProcessEnv): void;
15
+ export declare function isLegacyClaudeCompatibilityAlias(command: string, args: string[]): boolean;
16
+ export declare function isLegacyClaudeBinaryCommand(command: string): boolean;
17
+ export declare function hasLegacyClaudeOneShotArgs(args: string[]): boolean;
18
+ export declare function assertClaudeCommandCompatibility(command: string, args: string[], sourceLabel: string): void;
19
+ export declare function assertProviderCommandCompatibility(provider: ProviderKind, config: Pick<ProviderCommandConfig, 'claudeCommand' | 'claudeArgs'>, sourceLabel: string): void;
12
20
  export declare function resolveProviderCommandConfig(overrides?: Partial<ProviderCommandConfig>): ProviderCommandConfig;
13
21
  export declare function loadConfigFromEnv(env?: NodeJS.ProcessEnv): AgentsHostConfig;
package/dist/config.js CHANGED
@@ -1,11 +1,15 @@
1
+ import { basename } from 'node:path';
1
2
  import { resolveSingleAgentStateRoot } from './state-paths.js';
2
3
  import { CODEX_PROVIDER_COMPATIBILITY_GATE, resolveInternalCompatibilityGates, } from './compatibility-gates.js';
3
4
  const MAX_TIMER_DELAY_MS = 2_147_483_647;
4
5
  export const MAX_COPILOT_SESSION_TTL_MINUTES = MAX_TIMER_DELAY_MS / 60_000;
5
6
  export const DEFAULT_COPILOT_SESSION_TTL_MINUTES = 2 * 24 * 60;
7
+ export const DEFAULT_CLAUDE_COMMAND = 'claude-agent-acp';
8
+ export const LEGACY_CLAUDE_COMMAND = 'claude';
9
+ export const LEGACY_CLAUDE_ONE_SHOT_ARGS = ['--print', '--permission-mode', 'bypassPermissions'];
6
10
  export const DEFAULT_PROVIDER_COMMAND_CONFIG = {
7
- claudeCommand: 'claude',
8
- claudeArgs: ['--print', '--permission-mode', 'bypassPermissions'],
11
+ claudeCommand: DEFAULT_CLAUDE_COMMAND,
12
+ claudeArgs: [],
9
13
  codexCommand: 'codex-acp',
10
14
  codexArgs: [],
11
15
  copilotCommand: 'copilot',
@@ -74,6 +78,38 @@ export function assertProviderCompatibility(provider, sourceLabel, env = process
74
78
  throw new Error(`${sourceLabel}: provider "codex" requires the shipped ${CODEX_PROVIDER_COMPATIBILITY_GATE} path to remain enabled`);
75
79
  }
76
80
  }
81
+ export function isLegacyClaudeCompatibilityAlias(command, args) {
82
+ if (command !== LEGACY_CLAUDE_COMMAND || args.length !== LEGACY_CLAUDE_ONE_SHOT_ARGS.length) {
83
+ return false;
84
+ }
85
+ return args.every((arg, index) => arg === LEGACY_CLAUDE_ONE_SHOT_ARGS[index]);
86
+ }
87
+ export function isLegacyClaudeBinaryCommand(command) {
88
+ return basename(command) === LEGACY_CLAUDE_COMMAND;
89
+ }
90
+ export function hasLegacyClaudeOneShotArgs(args) {
91
+ return (args.length === LEGACY_CLAUDE_ONE_SHOT_ARGS.length
92
+ && args.every((arg, index) => arg === LEGACY_CLAUDE_ONE_SHOT_ARGS[index]));
93
+ }
94
+ export function assertClaudeCommandCompatibility(command, args, sourceLabel) {
95
+ if (command === DEFAULT_CLAUDE_COMMAND) {
96
+ if (args.length > 0) {
97
+ throw new Error(`Invalid Claude config in ${sourceLabel}: the shipped ${DEFAULT_CLAUDE_COMMAND} path does not accept CLAUDE_ARGS/claudeArgs. Leave them empty or point claudeCommand/CLAUDE_COMMAND at a custom ACP adapter command instead.`);
98
+ }
99
+ return;
100
+ }
101
+ if (isLegacyClaudeBinaryCommand(command)) {
102
+ if (isLegacyClaudeCompatibilityAlias(command, args)) {
103
+ return;
104
+ }
105
+ throw new Error(`Invalid Claude config in ${sourceLabel}: raw "${LEGACY_CLAUDE_COMMAND}" commands no longer speak ACP directly. Use the shipped ${DEFAULT_CLAUDE_COMMAND} default, keep only the exact legacy compatibility alias "${LEGACY_CLAUDE_COMMAND} ${LEGACY_CLAUDE_ONE_SHOT_ARGS.join(' ')}", or point claudeCommand/CLAUDE_COMMAND at a real ACP adapter command.`);
106
+ }
107
+ }
108
+ export function assertProviderCommandCompatibility(provider, config, sourceLabel) {
109
+ if (provider === 'claude') {
110
+ assertClaudeCommandCompatibility(config.claudeCommand, config.claudeArgs, sourceLabel);
111
+ }
112
+ }
77
113
  export function resolveProviderCommandConfig(overrides = {}) {
78
114
  return {
79
115
  claudeCommand: overrides.claudeCommand ?? DEFAULT_PROVIDER_COMMAND_CONFIG.claudeCommand,
@@ -89,20 +125,22 @@ export function loadConfigFromEnv(env = process.env) {
89
125
  const provider = resolveProvider(envOr('RUNTIME_PROVIDER', 'claude', env), 'Unsupported RUNTIME_PROVIDER');
90
126
  assertProviderCompatibility(provider, 'Unsupported RUNTIME_PROVIDER', env);
91
127
  const agentApiKey = requireEnv('BORGEE_AGENT_API_KEY', env);
128
+ const providerConfig = resolveProviderCommandConfig({
129
+ claudeCommand: envOr('CLAUDE_COMMAND', DEFAULT_PROVIDER_COMMAND_CONFIG.claudeCommand, env),
130
+ claudeArgs: parseArgs(envOr('CLAUDE_ARGS', DEFAULT_PROVIDER_COMMAND_CONFIG.claudeArgs.join(' '), env)),
131
+ codexCommand: envOr('CODEX_COMMAND', DEFAULT_PROVIDER_COMMAND_CONFIG.codexCommand, env),
132
+ codexArgs: parseArgs(envOr('CODEX_ARGS', DEFAULT_PROVIDER_COMMAND_CONFIG.codexArgs.join(' '), env)),
133
+ copilotCommand: envOr('COPILOT_COMMAND', DEFAULT_PROVIDER_COMMAND_CONFIG.copilotCommand, env),
134
+ copilotArgs: parseArgs(envOr('COPILOT_ARGS', DEFAULT_PROVIDER_COMMAND_CONFIG.copilotArgs.join(' '), env)),
135
+ copilotSessionTtlMinutes: env.COPILOT_SESSION_TTL_MINUTES && env.COPILOT_SESSION_TTL_MINUTES.trim().length > 0
136
+ ? parseCopilotSessionTtlMinutesValue(env.COPILOT_SESSION_TTL_MINUTES, 'environment variable COPILOT_SESSION_TTL_MINUTES')
137
+ : DEFAULT_PROVIDER_COMMAND_CONFIG.copilotSessionTtlMinutes,
138
+ });
139
+ assertProviderCommandCompatibility(provider, providerConfig, 'environment variables');
92
140
  return {
93
141
  borgeeBaseUrl: requireEnv('BORGEE_BASE_URL', env),
94
142
  stateRootDir: resolveSingleAgentStateRoot(env, undefined, agentApiKey),
95
- ...resolveProviderCommandConfig({
96
- claudeCommand: envOr('CLAUDE_COMMAND', DEFAULT_PROVIDER_COMMAND_CONFIG.claudeCommand, env),
97
- claudeArgs: parseArgs(envOr('CLAUDE_ARGS', DEFAULT_PROVIDER_COMMAND_CONFIG.claudeArgs.join(' '), env)),
98
- codexCommand: envOr('CODEX_COMMAND', DEFAULT_PROVIDER_COMMAND_CONFIG.codexCommand, env),
99
- codexArgs: parseArgs(envOr('CODEX_ARGS', DEFAULT_PROVIDER_COMMAND_CONFIG.codexArgs.join(' '), env)),
100
- copilotCommand: envOr('COPILOT_COMMAND', DEFAULT_PROVIDER_COMMAND_CONFIG.copilotCommand, env),
101
- copilotArgs: parseArgs(envOr('COPILOT_ARGS', DEFAULT_PROVIDER_COMMAND_CONFIG.copilotArgs.join(' '), env)),
102
- copilotSessionTtlMinutes: env.COPILOT_SESSION_TTL_MINUTES && env.COPILOT_SESSION_TTL_MINUTES.trim().length > 0
103
- ? parseCopilotSessionTtlMinutesValue(env.COPILOT_SESSION_TTL_MINUTES, 'environment variable COPILOT_SESSION_TTL_MINUTES')
104
- : DEFAULT_PROVIDER_COMMAND_CONFIG.copilotSessionTtlMinutes,
105
- }),
143
+ ...providerConfig,
106
144
  agent: {
107
145
  agentApiKey,
108
146
  agentName: envOr('BORGEE_AGENT_NAME', 'Assistant', env),
@@ -778,8 +778,12 @@ function parseUpdateTaskInput(taskId, body) {
778
778
  status: readOptionalString(body.status),
779
779
  assigneeId: readOptionalString(body.assigneeId) ?? readOptionalString(body.assignee_id),
780
780
  title: readOptionalString(body.title),
781
+ description: readOptionalString(body.description),
781
782
  };
782
- if (input.status === undefined && input.assigneeId === undefined && input.title === undefined) {
783
+ if (input.status === undefined &&
784
+ input.assigneeId === undefined &&
785
+ input.title === undefined &&
786
+ input.description === undefined) {
783
787
  throw new GatewayHttpError(400, { error: 'no_updates' }, 'bad-request');
784
788
  }
785
789
  return input;
@@ -2,7 +2,7 @@ import { promises as fs } from 'node:fs';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { dirname, extname, isAbsolute, join, relative, resolve } from 'node:path';
4
4
  import { parseDocument, stringify } from 'yaml';
5
- import { assertProviderCompatibility, optionalNonEmptyString, optionalStringArray, parseCopilotSessionTtlMinutesValue, requireNonEmptyString, resolveProvider, resolveProviderCommandConfig, } from './config.js';
5
+ import { assertProviderCompatibility, assertProviderCommandCompatibility, optionalNonEmptyString, optionalStringArray, parseCopilotSessionTtlMinutesValue, requireNonEmptyString, resolveProvider, resolveProviderCommandConfig, } from './config.js';
6
6
  import { resolveLocalConfigAgentStateRoot } from './state-paths.js';
7
7
  const SUPPORTED_CONFIG_EXTENSIONS = new Set(['.json', '.yaml', '.yml']);
8
8
  export const DEFAULT_LOCAL_HOST_CONFIG_FILENAME = 'agents-host.yaml';
@@ -186,6 +186,8 @@ export function parseGenerateConfigSpec(value, sourceLabel, env = process.env) {
186
186
  throw new Error(`Invalid generate-config agents[${index}] in ${sourceLabel}: expected an object`);
187
187
  }
188
188
  const agent = parseAgentConfigFile(`generate-config agents[${index}] in ${sourceLabel}`, entry, env);
189
+ const providerConfig = resolveAgentProviderCommandConfig(host.defaults, agent);
190
+ assertProviderCommandCompatibility(agent.provider, providerConfig, `generate-config agents[${index}] in ${sourceLabel}`);
189
191
  const existingIndex = seenKeys.get(agent.key);
190
192
  if (existingIndex !== undefined) {
191
193
  throw new Error(`Duplicate generate-config agent key "${agent.key}" in ${sourceLabel} at indexes ${existingIndex} and ${index}`);
@@ -598,6 +600,7 @@ function buildManagedAgentSnapshot(host, stateRootBaseDir, sourcePath, agent) {
598
600
  ...host.defaults,
599
601
  ...parseProviderCommandOverrides(agent, `agent config ${sourcePath}`),
600
602
  });
603
+ assertProviderCommandCompatibility(agent.provider, providerConfig, `agent config ${sourcePath}`);
601
604
  const config = {
602
605
  borgeeBaseUrl: host.borgeeBaseUrl,
603
606
  stateRootDir: resolveLocalConfigAgentStateRoot(stateRootBaseDir, agent.key),
@@ -614,6 +617,20 @@ function buildManagedAgentSnapshot(host, stateRootBaseDir, sourcePath, agent) {
614
617
  config,
615
618
  };
616
619
  }
620
+ function resolveAgentProviderCommandConfig(hostDefaults, agent) {
621
+ return resolveProviderCommandConfig({
622
+ ...hostDefaults,
623
+ ...(agent.claudeCommand !== undefined ? { claudeCommand: agent.claudeCommand } : {}),
624
+ ...(agent.claudeArgs !== undefined ? { claudeArgs: agent.claudeArgs } : {}),
625
+ ...(agent.codexCommand !== undefined ? { codexCommand: agent.codexCommand } : {}),
626
+ ...(agent.codexArgs !== undefined ? { codexArgs: agent.codexArgs } : {}),
627
+ ...(agent.copilotCommand !== undefined ? { copilotCommand: agent.copilotCommand } : {}),
628
+ ...(agent.copilotArgs !== undefined ? { copilotArgs: agent.copilotArgs } : {}),
629
+ ...(agent.copilotSessionTtlMinutes !== undefined
630
+ ? { copilotSessionTtlMinutes: agent.copilotSessionTtlMinutes }
631
+ : {}),
632
+ });
633
+ }
617
634
  export async function loadLocalConfigSnapshot(hostConfigPath, deps = {}) {
618
635
  const fileSystem = deps.fileSystem ?? nodeFileSystem;
619
636
  const absoluteHostConfigPath = resolve(hostConfigPath);
@@ -698,6 +715,8 @@ export async function loadLocalConfigGenerateSpec(hostConfigPath, deps = {}) {
698
715
  }
699
716
  const agentRecord = await loadParsedDocument(fileSystem, agentFilePath, 'agent config');
700
717
  const agentConfig = parseAgentConfigFile(agentFilePath, agentRecord, deps.env);
718
+ const providerConfig = resolveAgentProviderCommandConfig(hostConfig.defaults, agentConfig);
719
+ assertProviderCommandCompatibility(agentConfig.provider, providerConfig, `agent config ${agentFilePath}`);
701
720
  const existingPath = seenKeys.get(agentConfig.key);
702
721
  if (existingPath) {
703
722
  throw new Error(`Duplicate agent key "${agentConfig.key}" in ${existingPath} and ${agentFilePath}`);
@@ -5,8 +5,8 @@ import { createConnection, createServer } from 'node:net';
5
5
  import { dirname, join, resolve } from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { AgentsHostSupervisor } from './agents-host-supervisor.js';
8
- import { COMPATIBILITY_GATES_ENV, createManagedRuntimeSettingsFingerprint, INTERNAL_DISABLED_COMPATIBILITY_GATES_ENV, INTERNAL_POLICY_MODE_ENV, INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV, MANAGED_RUNTIME_CONVERGENCE_COMPATIBILITY_GATE, MANAGED_RUNTIME_SETTINGS_SCHEMA_VERSION, resolveDisabledDefaultCompatibilityGates, resolveManagedRuntimeSettingsSnapshot, normalizeInternalProviderImplementationOverrides, } from './compatibility-gates.js';
9
- import { loadConfigFromEnv } from './config.js';
8
+ import { CLAUDE_PROVIDER_V2_COMPATIBILITY_GATE, COMPATIBILITY_GATES_ENV, createManagedRuntimeSettingsFingerprint, INTERNAL_DISABLED_COMPATIBILITY_GATES_ENV, INTERNAL_POLICY_MODE_ENV, INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV, MANAGED_RUNTIME_CONVERGENCE_COMPATIBILITY_GATE, MANAGED_RUNTIME_SETTINGS_SCHEMA_VERSION, resolveDisabledDefaultCompatibilityGates, resolveManagedRuntimeSettingsSnapshot, normalizeInternalProviderImplementationOverrides, } from './compatibility-gates.js';
9
+ import { DEFAULT_PROVIDER_COMMAND_CONFIG, hasLegacyClaudeOneShotArgs, loadConfigFromEnv, } from './config.js';
10
10
  import { loadLocalConfigGenerateSpec, materializeLocalConfig, parseGenerateConfigSpec, resolveLocalConfigLayout, } from './local-config.js';
11
11
  import { normalizeManagedRuntimeKey, resolveManagedBootstrapLockPath, resolveManagedDaemonLogPath, resolveManagedDaemonSocketPath, resolveManagedRuntimeRoot, resolveManagedRuntimeSettingsPath, } from './state-paths.js';
12
12
  const MANAGED_ROOT_MODE = 0o700;
@@ -149,8 +149,9 @@ function resolveDesiredManagedRuntimeSettings(env = process.env) {
149
149
  function normalizeManagedRuntimeSettingsSnapshot(snapshot) {
150
150
  const compatibilityGates = [...new Set(snapshot.compatibilityGates.map((gate) => gate.trim()))]
151
151
  .filter((gate) => gate.length > 0)
152
+ .filter((gate) => gate !== CLAUDE_PROVIDER_V2_COMPATIBILITY_GATE)
152
153
  .sort((left, right) => left.localeCompare(right));
153
- const providerImplementationOverrides = normalizeInternalProviderImplementationOverrides(snapshot.providerImplementationOverrides.join(','));
154
+ const providerImplementationOverrides = normalizeInternalProviderImplementationOverrides(snapshot.providerImplementationOverrides.join(',')).filter((assignment) => !assignment.startsWith('claude:'));
154
155
  return {
155
156
  schemaVersion: MANAGED_RUNTIME_SETTINGS_SCHEMA_VERSION,
156
157
  compatibilityGates,
@@ -341,9 +342,18 @@ export function buildManagedLocalAgentConfig(options) {
341
342
  },
342
343
  };
343
344
  }
344
- function mergeManagedLocalAgentConfig(existingAgent, generatedAgent, envOverrides) {
345
+ function mergeManagedLocalAgentConfig(hostDefaults, existingAgent, generatedAgent, envOverrides) {
345
346
  const overrides = envOverrides ?? {};
346
347
  const hasOverride = (key) => Object.prototype.hasOwnProperty.call(overrides, key);
348
+ const effectiveExistingClaudeCommand = existingAgent.claudeCommand ?? hostDefaults?.claudeCommand;
349
+ const effectiveExistingClaudeArgs = existingAgent.claudeArgs ?? hostDefaults?.claudeArgs ?? [];
350
+ const hasLegacyClaudeDefaults = effectiveExistingClaudeCommand === 'claude' && hasLegacyClaudeOneShotArgs(effectiveExistingClaudeArgs);
351
+ const shouldRefreshLegacyClaudeDefaults = hasLegacyClaudeDefaults
352
+ && generatedAgent.claudeCommand === DEFAULT_PROVIDER_COMMAND_CONFIG.claudeCommand
353
+ && JSON.stringify(generatedAgent.claudeArgs ?? []) === JSON.stringify(DEFAULT_PROVIDER_COMMAND_CONFIG.claudeArgs);
354
+ const shouldResetLegacyClaudeArgsForCommandOverride = hasLegacyClaudeDefaults
355
+ && hasOverride('CLAUDE_COMMAND')
356
+ && !hasOverride('CLAUDE_ARGS');
347
357
  return {
348
358
  ...cloneLocalAgentConfig(existingAgent),
349
359
  key: generatedAgent.key,
@@ -351,8 +361,12 @@ function mergeManagedLocalAgentConfig(existingAgent, generatedAgent, envOverride
351
361
  enabled: true,
352
362
  name: hasOverride('BORGEE_AGENT_NAME') ? generatedAgent.name : existingAgent.name,
353
363
  provider: hasOverride('RUNTIME_PROVIDER') ? generatedAgent.provider : existingAgent.provider,
354
- claudeCommand: hasOverride('CLAUDE_COMMAND') ? generatedAgent.claudeCommand : existingAgent.claudeCommand,
364
+ claudeCommand: hasOverride('CLAUDE_COMMAND') || shouldRefreshLegacyClaudeDefaults
365
+ ? generatedAgent.claudeCommand
366
+ : existingAgent.claudeCommand,
355
367
  claudeArgs: hasOverride('CLAUDE_ARGS')
368
+ || shouldRefreshLegacyClaudeDefaults
369
+ || shouldResetLegacyClaudeArgsForCommandOverride
356
370
  ? [...(generatedAgent.claudeArgs ?? [])]
357
371
  : [...(existingAgent.claudeArgs ?? [])],
358
372
  codexCommand: hasOverride('CODEX_COMMAND') ? generatedAgent.codexCommand : existingAgent.codexCommand,
@@ -1005,7 +1019,7 @@ export async function bootstrapManagedDaemonStart(options, deps = {}) {
1005
1019
  return existingAgent
1006
1020
  ? {
1007
1021
  ...generatedManagedAgent,
1008
- agent: mergeManagedLocalAgentConfig(existingAgent, generatedManagedAgent.agent, explicitManagedAgentOverrides),
1022
+ agent: mergeManagedLocalAgentConfig(currentManagedSpec?.host.defaults, existingAgent, generatedManagedAgent.agent, explicitManagedAgentOverrides),
1009
1023
  }
1010
1024
  : generatedManagedAgent;
1011
1025
  })();
@@ -1,19 +1,25 @@
1
1
  import spawn from 'cross-spawn';
2
+ import { PROTOCOL_VERSION, client, methods, ndJsonStream } from '@agentclientprotocol/sdk';
2
3
  import { type DebugLogger } from '../../debug.js';
3
4
  import type { PreparedProviderTurnInput, ProviderGenerateOptions } from '../../types.js';
4
5
  import type { ClaudeChannelSessionStore } from './session-store.js';
5
- interface ClaudeCliRuntime {
6
+ interface ClaudeAcpRuntime {
6
7
  spawn: typeof spawn;
8
+ client: typeof client;
9
+ ndJsonStream: typeof ndJsonStream;
10
+ methods: typeof methods;
11
+ protocolVersion: typeof PROTOCOL_VERSION;
7
12
  cwd: string;
13
+ shutdownGracePeriodMs: number;
14
+ shutdownForceKillWaitMs: number;
8
15
  }
9
16
  /**
10
- * CLI client for the Claude Code CLI (`claude`) non-interactive mode, with
11
- * native provider-session continuity.
17
+ * Persistent ACP-backed client for the Claude ACP adapter.
12
18
  *
13
- * Claude session memory remains entirely inside the Claude CLI. This client
14
- * only pins one native session id per routed provider session and serializes
15
- * turns per route so `--resume` is never called concurrently for the same
16
- * native session.
19
+ * The public caller surface intentionally stays stable: callers still create a
20
+ * `ClaudeCliClient`, then call `generateReply()` and `dispose()`. Internally,
21
+ * the shipped runtime now runs one Claude ACP adapter process and reuses one
22
+ * ACP session per routed Borgee channel.
17
23
  */
18
24
  export declare class ClaudeCliClient {
19
25
  private readonly command;
@@ -24,28 +30,61 @@ export declare class ClaudeCliClient {
24
30
  private readonly runtime;
25
31
  private readonly channels;
26
32
  private readonly persistedSessions;
33
+ private readonly closingSessions;
34
+ private readonly pendingSessionStarts;
35
+ private readonly pendingSessionCloses;
36
+ private readonly pendingSessionStoreOperations;
37
+ private readonly fatalPromise;
38
+ private rejectFatalPromise;
39
+ private child?;
40
+ private connection?;
41
+ private startPromise?;
42
+ private shutdownPromise?;
43
+ private childExitPromise?;
44
+ private resolveChildExit?;
45
+ private fatalError;
46
+ private disposing;
47
+ private backendClosed;
27
48
  private loadedSessionStoreAgentId;
28
- private stopped;
29
49
  private sessionStoreLoadPromise;
30
50
  private sessionStoreWriteQueue;
31
- constructor(command: string, args: string[], runtimeOverrides?: Partial<ClaudeCliRuntime>, sessionStore?: ClaudeChannelSessionStore | undefined, resolveSessionStoreAgentId?: () => string | undefined, logger?: DebugLogger);
51
+ private sessionCapabilities;
52
+ private childStderr;
53
+ constructor(command: string, args?: string[], runtimeOverrides?: Partial<ClaudeAcpRuntime>, sessionStore?: ClaudeChannelSessionStore | undefined, resolveSessionStoreAgentId?: () => string | undefined, logger?: DebugLogger);
32
54
  generateReply(turn: PreparedProviderTurnInput, options?: ProviderGenerateOptions): Promise<string>;
33
55
  generateReply(channelId: string, prompt: string, options?: ProviderGenerateOptions): Promise<string>;
34
56
  dispose(): Promise<void>;
57
+ private ensureStarted;
58
+ private startBackend;
35
59
  private getOrCreateChannelState;
36
60
  private processChannelQueue;
61
+ private getOrCreateSession;
62
+ private startFreshSession;
63
+ private restoreOrCreateSession;
64
+ private restoreSession;
65
+ private clearBufferedSessionReplay;
66
+ private resolveSessionCwd;
67
+ private recycleSessionIfScopeChanged;
37
68
  private runTurn;
38
- private runTurnAttempt;
69
+ private raceWithFatal;
70
+ private failAll;
71
+ private handlePermissionRequest;
72
+ private invalidateSession;
73
+ private closeSession;
74
+ private rejectQueuedTurnsAfterSessionTaint;
75
+ private findChannelIdBySessionId;
39
76
  private currentSessionStoreAgentId;
40
77
  private ensureSessionStoreLoaded;
41
- private hydrateChannelState;
78
+ private readPersistedSessionId;
42
79
  private persistSession;
43
80
  private persistSessionBestEffort;
44
- private resetPersistedSession;
45
- private resolveTurnCwd;
46
- private resetSessionIfCwdChanged;
47
- private resetPersistedSessionBestEffort;
81
+ private clearPersistedSession;
82
+ private clearPersistedSessionBestEffort;
48
83
  private enqueueSessionStoreWrite;
49
- private run;
84
+ private trackSessionStoreOperation;
85
+ private shutdownBackend;
86
+ private waitForPendingSessionStarts;
87
+ private waitForPendingSessionCloses;
88
+ private waitForChildExit;
50
89
  }
51
90
  export {};