@ycodium-ai/agent-grok 0.2.3766 → 0.2.3851
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 +135 -50
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -88,7 +88,10 @@ var GROK_CARD = {
|
|
|
88
88
|
// 压缩生命周期事件报;CLI 没宣告这条命令时 `compactContext` 拒绝,不退回发文本。
|
|
89
89
|
contextCompaction: "native",
|
|
90
90
|
// 子 agent 经父会话上的 subagent_* 通知报成 task.*(grokSubagents.ts)。
|
|
91
|
-
reportsSpawnedAgents: true
|
|
91
|
+
reportsSpawnedAgents: true,
|
|
92
|
+
// 插话:起会话前在配置里打开 `follow_up_behavior = "steer"`(grokFollowUpSteer.ts),运行中再发的 prompt
|
|
93
|
+
// 由 grok 在下一个工具调用结束时并进这一轮(1.0.70 ACP 模式实测);执行器不等前一条应答就写出去。
|
|
94
|
+
turnSteering: true
|
|
92
95
|
},
|
|
93
96
|
// 凭据由 CLI 自己保管在 `<GROK_HOME>/auth.json`,宿主读它只认 `/token`。
|
|
94
97
|
credentialSources: [
|
|
@@ -26288,6 +26291,7 @@ function createExecutorPrompt({
|
|
|
26288
26291
|
promptResults,
|
|
26289
26292
|
settleToolSubagents
|
|
26290
26293
|
}) {
|
|
26294
|
+
const ownOutcomes = /* @__PURE__ */ new Map();
|
|
26291
26295
|
const settleTurn = (input2) => {
|
|
26292
26296
|
if (!isLive(input2.expectedGeneration) || input2.record.finished) {
|
|
26293
26297
|
return false;
|
|
@@ -26304,14 +26308,22 @@ function createExecutorPrompt({
|
|
|
26304
26308
|
}
|
|
26305
26309
|
closeActiveAssistantSegment(input2.turnId);
|
|
26306
26310
|
shared.promptsInFlight = Math.max(0, shared.promptsInFlight - 1);
|
|
26307
|
-
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);
|
|
26308
26317
|
shared.activeTurnId = void 0;
|
|
26309
26318
|
if (shared.status !== "disposed") {
|
|
26310
26319
|
shared.status = "ready";
|
|
26311
26320
|
}
|
|
26312
26321
|
const interrupted = promptResults.hasInterrupted(input2.turnId);
|
|
26313
26322
|
settleToolSubagents(
|
|
26314
|
-
toolSubagentSettlementOfTurn(
|
|
26323
|
+
toolSubagentSettlementOfTurn(
|
|
26324
|
+
interrupted ? "cancelled" : outcome.state,
|
|
26325
|
+
outcome.failureCategory
|
|
26326
|
+
),
|
|
26315
26327
|
input2.turnId
|
|
26316
26328
|
);
|
|
26317
26329
|
emit({
|
|
@@ -26321,10 +26333,10 @@ function createExecutorPrompt({
|
|
|
26321
26333
|
threadId: options.threadId,
|
|
26322
26334
|
turnId: input2.turnId,
|
|
26323
26335
|
payload: {
|
|
26324
|
-
state: interrupted ? "cancelled" :
|
|
26325
|
-
stopReason: interrupted ? "cancelled" :
|
|
26326
|
-
...
|
|
26327
|
-
...
|
|
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) : {}
|
|
26328
26340
|
}
|
|
26329
26341
|
});
|
|
26330
26342
|
interruptedTurnIds.delete(input2.turnId);
|
|
@@ -26349,7 +26361,7 @@ function createExecutorPrompt({
|
|
|
26349
26361
|
return await promptRpc;
|
|
26350
26362
|
} else {
|
|
26351
26363
|
const { promise: early, resolve: settleEarly } = Promise.withResolvers();
|
|
26352
|
-
shared.
|
|
26364
|
+
shared.pendingSettlements.set(promptKey, {
|
|
26353
26365
|
promptKey,
|
|
26354
26366
|
sessionId,
|
|
26355
26367
|
settle: settleEarly,
|
|
@@ -26358,7 +26370,7 @@ function createExecutorPrompt({
|
|
|
26358
26370
|
onError: () => promptResults.reject(record4.promptId),
|
|
26359
26371
|
hasResult: () => record4.response !== void 0
|
|
26360
26372
|
}
|
|
26361
|
-
};
|
|
26373
|
+
});
|
|
26362
26374
|
try {
|
|
26363
26375
|
const outcome = await Promise.race([
|
|
26364
26376
|
promptRpc.then((value) => {
|
|
@@ -26371,7 +26383,7 @@ function createExecutorPrompt({
|
|
|
26371
26383
|
if (outcome.error !== void 0) throw outcome.error;
|
|
26372
26384
|
return outcome.response;
|
|
26373
26385
|
} finally {
|
|
26374
|
-
shared.
|
|
26386
|
+
shared.pendingSettlements.delete(promptKey);
|
|
26375
26387
|
void promptRpc.catch(() => void 0);
|
|
26376
26388
|
}
|
|
26377
26389
|
}
|
|
@@ -26521,7 +26533,9 @@ function createExecutorPrompt({
|
|
|
26521
26533
|
settle2({
|
|
26522
26534
|
turnId,
|
|
26523
26535
|
stopReason,
|
|
26524
|
-
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
|
|
26525
26539
|
});
|
|
26526
26540
|
return {
|
|
26527
26541
|
threadId: options.threadId,
|
|
@@ -26530,7 +26544,8 @@ function createExecutorPrompt({
|
|
|
26530
26544
|
...response2.usage !== void 0 && response2.usage !== null ? { usage: response2.usage } : {}
|
|
26531
26545
|
};
|
|
26532
26546
|
};
|
|
26533
|
-
|
|
26547
|
+
const writesWhileRunning = input2.expectedActiveTurnId !== void 0 && hooks.queuesPromptsWhileRunning === true;
|
|
26548
|
+
if (!writesWhileRunning) await promptMutex.acquire();
|
|
26534
26549
|
let response;
|
|
26535
26550
|
try {
|
|
26536
26551
|
failIfDisposed();
|
|
@@ -26612,7 +26627,7 @@ function createExecutorPrompt({
|
|
|
26612
26627
|
await options.beforeApplyResult();
|
|
26613
26628
|
}
|
|
26614
26629
|
} finally {
|
|
26615
|
-
promptMutex.release();
|
|
26630
|
+
if (!writesWhileRunning) promptMutex.release();
|
|
26616
26631
|
notifyPromptSettled();
|
|
26617
26632
|
}
|
|
26618
26633
|
if (!isLive(started.generation)) {
|
|
@@ -27655,28 +27670,29 @@ function createExecutorSettlement({
|
|
|
27655
27670
|
if (settledPromptKeys.length > SETTLED_PROMPT_KEY_LIMIT) settledPromptKeys.shift();
|
|
27656
27671
|
};
|
|
27657
27672
|
const abortPendingSettlement = (reason, failureCategory) => {
|
|
27658
|
-
const waiting
|
|
27659
|
-
|
|
27660
|
-
|
|
27661
|
-
|
|
27662
|
-
|
|
27663
|
-
|
|
27664
|
-
|
|
27665
|
-
|
|
27666
|
-
)
|
|
27667
|
-
}
|
|
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
|
+
}
|
|
27668
27683
|
};
|
|
27669
27684
|
const settleFromNotification = (method, params) => {
|
|
27670
27685
|
const hook = hooks.promptSettlement;
|
|
27671
|
-
if (hook === void 0 || shared.
|
|
27686
|
+
if (hook === void 0 || shared.pendingSettlements.size === 0) return false;
|
|
27672
27687
|
const signal = hook.fromNotification(method, params);
|
|
27673
27688
|
if (signal === void 0) return false;
|
|
27674
|
-
const waiting = shared.
|
|
27675
|
-
|
|
27676
|
-
|
|
27677
|
-
|
|
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);
|
|
27678
27694
|
}
|
|
27679
|
-
shared.
|
|
27695
|
+
shared.pendingSettlements.delete(waiting.promptKey);
|
|
27680
27696
|
rememberSettledPromptKey(waiting.promptKey);
|
|
27681
27697
|
if (signal.outcome === "error") {
|
|
27682
27698
|
waiting.onError?.();
|
|
@@ -28270,7 +28286,7 @@ function createAcpExecutor(options) {
|
|
|
28270
28286
|
startInFlight: void 0,
|
|
28271
28287
|
activeTurnId: void 0,
|
|
28272
28288
|
promptsInFlight: 0,
|
|
28273
|
-
|
|
28289
|
+
pendingSettlements: /* @__PURE__ */ new Map(),
|
|
28274
28290
|
manualCompaction: void 0,
|
|
28275
28291
|
assistantSegment: { nextSegmentIndex: 0 },
|
|
28276
28292
|
modeState: void 0,
|
|
@@ -29238,30 +29254,38 @@ var grokTurnUsageReport = (promptResponse) => {
|
|
|
29238
29254
|
...sessionId === void 0 ? {} : { sessionId }
|
|
29239
29255
|
};
|
|
29240
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
|
+
};
|
|
29241
29269
|
var createGrokTurnUsageCollector = (base) => {
|
|
29242
29270
|
const pastKeys = [];
|
|
29243
|
-
|
|
29244
|
-
|
|
29245
|
-
let
|
|
29271
|
+
const turn = /* @__PURE__ */ new Map();
|
|
29272
|
+
const answered = /* @__PURE__ */ new Set();
|
|
29273
|
+
let latestKey;
|
|
29246
29274
|
let wake;
|
|
29247
|
-
const
|
|
29248
|
-
seen = true;
|
|
29249
|
-
wake?.();
|
|
29250
|
-
};
|
|
29275
|
+
const allAnswered = () => [...turn.keys()].every((key) => answered.has(key));
|
|
29251
29276
|
const observe = (response) => {
|
|
29252
|
-
const key = base.responseKey?.(response);
|
|
29253
|
-
if (key
|
|
29254
|
-
|
|
29255
|
-
|
|
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?.();
|
|
29256
29283
|
};
|
|
29257
29284
|
const settlement = {
|
|
29258
29285
|
...base,
|
|
29259
29286
|
requestFields: (key) => {
|
|
29260
|
-
|
|
29261
|
-
|
|
29262
|
-
promptKey = key;
|
|
29263
|
-
report = void 0;
|
|
29264
|
-
seen = false;
|
|
29287
|
+
turn.set(key, void 0);
|
|
29288
|
+
latestKey = key;
|
|
29265
29289
|
return base.requestFields(key);
|
|
29266
29290
|
},
|
|
29267
29291
|
responseKey: (response) => {
|
|
@@ -29271,7 +29295,7 @@ var createGrokTurnUsageCollector = (base) => {
|
|
|
29271
29295
|
};
|
|
29272
29296
|
const attach = async (event) => {
|
|
29273
29297
|
if (event.type !== "turn.completed" || !isRecord8(event.payload)) return event;
|
|
29274
|
-
if (event.payload["state"] === "completed" && !
|
|
29298
|
+
if (event.payload["state"] === "completed" && !allAnswered()) {
|
|
29275
29299
|
await new Promise((resolve2) => {
|
|
29276
29300
|
const timer = setTimeout(resolve2, USAGE_GRACE_MS);
|
|
29277
29301
|
wake = () => {
|
|
@@ -29281,8 +29305,12 @@ var createGrokTurnUsageCollector = (base) => {
|
|
|
29281
29305
|
});
|
|
29282
29306
|
wake = void 0;
|
|
29283
29307
|
}
|
|
29284
|
-
|
|
29285
|
-
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();
|
|
29286
29314
|
return taken === void 0 ? event : { ...event, payload: { ...event.payload, tokenUsage: taken } };
|
|
29287
29315
|
};
|
|
29288
29316
|
return { settlement, attach };
|
|
@@ -30489,6 +30517,55 @@ function createGrokModelCatalog(input2) {
|
|
|
30489
30517
|
return { readCliVersion, refreshModelCatalog, refreshForSend };
|
|
30490
30518
|
}
|
|
30491
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
|
+
|
|
30492
30569
|
// src/grokInstance.ts
|
|
30493
30570
|
var RESUME_SCHEMA_VERSION = 1;
|
|
30494
30571
|
var yieldTick = () => new Promise((resolve2) => {
|
|
@@ -30603,6 +30680,7 @@ var createGrokInstance = (config2, host) => {
|
|
|
30603
30680
|
detail: "Grok program path is not configured"
|
|
30604
30681
|
};
|
|
30605
30682
|
}
|
|
30683
|
+
prepareGrokFollowUpSteer(resolveAccountHomePath(recipe, recipe.homePath), host.log);
|
|
30606
30684
|
const env = spawnEnv();
|
|
30607
30685
|
const version2 = await raceAbort3(modelCatalog.readCliVersion(signal), signal);
|
|
30608
30686
|
if (signal?.aborted) throw new Error("aborted");
|
|
@@ -30691,6 +30769,11 @@ var createGrokInstance = (config2, host) => {
|
|
|
30691
30769
|
if (disposed) throw new Error("instance disposed");
|
|
30692
30770
|
throwIfStartAborted(signal);
|
|
30693
30771
|
}
|
|
30772
|
+
prepareGrokFollowUpSteer(
|
|
30773
|
+
resolveAccountHomePath(recipe, recipe.homePath),
|
|
30774
|
+
host.log,
|
|
30775
|
+
input2.threadId
|
|
30776
|
+
);
|
|
30694
30777
|
const env = spawnEnv();
|
|
30695
30778
|
const effort = modelSelectionStringOption(input2.modelSelection, GROK_REASONING_OPTION_ID);
|
|
30696
30779
|
const baseArgs = tokenizeLaunchArgs(recipe.launchArgs);
|
|
@@ -30737,6 +30820,8 @@ var createGrokInstance = (config2, host) => {
|
|
|
30737
30820
|
authMethodId: resolveGrokAuthMethodId,
|
|
30738
30821
|
hooks: {
|
|
30739
30822
|
promptSettlement: turnUsage.settlement,
|
|
30823
|
+
// 运行中再收到的 prompt 由 grok 自己排队、在下一个工具调用结束时并进这一轮(配合上面写的配置)。
|
|
30824
|
+
queuesPromptsWhileRunning: true,
|
|
30740
30825
|
modelDefaultEffort: grokModelDefaultEffort,
|
|
30741
30826
|
// 派发子 agent 的调用由子 agent 名单接管,不再画成普通工具。
|
|
30742
30827
|
onToolCallUpdated: (update) => ({
|
|
@@ -30978,7 +31063,7 @@ var executors = [
|
|
|
30978
31063
|
];
|
|
30979
31064
|
var index_default = definePlugin({
|
|
30980
31065
|
id: "agent-grok",
|
|
30981
|
-
apiVersion:
|
|
31066
|
+
apiVersion: 63,
|
|
30982
31067
|
executors,
|
|
30983
31068
|
activate(ctx) {
|
|
30984
31069
|
ctx.command({
|
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.3851",
|
|
4
4
|
"description": "Grok executor: grok CLI over Agent Client Protocol stdio.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"@types/node": "24.12.4",
|
|
22
22
|
"esbuild": "0.28.1",
|
|
23
23
|
"vite-plus": "0.2.2",
|
|
24
|
-
"
|
|
25
|
-
"ycodium-
|
|
26
|
-
"ycodium-executor
|
|
24
|
+
"ycodium-executor-testing": "0.0.0",
|
|
25
|
+
"@ycodium-ai/plugin-api": "0.2.3851",
|
|
26
|
+
"ycodium-acp-executor": "0.2.3851"
|
|
27
27
|
},
|
|
28
28
|
"ycodium": {
|
|
29
29
|
"plugin": "./dist/index.js",
|