@ycodium-ai/agent-grok 0.2.3710 → 0.2.3799
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 +387 -277
- package/locales/en.json +9 -0
- package/locales/zh-CN.json +9 -0
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -6,6 +6,11 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
8
|
import { definePlugin } from "@ycodium-ai/plugin-api";
|
|
9
|
+
import {
|
|
10
|
+
EXECUTOR_EFFECTIVE_PAYLOAD_SCHEMA,
|
|
11
|
+
executorHomeEffectiveValue,
|
|
12
|
+
readExecutorEffectiveRequest
|
|
13
|
+
} from "@ycodium-ai/plugin-api/executor";
|
|
9
14
|
|
|
10
15
|
// src/card.ts
|
|
11
16
|
var GROK_DRIVER_KIND = "grok";
|
|
@@ -23,6 +28,8 @@ var GROK_CARD = {
|
|
|
23
28
|
// `grokInstance.startSession` 里按用户选择拼。
|
|
24
29
|
launchArgs: "agent stdio",
|
|
25
30
|
homeEnvVar: "GROK_HOME",
|
|
31
|
+
// 设置表单里留空的格子此刻会用什么,见 index.ts 的同名命令。
|
|
32
|
+
effectiveCommand: "effectiveConfig",
|
|
26
33
|
// 只有一个账户目录,它同时装着会话历史:换目录,已开的 thread 就接不上这个实例了。
|
|
27
34
|
accountDirectory: {
|
|
28
35
|
configKeys: ["homePath"],
|
|
@@ -81,7 +88,10 @@ var GROK_CARD = {
|
|
|
81
88
|
// 压缩生命周期事件报;CLI 没宣告这条命令时 `compactContext` 拒绝,不退回发文本。
|
|
82
89
|
contextCompaction: "native",
|
|
83
90
|
// 子 agent 经父会话上的 subagent_* 通知报成 task.*(grokSubagents.ts)。
|
|
84
|
-
reportsSpawnedAgents: true
|
|
91
|
+
reportsSpawnedAgents: true,
|
|
92
|
+
// 插话:起会话前在配置里打开 `follow_up_behavior = "steer"`(grokFollowUpSteer.ts),运行中再发的 prompt
|
|
93
|
+
// 由 grok 在下一个工具调用结束时并进这一轮(1.0.70 ACP 模式实测);执行器不等前一条应答就写出去。
|
|
94
|
+
turnSteering: true
|
|
85
95
|
},
|
|
86
96
|
// 凭据由 CLI 自己保管在 `<GROK_HOME>/auth.json`,宿主读它只认 `/token`。
|
|
87
97
|
credentialSources: [
|
|
@@ -161,6 +171,166 @@ var GROK_CARD = {
|
|
|
161
171
|
}
|
|
162
172
|
};
|
|
163
173
|
|
|
174
|
+
// src/grokHome.ts
|
|
175
|
+
import * as NodeCrypto from "node:crypto";
|
|
176
|
+
import * as NodeOS from "node:os";
|
|
177
|
+
import * as NodePath2 from "node:path";
|
|
178
|
+
import { mergeLaunchEnv } from "@ycodium-ai/plugin-api/executor";
|
|
179
|
+
|
|
180
|
+
// src/grokAccount.ts
|
|
181
|
+
import * as NodeFS from "node:fs";
|
|
182
|
+
import * as NodePath from "node:path";
|
|
183
|
+
var AUTH_FILE_NAME = "auth.json";
|
|
184
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
185
|
+
var readString = (record4, key) => {
|
|
186
|
+
const value = record4[key];
|
|
187
|
+
if (typeof value !== "string") return void 0;
|
|
188
|
+
const trimmed3 = value.trim();
|
|
189
|
+
return trimmed3.length > 0 ? trimmed3 : void 0;
|
|
190
|
+
};
|
|
191
|
+
var parseJsonRecord = (raw) => {
|
|
192
|
+
let parsed;
|
|
193
|
+
try {
|
|
194
|
+
parsed = JSON.parse(raw);
|
|
195
|
+
} catch {
|
|
196
|
+
return void 0;
|
|
197
|
+
}
|
|
198
|
+
return isRecord(parsed) ? parsed : void 0;
|
|
199
|
+
};
|
|
200
|
+
var directoryExists = (homePath) => {
|
|
201
|
+
try {
|
|
202
|
+
return NodeFS.statSync(homePath).isDirectory();
|
|
203
|
+
} catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
var readCredentialFile = (path) => {
|
|
208
|
+
try {
|
|
209
|
+
return NodeFS.readFileSync(path, "utf8");
|
|
210
|
+
} catch {
|
|
211
|
+
return void 0;
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
var signedOutProbe = (exists) => ({
|
|
215
|
+
state: "signed-out",
|
|
216
|
+
directoryExists: exists,
|
|
217
|
+
email: void 0,
|
|
218
|
+
name: void 0,
|
|
219
|
+
expiresAt: void 0
|
|
220
|
+
});
|
|
221
|
+
var unreadableProbe = (exists) => ({
|
|
222
|
+
state: "unreadable",
|
|
223
|
+
directoryExists: exists,
|
|
224
|
+
email: void 0,
|
|
225
|
+
name: void 0,
|
|
226
|
+
expiresAt: void 0
|
|
227
|
+
});
|
|
228
|
+
var joinName = (record4) => {
|
|
229
|
+
const first = readString(record4, "first_name");
|
|
230
|
+
const last = readString(record4, "last_name");
|
|
231
|
+
const joined = [first, last].filter((part) => part !== void 0).join(" ");
|
|
232
|
+
return joined.length > 0 ? joined : void 0;
|
|
233
|
+
};
|
|
234
|
+
var findIdentityEntry = (parsed) => {
|
|
235
|
+
for (const value of Object.values(parsed)) {
|
|
236
|
+
if (!isRecord(value)) continue;
|
|
237
|
+
if (readString(value, "email") !== void 0 || readString(value, "user_id") !== void 0) {
|
|
238
|
+
return value;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return void 0;
|
|
242
|
+
};
|
|
243
|
+
var isExpired = (expiresAt, nowMs) => {
|
|
244
|
+
if (expiresAt === void 0) return false;
|
|
245
|
+
const parsed = Date.parse(expiresAt);
|
|
246
|
+
return Number.isNaN(parsed) ? false : parsed <= nowMs;
|
|
247
|
+
};
|
|
248
|
+
var readGrokAccount = (homePath) => {
|
|
249
|
+
const exists = directoryExists(homePath);
|
|
250
|
+
const raw = readCredentialFile(NodePath.join(homePath, AUTH_FILE_NAME));
|
|
251
|
+
if (raw === void 0) return signedOutProbe(exists);
|
|
252
|
+
const parsed = parseJsonRecord(raw);
|
|
253
|
+
const identity = parsed === void 0 ? void 0 : findIdentityEntry(parsed);
|
|
254
|
+
if (identity === void 0) return unreadableProbe(exists);
|
|
255
|
+
const expiresAt = readString(identity, "expires_at");
|
|
256
|
+
return {
|
|
257
|
+
state: isExpired(expiresAt, Date.now()) ? "expired" : "signed-in",
|
|
258
|
+
directoryExists: exists,
|
|
259
|
+
email: readString(identity, "email"),
|
|
260
|
+
name: joinName(identity),
|
|
261
|
+
expiresAt
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// src/grokHome.ts
|
|
266
|
+
function expandHomePath(value) {
|
|
267
|
+
if (value === "~") return NodeOS.homedir();
|
|
268
|
+
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
269
|
+
return NodePath2.join(NodeOS.homedir(), value.slice(2));
|
|
270
|
+
}
|
|
271
|
+
return value;
|
|
272
|
+
}
|
|
273
|
+
function resolveGrokHomePath(value) {
|
|
274
|
+
const trimmed3 = value.trim();
|
|
275
|
+
if (trimmed3.length === 0) return NodePath2.join(NodeOS.homedir(), ".grok");
|
|
276
|
+
return NodePath2.resolve(expandHomePath(trimmed3));
|
|
277
|
+
}
|
|
278
|
+
function probeGrokAccount(accountPath) {
|
|
279
|
+
const resolved = resolveGrokHomePath(accountPath);
|
|
280
|
+
const account = readGrokAccount(resolved);
|
|
281
|
+
return {
|
|
282
|
+
accountPath: resolved,
|
|
283
|
+
state: account.state,
|
|
284
|
+
...account.email === void 0 ? {} : { email: account.email },
|
|
285
|
+
...account.name === void 0 ? {} : { name: account.name },
|
|
286
|
+
...account.expiresAt === void 0 ? {} : { expiresAt: account.expiresAt }
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function grokContinuationKey(recipe) {
|
|
290
|
+
return `grok:home:${resolveGrokHomePath(recipe.homePath)}`;
|
|
291
|
+
}
|
|
292
|
+
function resolveAccountHomePath(recipe, configuredHome) {
|
|
293
|
+
const fromEnvironment = recipe.environment["GROK_HOME"]?.trim();
|
|
294
|
+
if (fromEnvironment !== void 0 && fromEnvironment.length > 0) {
|
|
295
|
+
return NodePath2.resolve(expandHomePath(fromEnvironment));
|
|
296
|
+
}
|
|
297
|
+
return resolveGrokHomePath(configuredHome);
|
|
298
|
+
}
|
|
299
|
+
function absentPath() {
|
|
300
|
+
return NodePath2.join(
|
|
301
|
+
NodeOS.tmpdir(),
|
|
302
|
+
`ycodium-grok-no-auth-${NodeCrypto.randomUUID()}`,
|
|
303
|
+
"auth.json"
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
function ownEndpointAuthGuard(recipe) {
|
|
307
|
+
const connectivity = GROK_CARD.modelConnectivity;
|
|
308
|
+
const baseUrlKey = connectivity.baseUrlEnvKey;
|
|
309
|
+
if (baseUrlKey === void 0 || (recipe.environment[baseUrlKey]?.trim() ?? "") === "") return {};
|
|
310
|
+
const guard = {};
|
|
311
|
+
for (const entry of connectivity.extraEnv ?? []) {
|
|
312
|
+
if (entry.value === "$absentPath") guard[entry.name] = absentPath();
|
|
313
|
+
}
|
|
314
|
+
return guard;
|
|
315
|
+
}
|
|
316
|
+
function buildSignInEnv(recipe) {
|
|
317
|
+
const configuredHome = recipe.homePath;
|
|
318
|
+
const homeInjection = configuredHome.trim().length > 0 ? { [GROK_CARD.homeEnvVar]: resolveGrokHomePath(configuredHome) } : {};
|
|
319
|
+
return mergeLaunchEnv({
|
|
320
|
+
accountHome: homeInjection,
|
|
321
|
+
instanceTable: recipe.environment,
|
|
322
|
+
handOverrides: { GROK_OAUTH2_REFERRER: "ycodium" }
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
function buildSpawnEnv(recipe, resolvedHomePath, homeConfigured) {
|
|
326
|
+
const homeInjection = homeConfigured ? { [GROK_CARD.homeEnvVar]: resolvedHomePath } : {};
|
|
327
|
+
return mergeLaunchEnv({
|
|
328
|
+
accountHome: { ...homeInjection, ...ownEndpointAuthGuard(recipe) },
|
|
329
|
+
instanceTable: recipe.environment,
|
|
330
|
+
handOverrides: { GROK_OAUTH2_REFERRER: "ycodium" }
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
164
334
|
// src/grokInstance.ts
|
|
165
335
|
import * as NodeCrypto3 from "node:crypto";
|
|
166
336
|
import {
|
|
@@ -169,7 +339,7 @@ import {
|
|
|
169
339
|
import { nodeStreamsFromHandle as nodeStreamsFromHandle2 } from "@ycodium-ai/plugin-api/process-stdin";
|
|
170
340
|
|
|
171
341
|
// ../../packages/ycodium-acp-executor/src/executor.ts
|
|
172
|
-
import * as
|
|
342
|
+
import * as NodeCrypto2 from "node:crypto";
|
|
173
343
|
|
|
174
344
|
// ../../packages/ycodium-acp-executor/src/approvals.ts
|
|
175
345
|
function createApprovalGate(input2) {
|
|
@@ -397,7 +567,7 @@ var UnboundedEventStream = class {
|
|
|
397
567
|
};
|
|
398
568
|
|
|
399
569
|
// ../../packages/ycodium-acp-executor/src/config-options.ts
|
|
400
|
-
function
|
|
570
|
+
function isRecord2(value) {
|
|
401
571
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
402
572
|
}
|
|
403
573
|
function asString(value) {
|
|
@@ -416,7 +586,7 @@ function flattenChoices(rawOptions, currentValue) {
|
|
|
416
586
|
const out = [];
|
|
417
587
|
const seen = /* @__PURE__ */ new Set();
|
|
418
588
|
const push = (entry) => {
|
|
419
|
-
if (!
|
|
589
|
+
if (!isRecord2(entry)) return;
|
|
420
590
|
const value = asString(entry["value"]);
|
|
421
591
|
if (value === void 0 || seen.has(value)) return;
|
|
422
592
|
seen.add(value);
|
|
@@ -431,7 +601,7 @@ function flattenChoices(rawOptions, currentValue) {
|
|
|
431
601
|
});
|
|
432
602
|
};
|
|
433
603
|
for (const entry of rawOptions) {
|
|
434
|
-
if (
|
|
604
|
+
if (isRecord2(entry) && Array.isArray(entry["options"])) {
|
|
435
605
|
for (const nested of entry["options"]) push(nested);
|
|
436
606
|
continue;
|
|
437
607
|
}
|
|
@@ -440,7 +610,7 @@ function flattenChoices(rawOptions, currentValue) {
|
|
|
440
610
|
return out;
|
|
441
611
|
}
|
|
442
612
|
function isConfigOption(entry, configId) {
|
|
443
|
-
return
|
|
613
|
+
return isRecord2(entry) && asString(entry["id"])?.trim() === configId.trim();
|
|
444
614
|
}
|
|
445
615
|
function findConfigOptionEntry(configOptions, configId) {
|
|
446
616
|
return Array.isArray(configOptions) && configId.trim() !== "" ? configOptions.find(
|
|
@@ -455,7 +625,7 @@ function withConfigOptionValue(configOptions, configId, value) {
|
|
|
455
625
|
}
|
|
456
626
|
function pickEffortOption(configOptions) {
|
|
457
627
|
if (!Array.isArray(configOptions)) return void 0;
|
|
458
|
-
const candidates = configOptions.filter(
|
|
628
|
+
const candidates = configOptions.filter(isRecord2).filter((option) => normalizedField(option, "type") === "select").filter(looksLikeEffortOption);
|
|
459
629
|
return 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];
|
|
460
630
|
}
|
|
461
631
|
function findAcpEffortConfig(configOptions) {
|
|
@@ -475,7 +645,7 @@ function findAcpEffortConfig(configOptions) {
|
|
|
475
645
|
}
|
|
476
646
|
|
|
477
647
|
// ../../packages/ycodium-acp-executor/src/util.ts
|
|
478
|
-
function
|
|
648
|
+
function isRecord3(value) {
|
|
479
649
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
480
650
|
}
|
|
481
651
|
function asTrimmedString(value) {
|
|
@@ -530,11 +700,11 @@ function extractCommandFromTitle(title) {
|
|
|
530
700
|
return backtickMatch?.[1]?.trim() || void 0;
|
|
531
701
|
}
|
|
532
702
|
function extractToolCommand(data, title) {
|
|
533
|
-
const item =
|
|
534
|
-
const itemInput = item &&
|
|
535
|
-
const itemResult = item &&
|
|
536
|
-
const rawInput =
|
|
537
|
-
const dataInput =
|
|
703
|
+
const item = isRecord3(data?.["item"]) ? data["item"] : void 0;
|
|
704
|
+
const itemInput = item && isRecord3(item["input"]) ? item["input"] : void 0;
|
|
705
|
+
const itemResult = item && isRecord3(item["result"]) ? item["result"] : void 0;
|
|
706
|
+
const rawInput = isRecord3(data?.["rawInput"]) ? data["rawInput"] : void 0;
|
|
707
|
+
const dataInput = isRecord3(data?.["input"]) ? data["input"] : void 0;
|
|
538
708
|
const candidates = [
|
|
539
709
|
normalizeCommandValue(item?.["command"]),
|
|
540
710
|
normalizeCommandValue(itemInput?.["command"]),
|
|
@@ -579,7 +749,7 @@ function collectPaths(value, paths, seen, depth) {
|
|
|
579
749
|
}
|
|
580
750
|
return;
|
|
581
751
|
}
|
|
582
|
-
if (!
|
|
752
|
+
if (!isRecord3(value)) {
|
|
583
753
|
return;
|
|
584
754
|
}
|
|
585
755
|
for (const key of ["path", "filePath", "relativePath", "filename", "newPath", "oldPath"]) {
|
|
@@ -657,7 +827,7 @@ function deriveToolActivityPresentation(input2) {
|
|
|
657
827
|
const title = asTrimmedString(input2.title);
|
|
658
828
|
const detail = stripTrailingExitCode(asTrimmedString(input2.detail));
|
|
659
829
|
const fallbackSummary = asTrimmedString(input2.fallbackSummary) ?? "Tool";
|
|
660
|
-
const data =
|
|
830
|
+
const data = isRecord3(input2.data) ? input2.data : void 0;
|
|
661
831
|
const command = extractToolCommand(data, title);
|
|
662
832
|
const primaryPath = extractPrimaryPath(data);
|
|
663
833
|
const action = classifyToolAction({
|
|
@@ -689,7 +859,7 @@ function deriveToolActivityPresentation(input2) {
|
|
|
689
859
|
};
|
|
690
860
|
}
|
|
691
861
|
if (action === "search") {
|
|
692
|
-
const rawInput =
|
|
862
|
+
const rawInput = isRecord3(data?.["rawInput"]) ? data["rawInput"] : void 0;
|
|
693
863
|
const query = asTrimmedString(rawInput?.["query"]) ?? asTrimmedString(rawInput?.["pattern"]) ?? asTrimmedString(rawInput?.["searchTerm"]);
|
|
694
864
|
return {
|
|
695
865
|
summary: "Searched files",
|
|
@@ -749,7 +919,7 @@ function extractCommandFromTitle2(title) {
|
|
|
749
919
|
return match?.[1]?.trim() || void 0;
|
|
750
920
|
}
|
|
751
921
|
function extractToolCallCommand(rawInput, title) {
|
|
752
|
-
if (
|
|
922
|
+
if (isRecord3(rawInput)) {
|
|
753
923
|
const directCommand = normalizeCommandValue2(rawInput["command"]);
|
|
754
924
|
if (directCommand) {
|
|
755
925
|
return directCommand;
|
|
@@ -777,7 +947,7 @@ function boundTailText(text4, limit = TOOL_CALL_CONTENT_MAX_CHARS) {
|
|
|
777
947
|
var boundToolCallOutputText = (text4) => boundTailText(text4);
|
|
778
948
|
var RAW_OUTPUT_TEXT_FIELDS = ["content", "stdout", "stderr", "output"];
|
|
779
949
|
function boundToolCallRawOutput(rawOutput) {
|
|
780
|
-
if (!
|
|
950
|
+
if (!isRecord3(rawOutput)) {
|
|
781
951
|
return rawOutput;
|
|
782
952
|
}
|
|
783
953
|
let changed = false;
|
|
@@ -969,11 +1139,11 @@ function collectSessionConfigOptionValues(configOption) {
|
|
|
969
1139
|
);
|
|
970
1140
|
}
|
|
971
1141
|
function collectSessionModelIds(models) {
|
|
972
|
-
if (!
|
|
1142
|
+
if (!isRecord3(models) || !Array.isArray(models["availableModels"])) {
|
|
973
1143
|
return [];
|
|
974
1144
|
}
|
|
975
1145
|
return models["availableModels"].flatMap(
|
|
976
|
-
(model) =>
|
|
1146
|
+
(model) => isRecord3(model) && typeof model["modelId"] === "string" ? [model["modelId"]] : []
|
|
977
1147
|
);
|
|
978
1148
|
}
|
|
979
1149
|
function catalogModelLastSegment(value) {
|
|
@@ -1045,7 +1215,7 @@ function parseAvailableCommandsUpdate(params) {
|
|
|
1045
1215
|
}
|
|
1046
1216
|
const commands = [];
|
|
1047
1217
|
for (const command of availableCommands) {
|
|
1048
|
-
if (!
|
|
1218
|
+
if (!isRecord3(command)) {
|
|
1049
1219
|
continue;
|
|
1050
1220
|
}
|
|
1051
1221
|
const name = typeof command["name"] === "string" ? command["name"].trim() : "";
|
|
@@ -1053,7 +1223,7 @@ function parseAvailableCommandsUpdate(params) {
|
|
|
1053
1223
|
continue;
|
|
1054
1224
|
}
|
|
1055
1225
|
const description = typeof command["description"] === "string" ? command["description"].trim() || void 0 : void 0;
|
|
1056
|
-
const input2 =
|
|
1226
|
+
const input2 = isRecord3(command["input"]) ? command["input"] : void 0;
|
|
1057
1227
|
const inputHint = typeof input2?.["hint"] === "string" ? input2["hint"].trim() || void 0 : void 0;
|
|
1058
1228
|
commands.push({
|
|
1059
1229
|
name,
|
|
@@ -1107,7 +1277,7 @@ function boundToolCallRawPayload(params, update, toolCall) {
|
|
|
1107
1277
|
}
|
|
1108
1278
|
function textFromContentBlocks(blocks) {
|
|
1109
1279
|
const parts = blocks.flatMap(
|
|
1110
|
-
(block) =>
|
|
1280
|
+
(block) => isRecord3(block) && block["type"] === "text" && typeof block["text"] === "string" ? [block["text"]] : []
|
|
1111
1281
|
);
|
|
1112
1282
|
const joined = parts.join("");
|
|
1113
1283
|
return joined.trim().length > 0 ? joined : void 0;
|
|
@@ -1132,7 +1302,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
1132
1302
|
const entries = Array.isArray(upd["entries"]) ? upd["entries"] : [];
|
|
1133
1303
|
const plan = entries.map((entry, index) => ({
|
|
1134
1304
|
step: readAcpText(entry, "content") ?? `Step ${index + 1}`,
|
|
1135
|
-
status: normalizePlanStepStatus(
|
|
1305
|
+
status: normalizePlanStepStatus(isRecord3(entry) ? entry["status"] : void 0)
|
|
1136
1306
|
}));
|
|
1137
1307
|
if (plan.length > 0) {
|
|
1138
1308
|
events.push({
|
|
@@ -1172,7 +1342,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
1172
1342
|
}
|
|
1173
1343
|
case "agent_message_chunk":
|
|
1174
1344
|
case "agent_thought_chunk": {
|
|
1175
|
-
const content =
|
|
1345
|
+
const content = isRecord3(upd["content"]) ? upd["content"] : void 0;
|
|
1176
1346
|
const contentType = content?.["type"];
|
|
1177
1347
|
const streamKind = kind === "agent_thought_chunk" ? "reasoning_text" : "assistant_text";
|
|
1178
1348
|
if (contentType === "text") {
|
|
@@ -1212,7 +1382,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
1212
1382
|
}
|
|
1213
1383
|
case "compaction_summary_chunk": {
|
|
1214
1384
|
const compactionId = readAcpText(upd, "compactionId");
|
|
1215
|
-
const content =
|
|
1385
|
+
const content = isRecord3(upd["content"]) ? upd["content"] : void 0;
|
|
1216
1386
|
const text4 = content?.["type"] === "text" ? content["text"] : void 0;
|
|
1217
1387
|
if (compactionId === void 0 || typeof text4 !== "string" || text4.length === 0) break;
|
|
1218
1388
|
events.push({ _tag: "CompactionSummaryChunk", compactionId, text: text4 });
|
|
@@ -22906,17 +23076,17 @@ function isResponseMessage(value) {
|
|
|
22906
23076
|
function isNotificationMessage(value) {
|
|
22907
23077
|
return isJsonRpcEnvelope(value) && !("id" in value) && typeof value["method"] === "string";
|
|
22908
23078
|
}
|
|
22909
|
-
function
|
|
23079
|
+
function isRecord4(value) {
|
|
22910
23080
|
return typeof value === "object" && value !== null;
|
|
22911
23081
|
}
|
|
22912
23082
|
function isJsonRpcEnvelope(value) {
|
|
22913
|
-
return
|
|
23083
|
+
return isRecord4(value) && value["jsonrpc"] === "2.0";
|
|
22914
23084
|
}
|
|
22915
23085
|
function isJsonRpcId(value) {
|
|
22916
23086
|
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
22917
23087
|
}
|
|
22918
23088
|
function isResponseShapedMessage(value) {
|
|
22919
|
-
return
|
|
23089
|
+
return isRecord4(value) && !("method" in value) && ("id" in value || "result" in value || "error" in value);
|
|
22920
23090
|
}
|
|
22921
23091
|
function isResponseBatch(batch) {
|
|
22922
23092
|
let hasValidCall = false;
|
|
@@ -22926,7 +23096,7 @@ function isResponseBatch(batch) {
|
|
|
22926
23096
|
for (const entry of batch) {
|
|
22927
23097
|
hasValidCall ||= isRequestMessage(entry) || isNotificationMessage(entry);
|
|
22928
23098
|
hasValidResponse ||= isResponseMessage(entry);
|
|
22929
|
-
if (!
|
|
23099
|
+
if (!isRecord4(entry)) {
|
|
22930
23100
|
continue;
|
|
22931
23101
|
}
|
|
22932
23102
|
hasCallShape ||= "method" in entry;
|
|
@@ -22941,13 +23111,13 @@ function isResponseBatch(batch) {
|
|
|
22941
23111
|
return hasResponseShape && !hasCallShape;
|
|
22942
23112
|
}
|
|
22943
23113
|
function cancelRequestId(params) {
|
|
22944
|
-
if (!
|
|
23114
|
+
if (!isRecord4(params) || !isJsonRpcId(params["requestId"])) {
|
|
22945
23115
|
return void 0;
|
|
22946
23116
|
}
|
|
22947
23117
|
return params["requestId"];
|
|
22948
23118
|
}
|
|
22949
23119
|
function isErrorResponse(value) {
|
|
22950
|
-
return
|
|
23120
|
+
return isRecord4(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
|
|
22951
23121
|
}
|
|
22952
23122
|
var Handled = {
|
|
22953
23123
|
/**
|
|
@@ -23492,7 +23662,7 @@ var Connection = class {
|
|
|
23492
23662
|
if (this.abortController.signal.aborted) {
|
|
23493
23663
|
return Promise.resolve();
|
|
23494
23664
|
}
|
|
23495
|
-
if (!
|
|
23665
|
+
if (!isRecord4(message)) {
|
|
23496
23666
|
console.error("Invalid message", { message });
|
|
23497
23667
|
return Promise.resolve();
|
|
23498
23668
|
}
|
|
@@ -23895,7 +24065,7 @@ function ndJsonStream(output2, input2) {
|
|
|
23895
24065
|
await writeJson(protocolErrorResponse(RequestError.parseError()));
|
|
23896
24066
|
return;
|
|
23897
24067
|
}
|
|
23898
|
-
if (
|
|
24068
|
+
if (isRecord4(message) || Array.isArray(message)) {
|
|
23899
24069
|
controller.enqueue(message);
|
|
23900
24070
|
} else {
|
|
23901
24071
|
await writeJson(protocolErrorResponse(RequestError.invalidRequest(message)));
|
|
@@ -24882,14 +25052,14 @@ var legacyClientNotificationMethods = /* @__PURE__ */ new Set([
|
|
|
24882
25052
|
import * as NodeStream from "node:stream";
|
|
24883
25053
|
|
|
24884
25054
|
// ../../packages/ycodium-acp-executor/src/jsonrpc.ts
|
|
24885
|
-
function
|
|
25055
|
+
function isRecord5(value) {
|
|
24886
25056
|
return typeof value === "object" && value !== null;
|
|
24887
25057
|
}
|
|
24888
25058
|
function isJsonRpcId2(value) {
|
|
24889
25059
|
return typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
24890
25060
|
}
|
|
24891
25061
|
function isJsonRpcEnvelope2(value) {
|
|
24892
|
-
return
|
|
25062
|
+
return isRecord5(value) && value["jsonrpc"] === "2.0";
|
|
24893
25063
|
}
|
|
24894
25064
|
function isRequestMessage2(value) {
|
|
24895
25065
|
return isJsonRpcEnvelope2(value) && "id" in value && typeof value["method"] === "string" && isJsonRpcId2(value["id"]);
|
|
@@ -24909,7 +25079,7 @@ function isNotificationMessage2(value) {
|
|
|
24909
25079
|
return isJsonRpcEnvelope2(value) && !("id" in value) && typeof value["method"] === "string";
|
|
24910
25080
|
}
|
|
24911
25081
|
function readJsonRpcError(value) {
|
|
24912
|
-
if (!
|
|
25082
|
+
if (!isRecord5(value) || typeof value["code"] !== "number" || typeof value["message"] !== "string") {
|
|
24913
25083
|
return void 0;
|
|
24914
25084
|
}
|
|
24915
25085
|
return {
|
|
@@ -24982,11 +25152,11 @@ var KNOWN_SESSION_UPDATES = /* @__PURE__ */ new Set([
|
|
|
24982
25152
|
"compaction_summary_chunk"
|
|
24983
25153
|
]);
|
|
24984
25154
|
function isSessionUpdateEnvelope(payload) {
|
|
24985
|
-
if (!
|
|
25155
|
+
if (!isRecord5(payload) || typeof payload["sessionId"] !== "string") {
|
|
24986
25156
|
return false;
|
|
24987
25157
|
}
|
|
24988
25158
|
const update = payload["update"];
|
|
24989
|
-
return
|
|
25159
|
+
return isRecord5(update) && typeof update["sessionUpdate"] === "string";
|
|
24990
25160
|
}
|
|
24991
25161
|
function hasKnownVariantShape(update) {
|
|
24992
25162
|
const kind = update["sessionUpdate"];
|
|
@@ -24994,7 +25164,7 @@ function hasKnownVariantShape(update) {
|
|
|
24994
25164
|
return false;
|
|
24995
25165
|
}
|
|
24996
25166
|
if (kind === "user_message_chunk" || kind === "agent_message_chunk" || kind === "agent_thought_chunk") {
|
|
24997
|
-
return
|
|
25167
|
+
return isRecord5(update["content"]);
|
|
24998
25168
|
}
|
|
24999
25169
|
return true;
|
|
25000
25170
|
}
|
|
@@ -25400,7 +25570,7 @@ function forgetConfigOptionValue(state, configId) {
|
|
|
25400
25570
|
const forgetsModel = configId === void 0 || configId === state.modelConfigId;
|
|
25401
25571
|
const { currentModelReported: _forgottenReport, ...withoutReport } = state;
|
|
25402
25572
|
const configOptions = configId !== void 0 && Array.isArray(state.configOptions) ? state.configOptions.map((option) => {
|
|
25403
|
-
if (!
|
|
25573
|
+
if (!isRecord3(option) || option["id"] !== configId) return option;
|
|
25404
25574
|
const { currentValue: _forgotten, ...rest } = option;
|
|
25405
25575
|
return rest;
|
|
25406
25576
|
}) : state.configOptions;
|
|
@@ -25411,7 +25581,7 @@ function forgetConfigOptionValue(state, configId) {
|
|
|
25411
25581
|
};
|
|
25412
25582
|
}
|
|
25413
25583
|
function modelSelectionStateFromSetup(setup) {
|
|
25414
|
-
const sessionModels =
|
|
25584
|
+
const sessionModels = isRecord3(setup.models) ? setup.models : void 0;
|
|
25415
25585
|
const modelConfigId = extractModelConfigId(setup);
|
|
25416
25586
|
const strategy = modelConfigId !== void 0 ? "config-option" : "session/set_model";
|
|
25417
25587
|
const modelConfigOption = modelConfigId === void 0 ? void 0 : findSessionConfigOption(setup.configOptions, modelConfigId);
|
|
@@ -26121,6 +26291,7 @@ function createExecutorPrompt({
|
|
|
26121
26291
|
promptResults,
|
|
26122
26292
|
settleToolSubagents
|
|
26123
26293
|
}) {
|
|
26294
|
+
const ownOutcomes = /* @__PURE__ */ new Map();
|
|
26124
26295
|
const settleTurn = (input2) => {
|
|
26125
26296
|
if (!isLive(input2.expectedGeneration) || input2.record.finished) {
|
|
26126
26297
|
return false;
|
|
@@ -26137,14 +26308,22 @@ function createExecutorPrompt({
|
|
|
26137
26308
|
}
|
|
26138
26309
|
closeActiveAssistantSegment(input2.turnId);
|
|
26139
26310
|
shared.promptsInFlight = Math.max(0, shared.promptsInFlight - 1);
|
|
26140
|
-
if (shared.promptsInFlight !== 0 || shared.activeTurnId !== input2.turnId)
|
|
26311
|
+
if (shared.promptsInFlight !== 0 || shared.activeTurnId !== input2.turnId) {
|
|
26312
|
+
if (input2.foldedIn !== true) ownOutcomes.set(input2.turnId, input2);
|
|
26313
|
+
return false;
|
|
26314
|
+
}
|
|
26315
|
+
const outcome = (input2.foldedIn === true ? ownOutcomes.get(input2.turnId) : void 0) ?? input2;
|
|
26316
|
+
ownOutcomes.delete(input2.turnId);
|
|
26141
26317
|
shared.activeTurnId = void 0;
|
|
26142
26318
|
if (shared.status !== "disposed") {
|
|
26143
26319
|
shared.status = "ready";
|
|
26144
26320
|
}
|
|
26145
26321
|
const interrupted = promptResults.hasInterrupted(input2.turnId);
|
|
26146
26322
|
settleToolSubagents(
|
|
26147
|
-
toolSubagentSettlementOfTurn(
|
|
26323
|
+
toolSubagentSettlementOfTurn(
|
|
26324
|
+
interrupted ? "cancelled" : outcome.state,
|
|
26325
|
+
outcome.failureCategory
|
|
26326
|
+
),
|
|
26148
26327
|
input2.turnId
|
|
26149
26328
|
);
|
|
26150
26329
|
emit({
|
|
@@ -26154,10 +26333,10 @@ function createExecutorPrompt({
|
|
|
26154
26333
|
threadId: options.threadId,
|
|
26155
26334
|
turnId: input2.turnId,
|
|
26156
26335
|
payload: {
|
|
26157
|
-
state: interrupted ? "cancelled" :
|
|
26158
|
-
stopReason: interrupted ? "cancelled" :
|
|
26159
|
-
...
|
|
26160
|
-
...
|
|
26336
|
+
state: interrupted ? "cancelled" : outcome.state,
|
|
26337
|
+
stopReason: interrupted ? "cancelled" : outcome.stopReason,
|
|
26338
|
+
...outcome.errorMessage === void 0 ? {} : { errorMessage: outcome.errorMessage },
|
|
26339
|
+
...outcome.state === "failed" ? failureCategoryField(outcome.failureCategory) : {}
|
|
26161
26340
|
}
|
|
26162
26341
|
});
|
|
26163
26342
|
interruptedTurnIds.delete(input2.turnId);
|
|
@@ -26182,7 +26361,7 @@ function createExecutorPrompt({
|
|
|
26182
26361
|
return await promptRpc;
|
|
26183
26362
|
} else {
|
|
26184
26363
|
const { promise: early, resolve: settleEarly } = Promise.withResolvers();
|
|
26185
|
-
shared.
|
|
26364
|
+
shared.pendingSettlements.set(promptKey, {
|
|
26186
26365
|
promptKey,
|
|
26187
26366
|
sessionId,
|
|
26188
26367
|
settle: settleEarly,
|
|
@@ -26191,7 +26370,7 @@ function createExecutorPrompt({
|
|
|
26191
26370
|
onError: () => promptResults.reject(record4.promptId),
|
|
26192
26371
|
hasResult: () => record4.response !== void 0
|
|
26193
26372
|
}
|
|
26194
|
-
};
|
|
26373
|
+
});
|
|
26195
26374
|
try {
|
|
26196
26375
|
const outcome = await Promise.race([
|
|
26197
26376
|
promptRpc.then((value) => {
|
|
@@ -26204,7 +26383,7 @@ function createExecutorPrompt({
|
|
|
26204
26383
|
if (outcome.error !== void 0) throw outcome.error;
|
|
26205
26384
|
return outcome.response;
|
|
26206
26385
|
} finally {
|
|
26207
|
-
shared.
|
|
26386
|
+
shared.pendingSettlements.delete(promptKey);
|
|
26208
26387
|
void promptRpc.catch(() => void 0);
|
|
26209
26388
|
}
|
|
26210
26389
|
}
|
|
@@ -26354,7 +26533,9 @@ function createExecutorPrompt({
|
|
|
26354
26533
|
settle2({
|
|
26355
26534
|
turnId,
|
|
26356
26535
|
stopReason,
|
|
26357
|
-
state: response2.stopReason === "cancelled" ? "cancelled" : "completed"
|
|
26536
|
+
state: response2.stopReason === "cancelled" ? "cancelled" : "completed",
|
|
26537
|
+
// 立刻写出的插话没被打断却应答 cancelled:agent 把它并进了这一轮(grok 的 removedFromQueue)。
|
|
26538
|
+
foldedIn: response2.stopReason === "cancelled" && input2.expectedActiveTurnId !== void 0 && hooks.queuesPromptsWhileRunning === true
|
|
26358
26539
|
});
|
|
26359
26540
|
return {
|
|
26360
26541
|
threadId: options.threadId,
|
|
@@ -26363,7 +26544,8 @@ function createExecutorPrompt({
|
|
|
26363
26544
|
...response2.usage !== void 0 && response2.usage !== null ? { usage: response2.usage } : {}
|
|
26364
26545
|
};
|
|
26365
26546
|
};
|
|
26366
|
-
|
|
26547
|
+
const writesWhileRunning = input2.expectedActiveTurnId !== void 0 && hooks.queuesPromptsWhileRunning === true;
|
|
26548
|
+
if (!writesWhileRunning) await promptMutex.acquire();
|
|
26367
26549
|
let response;
|
|
26368
26550
|
try {
|
|
26369
26551
|
failIfDisposed();
|
|
@@ -26445,7 +26627,7 @@ function createExecutorPrompt({
|
|
|
26445
26627
|
await options.beforeApplyResult();
|
|
26446
26628
|
}
|
|
26447
26629
|
} finally {
|
|
26448
|
-
promptMutex.release();
|
|
26630
|
+
if (!writesWhileRunning) promptMutex.release();
|
|
26449
26631
|
notifyPromptSettled();
|
|
26450
26632
|
}
|
|
26451
26633
|
if (!isLive(started.generation)) {
|
|
@@ -26779,7 +26961,7 @@ function createExecutorRequests({
|
|
|
26779
26961
|
pendingUserInputs.delete(requestId);
|
|
26780
26962
|
pending.resolve({
|
|
26781
26963
|
kind: "answered",
|
|
26782
|
-
answers:
|
|
26964
|
+
answers: isRecord3(answers) ? answers : {}
|
|
26783
26965
|
});
|
|
26784
26966
|
};
|
|
26785
26967
|
return {
|
|
@@ -26793,7 +26975,7 @@ function createExecutorRequests({
|
|
|
26793
26975
|
}
|
|
26794
26976
|
|
|
26795
26977
|
// ../../packages/ycodium-acp-executor/src/artifacts.ts
|
|
26796
|
-
import * as
|
|
26978
|
+
import * as NodePath3 from "node:path";
|
|
26797
26979
|
import * as NodeURL from "node:url";
|
|
26798
26980
|
function resourceLinkArtifacts(content) {
|
|
26799
26981
|
if (content["type"] !== "resource_link" || typeof content["uri"] !== "string") return [];
|
|
@@ -26804,7 +26986,7 @@ function resourceLinkArtifacts(content) {
|
|
|
26804
26986
|
} catch {
|
|
26805
26987
|
return [];
|
|
26806
26988
|
}
|
|
26807
|
-
if (!
|
|
26989
|
+
if (!NodePath3.isAbsolute(path)) return [];
|
|
26808
26990
|
const name = typeof content["name"] === "string" ? content["name"].trim() : "";
|
|
26809
26991
|
const mimeType = typeof content["mimeType"] === "string" ? content["mimeType"].trim() : "";
|
|
26810
26992
|
return [
|
|
@@ -27078,18 +27260,18 @@ function modelRefreshFailedError(requestedModelId, error62) {
|
|
|
27078
27260
|
}
|
|
27079
27261
|
|
|
27080
27262
|
// ../../packages/ycodium-acp-executor/src/runtime-mode.ts
|
|
27081
|
-
function
|
|
27263
|
+
function isRecord6(value) {
|
|
27082
27264
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27083
27265
|
}
|
|
27084
27266
|
function asString2(value) {
|
|
27085
27267
|
return typeof value === "string" ? value : void 0;
|
|
27086
27268
|
}
|
|
27087
27269
|
function acpModeConfigId(setup) {
|
|
27088
|
-
if (!
|
|
27270
|
+
if (!isRecord6(setup)) return void 0;
|
|
27089
27271
|
const configOptions = setup["configOptions"];
|
|
27090
27272
|
if (!Array.isArray(configOptions)) return void 0;
|
|
27091
27273
|
for (const option of configOptions) {
|
|
27092
|
-
if (!
|
|
27274
|
+
if (!isRecord6(option)) continue;
|
|
27093
27275
|
if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
|
|
27094
27276
|
const id = asString2(option["id"])?.trim();
|
|
27095
27277
|
if (id) return id;
|
|
@@ -27488,28 +27670,29 @@ function createExecutorSettlement({
|
|
|
27488
27670
|
if (settledPromptKeys.length > SETTLED_PROMPT_KEY_LIMIT) settledPromptKeys.shift();
|
|
27489
27671
|
};
|
|
27490
27672
|
const abortPendingSettlement = (reason, failureCategory) => {
|
|
27491
|
-
const waiting
|
|
27492
|
-
|
|
27493
|
-
|
|
27494
|
-
|
|
27495
|
-
|
|
27496
|
-
|
|
27497
|
-
|
|
27498
|
-
|
|
27499
|
-
)
|
|
27500
|
-
}
|
|
27673
|
+
for (const [key, waiting] of shared.pendingSettlements) {
|
|
27674
|
+
if (waiting.hasResult?.()) continue;
|
|
27675
|
+
shared.pendingSettlements.delete(key);
|
|
27676
|
+
waiting.settle({
|
|
27677
|
+
error: withFailureCategory(
|
|
27678
|
+
new AcpExecutorRequestError("session/prompt", reason),
|
|
27679
|
+
failureCategory
|
|
27680
|
+
)
|
|
27681
|
+
});
|
|
27682
|
+
}
|
|
27501
27683
|
};
|
|
27502
27684
|
const settleFromNotification = (method, params) => {
|
|
27503
27685
|
const hook = hooks.promptSettlement;
|
|
27504
|
-
if (hook === void 0 || shared.
|
|
27686
|
+
if (hook === void 0 || shared.pendingSettlements.size === 0) return false;
|
|
27505
27687
|
const signal = hook.fromNotification(method, params);
|
|
27506
27688
|
if (signal === void 0) return false;
|
|
27507
|
-
const waiting = shared.
|
|
27508
|
-
|
|
27509
|
-
|
|
27510
|
-
|
|
27689
|
+
const waiting = signal.promptKey === void 0 ? [...shared.pendingSettlements.values()].find(
|
|
27690
|
+
(candidate) => candidate.sessionId === signal.sessionId
|
|
27691
|
+
) : shared.pendingSettlements.get(signal.promptKey);
|
|
27692
|
+
if (waiting === void 0 || waiting.sessionId !== signal.sessionId) {
|
|
27693
|
+
return signal.promptKey !== void 0 && settledPromptKeys.includes(signal.promptKey);
|
|
27511
27694
|
}
|
|
27512
|
-
shared.
|
|
27695
|
+
shared.pendingSettlements.delete(waiting.promptKey);
|
|
27513
27696
|
rememberSettledPromptKey(waiting.promptKey);
|
|
27514
27697
|
if (signal.outcome === "error") {
|
|
27515
27698
|
waiting.onError?.();
|
|
@@ -27536,14 +27719,14 @@ function createExecutorSettlement({
|
|
|
27536
27719
|
|
|
27537
27720
|
// ../../packages/ycodium-acp-executor/src/executor/subagent-sessions.ts
|
|
27538
27721
|
function parseState(raw) {
|
|
27539
|
-
if (!
|
|
27722
|
+
if (!isRecord3(raw)) return { status: void 0, error: void 0 };
|
|
27540
27723
|
const state = raw["state"];
|
|
27541
27724
|
if (state === "running") return { status: "running", error: void 0 };
|
|
27542
27725
|
if (state === "requires_action") return { status: "waiting", error: void 0 };
|
|
27543
27726
|
if (state !== "idle") return { status: void 0, error: void 0 };
|
|
27544
27727
|
const stopReason = raw["stopReason"];
|
|
27545
|
-
const error62 =
|
|
27546
|
-
if (stopReason === "error" ||
|
|
27728
|
+
const error62 = isRecord3(raw["error"]) ? asTrimmedString(raw["error"]["message"]) : void 0;
|
|
27729
|
+
if (stopReason === "error" || isRecord3(raw["error"])) return { status: "failed", error: error62 };
|
|
27547
27730
|
if (stopReason === "cancelled") return { status: "cancelled", error: void 0 };
|
|
27548
27731
|
return { status: "idle", error: void 0 };
|
|
27549
27732
|
}
|
|
@@ -27559,7 +27742,7 @@ function childLinkage(childId, record4) {
|
|
|
27559
27742
|
function createSubagentSessionTracker(registry2) {
|
|
27560
27743
|
const observe = (notification, ctx) => {
|
|
27561
27744
|
const update = notification.update;
|
|
27562
|
-
if (!
|
|
27745
|
+
if (!isRecord3(update) || update["sessionUpdate"] !== "subagent_update") return [];
|
|
27563
27746
|
const childId = asTrimmedString(update["sessionId"]);
|
|
27564
27747
|
if (childId === void 0 || ctx.ownSessionIds.has(childId)) return [];
|
|
27565
27748
|
const outerId = notification.sessionId;
|
|
@@ -27984,9 +28167,9 @@ function readOpenToolCalls(toolCalls, turnId) {
|
|
|
27984
28167
|
}
|
|
27985
28168
|
|
|
27986
28169
|
// ../../packages/ycodium-acp-executor/src/protocol-log.ts
|
|
27987
|
-
import * as
|
|
27988
|
-
import * as
|
|
27989
|
-
import * as
|
|
28170
|
+
import * as NodeFS2 from "node:fs";
|
|
28171
|
+
import * as NodeOS2 from "node:os";
|
|
28172
|
+
import * as NodePath4 from "node:path";
|
|
27990
28173
|
var DEFAULT_MAX_BYTES = 8 * 1024 * 1024;
|
|
27991
28174
|
var UNSAFE_FILE_CHARS = /[^A-Za-z0-9._-]+/gu;
|
|
27992
28175
|
function safeFileName(value) {
|
|
@@ -27994,12 +28177,12 @@ function safeFileName(value) {
|
|
|
27994
28177
|
}
|
|
27995
28178
|
function createAcpProtocolLogFile(input2) {
|
|
27996
28179
|
const maxBytes = input2.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
27997
|
-
|
|
27998
|
-
const filePath =
|
|
28180
|
+
NodeFS2.mkdirSync(input2.directory, { recursive: true });
|
|
28181
|
+
const filePath = NodePath4.join(
|
|
27999
28182
|
input2.directory,
|
|
28000
28183
|
`${safeFileName(input2.provider)}-${safeFileName(input2.threadId)}-${Date.now().toString(36)}.ndjson`
|
|
28001
28184
|
);
|
|
28002
|
-
const stream = (input2.openStream ?? ((path) =>
|
|
28185
|
+
const stream = (input2.openStream ?? ((path) => NodeFS2.createWriteStream(path, { flags: "a" })))(
|
|
28003
28186
|
filePath
|
|
28004
28187
|
);
|
|
28005
28188
|
let bytes = 0;
|
|
@@ -28051,7 +28234,7 @@ function createAcpProtocolLogFromEnv(input2) {
|
|
|
28051
28234
|
const flag = process.env.YCODIUM_ACP_PROTOCOL_LOG;
|
|
28052
28235
|
if (flag !== "1" && flag?.toLowerCase() !== "true") return void 0;
|
|
28053
28236
|
const configured = process.env.YCODIUM_ACP_PROTOCOL_LOG_DIR?.trim();
|
|
28054
|
-
const directory = configured && configured.length > 0 ? configured :
|
|
28237
|
+
const directory = configured && configured.length > 0 ? configured : NodePath4.join(NodeOS2.tmpdir(), "ycodium-acp-protocol");
|
|
28055
28238
|
try {
|
|
28056
28239
|
const sink = createAcpProtocolLogFile({
|
|
28057
28240
|
directory,
|
|
@@ -28075,7 +28258,7 @@ function defaultNowIso() {
|
|
|
28075
28258
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
28076
28259
|
}
|
|
28077
28260
|
function defaultRandomId() {
|
|
28078
|
-
return
|
|
28261
|
+
return NodeCrypto2.randomUUID();
|
|
28079
28262
|
}
|
|
28080
28263
|
function createAcpExecutor(options) {
|
|
28081
28264
|
const hooks = { ...defaultVendorHooks, ...options.hooks };
|
|
@@ -28103,7 +28286,7 @@ function createAcpExecutor(options) {
|
|
|
28103
28286
|
startInFlight: void 0,
|
|
28104
28287
|
activeTurnId: void 0,
|
|
28105
28288
|
promptsInFlight: 0,
|
|
28106
|
-
|
|
28289
|
+
pendingSettlements: /* @__PURE__ */ new Map(),
|
|
28107
28290
|
manualCompaction: void 0,
|
|
28108
28291
|
assistantSegment: { nextSegmentIndex: 0 },
|
|
28109
28292
|
modeState: void 0,
|
|
@@ -28671,28 +28854,28 @@ var MAX_VERSION_OUTPUT_BYTES = 64 * 1024;
|
|
|
28671
28854
|
|
|
28672
28855
|
// src/config.ts
|
|
28673
28856
|
var GROK_DEFAULT_LAUNCH_ARGS = "agent stdio";
|
|
28674
|
-
function
|
|
28857
|
+
function isRecord7(value) {
|
|
28675
28858
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28676
28859
|
}
|
|
28677
|
-
function
|
|
28860
|
+
function readString2(value) {
|
|
28678
28861
|
return typeof value === "string" ? value : "";
|
|
28679
28862
|
}
|
|
28680
28863
|
function readTrimmed(value) {
|
|
28681
|
-
return
|
|
28864
|
+
return readString2(value).trim();
|
|
28682
28865
|
}
|
|
28683
28866
|
function readEnvironment(value) {
|
|
28684
28867
|
if (!Array.isArray(value)) return {};
|
|
28685
28868
|
const env = {};
|
|
28686
28869
|
for (const entry of value) {
|
|
28687
|
-
if (!
|
|
28870
|
+
if (!isRecord7(entry)) continue;
|
|
28688
28871
|
const name = readTrimmed(entry["name"]);
|
|
28689
28872
|
if (name.length === 0) continue;
|
|
28690
|
-
env[name] =
|
|
28873
|
+
env[name] = readString2(entry["value"]);
|
|
28691
28874
|
}
|
|
28692
28875
|
return env;
|
|
28693
28876
|
}
|
|
28694
28877
|
function parseGrokInstanceConfig(config2) {
|
|
28695
|
-
if (!
|
|
28878
|
+
if (!isRecord7(config2)) {
|
|
28696
28879
|
return {
|
|
28697
28880
|
binaryPath: "",
|
|
28698
28881
|
launchArgs: GROK_DEFAULT_LAUNCH_ARGS,
|
|
@@ -28702,11 +28885,11 @@ function parseGrokInstanceConfig(config2) {
|
|
|
28702
28885
|
envelopeDriver: void 0
|
|
28703
28886
|
};
|
|
28704
28887
|
}
|
|
28705
|
-
const nested =
|
|
28888
|
+
const nested = isRecord7(config2["config"]) ? config2["config"] : void 0;
|
|
28706
28889
|
const settings = nested ?? config2;
|
|
28707
28890
|
return {
|
|
28708
28891
|
binaryPath: readTrimmed(settings["binaryPath"]),
|
|
28709
|
-
launchArgs:
|
|
28892
|
+
launchArgs: readString2(settings["launchArgs"]) || GROK_DEFAULT_LAUNCH_ARGS,
|
|
28710
28893
|
homePath: readTrimmed(settings["homePath"]) || readTrimmed(config2["homePath"]),
|
|
28711
28894
|
homeEnvVar: readTrimmed(settings["homeEnvVar"]) || readTrimmed(config2["homeEnvVar"]),
|
|
28712
28895
|
environment: readEnvironment(config2["environment"]),
|
|
@@ -28830,166 +29013,6 @@ function readDeviceCodeOutput(stdout, onText) {
|
|
|
28830
29013
|
return { text: text4, code };
|
|
28831
29014
|
}
|
|
28832
29015
|
|
|
28833
|
-
// src/grokHome.ts
|
|
28834
|
-
import * as NodeCrypto2 from "node:crypto";
|
|
28835
|
-
import * as NodeOS2 from "node:os";
|
|
28836
|
-
import * as NodePath4 from "node:path";
|
|
28837
|
-
import { mergeLaunchEnv } from "@ycodium-ai/plugin-api/executor";
|
|
28838
|
-
|
|
28839
|
-
// src/grokAccount.ts
|
|
28840
|
-
import * as NodeFS2 from "node:fs";
|
|
28841
|
-
import * as NodePath3 from "node:path";
|
|
28842
|
-
var AUTH_FILE_NAME = "auth.json";
|
|
28843
|
-
var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28844
|
-
var readString2 = (record4, key) => {
|
|
28845
|
-
const value = record4[key];
|
|
28846
|
-
if (typeof value !== "string") return void 0;
|
|
28847
|
-
const trimmed3 = value.trim();
|
|
28848
|
-
return trimmed3.length > 0 ? trimmed3 : void 0;
|
|
28849
|
-
};
|
|
28850
|
-
var parseJsonRecord = (raw) => {
|
|
28851
|
-
let parsed;
|
|
28852
|
-
try {
|
|
28853
|
-
parsed = JSON.parse(raw);
|
|
28854
|
-
} catch {
|
|
28855
|
-
return void 0;
|
|
28856
|
-
}
|
|
28857
|
-
return isRecord7(parsed) ? parsed : void 0;
|
|
28858
|
-
};
|
|
28859
|
-
var directoryExists = (homePath) => {
|
|
28860
|
-
try {
|
|
28861
|
-
return NodeFS2.statSync(homePath).isDirectory();
|
|
28862
|
-
} catch {
|
|
28863
|
-
return false;
|
|
28864
|
-
}
|
|
28865
|
-
};
|
|
28866
|
-
var readCredentialFile = (path) => {
|
|
28867
|
-
try {
|
|
28868
|
-
return NodeFS2.readFileSync(path, "utf8");
|
|
28869
|
-
} catch {
|
|
28870
|
-
return void 0;
|
|
28871
|
-
}
|
|
28872
|
-
};
|
|
28873
|
-
var signedOutProbe = (exists) => ({
|
|
28874
|
-
state: "signed-out",
|
|
28875
|
-
directoryExists: exists,
|
|
28876
|
-
email: void 0,
|
|
28877
|
-
name: void 0,
|
|
28878
|
-
expiresAt: void 0
|
|
28879
|
-
});
|
|
28880
|
-
var unreadableProbe = (exists) => ({
|
|
28881
|
-
state: "unreadable",
|
|
28882
|
-
directoryExists: exists,
|
|
28883
|
-
email: void 0,
|
|
28884
|
-
name: void 0,
|
|
28885
|
-
expiresAt: void 0
|
|
28886
|
-
});
|
|
28887
|
-
var joinName = (record4) => {
|
|
28888
|
-
const first = readString2(record4, "first_name");
|
|
28889
|
-
const last = readString2(record4, "last_name");
|
|
28890
|
-
const joined = [first, last].filter((part) => part !== void 0).join(" ");
|
|
28891
|
-
return joined.length > 0 ? joined : void 0;
|
|
28892
|
-
};
|
|
28893
|
-
var findIdentityEntry = (parsed) => {
|
|
28894
|
-
for (const value of Object.values(parsed)) {
|
|
28895
|
-
if (!isRecord7(value)) continue;
|
|
28896
|
-
if (readString2(value, "email") !== void 0 || readString2(value, "user_id") !== void 0) {
|
|
28897
|
-
return value;
|
|
28898
|
-
}
|
|
28899
|
-
}
|
|
28900
|
-
return void 0;
|
|
28901
|
-
};
|
|
28902
|
-
var isExpired = (expiresAt, nowMs) => {
|
|
28903
|
-
if (expiresAt === void 0) return false;
|
|
28904
|
-
const parsed = Date.parse(expiresAt);
|
|
28905
|
-
return Number.isNaN(parsed) ? false : parsed <= nowMs;
|
|
28906
|
-
};
|
|
28907
|
-
var readGrokAccount = (homePath) => {
|
|
28908
|
-
const exists = directoryExists(homePath);
|
|
28909
|
-
const raw = readCredentialFile(NodePath3.join(homePath, AUTH_FILE_NAME));
|
|
28910
|
-
if (raw === void 0) return signedOutProbe(exists);
|
|
28911
|
-
const parsed = parseJsonRecord(raw);
|
|
28912
|
-
const identity = parsed === void 0 ? void 0 : findIdentityEntry(parsed);
|
|
28913
|
-
if (identity === void 0) return unreadableProbe(exists);
|
|
28914
|
-
const expiresAt = readString2(identity, "expires_at");
|
|
28915
|
-
return {
|
|
28916
|
-
state: isExpired(expiresAt, Date.now()) ? "expired" : "signed-in",
|
|
28917
|
-
directoryExists: exists,
|
|
28918
|
-
email: readString2(identity, "email"),
|
|
28919
|
-
name: joinName(identity),
|
|
28920
|
-
expiresAt
|
|
28921
|
-
};
|
|
28922
|
-
};
|
|
28923
|
-
|
|
28924
|
-
// src/grokHome.ts
|
|
28925
|
-
function expandHomePath(value) {
|
|
28926
|
-
if (value === "~") return NodeOS2.homedir();
|
|
28927
|
-
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
28928
|
-
return NodePath4.join(NodeOS2.homedir(), value.slice(2));
|
|
28929
|
-
}
|
|
28930
|
-
return value;
|
|
28931
|
-
}
|
|
28932
|
-
function resolveGrokHomePath(value) {
|
|
28933
|
-
const trimmed3 = value.trim();
|
|
28934
|
-
if (trimmed3.length === 0) return NodePath4.join(NodeOS2.homedir(), ".grok");
|
|
28935
|
-
return NodePath4.resolve(expandHomePath(trimmed3));
|
|
28936
|
-
}
|
|
28937
|
-
function probeGrokAccount(accountPath) {
|
|
28938
|
-
const resolved = resolveGrokHomePath(accountPath);
|
|
28939
|
-
const account = readGrokAccount(resolved);
|
|
28940
|
-
return {
|
|
28941
|
-
accountPath: resolved,
|
|
28942
|
-
state: account.state,
|
|
28943
|
-
...account.email === void 0 ? {} : { email: account.email },
|
|
28944
|
-
...account.name === void 0 ? {} : { name: account.name },
|
|
28945
|
-
...account.expiresAt === void 0 ? {} : { expiresAt: account.expiresAt }
|
|
28946
|
-
};
|
|
28947
|
-
}
|
|
28948
|
-
function grokContinuationKey(recipe) {
|
|
28949
|
-
return `grok:home:${resolveGrokHomePath(recipe.homePath)}`;
|
|
28950
|
-
}
|
|
28951
|
-
function resolveAccountHomePath(recipe, configuredHome) {
|
|
28952
|
-
const fromEnvironment = recipe.environment["GROK_HOME"]?.trim();
|
|
28953
|
-
if (fromEnvironment !== void 0 && fromEnvironment.length > 0) {
|
|
28954
|
-
return NodePath4.resolve(expandHomePath(fromEnvironment));
|
|
28955
|
-
}
|
|
28956
|
-
return resolveGrokHomePath(configuredHome);
|
|
28957
|
-
}
|
|
28958
|
-
function absentPath() {
|
|
28959
|
-
return NodePath4.join(
|
|
28960
|
-
NodeOS2.tmpdir(),
|
|
28961
|
-
`ycodium-grok-no-auth-${NodeCrypto2.randomUUID()}`,
|
|
28962
|
-
"auth.json"
|
|
28963
|
-
);
|
|
28964
|
-
}
|
|
28965
|
-
function ownEndpointAuthGuard(recipe) {
|
|
28966
|
-
const connectivity = GROK_CARD.modelConnectivity;
|
|
28967
|
-
const baseUrlKey = connectivity.baseUrlEnvKey;
|
|
28968
|
-
if (baseUrlKey === void 0 || (recipe.environment[baseUrlKey]?.trim() ?? "") === "") return {};
|
|
28969
|
-
const guard = {};
|
|
28970
|
-
for (const entry of connectivity.extraEnv ?? []) {
|
|
28971
|
-
if (entry.value === "$absentPath") guard[entry.name] = absentPath();
|
|
28972
|
-
}
|
|
28973
|
-
return guard;
|
|
28974
|
-
}
|
|
28975
|
-
function buildSignInEnv(recipe) {
|
|
28976
|
-
const configuredHome = recipe.homePath;
|
|
28977
|
-
const homeInjection = configuredHome.trim().length > 0 ? { [GROK_CARD.homeEnvVar]: resolveGrokHomePath(configuredHome) } : {};
|
|
28978
|
-
return mergeLaunchEnv({
|
|
28979
|
-
accountHome: homeInjection,
|
|
28980
|
-
instanceTable: recipe.environment,
|
|
28981
|
-
handOverrides: { GROK_OAUTH2_REFERRER: "ycodium" }
|
|
28982
|
-
});
|
|
28983
|
-
}
|
|
28984
|
-
function buildSpawnEnv(recipe, resolvedHomePath, homeConfigured) {
|
|
28985
|
-
const homeInjection = homeConfigured ? { [GROK_CARD.homeEnvVar]: resolvedHomePath } : {};
|
|
28986
|
-
return mergeLaunchEnv({
|
|
28987
|
-
accountHome: { ...homeInjection, ...ownEndpointAuthGuard(recipe) },
|
|
28988
|
-
instanceTable: recipe.environment,
|
|
28989
|
-
handOverrides: { GROK_OAUTH2_REFERRER: "ycodium" }
|
|
28990
|
-
});
|
|
28991
|
-
}
|
|
28992
|
-
|
|
28993
29016
|
// src/grokSignIn.ts
|
|
28994
29017
|
function makeGrokSignIn(input2) {
|
|
28995
29018
|
const { host, recipe } = input2;
|
|
@@ -29231,30 +29254,38 @@ var grokTurnUsageReport = (promptResponse) => {
|
|
|
29231
29254
|
...sessionId === void 0 ? {} : { sessionId }
|
|
29232
29255
|
};
|
|
29233
29256
|
};
|
|
29257
|
+
var mergeReports = (left, right) => {
|
|
29258
|
+
if (left === void 0 || right === void 0) return left ?? right;
|
|
29259
|
+
const totals = {
|
|
29260
|
+
uncachedInputTokens: left.totals.uncachedInputTokens + right.totals.uncachedInputTokens,
|
|
29261
|
+
cachedInputTokens: left.totals.cachedInputTokens + right.totals.cachedInputTokens,
|
|
29262
|
+
cacheCreationTokens: left.totals.cacheCreationTokens + right.totals.cacheCreationTokens,
|
|
29263
|
+
outputTokens: left.totals.outputTokens + right.totals.outputTokens,
|
|
29264
|
+
reasoningTokens: left.totals.reasoningTokens + right.totals.reasoningTokens
|
|
29265
|
+
};
|
|
29266
|
+
const larger = sumOf(left.totals) >= sumOf(right.totals) ? left : right;
|
|
29267
|
+
return { ...larger, totals };
|
|
29268
|
+
};
|
|
29234
29269
|
var createGrokTurnUsageCollector = (base) => {
|
|
29235
29270
|
const pastKeys = [];
|
|
29236
|
-
|
|
29237
|
-
|
|
29238
|
-
let
|
|
29271
|
+
const turn = /* @__PURE__ */ new Map();
|
|
29272
|
+
const answered = /* @__PURE__ */ new Set();
|
|
29273
|
+
let latestKey;
|
|
29239
29274
|
let wake;
|
|
29240
|
-
const
|
|
29241
|
-
seen = true;
|
|
29242
|
-
wake?.();
|
|
29243
|
-
};
|
|
29275
|
+
const allAnswered = () => [...turn.keys()].every((key) => answered.has(key));
|
|
29244
29276
|
const observe = (response) => {
|
|
29245
|
-
const key = base.responseKey?.(response);
|
|
29246
|
-
if (key
|
|
29247
|
-
|
|
29248
|
-
|
|
29277
|
+
const key = base.responseKey?.(response) ?? latestKey;
|
|
29278
|
+
if (key === void 0) return;
|
|
29279
|
+
if (!turn.has(key) && pastKeys.includes(key)) return;
|
|
29280
|
+
turn.set(key, grokTurnUsageReport(response) ?? turn.get(key));
|
|
29281
|
+
answered.add(key);
|
|
29282
|
+
if (allAnswered()) wake?.();
|
|
29249
29283
|
};
|
|
29250
29284
|
const settlement = {
|
|
29251
29285
|
...base,
|
|
29252
29286
|
requestFields: (key) => {
|
|
29253
|
-
|
|
29254
|
-
|
|
29255
|
-
promptKey = key;
|
|
29256
|
-
report = void 0;
|
|
29257
|
-
seen = false;
|
|
29287
|
+
turn.set(key, void 0);
|
|
29288
|
+
latestKey = key;
|
|
29258
29289
|
return base.requestFields(key);
|
|
29259
29290
|
},
|
|
29260
29291
|
responseKey: (response) => {
|
|
@@ -29264,7 +29295,7 @@ var createGrokTurnUsageCollector = (base) => {
|
|
|
29264
29295
|
};
|
|
29265
29296
|
const attach = async (event) => {
|
|
29266
29297
|
if (event.type !== "turn.completed" || !isRecord8(event.payload)) return event;
|
|
29267
|
-
if (event.payload["state"] === "completed" && !
|
|
29298
|
+
if (event.payload["state"] === "completed" && !allAnswered()) {
|
|
29268
29299
|
await new Promise((resolve2) => {
|
|
29269
29300
|
const timer = setTimeout(resolve2, USAGE_GRACE_MS);
|
|
29270
29301
|
wake = () => {
|
|
@@ -29274,8 +29305,12 @@ var createGrokTurnUsageCollector = (base) => {
|
|
|
29274
29305
|
});
|
|
29275
29306
|
wake = void 0;
|
|
29276
29307
|
}
|
|
29277
|
-
|
|
29278
|
-
report =
|
|
29308
|
+
let taken;
|
|
29309
|
+
for (const report of turn.values()) taken = mergeReports(taken, report);
|
|
29310
|
+
for (const key of turn.keys()) pastKeys.push(key);
|
|
29311
|
+
while (pastKeys.length > 16) pastKeys.shift();
|
|
29312
|
+
turn.clear();
|
|
29313
|
+
answered.clear();
|
|
29279
29314
|
return taken === void 0 ? event : { ...event, payload: { ...event.payload, tokenUsage: taken } };
|
|
29280
29315
|
};
|
|
29281
29316
|
return { settlement, attach };
|
|
@@ -30482,6 +30517,55 @@ function createGrokModelCatalog(input2) {
|
|
|
30482
30517
|
return { readCliVersion, refreshModelCatalog, refreshForSend };
|
|
30483
30518
|
}
|
|
30484
30519
|
|
|
30520
|
+
// src/grokFollowUpSteer.ts
|
|
30521
|
+
import * as NodeFS5 from "node:fs";
|
|
30522
|
+
import * as NodePath8 from "node:path";
|
|
30523
|
+
var SETTING = 'follow_up_behavior = "steer"';
|
|
30524
|
+
function grokFollowUpSteerIsOn(text4) {
|
|
30525
|
+
const lines = text4.split(/\r?\n/).map((line) => line.trim());
|
|
30526
|
+
const headers = lines.flatMap((line, index) => line === "[ui]" ? [index] : []);
|
|
30527
|
+
const header = headers[0];
|
|
30528
|
+
if (headers.length !== 1 || header === void 0) return false;
|
|
30529
|
+
for (const line of lines.slice(header + 1)) {
|
|
30530
|
+
if (line.startsWith("[")) return false;
|
|
30531
|
+
if (line === SETTING) return true;
|
|
30532
|
+
}
|
|
30533
|
+
return false;
|
|
30534
|
+
}
|
|
30535
|
+
function ensureGrokFollowUpSteer(homePath) {
|
|
30536
|
+
const path = NodePath8.join(homePath, "config.toml");
|
|
30537
|
+
try {
|
|
30538
|
+
return grokFollowUpSteerIsOn(NodeFS5.readFileSync(path, "utf8")) ? "on" : "off";
|
|
30539
|
+
} catch (error62) {
|
|
30540
|
+
if (error62.code !== "ENOENT") throw error62;
|
|
30541
|
+
}
|
|
30542
|
+
NodeFS5.mkdirSync(homePath, { recursive: true });
|
|
30543
|
+
try {
|
|
30544
|
+
NodeFS5.writeFileSync(path, `[ui]
|
|
30545
|
+
${SETTING}
|
|
30546
|
+
`, { encoding: "utf8", flag: "wx" });
|
|
30547
|
+
return "created";
|
|
30548
|
+
} catch (error62) {
|
|
30549
|
+
if (error62.code !== "EEXIST") throw error62;
|
|
30550
|
+
return grokFollowUpSteerIsOn(NodeFS5.readFileSync(path, "utf8")) ? "on" : "off";
|
|
30551
|
+
}
|
|
30552
|
+
}
|
|
30553
|
+
function prepareGrokFollowUpSteer(homePath, log, threadId) {
|
|
30554
|
+
try {
|
|
30555
|
+
if (ensureGrokFollowUpSteer(homePath) === "off" && threadId !== void 0) {
|
|
30556
|
+
log.info(
|
|
30557
|
+
"grok follow-up steering is off in config.toml; mid-turn messages run after the current request",
|
|
30558
|
+
{ threadId }
|
|
30559
|
+
);
|
|
30560
|
+
}
|
|
30561
|
+
} catch (error62) {
|
|
30562
|
+
log.warn("could not read or create the grok config", {
|
|
30563
|
+
...threadId === void 0 ? {} : { threadId },
|
|
30564
|
+
cause: error62 instanceof Error ? error62.message : String(error62)
|
|
30565
|
+
});
|
|
30566
|
+
}
|
|
30567
|
+
}
|
|
30568
|
+
|
|
30485
30569
|
// src/grokInstance.ts
|
|
30486
30570
|
var RESUME_SCHEMA_VERSION = 1;
|
|
30487
30571
|
var yieldTick = () => new Promise((resolve2) => {
|
|
@@ -30596,6 +30680,7 @@ var createGrokInstance = (config2, host) => {
|
|
|
30596
30680
|
detail: "Grok program path is not configured"
|
|
30597
30681
|
};
|
|
30598
30682
|
}
|
|
30683
|
+
prepareGrokFollowUpSteer(resolveAccountHomePath(recipe, recipe.homePath), host.log);
|
|
30599
30684
|
const env = spawnEnv();
|
|
30600
30685
|
const version2 = await raceAbort3(modelCatalog.readCliVersion(signal), signal);
|
|
30601
30686
|
if (signal?.aborted) throw new Error("aborted");
|
|
@@ -30684,6 +30769,11 @@ var createGrokInstance = (config2, host) => {
|
|
|
30684
30769
|
if (disposed) throw new Error("instance disposed");
|
|
30685
30770
|
throwIfStartAborted(signal);
|
|
30686
30771
|
}
|
|
30772
|
+
prepareGrokFollowUpSteer(
|
|
30773
|
+
resolveAccountHomePath(recipe, recipe.homePath),
|
|
30774
|
+
host.log,
|
|
30775
|
+
input2.threadId
|
|
30776
|
+
);
|
|
30687
30777
|
const env = spawnEnv();
|
|
30688
30778
|
const effort = modelSelectionStringOption(input2.modelSelection, GROK_REASONING_OPTION_ID);
|
|
30689
30779
|
const baseArgs = tokenizeLaunchArgs(recipe.launchArgs);
|
|
@@ -30730,6 +30820,8 @@ var createGrokInstance = (config2, host) => {
|
|
|
30730
30820
|
authMethodId: resolveGrokAuthMethodId,
|
|
30731
30821
|
hooks: {
|
|
30732
30822
|
promptSettlement: turnUsage.settlement,
|
|
30823
|
+
// 运行中再收到的 prompt 由 grok 自己排队、在下一个工具调用结束时并进这一轮(配合上面写的配置)。
|
|
30824
|
+
queuesPromptsWhileRunning: true,
|
|
30733
30825
|
modelDefaultEffort: grokModelDefaultEffort,
|
|
30734
30826
|
// 派发子 agent 的调用由子 agent 名单接管,不再画成普通工具。
|
|
30735
30827
|
onToolCallUpdated: (update) => ({
|
|
@@ -30961,6 +31053,7 @@ var createGrokInstance = (config2, host) => {
|
|
|
30961
31053
|
var executors = [
|
|
30962
31054
|
{
|
|
30963
31055
|
card: GROK_CARD,
|
|
31056
|
+
lifecycle: [{ kind: "detect", reversible: true }],
|
|
30964
31057
|
createInstance: async (config2, host) => {
|
|
30965
31058
|
host.log.info("createInstance");
|
|
30966
31059
|
return createGrokInstance(config2, host);
|
|
@@ -30970,9 +31063,26 @@ var executors = [
|
|
|
30970
31063
|
];
|
|
30971
31064
|
var index_default = definePlugin({
|
|
30972
31065
|
id: "agent-grok",
|
|
30973
|
-
apiVersion:
|
|
31066
|
+
apiVersion: 60,
|
|
30974
31067
|
executors,
|
|
30975
31068
|
activate(ctx) {
|
|
31069
|
+
ctx.command({
|
|
31070
|
+
name: "effectiveConfig",
|
|
31071
|
+
description: "Settings form: the account directory an empty path resolves to on this machine.",
|
|
31072
|
+
scope: "read",
|
|
31073
|
+
payloadSchema: EXECUTOR_EFFECTIVE_PAYLOAD_SCHEMA,
|
|
31074
|
+
handle: async (payload) => {
|
|
31075
|
+
const request = readExecutorEffectiveRequest(payload);
|
|
31076
|
+
return {
|
|
31077
|
+
homePath: executorHomeEffectiveValue(
|
|
31078
|
+
"GROK_HOME",
|
|
31079
|
+
request,
|
|
31080
|
+
process.env,
|
|
31081
|
+
(value) => resolveGrokHomePath(value ?? "")
|
|
31082
|
+
)
|
|
31083
|
+
};
|
|
31084
|
+
}
|
|
31085
|
+
});
|
|
30976
31086
|
ctx.log.info("grok executor ready");
|
|
30977
31087
|
}
|
|
30978
31088
|
});
|
package/locales/en.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"presentation": {
|
|
3
|
+
"name": "Grok",
|
|
4
|
+
"description": "Use Grok in Ycodium and pick up earlier sessions where they left off."
|
|
5
|
+
},
|
|
2
6
|
"form": {
|
|
3
7
|
"binaryPath": {
|
|
4
8
|
"title": "Program path",
|
|
@@ -9,6 +13,11 @@
|
|
|
9
13
|
"title": "Account directory",
|
|
10
14
|
"description": "Sessions and the `grok login` credentials live here, so providers sharing this directory can pick up each other's threads and providers with different directories cannot. Leave empty to use the CLI's default (~/.grok).",
|
|
11
15
|
"placeholder": "e.g. ~/.grok-work"
|
|
16
|
+
},
|
|
17
|
+
"effective": {
|
|
18
|
+
"provider": "{{name}} in this provider",
|
|
19
|
+
"machine": "{{name}} on this machine",
|
|
20
|
+
"default": "default"
|
|
12
21
|
}
|
|
13
22
|
},
|
|
14
23
|
"usage": {
|
package/locales/zh-CN.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"presentation": {
|
|
3
|
+
"name": "Grok",
|
|
4
|
+
"description": "在 Ycodium 里使用 Grok,之前的会话可以接着做。"
|
|
5
|
+
},
|
|
2
6
|
"form": {
|
|
3
7
|
"binaryPath": {
|
|
4
8
|
"title": "程序路径",
|
|
@@ -9,6 +13,11 @@
|
|
|
9
13
|
"title": "账号目录",
|
|
10
14
|
"description": "会话和 `grok login` 的凭据都保存在这里,因此共用同一目录的 provider 可以接手彼此的会话,目录不同的则不能。留空则使用该命令行工具的默认目录(~/.grok)。",
|
|
11
15
|
"placeholder": "例如 ~/.grok-work"
|
|
16
|
+
},
|
|
17
|
+
"effective": {
|
|
18
|
+
"provider": "本 provider 的 {{name}}",
|
|
19
|
+
"machine": "本机的 {{name}}",
|
|
20
|
+
"default": "默认"
|
|
12
21
|
}
|
|
13
22
|
},
|
|
14
23
|
"usage": {
|
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.3799",
|
|
4
4
|
"description": "Grok executor: grok CLI over Agent Client Protocol stdio.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -21,14 +21,16 @@
|
|
|
21
21
|
"@types/node": "24.12.4",
|
|
22
22
|
"esbuild": "0.28.1",
|
|
23
23
|
"vite-plus": "0.2.2",
|
|
24
|
-
"@ycodium-ai/plugin-api": "0.2.
|
|
25
|
-
"ycodium-acp-executor": "0.2.
|
|
24
|
+
"@ycodium-ai/plugin-api": "0.2.3799",
|
|
25
|
+
"ycodium-acp-executor": "0.2.3799",
|
|
26
26
|
"ycodium-executor-testing": "0.0.0"
|
|
27
27
|
},
|
|
28
28
|
"ycodium": {
|
|
29
29
|
"plugin": "./dist/index.js",
|
|
30
30
|
"displayName": "Grok",
|
|
31
|
-
"
|
|
31
|
+
"displayNameKey": "presentation.name",
|
|
32
|
+
"description": "Use Grok in Ycodium and pick up earlier sessions where they left off.",
|
|
33
|
+
"descriptionKey": "presentation.description",
|
|
32
34
|
"icon": "./assets/icon.svg",
|
|
33
35
|
"permissions": [
|
|
34
36
|
{
|