grok-search-cli 0.1.2 → 0.1.3
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/README.md +33 -17
- package/README.zh.md +33 -17
- package/dist/cli.js +97 -552
- package/dist/index.js +2 -0
- package/dist/search-DcS355m9.js +573 -0
- package/dist/src/args.d.ts +4 -0
- package/dist/src/cli.d.ts +1 -0
- package/dist/src/config.d.ts +35 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/openrouter.d.ts +38 -0
- package/dist/src/openrouter.test.d.ts +1 -0
- package/dist/src/output.d.ts +19 -0
- package/dist/src/providers.d.ts +12 -0
- package/dist/src/search.d.ts +34 -0
- package/dist/src/skill.d.ts +2 -0
- package/dist/src/types.d.ts +121 -0
- package/package.json +15 -6
package/dist/cli.js
CHANGED
|
@@ -1,162 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import l from "conf";
|
|
7
|
-
import { createOpenAICompatible as ee } from "@ai-sdk/openai-compatible";
|
|
8
|
-
import { createXai as te, xai as u } from "@ai-sdk/xai";
|
|
9
|
-
import { fileURLToPath as ne } from "node:url";
|
|
10
|
-
//#region src/config.ts
|
|
11
|
-
var d = "grok-4-1-fast-non-reasoning", f = c.join(s.homedir(), ".config", "grok-search-cli");
|
|
12
|
-
function p(e) {
|
|
13
|
-
return typeof e == "string" && e.trim() || void 0;
|
|
14
|
-
}
|
|
15
|
-
function m() {
|
|
16
|
-
return {
|
|
17
|
-
XAI_API_KEY: "",
|
|
18
|
-
XAI_MODEL: d,
|
|
19
|
-
XAI_BASE_URL: "",
|
|
20
|
-
XAI_COMPAT_MODE: !1,
|
|
21
|
-
_examples: {
|
|
22
|
-
xai: {
|
|
23
|
-
XAI_API_KEY: "your_xai_api_key",
|
|
24
|
-
XAI_MODEL: "grok-4-1-fast-non-reasoning"
|
|
25
|
-
},
|
|
26
|
-
openrouter: {
|
|
27
|
-
XAI_API_KEY: "your_openrouter_api_key",
|
|
28
|
-
XAI_MODEL: "x-ai/grok-4.1-fast",
|
|
29
|
-
XAI_BASE_URL: "https://openrouter.ai/api/v1"
|
|
30
|
-
},
|
|
31
|
-
yunwu: {
|
|
32
|
-
XAI_API_KEY: "your_yunwu_api_key",
|
|
33
|
-
XAI_MODEL: "grok-4-fast",
|
|
34
|
-
XAI_BASE_URL: "https://yunwu.ai/v1",
|
|
35
|
-
XAI_COMPAT_MODE: !0
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
function h() {
|
|
41
|
-
try {
|
|
42
|
-
return new l({
|
|
43
|
-
projectName: "grok-search-cli",
|
|
44
|
-
configName: "config",
|
|
45
|
-
cwd: f,
|
|
46
|
-
defaults: m()
|
|
47
|
-
});
|
|
48
|
-
} catch (e) {
|
|
49
|
-
let t = e instanceof Error ? e.message : String(e);
|
|
50
|
-
throw Error(`Failed to initialize user config: ${t}`);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
var g = h(), _ = g.path;
|
|
54
|
-
function v() {
|
|
55
|
-
if (i(c.dirname(_), { recursive: !0 }), !r(_)) {
|
|
56
|
-
o(_, `${JSON.stringify(m(), null, 2)}\n`, "utf8");
|
|
57
|
-
try {
|
|
58
|
-
n(_, 384);
|
|
59
|
-
} catch {}
|
|
60
|
-
}
|
|
61
|
-
return _;
|
|
62
|
-
}
|
|
63
|
-
function y() {
|
|
64
|
-
let e = g.store;
|
|
65
|
-
return {
|
|
66
|
-
apiKey: p(process.env.XAI_API_KEY) ?? e?.XAI_API_KEY,
|
|
67
|
-
model: p(process.env.XAI_MODEL) ?? e?.XAI_MODEL ?? d,
|
|
68
|
-
baseUrl: p(process.env.XAI_BASE_URL) ?? e?.XAI_BASE_URL,
|
|
69
|
-
compatModeRaw: process.env.XAI_COMPAT_MODE?.trim() ?? e?.XAI_COMPAT_MODE
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function b() {
|
|
73
|
-
let e = g.store;
|
|
74
|
-
return {
|
|
75
|
-
apiKey: p(process.env.XAI_API_KEY) ? "env" : e?.XAI_API_KEY ? "config" : "missing",
|
|
76
|
-
model: p(process.env.XAI_MODEL) ? "env" : e?.XAI_MODEL ? "config" : "default",
|
|
77
|
-
baseUrl: p(process.env.XAI_BASE_URL) ? "env" : e?.XAI_BASE_URL ? "config" : "default",
|
|
78
|
-
compatMode: process.env.XAI_COMPAT_MODE?.trim() ? "env" : e?.XAI_COMPAT_MODE == null ? "default" : "config"
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
function x() {
|
|
82
|
-
return y().model;
|
|
83
|
-
}
|
|
84
|
-
function S() {
|
|
85
|
-
return y().apiKey;
|
|
86
|
-
}
|
|
87
|
-
function C() {
|
|
88
|
-
return y().baseUrl;
|
|
89
|
-
}
|
|
90
|
-
function re() {
|
|
91
|
-
let e = y(), t = b(), n = E(), r = T(e.baseUrl);
|
|
92
|
-
return {
|
|
93
|
-
configPath: _,
|
|
94
|
-
apiKeyPresent: !!e.apiKey,
|
|
95
|
-
model: e.model,
|
|
96
|
-
baseUrl: e.baseUrl,
|
|
97
|
-
providerKind: r,
|
|
98
|
-
apiMode: n,
|
|
99
|
-
sources: t
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
function w(e) {
|
|
103
|
-
if (!e) return !1;
|
|
104
|
-
try {
|
|
105
|
-
let { hostname: t } = new URL(e);
|
|
106
|
-
return t === "openrouter.ai" || t.endsWith(".openrouter.ai");
|
|
107
|
-
} catch {
|
|
108
|
-
return !1;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
function T(e) {
|
|
112
|
-
if (!e) return "xai";
|
|
113
|
-
if (w(e)) return "openrouter";
|
|
114
|
-
try {
|
|
115
|
-
let { hostname: t } = new URL(e);
|
|
116
|
-
if (t === "x.ai" || t.endsWith(".x.ai")) return "xai";
|
|
117
|
-
} catch {}
|
|
118
|
-
return "third-party";
|
|
119
|
-
}
|
|
120
|
-
function ie() {
|
|
121
|
-
let { compatModeRaw: e, baseUrl: t } = y();
|
|
122
|
-
return T(t) !== "openrouter" && /^(1|true|yes|on)$/i.test(String(e || ""));
|
|
123
|
-
}
|
|
124
|
-
function E() {
|
|
125
|
-
return ie() ? "completion" : "responses";
|
|
126
|
-
}
|
|
127
|
-
function D(e) {
|
|
128
|
-
return T(C()) === "openrouter" && e === "responses" ? "OpenRouter Responses API Beta" : e === "responses" ? "xAI Responses API" : "OpenAI-compatible /chat/completions";
|
|
129
|
-
}
|
|
130
|
-
function O(e, t) {
|
|
131
|
-
if (e === "xai") {
|
|
132
|
-
console.error(t === "responses" ? "xAI Responses API request failed. Check XAI_API_KEY, model name, and search parameters." : "xAI-compatible completion request failed. Check XAI_API_KEY, model name, and gateway settings.");
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
if (e === "openrouter") {
|
|
136
|
-
console.error("OpenRouter request failed. This CLI uses OpenRouter Responses API web search for openrouter.ai endpoints.");
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
console.error("Third-party gateway request failed. Verify the gateway supports the selected API shape and that web search is enabled on the provider side.");
|
|
140
|
-
}
|
|
141
|
-
//#endregion
|
|
2
|
+
import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, p as d, r as f, s as p, t as m, u as h } from "./search-DcS355m9.js";
|
|
3
|
+
import { readFileSync as g } from "node:fs";
|
|
4
|
+
import _ from "node:path";
|
|
5
|
+
import { fileURLToPath as v } from "node:url";
|
|
142
6
|
//#region src/args.ts
|
|
143
|
-
function
|
|
7
|
+
function y(e) {
|
|
144
8
|
process.stderr.write(`${e}\n`), process.exit(1);
|
|
145
9
|
}
|
|
146
|
-
function
|
|
147
|
-
let e =
|
|
10
|
+
function b() {
|
|
11
|
+
let e = o();
|
|
148
12
|
process.stdout.write(`\
|
|
149
13
|
Usage:
|
|
150
14
|
grok-search "<prompt>" [options]
|
|
151
15
|
grok-search doctor
|
|
152
16
|
grok-search skill
|
|
153
17
|
|
|
154
|
-
|
|
18
|
+
Commands:
|
|
155
19
|
doctor Show config and credential diagnostics
|
|
156
20
|
skill Print the bundled skill to stdout
|
|
21
|
+
|
|
22
|
+
Options:
|
|
157
23
|
--model=<id> Override model. Default: ${e}
|
|
158
24
|
--timeout=<seconds> Request timeout. Default: 60
|
|
159
|
-
--
|
|
25
|
+
-h, --help Show this help
|
|
26
|
+
|
|
27
|
+
Advanced Options:
|
|
28
|
+
Most of these are optional and usually not needed for normal research.
|
|
160
29
|
--verbose Print request and token diagnostics
|
|
161
30
|
--allowed-domains=a.com,b.com Web Search allowed domains
|
|
162
31
|
--excluded-domains=a.com,b.com Web Search excluded domains
|
|
@@ -166,22 +35,22 @@ Options:
|
|
|
166
35
|
--to-date=YYYY-MM-DD X Search end date
|
|
167
36
|
--image Enable image understanding
|
|
168
37
|
--video Enable video understanding for X Search
|
|
169
|
-
|
|
38
|
+
--json Output JSON instead of the default text stream
|
|
170
39
|
|
|
171
40
|
Environment:
|
|
172
41
|
XAI_API_KEY Required
|
|
173
42
|
`);
|
|
174
43
|
}
|
|
175
|
-
function
|
|
44
|
+
function x(e) {
|
|
176
45
|
return e ? e.split(",").map((e) => e.trim()).filter(Boolean) : [];
|
|
177
46
|
}
|
|
178
|
-
function
|
|
47
|
+
function S(e, t, n) {
|
|
179
48
|
let r = e.indexOf("=");
|
|
180
49
|
return r >= 0 ? e.slice(r + 1) : t[n + 1];
|
|
181
50
|
}
|
|
182
|
-
function
|
|
51
|
+
function C() {
|
|
183
52
|
return {
|
|
184
|
-
model:
|
|
53
|
+
model: o(),
|
|
185
54
|
timeoutMs: 6e4,
|
|
186
55
|
json: !1,
|
|
187
56
|
verbose: !1,
|
|
@@ -193,19 +62,19 @@ function se() {
|
|
|
193
62
|
enableVideoUnderstanding: !1
|
|
194
63
|
};
|
|
195
64
|
}
|
|
196
|
-
function
|
|
197
|
-
let a =
|
|
198
|
-
return a ||
|
|
65
|
+
function w(e, t, n, r, i) {
|
|
66
|
+
let a = S(e, t, n)?.trim();
|
|
67
|
+
return a || y(`Missing value for ${r}`), i(a), e.includes("=") ? n : n + 1;
|
|
199
68
|
}
|
|
200
|
-
function
|
|
201
|
-
return r(
|
|
69
|
+
function T(e, t, n, r) {
|
|
70
|
+
return r(x(S(e, t, n))), e.includes("=") ? n : n + 1;
|
|
202
71
|
}
|
|
203
|
-
function
|
|
204
|
-
let i =
|
|
205
|
-
return (!i || !Number.isFinite(a) || a <= 0) &&
|
|
72
|
+
function E(e, t, n, r) {
|
|
73
|
+
let i = S(e, t, n)?.trim(), a = Number(i);
|
|
74
|
+
return (!i || !Number.isFinite(a) || a <= 0) && y("Invalid value for --timeout. Use a number of seconds > 0."), r.timeoutMs = Math.round(a * 1e3), e.includes("=") ? n : n + 1;
|
|
206
75
|
}
|
|
207
|
-
function
|
|
208
|
-
let t =
|
|
76
|
+
function D(e) {
|
|
77
|
+
let t = C(), n = [];
|
|
209
78
|
for (let r = 0; r < e.length; r += 1) {
|
|
210
79
|
let i = e[r];
|
|
211
80
|
if (!i.startsWith("-")) {
|
|
@@ -229,493 +98,169 @@ function N(e) {
|
|
|
229
98
|
continue;
|
|
230
99
|
}
|
|
231
100
|
if (i.startsWith("--model")) {
|
|
232
|
-
r =
|
|
101
|
+
r = w(i, e, r, "--model", (e) => {
|
|
233
102
|
t.model = e;
|
|
234
103
|
});
|
|
235
104
|
continue;
|
|
236
105
|
}
|
|
237
106
|
if (i.startsWith("--timeout")) {
|
|
238
|
-
r =
|
|
107
|
+
r = E(i, e, r, t);
|
|
239
108
|
continue;
|
|
240
109
|
}
|
|
241
110
|
if (i.startsWith("--allowed-domains")) {
|
|
242
|
-
r =
|
|
111
|
+
r = T(i, e, r, (e) => {
|
|
243
112
|
t.allowedDomains = e;
|
|
244
113
|
});
|
|
245
114
|
continue;
|
|
246
115
|
}
|
|
247
116
|
if (i.startsWith("--excluded-domains")) {
|
|
248
|
-
r =
|
|
117
|
+
r = T(i, e, r, (e) => {
|
|
249
118
|
t.excludedDomains = e;
|
|
250
119
|
});
|
|
251
120
|
continue;
|
|
252
121
|
}
|
|
253
122
|
if (i.startsWith("--allowed-handles")) {
|
|
254
|
-
r =
|
|
123
|
+
r = T(i, e, r, (e) => {
|
|
255
124
|
t.allowedHandles = e;
|
|
256
125
|
});
|
|
257
126
|
continue;
|
|
258
127
|
}
|
|
259
128
|
if (i.startsWith("--excluded-handles")) {
|
|
260
|
-
r =
|
|
129
|
+
r = T(i, e, r, (e) => {
|
|
261
130
|
t.excludedHandles = e;
|
|
262
131
|
});
|
|
263
132
|
continue;
|
|
264
133
|
}
|
|
265
134
|
if (i.startsWith("--from-date")) {
|
|
266
|
-
r =
|
|
135
|
+
r = w(i, e, r, "--from-date", (e) => {
|
|
267
136
|
t.fromDate = e;
|
|
268
137
|
});
|
|
269
138
|
continue;
|
|
270
139
|
}
|
|
271
140
|
if (i.startsWith("--to-date")) {
|
|
272
|
-
r =
|
|
141
|
+
r = w(i, e, r, "--to-date", (e) => {
|
|
273
142
|
t.toDate = e;
|
|
274
143
|
});
|
|
275
144
|
continue;
|
|
276
145
|
}
|
|
277
|
-
|
|
146
|
+
y(`Unknown option: ${i}`);
|
|
278
147
|
}
|
|
279
148
|
let r = n.join(" ").trim();
|
|
280
|
-
return r ||
|
|
149
|
+
return r || y("Missing prompt."), t.allowedDomains.length > 0 && t.excludedDomains.length > 0 && y("Use either --allowed-domains or --excluded-domains, not both."), t.allowedHandles.length > 0 && t.excludedHandles.length > 0 && y("Use either --allowed-handles or --excluded-handles, not both."), {
|
|
281
150
|
command: "all",
|
|
282
151
|
prompt: r,
|
|
283
152
|
options: t
|
|
284
153
|
};
|
|
285
154
|
}
|
|
286
|
-
function
|
|
287
|
-
if ((e.length === 0 || e.includes("--help") || e.includes("-h")) && (
|
|
155
|
+
function O(e) {
|
|
156
|
+
if ((e.length === 0 || e.includes("--help") || e.includes("-h")) && (b(), process.exit(0)), e[0] === "skill") {
|
|
288
157
|
let t = e.filter((e, t) => t > 0 && e.startsWith("-") && e !== "--help" && e !== "-h");
|
|
289
|
-
return t.length > 0 &&
|
|
158
|
+
return t.length > 0 && y(`Unknown option: ${t[0]}`), { command: "skill" };
|
|
290
159
|
}
|
|
291
160
|
if (e[0] === "doctor") {
|
|
292
161
|
let t = e.filter((e, t) => t > 0 && e.startsWith("-") && e !== "--help" && e !== "-h");
|
|
293
|
-
return t.length > 0 &&
|
|
162
|
+
return t.length > 0 && y(`Unknown option: ${t[0]}`), { command: "doctor" };
|
|
294
163
|
}
|
|
295
|
-
return
|
|
296
|
-
}
|
|
297
|
-
//#endregion
|
|
298
|
-
//#region src/openrouter.ts
|
|
299
|
-
function F(e) {
|
|
300
|
-
let t = {};
|
|
301
|
-
return e.allowedDomains.length > 0 && (t.allowed_domains = e.allowedDomains), e.excludedDomains.length > 0 && (t.excluded_domains = e.excludedDomains), I(t) ? {
|
|
302
|
-
type: "openrouter:web_search",
|
|
303
|
-
parameters: t
|
|
304
|
-
} : { type: "openrouter:web_search" };
|
|
305
|
-
}
|
|
306
|
-
function I(e) {
|
|
307
|
-
return Object.keys(e).length > 0;
|
|
308
|
-
}
|
|
309
|
-
function L(e, t, n) {
|
|
310
|
-
return {
|
|
311
|
-
model: t.model,
|
|
312
|
-
input: e,
|
|
313
|
-
tools: [F(t)],
|
|
314
|
-
stream: n
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
async function R(e) {
|
|
318
|
-
if (!e.ok) throw Error(await e.text());
|
|
319
|
-
return e;
|
|
320
|
-
}
|
|
321
|
-
function z(e) {
|
|
322
|
-
return (e.output?.find((e) => e.type === "message"))?.content?.find((e) => e.type === "output_text")?.text ?? "";
|
|
323
|
-
}
|
|
324
|
-
function B(e) {
|
|
325
|
-
return ((e.output?.find((e) => e.type === "message"))?.content?.find((e) => e.type === "output_text"))?.annotations?.filter((e) => e.type === "url_citation").map((e) => ({
|
|
326
|
-
sourceType: "url_citation",
|
|
327
|
-
url: e.url
|
|
328
|
-
})) ?? [];
|
|
329
|
-
}
|
|
330
|
-
function V(e) {
|
|
331
|
-
return {
|
|
332
|
-
inputTokens: e?.input_tokens,
|
|
333
|
-
outputTokens: e?.output_tokens,
|
|
334
|
-
totalTokens: e?.total_tokens,
|
|
335
|
-
outputTokenDetails: {
|
|
336
|
-
textTokens: e?.output_tokens,
|
|
337
|
-
reasoningTokens: void 0
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
function H(e) {
|
|
342
|
-
return {
|
|
343
|
-
text: z(e),
|
|
344
|
-
finishReason: e.status ?? "unknown",
|
|
345
|
-
usage: V(e.usage),
|
|
346
|
-
sources: B(e)
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
async function U(e) {
|
|
350
|
-
return R(await fetch(`${e.baseUrl}/responses`, {
|
|
351
|
-
method: "POST",
|
|
352
|
-
headers: {
|
|
353
|
-
Authorization: `Bearer ${e.apiKey}`,
|
|
354
|
-
"Content-Type": "application/json"
|
|
355
|
-
},
|
|
356
|
-
body: JSON.stringify(e.body),
|
|
357
|
-
signal: e.abortSignal
|
|
358
|
-
}));
|
|
359
|
-
}
|
|
360
|
-
function W(e) {
|
|
361
|
-
return (t) => ({
|
|
362
|
-
...t,
|
|
363
|
-
tools: [F(e)]
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
function G(e) {
|
|
367
|
-
if (!e.startsWith("data: ")) return { type: "ignore" };
|
|
368
|
-
let t = e.slice(6);
|
|
369
|
-
if (t === "[DONE]") return { type: "done" };
|
|
370
|
-
let n = JSON.parse(t);
|
|
371
|
-
return n.type === "response.output_text.delta" && typeof n.delta == "string" ? {
|
|
372
|
-
type: "delta",
|
|
373
|
-
text: n.delta
|
|
374
|
-
} : n.type === "response.completed" ? {
|
|
375
|
-
type: "completed",
|
|
376
|
-
response: n.response
|
|
377
|
-
} : { type: "ignore" };
|
|
378
|
-
}
|
|
379
|
-
async function le(e) {
|
|
380
|
-
return H(await (await U({
|
|
381
|
-
baseUrl: e.baseUrl,
|
|
382
|
-
apiKey: e.apiKey,
|
|
383
|
-
body: L(e.prompt, e.options, !1),
|
|
384
|
-
abortSignal: e.abortSignal
|
|
385
|
-
})).json());
|
|
386
|
-
}
|
|
387
|
-
async function ue(e) {
|
|
388
|
-
let t = (await U({
|
|
389
|
-
baseUrl: e.baseUrl,
|
|
390
|
-
apiKey: e.apiKey,
|
|
391
|
-
body: L(e.prompt, e.options, !0),
|
|
392
|
-
abortSignal: e.abortSignal
|
|
393
|
-
})).body?.getReader();
|
|
394
|
-
if (!t) throw Error("OpenRouter streaming response body is missing.");
|
|
395
|
-
let n = new TextDecoder(), r = "", i, a, o = new Promise((e, t) => {
|
|
396
|
-
i = e, a = t;
|
|
397
|
-
}), s = !1, c = (async function* () {
|
|
398
|
-
try {
|
|
399
|
-
for (;;) {
|
|
400
|
-
let { done: e, value: a } = await t.read();
|
|
401
|
-
if (e) break;
|
|
402
|
-
r += n.decode(a, { stream: !0 });
|
|
403
|
-
let o = r.split("\n");
|
|
404
|
-
r = o.pop() ?? "";
|
|
405
|
-
for (let e of o) {
|
|
406
|
-
let t = G(e);
|
|
407
|
-
if (t.type === "delta") {
|
|
408
|
-
yield t.text;
|
|
409
|
-
continue;
|
|
410
|
-
}
|
|
411
|
-
if (t.type === "completed") {
|
|
412
|
-
s = !0, i?.(t.response);
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
if (t.type === "done") return;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
s || a?.(/* @__PURE__ */ Error("OpenRouter stream ended before response.completed."));
|
|
419
|
-
} catch (e) {
|
|
420
|
-
throw a?.(e), e;
|
|
421
|
-
}
|
|
422
|
-
})(), l = o.then(H);
|
|
423
|
-
return {
|
|
424
|
-
textStream: c,
|
|
425
|
-
text: l.then((e) => e.text),
|
|
426
|
-
finishReason: l.then((e) => e.finishReason),
|
|
427
|
-
usage: l.then((e) => e.usage),
|
|
428
|
-
sources: l.then((e) => e.sources)
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
//#endregion
|
|
432
|
-
//#region src/output.ts
|
|
433
|
-
function K({ model: e, finishReason: t, requestApi: n, baseUrl: r, durationMs: i, firstTokenLatencyMs: a, usage: o }) {
|
|
434
|
-
let s = o ?? {}, c = s.outputTokens, l = s.outputTokenDetails?.reasoningTokens;
|
|
435
|
-
return {
|
|
436
|
-
model: e,
|
|
437
|
-
finishReason: t,
|
|
438
|
-
requestApi: n,
|
|
439
|
-
baseUrl: r,
|
|
440
|
-
durationMs: i,
|
|
441
|
-
firstTokenLatencyMs: a,
|
|
442
|
-
tokensPerSecond: typeof c == "number" && i > 0 ? Number((c * 1e3 / i).toFixed(2)) : void 0,
|
|
443
|
-
usage: {
|
|
444
|
-
inputTokens: s.inputTokens,
|
|
445
|
-
outputTokens: c,
|
|
446
|
-
reasoningTokens: l,
|
|
447
|
-
totalTokens: s.totalTokens
|
|
448
|
-
}
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
function de(e) {
|
|
452
|
-
process.stdout.write("\nVerbose:\n"), process.stdout.write(`Model: ${e.model}\n`), process.stdout.write(`Finish reason: ${e.finishReason}\n`), process.stdout.write(`Request API: ${e.requestApi}\n`), e.baseUrl && process.stdout.write(`Base URL: ${e.baseUrl}\n`);
|
|
453
|
-
let t = [`Duration: ${(e.durationMs / 1e3).toFixed(2)}s`];
|
|
454
|
-
e.firstTokenLatencyMs != null && t.push(`first token ${(e.firstTokenLatencyMs / 1e3).toFixed(2)}s`), process.stdout.write(`${t.join(", ")}\n`);
|
|
455
|
-
let n = [
|
|
456
|
-
e.usage.inputTokens == null ? void 0 : `input=${e.usage.inputTokens}`,
|
|
457
|
-
e.usage.outputTokens == null ? void 0 : `output=${e.usage.outputTokens}`,
|
|
458
|
-
e.usage.reasoningTokens == null ? void 0 : `reasoning=${e.usage.reasoningTokens}`,
|
|
459
|
-
e.usage.totalTokens == null ? void 0 : `total=${e.usage.totalTokens}`
|
|
460
|
-
].filter(Boolean);
|
|
461
|
-
n.length > 0 && process.stdout.write(`Usage: ${n.join(", ")}\n`), e.tokensPerSecond != null && process.stdout.write(`TPS: ${e.tokensPerSecond}\n`);
|
|
462
|
-
}
|
|
463
|
-
function q(e) {
|
|
464
|
-
process.stdout.write(`${e.text}\n`), e.verbose && de(e.verbose);
|
|
465
|
-
}
|
|
466
|
-
async function fe(e) {
|
|
467
|
-
let t = !1, n = !1, r;
|
|
468
|
-
for await (let i of e.stream.textStream) r ??= Date.now() - e.startedAt, t = !0, n = i.endsWith("\n"), process.stdout.write(i);
|
|
469
|
-
(!t || !n) && process.stdout.write("\n");
|
|
470
|
-
let i = await e.stream.usage, a = await e.stream.finishReason ?? "unknown", o = {
|
|
471
|
-
...e.payload,
|
|
472
|
-
text: await e.stream.text,
|
|
473
|
-
finishReason: a,
|
|
474
|
-
usage: i ?? null,
|
|
475
|
-
sources: await e.stream.sources ?? [],
|
|
476
|
-
verbose: e.includeVerbose ? K({
|
|
477
|
-
model: e.payload.model,
|
|
478
|
-
finishReason: a,
|
|
479
|
-
requestApi: e.requestApi,
|
|
480
|
-
baseUrl: e.baseUrl,
|
|
481
|
-
durationMs: Date.now() - e.startedAt,
|
|
482
|
-
firstTokenLatencyMs: r,
|
|
483
|
-
usage: i
|
|
484
|
-
}) : void 0
|
|
485
|
-
};
|
|
486
|
-
process.stdout.write("\n"), q(o);
|
|
487
|
-
}
|
|
488
|
-
//#endregion
|
|
489
|
-
//#region src/providers.ts
|
|
490
|
-
function J(e) {
|
|
491
|
-
return {
|
|
492
|
-
web_search: u.tools.webSearch({
|
|
493
|
-
allowedDomains: e.allowedDomains.length > 0 ? e.allowedDomains : void 0,
|
|
494
|
-
excludedDomains: e.excludedDomains.length > 0 ? e.excludedDomains : void 0,
|
|
495
|
-
enableImageUnderstanding: e.enableImageUnderstanding || void 0
|
|
496
|
-
}),
|
|
497
|
-
x_search: u.tools.xSearch({
|
|
498
|
-
allowedXHandles: e.allowedHandles.length > 0 ? e.allowedHandles : void 0,
|
|
499
|
-
excludedXHandles: e.excludedHandles.length > 0 ? e.excludedHandles : void 0,
|
|
500
|
-
fromDate: e.fromDate,
|
|
501
|
-
toDate: e.toDate,
|
|
502
|
-
enableImageUnderstanding: e.enableImageUnderstanding || void 0,
|
|
503
|
-
enableVideoUnderstanding: e.enableVideoUnderstanding || void 0
|
|
504
|
-
})
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
function Y() {
|
|
508
|
-
let e = C();
|
|
509
|
-
return e ? te({ baseURL: e }) : u;
|
|
510
|
-
}
|
|
511
|
-
function X(e) {
|
|
512
|
-
let t = C();
|
|
513
|
-
return ee({
|
|
514
|
-
name: "compat",
|
|
515
|
-
apiKey: S(),
|
|
516
|
-
baseURL: t || "https://api.x.ai/v1",
|
|
517
|
-
transformRequestBody: w(t) ? W(e) : void 0
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
function pe(e) {
|
|
521
|
-
return e.allowedDomains.length > 0 || e.excludedDomains.length > 0 || e.allowedHandles.length > 0 || e.excludedHandles.length > 0 || typeof e.fromDate == "string" || typeof e.toDate == "string" || e.enableImageUnderstanding || e.enableVideoUnderstanding;
|
|
522
|
-
}
|
|
523
|
-
function me(e) {
|
|
524
|
-
return e.allowedHandles.length > 0 || e.excludedHandles.length > 0 || typeof e.fromDate == "string" || typeof e.toDate == "string" || e.enableImageUnderstanding || e.enableVideoUnderstanding;
|
|
164
|
+
return D(e);
|
|
525
165
|
}
|
|
526
166
|
//#endregion
|
|
527
167
|
//#region src/skill.ts
|
|
528
|
-
var
|
|
529
|
-
function
|
|
530
|
-
let t = [
|
|
168
|
+
var k = "grok-search-cli", A = v(import.meta.url), j = _.dirname(A);
|
|
169
|
+
function M(...e) {
|
|
170
|
+
let t = [_.resolve(j, "..", "skills", k, ...e), _.resolve(j, "..", "..", "skills", k, ...e)];
|
|
531
171
|
for (let e of t) try {
|
|
532
|
-
return
|
|
172
|
+
return g(e, "utf8");
|
|
533
173
|
} catch (e) {
|
|
534
174
|
if (e.code !== "ENOENT") throw e;
|
|
535
175
|
}
|
|
536
|
-
throw Error(`Bundled skill file not found for ${
|
|
176
|
+
throw Error(`Bundled skill file not found for ${k}: ${e.join("/")}`);
|
|
537
177
|
}
|
|
538
|
-
function
|
|
539
|
-
return
|
|
178
|
+
function N() {
|
|
179
|
+
return M("SKILL.md");
|
|
540
180
|
}
|
|
541
181
|
//#endregion
|
|
542
182
|
//#region src/cli.ts
|
|
543
|
-
function
|
|
544
|
-
let e =
|
|
183
|
+
function P() {
|
|
184
|
+
let e = l();
|
|
545
185
|
if (process.stdout.write("Doctor:\n"), process.stdout.write(`Config path: ${e.configPath}\n`), process.stdout.write(`API key: ${e.apiKeyPresent ? "present" : "missing"} (${e.sources.apiKey})\n`), process.stdout.write(`Model: ${e.model} (${e.sources.model})\n`), process.stdout.write(`Base URL: ${e.baseUrl ?? "(xAI default)"} (${e.sources.baseUrl})\n`), process.stdout.write(`Compat mode source: ${e.sources.compatMode}\n`), process.stdout.write(`Provider: ${e.providerKind}\n`), process.stdout.write(`API mode: ${e.apiMode}\n`), process.stdout.write(`Status: ${e.apiKeyPresent ? "OK" : "NOT READY"}\n`), !e.apiKeyPresent) {
|
|
546
|
-
let e =
|
|
186
|
+
let e = r();
|
|
547
187
|
process.stdout.write(`Action: edit ${e}\n`);
|
|
548
188
|
}
|
|
549
189
|
}
|
|
550
|
-
function
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
let n = C();
|
|
556
|
-
return e === "completion" && pe(t) && !w(n);
|
|
557
|
-
}
|
|
558
|
-
function xe(e, t) {
|
|
559
|
-
return $(e) && me(t);
|
|
560
|
-
}
|
|
561
|
-
function $(e) {
|
|
562
|
-
return T(C()) === "openrouter" && e === "responses";
|
|
563
|
-
}
|
|
564
|
-
function Se(e) {
|
|
565
|
-
return process.stdout.isTTY && !e;
|
|
566
|
-
}
|
|
567
|
-
function Ce(e) {
|
|
568
|
-
return {
|
|
569
|
-
command: e.command,
|
|
570
|
-
apiMode: e.apiMode,
|
|
571
|
-
model: e.model,
|
|
572
|
-
prompt: e.prompt,
|
|
573
|
-
text: e.result.text,
|
|
574
|
-
finishReason: e.result.finishReason ?? "unknown",
|
|
575
|
-
usage: e.result.usage ?? null,
|
|
576
|
-
sources: e.result.sources ?? [],
|
|
577
|
-
verbose: e.verbose ? K({
|
|
578
|
-
model: e.model,
|
|
579
|
-
finishReason: e.result.finishReason ?? "unknown",
|
|
580
|
-
requestApi: e.requestApi,
|
|
581
|
-
baseUrl: e.baseUrl,
|
|
582
|
-
durationMs: Date.now() - e.startedAt,
|
|
583
|
-
usage: e.result.usage ?? null
|
|
584
|
-
}) : void 0
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
function we(e) {
|
|
588
|
-
if (e.apiMode === "responses") {
|
|
589
|
-
let n = t({
|
|
590
|
-
model: Y().responses(e.model),
|
|
591
|
-
prompt: e.prompt,
|
|
592
|
-
tools: J(e.options),
|
|
593
|
-
abortSignal: e.abortSignal
|
|
594
|
-
});
|
|
595
|
-
return {
|
|
596
|
-
textStream: n.textStream,
|
|
597
|
-
text: n.text,
|
|
598
|
-
finishReason: n.finishReason,
|
|
599
|
-
usage: n.usage,
|
|
600
|
-
sources: n.sources
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
let n = t({
|
|
604
|
-
model: X(e.options)(e.model),
|
|
605
|
-
prompt: e.prompt,
|
|
606
|
-
abortSignal: e.abortSignal
|
|
607
|
-
});
|
|
608
|
-
return {
|
|
609
|
-
textStream: n.textStream,
|
|
610
|
-
text: n.text,
|
|
611
|
-
finishReason: n.finishReason,
|
|
612
|
-
usage: n.usage,
|
|
613
|
-
sources: n.sources
|
|
614
|
-
};
|
|
615
|
-
}
|
|
616
|
-
async function Te(t) {
|
|
617
|
-
if (t.apiMode === "responses") {
|
|
618
|
-
let n = await e({
|
|
619
|
-
model: Y().responses(t.model),
|
|
620
|
-
prompt: t.prompt,
|
|
621
|
-
tools: J(t.options),
|
|
622
|
-
abortSignal: t.abortSignal
|
|
623
|
-
});
|
|
624
|
-
return {
|
|
625
|
-
text: n.text,
|
|
626
|
-
finishReason: n.finishReason ?? "unknown",
|
|
627
|
-
usage: n.usage ?? null,
|
|
628
|
-
sources: n.sources ?? []
|
|
629
|
-
};
|
|
190
|
+
function F() {
|
|
191
|
+
try {
|
|
192
|
+
return s();
|
|
193
|
+
} catch (e) {
|
|
194
|
+
y(e instanceof Error ? e.message : String(e));
|
|
630
195
|
}
|
|
631
|
-
let n = await e({
|
|
632
|
-
model: X(t.options)(t.model),
|
|
633
|
-
prompt: t.prompt,
|
|
634
|
-
abortSignal: t.abortSignal
|
|
635
|
-
});
|
|
636
|
-
return {
|
|
637
|
-
text: n.text,
|
|
638
|
-
finishReason: n.finishReason ?? "unknown",
|
|
639
|
-
usage: n.usage ?? null,
|
|
640
|
-
sources: n.sources ?? []
|
|
641
|
-
};
|
|
642
196
|
}
|
|
643
|
-
async function
|
|
644
|
-
await
|
|
645
|
-
stream:
|
|
646
|
-
prompt: e.prompt,
|
|
647
|
-
options: e.options,
|
|
648
|
-
baseUrl: e.baseUrl || "https://openrouter.ai/api/v1",
|
|
649
|
-
apiKey: e.apiKey,
|
|
650
|
-
abortSignal: e.abortSignal
|
|
651
|
-
}) : we(e),
|
|
197
|
+
async function I(e) {
|
|
198
|
+
await h({
|
|
199
|
+
stream: await n(e),
|
|
652
200
|
payload: {
|
|
653
201
|
command: "all",
|
|
654
202
|
apiMode: e.apiMode,
|
|
655
|
-
model: e.model,
|
|
203
|
+
model: e.options.model,
|
|
656
204
|
prompt: e.prompt
|
|
657
205
|
},
|
|
658
206
|
includeVerbose: e.options.verbose,
|
|
659
207
|
requestApi: e.requestApi,
|
|
660
|
-
baseUrl: e.baseUrl,
|
|
208
|
+
baseUrl: e.runtimeConfig.baseUrl,
|
|
661
209
|
startedAt: e.startedAt
|
|
662
210
|
});
|
|
663
211
|
}
|
|
664
|
-
async function
|
|
665
|
-
let
|
|
666
|
-
prompt: e.prompt,
|
|
667
|
-
options: e.options,
|
|
668
|
-
baseUrl: e.baseUrl || "https://openrouter.ai/api/v1",
|
|
669
|
-
apiKey: e.apiKey,
|
|
670
|
-
abortSignal: e.abortSignal
|
|
671
|
-
}) : await Te(e), n = Ce({
|
|
212
|
+
async function L(e, t) {
|
|
213
|
+
let n = await p(e), r = f({
|
|
672
214
|
command: "all",
|
|
673
215
|
apiMode: e.apiMode,
|
|
674
|
-
model: e.model,
|
|
216
|
+
model: e.options.model,
|
|
675
217
|
prompt: e.prompt,
|
|
676
|
-
result:
|
|
218
|
+
result: n,
|
|
677
219
|
verbose: e.options.verbose,
|
|
678
220
|
requestApi: e.requestApi,
|
|
679
|
-
baseUrl: e.baseUrl,
|
|
221
|
+
baseUrl: e.runtimeConfig.baseUrl,
|
|
680
222
|
startedAt: e.startedAt
|
|
681
223
|
});
|
|
682
|
-
if (
|
|
683
|
-
process.stdout.write(`${JSON.stringify(
|
|
224
|
+
if (t) {
|
|
225
|
+
process.stdout.write(`${JSON.stringify(r, null, 2)}\n`);
|
|
684
226
|
return;
|
|
685
227
|
}
|
|
686
|
-
|
|
228
|
+
c(r);
|
|
687
229
|
}
|
|
688
|
-
async function
|
|
689
|
-
let e =
|
|
230
|
+
async function R() {
|
|
231
|
+
let e = O(process.argv.slice(2));
|
|
690
232
|
if (e.command === "skill") {
|
|
691
|
-
process.stdout.write(`${
|
|
233
|
+
process.stdout.write(`${N()}\n`);
|
|
692
234
|
return;
|
|
693
235
|
}
|
|
694
236
|
if (e.command === "doctor") {
|
|
695
|
-
|
|
237
|
+
P();
|
|
696
238
|
return;
|
|
697
239
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
prompt: e.prompt,
|
|
240
|
+
F();
|
|
241
|
+
let n = {
|
|
242
|
+
...m(),
|
|
702
243
|
model: e.options.model,
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
244
|
+
timeoutMs: e.options.timeoutMs,
|
|
245
|
+
verbose: e.options.verbose,
|
|
246
|
+
allowedDomains: e.options.allowedDomains,
|
|
247
|
+
excludedDomains: e.options.excludedDomains,
|
|
248
|
+
allowedHandles: e.options.allowedHandles,
|
|
249
|
+
excludedHandles: e.options.excludedHandles,
|
|
250
|
+
fromDate: e.options.fromDate,
|
|
251
|
+
toDate: e.options.toDate,
|
|
252
|
+
enableImageUnderstanding: e.options.enableImageUnderstanding,
|
|
253
|
+
enableVideoUnderstanding: e.options.enableVideoUnderstanding
|
|
254
|
+
}, r = u(e.prompt, n);
|
|
255
|
+
for (let e of t(r.apiMode, r.runtimeConfig.baseUrl, r.options)) console.error(e);
|
|
256
|
+
if (!e.options.json) {
|
|
257
|
+
await I(r);
|
|
713
258
|
return;
|
|
714
259
|
}
|
|
715
|
-
await
|
|
260
|
+
await L(r, e.options.json);
|
|
716
261
|
}
|
|
717
|
-
|
|
718
|
-
let
|
|
719
|
-
|
|
262
|
+
R().catch((t) => {
|
|
263
|
+
let n = t instanceof Error ? t.stack || t.message : String(t);
|
|
264
|
+
e(a(d()), i()), process.stderr.write(`${n}\n`), process.exit(1);
|
|
720
265
|
});
|
|
721
266
|
//#endregion
|