qlogicagent 2.16.2 → 2.16.4

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.
@@ -12,6 +12,10 @@ export interface ArtifactContractState {
12
12
  browserVerified: boolean;
13
13
  browserEvidence: string[];
14
14
  browserFailureEvidence: string[];
15
+ /** Build/test verification: a test/build/compile command ran and passed (exit 0). */
16
+ buildVerified: boolean;
17
+ buildEvidence: string[];
18
+ buildFailureEvidence: string[];
15
19
  }
16
20
  export interface ArtifactContractEventPayload {
17
21
  artifactRoot?: string;
@@ -34,6 +38,7 @@ export interface TaskContractItem {
34
38
  }
35
39
  export declare function createArtifactContractState(inputMessages: readonly ChatMessage[]): ArtifactContractState;
36
40
  export declare function requiresBrowserAcceptance(inputMessages: readonly ChatMessage[]): boolean;
41
+ export declare function requiresBuildVerification(inputMessages: readonly ChatMessage[]): boolean;
37
42
  export declare function requiresResearchQualityGate(inputMessages: readonly ChatMessage[]): boolean;
38
43
  export declare function hasFinalStatusContract(content: string): boolean;
39
44
  export declare function hasResearchQualityGate(content: string): boolean;
@@ -1,5 +1,5 @@
1
1
  import type { AgentLogger, ChatMessage, ThinkingBlock, ToolLoopTransition } from "../types.js";
2
- export type CompletionActionPolicyReason = "file_action_verification" | "explicit_required_file_verification" | "explicit_extra_file_verification" | "artifact_index_evidence_verification" | "multi_file_skeleton_verification";
2
+ export type CompletionActionPolicyReason = "file_action_verification" | "explicit_required_file_verification" | "explicit_extra_file_verification" | "artifact_index_evidence_verification" | "multi_file_skeleton_verification" | "forbidden_file_creation";
3
3
  export interface CompletionActionPolicyInput {
4
4
  inputMessages: readonly ChatMessage[];
5
5
  messages: unknown[];
@@ -34,5 +34,6 @@ export declare function buildPrematureCompletionArtifactBlock(input: {
34
34
  messages: unknown[];
35
35
  toolCall: CandidateToolCall;
36
36
  }): string | undefined;
37
+ export declare function findForbiddenCreatedFiles(inputMessages: readonly ChatMessage[], messages: unknown[]): string[];
37
38
  export declare function resolveCompletionActionPolicy(input: CompletionActionPolicyInput): CompletionActionPolicyDecision | null;
38
39
  export {};
@@ -18,7 +18,7 @@
18
18
  *
19
19
  * Zero imports from express/pg/ioredis/ws.
20
20
  */
21
- import type { AgentLogger, ChatMessage, ToolDefinition, ToolInvoker, TurnEvent, HookRegistry, LLMTransport } from "./types.js";
21
+ import type { AgentLogger, ChatMessage, ToolDefinition, ToolInvoker, TurnEvent, HookRegistry, LLMTransport, MaintainedDocumentIndex } from "./types.js";
22
22
  import type { ToolLoopRuntimePorts } from "../runtime/ports/index.js";
23
23
  export interface ToolLoopParams {
24
24
  turnId: string;
@@ -39,6 +39,11 @@ export interface ToolLoopParams {
39
39
  modelMaxOutputTokens?: number;
40
40
  /** Tool choice strategy (default "auto") */
41
41
  toolChoice?: "auto" | "none" | "required";
42
+ /**
43
+ * Build/test verification gate (lever ②). Default true. Set false to disable the
44
+ * "fix-and-rerun until the test/build passes" recovery — used for A/B measurement.
45
+ */
46
+ buildVerificationGate?: boolean;
42
47
  /** Parent fork depth (0 = top-level) */
43
48
  parentDepth?: number;
44
49
  /** Tool eligibility context for policy-based filtering */
@@ -101,6 +106,21 @@ export interface ToolLoopParams {
101
106
  runtimePorts: ToolLoopRuntimePorts;
102
107
  signal?: AbortSignal;
103
108
  }
109
+ /** Crossing this many actions on the SAME target within a turn flags a no-progress candidate. */
110
+ export declare const NO_PROGRESS_TARGET_THRESHOLD = 4;
111
+ /**
112
+ * [lever 3 — observe-only] Identify the "target" a tool call acts on, for churn counting:
113
+ * the file path for write/edit/patch, the normalized command for exec. Returns null for
114
+ * tools whose repetition isn't a stuck-signal (read, search, etc.). Exported for testing.
115
+ */
116
+ export declare function noProgressTargetKey(toolName: string, rawArguments: string): string | null;
117
+ export declare function buildBenchmarkStateMaintenanceInstruction(documents: ReadonlyMap<string, MaintainedDocumentIndex>, turn: number): string | null;
118
+ export declare function benchmarkStateMaintenanceWriteValidation(maintainedDocuments: ReadonlyMap<string, MaintainedDocumentIndex>, filePath: string, rawArguments: string): {
119
+ ok: true;
120
+ } | {
121
+ ok: false;
122
+ reason: string;
123
+ };
104
124
  /**
105
125
  * Execute the tool loop -CC query.ts queryLoop() aligned.
106
126
  *
@@ -7,5 +7,8 @@ export interface CliAcpRequestHandlerHost extends acpSession.AcpSessionHost {
7
7
  /** Id of the turn currently running; used to key cancel requests. */
8
8
  currentTurnId?: string;
9
9
  permissionChecker?: PermissionApprovalResolver | null;
10
+ /** LH-10: propagate an explicit cancel to the background tasks the given (or
11
+ * current) session launched. No-op if the host has no task registry. */
12
+ cancelBackgroundTasksForSession?(sessionId?: string): void;
10
13
  }
11
14
  export declare function createCliAcpRequestHandler(host: CliAcpRequestHandlerHost, packageVersion: string, extendedHost?: acpExtended.AcpExtendedHost): AcpRequestHandler;
@@ -11,6 +11,9 @@ export interface AgentToolServiceHost {
11
11
  readonly currentApiKey: string;
12
12
  readonly currentModel: string;
13
13
  readonly currentTurnId?: string;
14
+ /** Session id of the launching turn — stamped on background tasks so an
15
+ * explicit cancel can reach the work this session spawned (LH-10). */
16
+ readonly currentSessionId?: string;
14
17
  sendNotification(method: string, params: Record<string, unknown>): void;
15
18
  /** Unified background execution registry. Required for background=true forks. */
16
19
  getBackgroundTasks(): BackgroundTaskManager | null;
@@ -15,6 +15,9 @@ export interface ControlHandlerHost {
15
15
  sendResponse(id: string | number, result?: unknown, error?: AgentRpcError): void;
16
16
  sendNotification<M extends keyof NotificationMethodMap>(method: M, params: NotificationMethodMap[M]): void;
17
17
  ensureDefaultProject(): void;
18
+ /** LH-10: propagate an explicit cancel to the background tasks the current
19
+ * session launched. No-op if the host has no task registry. */
20
+ cancelBackgroundTasksForSession?(sessionId?: string): void;
18
21
  /** Actual registered RPC method names (single source of truth = the live registry), so the
19
22
  * initialize capability declaration never drifts from what's really handled. */
20
23
  getRegisteredMethods(): string[];
@@ -16,6 +16,7 @@ export type StdioAcpRequestHostSource = Pick<CliAcpRequestHandlerHost, "activeTu
16
16
  petRuntime: unknown;
17
17
  projectMemoryStoreFactory: unknown;
18
18
  toolCatalog: unknown;
19
+ cancelBackgroundTasksForSession(sessionId?: string): void;
19
20
  configureTurnMedia(config: Record<string, unknown> | undefined, turnId: string): void;
20
21
  drainPendingTaskNotifications(): string[];
21
22
  resolveAgent(config: unknown): unknown;
@@ -106,6 +106,11 @@ export declare class StdioServer {
106
106
  set currentSessionId(v: string);
107
107
  get currentTurnId(): string;
108
108
  set currentTurnId(v: string);
109
+ /** LH-10: an explicit cancel of a session stops the background tasks that
110
+ * session launched — the forked agent + the exec processes it spawned —
111
+ * instead of leaving them running as zombies. Keyed by session id, which is
112
+ * shared across the client/agent boundary (turn ids are not). */
113
+ cancelBackgroundTasksForSession(sessionId?: string): void;
109
114
  get sessionState(): SessionState | null;
110
115
  set sessionState(v: SessionState | null);
111
116
  get sessionLlmConfig(): SessionLlmConfig;
@@ -168,6 +168,9 @@ export interface AcpSessionPromptParams {
168
168
  export interface AcpSessionPromptResult {
169
169
  /** Stop reason (required by ACP standard). */
170
170
  stopReason: AcpStopReason;
171
+ /** Final assistant text for the turn (non-standard extension; emitted on end_turn). Lets the host
172
+ * read the completed message alongside the streamed session/update chunks. */
173
+ content?: string;
171
174
  /** Token usage for this turn. */
172
175
  usage?: AcpUsage;
173
176
  /** Model that actually ran the turn (agent-resolved). Lets the host attribute
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Background-task liveness context — AsyncLocalStorage progress signal (LH-6).
3
+ *
4
+ * A forked background agent's idle-reclaim window (BackgroundTaskManager) is
5
+ * pushed forward by markProgress on every SUBAGENT TURN EVENT (delta / tool
6
+ * call / tool result). But a single long-running exec emits its stdout/stderr
7
+ * as tool-INTERNAL chunks, not turn events — so a 12-minute build that prints
8
+ * steadily would otherwise look idle and be wrongly reclaimed.
9
+ *
10
+ * The background runner stores its markProgress callback here (for the whole
11
+ * async subtree of the fork); exec progress calls signalBackgroundProgress() on
12
+ * every output chunk to push the window forward, so any actively-producing exec
13
+ * keeps its enclosing background task alive even between turn events.
14
+ *
15
+ * No-op at top level (no enclosing background runner) — a foreground exec just
16
+ * finds an empty store.
17
+ */
18
+ /** Run fn with a liveness callback bound for the current async subtree. */
19
+ export declare function runWithBackgroundProgress<T>(onProgress: () => void, fn: () => T): T;
20
+ /** Signal liveness to the enclosing background runner, if any. No-op at top level. */
21
+ export declare function signalBackgroundProgress(): void;
@@ -138,6 +138,9 @@ export declare class AcpDetector {
138
138
  private cache;
139
139
  private configStore;
140
140
  private keySources;
141
+ /** Shared in-flight async scan so concurrent scanAsync() callers (startup warm + a racing RPC)
142
+ * collapse onto ONE scan instead of each spawning its own probe storm. Cleared when it settles. */
143
+ private scanInFlight;
141
144
  /**
142
145
  * Provide the config store data so detector can populate `hasConfig` field
143
146
  * and include user-registered custom agents.
@@ -150,12 +153,32 @@ export declare class AcpDetector {
150
153
  * @param force - Clear cache and re-scan.
151
154
  */
152
155
  scan(force?: boolean): AgentDescriptor[];
156
+ /**
157
+ * Async, NON-BLOCKING twin of {@link scan}. Probes every backend CONCURRENTLY off the event loop
158
+ * (async `where`/`which` + version probes), so the engine's single-threaded loop keeps servicing
159
+ * ACP requests while detection runs — fixing the bug where a cold synchronous scan (11–18s here,
160
+ * 60s+ with more/slower CLIs) starved an already-dispatched `x/product.confirm` until it tripped
161
+ * the UI's 60s timeout. Populates the SAME cache as scan(), so a later sync list()/scan(false)
162
+ * returns instantly. Concurrent callers share one in-flight scan ({@link scanInFlight}).
163
+ *
164
+ * @param force - Bypass the fresh-cache short-circuit and re-probe.
165
+ */
166
+ scanAsync(force?: boolean): Promise<AgentDescriptor[]>;
167
+ private runScanAsync;
153
168
  /** Return cached results without IO. */
154
169
  list(): AgentDescriptor[];
155
170
  /** Clear the detection cache. */
156
171
  clearCache(): void;
157
172
  private detectBackend;
173
+ /** Async, NON-BLOCKING twin of {@link detectBackend} — identical detection, async probes. */
174
+ private detectBackendAsync;
175
+ /** Build a backend's descriptor from already-resolved cliPath/version. Shared by the sync and async
176
+ * detection paths so they can never drift (status rules, copilot's version-required gate, etc.). */
177
+ private assembleBackendDescriptor;
158
178
  private detectCustomAgent;
179
+ /** Async, NON-BLOCKING twin of {@link detectCustomAgent}. */
180
+ private detectCustomAgentAsync;
181
+ private assembleCustomAgentDescriptor;
159
182
  private hasAgentConfig;
160
183
  /**
161
184
  * Descriptor for qlogicagent participating in Solo/Product as a self-hosted ACP agent.
@@ -38,6 +38,17 @@ export interface StartAgentTaskOptions {
38
38
  depth: number;
39
39
  maxTurns: number;
40
40
  parentTaskId?: string;
41
+ /** Session that launched this task (LH-10: an explicit cancel propagates to the
42
+ * background work that session spawned). Keyed by session — turn ids don't
43
+ * cross the client/agent boundary, session ids do. */
44
+ launchSessionId?: string;
45
+ /**
46
+ * Idle (no-progress) reclaim window (ms): the task is force-failed as `timeout`
47
+ * only after `idleMs` with no progress signal — an actively-producing task is
48
+ * never reclaimed (LH-6). Defaults to DEFAULT_FORKED_AGENT_IDLE_MS; pass
49
+ * Infinity / <= 0 to disable.
50
+ */
51
+ idleMs?: number;
41
52
  /** The actual work. Receives the task's own abort signal and task id. */
42
53
  run(signal: AbortSignal, taskId: string): Promise<AgentRunOutcome>;
43
54
  }
@@ -68,11 +79,23 @@ export interface ExternalTaskControl {
68
79
  }
69
80
  export declare class BackgroundTaskManager {
70
81
  private readonly store;
82
+ /** LH-10: resolves the active session id for tasks registered without an
83
+ * explicit launchSessionId (e.g. a backgrounded shell from a sub-agent's
84
+ * exec) so an explicit cancel can still reach them. */
85
+ private readonly getCurrentSessionId?;
71
86
  private readonly controllers;
72
87
  private readonly bashHandles;
73
88
  private readonly externalControls;
89
+ private readonly deadlineTimers;
90
+ /** LH-6: last liveness signal + window per task — drives idle (no-progress) reclaim. */
91
+ private readonly lastProgressAt;
92
+ private readonly idleReclaimMs;
74
93
  private readonly settledListeners;
75
- constructor(store: TaskStore);
94
+ constructor(store: TaskStore,
95
+ /** LH-10: resolves the active session id for tasks registered without an
96
+ * explicit launchSessionId (e.g. a backgrounded shell from a sub-agent's
97
+ * exec) so an explicit cancel can still reach them. */
98
+ getCurrentSessionId?: (() => string | undefined) | undefined);
76
99
  /** Subscribe to natural task settlement (completed/failed). Returns unregister fn. */
77
100
  onTaskSettled(listener: (task: TaskState) => void): () => void;
78
101
  private fireSettled;
@@ -108,8 +131,44 @@ export declare class BackgroundTaskManager {
108
131
  */
109
132
  readOutput(taskId: string): Promise<TaskOutputSnapshot | null>;
110
133
  /**
111
- * Cancel a running task: kills the shell process / aborts the agent,
112
- * then marks the task cancelled. Returns false if not found or already terminal.
134
+ * Kill/abort whichever executor backs a task (bash handle, forked-agent abort
135
+ * controller, or external control) and drop its registry entry. Shared by
136
+ * cancelTask (user/turn cancel) and enforceTimeout (deadline).
137
+ */
138
+ private teardownExecutors;
139
+ /**
140
+ * Arm an idle (no-progress) reclaim window for a task (LH-6). The task is only
141
+ * force-failed as `timeout` after it goes fully silent — no output, no tool
142
+ * activity, no progress signal — for `idleMs`. A task that keeps producing is
143
+ * kept alive INDEFINITELY (markProgress resets the window), so a slow-but-working
144
+ * fork (deep research, a large build) is never killed; only a leaked runner
145
+ * promise, a dead subprocess, or a stuck-with-no-output loop is reclaimed. This
146
+ * is what distinguishes a dead task from a slow one — a fixed absolute deadline
147
+ * cannot. No-op for non-positive / non-finite windows.
148
+ */
149
+ private armIdleReclaim;
150
+ /**
151
+ * Record a liveness signal (a subagent event, output growth, etc.). Pushes the
152
+ * idle reclaim window forward so an actively-working task is never reclaimed.
153
+ * O(1) — only stamps the time; the timer re-checks the elapsed idle on expiry.
154
+ */
155
+ markProgress(taskId: string): void;
156
+ private scheduleIdleCheck;
157
+ private onIdleCheck;
158
+ private clearDeadline;
159
+ private enforceIdleTimeout;
160
+ /**
161
+ * Cancel a running task: kills the shell process / aborts the agent, then marks
162
+ * the task cancelled. Returns false if not found or already terminal.
113
163
  */
114
164
  cancelTask(taskId: string): boolean;
165
+ /**
166
+ * Cancel every still-running task launched by `sessionId` (LH-10). An explicit
167
+ * user cancel propagates to the background work that session spawned — unlike a
168
+ * superseded-turn abort or a natural turn-end, which leave background tasks
169
+ * running. Returns the ids actually cancelled.
170
+ */
171
+ cancelTasksForSession(sessionId: string): string[];
172
+ /** Cancel every non-terminal task (session teardown). Returns cancelled ids. */
173
+ cancelAllRunning(): string[];
115
174
  }
@@ -9,6 +9,16 @@ interface CatalogFetchOptions {
9
9
  export declare class LlmrouterCatalogUnavailableError extends Error {
10
10
  constructor(message?: string);
11
11
  }
12
+ /**
13
+ * Raised when the llmrouter published endpoint (/v1/models) rejects the inference key with an
14
+ * auth failure (401/403). This is a PERSISTENT condition (revoked/expired/inactive key), unlike a
15
+ * transient network blip — so callers must NOT fall back to the full routable catalog (that would
16
+ * advertise 600+ models the dead key cannot actually call). Surface "please re-authenticate" instead.
17
+ */
18
+ export declare class LlmrouterAuthError extends Error {
19
+ readonly status: number;
20
+ constructor(status: number, message?: string);
21
+ }
12
22
  export interface LlmrouterCatalogProvider {
13
23
  id: string;
14
24
  name?: string;
@@ -35,6 +35,11 @@ export declare function createTaskGuidanceSection(domain?: TaskDomain): SystemPr
35
35
  * Tells the LLM when to use specialized tools vs. primitives.
36
36
  */
37
37
  export declare function createToolGuidanceSection(): SystemPromptSection;
38
+ type DeferredIndexEntry = {
39
+ name: string;
40
+ description: string;
41
+ searchHint?: string;
42
+ };
38
43
  /**
39
44
  * Render the deferred-tool listing with accuracy-aware token discipline.
40
45
  *
@@ -48,10 +53,7 @@ export declare function createToolGuidanceSection(): SystemPromptSection;
48
53
  * details on demand).
49
54
  * Names are ALWAYS listed so any capability can be `select:`ed directly.
50
55
  */
51
- export declare function buildDeferredToolIndexBody(deferred: Array<{
52
- name: string;
53
- description: string;
54
- }>, richHintLimit: number): string[];
56
+ export declare function buildDeferredToolIndexBody(deferred: DeferredIndexEntry[], richHintLimit: number): string[];
55
57
  /**
56
58
  * Index of deferred tools so the model KNOWS these capabilities exist even
57
59
  * though their schemas are not loaded. Without this the model sees only the
@@ -61,10 +63,7 @@ export declare function buildDeferredToolIndexBody(deferred: Array<{
61
63
  * dynamic registrations (MCP, session bootstrap) land; the rendered text is
62
64
  * stable across turns otherwise, so prompt cache is preserved in practice.
63
65
  */
64
- export declare function createDeferredToolIndexSection(listDeferredTools: () => Array<{
65
- name: string;
66
- description: string;
67
- }>, options?: {
66
+ export declare function createDeferredToolIndexSection(listDeferredTools: () => DeferredIndexEntry[], options?: {
68
67
  richHintLimit?: number;
69
68
  }): SystemPromptSection;
70
69
  /**
@@ -88,3 +87,4 @@ export declare function createLanguageSection(language?: string): SystemPromptSe
88
87
  * fallback handle English/other, which weak models already mirror fine).
89
88
  */
90
89
  export declare function detectResponseLanguage(userText: string): string | undefined;
90
+ export {};
@@ -65,6 +65,11 @@ export interface TaskStateBase {
65
65
  lifecycle: TaskLifecycle;
66
66
  /** Parent task ID (for nested sub-agents). */
67
67
  parentTaskId?: string;
68
+ /** Session that launched this task — lets an explicit cancel propagate to the
69
+ * background work that session spawned (LH-10). Keyed by session, not turn:
70
+ * the client and agent mint turn ids in separate namespaces (they never match),
71
+ * but the session id is shared across the boundary. */
72
+ launchSessionId?: string;
68
73
  /** Execution depth (0 = root). */
69
74
  depth: number;
70
75
  /** Maximum turns before forced stop. */
@@ -11,3 +11,18 @@ export declare function missingRequiredStringParam(params: Record<string, unknow
11
11
  allowEmpty?: boolean;
12
12
  }): string | null;
13
13
  export declare function invalidFileToolArguments(type: "read" | "write" | "edit", message: string): PortableToolResult;
14
+ /**
15
+ * Turn a raw filesystem error (ENOENT/EISDIR/EACCES/…) into a structured, ACTIONABLE
16
+ * tool result. A bare "ENOENT: no such file or directory, open '…'" tells the model
17
+ * nothing it can act on; this names the path and the concrete recovery step, so the
18
+ * model self-corrects instead of thrashing. Shared by read/write/edit.
19
+ */
20
+ export declare function fileSystemErrorResult(type: "read" | "write" | "edit", resolvedPath: string, error: unknown): PortableToolResult;
21
+ /**
22
+ * LH-3: validate-before-write for structured artifacts. If `path` targets a
23
+ * `.json` file, its content MUST parse as JSON — otherwise a write/patch could
24
+ * persist a corrupt state file (continuity-checkpoint.json / document-index.json
25
+ * etc.) that the next reopen depends on, silently breaking reconstruction.
26
+ * Returns a human-readable error reason, or null when OK (or the path is not JSON).
27
+ */
28
+ export declare function jsonWriteValidationError(path: string, content: string): string | null;
@@ -43,3 +43,10 @@ export declare function commandHasAnyCd(command: string): boolean;
43
43
  */
44
44
  export declare function classifyCommand(command: string): CommandClassification;
45
45
  export declare function requiresDedicatedReadSearchTool(classification: CommandClassification): boolean;
46
+ /**
47
+ * Actionable, command-type-specific redirect for a blocked exec command. Spelling out the
48
+ * exact dedicated tool (read for file contents, search for content lookup) lets the model
49
+ * self-correct instead of retrying the same blocked command into a recovery stop. Only
50
+ * called for reads/searches now (directory listing is allowed via exec — see above).
51
+ */
52
+ export declare function dedicatedToolRedirectMessage(classification: CommandClassification): string;
@@ -4,7 +4,9 @@ import { type ProgressCallback } from "./task-output.js";
4
4
  import type { SandboxConfig } from "./sandbox/sandbox-types.js";
5
5
  export type { ExecResult } from "./shell-command.js";
6
6
  export declare function getCwd(): string;
7
- export declare function setCwd(path: string, relativeTo?: string): void;
7
+ export declare function setCwd(path: string, relativeTo?: string, opts?: {
8
+ mustExist?: boolean;
9
+ }): boolean;
8
10
  export declare function getOriginalCwd(): string;
9
11
  export declare function initCwd(cwd: string): void;
10
12
  export interface ExecOptions {
@@ -0,0 +1,9 @@
1
+ import type { ToolSearchCorpusEntry } from "./tool-search-tool.js";
2
+ import type { ToolSelectionCase } from "./tool-selection-eval.js";
3
+ export declare const TASK_CORPUS: ToolSearchCorpusEntry[];
4
+ export declare const EN_CASES: ToolSelectionCase[];
5
+ export declare const CN_CASES: ToolSelectionCase[];
6
+ export declare const ALL_CASES: ToolSelectionCase[];
7
+ export declare const HELDOUT_CASES: ToolSelectionCase[];
8
+ export declare const NEGATIVE_CASES: ToolSelectionCase[];
9
+ export declare const DECIRC_CASES: ToolSelectionCase[];
@@ -10,6 +10,15 @@ import type { PortableTool } from "./portable-tool.js";
10
10
  import type { ToolDefinition } from "../protocol/wire/index.js";
11
11
  import { AGENT_DISALLOWED_TOOLS, CUSTOM_AGENT_DISALLOWED_TOOLS, filterToolsForAgent } from "./tool-access.js";
12
12
  export { AGENT_DISALLOWED_TOOLS, CUSTOM_AGENT_DISALLOWED_TOOLS, filterToolsForAgent };
13
+ /**
14
+ * Deferral policy (CC-aligned): a few HIGH-FREQUENCY capabilities stay LOADED even if their
15
+ * factory marks them deferrable, so the model never has to voluntarily tool_search for the
16
+ * things users ask for most. Only the long tail (rare media variants, niche tools) and MCP
17
+ * stay deferred. Trades a small always-on token cost on common paths for discovery
18
+ * reliability — mirrors Claude Code (keeps common tools loaded; defers only the long
19
+ * tail / large MCP sets) rather than relying on the model to decide to search.
20
+ */
21
+ export declare const COMMON_LOADED_CAPABILITIES: Set<string>;
13
22
  export declare class ToolRegistry {
14
23
  private readonly toolPool;
15
24
  private readonly activatedTools;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qlogicagent",
3
- "version": "2.16.2",
3
+ "version": "2.16.4",
4
4
  "description": "XiaozhiClaw Agent CLI — subprocess architecture (JSON-RPC over stdio)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -91,7 +91,7 @@
91
91
  "@agentclientprotocol/sdk": "^0.25.0",
92
92
  "@napi-rs/canvas": "0.1.100",
93
93
  "@xiaozhiclaw/pet-core": "0.1.2",
94
- "@xiaozhiclaw/provider-core": "^0.1.19",
94
+ "@xiaozhiclaw/provider-core": "^0.1.20",
95
95
  "better-sqlite3": "^12.10.0",
96
96
  "dotenv": "^17.3.1",
97
97
  "ioredis": "^5.11.1",