@pushary/agent-hooks 0.4.4 → 0.4.6

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.
@@ -1,4 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ addClaudeMcpServer,
4
+ addPusharyHooks,
5
+ addPusharyToolPermissions
6
+ } from "../chunk-AC4UYAGX.js";
2
7
 
3
8
  // bin/pushary-setup.ts
4
9
  import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from "fs";
@@ -10,7 +15,9 @@ import { fileURLToPath } from "url";
10
15
  var CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json");
11
16
  var CLAUDE_JSON = join(homedir(), ".claude.json");
12
17
  var CURSOR_MCP = join(".cursor", "mcp.json");
13
- var SKILL_DIR = join(homedir(), ".claude", "skills", "pushary");
18
+ var CURSOR_RULES_DIR = join(".cursor", "rules");
19
+ var CLAUDE_SKILL_DIR = join(homedir(), ".claude", "skills", "pushary");
20
+ var CODEX_SKILL_DIR = join(homedir(), ".codex", "skills", "pushary");
14
21
  var SHELL_FILES = [".zshrc", ".bashrc"].map((f) => join(homedir(), f));
15
22
  var dim = (s) => `\x1B[2m${s}\x1B[0m`;
16
23
  var bold = (s) => `\x1B[1m${s}\x1B[0m`;
@@ -30,7 +37,8 @@ var writeJson = (path, data) => {
30
37
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
31
38
  writeFileSync(path, JSON.stringify(data, null, 2) + "\n", "utf-8");
32
39
  };
