qlogicagent 2.18.12 → 2.19.2
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 +382 -382
- package/dist/agent-contract.js +1 -0
- package/dist/cli.js +1 -1
- package/dist/default-project-knowledge/INSTRUCTIONS.md +7 -7
- package/dist/default-project-knowledge/rules/project-workflow.md +6 -6
- package/dist/host-contract.js +1 -1
- package/dist/host-session-collection-contract.js +1 -0
- package/dist/index.js +478 -505
- package/dist/pet-host.js +8 -8
- package/dist/project-memory-host.js +23 -23
- package/dist/protocol.js +1 -1
- package/dist/skills/builtin/desktop-screenshot/SKILL.md +62 -62
- package/dist/skills/builtin/office-doc-reading/SKILL.md +19 -19
- package/dist/types/cli/acp-commands.d.ts +1 -1
- package/dist/types/cli/acp-extended-handlers.d.ts +8 -8
- package/dist/types/cli/acp-extended-host-adapter.d.ts +0 -11
- package/dist/types/cli/acp-session-host.d.ts +2 -0
- package/dist/types/cli/core-tool-coordinator.d.ts +0 -9
- package/dist/types/cli/default-project-bootstrap.d.ts +2 -32
- package/dist/types/cli/handlers/session-handler.d.ts +0 -43
- package/dist/types/cli/handlers/solo-handler.d.ts +3 -14
- package/dist/types/cli/multi-agent-handler-host.d.ts +3 -16
- package/dist/types/cli/product-coordinator.d.ts +3 -14
- package/dist/types/cli/rpc-registry.d.ts +0 -2
- package/dist/types/cli/stdio-rpc-handler-hosts.d.ts +4 -1
- package/dist/types/cli/stdio-server.d.ts +1 -2
- package/dist/types/host-contract/index.d.ts +112 -19
- package/dist/types/host-session-collection-contract.d.ts +61 -0
- package/dist/types/orchestration/agent-instance.d.ts +11 -14
- package/dist/types/orchestration/agent-roster.d.ts +8 -4
- package/dist/types/orchestration/delegate-bridge.d.ts +8 -0
- package/dist/types/orchestration/goal-mode-adapters.d.ts +3 -3
- package/dist/types/orchestration/product-persistence.d.ts +0 -4
- package/dist/types/orchestration/product-planner.d.ts +4 -6
- package/dist/types/orchestration/solo-evaluator.d.ts +2 -5
- package/dist/types/orchestration/testing/delegate-test-bridge.d.ts +2 -1
- package/dist/types/orchestration/testing/host-agent-provider-directory-fixture.d.ts +7 -0
- package/dist/types/orchestration/workflow/qla-executor-host.d.ts +1 -1
- package/dist/types/protocol/agent-contract.d.ts +50 -0
- package/dist/types/protocol/methods.d.ts +20 -38
- package/dist/types/protocol/notifications.d.ts +1 -1
- package/dist/types/protocol/wire/acp-agent-management.d.ts +2 -190
- package/dist/types/protocol/wire/acp-protocol.d.ts +3 -4
- package/dist/types/protocol/wire/agent-events.d.ts +1 -32
- package/dist/types/protocol/wire/agent-methods.d.ts +1 -243
- package/dist/types/protocol/wire/gateway-rpc.d.ts +343 -15
- package/dist/types/protocol/wire/index.d.ts +3 -3
- package/dist/types/protocol/wire/notification-payloads.d.ts +103 -126
- package/dist/types/runtime/infra/host-agent-provider-directory.d.ts +17 -0
- package/dist/types/runtime/infra/project-authority-facade.d.ts +1 -1
- package/dist/types/runtime/infra/project-data-paths.d.ts +2 -1
- package/dist/types/runtime/infra/project-host-authority.d.ts +3 -2
- package/dist/types/runtime/infra/project-store.d.ts +4 -39
- package/dist/types/runtime/session/session-catalog.d.ts +0 -12
- package/dist/types/runtime/session/session-persistence.d.ts +1 -1
- package/dist/types/runtime/session/session-resource-key.d.ts +1 -1
- package/dist/types/runtime/session/session-types.d.ts +0 -23
- package/dist/types/transport/acp-server.d.ts +2 -10
- package/dist/vendor/hatch-pet/LICENSE.txt +201 -201
- package/dist/vendor/hatch-pet/NOTICE.md +25 -25
- package/dist/vendor/hatch-pet/references/animation-rows.md +29 -29
- package/dist/vendor/hatch-pet/references/codex-pet-contract.md +35 -35
- package/dist/vendor/hatch-pet/references/qa-rubric.md +66 -66
- package/dist/vendor/hatch-pet/scripts/compose_atlas.py +169 -169
- package/dist/vendor/hatch-pet/scripts/derive_running_left_from_running_right.py +150 -150
- package/dist/vendor/hatch-pet/scripts/extract_strip_frames.py +408 -408
- package/dist/vendor/hatch-pet/scripts/inspect_frames.py +256 -256
- package/dist/vendor/hatch-pet/scripts/make_contact_sheet.py +96 -96
- package/dist/vendor/hatch-pet/scripts/prepare_pet_run.py +834 -834
- package/dist/vendor/hatch-pet/scripts/render_animation_previews.py +78 -78
- package/dist/vendor/hatch-pet/scripts/validate_atlas.py +157 -157
- package/dist/workflow-host.js +10 -10
- package/package.json +16 -1
- package/dist/types/cli/agent-config-coordinator.d.ts +0 -27
- package/dist/types/cli/agent-config-runtime.d.ts +0 -11
- package/dist/types/cli/agent-status-notifier.d.ts +0 -11
- package/dist/types/cli/handlers/agents-handler.d.ts +0 -121
- package/dist/types/cli/handlers/project-handler.d.ts +0 -36
- package/dist/types/cli/project-command-service.d.ts +0 -28
- package/dist/types/orchestration/delegation-coordinator.d.ts +0 -100
- package/dist/types/runtime/infra/acp-detector.d.ts +0 -271
- package/dist/types/runtime/infra/agent-config-store.d.ts +0 -30
- package/dist/types/runtime/infra/agent-install-runner.d.ts +0 -80
- package/dist/types/runtime/infra/external-agent-approvals.d.ts +0 -59
- package/dist/types/runtime/infra/migrate-device-scope.d.ts +0 -49
- package/dist/types/runtime/infra/project-data-gc.d.ts +0 -15
- package/dist/types/runtime/session/native/claude-session-source.d.ts +0 -23
- package/dist/types/runtime/session/native/codex-index.d.ts +0 -21
- package/dist/types/runtime/session/native/codex-session-source.d.ts +0 -31
- package/dist/types/runtime/session/native/cwd-normalize.d.ts +0 -53
- package/dist/types/runtime/session/native/ephemeral-rollout-sweep.d.ts +0 -13
- package/dist/types/runtime/session/native/native-cwd-agents.d.ts +0 -17
- package/dist/types/runtime/session/native/native-session-source.d.ts +0 -89
- package/dist/types/runtime/session/native/native-title.d.ts +0 -1
- package/dist/types/runtime/session/native/register-builtin-sources.d.ts +0 -1
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ACP Agent Detector — scans PATH for installed ACP-compatible CLI agents.
|
|
3
|
-
*
|
|
4
|
-
* Uses `which` (Unix) / `where` (Windows) to locate CLI binaries,
|
|
5
|
-
* then optionally probes version. Results are cached with TTL.
|
|
6
|
-
*
|
|
7
|
-
* Reference: AionUI AcpDetector + ACP_BACKENDS_ALL registry.
|
|
8
|
-
*/
|
|
9
|
-
import type { AcpBackendConfig, AgentDescriptor, CustomAgentDef, AgentConfigStoreData, AuthPreference } from "../../protocol/wire/acp-agent-management.js";
|
|
10
|
-
export declare const ACP_BACKENDS: Record<string, AcpBackendConfig>;
|
|
11
|
-
export declare const AGENT_CATALOG_IDS: readonly ["claude", "codex", "gemini", "copilot", "cursor", "qwen", "kimi", "glm", "opencode", "kiro", "qoder", "openclaw", "hermes"];
|
|
12
|
-
/** Merged catalog entry (base ACP config + grid/install metadata) for one id. */
|
|
13
|
-
export declare function getCatalogEntry(id: string): AcpBackendConfig | undefined;
|
|
14
|
-
/** Ordered curated catalog: base ACP config merged with grid/install metadata. */
|
|
15
|
-
export declare function getAgentCatalog(): AcpBackendConfig[];
|
|
16
|
-
export declare function buildInternalAgentDescriptors(): AgentDescriptor[];
|
|
17
|
-
export declare function resolveWindowsCopilotLoader(): string | null;
|
|
18
|
-
export declare function getNpmInstallPackageName(command: string | undefined): string | null;
|
|
19
|
-
export declare function compareSemverVersions(a: string, b: string): number;
|
|
20
|
-
export declare function isVersionNewer(latest: string | null | undefined, current: string | null | undefined): boolean;
|
|
21
|
-
export declare function readGlobalNpmPackageVersion(packageName: string | null | undefined): string | null;
|
|
22
|
-
export declare function resolveInstalledNpmPackageVersionFromInstall(install: AcpBackendConfig["install"] | undefined): string | null;
|
|
23
|
-
export declare function getCatalogInstalledVersion(entry: AcpBackendConfig, detectedVersion?: string): string | undefined;
|
|
24
|
-
/** Resolve a package's latest published version via `npm view` (async + cached). Used by the background
|
|
25
|
-
* update check so N agents resolve concurrently (one `npm view` each) instead of blocking sequentially. */
|
|
26
|
-
export declare function fetchNpmLatestPackageVersionAsync(packageName: string | null | undefined, registry?: string): Promise<string | null>;
|
|
27
|
-
export interface CatalogUpdateInfo {
|
|
28
|
-
id: string;
|
|
29
|
-
packageName?: string;
|
|
30
|
-
installedVersion?: string;
|
|
31
|
-
latestVersion?: string;
|
|
32
|
-
updateAvailable: boolean;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Resolve latest-version / update-available info for the catalog's INSTALLED agents, all in PARALLEL
|
|
36
|
-
* (one concurrent `npm view` per package). Non-installed agents are skipped (nothing to update).
|
|
37
|
-
* Returns only entries where a latest version was resolved. Safe to call off the catalog hot path.
|
|
38
|
-
*/
|
|
39
|
-
export declare function getCatalogUpdateInfoAsync(entries: ReadonlyArray<{
|
|
40
|
-
id: string;
|
|
41
|
-
entry: AcpBackendConfig;
|
|
42
|
-
detectedVersion?: string;
|
|
43
|
-
}>, registry?: string): Promise<CatalogUpdateInfo[]>;
|
|
44
|
-
/**
|
|
45
|
-
* Synchronous, NETWORK-FREE update info read straight from the persisted cache (disk-seeded on first
|
|
46
|
-
* use). Returns immediately so the panel lights up last-known badges INSTANTLY — VS Code's gallery
|
|
47
|
-
* pattern — without waiting on `npm view`. `stale` is true when any installed package's cached "latest"
|
|
48
|
-
* is missing, errored, or older than the TTL; the caller then refreshes via getCatalogUpdateInfoAsync
|
|
49
|
-
* in the background, and the next call serves the fresh value.
|
|
50
|
-
*/
|
|
51
|
-
export declare function getCatalogUpdateInfoCached(entries: ReadonlyArray<{
|
|
52
|
-
id: string;
|
|
53
|
-
entry: AcpBackendConfig;
|
|
54
|
-
detectedVersion?: string;
|
|
55
|
-
}>, registry?: string): {
|
|
56
|
-
updates: CatalogUpdateInfo[];
|
|
57
|
-
stale: boolean;
|
|
58
|
-
};
|
|
59
|
-
export declare function normalizeWindowsAcpCommand(cliPath: string, args: string[]): {
|
|
60
|
-
cliPath: string;
|
|
61
|
-
acpArgs: string[];
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* Build the spawn env for an external ACP backend.
|
|
65
|
-
*
|
|
66
|
-
* Maps the agent-config's portable `apiKey`/`baseUrl` onto the backend-declared
|
|
67
|
-
* environment-variable names (`apiKeyEnvVar`/`baseUrlEnvVar`) so a user who only
|
|
68
|
-
* configures an API key + base URL (e.g. via agents.setConfig) actually drives the
|
|
69
|
-
* underlying CLI with a third-party OpenAI/Anthropic-compatible gateway — no official
|
|
70
|
-
* account login required. Without this mapping the backends declared the env-var names
|
|
71
|
-
* but nothing ever populated them.
|
|
72
|
-
*
|
|
73
|
-
* Precedence (lowest → highest), so explicit user input always wins:
|
|
74
|
-
* 1. backend.env (static backend defaults)
|
|
75
|
-
* 2. mapped apiKey/baseUrl (config.apiKey → backend.apiKeyEnvVar, etc.)
|
|
76
|
-
* 3. customConfig.env (raw env the user hand-entered)
|
|
77
|
-
*
|
|
78
|
-
* Injection is conditional: the apiKey/baseUrl mapping only fires when the backend
|
|
79
|
-
* actually declares the corresponding envVar name (so we never invent a var the CLI
|
|
80
|
-
* does not read). Returns undefined when there is nothing to inject, preserving the
|
|
81
|
-
* prior `env?: undefined` behavior for un-configured backends.
|
|
82
|
-
*/
|
|
83
|
-
export declare function buildBackendEnv(backend: AcpBackendConfig | undefined, customConfig: import("../../protocol/wire/acp-agent-management.js").AgentConfig | undefined, autoEnv?: Record<string, string>): Record<string, string> | undefined;
|
|
84
|
-
/** Unified key sources for login-free catalog injection (wired by the runtime). */
|
|
85
|
-
export interface CatalogKeySources {
|
|
86
|
-
/** Gateway-issued inference key (sk-qllm) for keySource:"llmrouter". */
|
|
87
|
-
llmrouterKey?: string;
|
|
88
|
-
/** Base URL an llmrouter-routed agent should call (our gateway endpoint). */
|
|
89
|
-
llmrouterBaseUrl?: string;
|
|
90
|
-
/** Resolve an agent/protocol-specific LLMRouter base URL. */
|
|
91
|
-
getLlmrouterBaseUrl?: (agentId: string, entry: AcpBackendConfig) => string | null | undefined;
|
|
92
|
-
/** Default LLMRouter model for agent CLIs that require an explicit model pin. */
|
|
93
|
-
llmrouterModel?: string;
|
|
94
|
-
/** Resolve a provider's direct third-party key for keySource:"direct". */
|
|
95
|
-
getDirectKey?: (providerId: string) => string | null | undefined;
|
|
96
|
-
/** The host's active text-generation model (deepseek / volcengine / …) to "pass through" to
|
|
97
|
-
* OpenAI-compatible spawned agents (codex/qwen/opencode) that resolve no key of their own — so
|
|
98
|
-
* they run on the configured key+baseUrl+model with zero per-agent credentials. */
|
|
99
|
-
passthroughModel?: {
|
|
100
|
-
apiKey: string;
|
|
101
|
-
baseUrl?: string;
|
|
102
|
-
model?: string;
|
|
103
|
-
};
|
|
104
|
-
/** Probe: does this agent have a usable native account/subscription login (e.g. ~/.codex/auth.json,
|
|
105
|
-
* present + not expired)? Drives `account`-mode readiness and `auto`'s account-first preference.
|
|
106
|
-
* Tri-state: true = detected login, false = probeable but not logged in (blocks readiness), undefined
|
|
107
|
-
* = no probe for this agent (treated as ready-if-installed; auto does NOT pick account). Wired in Cut 4. */
|
|
108
|
-
hasSubscription?: (agentId: string) => boolean | undefined;
|
|
109
|
-
}
|
|
110
|
-
/** Resolve the effective mode, coercing unsupported combinations (claude.account → auto). */
|
|
111
|
-
export declare function effectiveAuthPreference(entry: AcpBackendConfig, mode: AuthPreference): AuthPreference;
|
|
112
|
-
/**
|
|
113
|
-
* The credential-source modes the UI should offer for an agent (derived from catalog metadata, the
|
|
114
|
-
* single source of truth — spec §4.2/§8.2/§15). Never includes a permanently-dead option:
|
|
115
|
-
* - oauth / keyless (copilot/cursor/kimi/…): ["account"] only (no gateway endpoint to repoint)
|
|
116
|
-
* - claude (Anthropic bans subscription): ["managed","userKey"] — no account
|
|
117
|
-
* - codex (llmrouter + account-capable): ["account","userKey","managed"]
|
|
118
|
-
* - other llmrouter agents: ["userKey","managed"]
|
|
119
|
-
* - direct agents (qwen/glm/…): ["userKey"] (managed wiring for qwen/opencode is Cut 7)
|
|
120
|
-
*/
|
|
121
|
-
export declare function getAvailableAuthModes(entry: AcpBackendConfig): AuthPreference[];
|
|
122
|
-
/**
|
|
123
|
-
* Resolve the login-free key env for a catalog agent, honoring the per-agent `authPreference`.
|
|
124
|
-
* - "account" → {} (inject nothing; the spawn layer also deletes the forwarded key, see resolveSuppressEnvKeys)
|
|
125
|
-
* - "userKey" → the user's own provider key against the official endpoint (no gateway baseUrl/model)
|
|
126
|
-
* - "managed" → force the gateway sk-qllm + baseUrl (ignores any user key) — guarantees a first conversation
|
|
127
|
-
* - "auto" → ladder: user's own key (if present) → managed gateway → host-model passthrough
|
|
128
|
-
* oauth / keyless agents never get a key injected. Only emits env vars the backend declares.
|
|
129
|
-
*/
|
|
130
|
-
export declare function resolveCatalogKeyEnv(entry: AcpBackendConfig | undefined, sources: CatalogKeySources, mode?: AuthPreference): Record<string, string>;
|
|
131
|
-
/**
|
|
132
|
-
* Env var names the spawn layer must DELETE from the merged child env (account mode), so a
|
|
133
|
-
* forwarded/stale shell key cannot override the CLI's own native login. This is the load-bearing
|
|
134
|
-
* half of the §1.3 override-bug fix: buildBackendEnv alone cannot unset a whitelist-forwarded key.
|
|
135
|
-
* Returns [] when not in account mode (or the agent has no account path — claude is coerced to auto).
|
|
136
|
-
*/
|
|
137
|
-
export declare function resolveSuppressEnvKeys(entry: AcpBackendConfig | undefined, mode: AuthPreference, sources?: CatalogKeySources): string[];
|
|
138
|
-
/**
|
|
139
|
-
* Build a backend's descriptor from already-resolved cliPath/version (+ the caller-resolved
|
|
140
|
-
* hasConfig flag). Shared by AcpDetector's sync and async detection paths so they can never drift
|
|
141
|
-
* (status rules, copilot's version-required gate, etc.) — extracted to a standalone, IO-free, pure
|
|
142
|
-
* function (not a class method) so it is directly unit-testable without spawning a real CLI.
|
|
143
|
-
*
|
|
144
|
-
* sessionHistory (Task 1.2, third-party native session discovery): "native-cwd" only for an
|
|
145
|
-
* INSTALLED (status "available") codex or claude backend — the two agents whose native CWD-scoped
|
|
146
|
-
* session stores we've actually adapted to. Every other case — not-installed codex/claude, any other
|
|
147
|
-
* backend regardless of install state — falls back to "own". Unadapted agents ALWAYS get "own"; this
|
|
148
|
-
* is a hard invariant, not a default that later widens implicitly.
|
|
149
|
-
*/
|
|
150
|
-
export declare function assembleBackendDescriptor(backend: AcpBackendConfig, cliPath: string | null, version: string | null, hasConfig: boolean): AgentDescriptor;
|
|
151
|
-
/** Build a user-registered custom agent's descriptor. Extracted to a standalone, IO-free, pure
|
|
152
|
-
* function for the same testability reason as {@link assembleBackendDescriptor}. Custom agents are
|
|
153
|
-
* never adapted for native session discovery — regardless of what id/name the user gives them —
|
|
154
|
-
* so sessionHistory is always "own" (the hard own-by-default invariant). */
|
|
155
|
-
export declare function assembleCustomAgentDescriptor(custom: CustomAgentDef, cliPath: string | null, hasConfig: boolean): AgentDescriptor;
|
|
156
|
-
export declare class AcpDetector {
|
|
157
|
-
private cache;
|
|
158
|
-
/** Last scan that COMPLETED, surviving clearCache() and failed rescans. list() prefers this
|
|
159
|
-
* over an empty [] so a transient probe failure never reads as "no agents installed". */
|
|
160
|
-
private lastGoodScan;
|
|
161
|
-
private configStore;
|
|
162
|
-
private keySources;
|
|
163
|
-
/** Shared in-flight async scan so concurrent scanAsync() callers (startup warm + a racing RPC)
|
|
164
|
-
* collapse onto ONE scan instead of each spawning its own probe storm. Cleared when it settles. */
|
|
165
|
-
private scanInFlight;
|
|
166
|
-
/**
|
|
167
|
-
* Provide the config store data so detector can populate `hasConfig` field
|
|
168
|
-
* and include user-registered custom agents.
|
|
169
|
-
*/
|
|
170
|
-
setConfigStore(data: AgentConfigStoreData): void;
|
|
171
|
-
/** Wire the unified key sources for login-free catalog injection. */
|
|
172
|
-
setKeySources(sources: CatalogKeySources): void;
|
|
173
|
-
/**
|
|
174
|
-
* Scan for installed ACP agent CLIs.
|
|
175
|
-
* @param force - Clear cache and re-scan.
|
|
176
|
-
*/
|
|
177
|
-
scan(force?: boolean): AgentDescriptor[];
|
|
178
|
-
/**
|
|
179
|
-
* Async, NON-BLOCKING twin of {@link scan}. Probes every backend CONCURRENTLY off the event loop
|
|
180
|
-
* (async `where`/`which` + version probes), so the engine's single-threaded loop keeps servicing
|
|
181
|
-
* ACP requests while detection runs — fixing the bug where a cold synchronous scan (11–18s here,
|
|
182
|
-
* 60s+ with more/slower CLIs) starved an already-dispatched `x/product.confirm` until it tripped
|
|
183
|
-
* the UI's 60s timeout. Populates the SAME cache as scan(), so a later sync list()/scan(false)
|
|
184
|
-
* returns instantly. Concurrent callers share one in-flight scan ({@link scanInFlight}).
|
|
185
|
-
*
|
|
186
|
-
* @param force - Bypass the fresh-cache short-circuit and re-probe.
|
|
187
|
-
*/
|
|
188
|
-
scanAsync(force?: boolean): Promise<AgentDescriptor[]>;
|
|
189
|
-
private runScanAsync;
|
|
190
|
-
/**
|
|
191
|
-
* Return cached results without IO. 冷缓存时后台预热(scanAsync)并返回 [],
|
|
192
|
-
* 绝不在 RPC 路径上同步 scan —— 同步探测(11-18s+)会饿死单线程引擎循环
|
|
193
|
-
* (x/product.confirm 60s 超时的根因)。调用方按"稍后再查"处理空列表。
|
|
194
|
-
*
|
|
195
|
-
* A background-scan failure is reported (console.error), never swallowed: a swallowed
|
|
196
|
-
* failure made list() return [] forever and downstream (product planning) treated
|
|
197
|
-
* "scan failed" as "no agents installed". When the fresh cache is gone but an older
|
|
198
|
-
* scan succeeded, that stale-but-real result is returned instead of [].
|
|
199
|
-
*/
|
|
200
|
-
list(): AgentDescriptor[];
|
|
201
|
-
/** Clear the detection cache. */
|
|
202
|
-
clearCache(): void;
|
|
203
|
-
private detectBackend;
|
|
204
|
-
/** Async, NON-BLOCKING twin of {@link detectBackend} — identical detection, async probes. */
|
|
205
|
-
private detectBackendAsync;
|
|
206
|
-
private detectCustomAgent;
|
|
207
|
-
/** Async, NON-BLOCKING twin of {@link detectCustomAgent}. */
|
|
208
|
-
private detectCustomAgentAsync;
|
|
209
|
-
private hasAgentConfig;
|
|
210
|
-
/**
|
|
211
|
-
* Descriptor for qlogicagent participating in Solo/Product as a self-hosted ACP agent.
|
|
212
|
-
*
|
|
213
|
-
* qlogicagent's own CLI speaks ACP by default (cli/main.ts: ACP server unless --no-acp), so a
|
|
214
|
-
* participant is just another `node <cli.js>` process. The child reads the SAME owner-profile
|
|
215
|
-
* settings.json (model-registry), so it runs with the configured provider (deepseek / volcengine /
|
|
216
|
-
* llmrouter) — that is how the configured model "passes through" to every qlogicagent instance,
|
|
217
|
-
* with no per-agent key. We forward the owner-profile + llmrouter env so the child resolves its
|
|
218
|
-
* model identically to this (host) process. This lets Solo run N independent qlogicagent sessions
|
|
219
|
-
* in parallel (each its own worktree) — the core "多个 qlogicagent = 多会话并行" use case.
|
|
220
|
-
*/
|
|
221
|
-
private buildSelfDescriptor;
|
|
222
|
-
/**
|
|
223
|
-
* Build an ExternalAgentDescriptor suitable for Gateway Supervisor resolution.
|
|
224
|
-
* Returns null if the agent is not available.
|
|
225
|
-
*/
|
|
226
|
-
buildExternalDescriptor(agentId: string): import("../../protocol/wire/acp-agent-management.js").ExternalAgentDescriptor | null;
|
|
227
|
-
/**
|
|
228
|
-
* Async, NON-BLOCKING twin of {@link buildExternalDescriptor} — identical output for the same
|
|
229
|
-
* detector state, but resolves the agent list via {@link scanAsync} (a real probe, awaited, when
|
|
230
|
-
* the cache is cold) instead of the sync {@link list}'s cache-or-empty shortcut. Load-bearing for
|
|
231
|
-
* `agents.warm` (agents-handler.ts): the sync path's detect calls are cache-fronted today, but
|
|
232
|
-
* that non-blocking guarantee is an implementation detail of `list()` — routing the RPC path
|
|
233
|
-
* through this method instead makes "never synchronously probe on this path" an explicit
|
|
234
|
-
* contract that can't silently regress if `list()`'s internals change later.
|
|
235
|
-
*/
|
|
236
|
-
buildExternalDescriptorAsync(agentId: string): Promise<import("../../protocol/wire/acp-agent-management.js").ExternalAgentDescriptor | null>;
|
|
237
|
-
/** Shared descriptor-assembly logic for {@link buildExternalDescriptor} and
|
|
238
|
-
* {@link buildExternalDescriptorAsync} — everything AFTER "locate this agentId's AgentDescriptor
|
|
239
|
-
* in an already-resolved list", so the sync/async twins can never drift on behavior, only on how
|
|
240
|
-
* they obtain `agents`. */
|
|
241
|
-
private assembleExternalDescriptorFromAgents;
|
|
242
|
-
/**
|
|
243
|
-
* Whether an agent is ready to compete in Solo/Product: installed/available AND configured.
|
|
244
|
-
* qlogicagent self-resolves from the owner profile (always ready). External agents need a usable
|
|
245
|
-
* ACP descriptor (installed) and, for key-auth backends, the key env resolved (configured by the
|
|
246
|
-
* user on the welcome page). Used by the 启动 pre-check so a race never starts with an agent that
|
|
247
|
-
* would fail its turn ("No LLM provider"/auth). Does NOT verify the key is *valid* — that's only
|
|
248
|
-
* known at runtime.
|
|
249
|
-
*/
|
|
250
|
-
/**
|
|
251
|
-
* Tri-state native-login state for the credential UI's account label — distinct from isAgentReady.
|
|
252
|
-
* `true` = a native login/subscription was actually detected (e.g. codex ~/.codex/auth.json); `false`
|
|
253
|
-
* = probeable but not logged in; `undefined` = no probe for this agent (e.g. hermes' own `acp --setup`
|
|
254
|
-
* store, which we can't read). isAgentReady treats undefined as ready-if-installed so the CLI gets a
|
|
255
|
-
* chance to run, but the UI must NOT claim "已登录" on undefined — it just doesn't know.
|
|
256
|
-
*/
|
|
257
|
-
getNativeLoginState(agentId: string): boolean | undefined;
|
|
258
|
-
isAgentReady(agentId: string): boolean;
|
|
259
|
-
/**
|
|
260
|
-
* Fast-fail guard for the turn path: returns a user-facing error when an agent is in a key-required
|
|
261
|
-
* credential mode (managed / userKey / auto-resolving-to-key) but NO usable key got injected — so the
|
|
262
|
-
* caller can reject the turn cleanly instead of spawning a CLI that would silently stall on auth (the
|
|
263
|
-
* host then goes quiet → the gateway's hang-watchdog kills it → the user sees a cryptic "Agent process
|
|
264
|
-
* stdio closed"). Returns null when credentialed, or when the mode owns its own native login
|
|
265
|
-
* (account / oauth / keyless), or when we can't be sure a key is needed.
|
|
266
|
-
*/
|
|
267
|
-
resolveCredentialError(agentId: string): string | null;
|
|
268
|
-
}
|
|
269
|
-
/** Best-effort resolve the backing model id for an agent (for the planning roster).
|
|
270
|
-
* Returns the configured/auto model or undefined. No spawn — reads config + auto env only. */
|
|
271
|
-
export declare function resolveAgentModel(detector: AcpDetector, id: string): string | undefined;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Config Store — persistent per-agent configuration with project + global fallback.
|
|
3
|
-
*
|
|
4
|
-
* Storage paths:
|
|
5
|
-
* - Project-level: `<cwd>/.qlogicagent/agent-configs.json`
|
|
6
|
-
* - User-level: `~/.qlogicagent/profiles/<owner>/agent-configs.json`
|
|
7
|
-
*
|
|
8
|
-
* Merge strategy: project-level overrides take precedence.
|
|
9
|
-
* Sensitive fields (apiKey) use file permissions 0o600 on Unix.
|
|
10
|
-
*/
|
|
11
|
-
import type { AgentConfig, AgentConfigStoreData, CustomAgentDef } from "../../protocol/wire/acp-agent-management.js";
|
|
12
|
-
export declare class AgentConfigStore {
|
|
13
|
-
private data;
|
|
14
|
-
private cwd;
|
|
15
|
-
constructor(cwd?: string);
|
|
16
|
-
/** Load config from disk. Project-level merges on top of user-level. */
|
|
17
|
-
load(): Promise<void>;
|
|
18
|
-
/** Get the full store data (for AcpDetector.setConfigStore). */
|
|
19
|
-
getData(): AgentConfigStoreData;
|
|
20
|
-
getAgentConfig(agentId: string): AgentConfig | null;
|
|
21
|
-
setAgentConfig(agentId: string, config: AgentConfig): Promise<void>;
|
|
22
|
-
removeAgentConfig(agentId: string): Promise<void>;
|
|
23
|
-
getGatewayUrl(): string | undefined;
|
|
24
|
-
setGatewayUrl(url: string): Promise<void>;
|
|
25
|
-
registerCustomAgent(def: CustomAgentDef): Promise<void>;
|
|
26
|
-
unregisterCustomAgent(agentId: string): Promise<void>;
|
|
27
|
-
getCustomAgents(): Record<string, CustomAgentDef>;
|
|
28
|
-
/** Save to user-level config. Restricts permissions for sensitive data. */
|
|
29
|
-
private save;
|
|
30
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import type { AgentInstallSpec } from "../../protocol/wire/acp-agent-management.js";
|
|
2
|
-
export type InstallEvent = {
|
|
3
|
-
type: "state";
|
|
4
|
-
state: "installing" | "verifying" | "installed" | "failed";
|
|
5
|
-
} | {
|
|
6
|
-
type: "log";
|
|
7
|
-
stream: "stdout" | "stderr";
|
|
8
|
-
chunk: string;
|
|
9
|
-
} | {
|
|
10
|
-
type: "done";
|
|
11
|
-
ok: boolean;
|
|
12
|
-
error?: string;
|
|
13
|
-
};
|
|
14
|
-
/** A child process shaped like node's, so tests can inject a fake. */
|
|
15
|
-
export interface InstallProc {
|
|
16
|
-
stdout?: {
|
|
17
|
-
on(ev: "data", cb: (c: Buffer | string) => void): void;
|
|
18
|
-
} | null;
|
|
19
|
-
stderr?: {
|
|
20
|
-
on(ev: "data", cb: (c: Buffer | string) => void): void;
|
|
21
|
-
} | null;
|
|
22
|
-
on(ev: "close", cb: (code: number | null) => void): void;
|
|
23
|
-
on(ev: "error", cb: (err: Error) => void): void;
|
|
24
|
-
}
|
|
25
|
-
export type InstallSpawn = (command: string, shell: boolean) => InstallProc;
|
|
26
|
-
/**
|
|
27
|
-
* Choose the best official install command for the current platform.
|
|
28
|
-
* Preference: brew (macOS only) → npm → pip → curl (POSIX shell only). Returns the raw
|
|
29
|
-
* command + whether it must run through a shell (curl pipelines / shell metachars).
|
|
30
|
-
*/
|
|
31
|
-
export declare function pickInstallCommand(install: AgentInstallSpec, platform: NodeJS.Platform): {
|
|
32
|
-
command: string;
|
|
33
|
-
shell: boolean;
|
|
34
|
-
} | null;
|
|
35
|
-
/**
|
|
36
|
-
* Inject a package-registry mirror into an install command, for users behind slow or blocked public
|
|
37
|
-
* registries (e.g. PyPI / npm from mainland China, where the default index frequently times out).
|
|
38
|
-
*
|
|
39
|
-
* Opt-in via `mirror`: "cn" applies curated China mirrors per package manager; off (undefined) by
|
|
40
|
-
* default so other users are unaffected. Only rewrites a command that hasn't already pinned a
|
|
41
|
-
* registry/index, and never touches brew/curl. Returns the command unchanged when not applicable.
|
|
42
|
-
*/
|
|
43
|
-
export declare function applyInstallMirror(command: string, mirror: string | undefined): string;
|
|
44
|
-
/** Default spawner: split into argv (or run via shell for pipelines). */
|
|
45
|
-
export declare const defaultInstallSpawn: InstallSpawn;
|
|
46
|
-
/**
|
|
47
|
-
* Run an install spec end-to-end, streaming progress via onEvent. Emits state →
|
|
48
|
-
* log(s) → (verify) → done. Resolves with the final outcome.
|
|
49
|
-
*/
|
|
50
|
-
export declare function runAgentInstall(install: AgentInstallSpec, onEvent: (e: InstallEvent) => void, opts?: {
|
|
51
|
-
platform?: NodeJS.Platform;
|
|
52
|
-
spawnImpl?: InstallSpawn;
|
|
53
|
-
mirror?: string;
|
|
54
|
-
}): Promise<{
|
|
55
|
-
ok: boolean;
|
|
56
|
-
error?: string;
|
|
57
|
-
}>;
|
|
58
|
-
/**
|
|
59
|
-
* Open an OS terminal window running an agent's interactive login/setup command (e.g. `kimi login`,
|
|
60
|
-
* `hermes acp --setup`). The local desktop host can spawn a real terminal so the user completes the
|
|
61
|
-
* CLI's own login flow without leaving the app. Detached + unref so it outlives the engine. The command
|
|
62
|
-
* is a fixed catalog string (no user input) → no injection surface.
|
|
63
|
-
*/
|
|
64
|
-
export declare function launchSetupTerminal(command: string, platform?: NodeJS.Platform): {
|
|
65
|
-
ok: boolean;
|
|
66
|
-
error?: string;
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* Fire-and-forget install in a FULLY DETACHED process (own session/process-group, no stdio shared with
|
|
70
|
-
* us). Used for self/host-platform agents (xiaozhiclaw) whose in-place UPDATE would otherwise disrupt the
|
|
71
|
-
* running engine the install is a child of — "Agent process stdio closed". Returns immediately; the new
|
|
72
|
-
* version is live on the agent's next startup. No progress streaming (the process is detached).
|
|
73
|
-
*/
|
|
74
|
-
export declare function runAgentInstallDetached(install: AgentInstallSpec, opts?: {
|
|
75
|
-
platform?: NodeJS.Platform;
|
|
76
|
-
mirror?: string;
|
|
77
|
-
}): {
|
|
78
|
-
ok: boolean;
|
|
79
|
-
error?: string;
|
|
80
|
-
};
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pending interactive-approval registry for EXTERNAL agents.
|
|
3
|
-
*
|
|
4
|
-
* When a spawned external agent (Codex/Claude/…) asks for permission (ACP session/request_permission),
|
|
5
|
-
* the host handler forwards the request to the frontend and parks the ACP response here until the user
|
|
6
|
-
* decides. The gateway delivers the decision via the agents.approvalResponse RPC, which resolves the
|
|
7
|
-
* matching pending promise so the host handler can return the chosen optionId to the external agent.
|
|
8
|
-
*
|
|
9
|
-
* This is the qlogicagent-side mirror of the gateway adapter's pendingPermissionRequests map.
|
|
10
|
-
*/
|
|
11
|
-
/**
|
|
12
|
-
* Park an approval until the user decides. Resolves with the chosen optionId, or null on timeout
|
|
13
|
-
* (the caller then applies a safe default). Idempotent per approvalId — a duplicate replaces the old.
|
|
14
|
-
*/
|
|
15
|
-
export declare function awaitApprovalDecision(approvalId: string, timeoutMs: number): Promise<string | null>;
|
|
16
|
-
/** Deliver the user's decision. Returns false if no approval was pending for this id (no-op). */
|
|
17
|
-
export declare function resolveApprovalDecision(approvalId: string, optionId: string): boolean;
|
|
18
|
-
/** Cancel all pending approvals (e.g. on shutdown) — resolves them as null so awaiters unblock. */
|
|
19
|
-
export declare function cancelAllApprovals(): void;
|
|
20
|
-
export declare function pendingApprovalCount(): number;
|
|
21
|
-
export interface ApprovalForwardDeps {
|
|
22
|
-
agentId: string;
|
|
23
|
-
/** Current streaming turn identity (read fresh each call, since members are reused across turns). */
|
|
24
|
-
turnContext: () => {
|
|
25
|
-
sessionId?: string;
|
|
26
|
-
turnId?: string;
|
|
27
|
-
requestId?: string;
|
|
28
|
-
} | null;
|
|
29
|
-
/** Emit the forward notification to the gateway (→ turn.approval_request → UI card). */
|
|
30
|
-
sendNotification?: (method: string, params: Record<string, unknown>) => void;
|
|
31
|
-
timeoutMs?: number;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* 激活层(S3c §1.1)delegate 路径的审批决议:输入是 SupervisorEventSink.onApprovalRequest 的已翻译
|
|
35
|
-
* 形状(toolName/options 已扁平,非 ACP 原始 session/request_permission params)。决议序与旧路径
|
|
36
|
-
* forwardExternalApproval 逐条对齐:①AstraClaw 只读能力自批 ②有交互上下文 → forward()发 UI 卡 +
|
|
37
|
-
* 同一 PENDING registry 等 agents.approvalResponse ③无上下文/超时 → reject 回退。返回最终 optionId
|
|
38
|
-
* (不透明,E2);调用方拿它走 x/delegate.respond(gateway 唯一应答口 respondApproval)。
|
|
39
|
-
*/
|
|
40
|
-
export declare function decideExternalApproval(input: {
|
|
41
|
-
agentId: string;
|
|
42
|
-
approvalId: string;
|
|
43
|
-
toolName?: string;
|
|
44
|
-
options: Array<Record<string, unknown>>;
|
|
45
|
-
/** 有流式回合上下文(turnId 在)才值得转 UI 卡;否则直接回退 reject。 */
|
|
46
|
-
hasInteractiveContext: boolean;
|
|
47
|
-
/** 发 agents.prompt.approval UI 卡(形状归属调用方;只在需要用户决议时调用)。 */
|
|
48
|
-
forward: () => void;
|
|
49
|
-
timeoutMs?: number;
|
|
50
|
-
}): Promise<string>;
|
|
51
|
-
/**
|
|
52
|
-
* Drive one interactive approval for an external agent: forward the ACP session/request_permission
|
|
53
|
-
* to the user (agents.prompt.approval), await the decision, and return the chosen optionId. Falls
|
|
54
|
-
* back to a reject option if there's no streaming turn context or the user doesn't decide in time.
|
|
55
|
-
* Pure + injectable so the bidirectional loop is unit-testable without a live agent.
|
|
56
|
-
*/
|
|
57
|
-
export declare function forwardExternalApproval(params: Record<string, unknown>, deps: ApprovalForwardDeps): Promise<{
|
|
58
|
-
optionId: string;
|
|
59
|
-
}>;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* One-shot migration: fold legacy PER-PROFILE install assets into the device-level store.
|
|
3
|
-
*
|
|
4
|
-
* 设计裁定:安装的插件/技能/MCP 是【设备资产】,跟随机器;只有会话/记忆/设置/偏好随登录身份
|
|
5
|
-
* (owner profile)。历史版本把 skills/plugins/mcp.json/skill-lifecycle.json 挂在
|
|
6
|
-
* profiles/<owner>/ 下,登录切身份 → 引擎换 profile → 已装插件"消失"、预装跨身份失效。
|
|
7
|
-
*
|
|
8
|
-
* 折并规则(活跃 owner 的 profile 先处理,它的副本优先):
|
|
9
|
-
* - skills/<name>: 设备层缺 → 整目录 rename 进设备 store;同名且 SKILL.md 内容一致 → 丢弃
|
|
10
|
-
* profile 副本;同名不同内容 → 原地保留 + 大声告警(绝不静默覆盖)。
|
|
11
|
-
* - plugins/<name>: 设备层缺 → rename;同名 → 原地保留 + 告警(插件目录内容不可比对)。
|
|
12
|
-
* - skill-lifecycle.json: 按技能名合并进设备层 store(先到优先),消费掉的文件改名
|
|
13
|
-
* `*.migrated-to-device` 留痕。
|
|
14
|
-
* - mcp.json: 服务器按名合并(先到优先、绝不覆盖已有键),消费掉的文件同样改名留痕。
|
|
15
|
-
* - marketplace.json: 设备层缺 → rename 采用;已有 → 原地保留 + 告警。
|
|
16
|
-
* - skills-disabled.json(全局静音表): 与技能 store 同为设备资产 —— 各 profile 取【并集】合入
|
|
17
|
-
* 设备层(保守方向:任何身份下停放/静音过的技能绝不因迁移静默点亮;agent 自建技能的
|
|
18
|
-
* "默认停放"正是靠这张表,漏并会让它们在别的身份下全部亮起)。消费掉的文件改名留痕。
|
|
19
|
-
* - plugin-cache/、cache/community-installs/: 纯下载缓存,直接删除。
|
|
20
|
-
*
|
|
21
|
-
* 会话伴生数据(第二批裁定,对齐 codex/VS Code —— 会话也随设备):
|
|
22
|
-
* - projectData/<pid>/: 设备层缺该 pid → 整目录 rename;同 pid 跨 profile(同一 workspace 在
|
|
23
|
-
* 多身份下用过,path-derived id 相同)→ 结构化合并:sessions/、checkpoints/、uploads/ 的
|
|
24
|
-
* 子项按【uuid 名】跳已存在(同名=同一会话的陈旧副本,活跃身份先到先得);sessions/.deleted
|
|
25
|
-
* 墓碑按文件名并集;project.json back-ref 先到先得(输家副本可安全删除,注册表每次写都会重生成)。
|
|
26
|
-
* 未能并尽的残留原地保留 + 计入 conflicts(绝不静默销毁)。
|
|
27
|
-
* - projects.json(注册表): 按项目 id 合并(先到先得);activeProjectId 继承第一个有效值
|
|
28
|
-
* (活跃身份优先)。折并须在 rebuildIndexFromBackrefs 之前跑 —— 否则自愈会先用空注册表
|
|
29
|
-
* 重建、丢掉 active 指针等索引态。
|
|
30
|
-
*
|
|
31
|
-
* 幂等:按目录状态驱动(profile 里没有遗留 → 全程 no-op),每次启动同步段调用都安全。
|
|
32
|
-
*/
|
|
33
|
-
export interface DeviceScopeMigrationResult {
|
|
34
|
-
movedSkills: string[];
|
|
35
|
-
movedPlugins: string[];
|
|
36
|
-
/** projectData/<pid> trees moved or merged into the device store. */
|
|
37
|
-
movedProjects: string[];
|
|
38
|
-
/** Same-name different-content entries left in place (loud warning emitted). */
|
|
39
|
-
conflicts: string[];
|
|
40
|
-
/** Profile files (lifecycle/mcp/marketplace/registry/mute) whose content was folded into the device store. */
|
|
41
|
-
mergedFiles: string[];
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Fold every profile's legacy install assets into the device-level store. Bounded (rename-based),
|
|
45
|
-
* idempotent, best-effort with loud per-item diagnostics. Call from the SYNCHRONOUS bootstrap
|
|
46
|
-
* section BEFORE anything reads the skill store — on an upgraded machine every installed skill
|
|
47
|
-
* still lives under profiles/ until this runs.
|
|
48
|
-
*/
|
|
49
|
-
export declare function migrateDeviceScopeInstalls(): DeviceScopeMigrationResult;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project Data GC — best-effort startup reclamation of the companion-data tree, mirroring VS Code's
|
|
3
|
-
* UnusedWorkspaceStorageDataCleaner. A projectData/<id> dir is KEPT when it's either in projects.json
|
|
4
|
-
* OR carries a `project.json` back-ref (the durable truth — rebuildIndexFromBackrefs runs first and
|
|
5
|
-
* re-indexes it). Only a dir with NEITHER (truly corrupt/orphaned — crashed mid-create) is reclaimed.
|
|
6
|
-
* This makes the registry non-load-bearing for recovery: a lost projects.json never causes data loss.
|
|
7
|
-
* Also prunes stale deletion tombstones. NEVER touches live projects' data or the user's workspace.
|
|
8
|
-
*
|
|
9
|
-
* TRULY ASYNC (not just deferred): the iteration count grows with every project dir ever created on
|
|
10
|
-
* this machine (unbounded on a long-lived box). Following the AcpDetector.scanAsync convention, this
|
|
11
|
-
* uses fs/promises and awaits between each directory — every await yields the event loop, so an RPC
|
|
12
|
-
* that arrives mid-GC is dispatched between directories instead of waiting for the whole sweep. The
|
|
13
|
-
* keep/reclaim judgment is unchanged; only the sync fs calls became awaited yield points.
|
|
14
|
-
*/
|
|
15
|
-
export declare function gcOrphanProjectData(): Promise<void>;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { NativeSessionEntry, NativeSessionRef, NativeSessionSource, TranscriptMessage } from "./native-session-source.js";
|
|
2
|
-
/**
|
|
3
|
-
* Native session source for Claude Code (claude CLI). Reads directly from
|
|
4
|
-
* `~/.claude/projects/<claudeProjectDirName(cwd)>/<sessionUuid>.jsonl` — the same on-disk format
|
|
5
|
-
* Claude Code itself writes, so this is read-only and never touched by qlogicagent.
|
|
6
|
-
*
|
|
7
|
-
* `isSidechain: true` events are subagent side-chains, not part of the user-visible conversation,
|
|
8
|
-
* and are filtered out of both list() (message counting / title / lastActiveAt) and
|
|
9
|
-
* loadTranscript() (transcript body).
|
|
10
|
-
*/
|
|
11
|
-
export declare class ClaudeSessionSource implements NativeSessionSource {
|
|
12
|
-
private readonly home;
|
|
13
|
-
readonly agentId = "claude";
|
|
14
|
-
readonly kind: "claude";
|
|
15
|
-
/** `home` is injectable so tests can point at a temp directory instead of the real user home. */
|
|
16
|
-
constructor(home?: string);
|
|
17
|
-
list(cwd: string, opts?: {
|
|
18
|
-
limit?: number;
|
|
19
|
-
}): Promise<NativeSessionEntry[]>;
|
|
20
|
-
/** A claude native session is exactly the file `<encoded-cwd>/<sessionUuid>.jsonl` — a single stat. */
|
|
21
|
-
has(sessionId: string, cwd: string): Promise<boolean>;
|
|
22
|
-
loadTranscript(ref: NativeSessionRef): Promise<TranscriptMessage[]>;
|
|
23
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { NativeSessionEntry } from "./native-session-source.js";
|
|
2
|
-
/**
|
|
3
|
-
* Lists codex-native sessions belonging to `normalizedTargetCwd` (already run through
|
|
4
|
-
* {@link normalizeCwd} by the caller), sorted by `lastActiveAt` descending.
|
|
5
|
-
*
|
|
6
|
-
* Synchronous by design — built entirely on sync fs calls, since it's a Cut 3 building block; a
|
|
7
|
-
* future CodexSessionSource adapter (mirroring claude-session-source.ts's shape) would wrap this in
|
|
8
|
-
* the async `NativeSessionSource.list()` contract.
|
|
9
|
-
*
|
|
10
|
-
* `messageCount` is always 0: unlike claude's one-line-per-message transcript format, a codex
|
|
11
|
-
* rollout interleaves many event types per turn, so computing an exact count means fully parsing
|
|
12
|
-
* every candidate rollout's entire event stream — deliberately out of scope here. Revisit if/when a
|
|
13
|
-
* caller actually needs an exact count.
|
|
14
|
-
*
|
|
15
|
-
* Never throws: a missing/unreadable codexHome, sessions dir, session_index.jsonl, or cache file all
|
|
16
|
-
* degrade to "as if empty" rather than propagating an error.
|
|
17
|
-
*/
|
|
18
|
-
export declare function listCodexSessionsByCwd(normalizedTargetCwd: string, opts?: {
|
|
19
|
-
codexHome?: string;
|
|
20
|
-
cacheDir?: string;
|
|
21
|
-
}): NativeSessionEntry[];
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { NativeSessionEntry, NativeSessionRef, NativeSessionSource, TranscriptMessage } from "./native-session-source.js";
|
|
2
|
-
/**
|
|
3
|
-
* Native session source for Codex (codex CLI / codex_cli_rs) — Cut 3 Task 3.2.
|
|
4
|
-
*
|
|
5
|
-
* `list()` delegates entirely to {@link listCodexSessionsByCwd} (Task 3.1), which already handles
|
|
6
|
-
* cwd filtering, title/lastActiveAt joining against session_index.jsonl, and mtime-keyed caching;
|
|
7
|
-
* this adapter only adds the async `NativeSessionSource.list()` contract and cwd normalization on
|
|
8
|
-
* top of that synchronous building block (mirroring ClaudeSessionSource's shape).
|
|
9
|
-
*
|
|
10
|
-
* `loadTranscript()` reads a single rollout file and keeps only `event_msg` lines whose payload is
|
|
11
|
-
* `user_message` or `agent_message` with `phase: "final_answer"` — see {@link CodexEventMsgLine}'s
|
|
12
|
-
* doc for why every other line/event/payload type in a rollout is intentionally skipped.
|
|
13
|
-
*/
|
|
14
|
-
export declare class CodexSessionSource implements NativeSessionSource {
|
|
15
|
-
private readonly opts;
|
|
16
|
-
readonly agentId = "codex";
|
|
17
|
-
readonly kind: "codex";
|
|
18
|
-
/** `opts` is injectable (codexHome/cacheDir) so tests can point at temp directories instead of
|
|
19
|
-
* the real user home — mirrors listCodexSessionsByCwd's own opts shape. */
|
|
20
|
-
constructor(opts?: {
|
|
21
|
-
codexHome?: string;
|
|
22
|
-
cacheDir?: string;
|
|
23
|
-
});
|
|
24
|
-
list(cwd: string, opts?: {
|
|
25
|
-
limit?: number;
|
|
26
|
-
}): Promise<NativeSessionEntry[]>;
|
|
27
|
-
/** Codex has no id->file mapping without the index (id lives in each rollout's session_meta), so
|
|
28
|
-
* membership goes through the mtime-cached listCodexSessionsByCwd (no full re-scan when warm). */
|
|
29
|
-
has(sessionId: string, cwd: string): Promise<boolean>;
|
|
30
|
-
loadTranscript(ref: NativeSessionRef): Promise<TranscriptMessage[]>;
|
|
31
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Normalize a cwd for CODEX session-cwd equality comparisons (matching a codex rollout's
|
|
3
|
-
* `session_meta.cwd` against our own workspace cwd). Same rule in spirit as projectId derivation
|
|
4
|
-
* (see agent-paths.ts `deriveProjectId`: resolve + lowercase) — resolve to an absolute path, then
|
|
5
|
-
* lowercase and force forward-slash separators so both `E:\Foo\Bar` and `e:/foo/bar` compare equal.
|
|
6
|
-
* (path.resolve() already normalizes `/` to `\` on win32, so the explicit slash replace below is
|
|
7
|
-
* belt-and-suspenders rather than load-bearing — verified via `path.resolve("e:/xiaozhiclaw/openclaw")`
|
|
8
|
-
* === `"e:\\xiaozhiclaw\\openclaw"` on this machine — but kept explicit so the output format doesn't
|
|
9
|
-
* silently depend on that internal, unstated Node behavior.)
|
|
10
|
-
*/
|
|
11
|
-
export declare function normalizeCwd(cwd: string): string;
|
|
12
|
-
/**
|
|
13
|
-
* Encode a cwd into the directory name Claude Code uses under `~/.claude/projects/<encoded>`.
|
|
14
|
-
*
|
|
15
|
-
* This is Claude Code's OWN encoding (not ours) — we must replicate it byte-for-byte to locate
|
|
16
|
-
* existing native claude session directories on disk. It has no public spec, so this was reverse
|
|
17
|
-
* engineered two ways and cross-checked against each other:
|
|
18
|
-
*
|
|
19
|
-
* 1. Real directory names from `ls ~/.claude/projects` on this dev machine (see
|
|
20
|
-
* cwd-normalize.test.ts for the samples, notably a workspace with a literal space in its name
|
|
21
|
-
* — "QA Agent Mention Pool 20260701-1325" — which is what falsified the initially-assumed
|
|
22
|
-
* narrower rule).
|
|
23
|
-
* 2. Decompiling the bundled VS Code extension (anthropic.claude-code-2.1.168,
|
|
24
|
-
* extension/extension.js). The relevant minified functions (renamed here for readability;
|
|
25
|
-
* originals were Hv/yv/pOe/cOe):
|
|
26
|
-
*
|
|
27
|
-
* const MAX_LEN = 200;
|
|
28
|
-
* function hashCode(e) { // Java String.hashCode()-style,
|
|
29
|
-
* let t = 0; // 32-bit signed, wraps via `|0`
|
|
30
|
-
* for (let r = 0; r < e.length; r++) t = (t << 5) - t + e.charCodeAt(r) | 0;
|
|
31
|
-
* return t;
|
|
32
|
-
* }
|
|
33
|
-
* function encodeProjectDirName(e) {
|
|
34
|
-
* const t = e.replace(/[^a-zA-Z0-9]/g, "-");
|
|
35
|
-
* if (t.length <= MAX_LEN) return t;
|
|
36
|
-
* return `${t.slice(0, MAX_LEN)}-${Math.abs(hashCode(e)).toString(36)}`;
|
|
37
|
-
* }
|
|
38
|
-
*
|
|
39
|
-
* Two things this rule does that a naive "just swap \\/:. for -" guess would get wrong:
|
|
40
|
-
* - The replacement set is "everything that isn't [a-zA-Z0-9]", not a fixed 4-character set —
|
|
41
|
-
* spaces, underscores, parens, plus signs, and non-ASCII (e.g. Chinese) characters are all
|
|
42
|
-
* replaced too. Original casing is preserved (no lowercasing, unlike normalizeCwd above).
|
|
43
|
-
* - Encoded names longer than 200 characters are truncated to 200 chars plus a
|
|
44
|
-
* "-<base36 32-bit hash>" suffix, where the hash is computed over the ORIGINAL
|
|
45
|
-
* (pre-replacement) string, not the truncated one.
|
|
46
|
-
*
|
|
47
|
-
* This encoding is lossy/one-way by construction (e.g. `...\\qlogicagent-hub` and
|
|
48
|
-
* `...\\qlogicagent\\hub` both encode to the same name) — it can only be used to look up a
|
|
49
|
-
* directory for a known cwd, never to recover a cwd from a directory name. If Claude Code changes
|
|
50
|
-
* this encoding in a future version, update this function and the fixtures in
|
|
51
|
-
* cwd-normalize.test.ts together.
|
|
52
|
-
*/
|
|
53
|
-
export declare function claudeProjectDirName(cwd: string): string;
|