@ask-llm/plugin 0.13.0 → 0.15.0

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.
@@ -0,0 +1,247 @@
1
+ import { executeCodexCLI } from "@ask-llm/codex-mcp/executor";
2
+ import { executeGrok } from "@ask-llm/grok-mcp/executor";
3
+ import { executeCursorAgent } from "@ask-llm/mcp/cursor";
4
+ export const BRAINSTORM_PANEL_PROVIDERS = ["grok", "codex"];
5
+ export const BARE_BRAINSTORM_PROVIDERS = ["gemini", "codex", "grok", "ollama", "antigravity"];
6
+ const SYNTHESIS_RULE = "Call a point two-model consensus only when both requested participants fulfilled successfully and independently stated it. On any participant failure, label the run partial and attribute surviving insights to that participant only.";
7
+ function routeAllowed(participant) {
8
+ if (participant.provider === "grok") {
9
+ return ["cursor-agent", "grok-cli", "xai-api"].includes(participant.harness);
10
+ }
11
+ return ["cursor-agent", "codex-cli"].includes(participant.harness);
12
+ }
13
+ export function parseBrainstormParticipant(spec) {
14
+ const match = spec.match(/^(grok|codex)@(cursor-agent|grok-cli|xai-api|codex-cli):(.+)$/);
15
+ if (!match) {
16
+ throw new Error(`Invalid brainstorm participant "${spec}". Use provider@harness:exact-model-id (for example grok@cursor-agent:cursor-grok-4.6-high).`);
17
+ }
18
+ const participant = {
19
+ provider: match[1],
20
+ harness: match[2],
21
+ model: match[3].trim(),
22
+ };
23
+ if (!participant.model || participant.model.toLowerCase() === "auto") {
24
+ throw new Error(`Participant "${spec}" requires an exact non-Auto model ID from the selected harness catalog.`);
25
+ }
26
+ if (!routeAllowed(participant)) {
27
+ throw new Error(`Unsupported brainstorm route ${participant.provider}@${participant.harness}. Harness, provider, and model are not interchangeable; no substitute route was selected.`);
28
+ }
29
+ return participant;
30
+ }
31
+ function isBareProvider(spec) {
32
+ return BARE_BRAINSTORM_PROVIDERS.includes(spec);
33
+ }
34
+ export function parseBrainstormParticipantList(specs) {
35
+ const trimmed = specs.map((spec) => spec.trim()).filter(Boolean);
36
+ if (trimmed.length === 0)
37
+ throw new Error("The brainstorm participant list is empty.");
38
+ const bare = trimmed.filter((spec) => !spec.includes("@"));
39
+ const routed = trimmed.filter((spec) => spec.includes("@"));
40
+ if (bare.length > 0 && routed.length > 0) {
41
+ throw new Error(`Mixed brainstorm participant lists are not supported: routed ${routed.map((spec) => `"${spec}"`).join(", ")} cannot be combined with bare ${bare.map((spec) => `"${spec}"`).join(", ")}. Use either an all-bare provider list or the exact routed Grok + GPT-5.6 Sol panel. No participant was substituted, rerouted, or dispatched.`);
42
+ }
43
+ if (routed.length > 0) {
44
+ return { mode: "exact", participants: routed.map(parseBrainstormParticipant) };
45
+ }
46
+ const unknown = bare.find((spec) => !isBareProvider(spec));
47
+ if (unknown) {
48
+ throw new Error(`Unknown brainstorm provider "${unknown}". Supported bare providers: ${BARE_BRAINSTORM_PROVIDERS.join(", ")}; routed participants use provider@harness:exact-model-id. No substitute was selected.`);
49
+ }
50
+ return { mode: "bare", providers: bare.filter(isBareProvider) };
51
+ }
52
+ export function validateBrainstormPanel(participants) {
53
+ if (participants.length !== 2) {
54
+ throw new Error("The Grok + GPT-5.6 Sol panel requires exactly two participants.");
55
+ }
56
+ const providers = participants.map(({ provider }) => provider);
57
+ if (new Set(providers).size !== providers.length) {
58
+ throw new Error("The Grok + GPT-5.6 Sol panel requires one Grok participant and one Codex participant.");
59
+ }
60
+ for (const required of BRAINSTORM_PANEL_PROVIDERS) {
61
+ if (!providers.includes(required)) {
62
+ throw new Error(`The Grok + GPT-5.6 Sol panel is missing provider "${required}".`);
63
+ }
64
+ }
65
+ for (const participant of participants) {
66
+ if (!participant.model.trim() || participant.model.toLowerCase() === "auto") {
67
+ throw new Error(`${participant.provider}@${participant.harness} requires an exact non-Auto model ID.`);
68
+ }
69
+ if (!routeAllowed(participant)) {
70
+ throw new Error(`Unsupported brainstorm route ${participant.provider}@${participant.harness}. No provider or harness fallback was attempted.`);
71
+ }
72
+ if (participant.provider === "codex" && !participant.model.toLowerCase().includes("gpt-5.6-sol")) {
73
+ throw new Error(`The Codex participant must request an exact GPT-5.6 Sol model ID; received "${participant.model}". No model substitution was attempted.`);
74
+ }
75
+ }
76
+ }
77
+ const LATEST_ALIAS_SUFFIX = "-latest";
78
+ export function isSameProductResolution(requested, observed) {
79
+ const requestedId = requested.trim().toLowerCase();
80
+ const observedId = observed.trim().toLowerCase();
81
+ if (requestedId === observedId)
82
+ return true;
83
+ const productId = requestedId.endsWith(LATEST_ALIAS_SUFFIX)
84
+ ? requestedId.slice(0, -LATEST_ALIAS_SUFFIX.length)
85
+ : requestedId;
86
+ if (!productId || !observedId.startsWith(`${productId}-`))
87
+ return false;
88
+ return /^[0-9][0-9.-]*$/.test(observedId.slice(productId.length + 1));
89
+ }
90
+ function classifyObservedModel(participant, observedModel) {
91
+ const identity = `${participant.provider} via ${participant.harness}`;
92
+ if (observedModel.trim().toLowerCase() === participant.model.trim().toLowerCase()) {
93
+ return {
94
+ modelVerification: "observed-exact",
95
+ attributionNote: `${identity} reported served model "${observedModel}", matching the requested ID.`,
96
+ };
97
+ }
98
+ if (isSameProductResolution(participant.model, observedModel)) {
99
+ return {
100
+ modelVerification: "observed-alias",
101
+ attributionNote: `${identity} served "${observedModel}" for requested "${participant.model}" (disclosed provider-side alias/snapshot resolution of the same model; the requested ID was sent unchanged and was not rewritten).`,
102
+ };
103
+ }
104
+ throw new Error(`${identity} requested exact model "${participant.model}" but reported "${observedModel}". The response is excluded from two-model consensus; no additional route was attempted.`);
105
+ }
106
+ function selectedOnlyNote(participant, detail) {
107
+ return `${participant.provider} via ${participant.harness} ran the requested ID "${participant.model}" (${detail}); the harness does not independently confirm the served catalog model, so this attribution is selected-only and unverifiable, not an observed actual model.`;
108
+ }
109
+ async function invokeParticipant(participant, prompt, signal, onProgress) {
110
+ const identity = `${participant.provider} via ${participant.harness} (${participant.model})`;
111
+ const progress = onProgress ? (message) => onProgress(`[${identity}] ${message}`) : undefined;
112
+ const base = { ...participant, requestedModel: participant.model };
113
+ let observedModel;
114
+ let reportedModel;
115
+ let modelVerification;
116
+ try {
117
+ if (participant.harness === "cursor-agent") {
118
+ const result = await executeCursorAgent({
119
+ provider: participant.provider,
120
+ model: participant.model,
121
+ prompt,
122
+ signal,
123
+ onProgress: progress,
124
+ });
125
+ reportedModel = result.reportedModel;
126
+ if (result.usage.fellBack) {
127
+ modelVerification = "fallback";
128
+ throw new Error(`Cursor Agent reported a model fallback for requested "${participant.model}". The response is excluded from two-model consensus.`);
129
+ }
130
+ if (result.model !== participant.model) {
131
+ modelVerification = "mismatch";
132
+ throw new Error(`Cursor Agent ran "${result.model}" instead of requested "${participant.model}". The response is excluded from two-model consensus; no additional route was attempted.`);
133
+ }
134
+ modelVerification = "selected-unverified";
135
+ return {
136
+ ...base,
137
+ reportedModel,
138
+ modelVerification,
139
+ attributionNote: selectedOnlyNote(participant, reportedModel
140
+ ? `Cursor echoed the requested ID and reported display label "${reportedModel}", which is a label and not a catalog ID`
141
+ : "Cursor echoed the requested ID and reported no display label"),
142
+ response: result.response,
143
+ status: "fulfilled",
144
+ };
145
+ }
146
+ if (participant.provider === "grok") {
147
+ if (participant.harness !== "grok-cli" && participant.harness !== "xai-api") {
148
+ throw new Error(`Unsupported brainstorm route ${participant.provider}@${participant.harness}. No fallback was attempted.`);
149
+ }
150
+ const result = await executeGrok({
151
+ prompt,
152
+ model: participant.model,
153
+ harness: participant.harness,
154
+ reasoningEffort: "high",
155
+ signal,
156
+ onProgress: progress,
157
+ });
158
+ if (result.usage?.fellBack) {
159
+ modelVerification = "fallback";
160
+ throw new Error(`${participant.harness} reported a model fallback for requested "${participant.model}". The response is excluded from two-model consensus.`);
161
+ }
162
+ if (!result.reportedModel) {
163
+ if (result.model !== participant.model) {
164
+ modelVerification = "mismatch";
165
+ throw new Error(`${participant.provider} via ${participant.harness} ran "${result.model}" instead of requested "${participant.model}". The response is excluded from two-model consensus; no additional route was attempted.`);
166
+ }
167
+ modelVerification = "selected-unverified";
168
+ return {
169
+ ...base,
170
+ modelVerification,
171
+ attributionNote: selectedOnlyNote(participant, `${participant.harness} reported no served model ID, so only the requested ID is known`),
172
+ response: result.response,
173
+ status: "fulfilled",
174
+ };
175
+ }
176
+ observedModel = result.reportedModel;
177
+ let observed;
178
+ try {
179
+ observed = classifyObservedModel(participant, observedModel);
180
+ }
181
+ catch (error) {
182
+ modelVerification = "mismatch";
183
+ throw error;
184
+ }
185
+ modelVerification = observed.modelVerification;
186
+ return {
187
+ ...base,
188
+ observedModel,
189
+ modelVerification,
190
+ attributionNote: observed.attributionNote,
191
+ response: result.response,
192
+ status: "fulfilled",
193
+ };
194
+ }
195
+ const result = await executeCodexCLI({
196
+ prompt,
197
+ model: participant.model,
198
+ reasoningEffort: "high",
199
+ sandbox: "read-only",
200
+ signal,
201
+ onProgress: progress,
202
+ });
203
+ if (result.usage?.fellBack) {
204
+ modelVerification = "fallback";
205
+ throw new Error(`Codex CLI reported a model fallback to "${result.usage.model}" for requested "${participant.model}". The response is excluded from two-model consensus.`);
206
+ }
207
+ if (result.usage && result.usage.model !== participant.model) {
208
+ modelVerification = "mismatch";
209
+ throw new Error(`Codex CLI ran "${result.usage.model}" instead of requested "${participant.model}". The response is excluded from two-model consensus; no additional route was attempted.`);
210
+ }
211
+ modelVerification = "selected-unverified";
212
+ return {
213
+ ...base,
214
+ modelVerification,
215
+ attributionNote: selectedOnlyNote(participant, result.usage
216
+ ? "Codex CLI echoed the requested ID with no fallback"
217
+ : "served from the Codex response cache keyed by the requested ID, which stores only no-fallback responses"),
218
+ response: result.response,
219
+ status: "fulfilled",
220
+ };
221
+ }
222
+ catch (error) {
223
+ return {
224
+ ...base,
225
+ observedModel,
226
+ reportedModel,
227
+ modelVerification,
228
+ status: "rejected",
229
+ error: error instanceof Error ? error.message : String(error),
230
+ };
231
+ }
232
+ }
233
+ export async function runBrainstormPanel(options) {
234
+ if (!options.prompt.trim())
235
+ throw new Error("The brainstorm panel requires a non-empty prompt.");
236
+ validateBrainstormPanel(options.participants);
237
+ const participants = await Promise.all(options.participants.map((participant) => invokeParticipant(participant, options.prompt, options.signal, options.onProgress)));
238
+ const successCount = participants.filter(({ status }) => status === "fulfilled").length;
239
+ return {
240
+ panel: "grok+gpt-5.6-sol",
241
+ status: successCount === 2 ? "complete" : successCount === 1 ? "partial" : "failed",
242
+ consensusEligible: successCount === 2,
243
+ synthesisRule: SYNTHESIS_RULE,
244
+ participants,
245
+ };
246
+ }
247
+ //# sourceMappingURL=brainstorm-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brainstorm-panel.js","sourceRoot":"","sources":["../src/brainstorm-panel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=brainstorm-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brainstorm-run.d.ts","sourceRoot":"","sources":["../src/brainstorm-run.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ import { parseBrainstormParticipantList, runBrainstormPanel } from "./brainstorm-panel.js";
3
+ function parseArgs(argv) {
4
+ const participants = [];
5
+ for (let index = 0; index < argv.length; index += 1) {
6
+ const arg = argv[index];
7
+ if (arg === "--participant") {
8
+ const value = argv[index + 1];
9
+ if (!value)
10
+ throw new Error("--participant requires provider@harness:exact-model-id");
11
+ participants.push(value);
12
+ index += 1;
13
+ continue;
14
+ }
15
+ throw new Error(`Unknown argument "${arg}". Only repeated --participant arguments are supported.`);
16
+ }
17
+ return participants;
18
+ }
19
+ async function readStdin() {
20
+ if (process.stdin.isTTY)
21
+ return "";
22
+ const chunks = [];
23
+ for await (const chunk of process.stdin)
24
+ chunks.push(chunk);
25
+ return Buffer.concat(chunks).toString();
26
+ }
27
+ async function main() {
28
+ try {
29
+ const specs = parseArgs(process.argv.slice(2));
30
+ const list = parseBrainstormParticipantList(specs);
31
+ if (list.mode !== "exact") {
32
+ throw new Error(`ask-brainstorm-run executes only the exact routed Grok + GPT-5.6 Sol panel; bare providers (${list.providers.join(", ")}) use the standard coordinator dispatch. No participant was dispatched.`);
33
+ }
34
+ const prompt = await readStdin();
35
+ const report = await runBrainstormPanel({
36
+ prompt,
37
+ participants: list.participants,
38
+ onProgress: (message) => console.error(message),
39
+ });
40
+ console.log(JSON.stringify(report, null, 2));
41
+ if (report.status !== "complete")
42
+ process.exitCode = 2;
43
+ }
44
+ catch (error) {
45
+ const message = error instanceof Error ? error.message : String(error);
46
+ console.error(`ask-brainstorm-run failed: ${message}`);
47
+ process.exitCode = 1;
48
+ }
49
+ }
50
+ main();
51
+ //# sourceMappingURL=brainstorm-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brainstorm-run.js","sourceRoot":"","sources":["../src/brainstorm-run.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3F,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC9B,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;YACtF,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,yDAAyD,CAAC,CAAC;IACrG,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK;QAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;AAC1C,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,8BAA8B,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,+FAA+F,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,yEAAyE,CAClM,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC;YACtC,MAAM;YACN,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,UAAU,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;SAChD,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU;YAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,8BAA8B,OAAO,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=grok-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grok-run.d.ts","sourceRoot":"","sources":["../src/grok-run.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ import { executeGrok } from "@ask-llm/grok-mcp/executor";
3
+ const prompt = process.argv.slice(2).join(" ");
4
+ async function readStdin() {
5
+ if (process.stdin.isTTY)
6
+ return "";
7
+ const chunks = [];
8
+ for await (const chunk of process.stdin)
9
+ chunks.push(chunk);
10
+ return Buffer.concat(chunks).toString().trim();
11
+ }
12
+ async function main() {
13
+ const stdin = await readStdin();
14
+ if (!prompt && !stdin) {
15
+ console.error("Usage: ask-grok-run <prompt>");
16
+ console.error(" echo 'diff' | ask-grok-run 'Review this diff'");
17
+ process.exit(1);
18
+ }
19
+ try {
20
+ const result = await executeGrok({ prompt: [prompt, stdin].filter(Boolean).join("\n\n") });
21
+ console.log(result.response);
22
+ }
23
+ catch (error) {
24
+ const message = error instanceof Error ? error.message : String(error);
25
+ console.error(`ask-grok-run failed: ${message}`);
26
+ process.exit(1);
27
+ }
28
+ }
29
+ main();
30
+ //# sourceMappingURL=grok-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grok-run.js","sourceRoot":"","sources":["../src/grok-run.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,KAAK,UAAU,SAAS;IACtB,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK;QAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;AACjD,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;QACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3F,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7E;AAED,eAAO,MAAM,SAAS,EAAE,gBAAgB,EAqCvC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7E;AAED,eAAO,MAAM,SAAS,EAAE,gBAAgB,EA8CvC,CAAC"}
package/dist/index.js CHANGED
@@ -17,6 +17,15 @@ export const providers = [
17
17
  return result.response;
18
18
  },
