@ycodium-ai/agent-grok 0.2.3681 → 0.2.3766
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 +304 -239
- 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"],
|
|
@@ -161,6 +168,166 @@ var GROK_CARD = {
|
|
|
161
168
|
}
|
|
162
169
|
};
|
|
163
170
|
|
|
171
|
+
// src/grokHome.ts
|
|
172
|
+
import * as NodeCrypto from "node:crypto";
|
|
173
|
+
import * as NodeOS from "node:os";
|
|
174
|
+
import * as NodePath2 from "node:path";
|
|
175
|
+
import { mergeLaunchEnv } from "@ycodium-ai/plugin-api/executor";
|
|
176
|
+
|
|
177
|
+
// src/grokAccount.ts
|
|
178
|
+
import * as NodeFS from "node:fs";
|
|
179
|
+
import * as NodePath from "node:path";
|
|
180
|
+
var AUTH_FILE_NAME = "auth.json";
|
|
181
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
182
|
+
var readString = (record4, key) => {
|
|
183
|
+
const value = record4[key];
|
|
184
|
+
if (typeof value !== "string") return void 0;
|
|
185
|
+
const trimmed3 = value.trim();
|
|
186
|
+
return trimmed3.length > 0 ? trimmed3 : void 0;
|
|
187
|
+
};
|
|
188
|
+
var parseJsonRecord = (raw) => {
|
|
189
|
+
let parsed;
|
|
190
|
+
try {
|
|
191
|
+
parsed = JSON.parse(raw);
|
|
192
|
+
} catch {
|
|
193
|
+
return void 0;
|
|
194
|
+
}
|
|
195
|
+
return isRecord(parsed) ? parsed : void 0;
|
|
196
|
+
};
|
|
197
|
+
var directoryExists = (homePath) => {
|
|
198
|
+
try {
|
|
199
|
+
return NodeFS.statSync(homePath).isDirectory();
|
|
200
|
+
} catch {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
var readCredentialFile = (path) => {
|
|
205
|
+
try {
|
|
206
|
+
return NodeFS.readFileSync(path, "utf8");
|
|
207
|
+
} catch {
|
|
208
|
+
return void 0;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
var signedOutProbe = (exists) => ({
|
|
212
|
+
state: "signed-out",
|
|
213
|
+
directoryExists: exists,
|
|
214
|
+
email: void 0,
|
|
215
|
+
name: void 0,
|
|
216
|
+
expiresAt: void 0
|
|
217
|
+
});
|
|
218
|
+
var unreadableProbe = (exists) => ({
|
|
219
|
+
state: "unreadable",
|
|
220
|
+
directoryExists: exists,
|
|
221
|
+
email: void 0,
|
|
222
|
+
name: void 0,
|
|
223
|
+
expiresAt: void 0
|
|
224
|
+
});
|
|
225
|
+
var joinName = (record4) => {
|
|
226
|
+
const first = readString(record4, "first_name");
|
|
227
|
+
const last = readString(record4, "last_name");
|
|
228
|
+
const joined = [first, last].filter((part) => part !== void 0).join(" ");
|
|
229
|
+
return joined.length > 0 ? joined : void 0;
|
|
230
|
+
};
|
|
231
|
+
var findIdentityEntry = (parsed) => {
|
|
232
|
+
for (const value of Object.values(parsed)) {
|
|
233
|
+
if (!isRecord(value)) continue;
|
|
234
|
+
if (readString(value, "email") !== void 0 || readString(value, "user_id") !== void 0) {
|
|
235
|
+
return value;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return void 0;
|
|
239
|
+
};
|
|
240
|
+
var isExpired = (expiresAt, nowMs) => {
|
|
241
|
+
if (expiresAt === void 0) return false;
|
|
242
|
+
const parsed = Date.parse(expiresAt);
|
|
243
|
+
return Number.isNaN(parsed) ? false : parsed <= nowMs;
|
|
244
|
+
};
|
|
245
|
+
var readGrokAccount = (homePath) => {
|
|
246
|
+
const exists = directoryExists(homePath);
|
|
247
|
+
const raw = readCredentialFile(NodePath.join(homePath, AUTH_FILE_NAME));
|
|
248
|
+
if (raw === void 0) return signedOutProbe(exists);
|
|
249
|
+
const parsed = parseJsonRecord(raw);
|
|
250
|
+
const identity = parsed === void 0 ? void 0 : findIdentityEntry(parsed);
|
|
251
|
+
if (identity === void 0) return unreadableProbe(exists);
|
|
252
|
+
const expiresAt = readString(identity, "expires_at");
|
|
253
|
+
return {
|
|
254
|
+
state: isExpired(expiresAt, Date.now()) ? "expired" : "signed-in",
|
|
255
|
+
directoryExists: exists,
|
|
256
|
+
email: readString(identity, "email"),
|
|
257
|
+
name: joinName(identity),
|
|
258
|
+
expiresAt
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// src/grokHome.ts
|
|
263
|
+
function expandHomePath(value) {
|
|
264
|
+
if (value === "~") return NodeOS.homedir();
|
|
265
|
+
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
266
|
+
return NodePath2.join(NodeOS.homedir(), value.slice(2));
|
|
267
|
+
}
|
|
268
|
+
return value;
|
|
269
|
+
}
|
|
270
|
+
function resolveGrokHomePath(value) {
|
|
271
|
+
const trimmed3 = value.trim();
|
|
272
|
+
if (trimmed3.length === 0) return NodePath2.join(NodeOS.homedir(), ".grok");
|
|
273
|
+
return NodePath2.resolve(expandHomePath(trimmed3));
|
|
274
|
+
}
|
|
275
|
+
function probeGrokAccount(accountPath) {
|
|
276
|
+
const resolved = resolveGrokHomePath(accountPath);
|
|
277
|
+
const account = readGrokAccount(resolved);
|
|
278
|
+
return {
|
|
279
|
+
accountPath: resolved,
|
|
280
|
+
state: account.state,
|
|
281
|
+
...account.email === void 0 ? {} : { email: account.email },
|
|
282
|
+
...account.name === void 0 ? {} : { name: account.name },
|
|
283
|
+
...account.expiresAt === void 0 ? {} : { expiresAt: account.expiresAt }
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function grokContinuationKey(recipe) {
|
|
287
|
+
return `grok:home:${resolveGrokHomePath(recipe.homePath)}`;
|
|
288
|
+
}
|
|
289
|
+
function resolveAccountHomePath(recipe, configuredHome) {
|
|
290
|
+
const fromEnvironment = recipe.environment["GROK_HOME"]?.trim();
|
|
291
|
+
if (fromEnvironment !== void 0 && fromEnvironment.length > 0) {
|
|
292
|
+
return NodePath2.resolve(expandHomePath(fromEnvironment));
|
|
293
|
+
}
|
|
294
|
+
return resolveGrokHomePath(configuredHome);
|
|
295
|
+
}
|
|
296
|
+
function absentPath() {
|
|
297
|
+
return NodePath2.join(
|
|
298
|
+
NodeOS.tmpdir(),
|
|
299
|
+
`ycodium-grok-no-auth-${NodeCrypto.randomUUID()}`,
|
|
300
|
+
"auth.json"
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
function ownEndpointAuthGuard(recipe) {
|
|
304
|
+
const connectivity = GROK_CARD.modelConnectivity;
|
|
305
|
+
const baseUrlKey = connectivity.baseUrlEnvKey;
|
|
306
|
+
if (baseUrlKey === void 0 || (recipe.environment[baseUrlKey]?.trim() ?? "") === "") return {};
|
|
307
|
+
const guard = {};
|
|
308
|
+
for (const entry of connectivity.extraEnv ?? []) {
|
|
309
|
+
if (entry.value === "$absentPath") guard[entry.name] = absentPath();
|
|
310
|
+
}
|
|
311
|
+
return guard;
|
|
312
|
+
}
|
|
313
|
+
function buildSignInEnv(recipe) {
|
|
314
|
+
const configuredHome = recipe.homePath;
|
|
315
|
+
const homeInjection = configuredHome.trim().length > 0 ? { [GROK_CARD.homeEnvVar]: resolveGrokHomePath(configuredHome) } : {};
|
|
316
|
+
return mergeLaunchEnv({
|
|
317
|
+
accountHome: homeInjection,
|
|
318
|
+
instanceTable: recipe.environment,
|
|
319
|
+
handOverrides: { GROK_OAUTH2_REFERRER: "ycodium" }
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
function buildSpawnEnv(recipe, resolvedHomePath, homeConfigured) {
|
|
323
|
+
const homeInjection = homeConfigured ? { [GROK_CARD.homeEnvVar]: resolvedHomePath } : {};
|
|
324
|
+
return mergeLaunchEnv({
|
|
325
|
+
accountHome: { ...homeInjection, ...ownEndpointAuthGuard(recipe) },
|
|
326
|
+
instanceTable: recipe.environment,
|
|
327
|
+
handOverrides: { GROK_OAUTH2_REFERRER: "ycodium" }
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
164
331
|
// src/grokInstance.ts
|
|
165
332
|
import * as NodeCrypto3 from "node:crypto";
|
|
166
333
|
import {
|
|
@@ -169,7 +336,7 @@ import {
|
|
|
169
336
|
import { nodeStreamsFromHandle as nodeStreamsFromHandle2 } from "@ycodium-ai/plugin-api/process-stdin";
|
|
170
337
|
|
|
171
338
|
// ../../packages/ycodium-acp-executor/src/executor.ts
|
|
172
|
-
import * as
|
|
339
|
+
import * as NodeCrypto2 from "node:crypto";
|
|
173
340
|
|
|
174
341
|
// ../../packages/ycodium-acp-executor/src/approvals.ts
|
|
175
342
|
function createApprovalGate(input2) {
|
|
@@ -397,7 +564,7 @@ var UnboundedEventStream = class {
|
|
|
397
564
|
};
|
|
398
565
|
|
|
399
566
|
// ../../packages/ycodium-acp-executor/src/config-options.ts
|
|
400
|
-
function
|
|
567
|
+
function isRecord2(value) {
|
|
401
568
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
402
569
|
}
|
|
403
570
|
function asString(value) {
|
|
@@ -416,7 +583,7 @@ function flattenChoices(rawOptions, currentValue) {
|
|
|
416
583
|
const out = [];
|
|
417
584
|
const seen = /* @__PURE__ */ new Set();
|
|
418
585
|
const push = (entry) => {
|
|
419
|
-
if (!
|
|
586
|
+
if (!isRecord2(entry)) return;
|
|
420
587
|
const value = asString(entry["value"]);
|
|
421
588
|
if (value === void 0 || seen.has(value)) return;
|
|
422
589
|
seen.add(value);
|
|
@@ -431,7 +598,7 @@ function flattenChoices(rawOptions, currentValue) {
|
|
|
431
598
|
});
|
|
432
599
|
};
|
|
433
600
|
for (const entry of rawOptions) {
|
|
434
|
-
if (
|
|
601
|
+
if (isRecord2(entry) && Array.isArray(entry["options"])) {
|
|
435
602
|
for (const nested of entry["options"]) push(nested);
|
|
436
603
|
continue;
|
|
437
604
|
}
|
|
@@ -440,7 +607,7 @@ function flattenChoices(rawOptions, currentValue) {
|
|
|
440
607
|
return out;
|
|
441
608
|
}
|
|
442
609
|
function isConfigOption(entry, configId) {
|
|
443
|
-
return
|
|
610
|
+
return isRecord2(entry) && asString(entry["id"])?.trim() === configId.trim();
|
|
444
611
|
}
|
|
445
612
|
function findConfigOptionEntry(configOptions, configId) {
|
|
446
613
|
return Array.isArray(configOptions) && configId.trim() !== "" ? configOptions.find(
|
|
@@ -455,7 +622,7 @@ function withConfigOptionValue(configOptions, configId, value) {
|
|
|
455
622
|
}
|
|
456
623
|
function pickEffortOption(configOptions) {
|
|
457
624
|
if (!Array.isArray(configOptions)) return void 0;
|
|
458
|
-
const candidates = configOptions.filter(
|
|
625
|
+
const candidates = configOptions.filter(isRecord2).filter((option) => normalizedField(option, "type") === "select").filter(looksLikeEffortOption);
|
|
459
626
|
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
627
|
}
|
|
461
628
|
function findAcpEffortConfig(configOptions) {
|
|
@@ -475,7 +642,7 @@ function findAcpEffortConfig(configOptions) {
|
|
|
475
642
|
}
|
|
476
643
|
|
|
477
644
|
// ../../packages/ycodium-acp-executor/src/util.ts
|
|
478
|
-
function
|
|
645
|
+
function isRecord3(value) {
|
|
479
646
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
480
647
|
}
|
|
481
648
|
function asTrimmedString(value) {
|
|
@@ -530,11 +697,11 @@ function extractCommandFromTitle(title) {
|
|
|
530
697
|
return backtickMatch?.[1]?.trim() || void 0;
|
|
531
698
|
}
|
|
532
699
|
function extractToolCommand(data, title) {
|
|
533
|
-
const item =
|
|
534
|
-
const itemInput = item &&
|
|
535
|
-
const itemResult = item &&
|
|
536
|
-
const rawInput =
|
|
537
|
-
const dataInput =
|
|
700
|
+
const item = isRecord3(data?.["item"]) ? data["item"] : void 0;
|
|
701
|
+
const itemInput = item && isRecord3(item["input"]) ? item["input"] : void 0;
|
|
702
|
+
const itemResult = item && isRecord3(item["result"]) ? item["result"] : void 0;
|
|
703
|
+
const rawInput = isRecord3(data?.["rawInput"]) ? data["rawInput"] : void 0;
|
|
704
|
+
const dataInput = isRecord3(data?.["input"]) ? data["input"] : void 0;
|
|
538
705
|
const candidates = [
|
|
539
706
|
normalizeCommandValue(item?.["command"]),
|
|
540
707
|
normalizeCommandValue(itemInput?.["command"]),
|
|
@@ -579,7 +746,7 @@ function collectPaths(value, paths, seen, depth) {
|
|
|
579
746
|
}
|
|
580
747
|
return;
|
|
581
748
|
}
|
|
582
|
-
if (!
|
|
749
|
+
if (!isRecord3(value)) {
|
|
583
750
|
return;
|
|
584
751
|
}
|
|
585
752
|
for (const key of ["path", "filePath", "relativePath", "filename", "newPath", "oldPath"]) {
|
|
@@ -657,7 +824,7 @@ function deriveToolActivityPresentation(input2) {
|
|
|
657
824
|
const title = asTrimmedString(input2.title);
|
|
658
825
|
const detail = stripTrailingExitCode(asTrimmedString(input2.detail));
|
|
659
826
|
const fallbackSummary = asTrimmedString(input2.fallbackSummary) ?? "Tool";
|
|
660
|
-
const data =
|
|
827
|
+
const data = isRecord3(input2.data) ? input2.data : void 0;
|
|
661
828
|
const command = extractToolCommand(data, title);
|
|
662
829
|
const primaryPath = extractPrimaryPath(data);
|
|
663
830
|
const action = classifyToolAction({
|
|
@@ -689,7 +856,7 @@ function deriveToolActivityPresentation(input2) {
|
|
|
689
856
|
};
|
|
690
857
|
}
|
|
691
858
|
if (action === "search") {
|
|
692
|
-
const rawInput =
|
|
859
|
+
const rawInput = isRecord3(data?.["rawInput"]) ? data["rawInput"] : void 0;
|
|
693
860
|
const query = asTrimmedString(rawInput?.["query"]) ?? asTrimmedString(rawInput?.["pattern"]) ?? asTrimmedString(rawInput?.["searchTerm"]);
|
|
694
861
|
return {
|
|
695
862
|
summary: "Searched files",
|
|
@@ -749,7 +916,7 @@ function extractCommandFromTitle2(title) {
|
|
|
749
916
|
return match?.[1]?.trim() || void 0;
|
|
750
917
|
}
|
|
751
918
|
function extractToolCallCommand(rawInput, title) {
|
|
752
|
-
if (
|
|
919
|
+
if (isRecord3(rawInput)) {
|
|
753
920
|
const directCommand = normalizeCommandValue2(rawInput["command"]);
|
|
754
921
|
if (directCommand) {
|
|
755
922
|
return directCommand;
|
|
@@ -777,7 +944,7 @@ function boundTailText(text4, limit = TOOL_CALL_CONTENT_MAX_CHARS) {
|
|
|
777
944
|
var boundToolCallOutputText = (text4) => boundTailText(text4);
|
|
778
945
|
var RAW_OUTPUT_TEXT_FIELDS = ["content", "stdout", "stderr", "output"];
|
|
779
946
|
function boundToolCallRawOutput(rawOutput) {
|
|
780
|
-
if (!
|
|
947
|
+
if (!isRecord3(rawOutput)) {
|
|
781
948
|
return rawOutput;
|
|
782
949
|
}
|
|
783
950
|
let changed = false;
|
|
@@ -969,11 +1136,11 @@ function collectSessionConfigOptionValues(configOption) {
|
|
|
969
1136
|
);
|
|
970
1137
|
}
|
|
971
1138
|
function collectSessionModelIds(models) {
|
|
972
|
-
if (!
|
|
1139
|
+
if (!isRecord3(models) || !Array.isArray(models["availableModels"])) {
|
|
973
1140
|
return [];
|
|
974
1141
|
}
|
|
975
1142
|
return models["availableModels"].flatMap(
|
|
976
|
-
(model) =>
|
|
1143
|
+
(model) => isRecord3(model) && typeof model["modelId"] === "string" ? [model["modelId"]] : []
|
|
977
1144
|
);
|
|
978
1145
|
}
|
|
979
1146
|
function catalogModelLastSegment(value) {
|
|
@@ -1045,7 +1212,7 @@ function parseAvailableCommandsUpdate(params) {
|
|
|
1045
1212
|
}
|
|
1046
1213
|
const commands = [];
|
|
1047
1214
|
for (const command of availableCommands) {
|
|
1048
|
-
if (!
|
|
1215
|
+
if (!isRecord3(command)) {
|
|
1049
1216
|
continue;
|
|
1050
1217
|
}
|
|
1051
1218
|
const name = typeof command["name"] === "string" ? command["name"].trim() : "";
|
|
@@ -1053,7 +1220,7 @@ function parseAvailableCommandsUpdate(params) {
|
|
|
1053
1220
|
continue;
|
|
1054
1221
|
}
|
|
1055
1222
|
const description = typeof command["description"] === "string" ? command["description"].trim() || void 0 : void 0;
|
|
1056
|
-
const input2 =
|
|
1223
|
+
const input2 = isRecord3(command["input"]) ? command["input"] : void 0;
|
|
1057
1224
|
const inputHint = typeof input2?.["hint"] === "string" ? input2["hint"].trim() || void 0 : void 0;
|
|
1058
1225
|
commands.push({
|
|
1059
1226
|
name,
|
|
@@ -1107,7 +1274,7 @@ function boundToolCallRawPayload(params, update, toolCall) {
|
|
|
1107
1274
|
}
|
|
1108
1275
|
function textFromContentBlocks(blocks) {
|
|
1109
1276
|
const parts = blocks.flatMap(
|
|
1110
|
-
(block) =>
|
|
1277
|
+
(block) => isRecord3(block) && block["type"] === "text" && typeof block["text"] === "string" ? [block["text"]] : []
|
|
1111
1278
|
);
|
|
1112
1279
|
const joined = parts.join("");
|
|
1113
1280
|
return joined.trim().length > 0 ? joined : void 0;
|
|
@@ -1132,7 +1299,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
1132
1299
|
const entries = Array.isArray(upd["entries"]) ? upd["entries"] : [];
|
|
1133
1300
|
const plan = entries.map((entry, index) => ({
|
|
1134
1301
|
step: readAcpText(entry, "content") ?? `Step ${index + 1}`,
|
|
1135
|
-
status: normalizePlanStepStatus(
|
|
1302
|
+
status: normalizePlanStepStatus(isRecord3(entry) ? entry["status"] : void 0)
|
|
1136
1303
|
}));
|
|
1137
1304
|
if (plan.length > 0) {
|
|
1138
1305
|
events.push({
|
|
@@ -1172,7 +1339,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
1172
1339
|
}
|
|
1173
1340
|
case "agent_message_chunk":
|
|
1174
1341
|
case "agent_thought_chunk": {
|
|
1175
|
-
const content =
|
|
1342
|
+
const content = isRecord3(upd["content"]) ? upd["content"] : void 0;
|
|
1176
1343
|
const contentType = content?.["type"];
|
|
1177
1344
|
const streamKind = kind === "agent_thought_chunk" ? "reasoning_text" : "assistant_text";
|
|
1178
1345
|
if (contentType === "text") {
|
|
@@ -1212,7 +1379,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
1212
1379
|
}
|
|
1213
1380
|
case "compaction_summary_chunk": {
|
|
1214
1381
|
const compactionId = readAcpText(upd, "compactionId");
|
|
1215
|
-
const content =
|
|
1382
|
+
const content = isRecord3(upd["content"]) ? upd["content"] : void 0;
|
|
1216
1383
|
const text4 = content?.["type"] === "text" ? content["text"] : void 0;
|
|
1217
1384
|
if (compactionId === void 0 || typeof text4 !== "string" || text4.length === 0) break;
|
|
1218
1385
|
events.push({ _tag: "CompactionSummaryChunk", compactionId, text: text4 });
|
|
@@ -22906,17 +23073,17 @@ function isResponseMessage(value) {
|
|
|
22906
23073
|
function isNotificationMessage(value) {
|
|
22907
23074
|
return isJsonRpcEnvelope(value) && !("id" in value) && typeof value["method"] === "string";
|
|
22908
23075
|
}
|
|
22909
|
-
function
|
|
23076
|
+
function isRecord4(value) {
|
|
22910
23077
|
return typeof value === "object" && value !== null;
|
|
22911
23078
|
}
|
|
22912
23079
|
function isJsonRpcEnvelope(value) {
|
|
22913
|
-
return
|
|
23080
|
+
return isRecord4(value) && value["jsonrpc"] === "2.0";
|
|
22914
23081
|
}
|
|
22915
23082
|
function isJsonRpcId(value) {
|
|
22916
23083
|
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
22917
23084
|
}
|
|
22918
23085
|
function isResponseShapedMessage(value) {
|
|
22919
|
-
return
|
|
23086
|
+
return isRecord4(value) && !("method" in value) && ("id" in value || "result" in value || "error" in value);
|
|
22920
23087
|
}
|
|
22921
23088
|
function isResponseBatch(batch) {
|
|
22922
23089
|
let hasValidCall = false;
|
|
@@ -22926,7 +23093,7 @@ function isResponseBatch(batch) {
|
|
|
22926
23093
|
for (const entry of batch) {
|
|
22927
23094
|
hasValidCall ||= isRequestMessage(entry) || isNotificationMessage(entry);
|
|
22928
23095
|
hasValidResponse ||= isResponseMessage(entry);
|
|
22929
|
-
if (!
|
|
23096
|
+
if (!isRecord4(entry)) {
|
|
22930
23097
|
continue;
|
|
22931
23098
|
}
|
|
22932
23099
|
hasCallShape ||= "method" in entry;
|
|
@@ -22941,13 +23108,13 @@ function isResponseBatch(batch) {
|
|
|
22941
23108
|
return hasResponseShape && !hasCallShape;
|
|
22942
23109
|
}
|
|
22943
23110
|
function cancelRequestId(params) {
|
|
22944
|
-
if (!
|
|
23111
|
+
if (!isRecord4(params) || !isJsonRpcId(params["requestId"])) {
|
|
22945
23112
|
return void 0;
|
|
22946
23113
|
}
|
|
22947
23114
|
return params["requestId"];
|
|
22948
23115
|
}
|
|
22949
23116
|
function isErrorResponse(value) {
|
|
22950
|
-
return
|
|
23117
|
+
return isRecord4(value) && typeof value["code"] === "number" && Number.isInteger(value["code"]) && typeof value["message"] === "string";
|
|
22951
23118
|
}
|
|
22952
23119
|
var Handled = {
|
|
22953
23120
|
/**
|
|
@@ -23492,7 +23659,7 @@ var Connection = class {
|
|
|
23492
23659
|
if (this.abortController.signal.aborted) {
|
|
23493
23660
|
return Promise.resolve();
|
|
23494
23661
|
}
|
|
23495
|
-
if (!
|
|
23662
|
+
if (!isRecord4(message)) {
|
|
23496
23663
|
console.error("Invalid message", { message });
|
|
23497
23664
|
return Promise.resolve();
|
|
23498
23665
|
}
|
|
@@ -23895,7 +24062,7 @@ function ndJsonStream(output2, input2) {
|
|
|
23895
24062
|
await writeJson(protocolErrorResponse(RequestError.parseError()));
|
|
23896
24063
|
return;
|
|
23897
24064
|
}
|
|
23898
|
-
if (
|
|
24065
|
+
if (isRecord4(message) || Array.isArray(message)) {
|
|
23899
24066
|
controller.enqueue(message);
|
|
23900
24067
|
} else {
|
|
23901
24068
|
await writeJson(protocolErrorResponse(RequestError.invalidRequest(message)));
|
|
@@ -24882,14 +25049,14 @@ var legacyClientNotificationMethods = /* @__PURE__ */ new Set([
|
|
|
24882
25049
|
import * as NodeStream from "node:stream";
|
|
24883
25050
|
|
|
24884
25051
|
// ../../packages/ycodium-acp-executor/src/jsonrpc.ts
|
|
24885
|
-
function
|
|
25052
|
+
function isRecord5(value) {
|
|
24886
25053
|
return typeof value === "object" && value !== null;
|
|
24887
25054
|
}
|
|
24888
25055
|
function isJsonRpcId2(value) {
|
|
24889
25056
|
return typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
24890
25057
|
}
|
|
24891
25058
|
function isJsonRpcEnvelope2(value) {
|
|
24892
|
-
return
|
|
25059
|
+
return isRecord5(value) && value["jsonrpc"] === "2.0";
|
|
24893
25060
|
}
|
|
24894
25061
|
function isRequestMessage2(value) {
|
|
24895
25062
|
return isJsonRpcEnvelope2(value) && "id" in value && typeof value["method"] === "string" && isJsonRpcId2(value["id"]);
|
|
@@ -24909,7 +25076,7 @@ function isNotificationMessage2(value) {
|
|
|
24909
25076
|
return isJsonRpcEnvelope2(value) && !("id" in value) && typeof value["method"] === "string";
|
|
24910
25077
|
}
|
|
24911
25078
|
function readJsonRpcError(value) {
|
|
24912
|
-
if (!
|
|
25079
|
+
if (!isRecord5(value) || typeof value["code"] !== "number" || typeof value["message"] !== "string") {
|
|
24913
25080
|
return void 0;
|
|
24914
25081
|
}
|
|
24915
25082
|
return {
|
|
@@ -24982,11 +25149,11 @@ var KNOWN_SESSION_UPDATES = /* @__PURE__ */ new Set([
|
|
|
24982
25149
|
"compaction_summary_chunk"
|
|
24983
25150
|
]);
|
|
24984
25151
|
function isSessionUpdateEnvelope(payload) {
|
|
24985
|
-
if (!
|
|
25152
|
+
if (!isRecord5(payload) || typeof payload["sessionId"] !== "string") {
|
|
24986
25153
|
return false;
|
|
24987
25154
|
}
|
|
24988
25155
|
const update = payload["update"];
|
|
24989
|
-
return
|
|
25156
|
+
return isRecord5(update) && typeof update["sessionUpdate"] === "string";
|
|
24990
25157
|
}
|
|
24991
25158
|
function hasKnownVariantShape(update) {
|
|
24992
25159
|
const kind = update["sessionUpdate"];
|
|
@@ -24994,7 +25161,7 @@ function hasKnownVariantShape(update) {
|
|
|
24994
25161
|
return false;
|
|
24995
25162
|
}
|
|
24996
25163
|
if (kind === "user_message_chunk" || kind === "agent_message_chunk" || kind === "agent_thought_chunk") {
|
|
24997
|
-
return
|
|
25164
|
+
return isRecord5(update["content"]);
|
|
24998
25165
|
}
|
|
24999
25166
|
return true;
|
|
25000
25167
|
}
|
|
@@ -25381,29 +25548,37 @@ function createAcpConnection(options) {
|
|
|
25381
25548
|
function normalizeModelId(value) {
|
|
25382
25549
|
return value?.trim() || void 0;
|
|
25383
25550
|
}
|
|
25384
|
-
function adoptReportedConfigOptions(state, configOptions) {
|
|
25551
|
+
function adoptReportedConfigOptions(state, configOptions, fromAgent = true) {
|
|
25385
25552
|
const option = state.modelConfigId === void 0 ? void 0 : findConfigOptionEntry(configOptions, state.modelConfigId);
|
|
25386
25553
|
const value = option?.["currentValue"];
|
|
25387
25554
|
const reported = typeof value === "string" ? normalizeModelId(value) : void 0;
|
|
25388
25555
|
if (reported === void 0) return { ...state, configOptions };
|
|
25389
25556
|
const { modelUnconfirmed: _confirmed, ...known } = state;
|
|
25390
|
-
|
|
25557
|
+
const stillReported = fromAgent || state.currentModelReported === true && reported === state.currentModelId;
|
|
25558
|
+
const { currentModelReported: _stale, ...unreported } = known;
|
|
25559
|
+
return {
|
|
25560
|
+
...stillReported ? known : unreported,
|
|
25561
|
+
configOptions,
|
|
25562
|
+
currentModelId: reported,
|
|
25563
|
+
...stillReported ? { currentModelReported: true } : {}
|
|
25564
|
+
};
|
|
25391
25565
|
}
|
|
25392
25566
|
function forgetConfigOptionValue(state, configId) {
|
|
25393
25567
|
const forgetsModel = configId === void 0 || configId === state.modelConfigId;
|
|
25568
|
+
const { currentModelReported: _forgottenReport, ...withoutReport } = state;
|
|
25394
25569
|
const configOptions = configId !== void 0 && Array.isArray(state.configOptions) ? state.configOptions.map((option) => {
|
|
25395
|
-
if (!
|
|
25570
|
+
if (!isRecord3(option) || option["id"] !== configId) return option;
|
|
25396
25571
|
const { currentValue: _forgotten, ...rest } = option;
|
|
25397
25572
|
return rest;
|
|
25398
25573
|
}) : state.configOptions;
|
|
25399
25574
|
return {
|
|
25400
|
-
...state,
|
|
25575
|
+
...forgetsModel ? withoutReport : state,
|
|
25401
25576
|
configOptions,
|
|
25402
25577
|
...forgetsModel ? { currentModelId: void 0, modelUnconfirmed: true } : {}
|
|
25403
25578
|
};
|
|
25404
25579
|
}
|
|
25405
25580
|
function modelSelectionStateFromSetup(setup) {
|
|
25406
|
-
const sessionModels =
|
|
25581
|
+
const sessionModels = isRecord3(setup.models) ? setup.models : void 0;
|
|
25407
25582
|
const modelConfigId = extractModelConfigId(setup);
|
|
25408
25583
|
const strategy = modelConfigId !== void 0 ? "config-option" : "session/set_model";
|
|
25409
25584
|
const modelConfigOption = modelConfigId === void 0 ? void 0 : findSessionConfigOption(setup.configOptions, modelConfigId);
|
|
@@ -25414,6 +25589,7 @@ function modelSelectionStateFromSetup(setup) {
|
|
|
25414
25589
|
sessionModelsAdvertised: sessionModels !== void 0,
|
|
25415
25590
|
modelConfigId,
|
|
25416
25591
|
currentModelId,
|
|
25592
|
+
...currentModelId === void 0 ? {} : { currentModelReported: true },
|
|
25417
25593
|
advertisedModelValues: strategy === "config-option" ? modelConfigOption === void 0 ? [] : collectSessionConfigOptionValues(modelConfigOption) : collectSessionModelIds(sessionModels),
|
|
25418
25594
|
configOptions: setup.configOptions,
|
|
25419
25595
|
catalogSetup: setup
|
|
@@ -26201,14 +26377,28 @@ function createExecutorPrompt({
|
|
|
26201
26377
|
}
|
|
26202
26378
|
};
|
|
26203
26379
|
const alignTurnOptions = async (input2, sessionId, generation, isStale, signal) => {
|
|
26380
|
+
const before = shared.modelSelectionState;
|
|
26204
26381
|
const applied = await applyRequestedModel({
|
|
26205
|
-
state:
|
|
26382
|
+
state: before,
|
|
26206
26383
|
acpSessionId: sessionId,
|
|
26207
26384
|
requestedModelId: input2.requestedModelId,
|
|
26208
26385
|
expectedGeneration: generation,
|
|
26209
26386
|
signal
|
|
26210
26387
|
});
|
|
26211
26388
|
shared.modelSelectionState = applied;
|
|
26389
|
+
if (applied.currentModelId !== void 0 && (applied.currentModelId !== before.currentModelId || applied.currentModelReported !== before.currentModelReported)) {
|
|
26390
|
+
emit({
|
|
26391
|
+
type: "thread.metadata.updated",
|
|
26392
|
+
...stamp(),
|
|
26393
|
+
provider: options.provider,
|
|
26394
|
+
threadId: options.threadId,
|
|
26395
|
+
...shared.activeTurnId === void 0 ? {} : { turnId: shared.activeTurnId },
|
|
26396
|
+
payload: {
|
|
26397
|
+
model: applied.currentModelId,
|
|
26398
|
+
modelSource: applied.currentModelReported === true ? "reported" : "echo"
|
|
26399
|
+
}
|
|
26400
|
+
});
|
|
26401
|
+
}
|
|
26212
26402
|
if (isStale()) return;
|
|
26213
26403
|
const switched = applied.configOptions;
|
|
26214
26404
|
let aligned;
|
|
@@ -26233,7 +26423,8 @@ function createExecutorPrompt({
|
|
|
26233
26423
|
if (aligned.configOptions !== switched) {
|
|
26234
26424
|
shared.modelSelectionState = adoptReportedConfigOptions(
|
|
26235
26425
|
shared.modelSelectionState,
|
|
26236
|
-
aligned.configOptions
|
|
26426
|
+
aligned.configOptions,
|
|
26427
|
+
false
|
|
26237
26428
|
);
|
|
26238
26429
|
}
|
|
26239
26430
|
if (aligned.unsupportedEffort !== void 0) {
|
|
@@ -26755,7 +26946,7 @@ function createExecutorRequests({
|
|
|
26755
26946
|
pendingUserInputs.delete(requestId);
|
|
26756
26947
|
pending.resolve({
|
|
26757
26948
|
kind: "answered",
|
|
26758
|
-
answers:
|
|
26949
|
+
answers: isRecord3(answers) ? answers : {}
|
|
26759
26950
|
});
|
|
26760
26951
|
};
|
|
26761
26952
|
return {
|
|
@@ -26769,7 +26960,7 @@ function createExecutorRequests({
|
|
|
26769
26960
|
}
|
|
26770
26961
|
|
|
26771
26962
|
// ../../packages/ycodium-acp-executor/src/artifacts.ts
|
|
26772
|
-
import * as
|
|
26963
|
+
import * as NodePath3 from "node:path";
|
|
26773
26964
|
import * as NodeURL from "node:url";
|
|
26774
26965
|
function resourceLinkArtifacts(content) {
|
|
26775
26966
|
if (content["type"] !== "resource_link" || typeof content["uri"] !== "string") return [];
|
|
@@ -26780,7 +26971,7 @@ function resourceLinkArtifacts(content) {
|
|
|
26780
26971
|
} catch {
|
|
26781
26972
|
return [];
|
|
26782
26973
|
}
|
|
26783
|
-
if (!
|
|
26974
|
+
if (!NodePath3.isAbsolute(path)) return [];
|
|
26784
26975
|
const name = typeof content["name"] === "string" ? content["name"].trim() : "";
|
|
26785
26976
|
const mimeType = typeof content["mimeType"] === "string" ? content["mimeType"].trim() : "";
|
|
26786
26977
|
return [
|
|
@@ -27054,18 +27245,18 @@ function modelRefreshFailedError(requestedModelId, error62) {
|
|
|
27054
27245
|
}
|
|
27055
27246
|
|
|
27056
27247
|
// ../../packages/ycodium-acp-executor/src/runtime-mode.ts
|
|
27057
|
-
function
|
|
27248
|
+
function isRecord6(value) {
|
|
27058
27249
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27059
27250
|
}
|
|
27060
27251
|
function asString2(value) {
|
|
27061
27252
|
return typeof value === "string" ? value : void 0;
|
|
27062
27253
|
}
|
|
27063
27254
|
function acpModeConfigId(setup) {
|
|
27064
|
-
if (!
|
|
27255
|
+
if (!isRecord6(setup)) return void 0;
|
|
27065
27256
|
const configOptions = setup["configOptions"];
|
|
27066
27257
|
if (!Array.isArray(configOptions)) return void 0;
|
|
27067
27258
|
for (const option of configOptions) {
|
|
27068
|
-
if (!
|
|
27259
|
+
if (!isRecord6(option)) continue;
|
|
27069
27260
|
if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
|
|
27070
27261
|
const id = asString2(option["id"])?.trim();
|
|
27071
27262
|
if (id) return id;
|
|
@@ -27154,18 +27345,20 @@ function createExecutorSession({
|
|
|
27154
27345
|
const base = ours !== void 0 && ours.seq > issuedAt ? ours.configOptions : configOptions;
|
|
27155
27346
|
return { configOptions: withConfigOptionValue(base, configId, value), reported: false };
|
|
27156
27347
|
};
|
|
27157
|
-
const writeConfigOption = async (...args) => (await writeConfigOptionReported(...args)).configOptions;
|
|
27158
27348
|
const switchModel = async (input2) => {
|
|
27159
27349
|
let configOptions = input2.state.configOptions;
|
|
27350
|
+
let fromAgent = true;
|
|
27160
27351
|
const write = { option: "model", signal: input2.signal };
|
|
27161
27352
|
if (input2.state.strategy === "config-option" && input2.state.modelConfigId !== void 0) {
|
|
27162
|
-
|
|
27353
|
+
const written = await writeConfigOptionReported(
|
|
27163
27354
|
input2.sessionId,
|
|
27164
27355
|
configOptions,
|
|
27165
27356
|
input2.state.modelConfigId,
|
|
27166
27357
|
input2.value,
|
|
27167
27358
|
write
|
|
27168
27359
|
);
|
|
27360
|
+
configOptions = written.configOptions;
|
|
27361
|
+
fromAgent = written.reported;
|
|
27169
27362
|
} else {
|
|
27170
27363
|
const before = shared.configOptionUpdates.get(input2.sessionId);
|
|
27171
27364
|
const pending = connection.begin("session/set_model", {
|
|
@@ -27183,7 +27376,12 @@ function createExecutorSession({
|
|
|
27183
27376
|
throw new AcpExecutorDisposedError();
|
|
27184
27377
|
}
|
|
27185
27378
|
const { modelUnconfirmed: _confirmed, ...known } = input2.state;
|
|
27186
|
-
|
|
27379
|
+
const { currentModelReported: _echoed, ...requested } = known;
|
|
27380
|
+
return adoptReportedConfigOptions(
|
|
27381
|
+
{ ...requested, currentModelId: input2.value },
|
|
27382
|
+
configOptions,
|
|
27383
|
+
fromAgent
|
|
27384
|
+
);
|
|
27187
27385
|
};
|
|
27188
27386
|
const applyRequestedModel = async (input2) => {
|
|
27189
27387
|
const requestedModelId = normalizeModelId(input2.requestedModelId) ?? "";
|
|
@@ -27327,7 +27525,8 @@ function createExecutorSession({
|
|
|
27327
27525
|
});
|
|
27328
27526
|
nextModelSelectionState = adoptReportedConfigOptions(
|
|
27329
27527
|
nextModelSelectionState,
|
|
27330
|
-
aligned.configOptions
|
|
27528
|
+
aligned.configOptions,
|
|
27529
|
+
false
|
|
27331
27530
|
);
|
|
27332
27531
|
if (aligned.unsupportedEffort !== void 0) {
|
|
27333
27532
|
options.log?.info("requested effort is not offered by this model; using its default", {
|
|
@@ -27360,7 +27559,8 @@ function createExecutorSession({
|
|
|
27360
27559
|
initializeResult: initialized,
|
|
27361
27560
|
sessionSetupResult: setup,
|
|
27362
27561
|
modelConfigId: extractModelConfigId(setup),
|
|
27363
|
-
modelId: nextModelSelectionState.currentModelId
|
|
27562
|
+
modelId: nextModelSelectionState.currentModelId,
|
|
27563
|
+
modelReported: nextModelSelectionState.currentModelReported === true
|
|
27364
27564
|
};
|
|
27365
27565
|
shared.startResult = result;
|
|
27366
27566
|
shared.status = "ready";
|
|
@@ -27503,14 +27703,14 @@ function createExecutorSettlement({
|
|
|
27503
27703
|
|
|
27504
27704
|
// ../../packages/ycodium-acp-executor/src/executor/subagent-sessions.ts
|
|
27505
27705
|
function parseState(raw) {
|
|
27506
|
-
if (!
|
|
27706
|
+
if (!isRecord3(raw)) return { status: void 0, error: void 0 };
|
|
27507
27707
|
const state = raw["state"];
|
|
27508
27708
|
if (state === "running") return { status: "running", error: void 0 };
|
|
27509
27709
|
if (state === "requires_action") return { status: "waiting", error: void 0 };
|
|
27510
27710
|
if (state !== "idle") return { status: void 0, error: void 0 };
|
|
27511
27711
|
const stopReason = raw["stopReason"];
|
|
27512
|
-
const error62 =
|
|
27513
|
-
if (stopReason === "error" ||
|
|
27712
|
+
const error62 = isRecord3(raw["error"]) ? asTrimmedString(raw["error"]["message"]) : void 0;
|
|
27713
|
+
if (stopReason === "error" || isRecord3(raw["error"])) return { status: "failed", error: error62 };
|
|
27514
27714
|
if (stopReason === "cancelled") return { status: "cancelled", error: void 0 };
|
|
27515
27715
|
return { status: "idle", error: void 0 };
|
|
27516
27716
|
}
|
|
@@ -27526,7 +27726,7 @@ function childLinkage(childId, record4) {
|
|
|
27526
27726
|
function createSubagentSessionTracker(registry2) {
|
|
27527
27727
|
const observe = (notification, ctx) => {
|
|
27528
27728
|
const update = notification.update;
|
|
27529
|
-
if (!
|
|
27729
|
+
if (!isRecord3(update) || update["sessionUpdate"] !== "subagent_update") return [];
|
|
27530
27730
|
const childId = asTrimmedString(update["sessionId"]);
|
|
27531
27731
|
if (childId === void 0 || ctx.ownSessionIds.has(childId)) return [];
|
|
27532
27732
|
const outerId = notification.sessionId;
|
|
@@ -27951,9 +28151,9 @@ function readOpenToolCalls(toolCalls, turnId) {
|
|
|
27951
28151
|
}
|
|
27952
28152
|
|
|
27953
28153
|
// ../../packages/ycodium-acp-executor/src/protocol-log.ts
|
|
27954
|
-
import * as
|
|
27955
|
-
import * as
|
|
27956
|
-
import * as
|
|
28154
|
+
import * as NodeFS2 from "node:fs";
|
|
28155
|
+
import * as NodeOS2 from "node:os";
|
|
28156
|
+
import * as NodePath4 from "node:path";
|
|
27957
28157
|
var DEFAULT_MAX_BYTES = 8 * 1024 * 1024;
|
|
27958
28158
|
var UNSAFE_FILE_CHARS = /[^A-Za-z0-9._-]+/gu;
|
|
27959
28159
|
function safeFileName(value) {
|
|
@@ -27961,12 +28161,12 @@ function safeFileName(value) {
|
|
|
27961
28161
|
}
|
|
27962
28162
|
function createAcpProtocolLogFile(input2) {
|
|
27963
28163
|
const maxBytes = input2.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
27964
|
-
|
|
27965
|
-
const filePath =
|
|
28164
|
+
NodeFS2.mkdirSync(input2.directory, { recursive: true });
|
|
28165
|
+
const filePath = NodePath4.join(
|
|
27966
28166
|
input2.directory,
|
|
27967
28167
|
`${safeFileName(input2.provider)}-${safeFileName(input2.threadId)}-${Date.now().toString(36)}.ndjson`
|
|
27968
28168
|
);
|
|
27969
|
-
const stream = (input2.openStream ?? ((path) =>
|
|
28169
|
+
const stream = (input2.openStream ?? ((path) => NodeFS2.createWriteStream(path, { flags: "a" })))(
|
|
27970
28170
|
filePath
|
|
27971
28171
|
);
|
|
27972
28172
|
let bytes = 0;
|
|
@@ -28018,7 +28218,7 @@ function createAcpProtocolLogFromEnv(input2) {
|
|
|
28018
28218
|
const flag = process.env.YCODIUM_ACP_PROTOCOL_LOG;
|
|
28019
28219
|
if (flag !== "1" && flag?.toLowerCase() !== "true") return void 0;
|
|
28020
28220
|
const configured = process.env.YCODIUM_ACP_PROTOCOL_LOG_DIR?.trim();
|
|
28021
|
-
const directory = configured && configured.length > 0 ? configured :
|
|
28221
|
+
const directory = configured && configured.length > 0 ? configured : NodePath4.join(NodeOS2.tmpdir(), "ycodium-acp-protocol");
|
|
28022
28222
|
try {
|
|
28023
28223
|
const sink = createAcpProtocolLogFile({
|
|
28024
28224
|
directory,
|
|
@@ -28042,7 +28242,7 @@ function defaultNowIso() {
|
|
|
28042
28242
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
28043
28243
|
}
|
|
28044
28244
|
function defaultRandomId() {
|
|
28045
|
-
return
|
|
28245
|
+
return NodeCrypto2.randomUUID();
|
|
28046
28246
|
}
|
|
28047
28247
|
function createAcpExecutor(options) {
|
|
28048
28248
|
const hooks = { ...defaultVendorHooks, ...options.hooks };
|
|
@@ -28318,6 +28518,9 @@ function createAcpExecutor(options) {
|
|
|
28318
28518
|
get modelId() {
|
|
28319
28519
|
return shared.modelSelectionState.currentModelId;
|
|
28320
28520
|
},
|
|
28521
|
+
get modelReported() {
|
|
28522
|
+
return shared.modelSelectionState.currentModelReported === true;
|
|
28523
|
+
},
|
|
28321
28524
|
get status() {
|
|
28322
28525
|
return shared.status;
|
|
28323
28526
|
},
|
|
@@ -28635,28 +28838,28 @@ var MAX_VERSION_OUTPUT_BYTES = 64 * 1024;
|
|
|
28635
28838
|
|
|
28636
28839
|
// src/config.ts
|
|
28637
28840
|
var GROK_DEFAULT_LAUNCH_ARGS = "agent stdio";
|
|
28638
|
-
function
|
|
28841
|
+
function isRecord7(value) {
|
|
28639
28842
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28640
28843
|
}
|
|
28641
|
-
function
|
|
28844
|
+
function readString2(value) {
|
|
28642
28845
|
return typeof value === "string" ? value : "";
|
|
28643
28846
|
}
|
|
28644
28847
|
function readTrimmed(value) {
|
|
28645
|
-
return
|
|
28848
|
+
return readString2(value).trim();
|
|
28646
28849
|
}
|
|
28647
28850
|
function readEnvironment(value) {
|
|
28648
28851
|
if (!Array.isArray(value)) return {};
|
|
28649
28852
|
const env = {};
|
|
28650
28853
|
for (const entry of value) {
|
|
28651
|
-
if (!
|
|
28854
|
+
if (!isRecord7(entry)) continue;
|
|
28652
28855
|
const name = readTrimmed(entry["name"]);
|
|
28653
28856
|
if (name.length === 0) continue;
|
|
28654
|
-
env[name] =
|
|
28857
|
+
env[name] = readString2(entry["value"]);
|
|
28655
28858
|
}
|
|
28656
28859
|
return env;
|
|
28657
28860
|
}
|
|
28658
28861
|
function parseGrokInstanceConfig(config2) {
|
|
28659
|
-
if (!
|
|
28862
|
+
if (!isRecord7(config2)) {
|
|
28660
28863
|
return {
|
|
28661
28864
|
binaryPath: "",
|
|
28662
28865
|
launchArgs: GROK_DEFAULT_LAUNCH_ARGS,
|
|
@@ -28666,11 +28869,11 @@ function parseGrokInstanceConfig(config2) {
|
|
|
28666
28869
|
envelopeDriver: void 0
|
|
28667
28870
|
};
|
|
28668
28871
|
}
|
|
28669
|
-
const nested =
|
|
28872
|
+
const nested = isRecord7(config2["config"]) ? config2["config"] : void 0;
|
|
28670
28873
|
const settings = nested ?? config2;
|
|
28671
28874
|
return {
|
|
28672
28875
|
binaryPath: readTrimmed(settings["binaryPath"]),
|
|
28673
|
-
launchArgs:
|
|
28876
|
+
launchArgs: readString2(settings["launchArgs"]) || GROK_DEFAULT_LAUNCH_ARGS,
|
|
28674
28877
|
homePath: readTrimmed(settings["homePath"]) || readTrimmed(config2["homePath"]),
|
|
28675
28878
|
homeEnvVar: readTrimmed(settings["homeEnvVar"]) || readTrimmed(config2["homeEnvVar"]),
|
|
28676
28879
|
environment: readEnvironment(config2["environment"]),
|
|
@@ -28794,166 +28997,6 @@ function readDeviceCodeOutput(stdout, onText) {
|
|
|
28794
28997
|
return { text: text4, code };
|
|
28795
28998
|
}
|
|
28796
28999
|
|
|
28797
|
-
// src/grokHome.ts
|
|
28798
|
-
import * as NodeCrypto2 from "node:crypto";
|
|
28799
|
-
import * as NodeOS2 from "node:os";
|
|
28800
|
-
import * as NodePath4 from "node:path";
|
|
28801
|
-
import { mergeLaunchEnv } from "@ycodium-ai/plugin-api/executor";
|
|
28802
|
-
|
|
28803
|
-
// src/grokAccount.ts
|
|
28804
|
-
import * as NodeFS2 from "node:fs";
|
|
28805
|
-
import * as NodePath3 from "node:path";
|
|
28806
|
-
var AUTH_FILE_NAME = "auth.json";
|
|
28807
|
-
var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28808
|
-
var readString2 = (record4, key) => {
|
|
28809
|
-
const value = record4[key];
|
|
28810
|
-
if (typeof value !== "string") return void 0;
|
|
28811
|
-
const trimmed3 = value.trim();
|
|
28812
|
-
return trimmed3.length > 0 ? trimmed3 : void 0;
|
|
28813
|
-
};
|
|
28814
|
-
var parseJsonRecord = (raw) => {
|
|
28815
|
-
let parsed;
|
|
28816
|
-
try {
|
|
28817
|
-
parsed = JSON.parse(raw);
|
|
28818
|
-
} catch {
|
|
28819
|
-
return void 0;
|
|
28820
|
-
}
|
|
28821
|
-
return isRecord7(parsed) ? parsed : void 0;
|
|
28822
|
-
};
|
|
28823
|
-
var directoryExists = (homePath) => {
|
|
28824
|
-
try {
|
|
28825
|
-
return NodeFS2.statSync(homePath).isDirectory();
|
|
28826
|
-
} catch {
|
|
28827
|
-
return false;
|
|
28828
|
-
}
|
|
28829
|
-
};
|
|
28830
|
-
var readCredentialFile = (path) => {
|
|
28831
|
-
try {
|
|
28832
|
-
return NodeFS2.readFileSync(path, "utf8");
|
|
28833
|
-
} catch {
|
|
28834
|
-
return void 0;
|
|
28835
|
-
}
|
|
28836
|
-
};
|
|
28837
|
-
var signedOutProbe = (exists) => ({
|
|
28838
|
-
state: "signed-out",
|
|
28839
|
-
directoryExists: exists,
|
|
28840
|
-
email: void 0,
|
|
28841
|
-
name: void 0,
|
|
28842
|
-
expiresAt: void 0
|
|
28843
|
-
});
|
|
28844
|
-
var unreadableProbe = (exists) => ({
|
|
28845
|
-
state: "unreadable",
|
|
28846
|
-
directoryExists: exists,
|
|
28847
|
-
email: void 0,
|
|
28848
|
-
name: void 0,
|
|
28849
|
-
expiresAt: void 0
|
|
28850
|
-
});
|
|
28851
|
-
var joinName = (record4) => {
|
|
28852
|
-
const first = readString2(record4, "first_name");
|
|
28853
|
-
const last = readString2(record4, "last_name");
|
|
28854
|
-
const joined = [first, last].filter((part) => part !== void 0).join(" ");
|
|
28855
|
-
return joined.length > 0 ? joined : void 0;
|
|
28856
|
-
};
|
|
28857
|
-
var findIdentityEntry = (parsed) => {
|
|
28858
|
-
for (const value of Object.values(parsed)) {
|
|
28859
|
-
if (!isRecord7(value)) continue;
|
|
28860
|
-
if (readString2(value, "email") !== void 0 || readString2(value, "user_id") !== void 0) {
|
|
28861
|
-
return value;
|
|
28862
|
-
}
|
|
28863
|
-
}
|
|
28864
|
-
return void 0;
|
|
28865
|
-
};
|
|
28866
|
-
var isExpired = (expiresAt, nowMs) => {
|
|
28867
|
-
if (expiresAt === void 0) return false;
|
|
28868
|
-
const parsed = Date.parse(expiresAt);
|
|
28869
|
-
return Number.isNaN(parsed) ? false : parsed <= nowMs;
|
|
28870
|
-
};
|
|
28871
|
-
var readGrokAccount = (homePath) => {
|
|
28872
|
-
const exists = directoryExists(homePath);
|
|
28873
|
-
const raw = readCredentialFile(NodePath3.join(homePath, AUTH_FILE_NAME));
|
|
28874
|
-
if (raw === void 0) return signedOutProbe(exists);
|
|
28875
|
-
const parsed = parseJsonRecord(raw);
|
|
28876
|
-
const identity = parsed === void 0 ? void 0 : findIdentityEntry(parsed);
|
|
28877
|
-
if (identity === void 0) return unreadableProbe(exists);
|
|
28878
|
-
const expiresAt = readString2(identity, "expires_at");
|
|
28879
|
-
return {
|
|
28880
|
-
state: isExpired(expiresAt, Date.now()) ? "expired" : "signed-in",
|
|
28881
|
-
directoryExists: exists,
|
|
28882
|
-
email: readString2(identity, "email"),
|
|
28883
|
-
name: joinName(identity),
|
|
28884
|
-
expiresAt
|
|
28885
|
-
};
|
|
28886
|
-
};
|
|
28887
|
-
|
|
28888
|
-
// src/grokHome.ts
|
|
28889
|
-
function expandHomePath(value) {
|
|
28890
|
-
if (value === "~") return NodeOS2.homedir();
|
|
28891
|
-
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
28892
|
-
return NodePath4.join(NodeOS2.homedir(), value.slice(2));
|
|
28893
|
-
}
|
|
28894
|
-
return value;
|
|
28895
|
-
}
|
|
28896
|
-
function resolveGrokHomePath(value) {
|
|
28897
|
-
const trimmed3 = value.trim();
|
|
28898
|
-
if (trimmed3.length === 0) return NodePath4.join(NodeOS2.homedir(), ".grok");
|
|
28899
|
-
return NodePath4.resolve(expandHomePath(trimmed3));
|
|
28900
|
-
}
|
|
28901
|
-
function probeGrokAccount(accountPath) {
|
|
28902
|
-
const resolved = resolveGrokHomePath(accountPath);
|
|
28903
|
-
const account = readGrokAccount(resolved);
|
|
28904
|
-
return {
|
|
28905
|
-
accountPath: resolved,
|
|
28906
|
-
state: account.state,
|
|
28907
|
-
...account.email === void 0 ? {} : { email: account.email },
|
|
28908
|
-
...account.name === void 0 ? {} : { name: account.name },
|
|
28909
|
-
...account.expiresAt === void 0 ? {} : { expiresAt: account.expiresAt }
|
|
28910
|
-
};
|
|
28911
|
-
}
|
|
28912
|
-
function grokContinuationKey(recipe) {
|
|
28913
|
-
return `grok:home:${resolveGrokHomePath(recipe.homePath)}`;
|
|
28914
|
-
}
|
|
28915
|
-
function resolveAccountHomePath(recipe, configuredHome) {
|
|
28916
|
-
const fromEnvironment = recipe.environment["GROK_HOME"]?.trim();
|
|
28917
|
-
if (fromEnvironment !== void 0 && fromEnvironment.length > 0) {
|
|
28918
|
-
return NodePath4.resolve(expandHomePath(fromEnvironment));
|
|
28919
|
-
}
|
|
28920
|
-
return resolveGrokHomePath(configuredHome);
|
|
28921
|
-
}
|
|
28922
|
-
function absentPath() {
|
|
28923
|
-
return NodePath4.join(
|
|
28924
|
-
NodeOS2.tmpdir(),
|
|
28925
|
-
`ycodium-grok-no-auth-${NodeCrypto2.randomUUID()}`,
|
|
28926
|
-
"auth.json"
|
|
28927
|
-
);
|
|
28928
|
-
}
|
|
28929
|
-
function ownEndpointAuthGuard(recipe) {
|
|
28930
|
-
const connectivity = GROK_CARD.modelConnectivity;
|
|
28931
|
-
const baseUrlKey = connectivity.baseUrlEnvKey;
|
|
28932
|
-
if (baseUrlKey === void 0 || (recipe.environment[baseUrlKey]?.trim() ?? "") === "") return {};
|
|
28933
|
-
const guard = {};
|
|
28934
|
-
for (const entry of connectivity.extraEnv ?? []) {
|
|
28935
|
-
if (entry.value === "$absentPath") guard[entry.name] = absentPath();
|
|
28936
|
-
}
|
|
28937
|
-
return guard;
|
|
28938
|
-
}
|
|
28939
|
-
function buildSignInEnv(recipe) {
|
|
28940
|
-
const configuredHome = recipe.homePath;
|
|
28941
|
-
const homeInjection = configuredHome.trim().length > 0 ? { [GROK_CARD.homeEnvVar]: resolveGrokHomePath(configuredHome) } : {};
|
|
28942
|
-
return mergeLaunchEnv({
|
|
28943
|
-
accountHome: homeInjection,
|
|
28944
|
-
instanceTable: recipe.environment,
|
|
28945
|
-
handOverrides: { GROK_OAUTH2_REFERRER: "ycodium" }
|
|
28946
|
-
});
|
|
28947
|
-
}
|
|
28948
|
-
function buildSpawnEnv(recipe, resolvedHomePath, homeConfigured) {
|
|
28949
|
-
const homeInjection = homeConfigured ? { [GROK_CARD.homeEnvVar]: resolvedHomePath } : {};
|
|
28950
|
-
return mergeLaunchEnv({
|
|
28951
|
-
accountHome: { ...homeInjection, ...ownEndpointAuthGuard(recipe) },
|
|
28952
|
-
instanceTable: recipe.environment,
|
|
28953
|
-
handOverrides: { GROK_OAUTH2_REFERRER: "ycodium" }
|
|
28954
|
-
});
|
|
28955
|
-
}
|
|
28956
|
-
|
|
28957
29000
|
// src/grokSignIn.ts
|
|
28958
29001
|
function makeGrokSignIn(input2) {
|
|
28959
29002
|
const { host, recipe } = input2;
|
|
@@ -30780,7 +30823,11 @@ var createGrokInstance = (config2, host) => {
|
|
|
30780
30823
|
createdAt,
|
|
30781
30824
|
updatedAt: createdAt,
|
|
30782
30825
|
resumeCursor,
|
|
30783
|
-
...started.modelId === void 0 ? {} : {
|
|
30826
|
+
...started.modelId === void 0 ? {} : {
|
|
30827
|
+
model: started.modelId,
|
|
30828
|
+
// agent 在握手里报的才是读回的;切型号走 session/set_model 时回包不带型号,那只是请求值。
|
|
30829
|
+
modelSource: started.modelReported ? "reported" : "echo"
|
|
30830
|
+
},
|
|
30784
30831
|
...input2.bindingGeneration === void 0 ? {} : { bindingGeneration: input2.bindingGeneration }
|
|
30785
30832
|
};
|
|
30786
30833
|
registerSession(input2.threadId, {
|
|
@@ -30921,6 +30968,7 @@ var createGrokInstance = (config2, host) => {
|
|
|
30921
30968
|
var executors = [
|
|
30922
30969
|
{
|
|
30923
30970
|
card: GROK_CARD,
|
|
30971
|
+
lifecycle: [{ kind: "detect", reversible: true }],
|
|
30924
30972
|
createInstance: async (config2, host) => {
|
|
30925
30973
|
host.log.info("createInstance");
|
|
30926
30974
|
return createGrokInstance(config2, host);
|
|
@@ -30930,9 +30978,26 @@ var executors = [
|
|
|
30930
30978
|
];
|
|
30931
30979
|
var index_default = definePlugin({
|
|
30932
30980
|
id: "agent-grok",
|
|
30933
|
-
apiVersion:
|
|
30981
|
+
apiVersion: 56,
|
|
30934
30982
|
executors,
|
|
30935
30983
|
activate(ctx) {
|
|
30984
|
+
ctx.command({
|
|
30985
|
+
name: "effectiveConfig",
|
|
30986
|
+
description: "Settings form: the account directory an empty path resolves to on this machine.",
|
|
30987
|
+
scope: "read",
|
|
30988
|
+
payloadSchema: EXECUTOR_EFFECTIVE_PAYLOAD_SCHEMA,
|
|
30989
|
+
handle: async (payload) => {
|
|
30990
|
+
const request = readExecutorEffectiveRequest(payload);
|
|
30991
|
+
return {
|
|
30992
|
+
homePath: executorHomeEffectiveValue(
|
|
30993
|
+
"GROK_HOME",
|
|
30994
|
+
request,
|
|
30995
|
+
process.env,
|
|
30996
|
+
(value) => resolveGrokHomePath(value ?? "")
|
|
30997
|
+
)
|
|
30998
|
+
};
|
|
30999
|
+
}
|
|
31000
|
+
});
|
|
30936
31001
|
ctx.log.info("grok executor ready");
|
|
30937
31002
|
}
|
|
30938
31003
|
});
|
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.3766",
|
|
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.3766",
|
|
25
|
+
"ycodium-acp-executor": "0.2.3766",
|
|
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
|
{
|