@ycodium-ai/agent-grok 0.2.2106 → 0.2.2126
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/index.js +654 -187
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9,15 +9,18 @@ import { definePlugin } from "@ycodium-ai/plugin-api";
|
|
|
9
9
|
|
|
10
10
|
// src/card.ts
|
|
11
11
|
var GROK_DRIVER_KIND = "grok";
|
|
12
|
+
var GROK_CLIENT_INFO = { name: "ycodium-agent-grok", version: "0.1.0" };
|
|
12
13
|
var GROK_CARD = {
|
|
13
14
|
driverKind: GROK_DRIVER_KIND,
|
|
14
15
|
displayName: "Grok",
|
|
15
16
|
iconUrl: "./assets/icon.svg",
|
|
16
17
|
commandName: "grok",
|
|
17
18
|
// 启动命令是 `grok agent stdio`(GrokSettings 磁盘形状没有 launchArgs 字段,
|
|
18
|
-
// 宿主旧实现把它写死在 buildGrokAcpSpawnInput
|
|
19
|
-
//
|
|
20
|
-
//
|
|
19
|
+
// 宿主旧实现把它写死在 buildGrokAcpSpawnInput,这里落在名片上)。两个动态旗标
|
|
20
|
+
// 都不走名片这一栏,而且**位置不同**:思考档位 `--reasoning-effort` 是 agent 级、
|
|
21
|
+
// 插在 agent 与 stdio 之间;运行模式 `--permission-mode` 是顶层、排在 `agent`
|
|
22
|
+
// 前面(放进 agent 那一段 grok 当场报 unexpected argument)。两者都在
|
|
23
|
+
// `grokInstance.startSession` 里按用户选择拼。
|
|
21
24
|
launchArgs: "agent stdio",
|
|
22
25
|
homeEnvVar: "GROK_HOME",
|
|
23
26
|
// 只有这一条是实话:实测这个 CLI 从不播报 api key 认证方式,点名 XAI_API_KEY
|
|
@@ -33,7 +36,7 @@ var GROK_CARD = {
|
|
|
33
36
|
signIn: [{ kind: "command", command: "grok login" }],
|
|
34
37
|
deviceCodeSignInArgs: ["login", "--device-auth"],
|
|
35
38
|
// npm 上的 `@xai-official/grok` 只发 darwin-arm64,写出去等于给 Linux/Windows
|
|
36
|
-
//
|
|
39
|
+
// 用户一条装不上的路。
|
|
37
40
|
npmPackage: "",
|
|
38
41
|
homebrewFormula: "",
|
|
39
42
|
selfUpdateArgs: ["update"],
|
|
@@ -57,7 +60,16 @@ var GROK_CARD = {
|
|
|
57
60
|
// Grok 换模型只有 `session/set_config_option` 一条路;库会按握手形状自动协商,
|
|
58
61
|
// 但插件侧的执行路径还没接到模型管理 UI,名片必须说实话。
|
|
59
62
|
sessionModelSwitch: "unsupported",
|
|
60
|
-
|
|
63
|
+
// 运行模式只在 spawn 时定得了(`--permission-mode` 是启动旗标,ACP 那一侧
|
|
64
|
+
// `modes: null`,`session/set_mode` 对它无效),所以不许声称能会话中途换。
|
|
65
|
+
// 报 next-turn 之后宿主 `ProviderCommandReactor` 不再下发,而是把新档记在
|
|
66
|
+
// thread 上;下一轮 `ensureSessionForThread` 判到 runtimeModeChanged,带着
|
|
67
|
+
// resume cursor 真重开会话——历史续上,档位换掉。
|
|
68
|
+
runtimeModeSwitch: "next-turn",
|
|
69
|
+
// 档位走 spawn 旗标,切档要重开会话(与 runtimeModeSwitch 同为 next-turn 的原因)。
|
|
70
|
+
// 声明这一位让界面画这双手自报的三档;不声明就退回宿主四档,而四档在这只手上
|
|
71
|
+
// 有两档撞车(都落到 `auto`)。
|
|
72
|
+
nativeModeSwitch: true
|
|
61
73
|
},
|
|
62
74
|
// 凭据由 CLI 自己保管在 `<GROK_HOME>/auth.json`,宿主读它只认 `/token`。
|
|
63
75
|
credentialSources: [
|
|
@@ -84,11 +96,17 @@ var GROK_CARD = {
|
|
|
84
96
|
modelConnectivity: {
|
|
85
97
|
dialects: ["anthropic-messages", "openai-responses", "openai-chat-completions"],
|
|
86
98
|
acceptsExternalEndpoints: true,
|
|
87
|
-
//
|
|
99
|
+
// 地址那一栏必须投:不设 `GROK_MODELS_BASE_URL` 的话整条请求根本不来我们这儿
|
|
100
|
+
// (`grokModelProxyEgress.test.ts` 拿掉这一栏就红)。
|
|
101
|
+
//
|
|
102
|
+
// **但设了 base 并不会把客户端切成 API-key 认证。** 它的凭据顺序是
|
|
88
103
|
// `api_key` → `env_key` → **已登录的 session token** → `XAI_API_KEY`
|
|
89
|
-
// (`~/.grok/docs/user-guide/11-custom-models.md
|
|
90
|
-
//
|
|
91
|
-
//
|
|
104
|
+
// (`~/.grok/docs/user-guide/11-custom-models.md` 的 "Credential Resolution")。
|
|
105
|
+
// 1.0.34 实测:账号目录里有 `auth.json` 时,启动预取 `/v1/models` 用的是
|
|
106
|
+
// `XAI_API_KEY`,而**推理请求带的是用户自己的 x.ai OIDC token**——本地端点只认
|
|
107
|
+
// 这笔绑定的凭据,别的一律 401。所以绑定时还要把 `GROK_AUTH_PATH` 指到一个不存在
|
|
108
|
+
// 的路径(见下面那栏),让这次进程读不到那份登录。同批的实测落在
|
|
109
|
+
// `grokModelProxyEgress.test.ts`。
|
|
92
110
|
//
|
|
93
111
|
// 它启动时先打 `{base_url}/models` 拉模型列表(README:1953「on startup」),不给就
|
|
94
112
|
// 当端点不可用——代理为此支持了 /models。
|
|
@@ -96,13 +114,26 @@ var GROK_CARD = {
|
|
|
96
114
|
// base 含 /v1(它的例子是 `https://api.acme.com/v1`),后面自己加 /chat/completions。
|
|
97
115
|
nativePathSuffix: "/chat/completions",
|
|
98
116
|
baseUrlEnvKey: "GROK_MODELS_BASE_URL",
|
|
99
|
-
credentialEnvKey: "XAI_API_KEY"
|
|
117
|
+
credentialEnvKey: "XAI_API_KEY",
|
|
118
|
+
// 绑定这一轮不准用它自己的登录:凭据顺序里 session token 排在 `XAI_API_KEY`
|
|
119
|
+
// 前面,账号目录里有 `auth.json` 就一定发那一份,本机端点一律 401。
|
|
120
|
+
// `GROK_AUTH_PATH` 是 CLI 读登录文件的路径(1.0.34 的 argv 里与 `GROK_AUTH`、
|
|
121
|
+
// `GROK_DEPLOYMENT_KEY` 并列在同一张敏感变量表上)。`$absentPath` 是宿主按这次
|
|
122
|
+
// 绑定算的、必定不存在的路径——不用空设备是因为那是平台语义(POSIX `/dev/null`
|
|
123
|
+
// 对 Windows `NUL`),而「读不到」两边只有一种行为。1.0.34 实测:`authMethods`
|
|
124
|
+
// 少掉 `cached_token`、两笔请求(推理与标题)都改带绑定凭据,账号目录里那份
|
|
125
|
+
// `auth.json` 一个字节没动,也没在别处新建文件。
|
|
126
|
+
// 只在绑定时注入,非绑定会话照旧用用户自己的登录。
|
|
127
|
+
extraEnv: [{ name: "GROK_AUTH_PATH", value: "$absentPath" }]
|
|
100
128
|
}
|
|
101
129
|
};
|
|
102
130
|
|
|
103
131
|
// src/grokInstance.ts
|
|
132
|
+
import * as NodeCrypto2 from "node:crypto";
|
|
104
133
|
import * as NodeOS from "node:os";
|
|
105
134
|
import * as NodePath2 from "node:path";
|
|
135
|
+
import { mergeLaunchEnv, brainSlotEnvKeys } from "@ycodium-ai/plugin-api/executor";
|
|
136
|
+
import { nodeStreamsFromHandle as nodeStreamsFromHandle2 } from "@ycodium-ai/plugin-api/process-stdin";
|
|
106
137
|
|
|
107
138
|
// ../../packages/ycodium-acp-executor/src/executor.ts
|
|
108
139
|
import * as NodeCrypto from "node:crypto";
|
|
@@ -23972,6 +24003,12 @@ function acpApprovalOptions(request) {
|
|
|
23972
24003
|
}
|
|
23973
24004
|
return options;
|
|
23974
24005
|
}
|
|
24006
|
+
function selectAutoApprovedAcpPermissionOption(request) {
|
|
24007
|
+
if (new Set(request.options.map((option) => option.kind)).size !== request.options.length) {
|
|
24008
|
+
return void 0;
|
|
24009
|
+
}
|
|
24010
|
+
return selectAcpPermissionOptionId(request, "acceptForSession") ?? selectAcpPermissionOptionId(request, "accept");
|
|
24011
|
+
}
|
|
23975
24012
|
function parseAcpResumeCursor(raw, schemaVersion) {
|
|
23976
24013
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
|
|
23977
24014
|
const record2 = raw;
|
|
@@ -24365,6 +24402,150 @@ function makeAcpContentDeltaEvent(input2) {
|
|
|
24365
24402
|
};
|
|
24366
24403
|
}
|
|
24367
24404
|
|
|
24405
|
+
// ../../packages/ycodium-acp-executor/src/config-options.ts
|
|
24406
|
+
function isRecord3(value) {
|
|
24407
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24408
|
+
}
|
|
24409
|
+
function asString(value) {
|
|
24410
|
+
return typeof value === "string" ? value : void 0;
|
|
24411
|
+
}
|
|
24412
|
+
function normalizedField(option, key) {
|
|
24413
|
+
return asString(option[key])?.trim().toLowerCase() ?? "";
|
|
24414
|
+
}
|
|
24415
|
+
function looksLikeEffortOption(option) {
|
|
24416
|
+
const id = normalizedField(option, "id");
|
|
24417
|
+
const name = normalizedField(option, "name");
|
|
24418
|
+
return id === "effort" || id === "reasoning" || name === "effort" || name === "reasoning" || name.includes("effort") || name.includes("reasoning") || normalizedField(option, "category") === "thought_level";
|
|
24419
|
+
}
|
|
24420
|
+
function flattenChoices(rawOptions, currentValue) {
|
|
24421
|
+
if (!Array.isArray(rawOptions)) return [];
|
|
24422
|
+
const out = [];
|
|
24423
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24424
|
+
const push = (entry) => {
|
|
24425
|
+
if (!isRecord3(entry)) return;
|
|
24426
|
+
const value = asString(entry["value"]);
|
|
24427
|
+
if (value === void 0 || seen.has(value)) return;
|
|
24428
|
+
seen.add(value);
|
|
24429
|
+
const description = asString(entry["description"])?.trim();
|
|
24430
|
+
const name = asString(entry["name"])?.trim();
|
|
24431
|
+
out.push({
|
|
24432
|
+
value,
|
|
24433
|
+
...name ? { name } : {},
|
|
24434
|
+
label: name || value,
|
|
24435
|
+
...description ? { description } : {},
|
|
24436
|
+
...currentValue !== void 0 && currentValue === value ? { isDefault: true } : {}
|
|
24437
|
+
});
|
|
24438
|
+
};
|
|
24439
|
+
for (const entry of rawOptions) {
|
|
24440
|
+
if (isRecord3(entry) && Array.isArray(entry["options"])) {
|
|
24441
|
+
for (const nested of entry["options"]) push(nested);
|
|
24442
|
+
continue;
|
|
24443
|
+
}
|
|
24444
|
+
push(entry);
|
|
24445
|
+
}
|
|
24446
|
+
return out;
|
|
24447
|
+
}
|
|
24448
|
+
function findAcpEffortConfig(configOptions) {
|
|
24449
|
+
if (!Array.isArray(configOptions)) return void 0;
|
|
24450
|
+
const candidates = configOptions.filter(isRecord3).filter((option) => normalizedField(option, "type") === "select").filter(looksLikeEffortOption);
|
|
24451
|
+
if (candidates.length === 0) return void 0;
|
|
24452
|
+
const picked = candidates.find((option) => normalizedField(option, "category") === "model_option") ?? candidates.find((option) => normalizedField(option, "id") === "effort") ?? candidates.find((option) => normalizedField(option, "category") === "thought_level") ?? candidates[0];
|
|
24453
|
+
if (picked === void 0) return void 0;
|
|
24454
|
+
const configId = asString(picked["id"])?.trim();
|
|
24455
|
+
if (!configId) return void 0;
|
|
24456
|
+
const choices = flattenChoices(picked["options"], asString(picked["currentValue"])?.trim());
|
|
24457
|
+
if (choices.length === 0) return void 0;
|
|
24458
|
+
return {
|
|
24459
|
+
configId,
|
|
24460
|
+
label: asString(picked["name"])?.trim() ?? "",
|
|
24461
|
+
choices
|
|
24462
|
+
};
|
|
24463
|
+
}
|
|
24464
|
+
|
|
24465
|
+
// ../../packages/ycodium-acp-executor/src/runtime-mode.ts
|
|
24466
|
+
function isRecord4(value) {
|
|
24467
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24468
|
+
}
|
|
24469
|
+
function asString2(value) {
|
|
24470
|
+
return typeof value === "string" ? value : void 0;
|
|
24471
|
+
}
|
|
24472
|
+
function acpModeConfigId(setup) {
|
|
24473
|
+
if (!isRecord4(setup)) return void 0;
|
|
24474
|
+
const configOptions = setup["configOptions"];
|
|
24475
|
+
if (!Array.isArray(configOptions)) return void 0;
|
|
24476
|
+
for (const option of configOptions) {
|
|
24477
|
+
if (!isRecord4(option)) continue;
|
|
24478
|
+
if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
|
|
24479
|
+
const id = asString2(option["id"])?.trim();
|
|
24480
|
+
if (id) return id;
|
|
24481
|
+
}
|
|
24482
|
+
return void 0;
|
|
24483
|
+
}
|
|
24484
|
+
|
|
24485
|
+
// ../../packages/ycodium-acp-executor/src/handshake.ts
|
|
24486
|
+
function acpInitializePayload(clientInfo, overrides) {
|
|
24487
|
+
return {
|
|
24488
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
24489
|
+
clientCapabilities: {
|
|
24490
|
+
fs: {
|
|
24491
|
+
readTextFile: false,
|
|
24492
|
+
writeTextFile: false,
|
|
24493
|
+
...overrides?.fs
|
|
24494
|
+
},
|
|
24495
|
+
terminal: overrides?.terminal ?? false
|
|
24496
|
+
},
|
|
24497
|
+
clientInfo
|
|
24498
|
+
};
|
|
24499
|
+
}
|
|
24500
|
+
|
|
24501
|
+
// ../../packages/ycodium-acp-executor/src/config-option-wiring.ts
|
|
24502
|
+
var VENDOR_CATEGORY_PREFIX = "_";
|
|
24503
|
+
var ACP_CONFIG_CATEGORY_HANDLING = {
|
|
24504
|
+
mode: {
|
|
24505
|
+
consumed: true,
|
|
24506
|
+
via: "runtime-mode.ts\uFF1AacpAvailableModes / acpCurrentModeId / acpModeConfigId"
|
|
24507
|
+
},
|
|
24508
|
+
model: {
|
|
24509
|
+
consumed: true,
|
|
24510
|
+
via: "runtime-model.ts:extractModelConfigId \u2192 executor.ts:applyRequestedModel"
|
|
24511
|
+
},
|
|
24512
|
+
thought_level: {
|
|
24513
|
+
consumed: true,
|
|
24514
|
+
via: "config-options.ts:findAcpEffortConfig \u2192 executor.ts:applyRequestedEffort"
|
|
24515
|
+
},
|
|
24516
|
+
model_option: {
|
|
24517
|
+
consumed: true,
|
|
24518
|
+
// 精确说法:它不是**识别器**,是**优先级**。`looksLikeEffortOption` 先筛出候选,
|
|
24519
|
+
// 标了 `model_option` 的在候选里排第一(厂商自己标的最准),排在 id 叫 `effort`
|
|
24520
|
+
// 的和标 `thought_level` 的前面。光有这个 category 而 id/name 不像力度档的,
|
|
24521
|
+
// 压根进不了候选。
|
|
24522
|
+
via: "config-options.ts:findAcpEffortConfig\uFF08\u5019\u9009\u91CC\u7684\u6700\u9AD8\u4F18\u5148\u7EA7\uFF0C\u538B\u8FC7 thought_level\uFF09"
|
|
24523
|
+
},
|
|
24524
|
+
model_config: {
|
|
24525
|
+
consumed: false,
|
|
24526
|
+
note: "\u53EA\u6709\u5BBF\u4E3B\u7684 CursorProvider \u6D88\u8D39\u8FC7\uFF08context / fast / thinking \u4E09\u4E2A\u5F00\u5173\uFF09\u3002Cursor 2026-09-20 \u5E9F\u5F03\u5220\u9664\uFF0C\u8FD9\u4E00\u7C7B\u73B0\u5728\u6CA1\u6709\u6D88\u8D39\u70B9\uFF1B\u6CA1\u89C1\u8FC7\u522B\u5BB6\u7684\u771F\u5B9E\u8F7D\u8377\uFF0C\u5148\u8BB0\u8D26\u4E0D\u731C\u5F62\u72B6\u3002"
|
|
24527
|
+
}
|
|
24528
|
+
};
|
|
24529
|
+
var KNOWN_CATEGORIES = new Set(Object.keys(ACP_CONFIG_CATEGORY_HANDLING));
|
|
24530
|
+
function unhandledConfigCategories(configOptions) {
|
|
24531
|
+
if (!configOptions) return [];
|
|
24532
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24533
|
+
const out = [];
|
|
24534
|
+
for (const option of configOptions) {
|
|
24535
|
+
const category = option.category?.trim();
|
|
24536
|
+
if (!category) continue;
|
|
24537
|
+
if (KNOWN_CATEGORIES.has(category)) continue;
|
|
24538
|
+
if (seen.has(category)) continue;
|
|
24539
|
+
seen.add(category);
|
|
24540
|
+
out.push({
|
|
24541
|
+
category,
|
|
24542
|
+
optionId: option.id.trim(),
|
|
24543
|
+
vendorExtension: category.startsWith(VENDOR_CATEGORY_PREFIX)
|
|
24544
|
+
});
|
|
24545
|
+
}
|
|
24546
|
+
return out;
|
|
24547
|
+
}
|
|
24548
|
+
|
|
24368
24549
|
// ../../packages/ycodium-acp-executor/src/mutex.ts
|
|
24369
24550
|
var Mutex = class {
|
|
24370
24551
|
locked = false;
|
|
@@ -24407,7 +24588,7 @@ var Mutex = class {
|
|
|
24407
24588
|
};
|
|
24408
24589
|
|
|
24409
24590
|
// ../../packages/ycodium-acp-executor/src/util.ts
|
|
24410
|
-
function
|
|
24591
|
+
function isRecord5(value) {
|
|
24411
24592
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24412
24593
|
}
|
|
24413
24594
|
function asTrimmedString(value) {
|
|
@@ -24453,11 +24634,11 @@ function extractCommandFromTitle(title) {
|
|
|
24453
24634
|
return backtickMatch?.[1]?.trim() || void 0;
|
|
24454
24635
|
}
|
|
24455
24636
|
function extractToolCommand(data, title) {
|
|
24456
|
-
const item =
|
|
24457
|
-
const itemInput = item &&
|
|
24458
|
-
const itemResult = item &&
|
|
24459
|
-
const rawInput =
|
|
24460
|
-
const dataInput =
|
|
24637
|
+
const item = isRecord5(data?.["item"]) ? data["item"] : void 0;
|
|
24638
|
+
const itemInput = item && isRecord5(item["input"]) ? item["input"] : void 0;
|
|
24639
|
+
const itemResult = item && isRecord5(item["result"]) ? item["result"] : void 0;
|
|
24640
|
+
const rawInput = isRecord5(data?.["rawInput"]) ? data["rawInput"] : void 0;
|
|
24641
|
+
const dataInput = isRecord5(data?.["input"]) ? data["input"] : void 0;
|
|
24461
24642
|
const candidates = [
|
|
24462
24643
|
normalizeCommandValue(item?.["command"]),
|
|
24463
24644
|
normalizeCommandValue(itemInput?.["command"]),
|
|
@@ -24502,7 +24683,7 @@ function collectPaths(value, paths, seen, depth) {
|
|
|
24502
24683
|
}
|
|
24503
24684
|
return;
|
|
24504
24685
|
}
|
|
24505
|
-
if (!
|
|
24686
|
+
if (!isRecord5(value)) {
|
|
24506
24687
|
return;
|
|
24507
24688
|
}
|
|
24508
24689
|
for (const key of ["path", "filePath", "relativePath", "filename", "newPath", "oldPath"]) {
|
|
@@ -24565,7 +24746,7 @@ function deriveToolActivityPresentation(input2) {
|
|
|
24565
24746
|
const title = asTrimmedString(input2.title);
|
|
24566
24747
|
const detail = stripTrailingExitCode(asTrimmedString(input2.detail));
|
|
24567
24748
|
const fallbackSummary = asTrimmedString(input2.fallbackSummary) ?? "Tool";
|
|
24568
|
-
const data =
|
|
24749
|
+
const data = isRecord5(input2.data) ? input2.data : void 0;
|
|
24569
24750
|
const command = extractToolCommand(data, title);
|
|
24570
24751
|
const primaryPath = extractPrimaryPath(data);
|
|
24571
24752
|
const action = classifyToolAction({
|
|
@@ -24597,7 +24778,7 @@ function deriveToolActivityPresentation(input2) {
|
|
|
24597
24778
|
};
|
|
24598
24779
|
}
|
|
24599
24780
|
if (action === "search") {
|
|
24600
|
-
const rawInput =
|
|
24781
|
+
const rawInput = isRecord5(data?.["rawInput"]) ? data["rawInput"] : void 0;
|
|
24601
24782
|
const query = asTrimmedString(rawInput?.["query"]) ?? asTrimmedString(rawInput?.["pattern"]) ?? asTrimmedString(rawInput?.["searchTerm"]);
|
|
24602
24783
|
return {
|
|
24603
24784
|
summary: "Searched files",
|
|
@@ -24636,6 +24817,46 @@ function findSessionConfigOption(configOptions, configId) {
|
|
|
24636
24817
|
}
|
|
24637
24818
|
return configOptions.find((option) => option.id.trim() === normalizedConfigId);
|
|
24638
24819
|
}
|
|
24820
|
+
function collectSessionConfigOptionValues(configOption) {
|
|
24821
|
+
if (configOption.type !== "select" || !configOption.options) {
|
|
24822
|
+
return [];
|
|
24823
|
+
}
|
|
24824
|
+
return configOption.options.flatMap(
|
|
24825
|
+
(entry) => "value" in entry ? [entry.value] : entry.options.map((option) => option.value)
|
|
24826
|
+
);
|
|
24827
|
+
}
|
|
24828
|
+
function collectSessionModelIds(models) {
|
|
24829
|
+
if (!isRecord5(models) || !Array.isArray(models["availableModels"])) {
|
|
24830
|
+
return [];
|
|
24831
|
+
}
|
|
24832
|
+
return models["availableModels"].flatMap(
|
|
24833
|
+
(model) => isRecord5(model) && typeof model["modelId"] === "string" ? [model["modelId"]] : []
|
|
24834
|
+
);
|
|
24835
|
+
}
|
|
24836
|
+
function catalogModelLastSegment(value) {
|
|
24837
|
+
if (value.startsWith("[")) {
|
|
24838
|
+
let parsed;
|
|
24839
|
+
try {
|
|
24840
|
+
parsed = JSON.parse(value);
|
|
24841
|
+
} catch {
|
|
24842
|
+
return void 0;
|
|
24843
|
+
}
|
|
24844
|
+
if (!Array.isArray(parsed) || parsed.length < 2) return void 0;
|
|
24845
|
+
const last = parsed[parsed.length - 1];
|
|
24846
|
+
return typeof last === "string" ? last : void 0;
|
|
24847
|
+
}
|
|
24848
|
+
const separator = value.indexOf("/");
|
|
24849
|
+
return separator > 0 && separator < value.length - 1 ? value.slice(separator + 1) : void 0;
|
|
24850
|
+
}
|
|
24851
|
+
function matchAdvertisedModelValue(requestedModelId, advertisedValues) {
|
|
24852
|
+
const wanted = requestedModelId.trim();
|
|
24853
|
+
if (!wanted) return void 0;
|
|
24854
|
+
if (advertisedValues.includes(wanted)) return wanted;
|
|
24855
|
+
const byLastSegment = advertisedValues.filter(
|
|
24856
|
+
(value) => catalogModelLastSegment(value) === wanted
|
|
24857
|
+
);
|
|
24858
|
+
return byLastSegment.length === 1 ? byLastSegment[0] : void 0;
|
|
24859
|
+
}
|
|
24639
24860
|
function parseSessionModeState(sessionResponse) {
|
|
24640
24861
|
const modes = sessionResponse.modes;
|
|
24641
24862
|
if (!modes) return void 0;
|
|
@@ -24674,7 +24895,7 @@ function parseAvailableCommandsUpdate(params) {
|
|
|
24674
24895
|
}
|
|
24675
24896
|
const commands = [];
|
|
24676
24897
|
for (const command of availableCommands) {
|
|
24677
|
-
if (!
|
|
24898
|
+
if (!isRecord5(command)) {
|
|
24678
24899
|
continue;
|
|
24679
24900
|
}
|
|
24680
24901
|
const name = typeof command["name"] === "string" ? command["name"].trim() : "";
|
|
@@ -24682,7 +24903,7 @@ function parseAvailableCommandsUpdate(params) {
|
|
|
24682
24903
|
continue;
|
|
24683
24904
|
}
|
|
24684
24905
|
const description = typeof command["description"] === "string" ? command["description"].trim() || void 0 : void 0;
|
|
24685
|
-
const input2 =
|
|
24906
|
+
const input2 = isRecord5(command["input"]) ? command["input"] : void 0;
|
|
24686
24907
|
const inputHint = typeof input2?.["hint"] === "string" ? input2["hint"].trim() || void 0 : void 0;
|
|
24687
24908
|
commands.push({
|
|
24688
24909
|
name,
|
|
@@ -24744,7 +24965,7 @@ function extractCommandFromTitle2(title) {
|
|
|
24744
24965
|
return match?.[1]?.trim() || void 0;
|
|
24745
24966
|
}
|
|
24746
24967
|
function extractToolCallCommand(rawInput, title) {
|
|
24747
|
-
if (
|
|
24968
|
+
if (isRecord5(rawInput)) {
|
|
24748
24969
|
const directCommand = normalizeCommandValue2(rawInput["command"]);
|
|
24749
24970
|
if (directCommand) {
|
|
24750
24971
|
return directCommand;
|
|
@@ -24771,7 +24992,7 @@ function boundToolCallOutputText(text) {
|
|
|
24771
24992
|
}
|
|
24772
24993
|
var RAW_OUTPUT_TEXT_FIELDS = ["content", "stdout", "stderr", "output"];
|
|
24773
24994
|
function boundToolCallRawOutput(rawOutput) {
|
|
24774
|
-
if (!
|
|
24995
|
+
if (!isRecord5(rawOutput)) {
|
|
24775
24996
|
return rawOutput;
|
|
24776
24997
|
}
|
|
24777
24998
|
let changed = false;
|
|
@@ -25001,7 +25222,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
25001
25222
|
const entries = Array.isArray(upd["entries"]) ? upd["entries"] : [];
|
|
25002
25223
|
const plan = entries.map((entry, index) => ({
|
|
25003
25224
|
step: readAcpText(entry, "content") ?? `Step ${index + 1}`,
|
|
25004
|
-
status: normalizePlanStepStatus(
|
|
25225
|
+
status: normalizePlanStepStatus(isRecord5(entry) ? entry["status"] : void 0)
|
|
25005
25226
|
}));
|
|
25006
25227
|
if (plan.length > 0) {
|
|
25007
25228
|
events.push({
|
|
@@ -25040,7 +25261,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
25040
25261
|
}
|
|
25041
25262
|
case "agent_message_chunk":
|
|
25042
25263
|
case "agent_thought_chunk": {
|
|
25043
|
-
const content =
|
|
25264
|
+
const content = isRecord5(upd["content"]) ? upd["content"] : void 0;
|
|
25044
25265
|
const contentType = content?.["type"];
|
|
25045
25266
|
const streamKind = kind === "agent_thought_chunk" ? "reasoning_text" : "assistant_text";
|
|
25046
25267
|
if (contentType === "text") {
|
|
@@ -25107,16 +25328,18 @@ function normalizeModelId(value) {
|
|
|
25107
25328
|
return value?.trim() || void 0;
|
|
25108
25329
|
}
|
|
25109
25330
|
function modelSelectionStateFromSetup(setup) {
|
|
25110
|
-
const sessionModels =
|
|
25331
|
+
const sessionModels = isRecord5(setup.models) ? setup.models : void 0;
|
|
25111
25332
|
const modelConfigId = extractModelConfigId(setup);
|
|
25112
25333
|
const strategy = sessionModels === void 0 && modelConfigId !== void 0 ? "config-option" : "session/set_model";
|
|
25113
|
-
const
|
|
25334
|
+
const modelConfigOption = modelConfigId === void 0 ? void 0 : findSessionConfigOption(setup.configOptions, modelConfigId);
|
|
25335
|
+
const configModel = modelConfigOption?.currentValue;
|
|
25114
25336
|
const currentModelId = strategy === "config-option" ? typeof configModel === "string" ? normalizeModelId(configModel) : void 0 : typeof sessionModels?.["currentModelId"] === "string" ? normalizeModelId(sessionModels["currentModelId"]) : void 0;
|
|
25115
25337
|
return {
|
|
25116
25338
|
strategy,
|
|
25117
25339
|
sessionModelsAdvertised: sessionModels !== void 0,
|
|
25118
25340
|
modelConfigId,
|
|
25119
|
-
currentModelId
|
|
25341
|
+
currentModelId,
|
|
25342
|
+
advertisedModelValues: strategy === "config-option" ? modelConfigOption === void 0 ? [] : collectSessionConfigOptionValues(modelConfigOption) : collectSessionModelIds(sessionModels)
|
|
25120
25343
|
};
|
|
25121
25344
|
}
|
|
25122
25345
|
function createAcpExecutor(options) {
|
|
@@ -25135,8 +25358,10 @@ function createAcpExecutor(options) {
|
|
|
25135
25358
|
strategy: "session/set_model",
|
|
25136
25359
|
sessionModelsAdvertised: false,
|
|
25137
25360
|
modelConfigId: void 0,
|
|
25138
|
-
currentModelId: void 0
|
|
25361
|
+
currentModelId: void 0,
|
|
25362
|
+
advertisedModelValues: []
|
|
25139
25363
|
};
|
|
25364
|
+
let lastUnmatchedModelId;
|
|
25140
25365
|
let initializeResult;
|
|
25141
25366
|
let startResult;
|
|
25142
25367
|
let startInFlight;
|
|
@@ -25461,6 +25686,12 @@ function createAcpExecutor(options) {
|
|
|
25461
25686
|
const userInputOutcome = await handlePermissionAsUserInput(params);
|
|
25462
25687
|
if (userInputOutcome !== void 0) return userInputOutcome;
|
|
25463
25688
|
const permissionRequest = parsePermissionRequest(params);
|
|
25689
|
+
if (options.autoApprove?.(permissionRequest) === true) {
|
|
25690
|
+
const optionId = selectAutoApprovedAcpPermissionOption(params);
|
|
25691
|
+
if (optionId !== void 0) {
|
|
25692
|
+
return { outcome: { outcome: "selected", optionId } };
|
|
25693
|
+
}
|
|
25694
|
+
}
|
|
25464
25695
|
const requestId = randomId();
|
|
25465
25696
|
const outcome = await new Promise((resolve2) => {
|
|
25466
25697
|
const pending = {
|
|
@@ -25548,36 +25779,70 @@ function createAcpExecutor(options) {
|
|
|
25548
25779
|
if (requestedModelId === void 0 || requestedModelId === input2.state.currentModelId || input2.state.strategy === "session/set_model" && !input2.state.sessionModelsAdvertised || input2.state.strategy === "config-option" && input2.state.modelConfigId === void 0) {
|
|
25549
25780
|
return input2.state;
|
|
25550
25781
|
}
|
|
25782
|
+
const value = matchAdvertisedModelValue(requestedModelId, input2.state.advertisedModelValues);
|
|
25783
|
+
if (value === void 0) {
|
|
25784
|
+
if (requestedModelId !== lastUnmatchedModelId) {
|
|
25785
|
+
lastUnmatchedModelId = requestedModelId;
|
|
25786
|
+
options.log?.info("requested model is not in the agent catalog; keeping its own model", {
|
|
25787
|
+
requestedModelId,
|
|
25788
|
+
currentModelId: input2.state.currentModelId,
|
|
25789
|
+
advertisedModelValues: input2.state.advertisedModelValues
|
|
25790
|
+
});
|
|
25791
|
+
}
|
|
25792
|
+
return input2.state;
|
|
25793
|
+
}
|
|
25794
|
+
if (value === input2.state.currentModelId) {
|
|
25795
|
+
return input2.state;
|
|
25796
|
+
}
|
|
25551
25797
|
if (input2.state.strategy === "config-option") {
|
|
25552
25798
|
await connection.request("session/set_config_option", {
|
|
25553
25799
|
sessionId: input2.acpSessionId,
|
|
25554
25800
|
configId: input2.state.modelConfigId,
|
|
25555
|
-
value
|
|
25801
|
+
value
|
|
25556
25802
|
});
|
|
25557
25803
|
} else {
|
|
25558
25804
|
await connection.request("session/set_model", {
|
|
25559
25805
|
sessionId: input2.acpSessionId,
|
|
25560
|
-
modelId:
|
|
25806
|
+
modelId: value
|
|
25561
25807
|
});
|
|
25562
25808
|
}
|
|
25563
25809
|
if (!isLive(input2.expectedGeneration)) {
|
|
25564
25810
|
throw new AcpExecutorDisposedError();
|
|
25565
25811
|
}
|
|
25566
|
-
return { ...input2.state, currentModelId:
|
|
25812
|
+
return { ...input2.state, currentModelId: value };
|
|
25813
|
+
};
|
|
25814
|
+
const applyRequestedEffort = async (input2) => {
|
|
25815
|
+
const requested = input2.requestedEffort?.trim();
|
|
25816
|
+
if (!requested) return;
|
|
25817
|
+
const configOptions = typeof input2.setup === "object" && input2.setup !== null ? input2.setup.configOptions : void 0;
|
|
25818
|
+
const effort = findAcpEffortConfig(configOptions);
|
|
25819
|
+
if (effort === void 0) return;
|
|
25820
|
+
const matched = effort.choices.find((choice) => choice.value === requested);
|
|
25821
|
+
if (matched === void 0) {
|
|
25822
|
+
options.log?.info("requested effort is not in the agent catalog; keeping its own", {
|
|
25823
|
+
requestedEffort: requested,
|
|
25824
|
+
advertised: effort.choices.map((choice) => choice.value)
|
|
25825
|
+
});
|
|
25826
|
+
return;
|
|
25827
|
+
}
|
|
25828
|
+
if (matched.isDefault === true) return;
|
|
25829
|
+
if (!isLive(input2.expectedGeneration)) return;
|
|
25830
|
+
try {
|
|
25831
|
+
await connection.request("session/set_config_option", {
|
|
25832
|
+
sessionId: input2.acpSessionId,
|
|
25833
|
+
configId: effort.configId,
|
|
25834
|
+
value: requested
|
|
25835
|
+
});
|
|
25836
|
+
} catch (error62) {
|
|
25837
|
+
options.log?.info("setting the effort level failed; the session keeps its own", {
|
|
25838
|
+
requestedEffort: requested,
|
|
25839
|
+
configId: effort.configId,
|
|
25840
|
+
error: error62 instanceof Error ? error62.message : String(error62)
|
|
25841
|
+
});
|
|
25842
|
+
}
|
|
25567
25843
|
};
|
|
25568
25844
|
const startOnce = async (expectedGeneration) => {
|
|
25569
|
-
const initializePayload =
|
|
25570
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
25571
|
-
clientCapabilities: {
|
|
25572
|
-
fs: {
|
|
25573
|
-
readTextFile: false,
|
|
25574
|
-
writeTextFile: false,
|
|
25575
|
-
...options.clientCapabilities?.fs
|
|
25576
|
-
},
|
|
25577
|
-
terminal: options.clientCapabilities?.terminal ?? false
|
|
25578
|
-
},
|
|
25579
|
-
clientInfo: options.clientInfo
|
|
25580
|
-
};
|
|
25845
|
+
const initializePayload = acpInitializePayload(options.clientInfo, options.clientCapabilities);
|
|
25581
25846
|
const initialized = await connection.request(
|
|
25582
25847
|
"initialize",
|
|
25583
25848
|
initializePayload
|
|
@@ -25621,12 +25886,27 @@ function createAcpExecutor(options) {
|
|
|
25621
25886
|
nextSessionId = created.sessionId;
|
|
25622
25887
|
setup = created;
|
|
25623
25888
|
}
|
|
25889
|
+
const unhandledCategories = unhandledConfigCategories(
|
|
25890
|
+
setup.configOptions
|
|
25891
|
+
);
|
|
25892
|
+
if (unhandledCategories.length > 0) {
|
|
25893
|
+
options.log?.info("acp session reported config option categories we do not handle", {
|
|
25894
|
+
sessionId: nextSessionId,
|
|
25895
|
+
categories: unhandledCategories
|
|
25896
|
+
});
|
|
25897
|
+
}
|
|
25624
25898
|
const nextModelSelectionState = await applyRequestedModel({
|
|
25625
25899
|
state: modelSelectionStateFromSetup(setup),
|
|
25626
25900
|
acpSessionId: nextSessionId,
|
|
25627
25901
|
requestedModelId: options.requestedModelId,
|
|
25628
25902
|
expectedGeneration
|
|
25629
25903
|
});
|
|
25904
|
+
await applyRequestedEffort({
|
|
25905
|
+
setup,
|
|
25906
|
+
acpSessionId: nextSessionId,
|
|
25907
|
+
requestedEffort: options.requestedEffort,
|
|
25908
|
+
expectedGeneration
|
|
25909
|
+
});
|
|
25630
25910
|
if (options.beforeApplyResult) {
|
|
25631
25911
|
await options.beforeApplyResult();
|
|
25632
25912
|
}
|
|
@@ -25991,6 +26271,26 @@ function createAcpExecutor(options) {
|
|
|
25991
26271
|
};
|
|
25992
26272
|
apply();
|
|
25993
26273
|
};
|
|
26274
|
+
const setNativeMode = async (modeId) => {
|
|
26275
|
+
failIfDisposed();
|
|
26276
|
+
const started = startResult;
|
|
26277
|
+
if (started === void 0) {
|
|
26278
|
+
throw new AcpExecutorRequestError("session/set_mode", "session has not started yet");
|
|
26279
|
+
}
|
|
26280
|
+
const configId = acpModeConfigId(started.sessionSetupResult);
|
|
26281
|
+
if (configId !== void 0) {
|
|
26282
|
+
await connection.request("session/set_config_option", {
|
|
26283
|
+
sessionId: started.sessionId,
|
|
26284
|
+
configId,
|
|
26285
|
+
value: modeId
|
|
26286
|
+
});
|
|
26287
|
+
return;
|
|
26288
|
+
}
|
|
26289
|
+
await connection.request("session/set_mode", {
|
|
26290
|
+
sessionId: started.sessionId,
|
|
26291
|
+
modeId
|
|
26292
|
+
});
|
|
26293
|
+
};
|
|
25994
26294
|
const respondToUserInput = async (requestId, answers) => {
|
|
25995
26295
|
failIfDisposed();
|
|
25996
26296
|
const pending = pendingUserInputs.get(requestId);
|
|
@@ -26007,7 +26307,7 @@ function createAcpExecutor(options) {
|
|
|
26007
26307
|
pendingUserInputs.delete(requestId);
|
|
26008
26308
|
pending.resolve({
|
|
26009
26309
|
kind: "answered",
|
|
26010
|
-
answers:
|
|
26310
|
+
answers: isRecord5(answers) ? answers : {}
|
|
26011
26311
|
});
|
|
26012
26312
|
};
|
|
26013
26313
|
const dispose = async () => {
|
|
@@ -26057,13 +26357,56 @@ function createAcpExecutor(options) {
|
|
|
26057
26357
|
cancel,
|
|
26058
26358
|
respondToRequest,
|
|
26059
26359
|
respondToUserInput,
|
|
26360
|
+
setNativeMode,
|
|
26060
26361
|
dispose
|
|
26061
26362
|
};
|
|
26062
26363
|
}
|
|
26063
26364
|
|
|
26365
|
+
// ../../packages/ycodium-acp-executor/src/probe.ts
|
|
26366
|
+
function withProbeTimeout(promise2, timeoutMs, method) {
|
|
26367
|
+
return new Promise((resolve2, reject) => {
|
|
26368
|
+
const timer = setTimeout(() => {
|
|
26369
|
+
reject(new Error(`ACP probe request '${method}' timed out after ${timeoutMs}ms`));
|
|
26370
|
+
}, timeoutMs);
|
|
26371
|
+
timer.unref?.();
|
|
26372
|
+
promise2.then(
|
|
26373
|
+
(value) => {
|
|
26374
|
+
clearTimeout(timer);
|
|
26375
|
+
resolve2(value);
|
|
26376
|
+
},
|
|
26377
|
+
(error62) => {
|
|
26378
|
+
clearTimeout(timer);
|
|
26379
|
+
reject(error62 instanceof Error ? error62 : new Error(String(error62)));
|
|
26380
|
+
}
|
|
26381
|
+
);
|
|
26382
|
+
});
|
|
26383
|
+
}
|
|
26384
|
+
async function openAcpProbeHandshake(input2) {
|
|
26385
|
+
const connection = createAcpConnection({
|
|
26386
|
+
readable: input2.readable,
|
|
26387
|
+
writable: input2.writable,
|
|
26388
|
+
onNotification: () => void 0
|
|
26389
|
+
});
|
|
26390
|
+
try {
|
|
26391
|
+
const initializeResult = await withProbeTimeout(
|
|
26392
|
+
connection.request("initialize", acpInitializePayload(input2.clientInfo)),
|
|
26393
|
+
input2.requestTimeoutMs,
|
|
26394
|
+
"initialize"
|
|
26395
|
+
);
|
|
26396
|
+
return {
|
|
26397
|
+
initializeResult,
|
|
26398
|
+
request: (method, params) => withProbeTimeout(connection.request(method, params), input2.requestTimeoutMs, method),
|
|
26399
|
+
close: () => connection.close()
|
|
26400
|
+
};
|
|
26401
|
+
} catch (error62) {
|
|
26402
|
+
await connection.close().catch(() => void 0);
|
|
26403
|
+
throw error62;
|
|
26404
|
+
}
|
|
26405
|
+
}
|
|
26406
|
+
|
|
26064
26407
|
// src/config.ts
|
|
26065
26408
|
var GROK_DEFAULT_LAUNCH_ARGS = "agent stdio";
|
|
26066
|
-
function
|
|
26409
|
+
function isRecord6(value) {
|
|
26067
26410
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26068
26411
|
}
|
|
26069
26412
|
function readString(value) {
|
|
@@ -26076,7 +26419,7 @@ function readEnvironment(value) {
|
|
|
26076
26419
|
if (!Array.isArray(value)) return {};
|
|
26077
26420
|
const env = {};
|
|
26078
26421
|
for (const entry of value) {
|
|
26079
|
-
if (!
|
|
26422
|
+
if (!isRecord6(entry)) continue;
|
|
26080
26423
|
const name = readTrimmed(entry["name"]);
|
|
26081
26424
|
if (name.length === 0) continue;
|
|
26082
26425
|
env[name] = readString(entry["value"]);
|
|
@@ -26084,7 +26427,7 @@ function readEnvironment(value) {
|
|
|
26084
26427
|
return env;
|
|
26085
26428
|
}
|
|
26086
26429
|
function parseGrokInstanceConfig(config2) {
|
|
26087
|
-
if (!
|
|
26430
|
+
if (!isRecord6(config2)) {
|
|
26088
26431
|
return {
|
|
26089
26432
|
binaryPath: "",
|
|
26090
26433
|
launchArgs: GROK_DEFAULT_LAUNCH_ARGS,
|
|
@@ -26094,7 +26437,7 @@ function parseGrokInstanceConfig(config2) {
|
|
|
26094
26437
|
envelopeDriver: void 0
|
|
26095
26438
|
};
|
|
26096
26439
|
}
|
|
26097
|
-
const nested =
|
|
26440
|
+
const nested = isRecord6(config2["config"]) ? config2["config"] : void 0;
|
|
26098
26441
|
const settings = nested ?? config2;
|
|
26099
26442
|
return {
|
|
26100
26443
|
binaryPath: readTrimmed(settings["binaryPath"]),
|
|
@@ -26161,7 +26504,7 @@ function tokenizeLaunchArgs(value) {
|
|
|
26161
26504
|
import * as NodeFS from "node:fs";
|
|
26162
26505
|
import * as NodePath from "node:path";
|
|
26163
26506
|
var AUTH_FILE_NAME = "auth.json";
|
|
26164
|
-
var
|
|
26507
|
+
var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26165
26508
|
var readString2 = (record2, key) => {
|
|
26166
26509
|
const value = record2[key];
|
|
26167
26510
|
if (typeof value !== "string") return void 0;
|
|
@@ -26175,7 +26518,7 @@ var parseJsonRecord = (raw) => {
|
|
|
26175
26518
|
} catch {
|
|
26176
26519
|
return void 0;
|
|
26177
26520
|
}
|
|
26178
|
-
return
|
|
26521
|
+
return isRecord7(parsed) ? parsed : void 0;
|
|
26179
26522
|
};
|
|
26180
26523
|
var directoryExists = (homePath) => {
|
|
26181
26524
|
try {
|
|
@@ -26213,7 +26556,7 @@ var joinName = (record2) => {
|
|
|
26213
26556
|
};
|
|
26214
26557
|
var findIdentityEntry = (parsed) => {
|
|
26215
26558
|
for (const value of Object.values(parsed)) {
|
|
26216
|
-
if (!
|
|
26559
|
+
if (!isRecord7(value)) continue;
|
|
26217
26560
|
if (readString2(value, "email") !== void 0 || readString2(value, "user_id") !== void 0) {
|
|
26218
26561
|
return value;
|
|
26219
26562
|
}
|
|
@@ -26243,7 +26586,8 @@ var readGrokAccount = (homePath) => {
|
|
|
26243
26586
|
};
|
|
26244
26587
|
|
|
26245
26588
|
// src/grokSupport.ts
|
|
26246
|
-
|
|
26589
|
+
import { modelSelectionStringOption } from "@ycodium-ai/plugin-api/executor";
|
|
26590
|
+
var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26247
26591
|
var trimmed = (value) => {
|
|
26248
26592
|
if (typeof value !== "string") return void 0;
|
|
26249
26593
|
const text = value.trim();
|
|
@@ -26253,51 +26597,153 @@ function grokReasoningEffortArgs(effort) {
|
|
|
26253
26597
|
const value = effort?.trim();
|
|
26254
26598
|
return value === void 0 || value.length === 0 ? [] : ["--reasoning-effort", value];
|
|
26255
26599
|
}
|
|
26256
|
-
var
|
|
26257
|
-
|
|
26258
|
-
|
|
26259
|
-
|
|
26260
|
-
|
|
26261
|
-
|
|
26262
|
-
|
|
26263
|
-
|
|
26264
|
-
|
|
26600
|
+
var GROK_NATIVE_MODE_BY_RUNTIME_MODE = {
|
|
26601
|
+
"approval-required": "default",
|
|
26602
|
+
"auto-accept-edits": "auto",
|
|
26603
|
+
auto: "auto",
|
|
26604
|
+
"full-access": "bypassPermissions"
|
|
26605
|
+
};
|
|
26606
|
+
var GROK_NATIVE_MODES = [
|
|
26607
|
+
{
|
|
26608
|
+
id: "default",
|
|
26609
|
+
name: "Ask every time",
|
|
26610
|
+
description: "Asks before writing files, running commands, or spawning subagents."
|
|
26611
|
+
},
|
|
26612
|
+
{
|
|
26613
|
+
id: "auto",
|
|
26614
|
+
name: "Auto",
|
|
26615
|
+
description: "Runs edits and subagents without asking; still asks for shell writes and monitor."
|
|
26616
|
+
},
|
|
26617
|
+
{
|
|
26618
|
+
id: "bypassPermissions",
|
|
26619
|
+
name: "Bypass permissions",
|
|
26620
|
+
description: "Never asks. Every tool runs immediately."
|
|
26265
26621
|
}
|
|
26266
|
-
|
|
26622
|
+
];
|
|
26623
|
+
var GROK_DEFAULT_NATIVE_MODE_ID = "default";
|
|
26624
|
+
var GROK_NATIVE_MODE_REPORT = {
|
|
26625
|
+
nativeModes: GROK_NATIVE_MODES.map((mode) => ({
|
|
26626
|
+
id: mode.id,
|
|
26627
|
+
name: mode.name,
|
|
26628
|
+
description: mode.description
|
|
26629
|
+
})),
|
|
26630
|
+
currentNativeModeId: GROK_DEFAULT_NATIVE_MODE_ID,
|
|
26631
|
+
nativeModeByRuntimeMode: GROK_NATIVE_MODE_BY_RUNTIME_MODE
|
|
26632
|
+
};
|
|
26633
|
+
function isGrokNativeModeId(value) {
|
|
26634
|
+
return GROK_NATIVE_MODES.some((mode) => mode.id === value);
|
|
26635
|
+
}
|
|
26636
|
+
function grokPermissionModeFor(runtimeMode, nativeModeId) {
|
|
26637
|
+
return nativeModeId !== void 0 && isGrokNativeModeId(nativeModeId) ? nativeModeId : GROK_NATIVE_MODE_BY_RUNTIME_MODE[runtimeMode];
|
|
26638
|
+
}
|
|
26639
|
+
function grokPermissionModeArgs(runtimeMode, nativeModeId) {
|
|
26640
|
+
return ["--permission-mode", grokPermissionModeFor(runtimeMode, nativeModeId)];
|
|
26641
|
+
}
|
|
26642
|
+
var GROK_AUTO_APPROVAL_COVERAGE = {
|
|
26643
|
+
asked: ["run_terminal_command", "monitor"],
|
|
26644
|
+
unasked: [
|
|
26645
|
+
"write",
|
|
26646
|
+
"search_replace",
|
|
26647
|
+
"read_file",
|
|
26648
|
+
"todo_write",
|
|
26649
|
+
"web_search",
|
|
26650
|
+
"scheduler_create",
|
|
26651
|
+
"spawn_subagent",
|
|
26652
|
+
"workflow",
|
|
26653
|
+
"use_tool",
|
|
26654
|
+
"send_feedback",
|
|
26655
|
+
"image_gen"
|
|
26656
|
+
]
|
|
26657
|
+
};
|
|
26658
|
+
var GROK_APPROVAL_COVERAGE = {
|
|
26659
|
+
default: {
|
|
26660
|
+
asked: [
|
|
26661
|
+
"write",
|
|
26662
|
+
"search_replace",
|
|
26663
|
+
"run_terminal_command",
|
|
26664
|
+
"monitor",
|
|
26665
|
+
"spawn_subagent",
|
|
26666
|
+
"workflow",
|
|
26667
|
+
"scheduler_create",
|
|
26668
|
+
"use_tool",
|
|
26669
|
+
"send_feedback",
|
|
26670
|
+
"image_gen"
|
|
26671
|
+
],
|
|
26672
|
+
unasked: ["read_file", "todo_write", "web_search"]
|
|
26673
|
+
},
|
|
26674
|
+
// 「编辑不问、命令仍问」的那一档,实测只剩 shell 写删与 monitor 会问——落差就是
|
|
26675
|
+
// 这条要说的。
|
|
26676
|
+
auto: GROK_AUTO_APPROVAL_COVERAGE,
|
|
26677
|
+
// 全放行:档位自己就说「不问」,没有落差可报。
|
|
26678
|
+
bypassPermissions: null
|
|
26679
|
+
};
|
|
26680
|
+
var GROK_EXTERNAL_PERMISSION_RULES_PATHS = [
|
|
26681
|
+
// 顺序无语义:**这不是优先级表**,只是文案里列出来的次序(碰巧按用户级 → 用户本地
|
|
26682
|
+
// → 机器级排,别读出别的意思)。三份同时给冲突规则时谁赢**没量过**,别照这个顺序
|
|
26683
|
+
// 推断;要用就先量。唯一量过的相邻关系是「`settings.local.json` 的 `deny` 赢过
|
|
26684
|
+
// `settings.json` 的 `allow`」(F13 `loc-local-deny`)。
|
|
26685
|
+
"~/.claude/settings.json",
|
|
26686
|
+
"~/.claude/settings.local.json",
|
|
26687
|
+
"/etc/claude-code/managed-settings.json"
|
|
26688
|
+
];
|
|
26689
|
+
var RUNTIME_MODE_APPROVAL_COVERAGE_CODE = "runtime-mode-approval-coverage";
|
|
26690
|
+
function grokRuntimeModeCaveat(nativeModeId) {
|
|
26691
|
+
const coverage = GROK_APPROVAL_COVERAGE[nativeModeId];
|
|
26692
|
+
if (coverage === null) return void 0;
|
|
26693
|
+
const message = `Approval prompts do not cover every Grok tool in this mode. No prompt, inside or outside the workspace: ${coverage.unasked.join(", ")}, plus shell commands Grok rates safe such as \`touch\`. Prompts: ${coverage.asked.join(", ")}. Permission rules in ${GROK_EXTERNAL_PERMISSION_RULES_PATHS.join(", ")} override this mode \u2014 a matching allow entry drops the prompt, a matching deny entry blocks the call outright.`;
|
|
26694
|
+
return {
|
|
26695
|
+
code: RUNTIME_MODE_APPROVAL_COVERAGE_CODE,
|
|
26696
|
+
nativeModeId,
|
|
26697
|
+
asked: coverage.asked,
|
|
26698
|
+
unasked: coverage.unasked,
|
|
26699
|
+
externalRulesPaths: GROK_EXTERNAL_PERMISSION_RULES_PATHS,
|
|
26700
|
+
message
|
|
26701
|
+
};
|
|
26267
26702
|
}
|
|
26703
|
+
var GROK_REASONING_OPTION_ID = "reasoningEffort";
|
|
26268
26704
|
function resolveGrokAuthMethodId(initializeResult) {
|
|
26269
|
-
const authMethods =
|
|
26705
|
+
const authMethods = isRecord8(initializeResult) ? initializeResult["authMethods"] : void 0;
|
|
26270
26706
|
if (!Array.isArray(authMethods)) return void 0;
|
|
26271
26707
|
for (const method of authMethods) {
|
|
26272
|
-
if (
|
|
26708
|
+
if (isRecord8(method) && method["id"] === "cached_token") return "cached_token";
|
|
26273
26709
|
}
|
|
26274
26710
|
return void 0;
|
|
26275
26711
|
}
|
|
26276
26712
|
var positive = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.trunc(value) : void 0;
|
|
26277
26713
|
function grokPromptUsage(promptResponse) {
|
|
26278
|
-
if (!
|
|
26714
|
+
if (!isRecord8(promptResponse)) return void 0;
|
|
26279
26715
|
const meta3 = promptResponse["_meta"];
|
|
26280
|
-
if (!
|
|
26716
|
+
if (!isRecord8(meta3)) return void 0;
|
|
26281
26717
|
const usedTokens = positive(meta3["totalTokens"]);
|
|
26282
26718
|
if (usedTokens === void 0) return void 0;
|
|
26283
26719
|
return { usedTokens, modelId: trimmed(meta3["modelId"]) };
|
|
26284
26720
|
}
|
|
26285
|
-
function
|
|
26286
|
-
if (!
|
|
26721
|
+
function grokModelState(initializeResult) {
|
|
26722
|
+
if (!isRecord8(initializeResult)) return void 0;
|
|
26287
26723
|
const meta3 = initializeResult["_meta"];
|
|
26288
|
-
if (!
|
|
26724
|
+
if (!isRecord8(meta3)) return void 0;
|
|
26289
26725
|
const modelState = meta3["modelState"];
|
|
26290
|
-
if (!
|
|
26726
|
+
if (!isRecord8(modelState)) return void 0;
|
|
26291
26727
|
const availableModels = modelState["availableModels"];
|
|
26292
|
-
if (!Array.isArray(availableModels)) return
|
|
26728
|
+
if (!Array.isArray(availableModels)) return void 0;
|
|
26729
|
+
return { currentModelId: trimmed(modelState["currentModelId"]), availableModels };
|
|
26730
|
+
}
|
|
26731
|
+
function grokAdvertisedModels(initializeResult) {
|
|
26732
|
+
const state = grokModelState(initializeResult);
|
|
26733
|
+
if (state === void 0) return [];
|
|
26293
26734
|
const models = [];
|
|
26294
|
-
for (const entry of availableModels) {
|
|
26295
|
-
if (!
|
|
26735
|
+
for (const entry of state.availableModels) {
|
|
26736
|
+
if (!isRecord8(entry)) continue;
|
|
26296
26737
|
const modelId = trimmed(entry["modelId"]);
|
|
26297
26738
|
if (modelId === void 0) continue;
|
|
26298
26739
|
const modelMeta = entry["_meta"];
|
|
26299
|
-
const contextWindow =
|
|
26300
|
-
models.push({
|
|
26740
|
+
const contextWindow = isRecord8(modelMeta) ? positive(modelMeta["totalContextTokens"]) : void 0;
|
|
26741
|
+
models.push({
|
|
26742
|
+
modelId,
|
|
26743
|
+
name: trimmed(entry["name"]),
|
|
26744
|
+
isDefault: state.currentModelId !== void 0 && modelId === state.currentModelId,
|
|
26745
|
+
contextWindow
|
|
26746
|
+
});
|
|
26301
26747
|
}
|
|
26302
26748
|
return models;
|
|
26303
26749
|
}
|
|
@@ -26306,7 +26752,7 @@ var XAI_ASK_USER_QUESTION_METHODS = [
|
|
|
26306
26752
|
"x.ai/ask_user_question"
|
|
26307
26753
|
];
|
|
26308
26754
|
var readOption = (value) => {
|
|
26309
|
-
if (!
|
|
26755
|
+
if (!isRecord8(value)) return void 0;
|
|
26310
26756
|
const label = typeof value["label"] === "string" ? value["label"] : void 0;
|
|
26311
26757
|
if (label === void 0) return void 0;
|
|
26312
26758
|
return {
|
|
@@ -26317,7 +26763,7 @@ var readOption = (value) => {
|
|
|
26317
26763
|
};
|
|
26318
26764
|
};
|
|
26319
26765
|
var readQuestion = (value) => {
|
|
26320
|
-
if (!
|
|
26766
|
+
if (!isRecord8(value)) return void 0;
|
|
26321
26767
|
const question = typeof value["question"] === "string" ? value["question"] : void 0;
|
|
26322
26768
|
if (question === void 0) return void 0;
|
|
26323
26769
|
const optionsRaw = value["options"];
|
|
@@ -26333,9 +26779,9 @@ var readQuestion = (value) => {
|
|
|
26333
26779
|
};
|
|
26334
26780
|
};
|
|
26335
26781
|
function parseXAiAskUserQuestionParams(params) {
|
|
26336
|
-
const candidates = [params, ...
|
|
26782
|
+
const candidates = [params, ...isRecord8(params) ? [params["params"]] : []];
|
|
26337
26783
|
for (const candidate of candidates) {
|
|
26338
|
-
if (!
|
|
26784
|
+
if (!isRecord8(candidate)) continue;
|
|
26339
26785
|
const questionsRaw = candidate["questions"];
|
|
26340
26786
|
if (!Array.isArray(questionsRaw)) continue;
|
|
26341
26787
|
const questions = questionsRaw.flatMap((entry) => {
|
|
@@ -26412,14 +26858,14 @@ var grokPromptSettlement = {
|
|
|
26412
26858
|
// agent 认回哪个键是它的事,两个都给才不猜版本。
|
|
26413
26859
|
requestFields: (promptKey) => ({ _meta: { promptId: promptKey, requestId: promptKey } }),
|
|
26414
26860
|
responseKey: (response) => {
|
|
26415
|
-
if (!
|
|
26861
|
+
if (!isRecord8(response)) return void 0;
|
|
26416
26862
|
const meta3 = response["_meta"];
|
|
26417
|
-
if (!
|
|
26863
|
+
if (!isRecord8(meta3)) return void 0;
|
|
26418
26864
|
return trimmed(meta3["promptId"]) ?? trimmed(meta3["requestId"]);
|
|
26419
26865
|
},
|
|
26420
26866
|
fromNotification: (method, params) => {
|
|
26421
26867
|
if (method !== XAI_PROMPT_COMPLETE_METHOD) return void 0;
|
|
26422
|
-
if (!
|
|
26868
|
+
if (!isRecord8(params)) return void 0;
|
|
26423
26869
|
const sessionId = params["sessionId"];
|
|
26424
26870
|
if (typeof sessionId !== "string") return void 0;
|
|
26425
26871
|
const stopReason = trimmed(params["stopReason"]);
|
|
@@ -26433,57 +26879,53 @@ var grokPromptSettlement = {
|
|
|
26433
26879
|
}
|
|
26434
26880
|
};
|
|
26435
26881
|
|
|
26436
|
-
// src/
|
|
26437
|
-
import
|
|
26438
|
-
|
|
26439
|
-
|
|
26440
|
-
|
|
26441
|
-
|
|
26442
|
-
|
|
26443
|
-
|
|
26444
|
-
|
|
26445
|
-
|
|
26446
|
-
|
|
26447
|
-
|
|
26448
|
-
|
|
26449
|
-
|
|
26450
|
-
|
|
26451
|
-
|
|
26452
|
-
|
|
26453
|
-
|
|
26454
|
-
|
|
26455
|
-
|
|
26456
|
-
|
|
26457
|
-
|
|
26458
|
-
|
|
26459
|
-
}
|
|
26460
|
-
|
|
26461
|
-
|
|
26462
|
-
|
|
26463
|
-
|
|
26464
|
-
|
|
26465
|
-
|
|
26466
|
-
|
|
26467
|
-
|
|
26468
|
-
|
|
26469
|
-
|
|
26470
|
-
|
|
26471
|
-
|
|
26472
|
-
|
|
26473
|
-
|
|
26474
|
-
|
|
26475
|
-
|
|
26476
|
-
|
|
26477
|
-
|
|
26478
|
-
|
|
26479
|
-
}
|
|
26480
|
-
});
|
|
26481
|
-
return { readable, writable };
|
|
26882
|
+
// src/probeModels.ts
|
|
26883
|
+
import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
|
|
26884
|
+
var PROBE_REQUEST_TIMEOUT_MS = 2e4;
|
|
26885
|
+
function grokProbeModels(initializeResult) {
|
|
26886
|
+
if (grokModelState(initializeResult) === void 0) return void 0;
|
|
26887
|
+
return grokAdvertisedModels(initializeResult).map((model) => ({
|
|
26888
|
+
slug: model.modelId,
|
|
26889
|
+
...model.name === void 0 ? {} : { name: model.name },
|
|
26890
|
+
...model.isDefault ? { isDefault: true } : {},
|
|
26891
|
+
...model.contextWindow === void 0 ? {} : { contextWindow: model.contextWindow }
|
|
26892
|
+
}));
|
|
26893
|
+
}
|
|
26894
|
+
var failureDetail = (error62) => (error62 instanceof Error ? error62.message : String(error62)).trim() || void 0;
|
|
26895
|
+
async function probeGrokModels(input2) {
|
|
26896
|
+
const { recipe, host, env } = input2;
|
|
26897
|
+
let handle;
|
|
26898
|
+
try {
|
|
26899
|
+
handle = await host.process.spawn({
|
|
26900
|
+
program: recipe.binaryPath,
|
|
26901
|
+
args: tokenizeLaunchArgs(recipe.launchArgs),
|
|
26902
|
+
cwd: process.cwd(),
|
|
26903
|
+
owner: { bindingId: host.bindingId },
|
|
26904
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
26905
|
+
});
|
|
26906
|
+
} catch (error62) {
|
|
26907
|
+
return { kind: "not-started", detail: failureDetail(error62) };
|
|
26908
|
+
}
|
|
26909
|
+
let handshake;
|
|
26910
|
+
try {
|
|
26911
|
+
const { readable, writable } = nodeStreamsFromHandle(handle);
|
|
26912
|
+
handshake = await openAcpProbeHandshake({
|
|
26913
|
+
readable,
|
|
26914
|
+
writable,
|
|
26915
|
+
clientInfo: GROK_CLIENT_INFO,
|
|
26916
|
+
requestTimeoutMs: PROBE_REQUEST_TIMEOUT_MS
|
|
26917
|
+
});
|
|
26918
|
+
return { kind: "answered", models: grokProbeModels(handshake.initializeResult) };
|
|
26919
|
+
} catch (error62) {
|
|
26920
|
+
return { kind: "failed", detail: failureDetail(error62) };
|
|
26921
|
+
} finally {
|
|
26922
|
+
await handshake?.close().catch(() => void 0);
|
|
26923
|
+
await handle.kill("SIGTERM").catch(() => void 0);
|
|
26924
|
+
}
|
|
26482
26925
|
}
|
|
26483
26926
|
|
|
26484
26927
|
// src/grokInstance.ts
|
|
26485
26928
|
var RESUME_SCHEMA_VERSION = 1;
|
|
26486
|
-
var CLIENT_INFO = { name: "ycodium-agent-grok", version: "0.1.0" };
|
|
26487
26929
|
var yieldTick = () => new Promise((resolve2) => {
|
|
26488
26930
|
setImmediate(resolve2);
|
|
26489
26931
|
});
|
|
@@ -26543,21 +26985,15 @@ function resolveAccountHomePath(recipe, configuredHome) {
|
|
|
26543
26985
|
}
|
|
26544
26986
|
return resolveGrokHomePath(configuredHome);
|
|
26545
26987
|
}
|
|
26546
|
-
function
|
|
26547
|
-
const out = {};
|
|
26548
|
-
for (const [key, value] of Object.entries(env)) {
|
|
26549
|
-
if (value !== void 0) out[key] = value;
|
|
26550
|
-
}
|
|
26551
|
-
return out;
|
|
26552
|
-
}
|
|
26553
|
-
function buildSpawnEnv(recipe, launch, resolvedHomePath, homeConfigured) {
|
|
26988
|
+
function buildSpawnEnv(recipe, resolvedHomePath, homeConfigured, launchEnv = {}) {
|
|
26554
26989
|
const homeInjection = homeConfigured ? { [GROK_CARD.homeEnvVar]: resolvedHomePath } : {};
|
|
26555
|
-
return {
|
|
26556
|
-
|
|
26557
|
-
|
|
26558
|
-
|
|
26559
|
-
GROK_OAUTH2_REFERRER: "ycodium"
|
|
26560
|
-
|
|
26990
|
+
return mergeLaunchEnv({
|
|
26991
|
+
brainSlots: brainSlotEnvKeys(GROK_CARD),
|
|
26992
|
+
accountHome: homeInjection,
|
|
26993
|
+
instanceTable: recipe.environment,
|
|
26994
|
+
handOverrides: { GROK_OAUTH2_REFERRER: "ycodium" },
|
|
26995
|
+
launch: launchEnv
|
|
26996
|
+
});
|
|
26561
26997
|
}
|
|
26562
26998
|
function nowIso() {
|
|
26563
26999
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -26601,24 +27037,49 @@ var createGrokInstance = (config2, host) => {
|
|
|
26601
27037
|
return { status: "unknown" };
|
|
26602
27038
|
}
|
|
26603
27039
|
};
|
|
26604
|
-
const
|
|
26605
|
-
|
|
26606
|
-
if (recipe.binaryPath.length === 0) {
|
|
26607
|
-
return {
|
|
26608
|
-
installed: false,
|
|
26609
|
-
version: null,
|
|
26610
|
-
readiness: "error",
|
|
26611
|
-
auth: { status: "unknown" },
|
|
26612
|
-
detail: "Grok program path is not configured"
|
|
26613
|
-
};
|
|
26614
|
-
}
|
|
27040
|
+
const probe = async () => {
|
|
27041
|
+
if (recipe.binaryPath.length === 0) {
|
|
26615
27042
|
return {
|
|
26616
|
-
installed:
|
|
27043
|
+
installed: false,
|
|
26617
27044
|
version: null,
|
|
26618
|
-
readiness: "
|
|
26619
|
-
auth:
|
|
27045
|
+
readiness: "error",
|
|
27046
|
+
auth: { status: "unknown" },
|
|
27047
|
+
detail: "Grok program path is not configured"
|
|
26620
27048
|
};
|
|
26621
|
-
}
|
|
27049
|
+
}
|
|
27050
|
+
const configuredHome = recipe.homePath;
|
|
27051
|
+
const outcome = await probeGrokModels({
|
|
27052
|
+
recipe,
|
|
27053
|
+
host,
|
|
27054
|
+
env: buildSpawnEnv(
|
|
27055
|
+
recipe,
|
|
27056
|
+
resolveGrokHomePath(configuredHome),
|
|
27057
|
+
configuredHome.trim().length > 0
|
|
27058
|
+
)
|
|
27059
|
+
});
|
|
27060
|
+
if (outcome.kind !== "answered") {
|
|
27061
|
+
return {
|
|
27062
|
+
installed: outcome.kind === "failed",
|
|
27063
|
+
version: null,
|
|
27064
|
+
readiness: "error",
|
|
27065
|
+
auth: probeAuth(),
|
|
27066
|
+
...outcome.detail === void 0 ? {} : { detail: outcome.detail },
|
|
27067
|
+
// 装着但握不上手时,界面照样画权限格。不报档就退回宿主四档,而那四档对这双手
|
|
27068
|
+
// 是撒谎的——这台开发机的 grok 就长期停在这个出口上。
|
|
27069
|
+
...outcome.kind === "failed" ? GROK_NATIVE_MODE_REPORT : {}
|
|
27070
|
+
};
|
|
27071
|
+
}
|
|
27072
|
+
return {
|
|
27073
|
+
installed: true,
|
|
27074
|
+
version: null,
|
|
27075
|
+
readiness: "ready",
|
|
27076
|
+
auth: probeAuth(),
|
|
27077
|
+
...outcome.models === void 0 ? {} : { models: outcome.models },
|
|
27078
|
+
...GROK_NATIVE_MODE_REPORT
|
|
27079
|
+
};
|
|
27080
|
+
};
|
|
27081
|
+
const instance = {
|
|
27082
|
+
probe,
|
|
26622
27083
|
startSession: async (input2, signal) => {
|
|
26623
27084
|
if (disposed) throw new Error("instance disposed");
|
|
26624
27085
|
if (signal?.aborted) throw new Error("aborted");
|
|
@@ -26634,11 +27095,18 @@ var createGrokInstance = (config2, host) => {
|
|
|
26634
27095
|
}
|
|
26635
27096
|
const configuredHome = input2.launch.homePath?.trim() || recipe.homePath;
|
|
26636
27097
|
const resolvedHomePath = resolveGrokHomePath(configuredHome);
|
|
26637
|
-
const env = buildSpawnEnv(
|
|
27098
|
+
const env = buildSpawnEnv(
|
|
27099
|
+
recipe,
|
|
27100
|
+
resolvedHomePath,
|
|
27101
|
+
configuredHome.length > 0,
|
|
27102
|
+
input2.launch.processEnv
|
|
27103
|
+
);
|
|
26638
27104
|
const effort = modelSelectionStringOption(input2.modelSelection, GROK_REASONING_OPTION_ID);
|
|
26639
27105
|
const baseArgs = tokenizeLaunchArgs(recipe.launchArgs);
|
|
26640
27106
|
const insertAt = baseArgs.length <= 1 ? baseArgs.length : baseArgs.length - 1;
|
|
27107
|
+
const permissionMode = grokPermissionModeFor(input2.runtimeMode, input2.nativeModeId);
|
|
26641
27108
|
const args = [
|
|
27109
|
+
...grokPermissionModeArgs(input2.runtimeMode, permissionMode),
|
|
26642
27110
|
...baseArgs.slice(0, insertAt),
|
|
26643
27111
|
...grokReasoningEffortArgs(effort),
|
|
26644
27112
|
...baseArgs.slice(insertAt)
|
|
@@ -26650,7 +27118,7 @@ var createGrokInstance = (config2, host) => {
|
|
|
26650
27118
|
owner: { bindingId: host.bindingId },
|
|
26651
27119
|
...Object.keys(env).length > 0 ? { env } : {}
|
|
26652
27120
|
});
|
|
26653
|
-
const { readable, writable } =
|
|
27121
|
+
const { readable, writable } = nodeStreamsFromHandle2(handle);
|
|
26654
27122
|
const resume = input2.discardResumeCursor === true ? void 0 : parseAcpResumeCursor(input2.resumeCursor, RESUME_SCHEMA_VERSION);
|
|
26655
27123
|
const requestedModelId = input2.launch.requestedModelId?.trim() || modelIdFromSelection(input2.modelSelection);
|
|
26656
27124
|
let initializeResult;
|
|
@@ -26661,7 +27129,8 @@ var createGrokInstance = (config2, host) => {
|
|
|
26661
27129
|
threadId: input2.threadId,
|
|
26662
27130
|
provider: GROK_DRIVER_KIND,
|
|
26663
27131
|
providerInstanceId: host.instanceId,
|
|
26664
|
-
clientInfo:
|
|
27132
|
+
clientInfo: GROK_CLIENT_INFO,
|
|
27133
|
+
log: host.log,
|
|
26665
27134
|
// 等 `initialize` 回来再挑认证方式:能不能用 `cached_token`,只有 agent
|
|
26666
27135
|
// 播报的 `authMethods` 说了算(见 resolveGrokAuthMethodId)。
|
|
26667
27136
|
authMethodId: resolveGrokAuthMethodId,
|
|
@@ -26715,6 +27184,7 @@ var createGrokInstance = (config2, host) => {
|
|
|
26715
27184
|
providerInstanceId: host.instanceId,
|
|
26716
27185
|
status: "idle",
|
|
26717
27186
|
runtimeMode: input2.runtimeMode,
|
|
27187
|
+
nativeModeId: permissionMode,
|
|
26718
27188
|
cwd,
|
|
26719
27189
|
threadId: input2.threadId,
|
|
26720
27190
|
createdAt,
|
|
@@ -26734,6 +27204,27 @@ var createGrokInstance = (config2, host) => {
|
|
|
26734
27204
|
threadId: input2.threadId,
|
|
26735
27205
|
sessionId: started.sessionId
|
|
26736
27206
|
});
|
|
27207
|
+
const caveat = grokRuntimeModeCaveat(permissionMode);
|
|
27208
|
+
if (caveat !== void 0) {
|
|
27209
|
+
events.push({
|
|
27210
|
+
type: "runtime.warning",
|
|
27211
|
+
eventId: NodeCrypto2.randomUUID(),
|
|
27212
|
+
provider: GROK_DRIVER_KIND,
|
|
27213
|
+
providerInstanceId: host.instanceId,
|
|
27214
|
+
threadId: input2.threadId,
|
|
27215
|
+
createdAt: nowIso(),
|
|
27216
|
+
payload: {
|
|
27217
|
+
message: caveat.message,
|
|
27218
|
+
detail: {
|
|
27219
|
+
code: caveat.code,
|
|
27220
|
+
nativeModeId: caveat.nativeModeId,
|
|
27221
|
+
asked: caveat.asked,
|
|
27222
|
+
unasked: caveat.unasked,
|
|
27223
|
+
externalRulesPaths: caveat.externalRulesPaths
|
|
27224
|
+
}
|
|
27225
|
+
}
|
|
27226
|
+
});
|
|
27227
|
+
}
|
|
26737
27228
|
return session;
|
|
26738
27229
|
} catch (error62) {
|
|
26739
27230
|
await executor.dispose().catch(() => void 0);
|
|
@@ -26803,14 +27294,6 @@ var createGrokInstance = (config2, host) => {
|
|
|
26803
27294
|
const booked = requireThread(threadId);
|
|
26804
27295
|
await booked.executor.respondToUserInput(requestId, answers);
|
|
26805
27296
|
},
|
|
26806
|
-
setRuntimeMode: async (threadId, runtimeMode) => {
|
|
26807
|
-
const booked = requireThread(threadId);
|
|
26808
|
-
booked.session = {
|
|
26809
|
-
...booked.session,
|
|
26810
|
-
runtimeMode,
|
|
26811
|
-
updatedAt: nowIso()
|
|
26812
|
-
};
|
|
26813
|
-
},
|
|
26814
27297
|
stopSession: async (threadId) => {
|
|
26815
27298
|
const booked = threads.get(threadId);
|
|
26816
27299
|
if (booked === void 0) return;
|
|
@@ -26899,23 +27382,7 @@ var createGrokInstance = (config2, host) => {
|
|
|
26899
27382
|
await operation.handle.kill("SIGTERM").catch(() => void 0);
|
|
26900
27383
|
await operation.stdoutText.catch(() => void 0);
|
|
26901
27384
|
},
|
|
26902
|
-
verify:
|
|
26903
|
-
if (recipe.binaryPath.length === 0) {
|
|
26904
|
-
return {
|
|
26905
|
-
installed: false,
|
|
26906
|
-
version: null,
|
|
26907
|
-
readiness: "error",
|
|
26908
|
-
auth: { status: "unknown" },
|
|
26909
|
-
detail: "Grok program path is not configured"
|
|
26910
|
-
};
|
|
26911
|
-
}
|
|
26912
|
-
return {
|
|
26913
|
-
installed: true,
|
|
26914
|
-
version: null,
|
|
26915
|
-
readiness: "unchecked",
|
|
26916
|
-
auth: probeAuth()
|
|
26917
|
-
};
|
|
26918
|
-
}
|
|
27385
|
+
verify: () => probe()
|
|
26919
27386
|
}
|
|
26920
27387
|
};
|
|
26921
27388
|
return instance;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ycodium-ai/agent-grok",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2126",
|
|
4
4
|
"description": "Grok executor: grok CLI over Agent Client Protocol stdio.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@types/node": "24.12.4",
|
|
21
21
|
"esbuild": "0.28.1",
|
|
22
22
|
"vite-plus": "0.2.2",
|
|
23
|
-
"@ycodium-ai/plugin-api": "0.2.
|
|
23
|
+
"@ycodium-ai/plugin-api": "0.2.2126",
|
|
24
24
|
"ycodium-acp-executor": "0.0.0",
|
|
25
25
|
"ycodium-acp-protocol": "0.0.0"
|
|
26
26
|
},
|