qlogicagent 2.18.9 → 2.18.10
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/dist/cli.js +1 -1
- package/dist/host-contract.js +1 -1
- package/dist/index.js +445 -984
- package/dist/pet-host.js +8 -8
- package/dist/project-memory-host.js +40 -0
- package/dist/protocol.js +1 -1
- package/dist/types/cli/acp-session-host.d.ts +1 -1
- package/dist/types/cli/community-resource-installer.d.ts +3 -5
- package/dist/types/cli/default-project-bootstrap.d.ts +1 -1
- package/dist/types/cli/handlers/agents-handler.d.ts +8 -6
- package/dist/types/cli/handlers/community-handler.d.ts +0 -4
- package/dist/types/cli/handlers/control-handler.d.ts +1 -1
- package/dist/types/cli/handlers/project-handler.d.ts +1 -1
- package/dist/types/cli/handlers/session-handler.d.ts +0 -7
- package/dist/types/cli/handlers/solo-handler.d.ts +0 -2
- package/dist/types/cli/memory-coordinator.d.ts +1 -1
- package/dist/types/cli/multi-agent-state-coordinator.d.ts +0 -3
- package/dist/types/cli/pet-runtime.d.ts +5 -5
- package/dist/types/cli/product-coordinator.d.ts +0 -2
- package/dist/types/cli/project-memory-store-factory.d.ts +11 -1
- package/dist/types/cli/rpc-registry.d.ts +0 -2
- package/dist/types/cli/stdio-runtime-bootstrap.d.ts +2 -0
- package/dist/types/cli/stdio-runtime-services.d.ts +2 -0
- package/dist/types/cli/stdio-server.d.ts +3 -1
- package/dist/types/config/cn-mirror.d.ts +2 -2
- package/dist/types/host-contract/index.d.ts +167 -9
- package/dist/types/orchestration/agent-instance.d.ts +1 -3
- package/dist/types/orchestration/goal-mode-adapters.d.ts +0 -3
- package/dist/types/orchestration/goal-run-persistence.d.ts +0 -3
- package/dist/types/orchestration/product-persistence.d.ts +1 -4
- package/dist/types/orchestration/product-planner.d.ts +2 -3
- package/dist/types/orchestration/run-state-host-authority.d.ts +7 -0
- package/dist/types/orchestration/solo-evaluator.d.ts +2 -3
- package/dist/types/orchestration/solo-persistence.d.ts +4 -7
- package/dist/types/orchestration/testing/delegate-test-bridge.d.ts +13 -2
- package/dist/types/orchestration/workflow/node-schema.d.ts +2 -1
- package/dist/types/orchestration/workflow/qla-executor-host.d.ts +1 -1
- package/dist/types/orchestration/workflow/workflow-bundle.d.ts +1 -1
- package/dist/types/project-memory-host.d.ts +3 -0
- package/dist/types/protocol/wire/acp-agent-management.d.ts +1 -1
- package/dist/types/protocol/wire/acp-protocol.d.ts +1 -1
- package/dist/types/runtime/infra/acp-detector.d.ts +1 -1
- package/dist/types/runtime/infra/background-tasks.d.ts +1 -1
- package/dist/types/runtime/pet/pet-community-assets.d.ts +7 -17
- package/dist/types/runtime/pet/petdex-vision-qa.d.ts +12 -0
- package/dist/types/runtime/ports/memory-recall-source.d.ts +10 -0
- package/dist/types/runtime/ports/project-memory-store.d.ts +1 -1
- package/dist/types/runtime/session/session-persistence.d.ts +3 -4
- package/dist/types/skills/memory/host-memory-provider.d.ts +2 -2
- package/dist/types/skills/memory/memory-config-resolver.d.ts +4 -0
- package/dist/types/skills/memory/task-distillation.d.ts +1 -1
- package/dist/types/test-support/run-state-authority-setup.d.ts +1 -0
- package/dist/types/transport/host-pet-client.d.ts +20 -0
- package/dist/types/transport/host-run-state-client.d.ts +17 -0
- package/dist/workflow-host.js +9 -9
- package/package.json +12 -2
- package/dist/runtime/infra/mcp-bridge-server.js +0 -338
- package/dist/types/cli/handlers/message-feedback-handler.d.ts +0 -31
- package/dist/types/runtime/infra/agent-process.d.ts +0 -368
- package/dist/types/runtime/infra/external-agent-pool.d.ts +0 -89
- package/dist/types/skills/memory/local-memory-provider.d.ts +0 -325
- package/dist/types/skills/memory/memory-provider-factory.d.ts +0 -33
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Process Manager — CC tmux-aligned subprocess isolation.
|
|
3
|
-
*
|
|
4
|
-
* Spawns team member agents as independent child processes, each with:
|
|
5
|
-
* - Own cwd (set to worktree path for git isolation)
|
|
6
|
-
* - Own stdin/stdout JSON-RPC transport
|
|
7
|
-
* - Own memory + tool context (no shared process.cwd)
|
|
8
|
-
* - Lifecycle tracking (PID, health, abort)
|
|
9
|
-
*
|
|
10
|
-
* CC does this via tmux split-pane + `claudeagent-id ...` commands.
|
|
11
|
-
* We spawn `node dist/cli.js` as child processes with JSON-RPC stdio.
|
|
12
|
-
*
|
|
13
|
-
* Reference: claude-code-haha/src/utils/swarm/spawnMultiAgent.ts
|
|
14
|
-
* Reference: claude-code-haha/src/utils/swarm/spawnUtils.ts
|
|
15
|
-
*/
|
|
16
|
-
import type { ExternalAgentDescriptor, McpServerConfig } from "../../protocol/wire/acp-agent-management.js";
|
|
17
|
-
import type { AgentConfig } from "../../protocol/wire/acp-agent-management.js";
|
|
18
|
-
import { AcpUsageTracker } from "./acp-usage-tracker.js";
|
|
19
|
-
export interface AgentProcessConfig {
|
|
20
|
-
/** Unique member ID (e.g. "team-research-coder"). */
|
|
21
|
-
memberId: string;
|
|
22
|
-
/** Display name. */
|
|
23
|
-
name: string;
|
|
24
|
-
/** Working directory for this agent (worktree path). */
|
|
25
|
-
cwd: string;
|
|
26
|
-
/** Initial task prompt sent after handshake. */
|
|
27
|
-
prompt: string;
|
|
28
|
-
/** Environment variables to forward (subset of parent env). */
|
|
29
|
-
env?: Record<string, string>;
|
|
30
|
-
/** Agent type hint for the child (sets system prompt behavior). */
|
|
31
|
-
agentType?: string;
|
|
32
|
-
/**
|
|
33
|
-
* Standing LLM config for an internal child. Pushed via session/set_config_option
|
|
34
|
-
* right after session/new so every turn (initial task, team send replies)
|
|
35
|
-
* resolves provider/model/apiKey explicitly. A standalone child has no llmrouter
|
|
36
|
-
* directory to hydrate a model catalog from — without this push its first turn
|
|
37
|
-
* dies with NO_PROVIDER. provider+apiKey are what the child's turn resolution
|
|
38
|
-
* requires (resolveTextGenerationConfig); model rides along for determinism.
|
|
39
|
-
*/
|
|
40
|
-
provider?: string;
|
|
41
|
-
/** Model for the child's turns (see provider). */
|
|
42
|
-
model?: string;
|
|
43
|
-
/** API key for the child's turns (see provider). */
|
|
44
|
-
apiKey?: string;
|
|
45
|
-
/** Base URL for the child's LLM API (see provider). */
|
|
46
|
-
baseUrl?: string;
|
|
47
|
-
/** Enable verbose logging in child. */
|
|
48
|
-
verbose?: boolean;
|
|
49
|
-
/** External ACP agent descriptor (if set, spawn via ACP protocol). */
|
|
50
|
-
external?: ExternalAgentDescriptor;
|
|
51
|
-
/** MCP server configs to inject into ACP session (only for external agents). */
|
|
52
|
-
mcpServers?: McpServerConfig[];
|
|
53
|
-
/** System prompt to inject into ACP session. */
|
|
54
|
-
systemPrompt?: string;
|
|
55
|
-
/**
|
|
56
|
-
* Cut 5 — RESUME a third-party native session (ACP session/load, replays history) instead of
|
|
57
|
-
* creating a fresh one. The id is the agent's OWN native session id (codex rollout id / claude
|
|
58
|
-
* UUID). Only honored when the agent advertised loadSession at initialize (handle.supportsResume);
|
|
59
|
-
* otherwise spawn throws — we never silently open a blank session ("fake continuation" is forbidden
|
|
60
|
-
* by the Phase 2 design).
|
|
61
|
-
*/
|
|
62
|
-
resumeSessionId?: string;
|
|
63
|
-
}
|
|
64
|
-
export declare function buildExternalAcpSpawnCommand(cliPath: string, acpArgs: string[]): {
|
|
65
|
-
command: string;
|
|
66
|
-
args: string[];
|
|
67
|
-
};
|
|
68
|
-
/** Snapshot of ongoing media generation progress reported by a child agent. */
|
|
69
|
-
export interface MediaProgressSnapshot {
|
|
70
|
-
/** Provider-specific task ID (e.g. volcengine job id). */
|
|
71
|
-
taskId: string;
|
|
72
|
-
/** Media type ("video" | "image" | "tts" | "3d"). */
|
|
73
|
-
mediaType: string;
|
|
74
|
-
/** Estimated completion 0-100. */
|
|
75
|
-
percent: number;
|
|
76
|
-
/** Provider status label (e.g. "queuing", "running", "processing"). */
|
|
77
|
-
status: string;
|
|
78
|
-
/** Which provider. */
|
|
79
|
-
provider?: string;
|
|
80
|
-
/** When this snapshot was last updated. */
|
|
81
|
-
updatedAt: number;
|
|
82
|
-
}
|
|
83
|
-
export interface AgentProcessHandle {
|
|
84
|
-
/** Process identifier for this agent. */
|
|
85
|
-
memberId: string;
|
|
86
|
-
/** Display name. */
|
|
87
|
-
name: string;
|
|
88
|
-
/** OS process ID (-1 if not spawned). */
|
|
89
|
-
pid: number;
|
|
90
|
-
/** Working directory. */
|
|
91
|
-
cwd: string;
|
|
92
|
-
/** Current lifecycle state. */
|
|
93
|
-
state: "starting" | "ready" | "running" | "completed" | "failed" | "killed";
|
|
94
|
-
/** Session ID assigned by the child (after initialize). */
|
|
95
|
-
sessionId?: string;
|
|
96
|
-
/** Final result text (after turn completes). */
|
|
97
|
-
resultText?: string;
|
|
98
|
-
/** Error message if failed. */
|
|
99
|
-
error?: string;
|
|
100
|
-
/** Spawn timestamp. */
|
|
101
|
-
startedAt: number;
|
|
102
|
-
/** End timestamp. */
|
|
103
|
-
endedAt?: number;
|
|
104
|
-
/** Latest media generation progress (auto-captured from child turn.media_progress). */
|
|
105
|
-
mediaProgress?: MediaProgressSnapshot;
|
|
106
|
-
/** Last tool call name seen from child (from turn.tool_call notification). */
|
|
107
|
-
lastToolCall?: string;
|
|
108
|
-
/** Last status text from child (from turn.delta notification). */
|
|
109
|
-
lastDelta?: string;
|
|
110
|
-
/** Last delta timestamp. */
|
|
111
|
-
lastActivityAt?: number;
|
|
112
|
-
/** Whether the ACP agent supports session/resume (D-1). */
|
|
113
|
-
supportsResume?: boolean;
|
|
114
|
-
/** Whether the ACP agent advertised stdio MCP support during initialize. */
|
|
115
|
-
supportsStdioMcp?: boolean;
|
|
116
|
-
/** ACP session/update types observed during the current external-agent prompt. */
|
|
117
|
-
acpUpdateTypes?: string[];
|
|
118
|
-
/** Stderr log path for this agent process, when diagnostics logging is enabled. */
|
|
119
|
-
stderrLogPath?: string;
|
|
120
|
-
/** Sanitized external ACP launch details for empty-output diagnostics. */
|
|
121
|
-
acpLaunchDiagnostics?: {
|
|
122
|
-
cliPath: string;
|
|
123
|
-
acpArgs: string[];
|
|
124
|
-
cwd: string;
|
|
125
|
-
env: string;
|
|
126
|
-
};
|
|
127
|
-
/** Last external ACP prompt elapsed time in milliseconds. */
|
|
128
|
-
acpLastPromptElapsedMs?: number;
|
|
129
|
-
}
|
|
130
|
-
/** Callbacks for process lifecycle events. */
|
|
131
|
-
export interface AgentProcessCallbacks {
|
|
132
|
-
/** Called when child emits a JSON-RPC notification. */
|
|
133
|
-
onNotification?: (memberId: string, method: string, params: unknown) => void;
|
|
134
|
-
/** Called when child process state changes. */
|
|
135
|
-
onStateChange?: (memberId: string, state: AgentProcessHandle["state"]) => void;
|
|
136
|
-
/** Called when child process exits. */
|
|
137
|
-
onExit?: (memberId: string, code: number | null, signal: string | null) => void;
|
|
138
|
-
/** Called when MCP bridge server proxies a tool call from an external agent. */
|
|
139
|
-
onMcpToolCall?: (memberId: string, tool: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
140
|
-
/**
|
|
141
|
-
* Called when an external agent requests permission (ACP session/request_permission). When set,
|
|
142
|
-
* it drives interactive approval (forward to user, await decision) instead of the auto-allow
|
|
143
|
-
* host-trust baseline; resolve with the chosen optionId.
|
|
144
|
-
*/
|
|
145
|
-
onPermissionRequest?: (memberId: string, params: Record<string, unknown>) => Promise<{
|
|
146
|
-
optionId: string;
|
|
147
|
-
}>;
|
|
148
|
-
/** Logger. */
|
|
149
|
-
log?: {
|
|
150
|
-
info(msg: string): void;
|
|
151
|
-
warn(msg: string): void;
|
|
152
|
-
debug?(msg: string): void;
|
|
153
|
-
};
|
|
154
|
-
/** Session directory for stderr logs. If set, ACP agent stderr is written to {sessionDir}/{agentId}.stderr.log. */
|
|
155
|
-
sessionDir?: string;
|
|
156
|
-
/** Test hook: redirect native third-party MCP config writes away from the real user home. */
|
|
157
|
-
nativeMcpHomeDir?: string;
|
|
158
|
-
}
|
|
159
|
-
export declare function ensureLoopbackNoProxy(env: Record<string, string>): Record<string, string>;
|
|
160
|
-
/**
|
|
161
|
-
* Merge an external descriptor's env onto the forwarded base env, then DELETE any `suppressEnvKeys`
|
|
162
|
-
* (account mode). This is the load-bearing half of the env-injection-override fix: `Object.assign` can
|
|
163
|
-
* only add/overwrite, so a whitelist-forwarded `ANTHROPIC_API_KEY`/`OPENAI_API_KEY` (from the gateway's
|
|
164
|
-
* own shell) would otherwise survive into the child and override the CLI's native subscription login.
|
|
165
|
-
* Deleting after the merge guarantees `account` mode hands credential control to the CLI's own store.
|
|
166
|
-
*/
|
|
167
|
-
export declare function applyExternalDescriptorEnv(env: Record<string, string>, ext: {
|
|
168
|
-
env?: Record<string, string>;
|
|
169
|
-
suppressEnvKeys?: string[];
|
|
170
|
-
}): Record<string, string>;
|
|
171
|
-
export declare function buildChildEnv(config: AgentProcessConfig): Record<string, string>;
|
|
172
|
-
/**
|
|
173
|
-
* Build LLM-related environment variables for an external ACP teammate.
|
|
174
|
-
*
|
|
175
|
-
* Priority chain:
|
|
176
|
-
* 1. Per-agent override (AgentConfig.apiKey / baseUrl)
|
|
177
|
-
* 2. Gateway proxy mode (all requests through shared gateway)
|
|
178
|
-
* 3. Inherit from qlogicagent's own env
|
|
179
|
-
*
|
|
180
|
-
* Handles the asymmetry between agents that support base URL override
|
|
181
|
-
* (can redirect to gateway) vs those that don't (only API key forwarding).
|
|
182
|
-
*/
|
|
183
|
-
export declare function buildLlmEnvForTeammate(agentId: string, agentConfig: AgentConfig | null, gatewayUrl: string | undefined): Record<string, string>;
|
|
184
|
-
/** Fault severity levels for ACP agent errors. */
|
|
185
|
-
export declare const ACP_FAULT_LEVEL: {
|
|
186
|
-
/** Unrecoverable — agent binary missing, permission denied, etc. */
|
|
187
|
-
readonly FATAL: "fatal";
|
|
188
|
-
/** Retriable — spawn timeout, handshake timeout, transient crash. */
|
|
189
|
-
readonly RETRIABLE: "retriable";
|
|
190
|
-
/** Warning — non-critical issue (e.g. degraded capabilities). */
|
|
191
|
-
readonly WARN: "warn";
|
|
192
|
-
};
|
|
193
|
-
export type AcpFaultLevel = (typeof ACP_FAULT_LEVEL)[keyof typeof ACP_FAULT_LEVEL];
|
|
194
|
-
export declare function sanitizeAgentLogFileName(memberId: string): string;
|
|
195
|
-
/**
|
|
196
|
-
* Manages a pool of child agent processes.
|
|
197
|
-
* Each child is a `qlogicagent` subprocess using JSON-RPC over stdio.
|
|
198
|
-
*/
|
|
199
|
-
export declare class AgentProcessManager {
|
|
200
|
-
private processes;
|
|
201
|
-
private callbacks;
|
|
202
|
-
private cliBinaryPath;
|
|
203
|
-
private mcpBridgeScriptPath;
|
|
204
|
-
private nativeMcpServerScriptPath;
|
|
205
|
-
constructor(callbacks?: AgentProcessCallbacks);
|
|
206
|
-
/** Format: [ISO] [level] [agent:id] [phase] message */
|
|
207
|
-
private slog;
|
|
208
|
-
/** Spawn a child agent process in the given cwd. */
|
|
209
|
-
spawn(config: AgentProcessConfig): Promise<AgentProcessHandle>;
|
|
210
|
-
/**
|
|
211
|
-
* Send a task to a child agent via ACP session/prompt.
|
|
212
|
-
* Returns the JSON-RPC result (content/usage carried on the response).
|
|
213
|
-
*/
|
|
214
|
-
sendTask(memberId: string, prompt: string, options?: {
|
|
215
|
-
sessionId?: string;
|
|
216
|
-
timeout?: number;
|
|
217
|
-
}): Promise<unknown>;
|
|
218
|
-
private buildExternalPromptDiagnostics;
|
|
219
|
-
/** Send a raw JSON-RPC request to a child. */
|
|
220
|
-
sendRpc(memberId: string, method: string, params?: unknown, timeoutMs?: number): Promise<unknown>;
|
|
221
|
-
/**
|
|
222
|
-
* Send a long-running task to a child agent with heartbeat keepalive.
|
|
223
|
-
*
|
|
224
|
-
* Unlike `sendTask()` (which blocks for up to 5 minutes), this method:
|
|
225
|
-
* 1. Dispatches the task via ACP `session/prompt`
|
|
226
|
-
* 2. Periodically sends `ping` RPCs to detect child liveness
|
|
227
|
-
* 3. Supports very long execution times (hours/days) for async work
|
|
228
|
-
* like video generation, batch processing, etc.
|
|
229
|
-
*
|
|
230
|
-
* The child is expected to emit `turn.delta` / `turn.progress`
|
|
231
|
-
* notifications during long work. If no response to ping within
|
|
232
|
-
* `pingTimeout`, the task is considered failed.
|
|
233
|
-
*/
|
|
234
|
-
sendTaskAsync(memberId: string, prompt: string, options?: {
|
|
235
|
-
sessionId?: string;
|
|
236
|
-
/** Total timeout for the task (default: unlimited, 0 = no timeout) */
|
|
237
|
-
timeout?: number;
|
|
238
|
-
/** Ping interval in ms (default: 60_000 = 1 minute) */
|
|
239
|
-
pingInterval?: number;
|
|
240
|
-
/** Ping response timeout in ms (default: 10_000) */
|
|
241
|
-
pingTimeout?: number;
|
|
242
|
-
}): Promise<unknown>;
|
|
243
|
-
/**
|
|
244
|
-
* Ping a child agent to check liveness.
|
|
245
|
-
*
|
|
246
|
-
* Q-2 protocol alignment:
|
|
247
|
-
* - Internal agents: JSON-RPC `ping` request (guaranteed to respond).
|
|
248
|
-
* - ACP agents: Send `notifications/ping` notification, then wait for
|
|
249
|
-
* `$/alive` notification back. Falls back to `sendRpc("ping")` if
|
|
250
|
-
* `$/alive` is not received (some ACP agents may support RPC ping).
|
|
251
|
-
*/
|
|
252
|
-
ping(memberId: string, timeoutMs?: number): Promise<boolean>;
|
|
253
|
-
/**
|
|
254
|
-
* Get the runtime status of a child agent process.
|
|
255
|
-
* Includes real-time media generation progress if available.
|
|
256
|
-
*/
|
|
257
|
-
getStatus(memberId: string): {
|
|
258
|
-
alive: boolean;
|
|
259
|
-
state: AgentProcessHandle["state"];
|
|
260
|
-
runningFor?: number;
|
|
261
|
-
resultText?: string;
|
|
262
|
-
error?: string;
|
|
263
|
-
/** Current media generation progress (from child's turn.media_progress). */
|
|
264
|
-
mediaProgress?: MediaProgressSnapshot;
|
|
265
|
-
/** Last tool the child invoked. */
|
|
266
|
-
lastToolCall?: string;
|
|
267
|
-
/** Seconds since last activity from child. */
|
|
268
|
-
idleFor?: number;
|
|
269
|
-
} | null;
|
|
270
|
-
/**
|
|
271
|
-
* Auto-capture structured progress from child notifications.
|
|
272
|
-
* This is the key mechanism that allows the parent to know:
|
|
273
|
-
* - Which provider task ID the child is polling (for video/3D/TTS)
|
|
274
|
-
* - Real progress percentage
|
|
275
|
-
* - What the child is currently doing (which tool, what delta text)
|
|
276
|
-
*/
|
|
277
|
-
/**
|
|
278
|
-
* Respond to a request the child agent makes to the parent (host) over ACP —
|
|
279
|
-
* e.g. session/request_permission. Sub-agents run autonomously under the parent,
|
|
280
|
-
* so tool-permission requests are auto-approved.
|
|
281
|
-
*/
|
|
282
|
-
private handleChildHostRequest;
|
|
283
|
-
private captureChildProgress;
|
|
284
|
-
/**
|
|
285
|
-
* Spawn an external ACP agent with retry logic.
|
|
286
|
-
* Retries up to MAX_SPAWN_RETRIES times with exponential backoff.
|
|
287
|
-
*/
|
|
288
|
-
private spawnAcpAgentWithRetry;
|
|
289
|
-
/**
|
|
290
|
-
* Spawn an external ACP agent process.
|
|
291
|
-
* Uses the ACP protocol adapter for lifecycle management.
|
|
292
|
-
*/
|
|
293
|
-
private spawnAcpAgent;
|
|
294
|
-
/**
|
|
295
|
-
* Surface a recorded session/set_model failure: the session is alive but runs the agent's
|
|
296
|
-
* DEFAULT model instead of the managed/platform one (wrong vendor/billing/capability). Same
|
|
297
|
-
* agents.error channel as the other spawn/restart failures.
|
|
298
|
-
*/
|
|
299
|
-
private reportModelMismatch;
|
|
300
|
-
private syncNativeMcpConfig;
|
|
301
|
-
/** Kill a specific child agent process. */
|
|
302
|
-
kill(memberId: string): void;
|
|
303
|
-
/** Kill all child processes and clean up. */
|
|
304
|
-
killAll(): void;
|
|
305
|
-
/** Get the handle for a specific member. */
|
|
306
|
-
getHandle(memberId: string): AgentProcessHandle | undefined;
|
|
307
|
-
/** Get all handles. */
|
|
308
|
-
getAllHandles(): AgentProcessHandle[];
|
|
309
|
-
/** Whether a member's process is still spawned and usable (for pool reuse across turns). */
|
|
310
|
-
isAlive(memberId: string): boolean;
|
|
311
|
-
/** Get usage tracker for an ACP agent (returns null for internal agents). */
|
|
312
|
-
getUsageTracker(memberId: string): AcpUsageTracker | null;
|
|
313
|
-
/**
|
|
314
|
-
* The agent-assigned native session id (from ACP session/new or session/load) for a pooled member,
|
|
315
|
-
* once its session exists — undefined before creation. For native-cwd agents (codex/claude) this is
|
|
316
|
-
* the id under which the agent persists its OWN transcript (e.g. claude's ~/.claude uuid), distinct
|
|
317
|
-
* from the engine/stream id; used to converge on a single session identity (own/native unification).
|
|
318
|
-
*/
|
|
319
|
-
getNativeSessionId(memberId: string): string | undefined;
|
|
320
|
-
/**
|
|
321
|
-
* Feed token usage into the tracker from a child notification (Tier 1). Handles all three shapes a
|
|
322
|
-
* child may use so the tracker is actually populated:
|
|
323
|
-
* - a top-level `usage_update` method (legacy/non-standard),
|
|
324
|
-
* - standard ACP `session/update` with `sessionUpdate:"usage_update"` (fields on the update),
|
|
325
|
-
* - the self-hosted qlogicagent's relay: `session/update` → `sessionUpdate:"x_relay"` carrying
|
|
326
|
-
* `method:"turn.usage_update"` with `params.usage` (a TokenUsage object).
|
|
327
|
-
* Without the x_relay branch the self-agent's usage was never captured → Solo columns showed ↓0 ↑0.
|
|
328
|
-
*/
|
|
329
|
-
private feedUsageFromNotification;
|
|
330
|
-
/**
|
|
331
|
-
* Create a named-pipe IPC server for MCP bridge tool-call proxying.
|
|
332
|
-
* External agents' MCP bridge servers connect here to proxy tool calls
|
|
333
|
-
* back to qlogicagent.
|
|
334
|
-
*/
|
|
335
|
-
private createMcpIpcServer;
|
|
336
|
-
/** Handle a single JSON-RPC message from the MCP bridge IPC connection. */
|
|
337
|
-
private handleMcpIpcMessage;
|
|
338
|
-
/**
|
|
339
|
-
* Attempt to restart a crashed ACP agent.
|
|
340
|
-
* Re-spawns the child process prepping the same config and env,
|
|
341
|
-
* then re-runs ACP handshake.
|
|
342
|
-
*/
|
|
343
|
-
private attemptRuntimeRestart;
|
|
344
|
-
/** Get IPC pipe path for a member's MCP bridge. */
|
|
345
|
-
getMcpIpcPath(memberId: string): string | undefined;
|
|
346
|
-
private heartbeatTimers;
|
|
347
|
-
private missedBeats;
|
|
348
|
-
/** Heartbeat interval (ms). */
|
|
349
|
-
private static readonly HEARTBEAT_INTERVAL;
|
|
350
|
-
/** Number of missed heartbeats before force-kill. */
|
|
351
|
-
private static readonly MAX_MISSED_BEATS;
|
|
352
|
-
/**
|
|
353
|
-
* Start heartbeat monitoring for a running agent.
|
|
354
|
-
* Sends periodic ping RPCs; after MAX_MISSED_BEATS consecutive failures,
|
|
355
|
-
* the agent is force-killed and marked as "hang".
|
|
356
|
-
*/
|
|
357
|
-
startHeartbeat(memberId: string, onHang?: (memberId: string) => void): void;
|
|
358
|
-
/** Stop heartbeat monitoring for an agent. */
|
|
359
|
-
stopHeartbeat(memberId: string): void;
|
|
360
|
-
/** Get missed heartbeat count for an agent. */
|
|
361
|
-
getMissedBeats(memberId: string): number;
|
|
362
|
-
/** Get count of active (non-terminal) processes. */
|
|
363
|
-
activeCount(): number;
|
|
364
|
-
/** Remove a terminated process from tracking. */
|
|
365
|
-
remove(memberId: string): void;
|
|
366
|
-
/** Clean up all processes. */
|
|
367
|
-
dispose(): void;
|
|
368
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* External-agent process pool (A).
|
|
3
|
-
*
|
|
4
|
-
* Keeps spawned external ACP agents (Codex/Claude/etc.) alive and reuses them across chat turns,
|
|
5
|
-
* instead of the spawn → one turn → kill cycle that paid a full ACP cold-start (several seconds)
|
|
6
|
-
* on every message. Reuse also gives external agents real multi-turn memory (same ACP session).
|
|
7
|
-
*
|
|
8
|
-
* Design (mirrors how VSCode keeps language-server-style agent CLIs resident):
|
|
9
|
-
* - One AgentProcessManager + one spawned member per pool key (agentId + cwd + sessionId).
|
|
10
|
-
* - The first turn spawns + registers; subsequent turns reuse the live member (sendTask only).
|
|
11
|
-
* - A mutable `holder.current` carries the *current* turn's identity so the manager's
|
|
12
|
-
* construction-time onNotification can tag live deltas with the right turn (see agents-handler).
|
|
13
|
-
* - Idle entries are reaped after IDLE_TTL_MS; the pool is bounded to MAX_POOL by LRU eviction.
|
|
14
|
-
* - Busy entries (a turn in flight) are never evicted.
|
|
15
|
-
*/
|
|
16
|
-
import type { AgentProcessManager } from "./agent-process.js";
|
|
17
|
-
/** Mutable per-turn context read by the pooled manager's onNotification callback. */
|
|
18
|
-
export interface PooledTurnCtx {
|
|
19
|
-
sessionId?: string;
|
|
20
|
-
turnId?: string;
|
|
21
|
-
requestId?: string;
|
|
22
|
-
deltas: string[];
|
|
23
|
-
streamedAny: boolean;
|
|
24
|
-
}
|
|
25
|
-
export interface PooledAgentEntry {
|
|
26
|
-
manager: AgentProcessManager;
|
|
27
|
-
memberId: string;
|
|
28
|
-
/** Boxed so the manager's onNotification (built before registration) can read the live turn. */
|
|
29
|
-
holder: {
|
|
30
|
-
current: PooledTurnCtx | null;
|
|
31
|
-
};
|
|
32
|
-
lastUsed: number;
|
|
33
|
-
/**
|
|
34
|
-
* Set when a credential-mode change (authPreference / key / login) arrived while this process was
|
|
35
|
-
* mid-turn. The env is baked at spawn, so the switch can only take effect by respawning — but we must
|
|
36
|
-
* not abort the in-flight turn (D2: "下条消息生效"). The turn-runner evicts the entry once the turn
|
|
37
|
-
* settles (settlePooledTurn), so the NEXT turn respawns with the new credentials.
|
|
38
|
-
*/
|
|
39
|
-
pendingRecredential?: boolean;
|
|
40
|
-
}
|
|
41
|
-
/** Pool key: same agent + workspace + session ⇒ same resident process (and shared memory). */
|
|
42
|
-
export declare function poolKey(agentId: string, cwd: string, sessionId?: string): string;
|
|
43
|
-
/** Return a live pooled entry for the key, or undefined (evicting a dead one if found). */
|
|
44
|
-
export declare function getAlivePooledAgent(key: string): PooledAgentEntry | undefined;
|
|
45
|
-
/** Register a freshly-spawned entry, evicting any stale same-key entry and enforcing MAX_POOL. */
|
|
46
|
-
export declare function registerPooledAgent(key: string, entry: PooledAgentEntry): void;
|
|
47
|
-
/**
|
|
48
|
-
* Move a live pooled entry from one key to another without disposing it — the same ACP process keeps
|
|
49
|
-
* running, only its pool key changes. Disposes any stale occupant of the destination key. Returns the
|
|
50
|
-
* moved entry, or undefined if `fromKey` has no live entry (a dead one is reaped). No-op returning the
|
|
51
|
-
* existing entry when the keys are equal.
|
|
52
|
-
*
|
|
53
|
-
* Merge note (session-identity-alignment): the second caller this was extracted for — the transient→native
|
|
54
|
-
* X→Y re-key after a native agent reported its own id — is GONE. Under canonical-id-stable, the frontend
|
|
55
|
-
* never converges to Y, so the pool key never changes mid-conversation; the sole caller is adoptWarmedAgent
|
|
56
|
-
* (warm → real session key). Kept as the general re-key primitive.
|
|
57
|
-
*/
|
|
58
|
-
export declare function rekeyPooledAgent(fromKey: string, toKey: string): PooledAgentEntry | undefined;
|
|
59
|
-
/**
|
|
60
|
-
* Re-key a pre-warmed entry (spawned before a session existed, under WARM_SESSION) onto the real
|
|
61
|
-
* session key, so the first turn adopts the warmed process and skips the cold start. Does not
|
|
62
|
-
* dispose — the same live process is moved. Returns undefined if no live warmed entry exists.
|
|
63
|
-
*/
|
|
64
|
-
export declare function adoptWarmedAgent(warmKey: string, sessionKey: string): PooledAgentEntry | undefined;
|
|
65
|
-
/** Reserved session token for a process pre-warmed before its real session id is known. */
|
|
66
|
-
export declare const WARM_SESSION = "__warm__";
|
|
67
|
-
/** Drop + dispose a single entry (e.g. after a turn errors and the process is suspect). */
|
|
68
|
-
export declare function evictPooledAgent(key: string): void;
|
|
69
|
-
/**
|
|
70
|
-
* Invalidate every resident process for an agent after a credential-mode change (authPreference / key /
|
|
71
|
-
* login). The spawn env is baked at spawn time and reused across turns, so a switch only takes effect by
|
|
72
|
-
* respawning. Idle/warm entries are evicted immediately; a busy entry (turn in flight) is flagged
|
|
73
|
-
* `pendingRecredential` and evicted by settlePooledTurn when its turn settles (D2: never abort the
|
|
74
|
-
* in-flight turn — the switch lands on the next message). Returns counts for UI messaging.
|
|
75
|
-
*/
|
|
76
|
-
export declare function evictPooledAgentsByAgentId(agentId: string): {
|
|
77
|
-
evicted: number;
|
|
78
|
-
deferred: number;
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* Call when a pooled turn settles (success or error). If a credential change arrived mid-turn
|
|
82
|
-
* (pendingRecredential), evict now so the next turn respawns with the new credentials.
|
|
83
|
-
*/
|
|
84
|
-
export declare function settlePooledTurn(key: string): void;
|
|
85
|
-
/** Kill + dispose every pooled agent and stop the reaper. Call on agent shutdown. */
|
|
86
|
-
export declare function disposeAllPooledAgents(): void;
|
|
87
|
-
export declare function pooledAgentCount(): number;
|
|
88
|
-
/** Reap idle (non-busy) entries past the TTL. Exposed for deterministic testing. */
|
|
89
|
-
export declare function reapIdlePooledAgents(now: number): void;
|