@tencent-ai/agent-sdk 0.3.147 → 0.3.150

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/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-ai/codebuddy-code",
3
- "version": "2.95.1",
3
+ "version": "2.97.0",
4
4
  "description": "Use CodeBuddy, Tencent's AI assistant, right from your terminal. CodeBuddy can understand your codebase, edit files, run terminal commands, and handle entire workflows for you.",
5
5
  "main": "lib/node/index.js",
6
6
  "typings": "lib/node/index.d.ts",
@@ -110,6 +110,9 @@
110
110
  "tools": [
111
111
  "Read"
112
112
  ],
113
+ "commands": [
114
+ "_compact"
115
+ ],
113
116
  "tags": [
114
117
  "cli",
115
118
  "compact"
@@ -407,8 +410,9 @@
407
410
  "DeferToolLoading": true,
408
411
  "ImageGen": true,
409
412
  "ScheduledTasks": true,
410
- "SkillManage": false
413
+ "SkillManage": false,
414
+ "SelectImage": true
411
415
  },
412
- "commit": "8e49c921711de49156059cd1c5e35e11e28423ba",
413
- "date": "2026-05-07T12:47:07.850Z"
416
+ "commit": "128246570576896f27eea5952184b086b997c167",
417
+ "date": "2026-05-13T06:44:47.289Z"
414
418
  }
@@ -118,6 +118,9 @@
118
118
  "tools": [
119
119
  "Read"
120
120
  ],
121
+ "commands": [
122
+ "_compact"
123
+ ],
121
124
  "tags": [
122
125
  "cli",
123
126
  "compact"
@@ -594,6 +597,6 @@
594
597
  }
595
598
  }
596
599
  },
597
- "commit": "8e49c921711de49156059cd1c5e35e11e28423ba",
598
- "date": "2026-05-07T12:47:07.849Z"
600
+ "commit": "128246570576896f27eea5952184b086b997c167",
601
+ "date": "2026-05-13T06:44:47.289Z"
599
602
  }
@@ -141,6 +141,9 @@
141
141
  "tools": [
142
142
  "Read"
143
143
  ],
144
+ "commands": [
145
+ "_compact"
146
+ ],
144
147
  "tags": [
145
148
  "cli",
146
149
  "compact"
@@ -945,6 +948,6 @@
945
948
  }
946
949
  }
947
950
  },
948
- "commit": "8e49c921711de49156059cd1c5e35e11e28423ba",
949
- "date": "2026-05-07T12:47:07.855Z"
951
+ "commit": "128246570576896f27eea5952184b086b997c167",
952
+ "date": "2026-05-13T06:44:47.278Z"
950
953
  }
package/cli/product.json CHANGED
@@ -505,7 +505,7 @@
505
505
  },
506
506
  {
507
507
  "name": "terminal-title-generator-instructions",
508
- "template": "You are a topic analyzer. Your ONLY purpose is to identify conversation topics.\n\nYour job:\n1. Read the user message\n2. Determine if it starts a NEW conversation topic (compared to previous context if any)\n3. If yes, extract a 2-3 word title for the topic\n\nCRITICAL CONSTRAINTS:\n- You are NOT a code generator, writer, or task executor\n- You MUST respond ONLY with JSON in this exact format:\n {\"isNewTopic\": boolean, \"title\": string or null}\n- NEVER generate, implement, code, or produce any content\n- NEVER provide explanations, reasoning, or extra text\n- NEVER engage with the user's actual request beyond identifying the topic\n\nExamples:\nUser: \"Can you build an HTML5 game?\" → {\"isNewTopic\": true, \"title\": \"Game Development\"}\nUser: \"Add more features\" → {\"isNewTopic\": false, \"title\": null}\n\nReturn only the JSON object. Nothing else.\n"
508
+ "template": "You are a topic analyzer. Your ONLY purpose is to identify conversation topics.\n\nYour job:\n1. Read the user message\n2. Determine if it starts a NEW conversation topic (compared to previous context if any)\n3. If yes, extract a 2-3 word title for the topic\n\nCRITICAL CONSTRAINTS:\n- You are NOT a code generator, writer, or task executor\n- You MUST respond ONLY with JSON in this exact format:\n {\"isNewTopic\": boolean, \"title\": string or null}\n- NEVER generate, implement, code, or produce any content\n- NEVER provide explanations, reasoning, or extra text\n- NEVER engage with the user's actual request beyond identifying the topic\n\nExamples:\nUser: \"Can you build an HTML5 game?\" → {\"isNewTopic\": true, \"title\": \"Game Development\"}\nUser: \"Add more features\" → {\"isNewTopic\": false, \"title\": null}\n\nReturn only the JSON object. Nothing else.\n{%- if language -%}\n\nIMPORTANT: The `title` field MUST be written in {{language}}. Do not use English for the title value even though these instructions are in English. The JSON structure itself (field names, boolean values) stays unchanged.\n{%- endif -%}\n"
509
509
  },
