@opentig/cli 0.1.7 → 0.1.8
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/dist/bin.mjs +1 -4
- package/dist/chunks/{cli-DCPhUVBb.mjs → cli-BgNif2D1.mjs} +1 -1
- package/dist/client/assets/App-9EfSdZB8.js +74 -0
- package/dist/client/assets/CreatePullRequestDialog-BgVrWdkH.js +2 -0
- package/dist/client/assets/DiffWorkspace-Ca2ZUlVn.js +26 -0
- package/dist/client/assets/EditableFileViewer-85aEeMBK.js +1 -0
- package/dist/client/assets/File-DTtWrbYf.js +1 -0
- package/dist/client/assets/{FilesView-BUAz46Qa.js → FilesView-rT5hzb7y.js} +1 -1
- package/dist/client/assets/{GitHubAvatar-Depnd_JA.js → GitHubAvatar-EO1TD_1z.js} +1 -1
- package/dist/client/assets/{HistoryView-Dd4Kr4KN.js → HistoryView-C4c0CqMC.js} +1 -1
- package/dist/client/assets/{HtmlFileViewer-C3Qylr9B.js → HtmlFileViewer-bL6T57PQ.js} +1 -1
- package/dist/client/assets/{IconEdit-BHqlqze_.js → IconEdit-DePJMGIi.js} +1 -1
- package/dist/client/assets/{IconFolderPlus-BJIo1hfe.js → IconFolderPlus-ByGyA0Di.js} +1 -1
- package/dist/client/assets/{ImageFileViewer-BJy0ptmR.js → ImageFileViewer-DJaHH3hJ.js} +1 -1
- package/dist/client/assets/{LocalRefsDialog-C1MWMkv1.js → LocalRefsDialog-D9wYZWBg.js} +1 -1
- package/dist/client/assets/MarkdownFileViewer-BNPb9v8u.js +2 -0
- package/dist/client/assets/{PairingPage-DOPAXy3a.js → PairingPage-D9oguvKU.js} +1 -1
- package/dist/client/assets/PierreDiffViewer-8wTLYd5-.js +1 -0
- package/dist/client/assets/{PierreEditBoundary-mxtF7x3F.js → PierreEditBoundary-KzU3HDc2.js} +2 -2
- package/dist/client/assets/{PierreWorkerPool-B_NFnwU-.js → PierreWorkerPool-DH2jp9oe.js} +18 -18
- package/dist/client/assets/{PullRequestDiff-Bcu8Gmrf.js → PullRequestDiff-DK-m07ZP.js} +1 -1
- package/dist/client/assets/{PullRequestViewer-oeDoq-3g.js → PullRequestViewer-CpLwq4o2.js} +2 -2
- package/dist/client/assets/{PullRequestsView-DpTtagTX.js → PullRequestsView-DnvXaJ4t.js} +1 -1
- package/dist/client/assets/{QuickOpenDialog-rjeV0l_J.js → QuickOpenDialog-DIWjfUkt.js} +1 -1
- package/dist/client/assets/RepositoryProjectsDialog-BsQn5Yjr.js +1 -0
- package/dist/client/assets/{SearchView-C-c6oCil.js → SearchView-D-91dtSv.js} +1 -1
- package/dist/client/assets/SettingsDialog-dJUYk2cP.js +9 -0
- package/dist/client/assets/{Viewer-B6qUr83C.js → Viewer-GH-5bJW4.js} +2 -2
- package/dist/client/assets/{abnfDiagram-N423BO3Z-BxGW6tGd.js → abnfDiagram-N423BO3Z-CkHOGdAl.js} +1 -1
- package/dist/client/assets/{arc-CphVLv_F.js → arc-Dj8F8CO5.js} +1 -1
- package/dist/client/assets/{architectureDiagram-T3A2C74G-D9IDzZ6u.js → architectureDiagram-T3A2C74G-g87Y5LXk.js} +1 -1
- package/dist/client/assets/{blockDiagram-VBNYF7ZC-CzCatff9.js → blockDiagram-VBNYF7ZC-D6efB7jD.js} +1 -1
- package/dist/client/assets/{c4Diagram-5PPSVZJV-jvC7ACDE.js → c4Diagram-5PPSVZJV-DoZEC2xg.js} +1 -1
- package/dist/client/assets/channel-Dsy2VD23.js +1 -0
- package/dist/client/assets/{checkbox-DDpujnre.js → checkbox-DYwmgDPS.js} +1 -1
- package/dist/client/assets/{chunk-2GRJ4B5K-CNRn3w2y.js → chunk-2GRJ4B5K-Dr44hDNV.js} +1 -1
- package/dist/client/assets/{chunk-2Q5K7J3B-CnTjXDS8.js → chunk-2Q5K7J3B-YIEyVOOL.js} +1 -1
- package/dist/client/assets/{chunk-5RXB4S5H-8QZZSU3J.js → chunk-5RXB4S5H-gjmGBtkE.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-B2MFN1L0.js → chunk-5VM5RSS4-DCOQko4g.js} +1 -1
- package/dist/client/assets/{chunk-6Q2QTUOP-BRGuFKSr.js → chunk-6Q2QTUOP-DfGlvPVm.js} +1 -1
- package/dist/client/assets/{chunk-GF5L2VYU-CWTKyD7U.js → chunk-GF5L2VYU-CCWOLPVL.js} +1 -1
- package/dist/client/assets/{chunk-JWPE2WC7-rGurufZY.js → chunk-JWPE2WC7-CFRTGh8r.js} +1 -1
- package/dist/client/assets/{chunk-KBJHAD2P-DOwIHyo0.js → chunk-KBJHAD2P-By3wsJVD.js} +1 -1
- package/dist/client/assets/{chunk-RYQCIY6F-qrVd0AV3.js → chunk-RYQCIY6F-C0wmsHmy.js} +1 -1
- package/dist/client/assets/{chunk-XXDRQBXY-BGvaybJK.js → chunk-XXDRQBXY-t3SnJvV_.js} +1 -1
- package/dist/client/assets/classDiagram-JCYQIIEL-BBQJgoWd.js +1 -0
- package/dist/client/assets/classDiagram-v2-OCEON4UE-BBQJgoWd.js +1 -0
- package/dist/client/assets/{vb-D17OF-Vu.js → cmd-BW5THilD.js} +1 -1
- package/dist/client/assets/{cose-bilkent-JH36ORCC-CHgOt-vq.js → cose-bilkent-JH36ORCC-D3VltoVk.js} +1 -1
- package/dist/client/assets/{cynefin-VYW2F7L2-DX7Kb3Ft.js → cynefin-VYW2F7L2-DwLwbeoe.js} +1 -1
- package/dist/client/assets/{cynefinDiagram-MW4NZA55-B4MgYgbV.js → cynefinDiagram-MW4NZA55-B23kuaQF.js} +1 -1
- package/dist/client/assets/{dagre-VZM6K2ZE-xG9l95NU.js → dagre-VZM6K2ZE-SgMrTr2p.js} +1 -1
- package/dist/client/assets/{diagram-7IWD3JNH-BQKb8ivh.js → diagram-7IWD3JNH-C7cQN4aD.js} +1 -1
- package/dist/client/assets/{diagram-B4RE2ZJO-CyIMrtDr.js → diagram-B4RE2ZJO-CzeI3yOw.js} +1 -1
- package/dist/client/assets/{diagram-LBJQPF4R-WuCMu4WW.js → diagram-LBJQPF4R-DhKm4hlI.js} +1 -1
- package/dist/client/assets/{diagram-Q27KOJAE--Oi1nRrR.js → diagram-Q27KOJAE-BXlU6Wp3.js} +1 -1
- package/dist/client/assets/{diagram-UB23O5K3-CP1DXsa_.js → diagram-UB23O5K3-BOwY_YwR.js} +1 -1
- package/dist/client/assets/{ebnfDiagram-BXEA7PRR-C-7jJg9C.js → ebnfDiagram-BXEA7PRR-CuIQuYPa.js} +1 -1
- package/dist/client/assets/{erDiagram-JOGREHBK-FSyqgO_9.js → erDiagram-JOGREHBK-d45NhKfk.js} +1 -1
- package/dist/client/assets/{flowDiagram-UKHOOZJN-y2e2HZHu.js → flowDiagram-UKHOOZJN-Dzq-6qo7.js} +1 -1
- package/dist/client/assets/{ganttDiagram-PKOTCBZU-kZ3m3wwW.js → ganttDiagram-PKOTCBZU-RVlL9mX2.js} +1 -1
- package/dist/client/assets/{gh-utils-DxPHIkD8.js → gh-utils-LsOSydCg.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-DS77QQ5N-3Z9e4WPi.js → gitGraphDiagram-DS77QQ5N-8kEJVUFH.js} +1 -1
- package/dist/client/assets/{index-DDbUjVD9.js → index-BzmFkR37.js} +1 -1
- package/dist/client/assets/{index-ChKJF4C_.js → index-CQcx9aRt.js} +4 -4
- package/dist/client/assets/index-DMbFAH51.css +1 -0
- package/dist/client/assets/{infoDiagram-6WML65LV-TfCo0Rhw.js → infoDiagram-6WML65LV-Co21Ql9M.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-WSZJBQD7-DaXI89rw.js → ishikawaDiagram-WSZJBQD7-BvPB_G97.js} +1 -1
- package/dist/client/assets/{journeyDiagram-NVQOT4AX-C4jS6BVn.js → journeyDiagram-NVQOT4AX-k7x89IE9.js} +1 -1
- package/dist/client/assets/{kanban-definition-27J2QSJJ-bwOtQiC8.js → kanban-definition-27J2QSJJ-BjrgN30t.js} +1 -1
- package/dist/client/assets/{linear-DfZM9J6Z.js → linear-m158kske.js} +1 -1
- package/dist/client/assets/{mermaid.core-B-iLnCqi.js → mermaid.core-C0FKucv-.js} +4 -4
- package/dist/client/assets/{mindmap-definition-FAOFIHXS-DAdKdypB.js → mindmap-definition-FAOFIHXS-CF8noycK.js} +1 -1
- package/dist/client/assets/{pegDiagram-VL7TDLO6-Bl95_ELH.js → pegDiagram-VL7TDLO6-_y7nfJFV.js} +1 -1
- package/dist/client/assets/{pieDiagram-7S7Q4E2Y-DXf4GTLI.js → pieDiagram-7S7Q4E2Y-DhdWHi45.js} +1 -1
- package/dist/client/assets/{platform-BMNQ8V5r.js → platform-Bqt97_Jr.js} +2 -2
- package/dist/client/assets/{quadrantDiagram-CIZ2JOQS-CDiwouFY.js → quadrantDiagram-CIZ2JOQS-BRvEIECQ.js} +1 -1
- package/dist/client/assets/{railroadDiagram-AXF67PYL-CZAR7rja.js → railroadDiagram-AXF67PYL-BgLZ8XU1.js} +1 -1
- package/dist/client/assets/render-markdown-2GjhuGA-.js +280 -0
- package/dist/client/assets/repository-grammars-ixqpb0uW.js +1 -0
- package/dist/client/assets/{requirementDiagram-LRYGKXZP-BklWtcnl.js → requirementDiagram-LRYGKXZP-CX-gxyGF.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-W5VNT64P-CpD7cM5j.js → sankeyDiagram-W5VNT64P-CLSjSU_X.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-SI44F4Z6-BnHPNl9l.js → sequenceDiagram-SI44F4Z6-dGlHyZRB.js} +1 -1
- package/dist/client/assets/{sizeCapture-X5ZJPWSS-D1eo0r-2.js → sizeCapture-X5ZJPWSS-BH3qO9T3.js} +1 -1
- package/dist/client/assets/{stateDiagram-OKZ733FA-ClTacl-d.js → stateDiagram-OKZ733FA-FXxo1iIM.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-UEYNNEHI-DAo7Tfh9.js → stateDiagram-v2-UEYNNEHI-DqxQ14yP.js} +1 -1
- package/dist/client/assets/{swimlanes-SLNWSIFB-_PLbkM5u.js → swimlanes-SLNWSIFB-VJGIuM4S.js} +2 -2
- package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-No0dCAkd.js +8 -0
- package/dist/client/assets/{timeline-definition-Z64GVDOM-C9U6VikV.js → timeline-definition-Z64GVDOM-BXNTAanY.js} +1 -1
- package/dist/client/assets/{vennDiagram-T6HMQDX7-Desj7KFU.js → vennDiagram-T6HMQDX7-D9nXAts5.js} +1 -1
- package/dist/client/assets/{viewer-tabs-BwMhis6Q.js → viewer-tabs-DkLmDzFg.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-T6FBY63Y-rlMEd5tV.js → wardleyDiagram-T6FBY63Y-D89EaEfa.js} +1 -1
- package/dist/client/assets/{xychartDiagram-ELKLHX3M-CzFgA0NM.js → xychartDiagram-ELKLHX3M-B_xFDiIh.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/dev.mjs +1 -4
- package/dist/manifest.json +1 -1
- package/dist/server.mjs +295 -2351
- package/dist/utility.mjs +0 -3
- package/package.json +1 -1
- package/dist/client/assets/App-CGiS2z40.js +0 -74
- package/dist/client/assets/CreatePullRequestDialog-dNbTTo9i.js +0 -2
- package/dist/client/assets/DiffWorkspace-XS025gbZ.js +0 -26
- package/dist/client/assets/EditableFileViewer-Cve4V9RS.js +0 -1
- package/dist/client/assets/File-BJuBDans.js +0 -1
- package/dist/client/assets/MarkdownFileViewer-pagMxv2y.js +0 -2
- package/dist/client/assets/PierreDiffViewer-FmgbHdls.js +0 -1
- package/dist/client/assets/RepositoryProjectsDialog-QYXEt7Lg.js +0 -1
- package/dist/client/assets/SettingsDialog-DHmWkKYV.js +0 -9
- package/dist/client/assets/channel-BGbncBYv.js +0 -1
- package/dist/client/assets/classDiagram-JCYQIIEL-BoYriqPM.js +0 -1
- package/dist/client/assets/classDiagram-v2-OCEON4UE-BoYriqPM.js +0 -1
- package/dist/client/assets/index-WwGOu_aM.css +0 -1
- package/dist/client/assets/render-markdown-BiKX2Zdv.js +0 -280
- package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-DHeOpgR_.js +0 -8
package/dist/server.mjs
CHANGED
|
@@ -16,9 +16,6 @@ import { Buffer as Buffer$1 } from "node:buffer";
|
|
|
16
16
|
import { Transform, getDefaultHighWaterMark, Duplex, Writable, Readable, PassThrough } from "node:stream";
|
|
17
17
|
import { finished } from "node:stream/promises";
|
|
18
18
|
import path$1 from "node:path/win32";
|
|
19
|
-
import require$$0$2 from "child_process";
|
|
20
|
-
import require$$0$1 from "path";
|
|
21
|
-
import require$$0 from "fs";
|
|
22
19
|
import { createServer, isIP } from "node:net";
|
|
23
20
|
import { createServer as createServer$1 } from "node:http";
|
|
24
21
|
import WebSocket, { WebSocketServer } from "ws";
|
|
@@ -769,7 +766,7 @@ const handleCommand = (filePath, rawArguments, rawOptions) => {
|
|
|
769
766
|
verboseInfo
|
|
770
767
|
};
|
|
771
768
|
};
|
|
772
|
-
function pathKey$
|
|
769
|
+
function pathKey$1(options = {}) {
|
|
773
770
|
const {
|
|
774
771
|
env = process.env,
|
|
775
772
|
platform: platform2 = process.platform
|
|
@@ -798,7 +795,7 @@ function traversePathUp(startPath) {
|
|
|
798
795
|
}
|
|
799
796
|
const npmRunPath = ({
|
|
800
797
|
cwd = process$3.cwd(),
|
|
801
|
-
path: pathOption = process$3.env[pathKey$
|
|
798
|
+
path: pathOption = process$3.env[pathKey$1()],
|
|
802
799
|
preferLocal = true,
|
|
803
800
|
execPath: execPath2 = process$3.execPath,
|
|
804
801
|
addExecPath = true
|
|
@@ -830,7 +827,7 @@ const applyExecPath = (result, pathParts, execPath2, cwdPath) => {
|
|
|
830
827
|
};
|
|
831
828
|
const npmRunPathEnv = ({ env = process$3.env, ...options } = {}) => {
|
|
832
829
|
env = { ...env };
|
|
833
|
-
const pathName = pathKey$
|
|
830
|
+
const pathName = pathKey$1({ env });
|
|
834
831
|
options.path = env[pathName];
|
|
835
832
|
env[pathName] = npmRunPath(options);
|
|
836
833
|
return env;
|
|
@@ -5262,7 +5259,7 @@ if (process.platform === "linux") {
|
|
|
5262
5259
|
}
|
|
5263
5260
|
const processOk = (process2) => !!process2 && typeof process2 === "object" && typeof process2.removeListener === "function" && typeof process2.emit === "function" && typeof process2.reallyExit === "function" && typeof process2.listeners === "function" && typeof process2.kill === "function" && typeof process2.pid === "number" && typeof process2.on === "function";
|
|
5264
5261
|
const kExitEmitter = /* @__PURE__ */ Symbol.for("signal-exit emitter");
|
|
5265
|
-
const global
|
|
5262
|
+
const global = globalThis;
|
|
5266
5263
|
const ObjectDefineProperty = Object.defineProperty.bind(Object);
|
|
5267
5264
|
class Emitter {
|
|
5268
5265
|
emitted = {
|
|
@@ -5276,10 +5273,10 @@ class Emitter {
|
|
|
5276
5273
|
count = 0;
|
|
5277
5274
|
id = Math.random();
|
|
5278
5275
|
constructor() {
|
|
5279
|
-
if (global
|
|
5280
|
-
return global
|
|
5276
|
+
if (global[kExitEmitter]) {
|
|
5277
|
+
return global[kExitEmitter];
|
|
5281
5278
|
}
|
|
5282
|
-
ObjectDefineProperty(global
|
|
5279
|
+
ObjectDefineProperty(global, kExitEmitter, {
|
|
5283
5280
|
value: this,
|
|
5284
5281
|
writable: false,
|
|
5285
5282
|
enumerable: false,
|
|
@@ -7014,26 +7011,30 @@ function cancelled() {
|
|
|
7014
7011
|
function processFailed() {
|
|
7015
7012
|
return new AiOperationError({ code: "AI_PROCESS_FAILED", operation: "ai-process", message: "Could not start the AI tool." });
|
|
7016
7013
|
}
|
|
7017
|
-
const ALLOWED = /* @__PURE__ */ new Set(["codex", "claude", "opencode", "gh"]);
|
|
7014
|
+
const ALLOWED = /* @__PURE__ */ new Set(["codex", "claude", "opencode", "grok", "gh"]);
|
|
7018
7015
|
const ALIASES = {
|
|
7019
7016
|
codex: ["codex"],
|
|
7020
7017
|
claude: ["claude"],
|
|
7021
|
-
//
|
|
7018
|
+
// Current v2 uses opencode; older distributions also provide opencode2.
|
|
7022
7019
|
opencode: ["opencode", "opencode2"],
|
|
7020
|
+
grok: ["grok"],
|
|
7023
7021
|
gh: ["gh"]
|
|
7024
7022
|
};
|
|
7025
7023
|
class CliResolver {
|
|
7026
7024
|
cache = /* @__PURE__ */ new Map();
|
|
7027
7025
|
async resolve(name, forceRefresh = false) {
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7026
|
+
return (await this.resolveAll(name, forceRefresh))[0] ?? null;
|
|
7027
|
+
}
|
|
7028
|
+
async resolveAll(name, forceRefresh = false) {
|
|
7029
|
+
if (!ALLOWED.has(name)) return [];
|
|
7030
|
+
if (!forceRefresh && this.cache.has(name)) return [...this.cache.get(name)];
|
|
7031
|
+
const resolved = [];
|
|
7031
7032
|
for (const alias of ALIASES[name] ?? [name]) {
|
|
7032
|
-
|
|
7033
|
-
if (resolved)
|
|
7033
|
+
const executable = await findOnPath(alias);
|
|
7034
|
+
if (executable && !resolved.includes(executable)) resolved.push(executable);
|
|
7034
7035
|
}
|
|
7035
7036
|
this.cache.set(name, resolved);
|
|
7036
|
-
return resolved;
|
|
7037
|
+
return [...resolved];
|
|
7037
7038
|
}
|
|
7038
7039
|
}
|
|
7039
7040
|
async function findOnPath(name) {
|
|
@@ -7286,7 +7287,7 @@ const NUMBER_FORMAT_RANGES = {
|
|
|
7286
7287
|
float32: [-34028234663852886e22, 34028234663852886e22],
|
|
7287
7288
|
float64: [-Number.MAX_VALUE, Number.MAX_VALUE]
|
|
7288
7289
|
};
|
|
7289
|
-
function pick
|
|
7290
|
+
function pick(schema, mask) {
|
|
7290
7291
|
const currDef = schema._zod.def;
|
|
7291
7292
|
const checks = currDef.checks;
|
|
7292
7293
|
const hasChecks = checks && checks.length > 0;
|
|
@@ -11529,7 +11530,7 @@ const ZodObject = /* @__PURE__ */ $constructor("ZodObject", (inst, def) => {
|
|
|
11529
11530
|
return merge(this, other);
|
|
11530
11531
|
},
|
|
11531
11532
|
pick(mask) {
|
|
11532
|
-
return pick
|
|
11533
|
+
return pick(this, mask);
|
|
11533
11534
|
},
|
|
11534
11535
|
omit(mask) {
|
|
11535
11536
|
return omit(this, mask);
|
|
@@ -11854,7 +11855,7 @@ const EMPTY_AI_USAGE = {
|
|
|
11854
11855
|
};
|
|
11855
11856
|
const OPERATIONS = ["commit-message", "pull-request-draft"];
|
|
11856
11857
|
const STATUSES = ["success", "failed", "cancelled"];
|
|
11857
|
-
const HARNESSES = ["codex", "claude", "opencode"];
|
|
11858
|
+
const HARNESSES = ["codex", "claude", "opencode", "grok"];
|
|
11858
11859
|
const MAX_TEXT$1 = 200;
|
|
11859
11860
|
const MAX_ERROR_TEXT = 400;
|
|
11860
11861
|
const aiUsageRecordSchema = looseObject({
|
|
@@ -12134,7 +12135,7 @@ function parseGeneratedParts(value) {
|
|
|
12134
12135
|
const parsed = generatedPartsSchema.safeParse(value);
|
|
12135
12136
|
if (!parsed.success || `${parsed.data.subject}
|
|
12136
12137
|
|
|
12137
|
-
${parsed.data.body}`.length > 1e4) throw invalidOutput$
|
|
12138
|
+
${parsed.data.body}`.length > 1e4) throw invalidOutput$4();
|
|
12138
12139
|
return parsed.data;
|
|
12139
12140
|
}
|
|
12140
12141
|
function parseCommitSplitProposal(value, stagedPaths) {
|
|
@@ -12194,14 +12195,14 @@ function parseJsonPayload(raw) {
|
|
|
12194
12195
|
if (nested instanceof AiOperationError) throw nested;
|
|
12195
12196
|
}
|
|
12196
12197
|
}
|
|
12197
|
-
throw invalidOutput$
|
|
12198
|
+
throw invalidOutput$4();
|
|
12198
12199
|
}
|
|
12199
12200
|
}
|
|
12200
12201
|
function asRecord(value) {
|
|
12201
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw invalidOutput$
|
|
12202
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw invalidOutput$4();
|
|
12202
12203
|
return value;
|
|
12203
12204
|
}
|
|
12204
|
-
function invalidOutput$
|
|
12205
|
+
function invalidOutput$4() {
|
|
12205
12206
|
return new AiOperationError({ code: "AI_INVALID_OUTPUT", operation: "ai-parse-output", message: "The AI returned a message with an invalid format.", retryable: true });
|
|
12206
12207
|
}
|
|
12207
12208
|
function hasControlCharacters$6(value, allowWhitespace) {
|
|
@@ -12293,7 +12294,7 @@ ${parts.body}` : parts.subject,
|
|
|
12293
12294
|
splitBlockedReason: context.splitBlockedReason
|
|
12294
12295
|
};
|
|
12295
12296
|
} catch (error) {
|
|
12296
|
-
const
|
|
12297
|
+
const failure2 = failureLogFields(error);
|
|
12297
12298
|
recordSafely(this.log, {
|
|
12298
12299
|
operation: "commit-message",
|
|
12299
12300
|
harness: input.harness,
|
|
@@ -12301,10 +12302,10 @@ ${parts.body}` : parts.subject,
|
|
|
12301
12302
|
repositoryId: input.repositoryId,
|
|
12302
12303
|
// A cancellation is a decision, not a failure; merging the two would
|
|
12303
12304
|
// poison any reliability figure taken from this log.
|
|
12304
|
-
status:
|
|
12305
|
+
status: failure2.status,
|
|
12305
12306
|
durationMs: Date.now() - startedAt,
|
|
12306
|
-
errorCode:
|
|
12307
|
-
errorMessage:
|
|
12307
|
+
errorCode: failure2.errorCode,
|
|
12308
|
+
errorMessage: failure2.errorMessage,
|
|
12308
12309
|
usage,
|
|
12309
12310
|
stagedFileCount,
|
|
12310
12311
|
contextTruncated,
|
|
@@ -12375,10 +12376,10 @@ ${context.patch}`;
|
|
|
12375
12376
|
}
|
|
12376
12377
|
function parsePullRequestDraft(value) {
|
|
12377
12378
|
const parsed = pullRequestDraftSchema.safeParse(value);
|
|
12378
|
-
if (!parsed.success) throw invalidOutput$
|
|
12379
|
+
if (!parsed.success) throw invalidOutput$3();
|
|
12379
12380
|
return parsed.data;
|
|
12380
12381
|
}
|
|
12381
|
-
function invalidOutput$
|
|
12382
|
+
function invalidOutput$3() {
|
|
12382
12383
|
return new AiOperationError({ code: "AI_INVALID_OUTPUT", operation: "ai-parse-pr-draft", message: "The AI returned a pull request draft with an invalid format.", retryable: true });
|
|
12383
12384
|
}
|
|
12384
12385
|
function hasControlCharacters$5(value, allowWhitespace) {
|
|
@@ -12428,8 +12429,8 @@ class PullRequestDraftService {
|
|
|
12428
12429
|
this.record(input, "success", null, null, usage, contextTruncated, Date.now() - startedAt);
|
|
12429
12430
|
return { ...parts, harness: input.harness, model: input.model, contextWasTruncated: context.truncated };
|
|
12430
12431
|
} catch (error) {
|
|
12431
|
-
const
|
|
12432
|
-
this.record(input,
|
|
12432
|
+
const failure2 = failureLogFields(error);
|
|
12433
|
+
this.record(input, failure2.status, failure2.errorCode, failure2.errorMessage, usage, contextTruncated, Date.now() - startedAt);
|
|
12433
12434
|
throw error;
|
|
12434
12435
|
} finally {
|
|
12435
12436
|
this.active.delete(input.requestId);
|
|
@@ -12469,7 +12470,20 @@ function throwIfCancelled(signal, harness) {
|
|
|
12469
12470
|
}
|
|
12470
12471
|
const AI_PROVIDER_TIMEOUT_MS = 9 * 6e4;
|
|
12471
12472
|
const AI_SERVER_TIMEOUT_MS = AI_PROVIDER_TIMEOUT_MS + 3e4;
|
|
12472
|
-
const DEFAULT_MODEL = { id: "default", label: "Default (CLI)" };
|
|
12473
|
+
const DEFAULT_MODEL$1 = { id: "default", label: "Default (CLI)" };
|
|
12474
|
+
function grokUsage(envelope) {
|
|
12475
|
+
if (!envelope || typeof envelope !== "object") return { ...EMPTY_AI_USAGE };
|
|
12476
|
+
const record2 = envelope;
|
|
12477
|
+
const usage = record2.usage && typeof record2.usage === "object" ? record2.usage : {};
|
|
12478
|
+
return {
|
|
12479
|
+
inputTokens: count(usage.input_tokens),
|
|
12480
|
+
outputTokens: count(usage.output_tokens),
|
|
12481
|
+
reasoningTokens: count(usage.reasoning_tokens),
|
|
12482
|
+
cacheReadTokens: count(usage.cache_read_input_tokens),
|
|
12483
|
+
cacheWriteTokens: count(usage.cache_creation_input_tokens),
|
|
12484
|
+
costUsd: count(record2.total_cost_usd, true)
|
|
12485
|
+
};
|
|
12486
|
+
}
|
|
12473
12487
|
function claudeUsage(envelope) {
|
|
12474
12488
|
if (!envelope || typeof envelope !== "object") return { ...EMPTY_AI_USAGE };
|
|
12475
12489
|
const record2 = envelope;
|
|
@@ -12507,20 +12521,6 @@ function codexUsage(stdout) {
|
|
|
12507
12521
|
costUsd: null
|
|
12508
12522
|
};
|
|
12509
12523
|
}
|
|
12510
|
-
function openCodeUsage(info) {
|
|
12511
|
-
if (!info || typeof info !== "object") return { ...EMPTY_AI_USAGE };
|
|
12512
|
-
const record2 = info;
|
|
12513
|
-
const tokens = record2.tokens ?? {};
|
|
12514
|
-
const cache = tokens.cache ?? {};
|
|
12515
|
-
return {
|
|
12516
|
-
inputTokens: count(tokens.input),
|
|
12517
|
-
outputTokens: count(tokens.output),
|
|
12518
|
-
reasoningTokens: count(tokens.reasoning),
|
|
12519
|
-
cacheReadTokens: count(cache.read),
|
|
12520
|
-
cacheWriteTokens: count(cache.write),
|
|
12521
|
-
costUsd: count(record2.cost, true)
|
|
12522
|
-
};
|
|
12523
|
-
}
|
|
12524
12524
|
function count(value, fractional = false) {
|
|
12525
12525
|
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return null;
|
|
12526
12526
|
return fractional ? value : Math.round(value);
|
|
@@ -12569,7 +12569,7 @@ ${diagnostic ?? ""}`.toLowerCase();
|
|
|
12569
12569
|
});
|
|
12570
12570
|
}
|
|
12571
12571
|
function label(harness) {
|
|
12572
|
-
return harness === "codex" ? "Codex" : harness === "claude" ? "Claude Code" : "OpenCode";
|
|
12572
|
+
return harness === "codex" ? "Codex" : harness === "claude" ? "Claude Code" : harness === "grok" ? "Grok Build" : "OpenCode";
|
|
12573
12573
|
}
|
|
12574
12574
|
function stripAnsi(value) {
|
|
12575
12575
|
return value.replace(new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g"), "");
|
|
@@ -12663,7 +12663,7 @@ function flattenWhitespace(value) {
|
|
|
12663
12663
|
}
|
|
12664
12664
|
return flattened.replace(/ {2,}/g, " ").trim();
|
|
12665
12665
|
}
|
|
12666
|
-
const MODELS = [DEFAULT_MODEL, { id: "sonnet", label: "Sonnet" }, { id: "opus", label: "Opus" }, { id: "haiku", label: "Haiku" }];
|
|
12666
|
+
const MODELS = [DEFAULT_MODEL$1, { id: "sonnet", label: "Sonnet" }, { id: "opus", label: "Opus" }, { id: "haiku", label: "Haiku" }];
|
|
12667
12667
|
class ClaudeProvider {
|
|
12668
12668
|
constructor(resolver, runner) {
|
|
12669
12669
|
this.resolver = resolver;
|
|
@@ -12725,15 +12725,15 @@ class CodexProvider {
|
|
|
12725
12725
|
async status(forceRefresh = false) {
|
|
12726
12726
|
const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12727
12727
|
const executable = await this.resolver.resolve("codex", forceRefresh);
|
|
12728
|
-
if (!executable) return { id: this.id, label: "Codex", availability: "error", installed: false, authStatus: "unknown", message: "Install Codex CLI to use this harness.", models: [DEFAULT_MODEL], checkedAt };
|
|
12728
|
+
if (!executable) return { id: this.id, label: "Codex", availability: "error", installed: false, authStatus: "unknown", message: "Install Codex CLI to use this harness.", models: [DEFAULT_MODEL$1], checkedAt };
|
|
12729
12729
|
const version2 = await this.runner.run(executable, ["--version"]);
|
|
12730
12730
|
const login = await this.runner.run(executable, ["login", "status"]);
|
|
12731
12731
|
if (login.exitCode !== 0 || !/logged in/i.test(`${login.stdout}
|
|
12732
12732
|
${login.stderr}`)) {
|
|
12733
|
-
return { id: this.id, label: "Codex", availability: "error", installed: true, authStatus: "unauthenticated", version: version2.stdout.trim() || version2.stderr.trim(), message: "Run codex login.", models: [DEFAULT_MODEL], checkedAt };
|
|
12733
|
+
return { id: this.id, label: "Codex", availability: "error", installed: true, authStatus: "unauthenticated", version: version2.stdout.trim() || version2.stderr.trim(), message: "Run codex login.", models: [DEFAULT_MODEL$1], checkedAt };
|
|
12734
12734
|
}
|
|
12735
12735
|
const catalog = await this.runner.run(executable, ["debug", "models", "--bundled"]);
|
|
12736
|
-
const models = catalog.exitCode === 0 ? parseCodexModels(catalog.stdout) : [DEFAULT_MODEL];
|
|
12736
|
+
const models = catalog.exitCode === 0 ? parseCodexModels(catalog.stdout) : [DEFAULT_MODEL$1];
|
|
12737
12737
|
return {
|
|
12738
12738
|
id: this.id,
|
|
12739
12739
|
label: "Codex",
|
|
@@ -12769,2254 +12769,223 @@ function parseCodexModels(raw) {
|
|
|
12769
12769
|
try {
|
|
12770
12770
|
const parsed = JSON.parse(raw);
|
|
12771
12771
|
const options = (parsed.models ?? []).filter((item) => typeof item.slug === "string" && item.visibility !== "hidden").map((item) => ({ id: item.slug, label: typeof item.display_name === "string" ? item.display_name : item.slug }));
|
|
12772
|
-
return [DEFAULT_MODEL, ...options];
|
|
12772
|
+
return [DEFAULT_MODEL$1, ...options];
|
|
12773
12773
|
} catch {
|
|
12774
|
-
return [DEFAULT_MODEL];
|
|
12775
|
-
}
|
|
12776
|
-
}
|
|
12777
|
-
const createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url, ...options }) => {
|
|
12778
|
-
let lastEventId;
|
|
12779
|
-
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
12780
|
-
const createStream = async function* () {
|
|
12781
|
-
let retryDelay = sseDefaultRetryDelay ?? 3e3;
|
|
12782
|
-
let attempt = 0;
|
|
12783
|
-
const signal = options.signal ?? new AbortController().signal;
|
|
12784
|
-
while (true) {
|
|
12785
|
-
if (signal.aborted)
|
|
12786
|
-
break;
|
|
12787
|
-
attempt++;
|
|
12788
|
-
const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
|
|
12789
|
-
if (lastEventId !== void 0) {
|
|
12790
|
-
headers.set("Last-Event-ID", lastEventId);
|
|
12791
|
-
}
|
|
12792
|
-
try {
|
|
12793
|
-
const response = await fetch(url, { ...options, headers, signal });
|
|
12794
|
-
if (!response.ok)
|
|
12795
|
-
throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
|
|
12796
|
-
if (!response.body)
|
|
12797
|
-
throw new Error("No body in SSE response");
|
|
12798
|
-
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
12799
|
-
let buffer = "";
|
|
12800
|
-
const abortHandler = () => {
|
|
12801
|
-
try {
|
|
12802
|
-
void reader.cancel();
|
|
12803
|
-
} catch {
|
|
12804
|
-
}
|
|
12805
|
-
};
|
|
12806
|
-
signal.addEventListener("abort", abortHandler);
|
|
12807
|
-
try {
|
|
12808
|
-
while (true) {
|
|
12809
|
-
const { done, value } = await reader.read();
|
|
12810
|
-
if (done)
|
|
12811
|
-
break;
|
|
12812
|
-
buffer += value;
|
|
12813
|
-
const chunks = buffer.split("\n\n");
|
|
12814
|
-
buffer = chunks.pop() ?? "";
|
|
12815
|
-
for (const chunk of chunks) {
|
|
12816
|
-
const lines = chunk.split("\n");
|
|
12817
|
-
const dataLines = [];
|
|
12818
|
-
let eventName;
|
|
12819
|
-
for (const line of lines) {
|
|
12820
|
-
if (line.startsWith("data:")) {
|
|
12821
|
-
dataLines.push(line.replace(/^data:\s*/, ""));
|
|
12822
|
-
} else if (line.startsWith("event:")) {
|
|
12823
|
-
eventName = line.replace(/^event:\s*/, "");
|
|
12824
|
-
} else if (line.startsWith("id:")) {
|
|
12825
|
-
lastEventId = line.replace(/^id:\s*/, "");
|
|
12826
|
-
} else if (line.startsWith("retry:")) {
|
|
12827
|
-
const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
|
|
12828
|
-
if (!Number.isNaN(parsed)) {
|
|
12829
|
-
retryDelay = parsed;
|
|
12830
|
-
}
|
|
12831
|
-
}
|
|
12832
|
-
}
|
|
12833
|
-
let data;
|
|
12834
|
-
let parsedJson = false;
|
|
12835
|
-
if (dataLines.length) {
|
|
12836
|
-
const rawData = dataLines.join("\n");
|
|
12837
|
-
try {
|
|
12838
|
-
data = JSON.parse(rawData);
|
|
12839
|
-
parsedJson = true;
|
|
12840
|
-
} catch {
|
|
12841
|
-
data = rawData;
|
|
12842
|
-
}
|
|
12843
|
-
}
|
|
12844
|
-
if (parsedJson) {
|
|
12845
|
-
if (responseValidator) {
|
|
12846
|
-
await responseValidator(data);
|
|
12847
|
-
}
|
|
12848
|
-
if (responseTransformer) {
|
|
12849
|
-
data = await responseTransformer(data);
|
|
12850
|
-
}
|
|
12851
|
-
}
|
|
12852
|
-
onSseEvent?.({
|
|
12853
|
-
data,
|
|
12854
|
-
event: eventName,
|
|
12855
|
-
id: lastEventId,
|
|
12856
|
-
retry: retryDelay
|
|
12857
|
-
});
|
|
12858
|
-
if (dataLines.length) {
|
|
12859
|
-
yield data;
|
|
12860
|
-
}
|
|
12861
|
-
}
|
|
12862
|
-
}
|
|
12863
|
-
} finally {
|
|
12864
|
-
signal.removeEventListener("abort", abortHandler);
|
|
12865
|
-
reader.releaseLock();
|
|
12866
|
-
}
|
|
12867
|
-
break;
|
|
12868
|
-
} catch (error) {
|
|
12869
|
-
onSseError?.(error);
|
|
12870
|
-
if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
|
|
12871
|
-
break;
|
|
12872
|
-
}
|
|
12873
|
-
const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4);
|
|
12874
|
-
await sleep(backoff);
|
|
12875
|
-
}
|
|
12876
|
-
}
|
|
12877
|
-
};
|
|
12878
|
-
const stream = createStream();
|
|
12879
|
-
return { stream };
|
|
12880
|
-
};
|
|
12881
|
-
const getAuthToken = async (auth, callback) => {
|
|
12882
|
-
const token = typeof callback === "function" ? await callback(auth) : callback;
|
|
12883
|
-
if (!token) {
|
|
12884
|
-
return;
|
|
12885
|
-
}
|
|
12886
|
-
if (auth.scheme === "bearer") {
|
|
12887
|
-
return `Bearer ${token}`;
|
|
12888
|
-
}
|
|
12889
|
-
if (auth.scheme === "basic") {
|
|
12890
|
-
return `Basic ${btoa(token)}`;
|
|
12891
|
-
}
|
|
12892
|
-
return token;
|
|
12893
|
-
};
|
|
12894
|
-
const jsonBodySerializer = {
|
|
12895
|
-
bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
|
|
12896
|
-
};
|
|
12897
|
-
const separatorArrayExplode = (style) => {
|
|
12898
|
-
switch (style) {
|
|
12899
|
-
case "label":
|
|
12900
|
-
return ".";
|
|
12901
|
-
case "matrix":
|
|
12902
|
-
return ";";
|
|
12903
|
-
case "simple":
|
|
12904
|
-
return ",";
|
|
12905
|
-
default:
|
|
12906
|
-
return "&";
|
|
12907
|
-
}
|
|
12908
|
-
};
|
|
12909
|
-
const separatorArrayNoExplode = (style) => {
|
|
12910
|
-
switch (style) {
|
|
12911
|
-
case "form":
|
|
12912
|
-
return ",";
|
|
12913
|
-
case "pipeDelimited":
|
|
12914
|
-
return "|";
|
|
12915
|
-
case "spaceDelimited":
|
|
12916
|
-
return "%20";
|
|
12917
|
-
default:
|
|
12918
|
-
return ",";
|
|
12919
|
-
}
|
|
12920
|
-
};
|
|
12921
|
-
const separatorObjectExplode = (style) => {
|
|
12922
|
-
switch (style) {
|
|
12923
|
-
case "label":
|
|
12924
|
-
return ".";
|
|
12925
|
-
case "matrix":
|
|
12926
|
-
return ";";
|
|
12927
|
-
case "simple":
|
|
12928
|
-
return ",";
|
|
12929
|
-
default:
|
|
12930
|
-
return "&";
|
|
12931
|
-
}
|
|
12932
|
-
};
|
|
12933
|
-
const serializeArrayParam = ({ allowReserved, explode, name, style, value }) => {
|
|
12934
|
-
if (!explode) {
|
|
12935
|
-
const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
|
|
12936
|
-
switch (style) {
|
|
12937
|
-
case "label":
|
|
12938
|
-
return `.${joinedValues2}`;
|
|
12939
|
-
case "matrix":
|
|
12940
|
-
return `;${name}=${joinedValues2}`;
|
|
12941
|
-
case "simple":
|
|
12942
|
-
return joinedValues2;
|
|
12943
|
-
default:
|
|
12944
|
-
return `${name}=${joinedValues2}`;
|
|
12945
|
-
}
|
|
12946
|
-
}
|
|
12947
|
-
const separator = separatorArrayExplode(style);
|
|
12948
|
-
const joinedValues = value.map((v) => {
|
|
12949
|
-
if (style === "label" || style === "simple") {
|
|
12950
|
-
return allowReserved ? v : encodeURIComponent(v);
|
|
12951
|
-
}
|
|
12952
|
-
return serializePrimitiveParam({
|
|
12953
|
-
allowReserved,
|
|
12954
|
-
name,
|
|
12955
|
-
value: v
|
|
12956
|
-
});
|
|
12957
|
-
}).join(separator);
|
|
12958
|
-
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
12959
|
-
};
|
|
12960
|
-
const serializePrimitiveParam = ({ allowReserved, name, value }) => {
|
|
12961
|
-
if (value === void 0 || value === null) {
|
|
12962
|
-
return "";
|
|
12963
|
-
}
|
|
12964
|
-
if (typeof value === "object") {
|
|
12965
|
-
throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
|
|
12966
|
-
}
|
|
12967
|
-
return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
|
|
12968
|
-
};
|
|
12969
|
-
const serializeObjectParam = ({ allowReserved, explode, name, style, value, valueOnly }) => {
|
|
12970
|
-
if (value instanceof Date) {
|
|
12971
|
-
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
|
12972
|
-
}
|
|
12973
|
-
if (style !== "deepObject" && !explode) {
|
|
12974
|
-
let values = [];
|
|
12975
|
-
Object.entries(value).forEach(([key, v]) => {
|
|
12976
|
-
values = [...values, key, allowReserved ? v : encodeURIComponent(v)];
|
|
12977
|
-
});
|
|
12978
|
-
const joinedValues2 = values.join(",");
|
|
12979
|
-
switch (style) {
|
|
12980
|
-
case "form":
|
|
12981
|
-
return `${name}=${joinedValues2}`;
|
|
12982
|
-
case "label":
|
|
12983
|
-
return `.${joinedValues2}`;
|
|
12984
|
-
case "matrix":
|
|
12985
|
-
return `;${name}=${joinedValues2}`;
|
|
12986
|
-
default:
|
|
12987
|
-
return joinedValues2;
|
|
12988
|
-
}
|
|
12989
|
-
}
|
|
12990
|
-
const separator = separatorObjectExplode(style);
|
|
12991
|
-
const joinedValues = Object.entries(value).map(([key, v]) => serializePrimitiveParam({
|
|
12992
|
-
allowReserved,
|
|
12993
|
-
name: style === "deepObject" ? `${name}[${key}]` : key,
|
|
12994
|
-
value: v
|
|
12995
|
-
})).join(separator);
|
|
12996
|
-
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
12997
|
-
};
|
|
12998
|
-
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
12999
|
-
const defaultPathSerializer = ({ path: path2, url: _url2 }) => {
|
|
13000
|
-
let url = _url2;
|
|
13001
|
-
const matches = _url2.match(PATH_PARAM_RE);
|
|
13002
|
-
if (matches) {
|
|
13003
|
-
for (const match of matches) {
|
|
13004
|
-
let explode = false;
|
|
13005
|
-
let name = match.substring(1, match.length - 1);
|
|
13006
|
-
let style = "simple";
|
|
13007
|
-
if (name.endsWith("*")) {
|
|
13008
|
-
explode = true;
|
|
13009
|
-
name = name.substring(0, name.length - 1);
|
|
13010
|
-
}
|
|
13011
|
-
if (name.startsWith(".")) {
|
|
13012
|
-
name = name.substring(1);
|
|
13013
|
-
style = "label";
|
|
13014
|
-
} else if (name.startsWith(";")) {
|
|
13015
|
-
name = name.substring(1);
|
|
13016
|
-
style = "matrix";
|
|
13017
|
-
}
|
|
13018
|
-
const value = path2[name];
|
|
13019
|
-
if (value === void 0 || value === null) {
|
|
13020
|
-
continue;
|
|
13021
|
-
}
|
|
13022
|
-
if (Array.isArray(value)) {
|
|
13023
|
-
url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
|
|
13024
|
-
continue;
|
|
13025
|
-
}
|
|
13026
|
-
if (typeof value === "object") {
|
|
13027
|
-
url = url.replace(match, serializeObjectParam({
|
|
13028
|
-
explode,
|
|
13029
|
-
name,
|
|
13030
|
-
style,
|
|
13031
|
-
value,
|
|
13032
|
-
valueOnly: true
|
|
13033
|
-
}));
|
|
13034
|
-
continue;
|
|
13035
|
-
}
|
|
13036
|
-
if (style === "matrix") {
|
|
13037
|
-
url = url.replace(match, `;${serializePrimitiveParam({
|
|
13038
|
-
name,
|
|
13039
|
-
value
|
|
13040
|
-
})}`);
|
|
13041
|
-
continue;
|
|
13042
|
-
}
|
|
13043
|
-
const replaceValue = encodeURIComponent(style === "label" ? `.${value}` : value);
|
|
13044
|
-
url = url.replace(match, replaceValue);
|
|
13045
|
-
}
|
|
13046
|
-
}
|
|
13047
|
-
return url;
|
|
13048
|
-
};
|
|
13049
|
-
const getUrl = ({ baseUrl, path: path2, query, querySerializer, url: _url2 }) => {
|
|
13050
|
-
const pathUrl = _url2.startsWith("/") ? _url2 : `/${_url2}`;
|
|
13051
|
-
let url = (baseUrl ?? "") + pathUrl;
|
|
13052
|
-
if (path2) {
|
|
13053
|
-
url = defaultPathSerializer({ path: path2, url });
|
|
13054
|
-
}
|
|
13055
|
-
let search = query ? querySerializer(query) : "";
|
|
13056
|
-
if (search.startsWith("?")) {
|
|
13057
|
-
search = search.substring(1);
|
|
13058
|
-
}
|
|
13059
|
-
if (search) {
|
|
13060
|
-
url += `?${search}`;
|
|
12774
|
+
return [DEFAULT_MODEL$1];
|
|
13061
12775
|
}
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
const
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
|
|
13074
|
-
|
|
13075
|
-
|
|
13076
|
-
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
style: "deepObject",
|
|
13090
|
-
value,
|
|
13091
|
-
...object2
|
|
13092
|
-
});
|
|
13093
|
-
if (serializedObject)
|
|
13094
|
-
search.push(serializedObject);
|
|
13095
|
-
} else {
|
|
13096
|
-
const serializedPrimitive = serializePrimitiveParam({
|
|
13097
|
-
allowReserved,
|
|
13098
|
-
name,
|
|
13099
|
-
value
|
|
13100
|
-
});
|
|
13101
|
-
if (serializedPrimitive)
|
|
13102
|
-
search.push(serializedPrimitive);
|
|
13103
|
-
}
|
|
13104
|
-
}
|
|
13105
|
-
}
|
|
13106
|
-
return search.join("&");
|
|
13107
|
-
};
|
|
13108
|
-
return querySerializer;
|
|
13109
|
-
};
|
|
13110
|
-
const getParseAs = (contentType) => {
|
|
13111
|
-
if (!contentType) {
|
|
13112
|
-
return "stream";
|
|
13113
|
-
}
|
|
13114
|
-
const cleanContent = contentType.split(";")[0]?.trim();
|
|
13115
|
-
if (!cleanContent) {
|
|
13116
|
-
return;
|
|
13117
|
-
}
|
|
13118
|
-
if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
|
|
13119
|
-
return "json";
|
|
13120
|
-
}
|
|
13121
|
-
if (cleanContent === "multipart/form-data") {
|
|
13122
|
-
return "formData";
|
|
13123
|
-
}
|
|
13124
|
-
if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
|
|
13125
|
-
return "blob";
|
|
13126
|
-
}
|
|
13127
|
-
if (cleanContent.startsWith("text/")) {
|
|
13128
|
-
return "text";
|
|
13129
|
-
}
|
|
13130
|
-
return;
|
|
13131
|
-
};
|
|
13132
|
-
const checkForExistence = (options, name) => {
|
|
13133
|
-
if (!name) {
|
|
13134
|
-
return false;
|
|
13135
|
-
}
|
|
13136
|
-
if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
|
|
13137
|
-
return true;
|
|
13138
|
-
}
|
|
13139
|
-
return false;
|
|
13140
|
-
};
|
|
13141
|
-
const setAuthParams = async ({ security, ...options }) => {
|
|
13142
|
-
for (const auth of security) {
|
|
13143
|
-
if (checkForExistence(options, auth.name)) {
|
|
13144
|
-
continue;
|
|
13145
|
-
}
|
|
13146
|
-
const token = await getAuthToken(auth, options.auth);
|
|
13147
|
-
if (!token) {
|
|
13148
|
-
continue;
|
|
13149
|
-
}
|
|
13150
|
-
const name = auth.name ?? "Authorization";
|
|
13151
|
-
switch (auth.in) {
|
|
13152
|
-
case "query":
|
|
13153
|
-
if (!options.query) {
|
|
13154
|
-
options.query = {};
|
|
13155
|
-
}
|
|
13156
|
-
options.query[name] = token;
|
|
13157
|
-
break;
|
|
13158
|
-
case "cookie":
|
|
13159
|
-
options.headers.append("Cookie", `${name}=${token}`);
|
|
13160
|
-
break;
|
|
13161
|
-
case "header":
|
|
13162
|
-
default:
|
|
13163
|
-
options.headers.set(name, token);
|
|
13164
|
-
break;
|
|
13165
|
-
}
|
|
13166
|
-
}
|
|
13167
|
-
};
|
|
13168
|
-
const buildUrl = (options) => getUrl({
|
|
13169
|
-
baseUrl: options.baseUrl,
|
|
13170
|
-
path: options.path,
|
|
13171
|
-
query: options.query,
|
|
13172
|
-
querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
|
|
13173
|
-
url: options.url
|
|
13174
|
-
});
|
|
13175
|
-
const mergeConfigs = (a2, b) => {
|
|
13176
|
-
const config2 = { ...a2, ...b };
|
|
13177
|
-
if (config2.baseUrl?.endsWith("/")) {
|
|
13178
|
-
config2.baseUrl = config2.baseUrl.substring(0, config2.baseUrl.length - 1);
|
|
13179
|
-
}
|
|
13180
|
-
config2.headers = mergeHeaders(a2.headers, b.headers);
|
|
13181
|
-
return config2;
|
|
13182
|
-
};
|
|
13183
|
-
const mergeHeaders = (...headers) => {
|
|
13184
|
-
const mergedHeaders = new Headers();
|
|
13185
|
-
for (const header of headers) {
|
|
13186
|
-
if (!header || typeof header !== "object") {
|
|
13187
|
-
continue;
|
|
13188
|
-
}
|
|
13189
|
-
const iterator = header instanceof Headers ? header.entries() : Object.entries(header);
|
|
13190
|
-
for (const [key, value] of iterator) {
|
|
13191
|
-
if (value === null) {
|
|
13192
|
-
mergedHeaders.delete(key);
|
|
13193
|
-
} else if (Array.isArray(value)) {
|
|
13194
|
-
for (const v of value) {
|
|
13195
|
-
mergedHeaders.append(key, v);
|
|
13196
|
-
}
|
|
13197
|
-
} else if (value !== void 0) {
|
|
13198
|
-
mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : value);
|
|
13199
|
-
}
|
|
13200
|
-
}
|
|
13201
|
-
}
|
|
13202
|
-
return mergedHeaders;
|
|
13203
|
-
};
|
|
13204
|
-
class Interceptors {
|
|
13205
|
-
_fns;
|
|
13206
|
-
constructor() {
|
|
13207
|
-
this._fns = [];
|
|
13208
|
-
}
|
|
13209
|
-
clear() {
|
|
13210
|
-
this._fns = [];
|
|
13211
|
-
}
|
|
13212
|
-
getInterceptorIndex(id) {
|
|
13213
|
-
if (typeof id === "number") {
|
|
13214
|
-
return this._fns[id] ? id : -1;
|
|
13215
|
-
} else {
|
|
13216
|
-
return this._fns.indexOf(id);
|
|
13217
|
-
}
|
|
13218
|
-
}
|
|
13219
|
-
exists(id) {
|
|
13220
|
-
const index = this.getInterceptorIndex(id);
|
|
13221
|
-
return !!this._fns[index];
|
|
13222
|
-
}
|
|
13223
|
-
eject(id) {
|
|
13224
|
-
const index = this.getInterceptorIndex(id);
|
|
13225
|
-
if (this._fns[index]) {
|
|
13226
|
-
this._fns[index] = null;
|
|
13227
|
-
}
|
|
12776
|
+
}
|
|
12777
|
+
function isSupportedGrokVersion(raw) {
|
|
12778
|
+
const match = /^grok (\d+)\.(\d+)\.(\d+)\b/i.exec(stripAnsi(raw).trim());
|
|
12779
|
+
return !!match && Number(match[1]) === 1 && (Number(match[2]) > 0 || Number(match[3]) >= 46);
|
|
12780
|
+
}
|
|
12781
|
+
function parseGrokModels(raw) {
|
|
12782
|
+
const text2 = stripAnsi(raw);
|
|
12783
|
+
const authStatus = /You are not authenticated\./.test(text2) ? "unauthenticated" : /You are logged in with |You are using XAI_API_KEY\.|is using its own API key\.|authenticated via deployment key/.test(text2) ? "authenticated" : "unknown";
|
|
12784
|
+
const models = [{ id: "default", label: "Default (Grok)" }];
|
|
12785
|
+
const seen = /* @__PURE__ */ new Set(["default"]);
|
|
12786
|
+
const catalog = text2.split("Available models:")[1] ?? "";
|
|
12787
|
+
for (const line of catalog.split(/\r?\n/)) {
|
|
12788
|
+
const match = /^\s+[*-]\s+([^\s]+?)(?:\s+\(default\))?\s*$/.exec(line);
|
|
12789
|
+
const id = match?.[1];
|
|
12790
|
+
if (id && id.length <= 200 && /^[\w.:/#-]+$/.test(id) && !seen.has(id)) {
|
|
12791
|
+
seen.add(id);
|
|
12792
|
+
models.push({ id, label: id });
|
|
12793
|
+
}
|
|
12794
|
+
}
|
|
12795
|
+
return { authStatus, models };
|
|
12796
|
+
}
|
|
12797
|
+
function parseGrokOutput(raw) {
|
|
12798
|
+
let envelope;
|
|
12799
|
+
try {
|
|
12800
|
+
envelope = parseJsonPayload(stripAnsi(raw));
|
|
12801
|
+
} catch {
|
|
12802
|
+
throw invalidOutput$2();
|
|
13228
12803
|
}
|
|
13229
|
-
|
|
13230
|
-
|
|
13231
|
-
|
|
13232
|
-
|
|
13233
|
-
|
|
13234
|
-
} else {
|
|
13235
|
-
return false;
|
|
13236
|
-
}
|
|
12804
|
+
if (envelope.type === "error" || envelope.structuredOutputError || envelope.stopReason !== "end_turn") throw invalidOutput$2();
|
|
12805
|
+
const structured = envelope.structuredOutput;
|
|
12806
|
+
if (structured !== void 0) {
|
|
12807
|
+
if (!structured || typeof structured !== "object" || Array.isArray(structured)) throw invalidOutput$2();
|
|
12808
|
+
return { envelope, output: structured };
|
|
13237
12809
|
}
|
|
13238
|
-
|
|
13239
|
-
|
|
13240
|
-
return
|
|
12810
|
+
if (typeof envelope.text !== "string") throw invalidOutput$2();
|
|
12811
|
+
try {
|
|
12812
|
+
return { envelope, output: parseJsonPayload(envelope.text) };
|
|
12813
|
+
} catch {
|
|
12814
|
+
throw invalidOutput$2();
|
|
13241
12815
|
}
|
|
13242
12816
|
}
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
const
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
object: {
|
|
13255
|
-
explode: true,
|
|
13256
|
-
style: "deepObject"
|
|
12817
|
+
function invalidOutput$2() {
|
|
12818
|
+
return new AiOperationError({ code: "AI_INVALID_OUTPUT", operation: "grok-generate", harness: "grok", message: "Grok returned an incomplete or invalid structured response.", retryable: true });
|
|
12819
|
+
}
|
|
12820
|
+
const DEFAULT_MODEL = { id: "default", label: "Default (Grok)" };
|
|
12821
|
+
const UNSUPPORTED = "Grok Build 1.0.46 or later in the 1.x series is required, with headless JSON and tool controls.";
|
|
12822
|
+
const CONFIG = "[cli]\nauto_update = false\n[subagents]\nenabled = false\n[managed_mcps]\nenabled = false\ngateway_tools_enabled = false\n[memory]\nenabled = false\n[features]\nmanaged_config = false\ntitle_refresh = false\nturn_summary = false\n";
|
|
12823
|
+
const REQUIRED_FLAGS = ["--prompt-file", "--json-schema", "--output-format", "--tools", "--disallowed-tools", "--deny", "--disable-web-search", "--max-turns", "--permission-mode", "--verbatim"];
|
|
12824
|
+
class GrokProvider {
|
|
12825
|
+
constructor(resolver, runner) {
|
|
12826
|
+
this.resolver = resolver;
|
|
12827
|
+
this.runner = runner;
|
|
13257
12828
|
}
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
const
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
|
|
13266
|
-
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
const
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
headers: mergeHeaders(_config.headers, options.headers),
|
|
13283
|
-
serializedBody: void 0
|
|
13284
|
-
};
|
|
13285
|
-
if (opts.security) {
|
|
13286
|
-
await setAuthParams({
|
|
13287
|
-
...opts,
|
|
13288
|
-
security: opts.security
|
|
13289
|
-
});
|
|
13290
|
-
}
|
|
13291
|
-
if (opts.requestValidator) {
|
|
13292
|
-
await opts.requestValidator(opts);
|
|
13293
|
-
}
|
|
13294
|
-
if (opts.body && opts.bodySerializer) {
|
|
13295
|
-
opts.serializedBody = opts.bodySerializer(opts.body);
|
|
13296
|
-
}
|
|
13297
|
-
if (opts.serializedBody === void 0 || opts.serializedBody === "") {
|
|
13298
|
-
opts.headers.delete("Content-Type");
|
|
13299
|
-
}
|
|
13300
|
-
const url = buildUrl(opts);
|
|
13301
|
-
return { opts, url };
|
|
13302
|
-
};
|
|
13303
|
-
const request = async (options) => {
|
|
13304
|
-
const { opts, url } = await beforeRequest(options);
|
|
13305
|
-
const requestInit = {
|
|
13306
|
-
redirect: "follow",
|
|
13307
|
-
...opts,
|
|
13308
|
-
body: opts.serializedBody
|
|
13309
|
-
};
|
|
13310
|
-
let request2 = new Request(url, requestInit);
|
|
13311
|
-
for (const fn of interceptors.request._fns) {
|
|
13312
|
-
if (fn) {
|
|
13313
|
-
request2 = await fn(request2, opts);
|
|
13314
|
-
}
|
|
13315
|
-
}
|
|
13316
|
-
const _fetch = opts.fetch;
|
|
13317
|
-
let response = await _fetch(request2);
|
|
13318
|
-
for (const fn of interceptors.response._fns) {
|
|
13319
|
-
if (fn) {
|
|
13320
|
-
response = await fn(response, request2, opts);
|
|
13321
|
-
}
|
|
13322
|
-
}
|
|
13323
|
-
const result = {
|
|
13324
|
-
request: request2,
|
|
13325
|
-
response
|
|
13326
|
-
};
|
|
13327
|
-
if (response.ok) {
|
|
13328
|
-
if (response.status === 204 || response.headers.get("Content-Length") === "0") {
|
|
13329
|
-
return opts.responseStyle === "data" ? {} : {
|
|
13330
|
-
data: {},
|
|
13331
|
-
...result
|
|
12829
|
+
resolver;
|
|
12830
|
+
runner;
|
|
12831
|
+
id = "grok";
|
|
12832
|
+
async status(forceRefresh = false) {
|
|
12833
|
+
const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12834
|
+
const base = { id: this.id, label: "Grok Build", checkedAt, models: [DEFAULT_MODEL] };
|
|
12835
|
+
const executable = await this.resolver.resolve("grok", forceRefresh);
|
|
12836
|
+
if (!executable) return { ...base, installed: false, availability: "error", authStatus: "unknown", message: "Install the official Grok Build CLI and run grok login." };
|
|
12837
|
+
return this.withEnvironment(async (options) => {
|
|
12838
|
+
const version2 = await this.runner.run(executable, ["--version"], options);
|
|
12839
|
+
const versionText = version2.stdout.trim();
|
|
12840
|
+
const installed = { ...base, installed: true, version: versionText };
|
|
12841
|
+
if (version2.exitCode !== 0 || !isSupportedGrokVersion(versionText)) return { ...installed, availability: "error", authStatus: "unknown", message: UNSUPPORTED };
|
|
12842
|
+
try {
|
|
12843
|
+
await this.checkControls(executable, options);
|
|
12844
|
+
const result = await this.runner.run(executable, ["models"], options);
|
|
12845
|
+
if (result.exitCode !== 0) return { ...installed, availability: "warning", authStatus: "unknown", message: "Could not check Grok authentication or models. Check again or run grok models in a terminal." };
|
|
12846
|
+
const { authStatus, models } = parseGrokModels(result.stdout);
|
|
12847
|
+
return {
|
|
12848
|
+
...installed,
|
|
12849
|
+
models,
|
|
12850
|
+
authStatus,
|
|
12851
|
+
availability: authStatus === "unauthenticated" ? "error" : authStatus === "authenticated" && models.length > 1 ? "ready" : "warning",
|
|
12852
|
+
...authStatus === "unauthenticated" ? { message: "Run grok login, or provide XAI_API_KEY to the OpenTig process." } : authStatus === "unknown" ? { message: "Could not confirm Grok authentication." } : {}
|
|
13332
12853
|
};
|
|
12854
|
+
} catch (error) {
|
|
12855
|
+
return { ...installed, availability: "error", authStatus: "unknown", message: error instanceof AiOperationError ? error.message : "Could not verify Grok execution controls." };
|
|
13333
12856
|
}
|
|
13334
|
-
|
|
13335
|
-
|
|
13336
|
-
|
|
13337
|
-
|
|
13338
|
-
|
|
13339
|
-
|
|
13340
|
-
|
|
13341
|
-
|
|
13342
|
-
|
|
13343
|
-
|
|
13344
|
-
|
|
13345
|
-
|
|
13346
|
-
|
|
13347
|
-
|
|
13348
|
-
|
|
13349
|
-
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
|
|
13353
|
-
|
|
13354
|
-
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
12857
|
+
});
|
|
12858
|
+
}
|
|
12859
|
+
async generate(input) {
|
|
12860
|
+
const executable = await this.resolver.resolve("grok");
|
|
12861
|
+
if (!executable) throw failure("AI_CLI_NOT_FOUND", "Grok Build is not installed.");
|
|
12862
|
+
const timeout = AbortSignal.timeout(AI_PROVIDER_TIMEOUT_MS);
|
|
12863
|
+
const signal = AbortSignal.any([input.signal, timeout]);
|
|
12864
|
+
try {
|
|
12865
|
+
return await this.withEnvironment(async (options) => {
|
|
12866
|
+
const controlled = { ...options, signal };
|
|
12867
|
+
const version2 = await this.runner.run(executable, ["--version"], controlled);
|
|
12868
|
+
if (version2.exitCode !== 0 || !isSupportedGrokVersion(version2.stdout)) throw failure("AI_PROCESS_FAILED", UNSUPPORTED);
|
|
12869
|
+
await this.checkControls(executable, controlled);
|
|
12870
|
+
const promptFile = path.join(options.cwd, "prompt.txt");
|
|
12871
|
+
await writeFile(promptFile, input.prompt, { encoding: "utf8", mode: 384 });
|
|
12872
|
+
const args = [
|
|
12873
|
+
"--prompt-file",
|
|
12874
|
+
promptFile,
|
|
12875
|
+
"--output-format",
|
|
12876
|
+
"json",
|
|
12877
|
+
"--json-schema",
|
|
12878
|
+
JSON.stringify(input.schema),
|
|
12879
|
+
"--verbatim",
|
|
12880
|
+
"--tools",
|
|
12881
|
+
"read_file",
|
|
12882
|
+
"--disallowed-tools",
|
|
12883
|
+
"read_file,search_tool,use_tool,Agent",
|
|
12884
|
+
"--deny",
|
|
12885
|
+
"MCPTool",
|
|
12886
|
+
"--disable-web-search",
|
|
12887
|
+
"--max-turns",
|
|
12888
|
+
"1",
|
|
12889
|
+
"--permission-mode",
|
|
12890
|
+
"dontAsk",
|
|
12891
|
+
"--no-memory"
|
|
12892
|
+
];
|
|
12893
|
+
if (input.model !== "default") args.push("--model", input.model);
|
|
12894
|
+
const result = await this.runner.run(executable, args, { ...controlled, timeoutMs: AI_PROVIDER_TIMEOUT_MS });
|
|
12895
|
+
requireGrokSuccess(result);
|
|
12896
|
+
const parsed = parseGrokOutput(result.stdout);
|
|
12897
|
+
return { output: parsed.output, usage: grokUsage(parsed.envelope) };
|
|
12898
|
+
});
|
|
12899
|
+
} catch (error) {
|
|
12900
|
+
if (input.signal.aborted) throw failure("AI_CANCELLED", "Generation canceled.");
|
|
12901
|
+
if (timeout.aborted) throw failure("AI_TIMEOUT", "Generation took too long.");
|
|
12902
|
+
throw error;
|
|
13362
12903
|
}
|
|
13363
|
-
|
|
13364
|
-
|
|
12904
|
+
}
|
|
12905
|
+
async checkControls(executable, options) {
|
|
12906
|
+
const help = await this.runner.run(executable, ["--help"], options);
|
|
12907
|
+
if (help.exitCode !== 0 || REQUIRED_FLAGS.some((flag2) => !help.stdout.includes(flag2))) throw failure("AI_PROCESS_FAILED", UNSUPPORTED);
|
|
12908
|
+
const result = await this.runner.run(executable, ["inspect", "--json"], options);
|
|
12909
|
+
let report;
|
|
13365
12910
|
try {
|
|
13366
|
-
|
|
12911
|
+
report = JSON.parse(result.stdout);
|
|
13367
12912
|
} catch {
|
|
12913
|
+
throw failure("AI_PROCESS_FAILED", "Could not verify the isolated Grok configuration.");
|
|
13368
12914
|
}
|
|
13369
|
-
const
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
if (fn) {
|
|
13373
|
-
finalError = await fn(error, response, request2, opts);
|
|
13374
|
-
}
|
|
13375
|
-
}
|
|
13376
|
-
finalError = finalError || {};
|
|
13377
|
-
if (opts.throwOnError) {
|
|
13378
|
-
throw finalError;
|
|
12915
|
+
const surfaces = ["hooks", "plugins", "mcpServers", "projectInstructions"];
|
|
12916
|
+
if (result.exitCode !== 0 || !report || surfaces.some((key) => !Array.isArray(report[key]) || report[key].length > 0)) {
|
|
12917
|
+
throw failure("AI_PROCESS_FAILED", "Grok configuration includes hooks, plugins, MCP servers or instructions. OpenTig requires an isolated text-only configuration.");
|
|
13379
12918
|
}
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13384
|
-
|
|
13385
|
-
|
|
13386
|
-
|
|
13387
|
-
|
|
13388
|
-
|
|
13389
|
-
|
|
13390
|
-
|
|
13391
|
-
|
|
13392
|
-
|
|
13393
|
-
|
|
13394
|
-
|
|
13395
|
-
|
|
13396
|
-
|
|
13397
|
-
|
|
13398
|
-
|
|
13399
|
-
|
|
13400
|
-
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
|
|
13404
|
-
|
|
13405
|
-
|
|
13406
|
-
|
|
13407
|
-
options: makeMethod("OPTIONS"),
|
|
13408
|
-
patch: makeMethod("PATCH"),
|
|
13409
|
-
post: makeMethod("POST"),
|
|
13410
|
-
put: makeMethod("PUT"),
|
|
13411
|
-
request,
|
|
13412
|
-
setConfig,
|
|
13413
|
-
trace: makeMethod("TRACE")
|
|
13414
|
-
};
|
|
13415
|
-
};
|
|
13416
|
-
const client = createClient(createConfig({
|
|
13417
|
-
baseUrl: "http://localhost:4096"
|
|
13418
|
-
}));
|
|
13419
|
-
class _HeyApiClient {
|
|
13420
|
-
_client = client;
|
|
13421
|
-
constructor(args) {
|
|
13422
|
-
if (args?.client) {
|
|
13423
|
-
this._client = args.client;
|
|
12919
|
+
}
|
|
12920
|
+
async withEnvironment(run) {
|
|
12921
|
+
const temporary = await mkdtemp(path.join(os.tmpdir(), "opentig-grok-"));
|
|
12922
|
+
const userGrokHome = process.env.GROK_HOME || path.join(os.homedir(), ".grok");
|
|
12923
|
+
const authPath = path.resolve(process.env.GROK_AUTH_PATH || path.join(userGrokHome, "auth.json"));
|
|
12924
|
+
const privateGrokHome = path.join(temporary, ".grok");
|
|
12925
|
+
try {
|
|
12926
|
+
await mkdir(privateGrokHome, { mode: 448 });
|
|
12927
|
+
await writeFile(path.join(privateGrokHome, "config.toml"), CONFIG, { encoding: "utf8", mode: 384 });
|
|
12928
|
+
const env = {
|
|
12929
|
+
HOME: temporary,
|
|
12930
|
+
USERPROFILE: temporary,
|
|
12931
|
+
GROK_HOME: privateGrokHome,
|
|
12932
|
+
GROK_AUTH_PATH: authPath,
|
|
12933
|
+
XDG_CONFIG_HOME: path.join(temporary, "config"),
|
|
12934
|
+
XDG_DATA_HOME: path.join(temporary, "data"),
|
|
12935
|
+
XDG_CACHE_HOME: path.join(temporary, "cache"),
|
|
12936
|
+
GROK_SUBAGENTS: "0",
|
|
12937
|
+
GROK_MANAGED_MCPS_ENABLED: "0",
|
|
12938
|
+
GROK_MANAGED_MCP_GATEWAY_TOOLS_ENABLED: "0",
|
|
12939
|
+
GROK_TITLE_REFRESH: "0"
|
|
12940
|
+
};
|
|
12941
|
+
const preserved = /* @__PURE__ */ new Set([...Object.keys(env), "GROK_AUTH", "GROK_CODE_XAI_API_KEY"]);
|
|
12942
|
+
const removeEnv = Object.keys(process.env).filter((key) => key.startsWith("GROK_") && !preserved.has(key));
|
|
12943
|
+
return await run({ cwd: temporary, env, removeEnv });
|
|
12944
|
+
} finally {
|
|
12945
|
+
await rm(temporary, { recursive: true, force: true, maxRetries: 3 });
|
|
13424
12946
|
}
|
|
13425
12947
|
}
|
|
13426
12948
|
}
|
|
13427
|
-
|
|
13428
|
-
|
|
13429
|
-
|
|
13430
|
-
|
|
13431
|
-
|
|
13432
|
-
|
|
13433
|
-
|
|
13434
|
-
|
|
13435
|
-
});
|
|
13436
|
-
}
|
|
12949
|
+
function requireGrokSuccess(result) {
|
|
12950
|
+
if (result.exitCode === 0) return;
|
|
12951
|
+
const diagnostic = `${result.stdout}
|
|
12952
|
+
${result.stderr}`.toLowerCase();
|
|
12953
|
+
if (/not authenticated|not logged|login required|unauth|authentication|sign in/.test(diagnostic)) throw failure("AI_AUTH_REQUIRED", "Sign in with grok login to generate content.");
|
|
12954
|
+
if (/rate.?limit|quota|usage limit|too many requests|credit/.test(diagnostic)) throw failure("AI_RATE_LIMITED", "Grok rejected the request because of a usage limit.");
|
|
12955
|
+
if (/model.*(not found|unavailable|invalid|access|not supported)|unknown model/.test(diagnostic)) throw failure("AI_MODEL_UNAVAILABLE", "The selected Grok model is unavailable.");
|
|
12956
|
+
throw failure("AI_PROCESS_FAILED", "Grok could not generate content.");
|
|
13437
12957
|
}
|
|
13438
|
-
|
|
13439
|
-
|
|
13440
|
-
* List all projects
|
|
13441
|
-
*/
|
|
13442
|
-
list(options) {
|
|
13443
|
-
return (options?.client ?? this._client).get({
|
|
13444
|
-
url: "/project",
|
|
13445
|
-
...options
|
|
13446
|
-
});
|
|
13447
|
-
}
|
|
13448
|
-
/**
|
|
13449
|
-
* Get the current project
|
|
13450
|
-
*/
|
|
13451
|
-
current(options) {
|
|
13452
|
-
return (options?.client ?? this._client).get({
|
|
13453
|
-
url: "/project/current",
|
|
13454
|
-
...options
|
|
13455
|
-
});
|
|
13456
|
-
}
|
|
12958
|
+
function failure(code, message) {
|
|
12959
|
+
return new AiOperationError({ code, operation: "grok-generate", harness: "grok", message });
|
|
13457
12960
|
}
|
|
13458
|
-
|
|
13459
|
-
|
|
13460
|
-
* List all PTY sessions
|
|
13461
|
-
*/
|
|
13462
|
-
list(options) {
|
|
13463
|
-
return (options?.client ?? this._client).get({
|
|
13464
|
-
url: "/pty",
|
|
13465
|
-
...options
|
|
13466
|
-
});
|
|
13467
|
-
}
|
|
13468
|
-
/**
|
|
13469
|
-
* Create a new PTY session
|
|
13470
|
-
*/
|
|
13471
|
-
create(options) {
|
|
13472
|
-
return (options?.client ?? this._client).post({
|
|
13473
|
-
url: "/pty",
|
|
13474
|
-
...options,
|
|
13475
|
-
headers: {
|
|
13476
|
-
"Content-Type": "application/json",
|
|
13477
|
-
...options?.headers
|
|
13478
|
-
}
|
|
13479
|
-
});
|
|
13480
|
-
}
|
|
13481
|
-
/**
|
|
13482
|
-
* Remove a PTY session
|
|
13483
|
-
*/
|
|
13484
|
-
remove(options) {
|
|
13485
|
-
return (options.client ?? this._client).delete({
|
|
13486
|
-
url: "/pty/{id}",
|
|
13487
|
-
...options
|
|
13488
|
-
});
|
|
13489
|
-
}
|
|
13490
|
-
/**
|
|
13491
|
-
* Get PTY session info
|
|
13492
|
-
*/
|
|
13493
|
-
get(options) {
|
|
13494
|
-
return (options.client ?? this._client).get({
|
|
13495
|
-
url: "/pty/{id}",
|
|
13496
|
-
...options
|
|
13497
|
-
});
|
|
13498
|
-
}
|
|
13499
|
-
/**
|
|
13500
|
-
* Update PTY session
|
|
13501
|
-
*/
|
|
13502
|
-
update(options) {
|
|
13503
|
-
return (options.client ?? this._client).put({
|
|
13504
|
-
url: "/pty/{id}",
|
|
13505
|
-
...options,
|
|
13506
|
-
headers: {
|
|
13507
|
-
"Content-Type": "application/json",
|
|
13508
|
-
...options.headers
|
|
13509
|
-
}
|
|
13510
|
-
});
|
|
13511
|
-
}
|
|
13512
|
-
/**
|
|
13513
|
-
* Connect to a PTY session
|
|
13514
|
-
*/
|
|
13515
|
-
connect(options) {
|
|
13516
|
-
return (options.client ?? this._client).get({
|
|
13517
|
-
url: "/pty/{id}/connect",
|
|
13518
|
-
...options
|
|
13519
|
-
});
|
|
13520
|
-
}
|
|
12961
|
+
function openCodeCliName(executable) {
|
|
12962
|
+
return path.parse(executable).name.toLowerCase() === "opencode2" ? "opencode2" : "opencode";
|
|
13521
12963
|
}
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
* Get config info
|
|
13525
|
-
*/
|
|
13526
|
-
get(options) {
|
|
13527
|
-
return (options?.client ?? this._client).get({
|
|
13528
|
-
url: "/config",
|
|
13529
|
-
...options
|
|
13530
|
-
});
|
|
13531
|
-
}
|
|
13532
|
-
/**
|
|
13533
|
-
* Update config
|
|
13534
|
-
*/
|
|
13535
|
-
update(options) {
|
|
13536
|
-
return (options?.client ?? this._client).patch({
|
|
13537
|
-
url: "/config",
|
|
13538
|
-
...options,
|
|
13539
|
-
headers: {
|
|
13540
|
-
"Content-Type": "application/json",
|
|
13541
|
-
...options?.headers
|
|
13542
|
-
}
|
|
13543
|
-
});
|
|
13544
|
-
}
|
|
13545
|
-
/**
|
|
13546
|
-
* List all providers
|
|
13547
|
-
*/
|
|
13548
|
-
providers(options) {
|
|
13549
|
-
return (options?.client ?? this._client).get({
|
|
13550
|
-
url: "/config/providers",
|
|
13551
|
-
...options
|
|
13552
|
-
});
|
|
13553
|
-
}
|
|
12964
|
+
function isOpenCodeV2Version(raw) {
|
|
12965
|
+
return /^(?:opencode2?\s+)?v?2\.\d+\.\d+(?:[-+][\w.-]+)?$/.test(stripAnsi(raw).trim());
|
|
13554
12966
|
}
|
|
13555
|
-
|
|
13556
|
-
|
|
13557
|
-
* List all tool IDs (including built-in and dynamically registered)
|
|
13558
|
-
*/
|
|
13559
|
-
ids(options) {
|
|
13560
|
-
return (options?.client ?? this._client).get({
|
|
13561
|
-
url: "/experimental/tool/ids",
|
|
13562
|
-
...options
|
|
13563
|
-
});
|
|
13564
|
-
}
|
|
13565
|
-
/**
|
|
13566
|
-
* List tools with JSON schema parameters for a provider/model
|
|
13567
|
-
*/
|
|
13568
|
-
list(options) {
|
|
13569
|
-
return (options.client ?? this._client).get({
|
|
13570
|
-
url: "/experimental/tool",
|
|
13571
|
-
...options
|
|
13572
|
-
});
|
|
13573
|
-
}
|
|
12967
|
+
function openCodeLoginCommand(cliName) {
|
|
12968
|
+
return cliName === "opencode2" ? "opencode2 auth login" : "opencode auth login";
|
|
13574
12969
|
}
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13578
|
-
|
|
13579
|
-
|
|
13580
|
-
return (
|
|
13581
|
-
|
|
13582
|
-
...options
|
|
13583
|
-
});
|
|
12970
|
+
function parseOpenCodeAuthList(raw, exitCode) {
|
|
12971
|
+
if (exitCode !== 0) return "unknown";
|
|
12972
|
+
try {
|
|
12973
|
+
const integrations = JSON.parse(stripAnsi(raw).trim());
|
|
12974
|
+
if (!Array.isArray(integrations) || integrations.some((item) => !item || typeof item !== "object" || !Array.isArray(item.connections))) return "unknown";
|
|
12975
|
+
return integrations.some((item) => item.connections.length > 0) ? "authenticated" : "unauthenticated";
|
|
12976
|
+
} catch {
|
|
13584
12977
|
}
|
|
13585
|
-
|
|
13586
|
-
class Path extends _HeyApiClient {
|
|
13587
|
-
/**
|
|
13588
|
-
* Get the current path
|
|
13589
|
-
*/
|
|
13590
|
-
get(options) {
|
|
13591
|
-
return (options?.client ?? this._client).get({
|
|
13592
|
-
url: "/path",
|
|
13593
|
-
...options
|
|
13594
|
-
});
|
|
13595
|
-
}
|
|
13596
|
-
}
|
|
13597
|
-
class Vcs extends _HeyApiClient {
|
|
13598
|
-
/**
|
|
13599
|
-
* Get VCS info for the current instance
|
|
13600
|
-
*/
|
|
13601
|
-
get(options) {
|
|
13602
|
-
return (options?.client ?? this._client).get({
|
|
13603
|
-
url: "/vcs",
|
|
13604
|
-
...options
|
|
13605
|
-
});
|
|
13606
|
-
}
|
|
13607
|
-
}
|
|
13608
|
-
class Session extends _HeyApiClient {
|
|
13609
|
-
/**
|
|
13610
|
-
* List all sessions
|
|
13611
|
-
*/
|
|
13612
|
-
list(options) {
|
|
13613
|
-
return (options?.client ?? this._client).get({
|
|
13614
|
-
url: "/session",
|
|
13615
|
-
...options
|
|
13616
|
-
});
|
|
13617
|
-
}
|
|
13618
|
-
/**
|
|
13619
|
-
* Create a new session
|
|
13620
|
-
*/
|
|
13621
|
-
create(options) {
|
|
13622
|
-
return (options?.client ?? this._client).post({
|
|
13623
|
-
url: "/session",
|
|
13624
|
-
...options,
|
|
13625
|
-
headers: {
|
|
13626
|
-
"Content-Type": "application/json",
|
|
13627
|
-
...options?.headers
|
|
13628
|
-
}
|
|
13629
|
-
});
|
|
13630
|
-
}
|
|
13631
|
-
/**
|
|
13632
|
-
* Get session status
|
|
13633
|
-
*/
|
|
13634
|
-
status(options) {
|
|
13635
|
-
return (options?.client ?? this._client).get({
|
|
13636
|
-
url: "/session/status",
|
|
13637
|
-
...options
|
|
13638
|
-
});
|
|
13639
|
-
}
|
|
13640
|
-
/**
|
|
13641
|
-
* Delete a session and all its data
|
|
13642
|
-
*/
|
|
13643
|
-
delete(options) {
|
|
13644
|
-
return (options.client ?? this._client).delete({
|
|
13645
|
-
url: "/session/{id}",
|
|
13646
|
-
...options
|
|
13647
|
-
});
|
|
13648
|
-
}
|
|
13649
|
-
/**
|
|
13650
|
-
* Get session
|
|
13651
|
-
*/
|
|
13652
|
-
get(options) {
|
|
13653
|
-
return (options.client ?? this._client).get({
|
|
13654
|
-
url: "/session/{id}",
|
|
13655
|
-
...options
|
|
13656
|
-
});
|
|
13657
|
-
}
|
|
13658
|
-
/**
|
|
13659
|
-
* Update session properties
|
|
13660
|
-
*/
|
|
13661
|
-
update(options) {
|
|
13662
|
-
return (options.client ?? this._client).patch({
|
|
13663
|
-
url: "/session/{id}",
|
|
13664
|
-
...options,
|
|
13665
|
-
headers: {
|
|
13666
|
-
"Content-Type": "application/json",
|
|
13667
|
-
...options.headers
|
|
13668
|
-
}
|
|
13669
|
-
});
|
|
13670
|
-
}
|
|
13671
|
-
/**
|
|
13672
|
-
* Get a session's children
|
|
13673
|
-
*/
|
|
13674
|
-
children(options) {
|
|
13675
|
-
return (options.client ?? this._client).get({
|
|
13676
|
-
url: "/session/{id}/children",
|
|
13677
|
-
...options
|
|
13678
|
-
});
|
|
13679
|
-
}
|
|
13680
|
-
/**
|
|
13681
|
-
* Get the todo list for a session
|
|
13682
|
-
*/
|
|
13683
|
-
todo(options) {
|
|
13684
|
-
return (options.client ?? this._client).get({
|
|
13685
|
-
url: "/session/{id}/todo",
|
|
13686
|
-
...options
|
|
13687
|
-
});
|
|
13688
|
-
}
|
|
13689
|
-
/**
|
|
13690
|
-
* Analyze the app and create an AGENTS.md file
|
|
13691
|
-
*/
|
|
13692
|
-
init(options) {
|
|
13693
|
-
return (options.client ?? this._client).post({
|
|
13694
|
-
url: "/session/{id}/init",
|
|
13695
|
-
...options,
|
|
13696
|
-
headers: {
|
|
13697
|
-
"Content-Type": "application/json",
|
|
13698
|
-
...options.headers
|
|
13699
|
-
}
|
|
13700
|
-
});
|
|
13701
|
-
}
|
|
13702
|
-
/**
|
|
13703
|
-
* Fork an existing session at a specific message
|
|
13704
|
-
*/
|
|
13705
|
-
fork(options) {
|
|
13706
|
-
return (options.client ?? this._client).post({
|
|
13707
|
-
url: "/session/{id}/fork",
|
|
13708
|
-
...options,
|
|
13709
|
-
headers: {
|
|
13710
|
-
"Content-Type": "application/json",
|
|
13711
|
-
...options.headers
|
|
13712
|
-
}
|
|
13713
|
-
});
|
|
13714
|
-
}
|
|
13715
|
-
/**
|
|
13716
|
-
* Abort a session
|
|
13717
|
-
*/
|
|
13718
|
-
abort(options) {
|
|
13719
|
-
return (options.client ?? this._client).post({
|
|
13720
|
-
url: "/session/{id}/abort",
|
|
13721
|
-
...options
|
|
13722
|
-
});
|
|
13723
|
-
}
|
|
13724
|
-
/**
|
|
13725
|
-
* Unshare the session
|
|
13726
|
-
*/
|
|
13727
|
-
unshare(options) {
|
|
13728
|
-
return (options.client ?? this._client).delete({
|
|
13729
|
-
url: "/session/{id}/share",
|
|
13730
|
-
...options
|
|
13731
|
-
});
|
|
13732
|
-
}
|
|
13733
|
-
/**
|
|
13734
|
-
* Share a session
|
|
13735
|
-
*/
|
|
13736
|
-
share(options) {
|
|
13737
|
-
return (options.client ?? this._client).post({
|
|
13738
|
-
url: "/session/{id}/share",
|
|
13739
|
-
...options
|
|
13740
|
-
});
|
|
13741
|
-
}
|
|
13742
|
-
/**
|
|
13743
|
-
* Get the diff for this session
|
|
13744
|
-
*/
|
|
13745
|
-
diff(options) {
|
|
13746
|
-
return (options.client ?? this._client).get({
|
|
13747
|
-
url: "/session/{id}/diff",
|
|
13748
|
-
...options
|
|
13749
|
-
});
|
|
13750
|
-
}
|
|
13751
|
-
/**
|
|
13752
|
-
* Summarize the session
|
|
13753
|
-
*/
|
|
13754
|
-
summarize(options) {
|
|
13755
|
-
return (options.client ?? this._client).post({
|
|
13756
|
-
url: "/session/{id}/summarize",
|
|
13757
|
-
...options,
|
|
13758
|
-
headers: {
|
|
13759
|
-
"Content-Type": "application/json",
|
|
13760
|
-
...options.headers
|
|
13761
|
-
}
|
|
13762
|
-
});
|
|
13763
|
-
}
|
|
13764
|
-
/**
|
|
13765
|
-
* List messages for a session
|
|
13766
|
-
*/
|
|
13767
|
-
messages(options) {
|
|
13768
|
-
return (options.client ?? this._client).get({
|
|
13769
|
-
url: "/session/{id}/message",
|
|
13770
|
-
...options
|
|
13771
|
-
});
|
|
13772
|
-
}
|
|
13773
|
-
/**
|
|
13774
|
-
* Create and send a new message to a session
|
|
13775
|
-
*/
|
|
13776
|
-
prompt(options) {
|
|
13777
|
-
return (options.client ?? this._client).post({
|
|
13778
|
-
url: "/session/{id}/message",
|
|
13779
|
-
...options,
|
|
13780
|
-
headers: {
|
|
13781
|
-
"Content-Type": "application/json",
|
|
13782
|
-
...options.headers
|
|
13783
|
-
}
|
|
13784
|
-
});
|
|
13785
|
-
}
|
|
13786
|
-
/**
|
|
13787
|
-
* Get a message from a session
|
|
13788
|
-
*/
|
|
13789
|
-
message(options) {
|
|
13790
|
-
return (options.client ?? this._client).get({
|
|
13791
|
-
url: "/session/{id}/message/{messageID}",
|
|
13792
|
-
...options
|
|
13793
|
-
});
|
|
13794
|
-
}
|
|
13795
|
-
/**
|
|
13796
|
-
* Create and send a new message to a session, start if needed and return immediately
|
|
13797
|
-
*/
|
|
13798
|
-
promptAsync(options) {
|
|
13799
|
-
return (options.client ?? this._client).post({
|
|
13800
|
-
url: "/session/{id}/prompt_async",
|
|
13801
|
-
...options,
|
|
13802
|
-
headers: {
|
|
13803
|
-
"Content-Type": "application/json",
|
|
13804
|
-
...options.headers
|
|
13805
|
-
}
|
|
13806
|
-
});
|
|
13807
|
-
}
|
|
13808
|
-
/**
|
|
13809
|
-
* Send a new command to a session
|
|
13810
|
-
*/
|
|
13811
|
-
command(options) {
|
|
13812
|
-
return (options.client ?? this._client).post({
|
|
13813
|
-
url: "/session/{id}/command",
|
|
13814
|
-
...options,
|
|
13815
|
-
headers: {
|
|
13816
|
-
"Content-Type": "application/json",
|
|
13817
|
-
...options.headers
|
|
13818
|
-
}
|
|
13819
|
-
});
|
|
13820
|
-
}
|
|
13821
|
-
/**
|
|
13822
|
-
* Run a shell command
|
|
13823
|
-
*/
|
|
13824
|
-
shell(options) {
|
|
13825
|
-
return (options.client ?? this._client).post({
|
|
13826
|
-
url: "/session/{id}/shell",
|
|
13827
|
-
...options,
|
|
13828
|
-
headers: {
|
|
13829
|
-
"Content-Type": "application/json",
|
|
13830
|
-
...options.headers
|
|
13831
|
-
}
|
|
13832
|
-
});
|
|
13833
|
-
}
|
|
13834
|
-
/**
|
|
13835
|
-
* Revert a message
|
|
13836
|
-
*/
|
|
13837
|
-
revert(options) {
|
|
13838
|
-
return (options.client ?? this._client).post({
|
|
13839
|
-
url: "/session/{id}/revert",
|
|
13840
|
-
...options,
|
|
13841
|
-
headers: {
|
|
13842
|
-
"Content-Type": "application/json",
|
|
13843
|
-
...options.headers
|
|
13844
|
-
}
|
|
13845
|
-
});
|
|
13846
|
-
}
|
|
13847
|
-
/**
|
|
13848
|
-
* Restore all reverted messages
|
|
13849
|
-
*/
|
|
13850
|
-
unrevert(options) {
|
|
13851
|
-
return (options.client ?? this._client).post({
|
|
13852
|
-
url: "/session/{id}/unrevert",
|
|
13853
|
-
...options
|
|
13854
|
-
});
|
|
13855
|
-
}
|
|
13856
|
-
}
|
|
13857
|
-
class Command extends _HeyApiClient {
|
|
13858
|
-
/**
|
|
13859
|
-
* List all commands
|
|
13860
|
-
*/
|
|
13861
|
-
list(options) {
|
|
13862
|
-
return (options?.client ?? this._client).get({
|
|
13863
|
-
url: "/command",
|
|
13864
|
-
...options
|
|
13865
|
-
});
|
|
13866
|
-
}
|
|
13867
|
-
}
|
|
13868
|
-
class Oauth extends _HeyApiClient {
|
|
13869
|
-
/**
|
|
13870
|
-
* Authorize a provider using OAuth
|
|
13871
|
-
*/
|
|
13872
|
-
authorize(options) {
|
|
13873
|
-
return (options.client ?? this._client).post({
|
|
13874
|
-
url: "/provider/{id}/oauth/authorize",
|
|
13875
|
-
...options,
|
|
13876
|
-
headers: {
|
|
13877
|
-
"Content-Type": "application/json",
|
|
13878
|
-
...options.headers
|
|
13879
|
-
}
|
|
13880
|
-
});
|
|
13881
|
-
}
|
|
13882
|
-
/**
|
|
13883
|
-
* Handle OAuth callback for a provider
|
|
13884
|
-
*/
|
|
13885
|
-
callback(options) {
|
|
13886
|
-
return (options.client ?? this._client).post({
|
|
13887
|
-
url: "/provider/{id}/oauth/callback",
|
|
13888
|
-
...options,
|
|
13889
|
-
headers: {
|
|
13890
|
-
"Content-Type": "application/json",
|
|
13891
|
-
...options.headers
|
|
13892
|
-
}
|
|
13893
|
-
});
|
|
13894
|
-
}
|
|
13895
|
-
}
|
|
13896
|
-
class Provider extends _HeyApiClient {
|
|
13897
|
-
/**
|
|
13898
|
-
* List all providers
|
|
13899
|
-
*/
|
|
13900
|
-
list(options) {
|
|
13901
|
-
return (options?.client ?? this._client).get({
|
|
13902
|
-
url: "/provider",
|
|
13903
|
-
...options
|
|
13904
|
-
});
|
|
13905
|
-
}
|
|
13906
|
-
/**
|
|
13907
|
-
* Get provider authentication methods
|
|
13908
|
-
*/
|
|
13909
|
-
auth(options) {
|
|
13910
|
-
return (options?.client ?? this._client).get({
|
|
13911
|
-
url: "/provider/auth",
|
|
13912
|
-
...options
|
|
13913
|
-
});
|
|
13914
|
-
}
|
|
13915
|
-
oauth = new Oauth({ client: this._client });
|
|
13916
|
-
}
|
|
13917
|
-
class Find extends _HeyApiClient {
|
|
13918
|
-
/**
|
|
13919
|
-
* Find text in files
|
|
13920
|
-
*/
|
|
13921
|
-
text(options) {
|
|
13922
|
-
return (options.client ?? this._client).get({
|
|
13923
|
-
url: "/find",
|
|
13924
|
-
...options
|
|
13925
|
-
});
|
|
13926
|
-
}
|
|
13927
|
-
/**
|
|
13928
|
-
* Find files
|
|
13929
|
-
*/
|
|
13930
|
-
files(options) {
|
|
13931
|
-
return (options.client ?? this._client).get({
|
|
13932
|
-
url: "/find/file",
|
|
13933
|
-
...options
|
|
13934
|
-
});
|
|
13935
|
-
}
|
|
13936
|
-
/**
|
|
13937
|
-
* Find workspace symbols
|
|
13938
|
-
*/
|
|
13939
|
-
symbols(options) {
|
|
13940
|
-
return (options.client ?? this._client).get({
|
|
13941
|
-
url: "/find/symbol",
|
|
13942
|
-
...options
|
|
13943
|
-
});
|
|
13944
|
-
}
|
|
13945
|
-
}
|
|
13946
|
-
class File extends _HeyApiClient {
|
|
13947
|
-
/**
|
|
13948
|
-
* List files and directories
|
|
13949
|
-
*/
|
|
13950
|
-
list(options) {
|
|
13951
|
-
return (options.client ?? this._client).get({
|
|
13952
|
-
url: "/file",
|
|
13953
|
-
...options
|
|
13954
|
-
});
|
|
13955
|
-
}
|
|
13956
|
-
/**
|
|
13957
|
-
* Read a file
|
|
13958
|
-
*/
|
|
13959
|
-
read(options) {
|
|
13960
|
-
return (options.client ?? this._client).get({
|
|
13961
|
-
url: "/file/content",
|
|
13962
|
-
...options
|
|
13963
|
-
});
|
|
13964
|
-
}
|
|
13965
|
-
/**
|
|
13966
|
-
* Get file status
|
|
13967
|
-
*/
|
|
13968
|
-
status(options) {
|
|
13969
|
-
return (options?.client ?? this._client).get({
|
|
13970
|
-
url: "/file/status",
|
|
13971
|
-
...options
|
|
13972
|
-
});
|
|
13973
|
-
}
|
|
13974
|
-
}
|
|
13975
|
-
class App extends _HeyApiClient {
|
|
13976
|
-
/**
|
|
13977
|
-
* Write a log entry to the server logs
|
|
13978
|
-
*/
|
|
13979
|
-
log(options) {
|
|
13980
|
-
return (options?.client ?? this._client).post({
|
|
13981
|
-
url: "/log",
|
|
13982
|
-
...options,
|
|
13983
|
-
headers: {
|
|
13984
|
-
"Content-Type": "application/json",
|
|
13985
|
-
...options?.headers
|
|
13986
|
-
}
|
|
13987
|
-
});
|
|
13988
|
-
}
|
|
13989
|
-
/**
|
|
13990
|
-
* List all agents
|
|
13991
|
-
*/
|
|
13992
|
-
agents(options) {
|
|
13993
|
-
return (options?.client ?? this._client).get({
|
|
13994
|
-
url: "/agent",
|
|
13995
|
-
...options
|
|
13996
|
-
});
|
|
13997
|
-
}
|
|
13998
|
-
}
|
|
13999
|
-
class Auth extends _HeyApiClient {
|
|
14000
|
-
/**
|
|
14001
|
-
* Remove OAuth credentials for an MCP server
|
|
14002
|
-
*/
|
|
14003
|
-
remove(options) {
|
|
14004
|
-
return (options.client ?? this._client).delete({
|
|
14005
|
-
url: "/mcp/{name}/auth",
|
|
14006
|
-
...options
|
|
14007
|
-
});
|
|
14008
|
-
}
|
|
14009
|
-
/**
|
|
14010
|
-
* Start OAuth authentication flow for an MCP server
|
|
14011
|
-
*/
|
|
14012
|
-
start(options) {
|
|
14013
|
-
return (options.client ?? this._client).post({
|
|
14014
|
-
url: "/mcp/{name}/auth",
|
|
14015
|
-
...options
|
|
14016
|
-
});
|
|
14017
|
-
}
|
|
14018
|
-
/**
|
|
14019
|
-
* Complete OAuth authentication with authorization code
|
|
14020
|
-
*/
|
|
14021
|
-
callback(options) {
|
|
14022
|
-
return (options.client ?? this._client).post({
|
|
14023
|
-
url: "/mcp/{name}/auth/callback",
|
|
14024
|
-
...options,
|
|
14025
|
-
headers: {
|
|
14026
|
-
"Content-Type": "application/json",
|
|
14027
|
-
...options.headers
|
|
14028
|
-
}
|
|
14029
|
-
});
|
|
14030
|
-
}
|
|
14031
|
-
/**
|
|
14032
|
-
* Start OAuth flow and wait for callback (opens browser)
|
|
14033
|
-
*/
|
|
14034
|
-
authenticate(options) {
|
|
14035
|
-
return (options.client ?? this._client).post({
|
|
14036
|
-
url: "/mcp/{name}/auth/authenticate",
|
|
14037
|
-
...options
|
|
14038
|
-
});
|
|
14039
|
-
}
|
|
14040
|
-
/**
|
|
14041
|
-
* Set authentication credentials
|
|
14042
|
-
*/
|
|
14043
|
-
set(options) {
|
|
14044
|
-
return (options.client ?? this._client).put({
|
|
14045
|
-
url: "/auth/{id}",
|
|
14046
|
-
...options,
|
|
14047
|
-
headers: {
|
|
14048
|
-
"Content-Type": "application/json",
|
|
14049
|
-
...options.headers
|
|
14050
|
-
}
|
|
14051
|
-
});
|
|
14052
|
-
}
|
|
14053
|
-
}
|
|
14054
|
-
class Mcp extends _HeyApiClient {
|
|
14055
|
-
/**
|
|
14056
|
-
* Get MCP server status
|
|
14057
|
-
*/
|
|
14058
|
-
status(options) {
|
|
14059
|
-
return (options?.client ?? this._client).get({
|
|
14060
|
-
url: "/mcp",
|
|
14061
|
-
...options
|
|
14062
|
-
});
|
|
14063
|
-
}
|
|
14064
|
-
/**
|
|
14065
|
-
* Add MCP server dynamically
|
|
14066
|
-
*/
|
|
14067
|
-
add(options) {
|
|
14068
|
-
return (options?.client ?? this._client).post({
|
|
14069
|
-
url: "/mcp",
|
|
14070
|
-
...options,
|
|
14071
|
-
headers: {
|
|
14072
|
-
"Content-Type": "application/json",
|
|
14073
|
-
...options?.headers
|
|
14074
|
-
}
|
|
14075
|
-
});
|
|
14076
|
-
}
|
|
14077
|
-
/**
|
|
14078
|
-
* Connect an MCP server
|
|
14079
|
-
*/
|
|
14080
|
-
connect(options) {
|
|
14081
|
-
return (options.client ?? this._client).post({
|
|
14082
|
-
url: "/mcp/{name}/connect",
|
|
14083
|
-
...options
|
|
14084
|
-
});
|
|
14085
|
-
}
|
|
14086
|
-
/**
|
|
14087
|
-
* Disconnect an MCP server
|
|
14088
|
-
*/
|
|
14089
|
-
disconnect(options) {
|
|
14090
|
-
return (options.client ?? this._client).post({
|
|
14091
|
-
url: "/mcp/{name}/disconnect",
|
|
14092
|
-
...options
|
|
14093
|
-
});
|
|
14094
|
-
}
|
|
14095
|
-
auth = new Auth({ client: this._client });
|
|
14096
|
-
}
|
|
14097
|
-
class Lsp extends _HeyApiClient {
|
|
14098
|
-
/**
|
|
14099
|
-
* Get LSP server status
|
|
14100
|
-
*/
|
|
14101
|
-
status(options) {
|
|
14102
|
-
return (options?.client ?? this._client).get({
|
|
14103
|
-
url: "/lsp",
|
|
14104
|
-
...options
|
|
14105
|
-
});
|
|
14106
|
-
}
|
|
14107
|
-
}
|
|
14108
|
-
class Formatter extends _HeyApiClient {
|
|
14109
|
-
/**
|
|
14110
|
-
* Get formatter status
|
|
14111
|
-
*/
|
|
14112
|
-
status(options) {
|
|
14113
|
-
return (options?.client ?? this._client).get({
|
|
14114
|
-
url: "/formatter",
|
|
14115
|
-
...options
|
|
14116
|
-
});
|
|
14117
|
-
}
|
|
14118
|
-
}
|
|
14119
|
-
class Control extends _HeyApiClient {
|
|
14120
|
-
/**
|
|
14121
|
-
* Get the next TUI request from the queue
|
|
14122
|
-
*/
|
|
14123
|
-
next(options) {
|
|
14124
|
-
return (options?.client ?? this._client).get({
|
|
14125
|
-
url: "/tui/control/next",
|
|
14126
|
-
...options
|
|
14127
|
-
});
|
|
14128
|
-
}
|
|
14129
|
-
/**
|
|
14130
|
-
* Submit a response to the TUI request queue
|
|
14131
|
-
*/
|
|
14132
|
-
response(options) {
|
|
14133
|
-
return (options?.client ?? this._client).post({
|
|
14134
|
-
url: "/tui/control/response",
|
|
14135
|
-
...options,
|
|
14136
|
-
headers: {
|
|
14137
|
-
"Content-Type": "application/json",
|
|
14138
|
-
...options?.headers
|
|
14139
|
-
}
|
|
14140
|
-
});
|
|
14141
|
-
}
|
|
14142
|
-
}
|
|
14143
|
-
class Tui extends _HeyApiClient {
|
|
14144
|
-
/**
|
|
14145
|
-
* Append prompt to the TUI
|
|
14146
|
-
*/
|
|
14147
|
-
appendPrompt(options) {
|
|
14148
|
-
return (options?.client ?? this._client).post({
|
|
14149
|
-
url: "/tui/append-prompt",
|
|
14150
|
-
...options,
|
|
14151
|
-
headers: {
|
|
14152
|
-
"Content-Type": "application/json",
|
|
14153
|
-
...options?.headers
|
|
14154
|
-
}
|
|
14155
|
-
});
|
|
14156
|
-
}
|
|
14157
|
-
/**
|
|
14158
|
-
* Open the help dialog
|
|
14159
|
-
*/
|
|
14160
|
-
openHelp(options) {
|
|
14161
|
-
return (options?.client ?? this._client).post({
|
|
14162
|
-
url: "/tui/open-help",
|
|
14163
|
-
...options
|
|
14164
|
-
});
|
|
14165
|
-
}
|
|
14166
|
-
/**
|
|
14167
|
-
* Open the session dialog
|
|
14168
|
-
*/
|
|
14169
|
-
openSessions(options) {
|
|
14170
|
-
return (options?.client ?? this._client).post({
|
|
14171
|
-
url: "/tui/open-sessions",
|
|
14172
|
-
...options
|
|
14173
|
-
});
|
|
14174
|
-
}
|
|
14175
|
-
/**
|
|
14176
|
-
* Open the theme dialog
|
|
14177
|
-
*/
|
|
14178
|
-
openThemes(options) {
|
|
14179
|
-
return (options?.client ?? this._client).post({
|
|
14180
|
-
url: "/tui/open-themes",
|
|
14181
|
-
...options
|
|
14182
|
-
});
|
|
14183
|
-
}
|
|
14184
|
-
/**
|
|
14185
|
-
* Open the model dialog
|
|
14186
|
-
*/
|
|
14187
|
-
openModels(options) {
|
|
14188
|
-
return (options?.client ?? this._client).post({
|
|
14189
|
-
url: "/tui/open-models",
|
|
14190
|
-
...options
|
|
14191
|
-
});
|
|
14192
|
-
}
|
|
14193
|
-
/**
|
|
14194
|
-
* Submit the prompt
|
|
14195
|
-
*/
|
|
14196
|
-
submitPrompt(options) {
|
|
14197
|
-
return (options?.client ?? this._client).post({
|
|
14198
|
-
url: "/tui/submit-prompt",
|
|
14199
|
-
...options
|
|
14200
|
-
});
|
|
14201
|
-
}
|
|
14202
|
-
/**
|
|
14203
|
-
* Clear the prompt
|
|
14204
|
-
*/
|
|
14205
|
-
clearPrompt(options) {
|
|
14206
|
-
return (options?.client ?? this._client).post({
|
|
14207
|
-
url: "/tui/clear-prompt",
|
|
14208
|
-
...options
|
|
14209
|
-
});
|
|
14210
|
-
}
|
|
14211
|
-
/**
|
|
14212
|
-
* Execute a TUI command (e.g. agent_cycle)
|
|
14213
|
-
*/
|
|
14214
|
-
executeCommand(options) {
|
|
14215
|
-
return (options?.client ?? this._client).post({
|
|
14216
|
-
url: "/tui/execute-command",
|
|
14217
|
-
...options,
|
|
14218
|
-
headers: {
|
|
14219
|
-
"Content-Type": "application/json",
|
|
14220
|
-
...options?.headers
|
|
14221
|
-
}
|
|
14222
|
-
});
|
|
14223
|
-
}
|
|
14224
|
-
/**
|
|
14225
|
-
* Show a toast notification in the TUI
|
|
14226
|
-
*/
|
|
14227
|
-
showToast(options) {
|
|
14228
|
-
return (options?.client ?? this._client).post({
|
|
14229
|
-
url: "/tui/show-toast",
|
|
14230
|
-
...options,
|
|
14231
|
-
headers: {
|
|
14232
|
-
"Content-Type": "application/json",
|
|
14233
|
-
...options?.headers
|
|
14234
|
-
}
|
|
14235
|
-
});
|
|
14236
|
-
}
|
|
14237
|
-
/**
|
|
14238
|
-
* Publish a TUI event
|
|
14239
|
-
*/
|
|
14240
|
-
publish(options) {
|
|
14241
|
-
return (options?.client ?? this._client).post({
|
|
14242
|
-
url: "/tui/publish",
|
|
14243
|
-
...options,
|
|
14244
|
-
headers: {
|
|
14245
|
-
"Content-Type": "application/json",
|
|
14246
|
-
...options?.headers
|
|
14247
|
-
}
|
|
14248
|
-
});
|
|
14249
|
-
}
|
|
14250
|
-
control = new Control({ client: this._client });
|
|
14251
|
-
}
|
|
14252
|
-
class Event extends _HeyApiClient {
|
|
14253
|
-
/**
|
|
14254
|
-
* Get events
|
|
14255
|
-
*/
|
|
14256
|
-
subscribe(options) {
|
|
14257
|
-
return (options?.client ?? this._client).get.sse({
|
|
14258
|
-
url: "/event",
|
|
14259
|
-
...options
|
|
14260
|
-
});
|
|
14261
|
-
}
|
|
14262
|
-
}
|
|
14263
|
-
class OpencodeClient extends _HeyApiClient {
|
|
14264
|
-
/**
|
|
14265
|
-
* Respond to a permission request
|
|
14266
|
-
*/
|
|
14267
|
-
postSessionIdPermissionsPermissionId(options) {
|
|
14268
|
-
return (options.client ?? this._client).post({
|
|
14269
|
-
url: "/session/{id}/permissions/{permissionID}",
|
|
14270
|
-
...options,
|
|
14271
|
-
headers: {
|
|
14272
|
-
"Content-Type": "application/json",
|
|
14273
|
-
...options.headers
|
|
14274
|
-
}
|
|
14275
|
-
});
|
|
14276
|
-
}
|
|
14277
|
-
global = new Global({ client: this._client });
|
|
14278
|
-
project = new Project({ client: this._client });
|
|
14279
|
-
pty = new Pty({ client: this._client });
|
|
14280
|
-
config = new Config({ client: this._client });
|
|
14281
|
-
tool = new Tool({ client: this._client });
|
|
14282
|
-
instance = new Instance({ client: this._client });
|
|
14283
|
-
path = new Path({ client: this._client });
|
|
14284
|
-
vcs = new Vcs({ client: this._client });
|
|
14285
|
-
session = new Session({ client: this._client });
|
|
14286
|
-
command = new Command({ client: this._client });
|
|
14287
|
-
provider = new Provider({ client: this._client });
|
|
14288
|
-
find = new Find({ client: this._client });
|
|
14289
|
-
file = new File({ client: this._client });
|
|
14290
|
-
app = new App({ client: this._client });
|
|
14291
|
-
mcp = new Mcp({ client: this._client });
|
|
14292
|
-
lsp = new Lsp({ client: this._client });
|
|
14293
|
-
formatter = new Formatter({ client: this._client });
|
|
14294
|
-
tui = new Tui({ client: this._client });
|
|
14295
|
-
auth = new Auth({ client: this._client });
|
|
14296
|
-
event = new Event({ client: this._client });
|
|
14297
|
-
}
|
|
14298
|
-
function wrapClientError(error, response, request, opts) {
|
|
14299
|
-
if (!opts?.throwOnError)
|
|
14300
|
-
return error;
|
|
14301
|
-
if (error instanceof Error)
|
|
14302
|
-
return error;
|
|
14303
|
-
if (typeof error === "object" && error !== null && Object.keys(error).length > 0) {
|
|
14304
|
-
const obj = error;
|
|
14305
|
-
const message = typeof obj.data?.message === "string" && obj.data.message || typeof obj.message === "string" && obj.message || typeof obj.name === "string" && obj.name || describe(request, response);
|
|
14306
|
-
return new Error(message, { cause: { body: error, status: response?.status } });
|
|
14307
|
-
}
|
|
14308
|
-
if (typeof error === "string" && error.length > 0) {
|
|
14309
|
-
return new Error(error, { cause: { body: error, status: response?.status } });
|
|
14310
|
-
}
|
|
14311
|
-
const reason = response ? "(empty response body)" : "network error (no response)";
|
|
14312
|
-
return new Error(`opencode server ${describe(request, response)}: ${reason}`, {
|
|
14313
|
-
cause: { body: error, status: response?.status }
|
|
14314
|
-
});
|
|
14315
|
-
}
|
|
14316
|
-
function describe(request, response) {
|
|
14317
|
-
const method = request?.method ?? "?";
|
|
14318
|
-
const url = request?.url ?? "?";
|
|
14319
|
-
const status = response?.status;
|
|
14320
|
-
const statusText = response?.statusText;
|
|
14321
|
-
return `${method} ${url}${status ? " → " + status : ""}${statusText ? " " + statusText : ""}`;
|
|
14322
|
-
}
|
|
14323
|
-
function pick(value, fallback) {
|
|
14324
|
-
if (!value)
|
|
14325
|
-
return;
|
|
14326
|
-
if (!fallback)
|
|
14327
|
-
return value;
|
|
14328
|
-
if (value === fallback)
|
|
14329
|
-
return fallback;
|
|
14330
|
-
if (value === encodeURIComponent(fallback))
|
|
14331
|
-
return fallback;
|
|
14332
|
-
return value;
|
|
14333
|
-
}
|
|
14334
|
-
function rewrite(request, directory) {
|
|
14335
|
-
if (request.method !== "GET" && request.method !== "HEAD")
|
|
14336
|
-
return request;
|
|
14337
|
-
const value = pick(request.headers.get("x-opencode-directory"), directory);
|
|
14338
|
-
if (!value)
|
|
14339
|
-
return request;
|
|
14340
|
-
const url = new URL(request.url);
|
|
14341
|
-
if (!url.searchParams.has("directory")) {
|
|
14342
|
-
url.searchParams.set("directory", value);
|
|
14343
|
-
}
|
|
14344
|
-
const next = new Request(url, request);
|
|
14345
|
-
next.headers.delete("x-opencode-directory");
|
|
14346
|
-
return next;
|
|
14347
|
-
}
|
|
14348
|
-
function createOpencodeClient(config2) {
|
|
14349
|
-
if (!config2?.fetch) {
|
|
14350
|
-
const customFetch = (req) => {
|
|
14351
|
-
req.timeout = false;
|
|
14352
|
-
return fetch(req);
|
|
14353
|
-
};
|
|
14354
|
-
config2 = {
|
|
14355
|
-
...config2,
|
|
14356
|
-
fetch: customFetch
|
|
14357
|
-
};
|
|
14358
|
-
}
|
|
14359
|
-
if (config2?.directory) {
|
|
14360
|
-
config2.headers = {
|
|
14361
|
-
...config2.headers,
|
|
14362
|
-
"x-opencode-directory": encodeURIComponent(config2.directory)
|
|
14363
|
-
};
|
|
14364
|
-
}
|
|
14365
|
-
const client2 = createClient(config2);
|
|
14366
|
-
client2.interceptors.request.use((request) => rewrite(request, config2?.directory));
|
|
14367
|
-
client2.interceptors.error.use(wrapClientError);
|
|
14368
|
-
return new OpencodeClient({ client: client2 });
|
|
14369
|
-
}
|
|
14370
|
-
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
14371
|
-
function getDefaultExportFromCjs(x) {
|
|
14372
|
-
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
14373
|
-
}
|
|
14374
|
-
var crossSpawn = { exports: {} };
|
|
14375
|
-
var windows;
|
|
14376
|
-
var hasRequiredWindows;
|
|
14377
|
-
function requireWindows() {
|
|
14378
|
-
if (hasRequiredWindows) return windows;
|
|
14379
|
-
hasRequiredWindows = 1;
|
|
14380
|
-
windows = isexe;
|
|
14381
|
-
isexe.sync = sync;
|
|
14382
|
-
var fs2 = require$$0;
|
|
14383
|
-
function checkPathExt(path2, options) {
|
|
14384
|
-
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
14385
|
-
if (!pathext) {
|
|
14386
|
-
return true;
|
|
14387
|
-
}
|
|
14388
|
-
pathext = pathext.split(";");
|
|
14389
|
-
if (pathext.indexOf("") !== -1) {
|
|
14390
|
-
return true;
|
|
14391
|
-
}
|
|
14392
|
-
for (var i2 = 0; i2 < pathext.length; i2++) {
|
|
14393
|
-
var p = pathext[i2].toLowerCase();
|
|
14394
|
-
if (p && path2.substr(-p.length).toLowerCase() === p) {
|
|
14395
|
-
return true;
|
|
14396
|
-
}
|
|
14397
|
-
}
|
|
14398
|
-
return false;
|
|
14399
|
-
}
|
|
14400
|
-
function checkStat(stat2, path2, options) {
|
|
14401
|
-
if (!stat2.isSymbolicLink() && !stat2.isFile()) {
|
|
14402
|
-
return false;
|
|
14403
|
-
}
|
|
14404
|
-
return checkPathExt(path2, options);
|
|
14405
|
-
}
|
|
14406
|
-
function isexe(path2, options, cb) {
|
|
14407
|
-
fs2.stat(path2, function(er, stat2) {
|
|
14408
|
-
cb(er, er ? false : checkStat(stat2, path2, options));
|
|
14409
|
-
});
|
|
14410
|
-
}
|
|
14411
|
-
function sync(path2, options) {
|
|
14412
|
-
return checkStat(fs2.statSync(path2), path2, options);
|
|
14413
|
-
}
|
|
14414
|
-
return windows;
|
|
14415
|
-
}
|
|
14416
|
-
var mode;
|
|
14417
|
-
var hasRequiredMode;
|
|
14418
|
-
function requireMode() {
|
|
14419
|
-
if (hasRequiredMode) return mode;
|
|
14420
|
-
hasRequiredMode = 1;
|
|
14421
|
-
mode = isexe;
|
|
14422
|
-
isexe.sync = sync;
|
|
14423
|
-
var fs2 = require$$0;
|
|
14424
|
-
function isexe(path2, options, cb) {
|
|
14425
|
-
fs2.stat(path2, function(er, stat2) {
|
|
14426
|
-
cb(er, er ? false : checkStat(stat2, options));
|
|
14427
|
-
});
|
|
14428
|
-
}
|
|
14429
|
-
function sync(path2, options) {
|
|
14430
|
-
return checkStat(fs2.statSync(path2), options);
|
|
14431
|
-
}
|
|
14432
|
-
function checkStat(stat2, options) {
|
|
14433
|
-
return stat2.isFile() && checkMode(stat2, options);
|
|
14434
|
-
}
|
|
14435
|
-
function checkMode(stat2, options) {
|
|
14436
|
-
var mod = stat2.mode;
|
|
14437
|
-
var uid = stat2.uid;
|
|
14438
|
-
var gid = stat2.gid;
|
|
14439
|
-
var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
|
|
14440
|
-
var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
|
|
14441
|
-
var u2 = parseInt("100", 8);
|
|
14442
|
-
var g = parseInt("010", 8);
|
|
14443
|
-
var o2 = parseInt("001", 8);
|
|
14444
|
-
var ug = u2 | g;
|
|
14445
|
-
var ret = mod & o2 || mod & g && gid === myGid || mod & u2 && uid === myUid || mod & ug && myUid === 0;
|
|
14446
|
-
return ret;
|
|
14447
|
-
}
|
|
14448
|
-
return mode;
|
|
14449
|
-
}
|
|
14450
|
-
var isexe_1;
|
|
14451
|
-
var hasRequiredIsexe;
|
|
14452
|
-
function requireIsexe() {
|
|
14453
|
-
if (hasRequiredIsexe) return isexe_1;
|
|
14454
|
-
hasRequiredIsexe = 1;
|
|
14455
|
-
var core;
|
|
14456
|
-
if (process.platform === "win32" || commonjsGlobal.TESTING_WINDOWS) {
|
|
14457
|
-
core = requireWindows();
|
|
14458
|
-
} else {
|
|
14459
|
-
core = requireMode();
|
|
14460
|
-
}
|
|
14461
|
-
isexe_1 = isexe;
|
|
14462
|
-
isexe.sync = sync;
|
|
14463
|
-
function isexe(path2, options, cb) {
|
|
14464
|
-
if (typeof options === "function") {
|
|
14465
|
-
cb = options;
|
|
14466
|
-
options = {};
|
|
14467
|
-
}
|
|
14468
|
-
if (!cb) {
|
|
14469
|
-
if (typeof Promise !== "function") {
|
|
14470
|
-
throw new TypeError("callback not provided");
|
|
14471
|
-
}
|
|
14472
|
-
return new Promise(function(resolve2, reject) {
|
|
14473
|
-
isexe(path2, options || {}, function(er, is) {
|
|
14474
|
-
if (er) {
|
|
14475
|
-
reject(er);
|
|
14476
|
-
} else {
|
|
14477
|
-
resolve2(is);
|
|
14478
|
-
}
|
|
14479
|
-
});
|
|
14480
|
-
});
|
|
14481
|
-
}
|
|
14482
|
-
core(path2, options || {}, function(er, is) {
|
|
14483
|
-
if (er) {
|
|
14484
|
-
if (er.code === "EACCES" || options && options.ignoreErrors) {
|
|
14485
|
-
er = null;
|
|
14486
|
-
is = false;
|
|
14487
|
-
}
|
|
14488
|
-
}
|
|
14489
|
-
cb(er, is);
|
|
14490
|
-
});
|
|
14491
|
-
}
|
|
14492
|
-
function sync(path2, options) {
|
|
14493
|
-
try {
|
|
14494
|
-
return core.sync(path2, options || {});
|
|
14495
|
-
} catch (er) {
|
|
14496
|
-
if (options && options.ignoreErrors || er.code === "EACCES") {
|
|
14497
|
-
return false;
|
|
14498
|
-
} else {
|
|
14499
|
-
throw er;
|
|
14500
|
-
}
|
|
14501
|
-
}
|
|
14502
|
-
}
|
|
14503
|
-
return isexe_1;
|
|
14504
|
-
}
|
|
14505
|
-
var which_1;
|
|
14506
|
-
var hasRequiredWhich;
|
|
14507
|
-
function requireWhich() {
|
|
14508
|
-
if (hasRequiredWhich) return which_1;
|
|
14509
|
-
hasRequiredWhich = 1;
|
|
14510
|
-
const isWindows2 = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
14511
|
-
const path2 = require$$0$1;
|
|
14512
|
-
const COLON = isWindows2 ? ";" : ":";
|
|
14513
|
-
const isexe = requireIsexe();
|
|
14514
|
-
const getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
14515
|
-
const getPathInfo = (cmd, opt) => {
|
|
14516
|
-
const colon = opt.colon || COLON;
|
|
14517
|
-
const pathEnv = cmd.match(/\//) || isWindows2 && cmd.match(/\\/) ? [""] : [
|
|
14518
|
-
// windows always checks the cwd first
|
|
14519
|
-
...isWindows2 ? [process.cwd()] : [],
|
|
14520
|
-
...(opt.path || process.env.PATH || /* istanbul ignore next: very unusual */
|
|
14521
|
-
"").split(colon)
|
|
14522
|
-
];
|
|
14523
|
-
const pathExtExe = isWindows2 ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
|
|
14524
|
-
const pathExt = isWindows2 ? pathExtExe.split(colon) : [""];
|
|
14525
|
-
if (isWindows2) {
|
|
14526
|
-
if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
|
|
14527
|
-
pathExt.unshift("");
|
|
14528
|
-
}
|
|
14529
|
-
return {
|
|
14530
|
-
pathEnv,
|
|
14531
|
-
pathExt,
|
|
14532
|
-
pathExtExe
|
|
14533
|
-
};
|
|
14534
|
-
};
|
|
14535
|
-
const which = (cmd, opt, cb) => {
|
|
14536
|
-
if (typeof opt === "function") {
|
|
14537
|
-
cb = opt;
|
|
14538
|
-
opt = {};
|
|
14539
|
-
}
|
|
14540
|
-
if (!opt)
|
|
14541
|
-
opt = {};
|
|
14542
|
-
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
14543
|
-
const found = [];
|
|
14544
|
-
const step = (i2) => new Promise((resolve2, reject) => {
|
|
14545
|
-
if (i2 === pathEnv.length)
|
|
14546
|
-
return opt.all && found.length ? resolve2(found) : reject(getNotFoundError(cmd));
|
|
14547
|
-
const ppRaw = pathEnv[i2];
|
|
14548
|
-
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
14549
|
-
const pCmd = path2.join(pathPart, cmd);
|
|
14550
|
-
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
14551
|
-
resolve2(subStep(p, i2, 0));
|
|
14552
|
-
});
|
|
14553
|
-
const subStep = (p, i2, ii) => new Promise((resolve2, reject) => {
|
|
14554
|
-
if (ii === pathExt.length)
|
|
14555
|
-
return resolve2(step(i2 + 1));
|
|
14556
|
-
const ext = pathExt[ii];
|
|
14557
|
-
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
|
14558
|
-
if (!er && is) {
|
|
14559
|
-
if (opt.all)
|
|
14560
|
-
found.push(p + ext);
|
|
14561
|
-
else
|
|
14562
|
-
return resolve2(p + ext);
|
|
14563
|
-
}
|
|
14564
|
-
return resolve2(subStep(p, i2, ii + 1));
|
|
14565
|
-
});
|
|
14566
|
-
});
|
|
14567
|
-
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
14568
|
-
};
|
|
14569
|
-
const whichSync = (cmd, opt) => {
|
|
14570
|
-
opt = opt || {};
|
|
14571
|
-
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
14572
|
-
const found = [];
|
|
14573
|
-
for (let i2 = 0; i2 < pathEnv.length; i2++) {
|
|
14574
|
-
const ppRaw = pathEnv[i2];
|
|
14575
|
-
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
14576
|
-
const pCmd = path2.join(pathPart, cmd);
|
|
14577
|
-
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
14578
|
-
for (let j = 0; j < pathExt.length; j++) {
|
|
14579
|
-
const cur = p + pathExt[j];
|
|
14580
|
-
try {
|
|
14581
|
-
const is = isexe.sync(cur, { pathExt: pathExtExe });
|
|
14582
|
-
if (is) {
|
|
14583
|
-
if (opt.all)
|
|
14584
|
-
found.push(cur);
|
|
14585
|
-
else
|
|
14586
|
-
return cur;
|
|
14587
|
-
}
|
|
14588
|
-
} catch (ex) {
|
|
14589
|
-
}
|
|
14590
|
-
}
|
|
14591
|
-
}
|
|
14592
|
-
if (opt.all && found.length)
|
|
14593
|
-
return found;
|
|
14594
|
-
if (opt.nothrow)
|
|
14595
|
-
return null;
|
|
14596
|
-
throw getNotFoundError(cmd);
|
|
14597
|
-
};
|
|
14598
|
-
which_1 = which;
|
|
14599
|
-
which.sync = whichSync;
|
|
14600
|
-
return which_1;
|
|
14601
|
-
}
|
|
14602
|
-
var pathKey$1 = { exports: {} };
|
|
14603
|
-
var hasRequiredPathKey;
|
|
14604
|
-
function requirePathKey() {
|
|
14605
|
-
if (hasRequiredPathKey) return pathKey$1.exports;
|
|
14606
|
-
hasRequiredPathKey = 1;
|
|
14607
|
-
const pathKey2 = (options = {}) => {
|
|
14608
|
-
const environment = options.env || process.env;
|
|
14609
|
-
const platform2 = options.platform || process.platform;
|
|
14610
|
-
if (platform2 !== "win32") {
|
|
14611
|
-
return "PATH";
|
|
14612
|
-
}
|
|
14613
|
-
return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
|
|
14614
|
-
};
|
|
14615
|
-
pathKey$1.exports = pathKey2;
|
|
14616
|
-
pathKey$1.exports.default = pathKey2;
|
|
14617
|
-
return pathKey$1.exports;
|
|
14618
|
-
}
|
|
14619
|
-
var resolveCommand_1;
|
|
14620
|
-
var hasRequiredResolveCommand;
|
|
14621
|
-
function requireResolveCommand() {
|
|
14622
|
-
if (hasRequiredResolveCommand) return resolveCommand_1;
|
|
14623
|
-
hasRequiredResolveCommand = 1;
|
|
14624
|
-
const path2 = require$$0$1;
|
|
14625
|
-
const which = requireWhich();
|
|
14626
|
-
const getPathKey = requirePathKey();
|
|
14627
|
-
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
14628
|
-
const env = parsed.options.env || process.env;
|
|
14629
|
-
const cwd = process.cwd();
|
|
14630
|
-
const hasCustomCwd = parsed.options.cwd != null;
|
|
14631
|
-
const shouldSwitchCwd = hasCustomCwd && process.chdir !== void 0 && !process.chdir.disabled;
|
|
14632
|
-
if (shouldSwitchCwd) {
|
|
14633
|
-
try {
|
|
14634
|
-
process.chdir(parsed.options.cwd);
|
|
14635
|
-
} catch (err) {
|
|
14636
|
-
}
|
|
14637
|
-
}
|
|
14638
|
-
let resolved;
|
|
14639
|
-
try {
|
|
14640
|
-
resolved = which.sync(parsed.command, {
|
|
14641
|
-
path: env[getPathKey({ env })],
|
|
14642
|
-
pathExt: withoutPathExt ? path2.delimiter : void 0
|
|
14643
|
-
});
|
|
14644
|
-
} catch (e) {
|
|
14645
|
-
} finally {
|
|
14646
|
-
if (shouldSwitchCwd) {
|
|
14647
|
-
process.chdir(cwd);
|
|
14648
|
-
}
|
|
14649
|
-
}
|
|
14650
|
-
if (resolved) {
|
|
14651
|
-
resolved = path2.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
|
|
14652
|
-
}
|
|
14653
|
-
return resolved;
|
|
14654
|
-
}
|
|
14655
|
-
function resolveCommand(parsed) {
|
|
14656
|
-
return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
|
|
14657
|
-
}
|
|
14658
|
-
resolveCommand_1 = resolveCommand;
|
|
14659
|
-
return resolveCommand_1;
|
|
14660
|
-
}
|
|
14661
|
-
var _escape = {};
|
|
14662
|
-
var hasRequired_escape;
|
|
14663
|
-
function require_escape() {
|
|
14664
|
-
if (hasRequired_escape) return _escape;
|
|
14665
|
-
hasRequired_escape = 1;
|
|
14666
|
-
const metaCharsRegExp2 = /([()\][%!^"`<>&|;, *?])/g;
|
|
14667
|
-
function escapeCommand(arg) {
|
|
14668
|
-
arg = arg.replace(metaCharsRegExp2, "^$1");
|
|
14669
|
-
return arg;
|
|
14670
|
-
}
|
|
14671
|
-
function escapeArgument2(arg, doubleEscapeMetaChars) {
|
|
14672
|
-
arg = `${arg}`;
|
|
14673
|
-
arg = arg.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
|
|
14674
|
-
arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
|
|
14675
|
-
arg = `"${arg}"`;
|
|
14676
|
-
arg = arg.replace(metaCharsRegExp2, "^$1");
|
|
14677
|
-
if (doubleEscapeMetaChars) {
|
|
14678
|
-
arg = arg.replace(metaCharsRegExp2, "^$1");
|
|
14679
|
-
}
|
|
14680
|
-
return arg;
|
|
14681
|
-
}
|
|
14682
|
-
_escape.command = escapeCommand;
|
|
14683
|
-
_escape.argument = escapeArgument2;
|
|
14684
|
-
return _escape;
|
|
14685
|
-
}
|
|
14686
|
-
var shebangRegex;
|
|
14687
|
-
var hasRequiredShebangRegex;
|
|
14688
|
-
function requireShebangRegex() {
|
|
14689
|
-
if (hasRequiredShebangRegex) return shebangRegex;
|
|
14690
|
-
hasRequiredShebangRegex = 1;
|
|
14691
|
-
shebangRegex = /^#!(.*)/;
|
|
14692
|
-
return shebangRegex;
|
|
14693
|
-
}
|
|
14694
|
-
var shebangCommand;
|
|
14695
|
-
var hasRequiredShebangCommand;
|
|
14696
|
-
function requireShebangCommand() {
|
|
14697
|
-
if (hasRequiredShebangCommand) return shebangCommand;
|
|
14698
|
-
hasRequiredShebangCommand = 1;
|
|
14699
|
-
const shebangRegex2 = requireShebangRegex();
|
|
14700
|
-
shebangCommand = (string2 = "") => {
|
|
14701
|
-
const match = string2.match(shebangRegex2);
|
|
14702
|
-
if (!match) {
|
|
14703
|
-
return null;
|
|
14704
|
-
}
|
|
14705
|
-
const [path2, argument] = match[0].replace(/#! ?/, "").split(" ");
|
|
14706
|
-
const binary = path2.split("/").pop();
|
|
14707
|
-
if (binary === "env") {
|
|
14708
|
-
return argument;
|
|
14709
|
-
}
|
|
14710
|
-
return argument ? `${binary} ${argument}` : binary;
|
|
14711
|
-
};
|
|
14712
|
-
return shebangCommand;
|
|
14713
|
-
}
|
|
14714
|
-
var readShebang_1;
|
|
14715
|
-
var hasRequiredReadShebang;
|
|
14716
|
-
function requireReadShebang() {
|
|
14717
|
-
if (hasRequiredReadShebang) return readShebang_1;
|
|
14718
|
-
hasRequiredReadShebang = 1;
|
|
14719
|
-
const fs2 = require$$0;
|
|
14720
|
-
const shebangCommand2 = requireShebangCommand();
|
|
14721
|
-
function readShebang2(command2) {
|
|
14722
|
-
const size = 150;
|
|
14723
|
-
const buffer = Buffer.alloc(size);
|
|
14724
|
-
let fd;
|
|
14725
|
-
try {
|
|
14726
|
-
fd = fs2.openSync(command2, "r");
|
|
14727
|
-
fs2.readSync(fd, buffer, 0, size, 0);
|
|
14728
|
-
fs2.closeSync(fd);
|
|
14729
|
-
} catch (e) {
|
|
14730
|
-
}
|
|
14731
|
-
return shebangCommand2(buffer.toString());
|
|
14732
|
-
}
|
|
14733
|
-
readShebang_1 = readShebang2;
|
|
14734
|
-
return readShebang_1;
|
|
14735
|
-
}
|
|
14736
|
-
var parse_1;
|
|
14737
|
-
var hasRequiredParse;
|
|
14738
|
-
function requireParse() {
|
|
14739
|
-
if (hasRequiredParse) return parse_1;
|
|
14740
|
-
hasRequiredParse = 1;
|
|
14741
|
-
const path2 = require$$0$1;
|
|
14742
|
-
const resolveCommand = requireResolveCommand();
|
|
14743
|
-
const escape = require_escape();
|
|
14744
|
-
const readShebang2 = requireReadShebang();
|
|
14745
|
-
const isWin = process.platform === "win32";
|
|
14746
|
-
const isExecutableRegExp = /\.(?:com|exe)$/i;
|
|
14747
|
-
const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
|
|
14748
|
-
function detectShebang(parsed) {
|
|
14749
|
-
parsed.file = resolveCommand(parsed);
|
|
14750
|
-
const shebang = parsed.file && readShebang2(parsed.file);
|
|
14751
|
-
if (shebang) {
|
|
14752
|
-
parsed.args.unshift(parsed.file);
|
|
14753
|
-
parsed.command = shebang;
|
|
14754
|
-
return resolveCommand(parsed);
|
|
14755
|
-
}
|
|
14756
|
-
return parsed.file;
|
|
14757
|
-
}
|
|
14758
|
-
function parseNonShell(parsed) {
|
|
14759
|
-
if (!isWin) {
|
|
14760
|
-
return parsed;
|
|
14761
|
-
}
|
|
14762
|
-
const commandFile = detectShebang(parsed);
|
|
14763
|
-
const needsShell = !isExecutableRegExp.test(commandFile);
|
|
14764
|
-
if (parsed.options.forceShell || needsShell) {
|
|
14765
|
-
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
14766
|
-
parsed.command = path2.normalize(parsed.command);
|
|
14767
|
-
parsed.command = escape.command(parsed.command);
|
|
14768
|
-
parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
|
|
14769
|
-
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
14770
|
-
parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
|
|
14771
|
-
parsed.command = process.env.comspec || "cmd.exe";
|
|
14772
|
-
parsed.options.windowsVerbatimArguments = true;
|
|
14773
|
-
}
|
|
14774
|
-
return parsed;
|
|
14775
|
-
}
|
|
14776
|
-
function parse2(command2, args, options) {
|
|
14777
|
-
if (args && !Array.isArray(args)) {
|
|
14778
|
-
options = args;
|
|
14779
|
-
args = null;
|
|
14780
|
-
}
|
|
14781
|
-
args = args ? args.slice(0) : [];
|
|
14782
|
-
options = Object.assign({}, options);
|
|
14783
|
-
const parsed = {
|
|
14784
|
-
command: command2,
|
|
14785
|
-
args,
|
|
14786
|
-
options,
|
|
14787
|
-
file: void 0,
|
|
14788
|
-
original: {
|
|
14789
|
-
command: command2,
|
|
14790
|
-
args
|
|
14791
|
-
}
|
|
14792
|
-
};
|
|
14793
|
-
return options.shell ? parsed : parseNonShell(parsed);
|
|
14794
|
-
}
|
|
14795
|
-
parse_1 = parse2;
|
|
14796
|
-
return parse_1;
|
|
14797
|
-
}
|
|
14798
|
-
var enoent;
|
|
14799
|
-
var hasRequiredEnoent;
|
|
14800
|
-
function requireEnoent() {
|
|
14801
|
-
if (hasRequiredEnoent) return enoent;
|
|
14802
|
-
hasRequiredEnoent = 1;
|
|
14803
|
-
const isWin = process.platform === "win32";
|
|
14804
|
-
function notFoundError(original, syscall) {
|
|
14805
|
-
return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
|
|
14806
|
-
code: "ENOENT",
|
|
14807
|
-
errno: "ENOENT",
|
|
14808
|
-
syscall: `${syscall} ${original.command}`,
|
|
14809
|
-
path: original.command,
|
|
14810
|
-
spawnargs: original.args
|
|
14811
|
-
});
|
|
14812
|
-
}
|
|
14813
|
-
function hookChildProcess(cp2, parsed) {
|
|
14814
|
-
if (!isWin) {
|
|
14815
|
-
return;
|
|
14816
|
-
}
|
|
14817
|
-
const originalEmit = cp2.emit;
|
|
14818
|
-
cp2.emit = function(name, arg1) {
|
|
14819
|
-
if (name === "exit") {
|
|
14820
|
-
const err = verifyENOENT(arg1, parsed);
|
|
14821
|
-
if (err) {
|
|
14822
|
-
return originalEmit.call(cp2, "error", err);
|
|
14823
|
-
}
|
|
14824
|
-
}
|
|
14825
|
-
return originalEmit.apply(cp2, arguments);
|
|
14826
|
-
};
|
|
14827
|
-
}
|
|
14828
|
-
function verifyENOENT(status, parsed) {
|
|
14829
|
-
if (isWin && status === 1 && !parsed.file) {
|
|
14830
|
-
return notFoundError(parsed.original, "spawn");
|
|
14831
|
-
}
|
|
14832
|
-
return null;
|
|
14833
|
-
}
|
|
14834
|
-
function verifyENOENTSync(status, parsed) {
|
|
14835
|
-
if (isWin && status === 1 && !parsed.file) {
|
|
14836
|
-
return notFoundError(parsed.original, "spawnSync");
|
|
14837
|
-
}
|
|
14838
|
-
return null;
|
|
14839
|
-
}
|
|
14840
|
-
enoent = {
|
|
14841
|
-
hookChildProcess,
|
|
14842
|
-
verifyENOENT,
|
|
14843
|
-
verifyENOENTSync,
|
|
14844
|
-
notFoundError
|
|
14845
|
-
};
|
|
14846
|
-
return enoent;
|
|
14847
|
-
}
|
|
14848
|
-
var hasRequiredCrossSpawn;
|
|
14849
|
-
function requireCrossSpawn() {
|
|
14850
|
-
if (hasRequiredCrossSpawn) return crossSpawn.exports;
|
|
14851
|
-
hasRequiredCrossSpawn = 1;
|
|
14852
|
-
const cp2 = require$$0$2;
|
|
14853
|
-
const parse2 = requireParse();
|
|
14854
|
-
const enoent2 = requireEnoent();
|
|
14855
|
-
function spawn2(command2, args, options) {
|
|
14856
|
-
const parsed = parse2(command2, args, options);
|
|
14857
|
-
const spawned = cp2.spawn(parsed.command, parsed.args, parsed.options);
|
|
14858
|
-
enoent2.hookChildProcess(spawned, parsed);
|
|
14859
|
-
return spawned;
|
|
14860
|
-
}
|
|
14861
|
-
function spawnSync2(command2, args, options) {
|
|
14862
|
-
const parsed = parse2(command2, args, options);
|
|
14863
|
-
const result = cp2.spawnSync(parsed.command, parsed.args, parsed.options);
|
|
14864
|
-
result.error = result.error || enoent2.verifyENOENTSync(result.status, parsed);
|
|
14865
|
-
return result;
|
|
14866
|
-
}
|
|
14867
|
-
crossSpawn.exports = spawn2;
|
|
14868
|
-
crossSpawn.exports.spawn = spawn2;
|
|
14869
|
-
crossSpawn.exports.sync = spawnSync2;
|
|
14870
|
-
crossSpawn.exports._parse = parse2;
|
|
14871
|
-
crossSpawn.exports._enoent = enoent2;
|
|
14872
|
-
return crossSpawn.exports;
|
|
14873
|
-
}
|
|
14874
|
-
var crossSpawnExports = requireCrossSpawn();
|
|
14875
|
-
const launch = /* @__PURE__ */ getDefaultExportFromCjs(crossSpawnExports);
|
|
14876
|
-
function stop(proc) {
|
|
14877
|
-
if (proc.exitCode !== null || proc.signalCode !== null)
|
|
14878
|
-
return;
|
|
14879
|
-
if (process.platform === "win32" && proc.pid) {
|
|
14880
|
-
const out = spawnSync("taskkill", ["/pid", String(proc.pid), "/T", "/F"], { windowsHide: true });
|
|
14881
|
-
if (!out.error && out.status === 0)
|
|
14882
|
-
return;
|
|
14883
|
-
}
|
|
14884
|
-
proc.kill();
|
|
14885
|
-
}
|
|
14886
|
-
function bindAbort$1(proc, signal, onAbort) {
|
|
14887
|
-
if (!signal)
|
|
14888
|
-
return () => {
|
|
14889
|
-
};
|
|
14890
|
-
const abort = () => {
|
|
14891
|
-
clear();
|
|
14892
|
-
stop(proc);
|
|
14893
|
-
onAbort?.();
|
|
14894
|
-
};
|
|
14895
|
-
const clear = () => {
|
|
14896
|
-
signal.removeEventListener("abort", abort);
|
|
14897
|
-
proc.off("exit", clear);
|
|
14898
|
-
proc.off("error", clear);
|
|
14899
|
-
};
|
|
14900
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
14901
|
-
proc.on("exit", clear);
|
|
14902
|
-
proc.on("error", clear);
|
|
14903
|
-
if (signal.aborted)
|
|
14904
|
-
abort();
|
|
14905
|
-
return clear;
|
|
14906
|
-
}
|
|
14907
|
-
async function createOpencodeServer(options) {
|
|
14908
|
-
options = Object.assign({
|
|
14909
|
-
hostname: "127.0.0.1",
|
|
14910
|
-
port: 4096,
|
|
14911
|
-
timeout: 5e3
|
|
14912
|
-
}, options ?? {});
|
|
14913
|
-
const args = [`serve`, `--hostname=${options.hostname}`, `--port=${options.port}`];
|
|
14914
|
-
if (options.config?.logLevel)
|
|
14915
|
-
args.push(`--log-level=${options.config.logLevel}`);
|
|
14916
|
-
const proc = launch(`opencode`, args, {
|
|
14917
|
-
env: {
|
|
14918
|
-
...process.env,
|
|
14919
|
-
OPENCODE_CONFIG_CONTENT: JSON.stringify(options.config ?? {})
|
|
14920
|
-
}
|
|
14921
|
-
});
|
|
14922
|
-
let clear = () => {
|
|
14923
|
-
};
|
|
14924
|
-
const url = await new Promise((resolve2, reject) => {
|
|
14925
|
-
const id = setTimeout(() => {
|
|
14926
|
-
clear();
|
|
14927
|
-
stop(proc);
|
|
14928
|
-
reject(new Error(`Timeout waiting for server to start after ${options.timeout}ms`));
|
|
14929
|
-
}, options.timeout);
|
|
14930
|
-
let output = "";
|
|
14931
|
-
let resolved = false;
|
|
14932
|
-
proc.stdout?.on("data", (chunk) => {
|
|
14933
|
-
if (resolved)
|
|
14934
|
-
return;
|
|
14935
|
-
output += chunk.toString();
|
|
14936
|
-
const lines = output.split("\n");
|
|
14937
|
-
for (const line of lines) {
|
|
14938
|
-
if (line.startsWith("opencode server listening")) {
|
|
14939
|
-
const match = line.match(/on\s+(https?:\/\/[^\s]+)/);
|
|
14940
|
-
if (!match) {
|
|
14941
|
-
clear();
|
|
14942
|
-
stop(proc);
|
|
14943
|
-
clearTimeout(id);
|
|
14944
|
-
reject(new Error(`Failed to parse server url from output: ${line}`));
|
|
14945
|
-
return;
|
|
14946
|
-
}
|
|
14947
|
-
clearTimeout(id);
|
|
14948
|
-
resolved = true;
|
|
14949
|
-
resolve2(match[1]);
|
|
14950
|
-
return;
|
|
14951
|
-
}
|
|
14952
|
-
}
|
|
14953
|
-
});
|
|
14954
|
-
proc.stderr?.on("data", (chunk) => {
|
|
14955
|
-
output += chunk.toString();
|
|
14956
|
-
});
|
|
14957
|
-
proc.on("exit", (code) => {
|
|
14958
|
-
clearTimeout(id);
|
|
14959
|
-
let msg = `Server exited with code ${code}`;
|
|
14960
|
-
if (output.trim()) {
|
|
14961
|
-
msg += `
|
|
14962
|
-
Server output: ${output}`;
|
|
14963
|
-
}
|
|
14964
|
-
reject(new Error(msg));
|
|
14965
|
-
});
|
|
14966
|
-
proc.on("error", (error) => {
|
|
14967
|
-
clearTimeout(id);
|
|
14968
|
-
reject(error);
|
|
14969
|
-
});
|
|
14970
|
-
clear = bindAbort$1(proc, options.signal, () => {
|
|
14971
|
-
clearTimeout(id);
|
|
14972
|
-
reject(options.signal?.reason);
|
|
14973
|
-
});
|
|
14974
|
-
});
|
|
14975
|
-
return {
|
|
14976
|
-
url,
|
|
14977
|
-
close() {
|
|
14978
|
-
clear();
|
|
14979
|
-
stop(proc);
|
|
14980
|
-
}
|
|
14981
|
-
};
|
|
14982
|
-
}
|
|
14983
|
-
function openCodeCliName(executable) {
|
|
14984
|
-
return path.parse(executable).name.toLowerCase() === "opencode2" ? "opencode2" : "opencode";
|
|
14985
|
-
}
|
|
14986
|
-
function isOpenCodeV2(executable) {
|
|
14987
|
-
return openCodeCliName(executable) === "opencode2";
|
|
14988
|
-
}
|
|
14989
|
-
function openCodeLoginCommand(cliName) {
|
|
14990
|
-
return cliName === "opencode2" ? "opencode2 auth login" : "opencode auth login";
|
|
14991
|
-
}
|
|
14992
|
-
function parseOpenCodeAuthList(raw, exitCode) {
|
|
14993
|
-
if (exitCode !== 0) return "unknown";
|
|
14994
|
-
const text2 = stripAnsi(raw);
|
|
14995
|
-
if (/no authenticated/i.test(text2)) return "unauthenticated";
|
|
14996
|
-
if (/credential/i.test(text2)) return "authenticated";
|
|
14997
|
-
const lines = text2.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
14998
|
-
if (lines.some((line) => /^[A-Za-z0-9._-]+$/.test(line) && !/^(providers?|credentials?|integrations?)$/i.test(line))) {
|
|
14999
|
-
return "authenticated";
|
|
15000
|
-
}
|
|
15001
|
-
return "unknown";
|
|
12978
|
+
return "unknown";
|
|
15002
12979
|
}
|
|
15003
12980
|
function parseOpenCodeModels(raw) {
|
|
15004
12981
|
const seen = /* @__PURE__ */ new Set();
|
|
15005
|
-
const models = stripAnsi(raw).split(/\r?\n/).map((line) => line.trim()).filter((line) => /^[A-Za-z0-9._-]+\/[A-Za-z0-9._:/-]
|
|
15006
|
-
return [DEFAULT_MODEL, ...models];
|
|
15007
|
-
}
|
|
15008
|
-
function parseOpenCodeV1Model(value) {
|
|
15009
|
-
const slash = value.indexOf("/");
|
|
15010
|
-
if (slash <= 0 || slash === value.length - 1) throw invalidModel();
|
|
15011
|
-
return { providerID: value.slice(0, slash), modelID: value.slice(slash + 1) };
|
|
12982
|
+
const models = stripAnsi(raw).split(/\r?\n/).map((line) => line.trim()).filter((line) => /^[A-Za-z0-9._-]+\/[A-Za-z0-9._:/-]+(?:#[A-Za-z0-9._-]+)?$/.test(line) && !seen.has(line) && seen.add(line)).map((id) => ({ id, label: id }));
|
|
12983
|
+
return [DEFAULT_MODEL$1, ...models];
|
|
15012
12984
|
}
|
|
15013
12985
|
function parseOpenCodeV2ModelRef(value) {
|
|
15014
|
-
const
|
|
15015
|
-
|
|
15016
|
-
|
|
15017
|
-
return { providerID: parsed.providerID, id: parsed.modelID.slice(0, hash), variant: parsed.modelID.slice(hash + 1) };
|
|
15018
|
-
}
|
|
15019
|
-
return { providerID: parsed.providerID, id: parsed.modelID };
|
|
12986
|
+
const match = /^([^/#\s]+)\/([^#\s]+)(?:#([^#\s]+))?$/.exec(value);
|
|
12987
|
+
if (!match?.[1] || !match[2]) throw invalidModel();
|
|
12988
|
+
return { providerID: match[1], id: match[2], ...match[3] ? { variant: match[3] } : {} };
|
|
15020
12989
|
}
|
|
15021
12990
|
function parseOpenCodeV2GenerateText(payload) {
|
|
15022
12991
|
if (!payload || typeof payload !== "object") throw invalidOutput$1();
|
|
@@ -15070,12 +13039,12 @@ async function startOpenCodeV2Server(options) {
|
|
|
15070
13039
|
});
|
|
15071
13040
|
void subprocess.catch(() => void 0);
|
|
15072
13041
|
let settled = false;
|
|
15073
|
-
const
|
|
13042
|
+
const stop = () => {
|
|
15074
13043
|
if (settled) return;
|
|
15075
13044
|
settled = true;
|
|
15076
13045
|
stopProcess(subprocess);
|
|
15077
13046
|
};
|
|
15078
|
-
const unbind = bindAbort(options.signal,
|
|
13047
|
+
const unbind = bindAbort(options.signal, stop);
|
|
15079
13048
|
try {
|
|
15080
13049
|
const url = await waitForListenUrl(subprocess, timeoutMs, options.signal);
|
|
15081
13050
|
return {
|
|
@@ -15083,12 +13052,12 @@ async function startOpenCodeV2Server(options) {
|
|
|
15083
13052
|
password,
|
|
15084
13053
|
close() {
|
|
15085
13054
|
unbind();
|
|
15086
|
-
|
|
13055
|
+
stop();
|
|
15087
13056
|
}
|
|
15088
13057
|
};
|
|
15089
13058
|
} catch (error) {
|
|
15090
13059
|
unbind();
|
|
15091
|
-
|
|
13060
|
+
stop();
|
|
15092
13061
|
if (options.signal?.aborted) {
|
|
15093
13062
|
throw new AiOperationError({ code: "AI_CANCELLED", operation: "opencode-server", harness: "opencode", message: "Generation canceled." });
|
|
15094
13063
|
}
|
|
@@ -15101,8 +13070,9 @@ async function generateOpenCodeV2Text(server, input) {
|
|
|
15101
13070
|
const created = await v2Request(server, "/api/session", {
|
|
15102
13071
|
method: "POST",
|
|
15103
13072
|
body: {
|
|
15104
|
-
title: "OpenTig
|
|
13073
|
+
title: "OpenTig text generation",
|
|
15105
13074
|
location: { directory: input.cwd },
|
|
13075
|
+
permissions: [{ action: "*", resource: "*", effect: "deny" }],
|
|
15106
13076
|
...model ? { model } : {}
|
|
15107
13077
|
},
|
|
15108
13078
|
signal
|
|
@@ -15155,7 +13125,7 @@ function throwIfV2Failed(status, payload, signal) {
|
|
|
15155
13125
|
if (status === 401 || /not logged|login required|unauth|authentication|sign in/.test(raw)) {
|
|
15156
13126
|
throw new AiOperationError({ code: "AI_AUTH_REQUIRED", operation: "opencode-generate", harness: "opencode", message: "Sign in to OpenCode to generate the message." });
|
|
15157
13127
|
}
|
|
15158
|
-
if (/rate.?limit|quota|usage limit|too many requests|credit/.test(raw)) {
|
|
13128
|
+
if (status === 429 || /rate.?limit|quota|usage limit|too many requests|credit/.test(raw)) {
|
|
15159
13129
|
throw new AiOperationError({ code: "AI_RATE_LIMITED", operation: "opencode-generate", harness: "opencode", message: "OpenCode rejected the request because of a usage limit.", retryable: true });
|
|
15160
13130
|
}
|
|
15161
13131
|
if (/model.*(not found|unavailable|invalid|access)|unknown model|no model specified/.test(raw)) {
|
|
@@ -15238,7 +13208,7 @@ function freePort() {
|
|
|
15238
13208
|
server.on("error", reject);
|
|
15239
13209
|
});
|
|
15240
13210
|
}
|
|
15241
|
-
const
|
|
13211
|
+
const UNSUPPORTED_MESSAGE = "OpenCode 2.x is required. Upgrade the installed CLI; OpenCode 1 and legacy beta builds are not supported.";
|
|
15242
13212
|
class OpenCodeProvider {
|
|
15243
13213
|
constructor(resolver, runner) {
|
|
15244
13214
|
this.resolver = resolver;
|
|
@@ -15250,18 +13220,17 @@ class OpenCodeProvider {
|
|
|
15250
13220
|
servers = /* @__PURE__ */ new Set();
|
|
15251
13221
|
async status(forceRefresh = false) {
|
|
15252
13222
|
const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
15253
|
-
const
|
|
15254
|
-
if (!
|
|
13223
|
+
const detected = await this.detect(forceRefresh);
|
|
13224
|
+
if (!detected) return { id: this.id, label: "OpenCode", availability: "error", installed: false, authStatus: "unknown", message: "Install OpenCode 2 to use this harness.", models: [DEFAULT_MODEL$1], checkedAt };
|
|
13225
|
+
const { executable, version: version2, compatible } = detected;
|
|
15255
13226
|
const cliName = openCodeCliName(executable);
|
|
15256
|
-
|
|
15257
|
-
const [
|
|
15258
|
-
this.runner.run(executable, ["--
|
|
15259
|
-
this.runner.run(executable, ["
|
|
15260
|
-
this.runner.run(executable, catalogArgs, cliName === "opencode2" ? { timeoutMs: 3e4 } : {})
|
|
13227
|
+
if (!compatible) return { id: this.id, label: "OpenCode", availability: "error", installed: true, authStatus: "unknown", message: UNSUPPORTED_MESSAGE, cliName, version: version2, models: [DEFAULT_MODEL$1], checkedAt };
|
|
13228
|
+
const [auth, catalog] = await Promise.all([
|
|
13229
|
+
this.runner.run(executable, ["auth", "list", "--format", "json", "--standalone"]),
|
|
13230
|
+
this.runner.run(executable, ["models", "--standalone"], { timeoutMs: 3e4 })
|
|
15261
13231
|
]);
|
|
15262
|
-
const models = catalog.exitCode === 0 ? parseOpenCodeModels(catalog.stdout) : [DEFAULT_MODEL];
|
|
15263
|
-
let authStatus = parseOpenCodeAuthList(
|
|
15264
|
-
${auth.stderr}`, auth.exitCode);
|
|
13232
|
+
const models = catalog.exitCode === 0 ? parseOpenCodeModels(catalog.stdout) : [DEFAULT_MODEL$1];
|
|
13233
|
+
let authStatus = parseOpenCodeAuthList(auth.stdout, auth.exitCode);
|
|
15265
13234
|
if (authStatus === "unauthenticated" && models.length > 1) authStatus = "unknown";
|
|
15266
13235
|
const confirmed = authStatus === "authenticated";
|
|
15267
13236
|
return {
|
|
@@ -15271,19 +13240,21 @@ ${auth.stderr}`, auth.exitCode);
|
|
|
15271
13240
|
installed: true,
|
|
15272
13241
|
authStatus,
|
|
15273
13242
|
cliName,
|
|
15274
|
-
version: version2
|
|
13243
|
+
version: version2,
|
|
15275
13244
|
models,
|
|
15276
13245
|
checkedAt,
|
|
15277
13246
|
...authStatus === "unauthenticated" ? { message: `Run ${openCodeLoginCommand(cliName)}.` } : !confirmed ? { message: "Could not confirm authentication for the selected provider." } : {}
|
|
15278
13247
|
};
|
|
15279
13248
|
}
|
|
15280
13249
|
async generate(input) {
|
|
15281
|
-
const
|
|
15282
|
-
if (!
|
|
13250
|
+
const detected = await this.detect(false, input.signal);
|
|
13251
|
+
if (!detected) throw new AiOperationError({ code: "AI_CLI_NOT_FOUND", operation: "opencode-generate", harness: this.id, message: "OpenCode is not installed." });
|
|
13252
|
+
if (!detected.compatible) throw new AiOperationError({ code: "AI_PROCESS_FAILED", operation: "opencode-generate", harness: this.id, message: UNSUPPORTED_MESSAGE });
|
|
13253
|
+
const executable = detected.executable;
|
|
15283
13254
|
const timeoutSignal = AbortSignal.timeout(AI_PROVIDER_TIMEOUT_MS);
|
|
15284
13255
|
const boundedInput = { ...input, signal: AbortSignal.any([input.signal, timeoutSignal]) };
|
|
15285
13256
|
try {
|
|
15286
|
-
return await
|
|
13257
|
+
return await this.generateV2(executable, boundedInput);
|
|
15287
13258
|
} catch (error) {
|
|
15288
13259
|
if (timeoutSignal.aborted && !input.signal.aborted) {
|
|
15289
13260
|
throw new AiOperationError({ code: "AI_TIMEOUT", operation: "opencode-generate", harness: this.id, message: "Generation took too long.", retryable: true });
|
|
@@ -15298,7 +13269,10 @@ ${auth.stderr}`, auth.exitCode);
|
|
|
15298
13269
|
});
|
|
15299
13270
|
this.servers.add(server);
|
|
15300
13271
|
try {
|
|
15301
|
-
const text2 = await generateOpenCodeV2Text(server, { prompt:
|
|
13272
|
+
const text2 = await generateOpenCodeV2Text(server, { prompt: `Reply with a single JSON object satisfying this JSON Schema:
|
|
13273
|
+
${JSON.stringify(input.schema)}
|
|
13274
|
+
|
|
13275
|
+
${input.prompt}`, model: input.model, cwd: input.repositoryPath, signal: input.signal });
|
|
15302
13276
|
return { output: parseJsonPayload(text2), usage: { ...EMPTY_AI_USAGE } };
|
|
15303
13277
|
} catch (error) {
|
|
15304
13278
|
if (input.signal.aborted) throw new AiOperationError({ code: "AI_CANCELLED", operation: "opencode-generate", harness: this.id, message: "Generation canceled." });
|
|
@@ -15311,53 +13285,22 @@ ${auth.stderr}`, auth.exitCode);
|
|
|
15311
13285
|
this.servers.delete(server);
|
|
15312
13286
|
}
|
|
15313
13287
|
}
|
|
15314
|
-
async
|
|
15315
|
-
const
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
|
|
15326
|
-
|
|
15327
|
-
|
|
15328
|
-
const created = await client2.session.create({ body: { title: "OpenTig commit message" }, query: { directory: input.repositoryPath } });
|
|
15329
|
-
if (!created.data?.id) throw new Error("missing session");
|
|
15330
|
-
sessionId = created.data.id;
|
|
15331
|
-
const model = input.model === "default" ? void 0 : parseOpenCodeV1Model(input.model);
|
|
15332
|
-
const response = await client2.session.prompt({
|
|
15333
|
-
path: { id: sessionId },
|
|
15334
|
-
query: { directory: input.repositoryPath },
|
|
15335
|
-
body: {
|
|
15336
|
-
parts: [{ type: "text", text: input.prompt }],
|
|
15337
|
-
tools: DISABLED_TOOLS,
|
|
15338
|
-
// The server API takes no schema, unlike the Codex and Claude CLIs, so
|
|
15339
|
-
// the only way to hold this harness to the contract is the system
|
|
15340
|
-
// prompt. Without it the model answers in whatever shape it likes.
|
|
15341
|
-
system: `Reply with a single JSON object and nothing else. It must satisfy this JSON Schema:
|
|
15342
|
-
${JSON.stringify(input.schema)}`,
|
|
15343
|
-
...model ? { model } : {}
|
|
15344
|
-
}
|
|
15345
|
-
});
|
|
15346
|
-
const infoError = response.data?.info && "error" in response.data.info ? response.data.info.error : void 0;
|
|
15347
|
-
if (infoError) throw new Error("provider rejected request");
|
|
15348
|
-
const text2 = (response.data?.parts ?? []).filter((part) => part.type === "text" && "text" in part && typeof part.text === "string").map((part) => part.text).join("").trim();
|
|
15349
|
-
return { output: parseJsonPayload(text2), usage: openCodeUsage(response.data?.info) };
|
|
15350
|
-
} catch (error) {
|
|
15351
|
-
if (input.signal?.aborted) throw new AiOperationError({ code: "AI_CANCELLED", operation: "opencode-generate", harness: this.id, message: "Generation canceled." });
|
|
15352
|
-
if (error instanceof AiOperationError) throw error;
|
|
15353
|
-
const synthetic = { exitCode: 1, stdout: "", stderr: error instanceof Error ? error.message : "" };
|
|
15354
|
-
requireSuccess(synthetic, this.id, "opencode-generate");
|
|
15355
|
-
throw error;
|
|
15356
|
-
} finally {
|
|
15357
|
-
if (sessionId) await client2.session.delete({ path: { id: sessionId }, query: { directory: input.repositoryPath } }).catch(() => void 0);
|
|
15358
|
-
server.close();
|
|
15359
|
-
this.servers.delete(server);
|
|
13288
|
+
async detect(forceRefresh = false, signal) {
|
|
13289
|
+
const candidates = await this.resolver.resolveAll("opencode", forceRefresh);
|
|
13290
|
+
let first = null;
|
|
13291
|
+
for (const executable of candidates) {
|
|
13292
|
+
try {
|
|
13293
|
+
const result = await this.runner.run(executable, ["--version"], signal ? { signal } : {});
|
|
13294
|
+
const version2 = result.stdout.trim() || result.stderr.trim();
|
|
13295
|
+
const detected = { executable, version: version2, compatible: result.exitCode === 0 && isOpenCodeV2Version(version2) };
|
|
13296
|
+
if (detected.compatible) return detected;
|
|
13297
|
+
first ??= detected;
|
|
13298
|
+
} catch (error) {
|
|
13299
|
+
if (signal?.aborted) throw error;
|
|
13300
|
+
first ??= { executable, version: "", compatible: false };
|
|
13301
|
+
}
|
|
15360
13302
|
}
|
|
13303
|
+
return first;
|
|
15361
13304
|
}
|
|
15362
13305
|
close() {
|
|
15363
13306
|
for (const server of this.servers) server.close();
|
|
@@ -19319,7 +17262,7 @@ const defaults = {
|
|
|
19319
17262
|
uiFont: "plus-jakarta-sans",
|
|
19320
17263
|
monoFont: "jetbrains-mono",
|
|
19321
17264
|
commitMessageHarness: "codex",
|
|
19322
|
-
commitMessageModels: { codex: "default", claude: "default", opencode: "default" },
|
|
17265
|
+
commitMessageModels: { codex: "default", claude: "default", opencode: "default", grok: "default" },
|
|
19323
17266
|
shortcutOverrides: {},
|
|
19324
17267
|
doubleControlShortcutEnabled: true,
|
|
19325
17268
|
remoteFetchIntervalSeconds: DEFAULT_REMOTE_FETCH_INTERVAL_SECONDS
|
|
@@ -19726,7 +17669,7 @@ function projectError(message) {
|
|
|
19726
17669
|
return new GitOperationError({ code: "INVALID_ARGUMENT", operation: "repository-projects", message });
|
|
19727
17670
|
}
|
|
19728
17671
|
function isHarness(value) {
|
|
19729
|
-
return value === "codex" || value === "claude" || value === "opencode";
|
|
17672
|
+
return value === "codex" || value === "claude" || value === "opencode" || value === "grok";
|
|
19730
17673
|
}
|
|
19731
17674
|
function normalizeUiFont(value) {
|
|
19732
17675
|
if (value === "cabinet-grotesk" || value === "satoshi") return "plus-jakarta-sans";
|
|
@@ -19741,9 +17684,9 @@ function normalizeSidebarWidth(value) {
|
|
|
19741
17684
|
return Math.max(300, Math.min(680, width));
|
|
19742
17685
|
}
|
|
19743
17686
|
function modelPreferences(value) {
|
|
19744
|
-
const result = { codex: "default", claude: "default", opencode: "default" };
|
|
17687
|
+
const result = { codex: "default", claude: "default", opencode: "default", grok: "default" };
|
|
19745
17688
|
if (!value || typeof value !== "object") return result;
|
|
19746
|
-
for (const harness of ["codex", "claude", "opencode"]) {
|
|
17689
|
+
for (const harness of ["codex", "claude", "opencode", "grok"]) {
|
|
19747
17690
|
const model = value[harness];
|
|
19748
17691
|
if (typeof model === "string" && model.length > 0 && model.length <= 200 && !hasControlCharacters$1(model)) result[harness] = model;
|
|
19749
17692
|
}
|
|
@@ -19886,7 +17829,8 @@ async function createOpenTigRuntime(options) {
|
|
|
19886
17829
|
const providers = [
|
|
19887
17830
|
new CodexProvider(cliResolver, cliRunner),
|
|
19888
17831
|
new ClaudeProvider(cliResolver, cliRunner),
|
|
19889
|
-
new OpenCodeProvider(cliResolver, cliRunner)
|
|
17832
|
+
new OpenCodeProvider(cliResolver, cliRunner),
|
|
17833
|
+
new GrokProvider(cliResolver, cliRunner)
|
|
19890
17834
|
];
|
|
19891
17835
|
const aiLog = new AiLogStore(options.aiLogPath);
|
|
19892
17836
|
await aiLog.load();
|
|
@@ -20408,7 +18352,7 @@ const searchOptionsSchema = object({
|
|
|
20408
18352
|
includeIgnored: unknown().optional()
|
|
20409
18353
|
});
|
|
20410
18354
|
const openFileTabSchema = object({ path: unknown(), pinned: boolean() });
|
|
20411
|
-
const aiHarnessSchema = _enum(["codex", "claude", "opencode"]);
|
|
18355
|
+
const aiHarnessSchema = _enum(["codex", "claude", "opencode", "grok"]);
|
|
20412
18356
|
const pullRequestStateSchema = _enum(["OPEN", "CLOSED", "MERGED"]);
|
|
20413
18357
|
function stringArg(value, operation, maxLength = 32768) {
|
|
20414
18358
|
const parsed = boundedStringSchema(maxLength, { controls: false }).safeParse(value);
|
|
@@ -22098,12 +20042,12 @@ class OpenTigWebSocketTransport {
|
|
|
22098
20042
|
upgradeHandler;
|
|
22099
20043
|
closePromise = null;
|
|
22100
20044
|
get connectedSessionCount() {
|
|
22101
|
-
return new Set([...this.clients.values()].map((
|
|
20045
|
+
return new Set([...this.clients.values()].map((client) => client.sessionId)).size;
|
|
22102
20046
|
}
|
|
22103
20047
|
connectionCount(sessionId) {
|
|
22104
20048
|
let count2 = 0;
|
|
22105
|
-
for (const
|
|
22106
|
-
if (
|
|
20049
|
+
for (const client of this.clients.values()) {
|
|
20050
|
+
if (client.sessionId === sessionId) count2 += 1;
|
|
22107
20051
|
}
|
|
22108
20052
|
return count2;
|
|
22109
20053
|
}
|
|
@@ -22149,7 +20093,7 @@ class OpenTigWebSocketTransport {
|
|
|
22149
20093
|
socket.on("close", () => {
|
|
22150
20094
|
for (const controller of state.requests.values()) controller.abort();
|
|
22151
20095
|
this.clients.delete(socket);
|
|
22152
|
-
if (![...this.clients.values()].some((
|
|
20096
|
+
if (![...this.clients.values()].some((client) => client.sessionId === sessionId)) {
|
|
22153
20097
|
this.options.registry.clearSession(sessionId);
|
|
22154
20098
|
}
|
|
22155
20099
|
});
|