33
- var spinner = async (label, fn) => {
40
+ var formatError = (err) => err instanceof Error ? err.message : String(err);
41
+ var spinner = async (label, fn, options = {}) => {
34
42
  const frames = [" ", ". ", ".. ", "..."];
35
43
  let i = 0;
36
44
  const interval = setInterval(() => {
@@ -41,10 +49,11 @@ var spinner = async (label, fn) => {
41
49
  clearInterval(interval);
42
50
  process.stdout.write(`\r ${check} ${label}
43
51
  `);
44
- } catch {
52
+ } catch (err) {
45
53
  clearInterval(interval);
46
- process.stdout.write(`\r ${yellow("!")} ${label} ${dim("(skipped)")}
54
+ process.stdout.write(`\r ${yellow("!")} ${label} ${dim(`(${formatError(err)})`)}
47
55
  `);
56
+ if (!options.optional) throw err;
48
57
  }
49
58
  };
50
59
  var getPackageVersion = () => {
@@ -76,74 +85,37 @@ var installGlobally = async () => {
76
85
  execSync("npm install -g @pushary/agent-hooks@latest", { stdio: "ignore" });
77
86
  });
78
87
  };
79
- var addMcpServer = (apiKey) => {
80
- const data = readJson(CLAUDE_JSON);
81
- const mcpServers = data.mcpServers ?? {};
82
- mcpServers.pushary = {
83
- type: "http",
84
- url: "https://pushary.com/api/mcp/mcp",
85
- headers: { Authorization: `Bearer ${apiKey}` }
86
- };
87
- data.mcpServers = mcpServers;
88
- writeJson(CLAUDE_JSON, data);
89
- };
90
- var addPermissionHooks = (settings) => {
91
- const hooks = settings.hooks ?? {};
92
- const preToolUse = hooks.PreToolUse ?? [];
93
- if (!JSON.stringify(preToolUse).includes("pushary-hook")) {
94
- preToolUse.push({
95
- matcher: "Bash|Write|Edit",
96
- hooks: [{
97
- type: "command",
98
- command: "pushary-hook",
99
- timeout: 120
100
- }]
101
- });
102
- hooks.PreToolUse = preToolUse;
103
- }
104
- const postToolUse = hooks.PostToolUse ?? [];
105
- if (!JSON.stringify(postToolUse).includes("pushary-post-hook")) {
106
- postToolUse.push({
107
- matcher: "Bash|Write|Edit",
108
- hooks: [{
109
- type: "command",
110
- command: "pushary-post-hook",
111
- timeout: 10
112
- }]
113
- });
114
- hooks.PostToolUse = postToolUse;
115
- }
116
- const stop = hooks.Stop ?? [];
117
- if (!JSON.stringify(stop).includes("pushary-stop-hook")) {
118
- stop.push({
119
- hooks: [{
120
- type: "command",
121
- command: "pushary-stop-hook",
122
- timeout: 10
123
- }]
124
- });
125
- hooks.Stop = stop;
126
- }
127
- settings.hooks = hooks;
88
+ var _cachedSkillContent = null;
89
+ var fetchSkillContent = async () => {
90
+ if (_cachedSkillContent) return _cachedSkillContent;
91
+ const __dirname = dirname(fileURLToPath(import.meta.url));
92
+ const candidates = [
93
+ join(__dirname, "..", "..", "data", "SKILL.md"),
94
+ join(__dirname, "..", "data", "SKILL.md")
95
+ ];
96
+ const source = candidates.find((path) => existsSync(path));
97
+ if (!source) throw new Error("packaged skill not found");
98
+ _cachedSkillContent = readFileSync(source, "utf-8");
99
+ return _cachedSkillContent;
128
100
  };
129
- var addToolPermissions = (settings) => {
130
- const permissions = settings.permissions ?? {};
131
- const allow = permissions.allow ?? [];
132
- const filtered = allow.filter((r) => !r.includes("pushary"));
133
- const rule = "MCP(pushary:*)";
134
- if (!filtered.includes(rule)) filtered.push(rule);
135
- permissions.allow = filtered;
136
- settings.permissions = permissions;
101
+ var installSkillToDir = async (dir, label) => {
102
+ await spinner(label, async () => {
103
+ const content = await fetchSkillContent();
104
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
105
+ writeFileSync(join(dir, "SKILL.md"), content, "utf-8");
106
+ });
137
107
  };
138
- var installSkill = async () => {
139
- await spinner("Installing Pushary skill", async () => {
140
- const res = await fetch("https://raw.githubusercontent.com/pushary/pushary-skill/main/skills/pushary/SKILL.md", {
141
- signal: AbortSignal.timeout(1e4)
142
- });
143
- if (!res.ok) throw new Error(`Failed to fetch skill (${res.status})`);
144
- const content = await res.text();
145
- if (!existsSync(SKILL_DIR)) mkdirSync(SKILL_DIR, { recursive: true });
146
- writeFileSync(join(SKILL_DIR, "SKILL.md"), content, "utf-8");
108
+ var installCursorRule = async () => {
109
+ await spinner("Installing Pushary rules", async () => {
110
+ const content = await fetchSkillContent();
111
+ const body = content.replace(/^---[\s\S]*?---\n*/m, "");
112
+ const mdc = `---
113
+ alwaysApply: true
114
+ ---
115
+
116
+ ${body}`;
117
+ if (!existsSync(CURSOR_RULES_DIR)) mkdirSync(CURSOR_RULES_DIR, { recursive: true });
118
+ writeFileSync(join(CURSOR_RULES_DIR, "pushary.mdc"), mdc, "utf-8");
147
119
  });
148
120
  };
149
121
  var setupClaudeCode = async (apiKey) => {
@@ -152,19 +124,21 @@ var setupClaudeCode = async (apiKey) => {
152
124
  `);
153
125
  const settings = readJson(CLAUDE_SETTINGS);
154
126
  await spinner("Adding MCP server (type: http)", async () => {
155
- addMcpServer(apiKey);
127
+ const data = readJson(CLAUDE_JSON);
128
+ addClaudeMcpServer(data, apiKey);
129
+ writeJson(CLAUDE_JSON, data);
156
130
  });
157
131
  await spinner("Auto-allowing Pushary tools", async () => {
158
- addToolPermissions(settings);
132
+ addPusharyToolPermissions(settings);
159
133
  });
160
134
  await installGlobally();
161
135
  await spinner("Adding hooks (PreToolUse, PostToolUse, Stop)", async () => {
162
- addPermissionHooks(settings);
136
+ addPusharyHooks(settings);
163
137
  });
164
138
  await spinner(`Writing ${CLAUDE_SETTINGS}`, async () => {
165
139
  writeJson(CLAUDE_SETTINGS, settings);
166
140
  });
167
- await installSkill();
141
+ await installSkillToDir(CLAUDE_SKILL_DIR, "Installing Pushary skill");
168
142
  console.log();
169
143
  console.log(` ${dim("What this configured:")}`);
170
144
  console.log(` ${dim("\u2022")} MCP server: your agent can send notifications and ask questions`);
@@ -196,10 +170,7 @@ var setupHermes = async (_apiKey) => {
196
170
  console.log(` ${dim(" Install Python 3.10+ and re-run setup to fix.")}`);
197
171
  }
198
172
  await spinner("Enabling plugin", async () => {
199
- try {
200
- execSync("hermes plugins enable pushary", { stdio: "ignore" });
201
- } catch {
202
- }
173
+ execSync("hermes plugins enable pushary", { stdio: "ignore" });
203
174
  });
204
175
  console.log();
205
176
  console.log(` ${dim("What this configured:")}`);
@@ -250,6 +221,7 @@ notify = ["${pusharyCodexPath}"]
250
221
  appendFileSync(codexConfig, notifyLine, "utf-8");
251
222
  }
252
223
  });
224
+ await installSkillToDir(CODEX_SKILL_DIR, "Installing Pushary skill");
253
225
  console.log();
254
226
  console.log(` ${dim("What this configured:")}`);
255
227
  console.log(` ${dim("\u2022")} MCP server: Codex can send notifications and ask questions`);
@@ -270,7 +242,7 @@ var setupCursor = async (apiKey) => {
270
242
  config.mcpServers = mcpServers;
271
243
  writeJson(CURSOR_MCP, config);
272
244
  });
273
- await installSkill();
245
+ await installCursorRule();
274
246
  };