510
510
  {
511
511
  "name": "memory-selector-instructions",
@@ -945,6 +945,9 @@
945
945
  "tools": [
946
946
  "Read"
947
947
  ],
948
+ "commands": [
949
+ "_compact"
950
+ ],
948
951
  "tags": [
949
952
  "cli",
950
953
  "compact"
@@ -1128,6 +1131,11 @@
1128
1131
  "compact-agent"
1129
1132
  ]
1130
1133
  },
1134
+ {
1135
+ "name": "_compact",
1136
+ "description": "Clear conversation history but keep a summary in context. Optional: /compact [instructions for summarization]",
1137
+ "prompt": "compact-prompt"
1138
+ },
1131
1139
  {
1132
1140
  "name": "upgrade",
1133
1141
  "description": "Open upgrade page in browser"
@@ -1519,6 +1527,6 @@
1519
1527
  "description": "Send a reply to a WeCom (企业微信) user. For text: pass text (markdown supported)."
1520
1528
  }
1521
1529
  ],
1522
- "commit": "8e49c921711de49156059cd1c5e35e11e28423ba",
1523
- "date": "2026-05-07T12:47:07.849Z"
1530
+ "commit": "128246570576896f27eea5952184b086b997c167",
1531
+ "date": "2026-05-13T06:44:47.294Z"
1524
1532
  }
@@ -104,6 +104,9 @@
104
104
  "tools": [
105
105
  "Read"
106
106
  ],
107
+ "commands": [
108
+ "_compact"
109
+ ],
107
110
  "tags": [
108
111
  "cli",
109
112
  "compact"
@@ -296,6 +299,6 @@
296
299
  "DeferToolLoading": true,
297
300
  "ScheduledTasks": true
298
301
  },
299
- "commit": "8e49c921711de49156059cd1c5e35e11e28423ba",
300
- "date": "2026-05-07T12:47:07.850Z"
302
+ "commit": "128246570576896f27eea5952184b086b997c167",
303
+ "date": "2026-05-13T06:44:47.285Z"
301
304
  }