19
19
  },
20
+ {
21
+ name: "grok",
22
+ command: "xai-api",
23
+ async execute(prompt) {
24
+ const { executeGrok } = await import("@ask-llm/grok-mcp/executor");
25
+ const result = await executeGrok({ prompt });
26
+ return result.response;
27
+ },
28
+ },
20
29
  {
21
30
  name: "ollama",
22
31
  command: "ollama",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,SAAS,GAAuB;IAC3C;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,QAAQ;QACjB,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;YAC1E,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;KACF;IACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,OAAO;QAChB,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;YACxE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACjD,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,QAAQ;QACjB,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;YAC1E,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,KAAK;QACd,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,mCAAmC,CAAC,CAAC;YACpF,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACvD,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;KACF;CACF,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,SAAS,GAAuB;IAC3C;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,QAAQ;QACjB,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;YAC1E,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;KACF;IACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,OAAO;QAChB,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;YACxE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACjD,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;KACF;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,SAAS;QAClB,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;YACnE,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC7C,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,QAAQ;QACjB,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;YAC1E,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,KAAK;QACd,KAAK,CAAC,OAAO,CAAC,MAAc;YAC1B,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,mCAAmC,CAAC,CAAC;YACpF,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACvD,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;KACF;CACF,CAAC"}
package/mcp.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "mcpServers": {
3
+ "ask-llm": {
4
+ "command": "npx",
5
+ "args": [
6
+ "-y",
7
+ "@ask-llm/mcp"
8
+ ]
9
+ }
10
+ }
11
+ }
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@ask-llm/plugin",
3
- "version": "0.13.0",
4
- "description": "Ask LLM review, comparison, brainstorming, image, verification, and pairing workflows for Claude Code and Pi",
3
+ "version": "0.15.0",
4
+ "description": "Ask LLM review, comparison, brainstorming, image, verification, and pairing workflows for Claude Code, Cursor Agent, and Pi",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "ask-antigravity-run": "dist/antigravity-run.js",
9
+ "ask-brainstorm-run": "dist/brainstorm-run.js",
9
10
  "ask-codex-run": "dist/codex-run.js",