275
247
  var saveApiKey = async (apiKey) => {
276
248
  await spinner("Saving API key to shell profile", async () => {
@@ -379,4 +351,10 @@ var main = async () => {
379
351
  console.log(` ${dim("3.")} Run ${cyan("npx @pushary/agent-hooks doctor")} to verify`);
380
352
  console.log();
381
353
  };
382
- main();
354
+ main().catch((err) => {
355
+ console.log();
356
+ console.log(` ${yellow("!")} Setup failed: ${formatError(err)}`);
357
+ console.log(` ${dim("Run")} ${cyan("npx @pushary/agent-hooks doctor")} ${dim("after fixing the issue, then rerun setup.")}`);
358
+ console.log();
359
+ process.exit(1);
360
+ });
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  askUser,
3
3
  waitForAnswer
4
- } from "./chunk-4TWRLEOX.js";
4
+ } from "./chunk-M5SRSBLS.js";
5
5
  import {
6
6
  getApiKey,
7
7
  getBaseUrl
@@ -0,0 +1,136 @@
1
+ // src/claude-config.ts
2
+ var PUSHARY_MCP_URL = "https://pushary.com/api/mcp/mcp";
3
+ var PUSHARY_PERMISSION_RULE = "mcp__pushary__*";
4
+ var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
5
+ var ensureRecord = (target, key) => {
6
+ const existing = asRecord(target[key]);
7
+ if (existing) return existing;
8
+ const created = {};
9
+ target[key] = created;
10
+ return created;
11
+ };
12
+ var isPusharyPermission = (rule) => typeof rule === "string" && (rule.includes("pushary") || rule.includes("MCP(pushary"));
13
+ var isPusharyHook = (entry) => {
14
+ const hooks = asRecord(entry)?.hooks;
15
+ if (!Array.isArray(hooks)) return false;
16
+ return hooks.some((hook) => {
17
+ const command = String(asRecord(hook)?.command ?? "");
18
+ return command.includes("pushary-hook") || command.includes("pushary-post-hook") || command.includes("pushary-stop-hook");
19
+ });
20
+ };
21
+ var addClaudeMcpServer = (config, apiKey) => {
22
+ const mcpServers = ensureRecord(config, "mcpServers");
23
+ mcpServers.pushary = {
24
+ type: "http",
25
+ url: PUSHARY_MCP_URL,
26
+ headers: { Authorization: `Bearer ${apiKey}` }
27
+ };
28
+ };
29
+ var removeClaudeMcpServers = (config) => {
30
+ let changed = false;
31
+ const removeFrom = (target) => {
32
+ const mcpServers = asRecord(target.mcpServers);
33
+ if (!mcpServers?.pushary) return;
34
+ delete mcpServers.pushary;
35
+ if (Object.keys(mcpServers).length === 0) delete target.mcpServers;
36
+ changed = true;
37
+ };
38
+ removeFrom(config);
39
+ const projects = asRecord(config.projects);
40
+ if (projects) {
41
+ for (const project of Object.values(projects)) {
42
+ const projectConfig = asRecord(project);
43
+ if (projectConfig) removeFrom(projectConfig);
44
+ }
45
+ }
46
+ return changed;
47
+ };
48
+ var addPusharyToolPermissions = (settings) => {
49
+ const permissions = ensureRecord(settings, "permissions");
50
+ const allow = Array.isArray(permissions.allow) ? permissions.allow : [];
51
+ const filtered = allow.filter((rule) => !isPusharyPermission(rule));
52
+ if (!filtered.includes(PUSHARY_PERMISSION_RULE)) {
53
+ filtered.push(PUSHARY_PERMISSION_RULE);
54
+ }
55
+ permissions.allow = filtered;
56
+ };
57
+ var addPusharyHooks = (settings) => {
58
+ const hooks = ensureRecord(settings, "hooks");
59
+ const preToolUse = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : [];
60
+ if (!preToolUse.some(isPusharyHook)) {
61
+ preToolUse.push({
62
+ matcher: "Bash|Write|Edit",
63
+ hooks: [{
64
+ type: "command",
65
+ command: "pushary-hook",
66
+ timeout: 120
67
+ }]
68
+ });
69
+ hooks.PreToolUse = preToolUse;
70
+ }
71
+ const postToolUse = Array.isArray(hooks.PostToolUse) ? hooks.PostToolUse : [];
72
+ if (!postToolUse.some(isPusharyHook)) {
73
+ postToolUse.push({
74
+ matcher: "Bash|Write|Edit",
75
+ hooks: [{
76
+ type: "command",
77
+ command: "pushary-post-hook",
78
+ timeout: 10
79
+ }]
80
+ });
81
+ hooks.PostToolUse = postToolUse;
82
+ }
83
+ const stop = Array.isArray(hooks.Stop) ? hooks.Stop : [];
84
+ if (!stop.some(isPusharyHook)) {
85
+ stop.push({
86
+ hooks: [{
87
+ type: "command",
88
+ command: "pushary-stop-hook",
89
+ timeout: 10
90
+ }]
91
+ });
92
+ hooks.Stop = stop;
93
+ }
94
+ };
95
+ var removePusharySettings = (settings) => {
96
+ let changed = removeClaudeMcpServers(settings);
97
+ const permissions = asRecord(settings.permissions);
98
+ if (permissions && Array.isArray(permissions.allow)) {
99
+ const filtered = permissions.allow.filter((rule) => !isPusharyPermission(rule));
100
+ if (filtered.length !== permissions.allow.length) {
101
+ if (filtered.length === 0) {
102
+ delete permissions.allow;
103
+ } else {
104
+ permissions.allow = filtered;
105
+ }
106
+ if (Object.keys(permissions).length === 0) delete settings.permissions;
107
+ changed = true;
108
+ }
109
+ }
110
+ const hooks = asRecord(settings.hooks);
111
+ if (hooks) {
112
+ for (const key of ["PreToolUse", "PostToolUse", "Stop"]) {
113
+ const entries = hooks[key];
114
+ if (!Array.isArray(entries)) continue;
115
+ const filtered = entries.filter((entry) => !isPusharyHook(entry));
116
+ if (filtered.length !== entries.length) {
117
+ if (filtered.length === 0) {
118
+ delete hooks[key];
119
+ } else {
120
+ hooks[key] = filtered;
121
+ }
122
+ changed = true;
123
+ }
124
+ }
125
+ if (Object.keys(hooks).length === 0) delete settings.hooks;
126
+ }
127
+ return changed;
128
+ };
129
+
130
+ export {
131
+ addClaudeMcpServer,
132
+ removeClaudeMcpServers,
133
+ addPusharyToolPermissions,
134
+ addPusharyHooks,
135
+ removePusharySettings
136
+ };
@@ -0,0 +1,23 @@
1
+ import {
2
+ callMcpTool
3
+ } from "./chunk-RJKW6LLC.js";
4
+
5
+ // src/api.ts
6
+ var askUser = async (apiKey, params) => {
7
+ return callMcpTool(apiKey, "ask_user", { ...params });
8
+ };
9
+ var waitForAnswer = async (apiKey, correlationId, timeoutMs = 3e4) => {
10
+ return callMcpTool(apiKey, "wait_for_answer", {
11
+ correlationId,
12
+ timeoutMs
13
+ });
14
+ };
15
+ var cancelQuestion = async (apiKey, correlationId) => {
16
+ await callMcpTool(apiKey, "cancel_question", { correlationId });
17
+ };
18
+
19
+ export {
20
+ askUser,
21
+ waitForAnswer,
22
+ cancelQuestion
23
+ };
@@ -0,0 +1,78 @@
1
+ import {
2
+ getBaseUrl
3
+ } from "./chunk-VUNL35KE.js";
4
+
5
+ // src/mcp-http.ts
6
+ var parseSseJson = (body) => {
7
+ const messages = [];
8
+ for (const event of body.split(/\r?\n\r?\n/)) {
9
+ const data = event.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join("\n").trim();
10
+ if (!data) continue;
11
+ messages.push(JSON.parse(data));
12
+ }
13
+ const message = messages.at(-1);
14
+ if (!message) throw new Error("Empty response from Pushary");
15
+ return message;
16
+ };
17
+ var parseMcpResponse = (body, contentType) => {
18
+ if (contentType?.includes("text/event-stream")) {
19
+ return parseSseJson(body);
20
+ }
21
+ return JSON.parse(body);
22
+ };
23
+ var sendMcpRequest = async (apiKey, message, options = {}) => {
24
+ const baseUrl = options.baseUrl ?? getBaseUrl();
25
+ const fetchFn = options.fetchFn ?? fetch;
26
+ const headers = {
27
+ "Content-Type": "application/json",
28
+ "Accept": "application/json, text/event-stream",
29
+ "Authorization": `Bearer ${apiKey}`
30
+ };
31
+ if (options.sessionId) {
32
+ headers["Mcp-Session-Id"] = options.sessionId;
33
+ }
34
+ const response = await fetchFn(`${baseUrl}/api/mcp/mcp`, {
35
+ method: "POST",
36
+ headers,
37
+ body: JSON.stringify(message),
38
+ signal: options.timeoutMs ? AbortSignal.timeout(options.timeoutMs) : void 0
39
+ });
40
+ const body = await response.text();
41
+ const contentType = response.headers.get("content-type");
42
+ let data = null;
43
+ if (body.trim()) {
44
+ try {
45
+ data = parseMcpResponse(body, contentType);
46
+ } catch (err) {
47
+ if (response.ok) throw err;
48
+ }
49
+ }
50
+ if (!response.ok) {
51
+ const message2 = data?.error?.message ?? (body.trim() || response.statusText);
52
+ throw new Error(`Pushary MCP error: ${response.status} ${message2}`);
53
+ }
54
+ if (!data) throw new Error("Empty response from Pushary");
55
+ if (data.error) throw new Error(data.error.message ?? "Pushary MCP error");
56
+ return {
57
+ data,
58
+ sessionId: response.headers.get("mcp-session-id") ?? "",
59
+ status: response.status,
60
+ statusText: response.statusText
61
+ };
62
+ };
63
+ var callMcpTool = async (apiKey, toolName, params, options = {}) => {
64
+ const { data } = await sendMcpRequest(apiKey, {
65
+ jsonrpc: "2.0",
66
+ id: options.id ?? Date.now(),
67
+ method: "tools/call",
68
+ params: { name: toolName, arguments: params }
69
+ }, options);
70
+ const text = data.result?.content?.[0]?.text;
71
+ if (!text) throw new Error("Empty response from Pushary");
72
+ return JSON.parse(text);
73
+ };
74
+
75
+ export {
76
+ sendMcpRequest,
77
+ callMcpTool
78
+ };
package/dist/src/index.js CHANGED
@@ -2,12 +2,13 @@ import {
2
2
  getPolicy,
3
3
  handlePreToolUse,
4
4
  resolvePolicy
5
- } from "../chunk-KINE5LNQ.js";
5
+ } from "../chunk-4TQW4K6T.js";
6
6
  import {
7
7
  askUser,
8
8
  cancelQuestion,
9
9
  waitForAnswer
10
- } from "../chunk-4TWRLEOX.js";
10
+ } from "../chunk-M5SRSBLS.js";
11
+ import "../chunk-RJKW6LLC.js";
11
12
  import {
12
13
  handleNotification,
13
14
  handlePostToolUse,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushary/agent-hooks",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "Permission hooks for AI coding agents: route tool approvals through Pushary push notifications",
5
5
  "author": "Pushary <business@pushary.com>",
6
6
  "homepage": "https://pushary.com",
@@ -25,11 +25,13 @@
25
25
  "pushary-doctor": "./dist/bin/pushary-doctor.js"
26
26
  },
