qlogicagent 2.17.10 → 2.18.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.
Files changed (70) hide show
  1. package/dist/agent.js +25 -21
  2. package/dist/cli.js +1 -1
  3. package/dist/index.js +451 -435
  4. package/dist/protocol.js +1 -1
  5. package/dist/skills/mcp/astraclaw-native-mcp-server.js +6 -5
  6. package/dist/types/agent/tool-loop/compression-pipeline.d.ts +2 -0
  7. package/dist/types/agent/tool-loop/loop-helpers.d.ts +1 -0
  8. package/dist/types/agent/tool-loop/tool-failure-policy.d.ts +13 -1
  9. package/dist/types/agent/tool-loop.d.ts +14 -0
  10. package/dist/types/agent/types.d.ts +7 -0
  11. package/dist/types/cli/handlers/agents-handler.d.ts +9 -0
  12. package/dist/types/cli/handlers/config-handler.d.ts +5 -0
  13. package/dist/types/cli/handlers/files-handler.d.ts +7 -0
  14. package/dist/types/cli/handlers/session-handler.d.ts +43 -0
  15. package/dist/types/cli/handlers/turn-handler.d.ts +12 -0
  16. package/dist/types/cli/handlers/workflow-handler.d.ts +1 -0
  17. package/dist/types/cli/permission-rule-persistence.d.ts +16 -0
  18. package/dist/types/cli/stdio-rpc-handler-hosts.d.ts +4 -0
  19. package/dist/types/cli/stdio-server.d.ts +16 -1
  20. package/dist/types/cli/turn-core.d.ts +2 -0
  21. package/dist/types/orchestration/agent-instance.d.ts +11 -1
  22. package/dist/types/orchestration/agent-roster.d.ts +12 -0
  23. package/dist/types/orchestration/dag-scheduler.d.ts +3 -0
  24. package/dist/types/orchestration/delegation-coordinator.d.ts +16 -1
  25. package/dist/types/orchestration/goal-loop-coordinator.d.ts +4 -1
  26. package/dist/types/orchestration/goal-mode-adapters.d.ts +3 -1
  27. package/dist/types/orchestration/goal-run-types.d.ts +2 -0
  28. package/dist/types/orchestration/product-budget.d.ts +13 -0
  29. package/dist/types/orchestration/product-persistence.d.ts +4 -0
  30. package/dist/types/orchestration/product-planner.d.ts +7 -2
  31. package/dist/types/orchestration/product-run-coordinator.d.ts +1 -0
  32. package/dist/types/orchestration/workflow/budget-permission-gate.d.ts +9 -0
  33. package/dist/types/orchestration/workflow/node-schema.d.ts +4 -1
  34. package/dist/types/orchestration/workflow/workflow-trigger.d.ts +5 -1
  35. package/dist/types/protocol/wire/acp-agent-management.d.ts +16 -0
  36. package/dist/types/protocol/wire/agent-events.d.ts +2 -2
  37. package/dist/types/protocol/wire/agent-methods.d.ts +3 -0
  38. package/dist/types/protocol/wire/gateway-rpc.d.ts +1 -0
  39. package/dist/types/runtime/execution/streaming-tool-executor.d.ts +2 -0
  40. package/dist/types/runtime/execution/tool-result-storage.d.ts +6 -4
  41. package/dist/types/runtime/infra/acp-detector.d.ts +35 -5
  42. package/dist/types/runtime/infra/acp-protocol-adapter.d.ts +23 -1
  43. package/dist/types/runtime/infra/agent-process.d.ts +15 -0
  44. package/dist/types/runtime/infra/external-agent-pool.d.ts +12 -0
  45. package/dist/types/runtime/infra/llmrouter-catalog.d.ts +26 -6
  46. package/dist/types/runtime/infra/model-registry.d.ts +43 -2
  47. package/dist/types/runtime/infra/user-dirs.d.ts +21 -0
  48. package/dist/types/runtime/permission-model.d.ts +1 -1
  49. package/dist/types/runtime/ports/agent-runtime-ports.d.ts +4 -1
  50. package/dist/types/runtime/ports/permission-contracts.d.ts +5 -2
  51. package/dist/types/runtime/prompt/environment-context.d.ts +10 -0
  52. package/dist/types/runtime/prompt/fresh-workspace-evidence.d.ts +1 -4
  53. package/dist/types/runtime/prompt/identity-section.d.ts +1 -1
  54. package/dist/types/runtime/session/inbound-upload-persistence.d.ts +8 -0
  55. package/dist/types/runtime/session/native/claude-session-source.d.ts +23 -0
  56. package/dist/types/runtime/session/native/codex-index.d.ts +21 -0
  57. package/dist/types/runtime/session/native/codex-session-source.d.ts +31 -0
  58. package/dist/types/runtime/session/native/cwd-normalize.d.ts +53 -0
  59. package/dist/types/runtime/session/native/ephemeral-rollout-sweep.d.ts +13 -0
  60. package/dist/types/runtime/session/native/native-cwd-agents.d.ts +17 -0
  61. package/dist/types/runtime/session/native/native-session-source.d.ts +89 -0
  62. package/dist/types/runtime/session/native/native-title.d.ts +1 -0
  63. package/dist/types/runtime/session/native/register-builtin-sources.d.ts +1 -0
  64. package/dist/types/runtime/session/session-resource-key.d.ts +28 -0
  65. package/dist/types/runtime/session/session-transcript-store.d.ts +2 -0
  66. package/dist/types/runtime/session/session-types.d.ts +37 -0
  67. package/dist/types/skills/permissions/hook-runner.d.ts +9 -0
  68. package/dist/types/skills/permissions/settings-watcher.d.ts +7 -0
  69. package/dist/types/transport/acp-server.d.ts +6 -0
  70. package/package.json +4 -3
