qlogicagent 2.19.1 → 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/dist/agent-contract.js +1 -1
- package/dist/cli.js +1 -1
- 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/types/cli/acp-commands.d.ts +1 -1
- package/dist/types/cli/acp-extended-handlers.d.ts +2 -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 +110 -18
- package/dist/types/host-session-collection-contract.d.ts +61 -0
- package/dist/types/orchestration/agent-instance.d.ts +4 -11
- package/dist/types/orchestration/agent-roster.d.ts +4 -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 +9 -3
- 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 +0 -4
- 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 +48 -134
- 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/workflow-host.js +10 -10
- package/package.json +8 -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 -126
- 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 -273
- 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,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;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sweep both native stores. Best-effort: never throws (all I/O is guarded); returns how many rollouts were
|
|
3
|
-
* reclaimed. `home`/`codexHome`/`ttlMs`/`now` are injectable for tests.
|
|
4
|
-
*/
|
|
5
|
-
export declare function sweepEphemeralWorktreeRollouts(opts?: {
|
|
6
|
-
home?: string;
|
|
7
|
-
codexHome?: string;
|
|
8
|
-
ttlMs?: number;
|
|
9
|
-
now?: number;
|
|
10
|
-
}): Promise<{
|
|
11
|
-
claudeDeleted: number;
|
|
12
|
-
codexDeleted: number;
|
|
13
|
-
}>;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Single source of truth for WHICH third-party ACP backend ids have local, cwd-discoverable
|
|
3
|
-
* native session history ("native-cwd" adapters registered in register-builtin-sources.ts).
|
|
4
|
-
*
|
|
5
|
-
* Consumed by both:
|
|
6
|
-
* - acp-detector.ts (assembleBackendDescriptor) — descriptor's capabilities.sessionHistory
|
|
7
|
-
* - session-handler.ts (resolveAgentSessionHistory) — session.list routing
|
|
8
|
-
*
|
|
9
|
-
* so the two can never drift on which ids are native-adapted (the DRY debt Cut 1 intentionally
|
|
10
|
-
* left behind — see Cut 3 Task 3.0). To add or remove a native-cwd agent: change this set AND
|
|
11
|
-
* register/unregister the matching NativeSessionSource adapter in register-builtin-sources.ts.
|
|
12
|
-
*
|
|
13
|
-
* Zero imports by design — this file must stay a dependency-free leaf so both acp-detector.ts and
|
|
14
|
-
* session-handler.ts (which itself imports ACP_BACKENDS from acp-detector.ts) can import it without
|
|
15
|
-
* risking an import cycle.
|
|
16
|
-
*/
|
|
17
|
-
export declare const NATIVE_CWD_BACKEND_IDS: ReadonlySet<string>;
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Native session source registry.
|
|
3
|
-
*
|
|
4
|
-
* A "native" session source lets a third-party ACP agent (codex/claude) expose ITS OWN
|
|
5
|
-
* CWD-scoped session history — recorded by the agent's own CLI, not by qlogicagent — through
|
|
6
|
-
* the same session.list / session.get surface as our own sessions.
|
|
7
|
-
*
|
|
8
|
-
* Cut 1 shipped only the registry contract with a loose shape; no adapter registered itself, so
|
|
9
|
-
* {@link getNativeSessionSource} always returned undefined and callers (session-handler's
|
|
10
|
-
* resolveSessionSource) fell back to an empty list for native-cwd agents. Cut 2 refines the
|
|
11
|
-
* contract below and adds the claude adapter (see claude-session-source.ts) that calls
|
|
12
|
-
* {@link registerNativeSessionSource}.
|
|
13
|
-
*/
|
|
14
|
-
/** Opaque locator for a single native session's transcript, round-tripped by the frontend without
|
|
15
|
-
* interpretation (session.list returns it, session.loadNativeTranscript consumes it). */
|
|
16
|
-
export interface NativeSessionRef {
|
|
17
|
-
agentId: string;
|
|
18
|
-
kind: "codex" | "claude";
|
|
19
|
-
/** Absolute path to the on-disk transcript file (adapter-specific format). */
|
|
20
|
-
file: string;
|
|
21
|
-
}
|
|
22
|
-
/** One native session list entry — the `source: "native"` variant of session.list's
|
|
23
|
-
* SessionListEntry (see session-types.ts SessionListEntry for the "own" counterpart). */
|
|
24
|
-
export interface NativeSessionEntry {
|
|
25
|
-
sessionId: string;
|
|
26
|
-
source: "native";
|
|
27
|
-
agentId: string;
|
|
28
|
-
title?: string;
|
|
29
|
-
lastActiveAt: string;
|
|
30
|
-
messageCount: number;
|
|
31
|
-
cwd: string;
|
|
32
|
-
nativeRef: NativeSessionRef;
|
|
33
|
-
/** Stamped by handleSessionList from the requested project so the frontend's per-project grouping
|
|
34
|
-
* (project-tree filters by projectId) shows native entries under it. The source discovers by cwd
|
|
35
|
-
* and cannot know the project, so it leaves this unset. */
|
|
36
|
-
projectId?: string;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Minimal transcript-line shape for native session.loadTranscript. This intentionally does NOT
|
|
40
|
-
* import the frontend's `InboundMessagePayload` (ui-next/src/types/gateway.ts) — that type lives
|
|
41
|
-
* in a separate package/repo from this engine and carries many fields irrelevant to a bare
|
|
42
|
-
* transcript line (sessionKey, blocks, attachments, mediaUrl, chatId, ...). Instead this is the
|
|
43
|
-
* minimal subset every native adapter can populate, documented field-for-field against the
|
|
44
|
-
* frontend contract so a caller can widen a TranscriptMessage into an InboundMessagePayload by
|
|
45
|
-
* filling in the rest as optional/absent:
|
|
46
|
-
* - messageId -> InboundMessagePayload.messageId (required)
|
|
47
|
-
* - content -> InboundMessagePayload.content (required)
|
|
48
|
-
* - timestamp -> InboundMessagePayload.timestamp (required)
|
|
49
|
-
* - source -> InboundMessagePayload.source (required, narrowed here to "user"|"assistant"
|
|
50
|
-
* since that's all a transcript line can be)
|
|
51
|
-
* - platform -> InboundMessagePayload.platform (required there; optional here since every
|
|
52
|
-
* current adapter always sets it to "desktop" — kept optional so future adapters
|
|
53
|
-
* aren't forced to fabricate a value)
|
|
54
|
-
*/
|
|
55
|
-
export interface TranscriptMessage {
|
|
56
|
-
messageId: string;
|
|
57
|
-
content: string;
|
|
58
|
-
timestamp: string;
|
|
59
|
-
source: "user" | "assistant";
|
|
60
|
-
platform?: string;
|
|
61
|
-
}
|
|
62
|
-
export interface NativeSessionSource {
|
|
63
|
-
readonly agentId: string;
|
|
64
|
-
readonly kind: "codex" | "claude";
|
|
65
|
-
/** `cwd` is the RAW (un-normalized) project cwd — callers (session-handler's
|
|
66
|
-
* resolveSessionSource, via handleSessionList) pass the REQUESTED project's workspaceDir
|
|
67
|
-
* (params.projectId's, when present) straight through, falling back to getActiveProjectRoot()
|
|
68
|
-
* only when no projectId was given. Each adapter is responsible for whatever
|
|
69
|
-
* normalization/encoding its own on-disk storage requires (e.g. claude's
|
|
70
|
-
* claudeProjectDirName preserves original casing). */
|
|
71
|
-
list(cwd: string, opts?: {
|
|
72
|
-
limit?: number;
|
|
73
|
-
}): Promise<NativeSessionEntry[]>;
|
|
74
|
-
/** Cheap existence check: is `sessionId` an existing native session under `cwd` for this agent?
|
|
75
|
-
* Used on a COLD spawn to decide whether to resume it (ACP session/load) instead of creating a
|
|
76
|
-
* fresh session — so a native conversation regains its authoritative history after pool eviction/
|
|
77
|
-
* restart, not only on the one-shot "继续". Optional so test fakes need not implement it. */
|
|
78
|
-
has?(sessionId: string, cwd: string): Promise<boolean>;
|
|
79
|
-
loadTranscript(ref: NativeSessionRef): Promise<TranscriptMessage[]>;
|
|
80
|
-
}
|
|
81
|
-
/** Register a native session source for an agentId. Last registration for a given id wins. */
|
|
82
|
-
export declare function registerNativeSessionSource(source: NativeSessionSource): void;
|
|
83
|
-
/** Look up a registered native session source by agentId. Undefined when none is registered for
|
|
84
|
-
* that id (no adapter registered itself yet, or the agentId has no native adapter at all). */
|
|
85
|
-
export declare function getNativeSessionSource(agentId?: string): NativeSessionSource | undefined;
|
|
86
|
-
/** Remove a registered native session source by agentId. Symmetric with {@link registerNativeSessionSource};
|
|
87
|
-
* exists primarily so tests can deregister a fake adapter afterward without leaking it into other
|
|
88
|
-
* test cases that share this module-level registry. No-op if nothing is registered for that id. */
|
|
89
|
-
export declare function unregisterNativeSessionSource(agentId: string): void;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function cleanNativeTitle(message: string, maxLen?: number): string | undefined;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function registerBuiltinNativeSources(): void;
|