27
27
  "files": [
28
- "dist"
28
+ "dist",
29
+ "data"
29
30
  ],
30
31
  "scripts": {
31
32
  "build": "tsup src/index.ts bin/pushary.ts bin/pushary-hook.ts bin/pushary-post-hook.ts bin/pushary-stop-hook.ts bin/pushary-codex.ts bin/pushary-setup.ts bin/pushary-clean.ts bin/pushary-doctor.ts --format esm --dts --outDir dist",
32
- "dev": "tsup src/index.ts bin/pushary.ts bin/pushary-hook.ts bin/pushary-post-hook.ts bin/pushary-stop-hook.ts bin/pushary-codex.ts bin/pushary-setup.ts bin/pushary-clean.ts bin/pushary-doctor.ts --format esm --watch"
33
+ "dev": "tsup src/index.ts bin/pushary.ts bin/pushary-hook.ts bin/pushary-post-hook.ts bin/pushary-stop-hook.ts bin/pushary-codex.ts bin/pushary-setup.ts bin/pushary-clean.ts bin/pushary-doctor.ts --format esm --watch",
34
+ "test": "bun test src/api.test.ts && bun test src/claude-config.test.ts && bun test src/mcp-http.test.ts"
33
35
  },
34
36
  "dependencies": {
35
37
  "@inquirer/prompts": "^8.4.2"
@@ -1,49 +0,0 @@
1
- import {
2
- getBaseUrl
3
- } from "./chunk-VUNL35KE.js";
4
-
5
- // src/api.ts
6
- var mcpToolCall = async (apiKey, toolName, params) => {
7
- const baseUrl = getBaseUrl();
8
- const response = await fetch(`${baseUrl}/api/mcp/mcp`, {
9
- method: "POST",
10
- headers: {
11
- "Content-Type": "application/json",
12
- "Authorization": `Bearer ${apiKey}`
13
- },
14
- body: JSON.stringify({
15
- jsonrpc: "2.0",
16
- id: Date.now(),
17
- method: "tools/call",
18
- params: { name: toolName, arguments: params }
19
- })
20
- });
21
- if (!response.ok) {
22
- throw new Error(`Pushary API error: ${response.status} ${response.statusText}`);
23
- }
24
- const json = await response.json();
25
- if (json.error) throw new Error(json.error.message);
26
- const text = json.result?.content?.[0]?.text;
27
- if (!text) throw new Error("Empty response from Pushary");
28
- return JSON.parse(text);
29
- };
30
- var askUser = async (apiKey, params) => {
31
- const result = await mcpToolCall(apiKey, "ask_user", { ...params });
32
- return result;
33
- };
34
- var waitForAnswer = async (apiKey, correlationId, timeoutMs = 3e4) => {
35
- const result = await mcpToolCall(apiKey, "wait_for_answer", {
36
- correlationId,
37
- timeoutMs
38
- });
39
- return result;
40
- };
41
- var cancelQuestion = async (apiKey, correlationId) => {
42
- await mcpToolCall(apiKey, "cancel_question", { correlationId });
43
- };
44
-
45
- export {
46
- askUser,
47
- waitForAnswer,
48
- cancelQuestion
49
- };