@ycodium-ai/agent-grok 0.2.2130 → 0.2.2155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/index.js +115 -19
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -34,8 +34,9 @@ Facts:
|
|
|
34
34
|
credential reads use the home the subprocess actually sees. An empty
|
|
35
35
|
account directory means the CLI default `~/.grok` is used without injection.
|
|
36
36
|
- Manifest permission is `{ kind: "executor" }`.
|
|
37
|
-
-
|
|
38
|
-
|
|
37
|
+
- Native in-session model switching is `unsupported` on the card. The host applies
|
|
38
|
+
upstream model changes by rebinding the local endpoint and resuming the existing
|
|
39
|
+
conversation; the CLI's internal model is tracked separately.
|
|
39
40
|
|
|
40
41
|
Develop with `vp run --filter @ycodium-ai/agent-grok typecheck`, `build`, and `test`.
|
|
41
42
|
|
package/dist/index.js
CHANGED
|
@@ -57,8 +57,7 @@ var GROK_CARD = {
|
|
|
57
57
|
verifiedSkills: false,
|
|
58
58
|
everydayHarness: false,
|
|
59
59
|
capabilities: {
|
|
60
|
-
//
|
|
61
|
-
// 但插件侧的执行路径还没接到模型管理 UI,名片必须说实话。
|
|
60
|
+
// 插件不承诺原生会话内活切型号;宿主更换上游模型时重绑端点并续接原生会话。
|
|
62
61
|
sessionModelSwitch: "unsupported",
|
|
63
62
|
// 运行模式只在 spawn 时定得了(`--permission-mode` 是启动旗标,ACP 那一侧
|
|
64
63
|
// `modes: null`,`session/set_mode` 对它无效),所以不许声称能会话中途换。
|
|
@@ -94,7 +93,11 @@ var GROK_CARD = {
|
|
|
94
93
|
additionalProperties: true
|
|
95
94
|
},
|
|
96
95
|
modelConnectivity: {
|
|
97
|
-
|
|
96
|
+
// 只报绑定送得出去的那一种:后缀是 `/chat/completions`,绑定也不替它改 `api_backend`,
|
|
97
|
+
// 所以它打本机端点说的永远是 chat。CLI 换了配置能说 messages / responses 不算——
|
|
98
|
+
// 报三种时兼容判定照着挑了「直通」,起手才发现后缀对不上,接 Anthropic 格式的脑与
|
|
99
|
+
// Responses 格式的订阅全起不来。别家的脑经宿主翻译接上。
|
|
100
|
+
dialects: ["openai-chat-completions"],
|
|
98
101
|
acceptsExternalEndpoints: true,
|
|
99
102
|
// 地址那一栏必须投:不设 `GROK_MODELS_BASE_URL` 的话整条请求根本不来我们这儿
|
|
100
103
|
// (`grokModelProxyEgress.test.ts` 拿掉这一栏就红)。
|
|
@@ -23751,6 +23754,7 @@ function createAcpConnection(options) {
|
|
|
23751
23754
|
options.readable.off("data", onData);
|
|
23752
23755
|
options.readable.off("end", onEnd);
|
|
23753
23756
|
options.readable.off("error", onError);
|
|
23757
|
+
options.writable.off("error", onWritableError);
|
|
23754
23758
|
try {
|
|
23755
23759
|
await byteWriter.close();
|
|
23756
23760
|
} catch {
|
|
@@ -23889,8 +23893,17 @@ function createAcpConnection(options) {
|
|
|
23889
23893
|
endInboundBatch();
|
|
23890
23894
|
}
|
|
23891
23895
|
};
|
|
23896
|
+
const failInbound = (error62) => {
|
|
23897
|
+
if (closedError !== void 0) return;
|
|
23898
|
+
options.onInboundFailure?.(error62);
|
|
23899
|
+
void shutdown(
|
|
23900
|
+
new AcpConnectionClosedError(
|
|
23901
|
+
`ACP inbound handling failed: ${error62 instanceof Error ? error62.message : String(error62)}`
|
|
23902
|
+
)
|
|
23903
|
+
);
|
|
23904
|
+
};
|
|
23892
23905
|
const enqueueInbound = (work) => {
|
|
23893
|
-
inboundTail = inboundTail.then(work
|
|
23906
|
+
inboundTail = inboundTail.then(work).catch(failInbound);
|
|
23894
23907
|
};
|
|
23895
23908
|
const onData = (chunk) => {
|
|
23896
23909
|
if (closedError !== void 0) {
|
|
@@ -23940,9 +23953,15 @@ function createAcpConnection(options) {
|
|
|
23940
23953
|
);
|
|
23941
23954
|
});
|
|
23942
23955
|
};
|
|
23956
|
+
const onWritableError = (error62) => {
|
|
23957
|
+
void shutdown(
|
|
23958
|
+
error62 instanceof Error ? error62 : new AcpConnectionClosedError("ACP output stream error")
|
|
23959
|
+
);
|
|
23960
|
+
};
|
|
23943
23961
|
options.readable.on("data", onData);
|
|
23944
23962
|
options.readable.on("end", onEnd);
|
|
23945
23963
|
options.readable.on("error", onError);
|
|
23964
|
+
options.writable.once("error", onWritableError);
|
|
23946
23965
|
const request = (async (method, params) => {
|
|
23947
23966
|
failIfClosed();
|
|
23948
23967
|
const id = nextRequestId;
|
|
@@ -23951,7 +23970,7 @@ function createAcpConnection(options) {
|
|
|
23951
23970
|
pending.set(String(id), { method, resolve: resolve2, reject });
|
|
23952
23971
|
const message = params === void 0 ? { jsonrpc: "2.0", id, method } : { jsonrpc: "2.0", id, method, params };
|
|
23953
23972
|
try {
|
|
23954
|
-
await writeMessage(message);
|
|
23973
|
+
await Promise.race([writeMessage(message), promise2]);
|
|
23955
23974
|
} catch (error62) {
|
|
23956
23975
|
if (pending.delete(String(id))) {
|
|
23957
23976
|
reject(error62);
|
|
@@ -25726,6 +25745,12 @@ function createAcpExecutor(options) {
|
|
|
25726
25745
|
const connection = createAcpConnection({
|
|
25727
25746
|
readable: options.readable,
|
|
25728
25747
|
writable: options.writable,
|
|
25748
|
+
onInboundFailure: (error62) => {
|
|
25749
|
+
options.log?.warn?.("acp connection closed: an inbound request could not be answered", {
|
|
25750
|
+
threadId: options.threadId,
|
|
25751
|
+
error: error62 instanceof Error ? error62.message : String(error62)
|
|
25752
|
+
});
|
|
25753
|
+
},
|
|
25729
25754
|
onNotification: (notification) => {
|
|
25730
25755
|
if (notification.method === "session/update") {
|
|
25731
25756
|
handleSessionUpdate(notification.params);
|
|
@@ -26363,10 +26388,10 @@ function createAcpExecutor(options) {
|
|
|
26363
26388
|
}
|
|
26364
26389
|
|
|
26365
26390
|
// ../../packages/ycodium-acp-executor/src/probe.ts
|
|
26366
|
-
function withProbeTimeout(promise2, timeoutMs,
|
|
26391
|
+
function withProbeTimeout(promise2, timeoutMs, what) {
|
|
26367
26392
|
return new Promise((resolve2, reject) => {
|
|
26368
26393
|
const timer = setTimeout(() => {
|
|
26369
|
-
reject(new Error(
|
|
26394
|
+
reject(new Error(`${what} timed out after ${timeoutMs}ms`));
|
|
26370
26395
|
}, timeoutMs);
|
|
26371
26396
|
timer.unref?.();
|
|
26372
26397
|
promise2.then(
|
|
@@ -26391,11 +26416,15 @@ async function openAcpProbeHandshake(input2) {
|
|
|
26391
26416
|
const initializeResult = await withProbeTimeout(
|
|
26392
26417
|
connection.request("initialize", acpInitializePayload(input2.clientInfo)),
|
|
26393
26418
|
input2.requestTimeoutMs,
|
|
26394
|
-
"initialize"
|
|
26419
|
+
"ACP probe request 'initialize'"
|
|
26395
26420
|
);
|
|
26396
26421
|
return {
|
|
26397
26422
|
initializeResult,
|
|
26398
|
-
request: (method, params) => withProbeTimeout(
|
|
26423
|
+
request: (method, params) => withProbeTimeout(
|
|
26424
|
+
connection.request(method, params),
|
|
26425
|
+
input2.requestTimeoutMs,
|
|
26426
|
+
`ACP probe request '${method}'`
|
|
26427
|
+
),
|
|
26399
26428
|
close: () => connection.close()
|
|
26400
26429
|
};
|
|
26401
26430
|
} catch (error62) {
|
|
@@ -26403,6 +26432,57 @@ async function openAcpProbeHandshake(input2) {
|
|
|
26403
26432
|
throw error62;
|
|
26404
26433
|
}
|
|
26405
26434
|
}
|
|
26435
|
+
var CLI_VERSION_PATTERN = /(?<![\d.])(\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)/;
|
|
26436
|
+
function parseCliVersion(output2) {
|
|
26437
|
+
return CLI_VERSION_PATTERN.exec(output2)?.[1] ?? null;
|
|
26438
|
+
}
|
|
26439
|
+
async function collectCappedText(stream, maxBytes) {
|
|
26440
|
+
const decoder = new TextDecoder();
|
|
26441
|
+
let text = "";
|
|
26442
|
+
let total = 0;
|
|
26443
|
+
for await (const chunk of stream) {
|
|
26444
|
+
total += chunk.byteLength;
|
|
26445
|
+
if (total <= maxBytes) text += decoder.decode(chunk, { stream: true });
|
|
26446
|
+
}
|
|
26447
|
+
return { text: text + decoder.decode(), overflowed: total > maxBytes };
|
|
26448
|
+
}
|
|
26449
|
+
async function collectProbeProcess(child, input2) {
|
|
26450
|
+
try {
|
|
26451
|
+
await child.closeStdin().catch(() => void 0);
|
|
26452
|
+
const [stdout, stderr, exitCode] = await withProbeTimeout(
|
|
26453
|
+
Promise.all([
|
|
26454
|
+
collectCappedText(child.stdout, input2.maxOutputBytes),
|
|
26455
|
+
collectCappedText(child.stderr, input2.maxOutputBytes),
|
|
26456
|
+
child.exited
|
|
26457
|
+
]),
|
|
26458
|
+
input2.timeoutMs,
|
|
26459
|
+
input2.what
|
|
26460
|
+
);
|
|
26461
|
+
return { stdout: stdout.overflowed ? void 0 : stdout.text, stderr: stderr.text, exitCode };
|
|
26462
|
+
} finally {
|
|
26463
|
+
await child.kill("SIGTERM").catch(() => void 0);
|
|
26464
|
+
}
|
|
26465
|
+
}
|
|
26466
|
+
var MAX_VERSION_OUTPUT_BYTES = 64 * 1024;
|
|
26467
|
+
async function probeCliVersion(input2) {
|
|
26468
|
+
let child;
|
|
26469
|
+
try {
|
|
26470
|
+
child = await input2.spawn();
|
|
26471
|
+
} catch {
|
|
26472
|
+
return null;
|
|
26473
|
+
}
|
|
26474
|
+
try {
|
|
26475
|
+
const run = await collectProbeProcess(child, {
|
|
26476
|
+
timeoutMs: input2.timeoutMs,
|
|
26477
|
+
maxOutputBytes: MAX_VERSION_OUTPUT_BYTES,
|
|
26478
|
+
what: "--version"
|
|
26479
|
+
});
|
|
26480
|
+
if (run.exitCode !== 0) return null;
|
|
26481
|
+
return parseCliVersion(run.stdout ?? "") ?? parseCliVersion(run.stderr);
|
|
26482
|
+
} catch {
|
|
26483
|
+
return null;
|
|
26484
|
+
}
|
|
26485
|
+
}
|
|
26406
26486
|
|
|
26407
26487
|
// src/config.ts
|
|
26408
26488
|
var GROK_DEFAULT_LAUNCH_ARGS = "agent stdio";
|
|
@@ -26880,6 +26960,9 @@ var grokPromptSettlement = {
|
|
|
26880
26960
|
};
|
|
26881
26961
|
|
|
26882
26962
|
// src/probeModels.ts
|
|
26963
|
+
import {
|
|
26964
|
+
ExecutorSpawnRefusedError
|
|
26965
|
+
} from "@ycodium-ai/plugin-api/executor";
|
|
26883
26966
|
import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
|
|
26884
26967
|
var PROBE_REQUEST_TIMEOUT_MS = 2e4;
|
|
26885
26968
|
function grokProbeModels(initializeResult) {
|
|
@@ -26904,6 +26987,7 @@ async function probeGrokModels(input2) {
|
|
|
26904
26987
|
...Object.keys(env).length > 0 ? { env } : {}
|
|
26905
26988
|
});
|
|
26906
26989
|
} catch (error62) {
|
|
26990
|
+
if (error62 instanceof ExecutorSpawnRefusedError) throw error62;
|
|
26907
26991
|
return { kind: "not-started", detail: failureDetail(error62) };
|
|
26908
26992
|
}
|
|
26909
26993
|
let handshake;
|
|
@@ -26923,6 +27007,18 @@ async function probeGrokModels(input2) {
|
|
|
26923
27007
|
await handle.kill("SIGTERM").catch(() => void 0);
|
|
26924
27008
|
}
|
|
26925
27009
|
}
|
|
27010
|
+
async function probeGrokVersion(input2) {
|
|
27011
|
+
const { recipe, host, env } = input2;
|
|
27012
|
+
return probeCliVersion({
|
|
27013
|
+
spawn: () => host.process.spawn({
|
|
27014
|
+
program: recipe.binaryPath,
|
|
27015
|
+
args: ["--version"],
|
|
27016
|
+
owner: { bindingId: host.bindingId },
|
|
27017
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
27018
|
+
}),
|
|
27019
|
+
timeoutMs: PROBE_REQUEST_TIMEOUT_MS
|
|
27020
|
+
});
|
|
27021
|
+
}
|
|
26926
27022
|
|
|
26927
27023
|
// src/grokInstance.ts
|
|
26928
27024
|
var RESUME_SCHEMA_VERSION = 1;
|
|
@@ -27051,19 +27147,19 @@ var createGrokInstance = (config2, host) => {
|
|
|
27051
27147
|
};
|
|
27052
27148
|
}
|
|
27053
27149
|
const configuredHome = recipe.homePath;
|
|
27054
|
-
const
|
|
27150
|
+
const env = buildSpawnEnv(
|
|
27055
27151
|
recipe,
|
|
27056
|
-
|
|
27057
|
-
|
|
27058
|
-
|
|
27059
|
-
|
|
27060
|
-
|
|
27061
|
-
)
|
|
27062
|
-
|
|
27152
|
+
resolveGrokHomePath(configuredHome),
|
|
27153
|
+
configuredHome.trim().length > 0
|
|
27154
|
+
);
|
|
27155
|
+
const [outcome, version2] = await Promise.all([
|
|
27156
|
+
probeGrokModels({ recipe, host, env }),
|
|
27157
|
+
probeGrokVersion({ recipe, host, env })
|
|
27158
|
+
]);
|
|
27063
27159
|
if (outcome.kind !== "answered") {
|
|
27064
27160
|
return {
|
|
27065
27161
|
installed: outcome.kind === "failed",
|
|
27066
|
-
version:
|
|
27162
|
+
version: version2,
|
|
27067
27163
|
readiness: "error",
|
|
27068
27164
|
auth: probeAuth(),
|
|
27069
27165
|
...outcome.detail === void 0 ? {} : { detail: outcome.detail },
|
|
@@ -27074,7 +27170,7 @@ var createGrokInstance = (config2, host) => {
|
|
|
27074
27170
|
}
|
|
27075
27171
|
return {
|
|
27076
27172
|
installed: true,
|
|
27077
|
-
version:
|
|
27173
|
+
version: version2,
|
|
27078
27174
|
readiness: "ready",
|
|
27079
27175
|
auth: probeAuth(),
|
|
27080
27176
|
...outcome.models === void 0 ? {} : { models: outcome.models },
|
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.2155",
|
|
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.2155",
|
|
24
24
|
"ycodium-acp-protocol": "0.0.0",
|
|
25
25
|
"ycodium-acp-executor": "0.0.0"
|
|
26
26
|
},
|