@@ -16,6 +16,8 @@ export interface TurnCoreRequest {
16
16
  tools: ToolDefinition[];
17
17
  /** Live tool-manifest rebuild for same-turn activation (forwarded to the loop). */
18
18
  refreshTools?: () => ToolDefinition[];
19
+ /** Mid-turn guidance drain (运行中引导) — forwarded to the tool loop. */
20
+ drainPendingGuidance?: () => string[];
19
21
  systemPrompt: string;
20
22
  config: TurnConfig;
21
23
  }
@@ -28,6 +28,7 @@ export interface ProductCallbacks {
28
28
  inputTokens: number;
29
29
  outputTokens: number;
30
30
  changedFiles: string[];
31
+ acceptanceUnverified?: boolean;
31
32
  }) => void;
32
33
  onTaskFailed?: (productId: string, taskId: string, error: string) => void;
33
34
  onCheckpointed?: (productId: string, timestamp: string) => void;
@@ -83,7 +84,12 @@ export declare class ProductOrchestrator {
83
84
  */
84
85
  create(params: ProductCreateParams): Promise<string>;
85
86
  /** Resume a product from persisted state. */
86
- resume(productId: string, cwd?: string): Promise<void>;
87
+ resume(productId: string, cwd?: string, opts?: {
88
+ additionalBudget?: {
89
+ maxTotalTokens?: number;
90
+ maxDuration?: number;
91
+ };
92
+ }): Promise<void>;
87
93
  /**
88
94
  * Pause a running product — the SINGLE pause path (I9).
89
95
  *
@@ -121,6 +127,10 @@ export declare class ProductOrchestrator {
121
127
  */
122
128
  replayTask(productId: string, taskId: string): Promise<void>;
123
129
  /** Get product status. */
130
+ /** P2-1: the native (codex/claude) session id captured for a delegation's single worker, so the
131
+ * DelegationCoordinator can resume it on the next same-(chat×agent) delegation. undefined for a
132
+ * multi-instance product, an own agent, or before the worker's first task settles. */
133
+ getDelegationNativeSessionId(productId: string): string | undefined;
124
134
  getStatus(productId: string): ProductStatus | null;
125
135
  /** Live DAG progress snapshot for a product (for the planner's execution-phase leader). */
126
136
  getProgressSnapshot(productId: string): {
@@ -15,3 +15,15 @@ import { type AcpDetector } from "../runtime/infra/acp-detector.js";
15
15
  * if not already in the roster, so the leader always has ≥1 valid assignee even when the user's picks turn
16
16
  * out unready (or when the pool is empty). */
17
17
  export declare function buildAgentRoster(detector: AcpDetector, _configStore: AgentConfigStoreData | null, allowedAgents?: string[]): AgentRosterEntry[];
18
+ /**
19
+ * User-PICKED worker ids that did NOT make it into the roster (unready: not installed / not logged in
20
+ * / not in the catalog). Excludes the leader (always force-included). Empty when nothing was dropped
21
+ * or when the pool was omitted. Callers surface this so a picked worker doesn't vanish silently and
22
+ * collapse the team to just 小智 (honesty over silence — goal used to degrade with no notice).
23
+ */
24
+ export declare function computeUnavailablePicks(allowedAgents: string[] | undefined, rosterIds: readonly string[]): string[];
25
+ /** buildAgentRoster + the diagnostics of which picked workers were dropped as unavailable. */
26
+ export declare function buildAgentRosterWithDiagnostics(detector: AcpDetector, configStore: AgentConfigStoreData | null, allowedAgents?: string[]): {
27
+ roster: AgentRosterEntry[];
28
+ unavailablePicks: string[];
29
+ };
@@ -34,6 +34,7 @@ export interface Node {
34
34
  inputTokens?: number;
35
35
  outputTokens?: number;
36
36
  changedFiles?: string[];
37
+ acceptanceUnverified?: boolean;
37
38
  runIndex: number;
38
39
  maxIterations?: number;
39
40
  iteration?: number;
@@ -89,6 +90,7 @@ export declare class DagScheduler {
89
90
  inputTokens?: number;
90
91
  outputTokens?: number;
91
92
  changedFiles?: string[];
93
+ acceptanceUnverified?: boolean;
92
94
  }): void;
93
95
  markFailed(id: string, error: string): void;
94
96
  markPaused(id: string): void;
@@ -188,6 +190,7 @@ export interface SerializedNode {
188
190
  inputTokens?: number;
189
191
  outputTokens?: number;
190
192
  changedFiles?: string[];
193
+ acceptanceUnverified?: boolean;
191
194
  runIndex: number;
192
195
  maxIterations?: number;
193
196
  iteration?: number;
@@ -11,10 +11,20 @@ export interface DelegationDeps {
11
11
  warn(m: string): void;
12
12
  };
13
13
  }
14
- type DelegationStatus = "running" | "completed" | "failed" | "cancelled";
14
+ type DelegationStatus = "running" | "completed" | "failed" | "cancelled" | "timed_out";
15
15
  export declare class DelegationCoordinator {
16
16
  private readonly deps;
17
17
  private readonly active;
18
+ /** Per-(chat×agent) tail promise — the next same-conversation delegation chains after it so they run
19
+ * strictly sequentially (single writer to the shared reused worktree + native session). One entry per
20
+ * active (chat×agent) pair (keyed, overwritten — not per-delegation), so it stays bounded. */
21
+ private readonly convChains;
22
+ /** Per-(chat×agent) native (codex/claude) session id — the background analogue of the foreground U5
23
+ * convergence. Seeded from the first delegation's captured session id; passed as resumeNativeSessionId on
24
+ * every subsequent same-conversation delegation so context accumulates (git AND non-git projects).
25
+ * In-memory (one entry per active pair); an engine restart resets it → the next delegation starts fresh,
26
+ * same as a cold foreground turn whose pool was evicted. */
27
+ private readonly nativeSessions;
18
28
  constructor(deps: DelegationDeps);
19
29
  /** Active + recent delegations for this project (x/mention.list). */
20
30
  list(): {
@@ -40,6 +50,11 @@ export declare class DelegationCoordinator {
40
50
  delegationId: string;
41
51
  };
42
52
  private run;
53
+ /** Collect a delegation's produced artifacts: the union of the worktree diff (tasks[].changedFiles,
54
+ * omitted by the wire type but carried at runtime) and the mtime-isolated capture of project-root files
55
+ * (for workers that write straight to the workspace), plus the worker task + terminal phase. Shared by
56
+ * the normal terminal path AND the timeout path, so a timed-out run still hands back its partial output. */
57
+ private collectProducts;
43
58
  private settle;
44
59
  }
45
60
  export {};
@@ -3,7 +3,10 @@ export interface LeaderPort {
3
3
  deriveChecklist(goal: string): Promise<AcceptanceCriterion[]>;
4
4
  planPhase(goal: string, summary: string, drained: GoalQueuedMessage[], checklist: AcceptanceChecklist, agentPool: string[]): Promise<PhaseSpec>;
5
5
  critiquePlan(spec: PhaseSpec, goal: string, checklist: AcceptanceChecklist, agentPool: string[]): Promise<PhaseSpec>;
6
- assess(productId: string, checklist: AcceptanceChecklist): Promise<AcceptanceDelta[]>;
6
+ assess(productId: string, checklist: AcceptanceChecklist): Promise<{
7
+ deltas: AcceptanceDelta[];
8
+ producedFiles: boolean;
9
+ }>;
7
10
  compact(prevSummary: string, deltas: AcceptanceDelta[]): Promise<string>;
8
11
  }
9
12
  export interface PhaseRunnerPort {
@@ -75,7 +75,9 @@ export interface PhaseRunnerAdapterDeps {
75
75
  };
76
76
  }
77
77
  export declare function createPhaseRunnerAdapter(deps: PhaseRunnerAdapterDeps): PhaseRunnerPort;
78
- export declare function parsePhaseSpec(reply: string, availableAgentIds: string[]): PhaseSpec;
78
+ export declare function parsePhaseSpec(reply: string, availableAgentIds: string[], log?: {
79
+ warn?(m: string): void;
80
+ }): PhaseSpec;
79
81
  /**
80
82
  * B (evidence-gating): goal-mode's assess() is the SOLE acceptance authority (Product's per-task judge
81
83
  * is a no-op for a session-less goal-mode run), so a criterion may only flip to `passed` when it is
@@ -1,5 +1,6 @@
1
1
  /** Loop tunables (single source of truth — I9). */
2
2
  export declare const GOAL_NO_PROGRESS_LIMIT = 3;
3
+ export declare const GOAL_SOFT_NO_PROGRESS_LIMIT = 8;
3
4
  export declare const GOAL_DRAIN_TIMEOUT_MS: number;
4
5
  export declare const GOAL_UNREACHABLE_MIN_STREAK = 2;
5
6
  export type GoalRunStatus = "running" | "ended";
@@ -76,6 +77,7 @@ export interface PersistedGoalRunState {
76
77
  pauseState: GoalPauseState;
77
78
  phaseIndex: number;
78
79
  noProgressCount: number;
80
+ noFlipStreak?: number;
79
81
  unreachableStreak?: Record<string, number>;
80
82
  progressSummary: string;
81
83
  acceptanceChecklist: AcceptanceChecklist;
@@ -43,6 +43,19 @@ export declare class ProductBudgetTracker {
43
43
  * - "exceeded": over 100%, should pause
44
44
  */
45
45
  check(): BudgetCheck;
46
+ /**
47
+ * Grant additional budget headroom — the escape hatch out of a budget-exhausted pause. Without it,
48
+ * resume just restores usedTokens (already >= max), re-checks, and immediately re-pauses forever
49
+ * (a permanent deadlock with no "add budget" entry). With no explicit amount, grants one more of the
50
+ * current quota's worth of headroom measured from where usage stands now; an explicit amount adds
51
+ * exactly that. Re-arms the 80% warning so the fresh quota warns again. Time budgets get a fresh
52
+ * window from now (elapsed already includes paused wall-clock, so extending the raw ceiling wouldn't
53
+ * help). The user's act of resuming a paused-at-budget run IS the decision to spend more.
54
+ */
55
+ raiseBudget(additional?: {
56
+ maxTotalTokens?: number;
57
+ maxDuration?: number;
58
+ }): void;
46
59
  /** Restore from persisted budget data. (input/output optional for back-compat with older snapshots.) */
47
60
  restore(data: {
48
61
  usedTokens: number;
@@ -30,6 +30,10 @@ export interface PersistedProductState {
30
30
  * PlanningSession is strings / arrays / plain objects (no functions, dates, or class instances).
31
31
  */
32
32
  leaderDialogue?: PlanningSession;
33
+ /** P2-1: run tasks in the project cwd instead of per-task worktrees (see
34
+ * ProductCreateParams.runInProjectCwd) — persisted so a delegation resumed after an engine restart
35
+ * keeps running in the project cwd, not a fresh isolated worktree. */
36
+ runInProjectCwd?: boolean;
33
37
  }
34
38
  export interface ProductPersistenceOptions {
35
39
  pathService?: PathService;
@@ -165,8 +165,12 @@ export declare class ProductPlanner {
165
165
  listSessions(): PlanningSession[];
166
166
  /**
167
167
  * Ask the leader to judge whether a worker task's output satisfies its acceptanceCriteria.
168
- * Returns { pass: true } immediately when there is no leader session (fail-open).
169
- * If the response cannot be parsed at all, defaults to { pass: true } (lenient, like solo.specJudge).
168
+ *
169
+ * Distinguishes a VERIFIED pass (the judge ran and returned PASS) from an UNVERIFIED pass
170
+ * (`unverified: true`) — the run continues rather than blocking, but the caller must NOT report
171
+ * an unverified pass as if the work were checked. Unverified means we could not judge at all: no
172
+ * leader session, or the judge response was unparseable/errored. (The judging *prompt* itself is
173
+ * deliberately lenient/evidence-aware — that is a real PASS, not an unverified one.)
170
174
  */
171
175
  reviewTaskOutput(productId: string, review: {
172
176
  taskId: string;
@@ -177,6 +181,7 @@ export declare class ProductPlanner {
177
181
  }): Promise<{
178
182
  pass: boolean;
179
183
  feedback?: string;
184
+ unverified?: boolean;
180
185
  }>;
181
186
  /**
182
187
  * Ask leader to evaluate execution state and propose DAG mutations.
@@ -25,6 +25,7 @@ export interface ProductLeaderCoordinator {
25
25
  }): Promise<{
26
26
  pass: boolean;
27
27
  feedback?: string;
28
+ unverified?: boolean;
28
29
  }>;
29
30
  /** Snapshot the leader's PlanningSession for checkpoint persistence (durable execution). */
30
31
  serializeSession(productId: string): PlanningSession | null;
@@ -31,6 +31,15 @@ export type WorkflowTriggerKind = "manual" | "schedule" | "im-message" | "webhoo
31
31
  * (set / if / loop / merge / passthrough / trigger) are NOT here — they cannot escape the engine.
32
32
  */
33
33
  export declare const SENSITIVE_KINDS: ReadonlySet<string>;
34
+ /**
35
+ * The distinct sensitive (side-effecting) kinds present among these node kinds — i.e. the
36
+ * capabilities a workflow will need authorized to run unattended. Pure; drives upfront disclosure at
37
+ * ACTIVATION so the user authorizes these knowingly, instead of the first unattended run hard-failing
38
+ * at the gate (the old surprise: "activated fine, then the 3am schedule died at a channel send").
39
+ */
40
+ export declare function requiredUnattendedPermissions(nodeKinds: Iterable<string>): string[];
41
+ /** Required unattended permissions NOT yet granted — exactly what activation should ask to authorize. */
42
+ export declare function missingUnattendedAuthorizations(nodeKinds: Iterable<string>, granted: readonly string[] | undefined): string[];
34
43
  /** Hard, non-resumable denial: an unauthorized side-effecting kind under an unattended trigger. */
35
44
  export declare class WorkflowPermissionDenied extends Error {
36
45
  readonly nodeId: string;
@@ -207,8 +207,11 @@ export interface ApprovalHostRequest {
207
207
  workflowId?: string;
208
208
  /** Plain-language question shown to the owner (默认 "继续执行?"). */
209
209
  prompt?: string;
210
- /** Auto-deny deadline; default 24h. */
210
+ /** Deadline for a decision; default 24h. What happens at the deadline is timeoutAction (default reject). */
211
211
  timeoutMs?: number;
212
+ /** Timeout policy (default "reject"): "reject" fails the node but ANNOUNCES it (not a silent auto-deny);
213
+ * "approve" auto-continues; "keepPending" stays suspended (persisted; re-prompts on restart). */
214
+ timeoutAction?: "approve" | "reject" | "keepPending";
212
215
  input: DataItem[];
213
216
  signal?: AbortSignal;
214
217
  }
@@ -28,7 +28,11 @@ export type TriggerDef = {
28
28
  aliases?: string[];
29
29
  /** 开启语义兜底(确定性未命中时一次 LLM 分类;有成本,默认关)。 */
30
30
  semantic?: boolean;
31
- /** 命中后是否弹确认(默认 true;关闭=说出即跑)。 */
31
+ /**
32
+ * 命中后是否弹确认。显式 true/false = 用户的判断,恒生效(false=说出即跑)。
33
+ * 缺省时由客户端按 intentIndex 的 sideEffectKinds 证据决定:无副作用节点→直接跑;
34
+ * 有副作用→弹确认(确认条上可选「总是直接运行」,持久化为 confirm:false)。
35
+ */
32
36
  confirm?: boolean;
33
37
  /** 生效界面;缺省 = 欢迎页+对话页都生效。 */
34
38
  surfaces?: ("welcome" | "chat")[];
@@ -337,6 +337,22 @@ export interface ProductCreateParams {
337
337
  maxTotalTokens?: number;
338
338
  maxDuration?: number;
339
339
  };
340
+ /**
341
+ * P2-1: run ALL tasks directly in the project cwd (`cwd`) instead of isolated per-task git worktrees.
342
+ * Set by DelegationCoordinator so a background @mention shares the project workspace exactly like
343
+ * foreground @codex — its native session then lives under a STABLE cwd (git or not) and resumes across
344
+ * delegations. Omitted everywhere else (per-task worktree isolation stays the default for parallel
345
+ * product/goal/solo tasks).
346
+ */
347
+ runInProjectCwd?: boolean;
348
+ /**
349
+ * P2-1: native (codex/claude) session id to RESUME for this delegation (ACP session/load), so repeated
350
+ * background @mention to the same (chat×agent) accumulates context — the background analogue of the
351
+ * foreground U4 resume. The DelegationCoordinator tracks it per (chat×agent): undefined on the first
352
+ * delegation (→ fresh session, whose id it then captures), the prior id thereafter. Validated by `has()`
353
+ * before use, so a stale id falls back to a fresh session. Git-independent (id, not cwd, drives reuse).
354
+ */
355
+ resumeNativeSessionId?: string;
340
356
  }
341
357
  /**
342
358
  * product.plan RPC params — starts an interactive planning session.
@@ -13,7 +13,7 @@
13
13
  * Turn-lifecycle events relayed to the Control UI WebSocket.
14
14
  * These are the "chat session" events that every UI client needs.
15
15
  */
16
- export declare const AGENT_WS_EVENT_NAMES: readonly ["turn.start", "turn.delta", "turn.end", "turn.error", "turn.recovery", "turn.file_changes", "turn.tool_call", "turn.tool_result", "turn.tool_blocked", "turn.reasoning_delta", "turn.approval_request", "turn.skill_instruction", "turn.ask_user", "turn.media_result", "turn.media_progress", "turn.media_usage", "turn.media_capability_check", "turn.plan_update", "turn.suggestions", "turn.sidechain_started", "turn.subagent_started", "turn.subagent_delta", "turn.subagent_ended", "turn.sidechain_completed", "turn.task_updated", "turn.todos_updated", "turn.exec_progress", "turn.progress", "turn.tool_use_summary", "turn.tool_selection_policy", "turn.lifecycle", "turn.document_maintenance", "turn.artifact_contract", "turn.usage_update", "team.member.notification", "session.info", "session.recovery_pending", "memory.updated", "skills.updated", "pet.soul_ready", "pet.reaction", "pet.growth", "pet.state", "pet.confirm", "pet.asset.updated", "system.activity", "workflow.created", "workflow.updated", "workflow.deleted", "workflow.runStarted", "workflow.runCompleted", "workflow.runFailed", "workflow.nodeStatus", "workflow.triggerDropped", "workflow.alert", "workflow.approvalRequested"];
16
+ export declare const AGENT_WS_EVENT_NAMES: readonly ["turn.start", "turn.delta", "turn.end", "turn.error", "turn.recovery", "turn.file_changes", "turn.tool_call", "turn.tool_result", "turn.tool_blocked", "turn.reasoning_delta", "turn.approval_request", "turn.skill_instruction", "turn.ask_user", "turn.media_result", "turn.media_progress", "turn.media_usage", "turn.media_capability_check", "turn.plan_update", "turn.suggestions", "turn.sidechain_started", "turn.subagent_started", "turn.subagent_delta", "turn.subagent_ended", "turn.sidechain_completed", "turn.task_updated", "turn.todos_updated", "turn.exec_progress", "turn.progress", "turn.tool_use_summary", "turn.tool_selection_policy", "turn.lifecycle", "turn.document_maintenance", "turn.artifact_contract", "turn.usage_update", "team.member.notification", "session.info", "session.recovery_pending", "memory.updated", "skills.updated", "pet.soul_ready", "pet.reaction", "pet.growth", "pet.state", "pet.confirm", "pet.asset.updated", "system.activity", "workflow.created", "workflow.updated", "workflow.deleted", "workflow.runStarted", "workflow.runCompleted", "workflow.runFailed", "workflow.nodeStatus", "workflow.triggerDropped", "workflow.alert", "workflow.approvalRequested", "workflow.approvalTimedOut"];
17
17
  /**
18
18
  * Agent Team events (Solo Mode, Product Mode, Plan lifecycle).
19
19
  * Relayed to the UI's team/orchestration panel.
@@ -23,7 +23,7 @@ export declare const AGENT_TEAM_WS_EVENT_NAMES: readonly ["solo.progress", "solo
23
23
  * All agent notifications that Gateway should relay to WS clients.
24
24
  * Union of session events + team events.
25
25
  */
26
- export declare const ALL_AGENT_WS_EVENT_NAMES: readonly ["turn.start", "turn.delta", "turn.end", "turn.error", "turn.recovery", "turn.file_changes", "turn.tool_call", "turn.tool_result", "turn.tool_blocked", "turn.reasoning_delta", "turn.approval_request", "turn.skill_instruction", "turn.ask_user", "turn.media_result", "turn.media_progress", "turn.media_usage", "turn.media_capability_check", "turn.plan_update", "turn.suggestions", "turn.sidechain_started", "turn.subagent_started", "turn.subagent_delta", "turn.subagent_ended", "turn.sidechain_completed", "turn.task_updated", "turn.todos_updated", "turn.exec_progress", "turn.progress", "turn.tool_use_summary", "turn.tool_selection_policy", "turn.lifecycle", "turn.document_maintenance", "turn.artifact_contract", "turn.usage_update", "team.member.notification", "session.info", "session.recovery_pending", "memory.updated", "skills.updated", "pet.soul_ready", "pet.reaction", "pet.growth", "pet.state", "pet.confirm", "pet.asset.updated", "system.activity", "workflow.created", "workflow.updated", "workflow.deleted", "workflow.runStarted", "workflow.runCompleted", "workflow.runFailed", "workflow.nodeStatus", "workflow.triggerDropped", "workflow.alert", "workflow.approvalRequested", "solo.progress", "solo.specProgress", "solo.agentDelta", "solo.agentActivity", "solo.agentUsage", "solo.evaluation", "product.taskStarted", "product.taskOutput", "product.members", "product.agentActivity", "product.taskCompleted", "product.taskFailed", "product.budgetUpdate", "product.budgetWarning", "product.checkpointed", "product.completed", "product.dagTopology", "plan.interrupted", "goal.run_state_changed", "goal.phase_boundary", "goal.goal_edited", "goal.message_queued", "goal.acceptance_updated"];
26
+ export declare const ALL_AGENT_WS_EVENT_NAMES: readonly ["turn.start", "turn.delta", "turn.end", "turn.error", "turn.recovery", "turn.file_changes", "turn.tool_call", "turn.tool_result", "turn.tool_blocked", "turn.reasoning_delta", "turn.approval_request", "turn.skill_instruction", "turn.ask_user", "turn.media_result", "turn.media_progress", "turn.media_usage", "turn.media_capability_check", "turn.plan_update", "turn.suggestions", "turn.sidechain_started", "turn.subagent_started", "turn.subagent_delta", "turn.subagent_ended", "turn.sidechain_completed", "turn.task_updated", "turn.todos_updated", "turn.exec_progress", "turn.progress", "turn.tool_use_summary", "turn.tool_selection_policy", "turn.lifecycle", "turn.document_maintenance", "turn.artifact_contract", "turn.usage_update", "team.member.notification", "session.info", "session.recovery_pending", "memory.updated", "skills.updated", "pet.soul_ready", "pet.reaction", "pet.growth", "pet.state", "pet.confirm", "pet.asset.updated", "system.activity", "workflow.created", "workflow.updated", "workflow.deleted", "workflow.runStarted", "workflow.runCompleted", "workflow.runFailed", "workflow.nodeStatus", "workflow.triggerDropped", "workflow.alert", "workflow.approvalRequested", "workflow.approvalTimedOut", "solo.progress", "solo.specProgress", "solo.agentDelta", "solo.agentActivity", "solo.agentUsage", "solo.evaluation", "product.taskStarted", "product.taskOutput", "product.members", "product.agentActivity", "product.taskCompleted", "product.taskFailed", "product.budgetUpdate", "product.budgetWarning", "product.checkpointed", "product.completed", "product.dagTopology", "plan.interrupted", "goal.run_state_changed", "goal.phase_boundary", "goal.goal_edited", "goal.message_queued", "goal.acceptance_updated"];
27
27
  /** Type-level event name for session events. */
28
28
  export type AgentWsEventName = (typeof AGENT_WS_EVENT_NAMES)[number];
29
29
  /** Type-level event name for team events. */
@@ -20,6 +20,8 @@ export interface AgentCapabilities {
20
20
  supportsResume: boolean;
21
21
  supportsUsageUpdate: boolean;
22
22
  skillsDirs?: string[];
23
+ /** 会话历史来源:native-cwd=有本地按 cwd 可发现的原生会话;省略/own=只显示自有会话 */
24
+ sessionHistory?: "native-cwd" | "own";
23
25
  }
24
26
  /** Descriptor for a discovered or registered agent. */
25
27
  export interface AgentDescriptor {
@@ -719,6 +721,7 @@ export interface AgentRpcMethodMap extends GatewayRpcMethodMap {
719
721
  params: {
720
722
  modelId: string;
721
723
  enabled: boolean;
724
+ purpose?: string;
722
725
  };
723
726
  result: {
724
727
  ok: true;
@@ -241,6 +241,7 @@ export interface GatewayRpcMethodMap {
241
241
  result: {
242
242
  messages: unknown[];
243
243
  total: number;
244
+ corruptLines?: number;
244
245
  };
245
246
  };
246
247
  "project.list": {
@@ -28,6 +28,8 @@ export interface StreamingToolExecutorConfig {
28
28
  toolInvoker: ToolInvoker;
29
29
  hooks?: HookRegistry;
30
30
  sessionId: string;
31
+ /** Turn workspace/cwd - routes oversized tool-result spillover to the session data dir. */
32
+ projectRoot?: string;
31
33
  turnId: string;
32
34
  log: AgentLogger;
33
35
  signal?: AbortSignal;
@@ -48,7 +48,7 @@ export declare function generatePreview(content: string, maxBytes: number): {
48
48
  preview: string;
49
49
  hasMore: boolean;
50
50
  };
51
- export declare function persistToolResult(content: string, toolCallId: string, sessionId: string): Promise<PersistedToolResult | null>;
51
+ export declare function persistToolResult(content: string, toolCallId: string, sessionId: string, projectRoot: string | undefined): Promise<PersistedToolResult | null>;
52
52
  /**
53
53
  * Build a reference message for large tool results (CC buildLargeToolResultMessage parity).
54
54
  */
@@ -58,7 +58,7 @@ export declare function buildLargeToolResultMessage(result: PersistedToolResult)
58
58
  * Falls back to hard truncation if persistence fails.
59
59
  * Called at tool execution time in streaming-tool-executor.ts.
60
60
  */
61
- export declare function maybePersistLargeToolResult(content: string, toolCallId: string, sessionId: string, threshold?: number): Promise<string>;
61
+ export declare function maybePersistLargeToolResult(content: string, toolCallId: string, sessionId: string, projectRoot: string | undefined, threshold?: number): Promise<string>;
62
62
  interface MessageLike {
63
63
  role: string;
64
64
  content?: string | unknown;
@@ -78,10 +78,12 @@ interface MessageLike {
78
78
  * replaced later (would break prompt cache).
79
79
  *
80
80
  * @param state — MUTATED in place (seenIds and replacements updated)
81
- * @returns messages with replacements applied + count of new replacements
81
+ * @returns messages with replacements applied + count of new replacements +
82
+ * total original bytes spilled this pass (so the caller can surface it)
82
83
  */
83
- export declare function enforceToolResultBudget(messages: MessageLike[], state: ContentReplacementState, sessionId: string, limit?: number): Promise<{
84
+ export declare function enforceToolResultBudget(messages: MessageLike[], state: ContentReplacementState, sessionId: string, projectRoot: string | undefined, limit?: number): Promise<{
84
85
  messages: MessageLike[];
85
86
  newlyReplacedCount: number;
87
+ newlyPersistedBytes: number;
86
88
  }>;
87
89
  export {};
@@ -6,13 +6,14 @@
6
6
  *
7
7
  * Reference: AionUI AcpDetector + ACP_BACKENDS_ALL registry.
8
8
  */
9
- import type { AcpBackendConfig, AgentDescriptor, AgentConfigStoreData, AuthPreference } from "../../protocol/wire/acp-agent-management.js";
9
+ import type { AcpBackendConfig, AgentDescriptor, CustomAgentDef, AgentConfigStoreData, AuthPreference } from "../../protocol/wire/acp-agent-management.js";
10
10
  export declare const ACP_BACKENDS: Record<string, AcpBackendConfig>;
11
11
  export declare const AGENT_CATALOG_IDS: readonly ["claude", "codex", "gemini", "copilot", "cursor", "qwen", "kimi", "glm", "opencode", "kiro", "qoder", "openclaw", "hermes"];
12
12
  /** Merged catalog entry (base ACP config + grid/install metadata) for one id. */
13
13
  export declare function getCatalogEntry(id: string): AcpBackendConfig | undefined;
14
14
  /** Ordered curated catalog: base ACP config merged with grid/install metadata. */
15
15
  export declare function getAgentCatalog(): AcpBackendConfig[];
16
+ export declare function buildInternalAgentDescriptors(): AgentDescriptor[];
16
17
  export declare function resolveWindowsCopilotLoader(): string | null;
17
18
  export declare function getNpmInstallPackageName(command: string | undefined): string | null;
18
19
  export declare function compareSemverVersions(a: string, b: string): number;
@@ -134,6 +135,24 @@ export declare function resolveCatalogKeyEnv(entry: AcpBackendConfig | undefined
134
135
  * Returns [] when not in account mode (or the agent has no account path — claude is coerced to auto).
135
136
  */
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;
137
156
  export declare class AcpDetector {
138
157
  private cache;
139
158
  private configStore;
@@ -176,13 +195,9 @@ export declare class AcpDetector {
176
195
  private detectBackend;
177
196
  /** Async, NON-BLOCKING twin of {@link detectBackend} — identical detection, async probes. */
178
197
  private detectBackendAsync;
179
- /** Build a backend's descriptor from already-resolved cliPath/version. Shared by the sync and async
180
- * detection paths so they can never drift (status rules, copilot's version-required gate, etc.). */
181
- private assembleBackendDescriptor;
182
198
  private detectCustomAgent;
183
199
  /** Async, NON-BLOCKING twin of {@link detectCustomAgent}. */
184
200
  private detectCustomAgentAsync;
185
- private assembleCustomAgentDescriptor;
186
201
  private hasAgentConfig;
187
202
  /**
188
203
  * Descriptor for qlogicagent participating in Solo/Product as a self-hosted ACP agent.
@@ -201,6 +216,21 @@ export declare class AcpDetector {
201
216
  * Returns null if the agent is not available.
202
217
  */
203
218
  buildExternalDescriptor(agentId: string): import("../../protocol/wire/acp-agent-management.js").ExternalAgentDescriptor | null;
219
+ /**
220
+ * Async, NON-BLOCKING twin of {@link buildExternalDescriptor} — identical output for the same
221
+ * detector state, but resolves the agent list via {@link scanAsync} (a real probe, awaited, when
222
+ * the cache is cold) instead of the sync {@link list}'s cache-or-empty shortcut. Load-bearing for
223
+ * `agents.warm` (agents-handler.ts): the sync path's detect calls are cache-fronted today, but
224
+ * that non-blocking guarantee is an implementation detail of `list()` — routing the RPC path
225
+ * through this method instead makes "never synchronously probe on this path" an explicit
226
+ * contract that can't silently regress if `list()`'s internals change later.
227
+ */
228
+ buildExternalDescriptorAsync(agentId: string): Promise<import("../../protocol/wire/acp-agent-management.js").ExternalAgentDescriptor | null>;
229
+ /** Shared descriptor-assembly logic for {@link buildExternalDescriptor} and
230
+ * {@link buildExternalDescriptorAsync} — everything AFTER "locate this agentId's AgentDescriptor
231
+ * in an already-resolved list", so the sync/async twins can never drift on behavior, only on how
232
+ * they obtain `agents`. */
233
+ private assembleExternalDescriptorFromAgents;
204
234
  /**
205
235
  * Whether an agent is ready to compete in Solo/Product: installed/available AND configured.
206
236
  * qlogicagent self-resolves from the owner profile (always ready). External agents need a usable
@@ -16,6 +16,12 @@
16
16
  */
17
17
  import type { ChildProcess } from "node:child_process";
18
18
  import type { AcpInitializeResult, AcpSessionResult, AcpPromptResponse, McpServerConfig } from "../../protocol/wire/acp-agent-management.js";
19
+ interface AcpPromptTimeoutOptions {
20
+ timeoutMs?: number;
21
+ getLastActivityAt?: () => number | undefined;
22
+ checkIntervalMs?: number;
23
+ }
24
+ type AcpPromptTimeoutInput = number | AcpPromptTimeoutOptions;
19
25
  /**
20
26
  * Handler for agent→host requests (fs, terminal, permission, elicitation).
21
27
  * Host implementations should implement the methods they support. This is intentionally loose
@@ -137,6 +143,7 @@ export declare class AcpProtocolAdapter {
137
143
  private requireConn;
138
144
  /** Race a connection call against a timeout; optionally run a side effect (e.g. cancel) on timeout. */
139
145
  private withTimeout;
146
+ private withActivityTimeout;
140
147
  /**
141
148
  * Perform the ACP initialize handshake. Sends standard clientInfo + clientCapabilities plus the
142
149
  * qlogicagent extension capability (forwarded verbatim by the SDK).
@@ -151,13 +158,26 @@ export declare class AcpProtocolAdapter {
151
158
  mcpServers?: McpServerConfig[];
152
159
  additionalDirectories?: string[];
153
160
  systemPrompt?: string;
161
+ /** Platform/managed model to select over ACP after session/new (see selectSessionModel). */
162
+ model?: string;
154
163
  }): Promise<AcpSessionResult>;
164
+ /**
165
+ * Select the platform/managed model over ACP after session/new. External CLIs (notably
166
+ * claude-code-acp) default to their OWN model (e.g. Sonnet 4.5) and merely EXPOSE the injected
167
+ * ANTHROPIC_MODEL/OPENAI_MODEL as an "available" option — they do NOT select it. Left on the default,
168
+ * the first prompt fails ("issue with the selected model …") because the platform shelf has no such
169
+ * model, and it surfaces as a cryptic "Agent process stdio closed". Best-effort: when the agent
170
+ * advertised its models, only switch if it offers `desired` and isn't already on it; otherwise attempt
171
+ * anyway and swallow rejection (the session still exists on its default model — the wrong-model prompt
172
+ * error is the backstop). Uses the generic sendRequest because the SDK has no typed set_model yet.
173
+ */
174
+ private selectSessionModel;
155
175
  /**
156
176
  * Send a prompt to a running ACP session (session/prompt). Content streams back via session/update
157
177
  * notifications during execution; the response carries only { stopReason, usage? }. On timeout the
158
178
  * turn is cancelled (session/cancel) so the agent stops cleanly.
159
179
  */
160
- sendPrompt(_child: ChildProcess, sessionId: string, content: string, timeoutMs?: number): Promise<AcpPromptResponse>;
180
+ sendPrompt(_child: ChildProcess, sessionId: string, content: string, timeoutInput?: AcpPromptTimeoutInput): Promise<AcpPromptResponse>;
161
181
  /**
162
182
  * Resume an existing ACP session (session/load — replays history via notifications).
163
183
  * Only valid when the agent advertised the loadSession capability.
@@ -165,6 +185,7 @@ export declare class AcpProtocolAdapter {
165
185
  resumeSession(_child: ChildProcess, sessionId: string, options?: {
166
186
  cwd?: string;
167
187
  mcpServers?: McpServerConfig[];
188
+ model?: string;
168
189
  }): Promise<AcpSessionResult>;
169
190
  /**
170
191
  * Translate an ACP notification into qlogicagent's internal format.
@@ -176,3 +197,4 @@ export declare class AcpProtocolAdapter {
176
197
  */
177
198
  static translateNotification(method: string, params: unknown): TranslatedNotification | null;
178
199
  }
200
+ export {};
@@ -52,6 +52,14 @@ export interface AgentProcessConfig {
52
52
  mcpServers?: McpServerConfig[];
53
53
  /** System prompt to inject into ACP session. */
54
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;
55
63
  }
56
64
  export declare function buildExternalAcpSpawnCommand(cliPath: string, acpArgs: string[]): {
57
65
  command: string;
@@ -296,6 +304,13 @@ export declare class AgentProcessManager {
296
304
  isAlive(memberId: string): boolean;
297
305
  /** Get usage tracker for an ACP agent (returns null for internal agents). */
298
306
  getUsageTracker(memberId: string): AcpUsageTracker | null;
307
+ /**
308
+ * The agent-assigned native session id (from ACP session/new or session/load) for a pooled member,
309
+ * once its session exists — undefined before creation. For native-cwd agents (codex/claude) this is
310
+ * the id under which the agent persists its OWN transcript (e.g. claude's ~/.claude uuid), distinct
311
+ * from the engine/stream id; used to converge on a single session identity (own/native unification).
312
+ */
313
+ getNativeSessionId(memberId: string): string | undefined;
299
314
  /**
300
315
  * Feed token usage into the tracker from a child notification (Tier 1). Handles all three shapes a
301
316
  * child may use so the tracker is actually populated:
@@ -44,6 +44,18 @@ export declare function poolKey(agentId: string, cwd: string, sessionId?: string
44
44
  export declare function getAlivePooledAgent(key: string): PooledAgentEntry | undefined;
45
45
  /** Register a freshly-spawned entry, evicting any stale same-key entry and enforcing MAX_POOL. */
46
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;
47
59
  /**
48
60
  * Re-key a pre-warmed entry (spawned before a session existed, under WARM_SESSION) onto the real
49
61
  * session key, so the first turn adopts the warmed process and skips the cold start. Does not