10
11
  "ask-gemini-run": "dist/run.js",
12
+ "ask-grok-run": "dist/grok-run.js",
11
13
  "ask-ollama-run": "dist/ollama-run.js"
12
14
  },
13
15
  "scripts": {
@@ -21,6 +23,8 @@
21
23
  "claude-code-plugin",
22
24
  "codex",
23
25
  "gemini",
26
+ "grok",
27
+ "xai",
24
28
  "ollama",
25
29
  "antigravity",
26
30
  "code-review",
@@ -40,7 +44,9 @@
40
44
  "homepage": "https://github.com/Lykhoyda/ask-llm#readme",
41
45
  "files": [
42
46
  ".claude-plugin/",
47
+ ".cursor-plugin/",
43
48
  ".mcp.json",
49
+ "mcp.json",
44
50
  "agents/",
45
51
  "codex-pair-defaults.json",
46
52
  "dist/",
@@ -70,16 +76,19 @@
70
76
  "./skills/codex-verify/SKILL.md",
71
77
  "./skills/compare/SKILL.md",
72
78
  "./skills/gemini-review/SKILL.md",
79
+ "./skills/grok-review/SKILL.md",
73
80
  "./skills/multi-review/SKILL.md",
74
81
  "./skills/ollama-review/SKILL.md",
75
82
  "./skills/sol-review/SKILL.md"
76
83
  ]
77
84
  },