Binary file
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Owns control protocol bookkeeping (initialize + hook/permission/mcp routing)
3
+ * shared by ``query()`` and ``createSession()``.
4
+ */
5
+ import type { Transport } from '../transport';
6
+ import type { AgentDefinition, CanUseTool, ControlInitializeRequest, ControlInitializeResponse, ControlRequest, HookCallbackMatcher, HookEvent } from '../types';
7
+ export interface InitializePayloadOptions {
8
+ /** SDK-defined agent definitions (sent via initialize control_request) */
9
+ agents?: Record<string, AgentDefinition>;
10
+ /** Override the default system prompt (string), or append (object) */
11
+ systemPrompt?: string | {
12
+ append: string;
13
+ };
14
+ /** Predefined environment for selfhosted authentication */
15
+ environment?: ControlInitializeRequest['environment'];
16
+ /** Custom endpoint URL for selfhosted environment */
17
+ endpoint?: ControlInitializeRequest['endpoint'];
18
+ /** Whether a prompt is going to follow this initialize (controls history replay) */
19
+ hasPrompt: boolean;
20
+ }
21
+ export declare class QueryController {
22
+ private readonly transport;
23
+ private readonly canUseToolGetter;
24
+ private readonly abortSignalGetter;
25
+ private hookCallbacks;
26
+ private registeredHooks?;
27
+ constructor(transport: Transport, hooks: Partial<Record<HookEvent, HookCallbackMatcher[]>> | undefined, canUseToolGetter: () => CanUseTool | undefined, abortSignalGetter: () => AbortSignal);
28
+ initialize(opts: InitializePayloadOptions): Promise<ControlInitializeResponse>;
29
+ handleControlRequest(request: ControlRequest): Promise<void>;
30
+ private handlePermissionRequest;
31
+ private handleHookCallback;
32
+ /**
33
+ * Replace the registered hook callbacks. The hook event structure (events,
34
+ * matchers) was sent to CLI during initialize() — this just rewires the
35
+ * callback functions for existing hook IDs.
36
+ */
37
+ setHooks(hooks: Partial<Record<HookEvent, HookCallbackMatcher[]>> | undefined): void;
38
+ private registerHooks;
39
+ private buildHooksConfig;
40
+ }
41
+ //# sourceMappingURL=query-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-controller.d.ts","sourceRoot":"","sources":["../../src/_internal/query-controller.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACR,eAAe,EACf,UAAU,EAEV,wBAAwB,EACxB,yBAAyB,EAEzB,cAAc,EACd,mBAAmB,EACnB,SAAS,EAKZ,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,wBAAwB;IACrC,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,2DAA2D;IAC3D,WAAW,CAAC,EAAE,wBAAwB,CAAC,aAAa,CAAC,CAAC;IACtD,qDAAqD;IACrD,QAAQ,CAAC,EAAE,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAChD,oFAAoF;IACpF,SAAS,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,eAAe;IAQpB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAG1B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAIjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAdtC,OAAO,CAAC,aAAa,CAGP;IACd,OAAO,CAAC,eAAe,CAAC,CAAoD;gBAGvD,SAAS,EAAE,SAAS,EACrC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,mBAAmB,EAAE,CAAC,CAAC,GAAG,SAAS,EAEnD,gBAAgB,EAAE,MAAM,UAAU,GAAG,SAAS,EAI9C,iBAAiB,EAAE,MAAM,WAAW;IAOnD,UAAU,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA8B9E,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;YAUpD,uBAAuB;YA4DvB,kBAAkB;IAsBhC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,mBAAmB,EAAE,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI;IAMpF,OAAO,CAAC,aAAa;IAmBrB,OAAO,CAAC,gBAAgB;CAoB3B"}
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ /**
3
+ * Owns control protocol bookkeeping (initialize + hook/permission/mcp routing)
4
+ * shared by ``query()`` and ``createSession()``.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.QueryController = void 0;
8
+ class QueryController {
9
+ constructor(transport, hooks,
10
+ // Lazy: Session may swap canUseTool at runtime via setCanUseTool().
11
+ canUseToolGetter,
12
+ // Lazy: Session replaces its AbortController after an interrupt+continue cycle
13
+ // (see SessionImpl.send) — a captured reference would dispatch hook / canUseTool
14
+ // callbacks with a stale, already-aborted signal.
15
+ abortSignalGetter) {
16
+ this.transport = transport;
17
+ this.canUseToolGetter = canUseToolGetter;
18
+ this.abortSignalGetter = abortSignalGetter;
19
+ this.hookCallbacks = new Map();
20
+ this.registerHooks(hooks);
21
+ }
22
+ // ============= Initialize =============
23
+ async initialize(opts) {
24
+ const systemPrompt = typeof opts.systemPrompt === 'string'
25
+ ? opts.systemPrompt
26
+ : undefined;
27
+ const appendSystemPrompt = typeof opts.systemPrompt === 'object'
28
+ ? opts.systemPrompt.append
29
+ : undefined;
30
+ const sdkMcpServerNames = this.transport.sdkMcpServerNames;
31
+ const initRequest = {
32
+ subtype: 'initialize',
33
+ hooks: this.buildHooksConfig(),
34
+ systemPrompt,
35
+ appendSystemPrompt,
36
+ agents: opts.agents,
37
+ sdkMcpServers: sdkMcpServerNames.length > 0 ? sdkMcpServerNames : undefined,
38
+ environment: opts.environment,
39
+ endpoint: opts.endpoint,
40
+ capabilities: {
41
+ askUserQuestion: true,
42
+ },
43
+ hasPrompt: opts.hasPrompt,
44
+ };
45
+ return this.transport.sendControlRequest(initRequest);
46
+ }
47
+ // ============= Control request routing =============
48
+ async handleControlRequest(request) {
49
+ const { subtype } = request.request;
50
+ if (subtype === 'hook_callback') {
51
+ await this.handleHookCallback(request);
52
+ }
53
+ else if (subtype === 'can_use_tool') {
54
+ await this.handlePermissionRequest(request);
55
+ }
56
+ // mcp_message is handled at the transport level
57
+ }
58
+ async handlePermissionRequest(request) {
59
+ const permRequest = request.request;
60
+ const { tool_name, input, tool_use_id, agent_id, permission_suggestions, blocked_path, decision_reason, } = permRequest;
61
+ const canUseTool = this.canUseToolGetter();
62
+ if (!canUseTool) {
63
+ this.transport.sendControlResponse(request.request_id, {
64
+ allowed: false,
65
+ reason: 'No permission handler provided',
66
+ tool_use_id,
67
+ });
68
+ return;
69
+ }
70
+ try {
71
+ const result = await canUseTool(tool_name, input, {
72
+ signal: this.abortSignalGetter(),
73
+ suggestions: permission_suggestions,
74
+ blockedPath: blocked_path,
75
+ decisionReason: decision_reason,
76
+ toolUseID: tool_use_id,
77
+ agentID: agent_id,
78
+ });
79
+ if (result.behavior === 'allow') {
80
+ this.transport.sendControlResponse(request.request_id, {
81
+ allowed: true,
82
+ updatedInput: result.updatedInput,
83
+ tool_use_id,
84
+ });
85
+ }
86
+ else {
87
+ this.transport.sendControlResponse(request.request_id, {
88
+ allowed: false,
89
+ reason: result.message,
90
+ interrupt: result.interrupt,
91
+ tool_use_id,
92
+ });
93
+ }
94
+ }
95
+ catch (error) {
96
+ this.transport.sendControlResponse(request.request_id, {
97
+ allowed: false,
98
+ reason: error instanceof Error ? error.message : String(error),
99
+ tool_use_id,
100
+ });
101
+ }
102
+ }
103
+ async handleHookCallback(request) {
104
+ const { callback_id, input, tool_use_id } = request.request;
105
+ const callback = this.hookCallbacks.get(callback_id);
106
+ let response = { continue: true };
107
+ if (callback) {
108
+ try {
109
+ response = await callback(input, tool_use_id, { signal: this.abortSignalGetter() });
110
+ }
111
+ catch (error) {
112
+ response = {
113
+ continue: false,
114
+ stopReason: error instanceof Error ? error.message : String(error),
115
+ };
116
+ }
117
+ }
118
+ this.transport.sendControlResponse(request.request_id, response);
119
+ }
120
+ // ============= Hooks =============
121
+ /**
122
+ * Replace the registered hook callbacks. The hook event structure (events,
123
+ * matchers) was sent to CLI during initialize() — this just rewires the
124
+ * callback functions for existing hook IDs.
125
+ */
126
+ setHooks(hooks) {
127
+ this.hookCallbacks.clear();
128
+ this.registeredHooks = undefined;
129
+ this.registerHooks(hooks);
130
+ }
131
+ registerHooks(hooks) {
132
+ if (!hooks) {
133
+ return;
134
+ }
135
+ this.registeredHooks = hooks;
136
+ for (const [event, matchers] of Object.entries(hooks)) {
137
+ if (!matchers) {
138
+ continue;
139
+ }
140
+ matchers.forEach((matcher, matcherIndex) => {
141
+ matcher.hooks.forEach((hook, hookIndex) => {
142
+ const callbackId = `hook_${event}_${matcherIndex}_${hookIndex}`;
143
+ this.hookCallbacks.set(callbackId, hook);
144
+ });
145
+ });
146
+ }
147
+ }
148
+ buildHooksConfig() {
149
+ if (!this.registeredHooks) {
150
+ return undefined;
151
+ }
152
+ const config = {};
153
+ for (const [event, matchers] of Object.entries(this.registeredHooks)) {
154
+ if (!matchers) {
155
+ continue;
156
+ }
157
+ const hookEvent = event;
158
+ config[hookEvent] = matchers.map((matcher, matcherIndex) => ({
159
+ matcher: matcher.matcher,
160
+ hookCallbackIds: matcher.hooks.map((_, hookIndex) => `hook_${event}_${matcherIndex}_${hookIndex}`),
161
+ timeout: matcher.timeout,
162
+ }));
163
+ }
164
+ return Object.keys(config).length > 0 ? config : undefined;
165
+ }
166
+ }
167
+ exports.QueryController = QueryController;
168
+ //# sourceMappingURL=query-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-controller.js","sourceRoot":"","sources":["../../src/_internal/query-controller.ts"],"names":[],"mappings":"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"}
package/lib/query.d.ts CHANGED
@@ -20,9 +20,9 @@ export declare class Query implements AsyncGenerator<Message, void> {
20
20
  private prompt;
21
21
  private options?;
22
22
  private transport;
23
+ private controller;
23
24
  private initialized;
24
25
  private abortController;
25
- private hookCallbacks;
26
26
  private iterator;
27
27
  private connectPromise;
28
28
  private lockedSessionId;
@@ -89,12 +89,6 @@ export declare class Query implements AsyncGenerator<Message, void> {
89
89
  private createIterator;
90
90
  private initialize;
91
91
  private sendPrompt;
92
- private handleControlRequest;
93
- private handlePermissionRequest;
94
- private handleHookCallback;
95
- private registeredHooks?;
96
- private registerHooks;
97
- private buildHooksConfig;
98
92
  /**
99
93
  * Cleanup all resources.
100
94
  */
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EACR,WAAW,EAUX,eAAe,EACf,OAAO,EACP,SAAS,EACT,OAAO,EACP,cAAc,EAGd,YAAY,EACZ,WAAW,EACd,MAAM,SAAS,CAAC;AAGjB;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,KAAK,CAER;AAED;;GAEG;AACH,qBAAa,KAAM,YAAW,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC;IAqBnD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO,CAAC;IArBpB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAA0I;IAC/J,OAAO,CAAC,QAAQ,CAA8C;IAC9D,OAAO,CAAC,cAAc,CAA8B;IAGpD,OAAO,CAAC,eAAe,CAAuB;IAG9C,OAAO,CAAC,UAAU,CAAuB;IAGzC,OAAO,CAAC,sBAAsB,CAAiB;IAC/C,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,sBAAsB,CAAiB;IAC/C,OAAO,CAAC,aAAa,CAAqB;gBAG9B,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,GAAG,SAAS,EACvD,OAAO,CAAC,EAAE,OAAO,YAAA;IAkG7B,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC;IAOjD,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAI9C,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAKhD,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAO7D;;;;;;;;;;;;;;;;OAgBG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAId,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAchC;;;;OAIG;IACG,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAa5D;;OAEG;IACH,iBAAiB,IAAI,cAAc;IAInC;;;;OAIG;IACG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa7C;;OAEG;IACH,QAAQ,IAAI,MAAM,GAAG,SAAS;IAIxB,oBAAoB,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrE,iBAAiB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAO5C,eAAe,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAOvC,eAAe,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAO7C,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;IAOnC,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;YAQrD,cAAc;YAmEf,UAAU;YA0DV,UAAU;YA0BV,oBAAoB;YAWpB,uBAAuB;YA6DvB,kBAAkB;IAoBhC,OAAO,CAAC,eAAe,CAAC,CAAoD;IAE5E,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,gBAAgB;IAyBxB;;OAEG;IACH,OAAO,CAAC,OAAO;CAUlB"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EACR,WAAW,EACX,eAAe,EACf,OAAO,EACP,SAAS,EACT,OAAO,EACP,cAAc,EACd,YAAY,EACZ,WAAW,EACd,MAAM,SAAS,CAAC;AAGjB;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,KAAK,CAER;AAED;;GAEG;AACH,qBAAa,KAAM,YAAW,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC;IAqBnD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO,CAAC;IArBpB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAA8C;IAC9D,OAAO,CAAC,cAAc,CAA8B;IAGpD,OAAO,CAAC,eAAe,CAAuB;IAG9C,OAAO,CAAC,UAAU,CAAuB;IAGzC,OAAO,CAAC,sBAAsB,CAAiB;IAC/C,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,sBAAsB,CAAiB;IAC/C,OAAO,CAAC,aAAa,CAAqB;gBAG9B,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,GAAG,SAAS,EACvD,OAAO,CAAC,EAAE,OAAO,YAAA;IA2G7B,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC;IAOjD,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAI9C,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAKhD,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAO7D;;;;;;;;;;;;;;;;OAgBG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAId,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAchC;;;;OAIG;IACG,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAa5D;;OAEG;IACH,iBAAiB,IAAI,cAAc;IAInC;;;;OAIG;IACG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa7C;;OAEG;IACH,QAAQ,IAAI,MAAM,GAAG,SAAS;IAIxB,oBAAoB,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrE,iBAAiB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAO5C,eAAe,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAOvC,eAAe,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAO7C,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;IAOnC,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;YAQrD,cAAc;YAmEf,UAAU;YAkCV,UAAU;IA0BxB;;OAEG;IACH,OAAO,CAAC,OAAO;CAUlB"}
package/lib/query.js CHANGED
@@ -5,6 +5,7 @@
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Query = void 0;
7
7
  exports.query = query;
8
+ const query_controller_1 = require("./_internal/query-controller");
8
9
  const connect_1 = require("./connect");
9
10
  const errors_1 = require("./errors");
10
11
  const transport_1 = require("./transport");
@@ -31,7 +32,6 @@ class Query {
31
32
  this.prompt = prompt;
32
33
  this.options = options;
33
34
  this.initialized = false;
34
- this.hookCallbacks = new Map();
35
35
  this.iterator = null;
36
36
  this.connectPromise = null;
37
37
  // Session lock tracking
@@ -97,11 +97,16 @@ class Query {
97
97
  requestTimeoutMs: options === null || options === void 0 ? void 0 : options.requestTimeoutMs,
98
98
  };
99
99
  this.transport = (0, transport_1.createTransport)(transportOptions);
100
+ this.abortController = (_a = options === null || options === void 0 ? void 0 : options.abortController) !== null && _a !== void 0 ? _a : new AbortController();
101
+ // QueryController owns initialize + hook registry + control-request routing.
102
+ // The canUseTool getter is lazy because options shouldn't be re-read on every
103
+ // call (they don't change for query()), but it matches Session's pattern.
104
+ this.controller = new query_controller_1.QueryController(this.transport, options === null || options === void 0 ? void 0 : options.hooks, () => options === null || options === void 0 ? void 0 : options.canUseTool, () => this.abortController.signal);
100
105
  // Register control request handler on transport so control requests
101
106
  // are dispatched directly in handleLine(), bypassing the message queue.
102
107
  this.transport.onControlRequest(request => {
103
108
  // eslint-disable-next-line no-void
104
- void this.handleControlRequest(request).catch(() => {
109
+ void this.controller.handleControlRequest(request).catch(() => {
105
110
  // Individual control request errors shouldn't affect the query
106
111
  });
107
112
  });
@@ -110,8 +115,6 @@ class Query {
110
115
  this.connectPromise = this.transport.connect().catch(() => {
111
116
  // Ignore connection errors - they'll be reported when iteration starts
112
117
  });
113
- this.abortController = (_a = options === null || options === void 0 ? void 0 : options.abortController) !== null && _a !== void 0 ? _a : new AbortController();
114
- this.registerHooks(options === null || options === void 0 ? void 0 : options.hooks);
115
118
  // Track initial values (passed to CLI via command line args)
116
119
  this._initialPermissionMode = (_b = options === null || options === void 0 ? void 0 : options.permissionMode) !== null && _b !== void 0 ? _b : 'default';
117
120
  this._initialModel = options === null || options === void 0 ? void 0 : options.model;
@@ -327,7 +330,7 @@ class Query {
327
330
  }
328
331
  }
329
332
  async initialize() {
330
- var _a, _b, _c, _d, _e, _f, _g;
333
+ var _a, _b, _c, _d, _e, _f;
331
334
  if (this.initialized) {
332
335
  return;
333
336
  }
@@ -339,39 +342,19 @@ class Query {
339
342
  }
340
343
  this.lockedSessionId = this.options.resume;
341
344
  }
342
- const systemPrompt = typeof ((_c = this.options) === null || _c === void 0 ? void 0 : _c.systemPrompt) === 'string'
343
- ? this.options.systemPrompt
344
- : undefined;
345
- const appendSystemPrompt = typeof ((_d = this.options) === null || _d === void 0 ? void 0 : _d.systemPrompt) === 'object'
346
- ? this.options.systemPrompt.append
347
- : undefined;
348
- // Get SDK MCP server names from transport
349
- const sdkMcpServerNames = this.transport.sdkMcpServerNames;
350
- const initRequest = {
351
- subtype: 'initialize',
352
- hooks: this.buildHooksConfig(),
353
- systemPrompt,
354
- appendSystemPrompt,
355
- agents: (_e = this.options) === null || _e === void 0 ? void 0 : _e.agents,
356
- // Include SDK MCP server names from transport
357
- sdkMcpServers: sdkMcpServerNames.length > 0 ? sdkMcpServerNames : undefined,
358
- // Pass environment/endpoint for selfhosted environment resolution
359
- environment: (_f = this.options) === null || _f === void 0 ? void 0 : _f.environment,
360
- endpoint: (_g = this.options) === null || _g === void 0 ? void 0 : _g.endpoint,
361
- // Declare SDK capabilities for tool enablement
362
- capabilities: {
363
- // SDK supports handling AskUserQuestion via canUseTool callback
364
- askUserQuestion: true,
365
- },
366
- // Tell CLI whether prompt will follow (for resume history decision)
367
- // hasPrompt=true means CLI should NOT replay history
345
+ const response = await this.controller.initialize({
346
+ agents: (_c = this.options) === null || _c === void 0 ? void 0 : _c.agents,
347
+ systemPrompt: (_d = this.options) === null || _d === void 0 ? void 0 : _d.systemPrompt,
348
+ environment: (_e = this.options) === null || _e === void 0 ? void 0 : _e.environment,
349
+ endpoint: (_f = this.options) === null || _f === void 0 ? void 0 : _f.endpoint,
350
+ // Tell CLI whether prompt will follow (controls resume history replay).
351
+ // hasPrompt=true means CLI should NOT replay history.
368
352
  hasPrompt: this.prompt !== undefined && this.prompt !== '',
369
- };
370
- const response = await this.transport.sendControlRequest(initRequest);
353
+ });
371
354
  this.initialized = true;
372
- // Update model from CLI response if not set locally.
373
- // Also update _initialModel so the "pending change" detection at iteration
374
- // start doesn't treat the CLI-reported model as a user-initiated change.
355
+ // When ``options.model`` was unset, sync the CLI-reported model into both
356
+ // current *and* initial otherwise the pending-change check at iteration
357
+ // start would treat the CLI's reported value as a user-initiated change.
375
358
  if (!this._currentModel && response.currentModelId) {
376
359
  this._currentModel = response.currentModelId;
377
360
  this._initialModel = response.currentModelId;
@@ -403,116 +386,6 @@ class Query {
403
386
  }
404
387
  }
405
388
  }
406
- async handleControlRequest(request) {
407
- const { subtype } = request.request;
408
- if (subtype === 'hook_callback') {
409
- await this.handleHookCallback(request);
410
- }
411
- else if (subtype === 'can_use_tool') {
412
- await this.handlePermissionRequest(request);
413
- }
414
- // Note: mcp_message is handled at the transport level
415
- }
416
- async handlePermissionRequest(request) {
417
- var _a;
418
- const permRequest = request.request;
419
- const { tool_name, input, tool_use_id, agent_id, permission_suggestions, blocked_path, decision_reason, } = permRequest;
420
- const canUseTool = (_a = this.options) === null || _a === void 0 ? void 0 : _a.canUseTool;
421
- // If no canUseTool callback provided, deny by default
422
- if (!canUseTool) {
423
- this.transport.sendControlResponse(request.request_id, {
424
- allowed: false,
425
- reason: 'No permission handler provided',
426
- tool_use_id,
427
- });
428
- return;
429
- }
430
- try {
431
- const result = await canUseTool(tool_name, input, {
432
- signal: this.abortController.signal,
433
- suggestions: permission_suggestions,
434
- blockedPath: blocked_path,
435
- decisionReason: decision_reason,
436
- toolUseID: tool_use_id,
437
- agentID: agent_id,
438
- });
439
- if (result.behavior === 'allow') {
440
- this.transport.sendControlResponse(request.request_id, {
441
- allowed: true,
442
- updatedInput: result.updatedInput,
443
- tool_use_id,
444
- });
445
- }
446
- else {
447
- this.transport.sendControlResponse(request.request_id, {
448
- allowed: false,
449
- reason: result.message,
450
- interrupt: result.interrupt,
451
- tool_use_id,
452
- });
453
- }
454
- }
455
- catch (error) {
456
- this.transport.sendControlResponse(request.request_id, {
457
- allowed: false,
458
- reason: error instanceof Error ? error.message : String(error),
459
- tool_use_id,
460
- });
461
- }
462
- }
463
- async handleHookCallback(request) {
464
- const { callback_id, input, tool_use_id } = request.request;
465
- const callback = this.hookCallbacks.get(callback_id);
466
- let response = { continue: true };
467
- if (callback) {
468
- try {
469
- response = await callback(input, tool_use_id, { signal: this.abortController.signal });
470
- }
471
- catch (error) {
472
- response = {
473
- continue: false,
474
- stopReason: error instanceof Error ? error.message : String(error),
475
- };
476
- }
477
- }
478
- this.transport.sendControlResponse(request.request_id, response);
479
- }
480
- registerHooks(hooks) {
481
- if (!hooks) {
482
- return;
483
- }
484
- this.registeredHooks = hooks;
485
- // Build callback ID mapping for each hook - must match buildHooksConfig
486
- for (const [event, matchers] of Object.entries(hooks)) {
487
- if (!matchers) {
488
- continue;
489
- }
490
- matchers.forEach((matcher, matcherIndex) => {
491
- matcher.hooks.forEach((hook, hookIndex) => {
492
- const callbackId = `hook_${event}_${matcherIndex}_${hookIndex}`;
493
- this.hookCallbacks.set(callbackId, hook);
494
- });
495
- });
496
- }
497
- }
498
- buildHooksConfig() {
499
- if (!this.registeredHooks) {
500
- return undefined;
501
- }
502
- const config = {};
503
- for (const [event, matchers] of Object.entries(this.registeredHooks)) {
504
- if (!matchers) {
505
- continue;
506
- }
507
- const hookEvent = event;
508
- config[hookEvent] = matchers.map((matcher, matcherIndex) => ({
509
- matcher: matcher.matcher,
510
- hookCallbackIds: matcher.hooks.map((_, hookIndex) => `hook_${event}_${matcherIndex}_${hookIndex}`),
511
- timeout: matcher.timeout,
512
- }));
513
- }
514
- return Object.keys(config).length > 0 ? config : undefined;
515
- }
516
389
  /**
517
390
  * Cleanup all resources.
518
391
  */