78
85
  "dependencies": {
79
- "@ask-llm/antigravity-mcp": "^0.7.1",
80
- "@ask-llm/codex-mcp": "^0.7.4",
81
- "@ask-llm/gemini-mcp": "^1.7.1",
82
- "@ask-llm/ollama-mcp": "^0.5.6"
86
+ "@ask-llm/antigravity-mcp": "^0.7.2",
87
+ "@ask-llm/codex-mcp": "^0.7.5",
88
+ "@ask-llm/gemini-mcp": "^1.7.2",
89
+ "@ask-llm/grok-mcp": "^0.1.2",
90
+ "@ask-llm/mcp": "^0.8.0",
91
+ "@ask-llm/ollama-mcp": "^0.5.7"
83
92
  },
84
93
  "peerDependencies": {
85
94
  "@earendil-works/pi-ai": "*",
@@ -52,6 +52,8 @@ const ALLOWLIST_LOCK_RETRY_MS = 25;
52
52
  const ALLOWLIST_LOCK_TIMEOUT_MS = 5_000;
53
53
  const ALLOWLIST_LOCK_STALE_MS = 30_000;
54
54
  const LOCK_CONTENTION_RETRY_MS = 100;
55
+ const CLAIM_SUFFIX = ".claim";
56
+ const CLAIM_STALE_MS = 30_000;
55
57
  const PI_PENDING_DIR = "pi-pending";
56
58
  const PI_REVIEWED_DIR = "pi-reviewed";
57
59
  const SKIP_PARTS = [
@@ -381,7 +383,7 @@ function sendFinding(pi: ExtensionAPI, finding: PairFinding): void {
381
383
 
382
384
  interface ClaimedFinding {
383
385
  claimPath: string;
384
- originalPath: string;
386
+ pendingPath: string;
385
387
  finding: PairFinding;
386
388
  }
387
389
 
@@ -398,39 +400,57 @@ function processIsAlive(pid: number): boolean {
398
400
  }
399
401
  }
400
402
 
403
+ function parseClaimOwner(content: string): number | undefined {
404
+ try {
405
+ const { pid } = JSON.parse(content) as { pid?: unknown };
406
+ return typeof pid === "number" && Number.isInteger(pid) ? pid : undefined;
407
+ } catch {
408
+ return undefined;
409
+ }
410
+ }
411
+
401
412
  async function recoverAbandonedClaims(markerDir: string): Promise<void> {
402
413
  const root = pendingRoot(markerDir);
403
414
  try {
404
- const names = (await readdir(root)).filter((name) => name.includes(".json.claim-")).sort();
415
+ const names = (await readdir(root)).filter((name) => name.endsWith(CLAIM_SUFFIX)).sort();
405
416
  for (const name of names) {
406
- const pid = Number(name.match(/\.claim-(\d+)-/)?.[1]);
407
- if (Number.isInteger(pid) && processIsAlive(pid)) continue;
408
417
  const claimPath = join(root, name);
409
- const originalPath = join(root, name.slice(0, name.indexOf(".claim-")));
418
+ const content = await readFile(claimPath, "utf8").catch(() => undefined);
419
+ const info = await stat(claimPath).catch(() => undefined);
420
+ // A live session releases and recreates claims at this same path, so only age plus an
421
+ // unchanged-identity recheck can tell an abandoned claim from one that was just taken.
422
+ if (content === undefined || !info || Date.now() - info.mtimeMs < CLAIM_STALE_MS) continue;
423
+ const pid = parseClaimOwner(content);
424
+ if (pid !== undefined && processIsAlive(pid)) continue;
425
+ const recheck = await readFile(claimPath, "utf8").catch(() => undefined);
426
+ const recheckInfo = await stat(claimPath).catch(() => undefined);
427
+ if (recheck !== content || recheckInfo?.mtimeMs !== info.mtimeMs) continue;
410
428
  try {
411
- await rename(claimPath, originalPath);
429
+ await unlink(claimPath);
412
430
  } catch {}
413
431
  }
414
432
  } catch {}
415
433
  }
416
434
 
417
435
  async function claimPending(path: string): Promise<ClaimedFinding | undefined> {
418
- const claimPath = `${path}.claim-${process.pid}-${randomUUID()}`;
436
+ const claimPath = `${path}${CLAIM_SUFFIX}`;
419
437
  try {
420
- await rename(path, claimPath);
438
+ await writeFile(claimPath, `${JSON.stringify({ pid: process.pid })}\n`, { flag: "wx", mode: 0o600 });
421
439
  } catch {
422
440
  return undefined;
423
441
  }
424
442
  try {
425
443
  return {
426
444
  claimPath,
427
- originalPath: path,
428
- finding: JSON.parse(await readFile(claimPath, "utf8")) as PairFinding,
445
+ pendingPath: path,
446
+ finding: JSON.parse(await readFile(path, "utf8")) as PairFinding,
429
447
  };
430
448
  } catch {
431
- try {
432
- await unlink(claimPath);
433
- } catch {}
449
+ for (const target of [path, claimPath]) {
450
+ try {
451
+ await unlink(target);
452
+ } catch {}
453
+ }
434
454
  return undefined;
435
455
  }
436
456
  }
@@ -498,30 +518,39 @@ export function registerCodexPair(pi: ExtensionAPI): void {
498
518
  return false;
499
519
  };
500
520
 
521
+ const releaseClaim = async (claimed: ClaimedFinding) => {
522
+ try {
523
+ await unlink(claimed.claimPath);
524
+ } catch {}
525
+ };
526
+
527
+ const consumeClaimed = async (claimed: ClaimedFinding) => {
528
+ try {
529
+ await unlink(claimed.pendingPath);
530
+ } catch {}
531
+ await releaseClaim(claimed);
532
+ };
533
+
501
534
  const deliverClaimed = async (claimed: ClaimedFinding) => {
502
535
  if (closed) {
503
- try {
504
- await rename(claimed.claimPath, claimed.originalPath);
505
- } catch {}
536
+ await releaseClaim(claimed);
506
537
  return;
507
538
  }
508
539
  try {
509
540
  const current = await readFile(claimed.finding.file);
510
541
  if (hash(current.toString("utf8")) !== claimed.finding.contentHash) {
511
- await unlink(claimed.claimPath);
542
+ await consumeClaimed(claimed);
512
543
  return;
513
544
  }
514
545
  if (closed) {
515
- await rename(claimed.claimPath, claimed.originalPath);
546
+ await releaseClaim(claimed);
516
547
  return;
517
548
  }
518
549
  sendFinding(pi, claimed.finding);
519
550
  await markReviewed(claimed.finding);
520
- await unlink(claimed.claimPath);
551
+ await consumeClaimed(claimed);
521
552
  } catch (error) {
522
- try {
523
- await rename(claimed.claimPath, claimed.originalPath);
524
- } catch {}
553
+ await releaseClaim(claimed);
525
554
  throw error;
526
555
  }
527
556
  };
@@ -531,8 +560,10 @@ export function registerCodexPair(pi: ExtensionAPI): void {
531
560
  while (!closed) {
532
561
  let names: string[];
533
562
  try {
534
- names = (await readdir(pendingRoot(markerDir)))
535
- .filter((name) => name.endsWith(".json"))
563
+ const entries = await readdir(pendingRoot(markerDir));
564
+ const claimedNames = new Set(entries.filter((name) => name.endsWith(CLAIM_SUFFIX)));
565
+ names = entries
566
+ .filter((name) => name.endsWith(".json") && !claimedNames.has(`${name}${CLAIM_SUFFIX}`))
536
567
  .sort()
537
568
  .slice(0, 8);
538
569
  } catch {
@@ -860,6 +891,7 @@ export const __testing = {
860
891
  activeConcerns,
861
892
  adaptiveContent,
862
893
  allowlistPath,
894
+ claimPending,
863
895
  deleteScheduledIfOwned,
864
896
  findMarkerUp,
865
897
  normalizeToolPath,