laohuang 0.9.5 → 0.9.6
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/bin.js +159 -148
- package/dist/bin.js.map +3 -3
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -9264,8 +9264,12 @@ var ContextGovernor = class {
|
|
|
9264
9264
|
retainTokens: input.reserveTokens === void 0 ? calculated.retainTokens : 1,
|
|
9265
9265
|
estimator: this.#estimator
|
|
9266
9266
|
});
|
|
9267
|
-
if (
|
|
9268
|
-
|
|
9267
|
+
if (plan.summarizedEntries.length === 0) {
|
|
9268
|
+
if (input.trigger === "manual")
|
|
9269
|
+
throw new Error("No messages to compact in current history.");
|
|
9270
|
+
if (input.trigger === "provider_overflow") {
|
|
9271
|
+
throw new ContextBudgetError("No earlier messages to compact after provider overflow.");
|
|
9272
|
+
}
|
|
9269
9273
|
}
|
|
9270
9274
|
const summarizedFromSeq = plan.summarizedEntries[0]?.seq ?? 1;
|
|
9271
9275
|
const summarizedThroughSeq = plan.summarizedEntries.at(-1)?.seq ?? Math.max(0, summarizedFromSeq - 1);
|
|
@@ -9306,10 +9310,13 @@ var ContextGovernor = class {
|
|
|
9306
9310
|
throw error;
|
|
9307
9311
|
}
|
|
9308
9312
|
}
|
|
9309
|
-
|
|
9310
|
-
prepared = await this.prepare({ ...input, entries: [...input.entries, compaction.entry] });
|
|
9313
|
+
prepared = await this.recoverAfterOverflow(input);
|
|
9311
9314
|
return await send(prepared);
|
|
9312
9315
|
}
|
|
9316
|
+
async recoverAfterOverflow(input) {
|
|
9317
|
+
const compaction = await this.compact({ ...input, trigger: "provider_overflow" });
|
|
9318
|
+
return this.prepare({ ...input, entries: [...input.entries, compaction.entry] });
|
|
9319
|
+
}
|
|
9313
9320
|
measure(input, built) {
|
|
9314
9321
|
const tools = input.projectTools?.(built.messages) ?? input.tools;
|
|
9315
9322
|
return this.#estimator.measure({
|
|
@@ -32495,7 +32502,7 @@ var AgentStepRunner = class {
|
|
|
32495
32502
|
}
|
|
32496
32503
|
modelRound += 1;
|
|
32497
32504
|
modelRequests += 1;
|
|
32498
|
-
|
|
32505
|
+
let requestId = modelRound === 1 && this.options.requestId !== null ? this.options.requestId : randomUUID10();
|
|
32499
32506
|
this.options.onRequestId(requestId);
|
|
32500
32507
|
const registry = this.options.getTools();
|
|
32501
32508
|
const selection = this.options.selection ?? new ToolSelection();
|
|
@@ -32533,96 +32540,137 @@ var AgentStepRunner = class {
|
|
|
32533
32540
|
throw error;
|
|
32534
32541
|
}
|
|
32535
32542
|
}, () => history.snapshot().map((message) => message.role === "system" || message.role === "user" ? message : {}));
|
|
32536
|
-
|
|
32537
|
-
|
|
32538
|
-
|
|
32539
|
-
|
|
32540
|
-
|
|
32541
|
-
|
|
32542
|
-
|
|
32543
|
-
|
|
32544
|
-
|
|
32545
|
-
|
|
32546
|
-
|
|
32547
|
-
|
|
32548
|
-
|
|
32549
|
-
|
|
32550
|
-
|
|
32551
|
-
|
|
32552
|
-
|
|
32553
|
-
|
|
32554
|
-
|
|
32555
|
-
|
|
32556
|
-
|
|
32557
|
-
|
|
32558
|
-
|
|
32559
|
-
|
|
32560
|
-
|
|
32561
|
-
}
|
|
32562
|
-
remainingTokens = prepared.hardInputLimit === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, prepared.hardInputLimit - (prepared.contextTokens ?? 0) - 1024);
|
|
32563
|
-
const tools = selected.view;
|
|
32564
|
-
const definitions = tools.definitions;
|
|
32565
|
-
const requestMessages = [...prepared.messages];
|
|
32566
|
-
this.emit("model_request", {
|
|
32567
|
-
round: modelRound,
|
|
32568
|
-
request_id: requestId,
|
|
32569
|
-
message_count: requestMessages.length,
|
|
32570
|
-
tool_rounds: toolRounds,
|
|
32571
|
-
model_requests: modelRequests,
|
|
32572
|
-
total_tokens: totalTokens,
|
|
32573
|
-
...prepared.contextTokens === void 0 ? {} : { context_tokens: prepared.contextTokens },
|
|
32574
|
-
...prepared.contextWindow === void 0 ? {} : { context_window: prepared.contextWindow }
|
|
32575
|
-
});
|
|
32576
|
-
let result;
|
|
32577
|
-
try {
|
|
32578
|
-
const modelRequestOpened = context?.modelRequestOpened;
|
|
32579
|
-
result = await this.options.modelRuntime.complete({
|
|
32580
|
-
provider: this.options.provider,
|
|
32581
|
-
model: this.options.model,
|
|
32582
|
-
...this.options.baseUrl === null ? {} : { baseUrl: this.options.baseUrl },
|
|
32583
|
-
messages: requestMessages,
|
|
32584
|
-
tools: definitions,
|
|
32585
|
-
reasoningEffort: this.options.getReasoningEffort(),
|
|
32586
|
-
requestId,
|
|
32587
|
-
cancelToken,
|
|
32588
|
-
isRequestActive: this.options.isRequestActive,
|
|
32589
|
-
onDelta: (kind, payload) => {
|
|
32590
|
-
this.emit(kind, { round: modelRound, request_id: requestId, ...payload });
|
|
32591
|
-
},
|
|
32592
|
-
onRequestOpened: () => {
|
|
32593
|
-
if (modelRequestOpened?.call(context) === false)
|
|
32594
|
-
return false;
|
|
32595
|
-
this.options.resources?.committed(pendingResourceInputs);
|
|
32596
|
-
pendingResourceInputs = [];
|
|
32597
|
-
return true;
|
|
32543
|
+
const prepareRequest = async () => {
|
|
32544
|
+
let selected2 = select(history.snapshot());
|
|
32545
|
+
if (selected2.announcement)
|
|
32546
|
+
history.commitToolContext({ role: "user", ...selected2.announcement });
|
|
32547
|
+
let prepared2 = { messages: history.snapshot() };
|
|
32548
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
32549
|
+
prepared2 = await this.options.contextGovernor?.prepare({
|
|
32550
|
+
messages: history.snapshot(),
|
|
32551
|
+
tools: selected2.view.definitions,
|
|
32552
|
+
provider: this.options.provider,
|
|
32553
|
+
model: this.options.model,
|
|
32554
|
+
projectTools: (messages) => select(messages).view.definitions
|
|
32555
|
+
}) ?? { messages: history.snapshot() };
|
|
32556
|
+
history.retain(prepared2.messages);
|
|
32557
|
+
selected2 = select(prepared2.messages);
|
|
32558
|
+
const resources = await this.options.resources?.prepareContext(prepared2.messages, cancelToken?.signal) ?? [];
|
|
32559
|
+
if (!selected2.announcement && resources.length === 0)
|
|
32560
|
+
break;
|
|
32561
|
+
if (attempt === 2)
|
|
32562
|
+
throw this.options.createError("Resource catalog cannot fit the retained context.");
|
|
32563
|
+
if (selected2.announcement)
|
|
32564
|
+
history.commitToolContext({ role: "user", ...selected2.announcement });
|
|
32565
|
+
for (const message of resources) {
|
|
32566
|
+
history.commitSkillContext(message);
|
|
32567
|
+
this.options.resources?.committed([message]);
|
|
32598
32568
|
}
|
|
32569
|
+
}
|
|
32570
|
+
remainingTokens = prepared2.hardInputLimit === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, prepared2.hardInputLimit - (prepared2.contextTokens ?? 0) - 1024);
|
|
32571
|
+
return { selected: selected2, prepared: prepared2 };
|
|
32572
|
+
};
|
|
32573
|
+
let { selected, prepared } = await prepareRequest();
|
|
32574
|
+
let tools = selected.view;
|
|
32575
|
+
let definitions = tools.definitions;
|
|
32576
|
+
let requestMessages = [...prepared.messages];
|
|
32577
|
+
let result;
|
|
32578
|
+
for (let overflowAttempt = 0; ; overflowAttempt++) {
|
|
32579
|
+
const attemptRequestId = requestId;
|
|
32580
|
+
const attemptRound = modelRound;
|
|
32581
|
+
this.emit("model_request", {
|
|
32582
|
+
round: attemptRound,
|
|
32583
|
+
request_id: attemptRequestId,
|
|
32584
|
+
message_count: requestMessages.length,
|
|
32585
|
+
tool_rounds: toolRounds,
|
|
32586
|
+
model_requests: modelRequests,
|
|
32587
|
+
total_tokens: totalTokens,
|
|
32588
|
+
...prepared.contextTokens === void 0 ? {} : { context_tokens: prepared.contextTokens },
|
|
32589
|
+
...prepared.contextWindow === void 0 ? {} : { context_window: prepared.contextWindow }
|
|
32599
32590
|
});
|
|
32600
|
-
|
|
32601
|
-
|
|
32602
|
-
this.
|
|
32603
|
-
|
|
32604
|
-
|
|
32605
|
-
|
|
32591
|
+
try {
|
|
32592
|
+
const modelRequestOpened = context?.modelRequestOpened;
|
|
32593
|
+
result = await this.options.modelRuntime.complete({
|
|
32594
|
+
provider: this.options.provider,
|
|
32595
|
+
model: this.options.model,
|
|
32596
|
+
...this.options.baseUrl === null ? {} : { baseUrl: this.options.baseUrl },
|
|
32597
|
+
messages: requestMessages,
|
|
32598
|
+
tools: definitions,
|
|
32599
|
+
reasoningEffort: this.options.getReasoningEffort(),
|
|
32600
|
+
requestId: attemptRequestId,
|
|
32601
|
+
cancelToken,
|
|
32602
|
+
isRequestActive: this.options.isRequestActive,
|
|
32603
|
+
onDelta: (kind, payload) => {
|
|
32604
|
+
this.emit(kind, { round: attemptRound, request_id: attemptRequestId, ...payload });
|
|
32605
|
+
},
|
|
32606
|
+
onRequestOpened: () => {
|
|
32607
|
+
if (modelRequestOpened?.call(context) === false)
|
|
32608
|
+
return false;
|
|
32609
|
+
this.options.resources?.committed(pendingResourceInputs);
|
|
32610
|
+
pendingResourceInputs = [];
|
|
32611
|
+
return true;
|
|
32612
|
+
}
|
|
32606
32613
|
});
|
|
32607
|
-
|
|
32608
|
-
}
|
|
32609
|
-
|
|
32610
|
-
|
|
32611
|
-
|
|
32612
|
-
|
|
32613
|
-
|
|
32614
|
-
|
|
32615
|
-
|
|
32616
|
-
|
|
32617
|
-
|
|
32618
|
-
|
|
32619
|
-
|
|
32620
|
-
|
|
32621
|
-
|
|
32622
|
-
|
|
32614
|
+
break;
|
|
32615
|
+
} catch (error) {
|
|
32616
|
+
if (error instanceof ModelStreamCancelled) {
|
|
32617
|
+
this.emit("model_response_aborted", {
|
|
32618
|
+
round: attemptRound,
|
|
32619
|
+
request_id: attemptRequestId,
|
|
32620
|
+
reason: errorMessage10(error)
|
|
32621
|
+
});
|
|
32622
|
+
throw this.options.createCancelled(errorMessage10(error), error);
|
|
32623
|
+
}
|
|
32624
|
+
const errorPayload = {
|
|
32625
|
+
round: attemptRound,
|
|
32626
|
+
request_id: attemptRequestId,
|
|
32627
|
+
error: errorMessage10(error)
|
|
32628
|
+
};
|
|
32629
|
+
if (error instanceof ModelStreamError && error.hadDelta) {
|
|
32630
|
+
this.emit("model_response_aborted", errorPayload);
|
|
32631
|
+
this.options.emitLegacy("model_error", errorPayload);
|
|
32632
|
+
} else {
|
|
32633
|
+
this.emit("model_error", errorPayload);
|
|
32634
|
+
}
|
|
32635
|
+
if (overflowAttempt === 0 && error instanceof ModelError && error.kind === "context_overflow" && !error.hadDelta && this.options.contextGovernor?.recoverAfterOverflow !== void 0) {
|
|
32636
|
+
this.raiseIfCancelled();
|
|
32637
|
+
const recovered = await this.options.contextGovernor.recoverAfterOverflow({
|
|
32638
|
+
messages: history.snapshot(),
|
|
32639
|
+
tools: definitions,
|
|
32640
|
+
provider: this.options.provider,
|
|
32641
|
+
model: this.options.model,
|
|
32642
|
+
projectTools: (messages) => select(messages).view.definitions
|
|
32643
|
+
});
|
|
32644
|
+
this.raiseIfCancelled();
|
|
32645
|
+
history.retain(recovered.messages);
|
|
32646
|
+
remainingTokens = Number.POSITIVE_INFINITY;
|
|
32647
|
+
preflightCompacted = false;
|
|
32648
|
+
({ selected, prepared } = await prepareRequest());
|
|
32649
|
+
this.raiseIfCancelled();
|
|
32650
|
+
tools = selected.view;
|
|
32651
|
+
definitions = tools.definitions;
|
|
32652
|
+
requestMessages = [...prepared.messages];
|
|
32653
|
+
this.emit("model_retry_scheduled", {
|
|
32654
|
+
round: attemptRound,
|
|
32655
|
+
request_id: attemptRequestId,
|
|
32656
|
+
attempt: 2,
|
|
32657
|
+
max_attempts: 2,
|
|
32658
|
+
delay_ms: 0,
|
|
32659
|
+
error_kind: "context_overflow"
|
|
32660
|
+
});
|
|
32661
|
+
modelRound += 1;
|
|
32662
|
+
modelRequests += 1;
|
|
32663
|
+
requestId = randomUUID10();
|
|
32664
|
+
this.options.onRequestId(requestId);
|
|
32665
|
+
continue;
|
|
32666
|
+
}
|
|
32667
|
+
let message = `Model request failed: ${errorMessage10(error)}`;
|
|
32668
|
+
if (this.options.provider && modelErrorKind(error) === "authentication") {
|
|
32669
|
+
message += `
|
|
32623
32670
|
Authentication failed for ${this.options.provider}. Run /login ${this.options.provider} to update your API key.`;
|
|
32671
|
+
}
|
|
32672
|
+
throw this.options.createError(message, error);
|
|
32624
32673
|
}
|
|
32625
|
-
throw this.options.createError(message, error);
|
|
32626
32674
|
}
|
|
32627
32675
|
const toolCalls = toolCallsOf(result.message);
|
|
32628
32676
|
let requestTokens = usageTotalTokens(result.usage);
|
|
@@ -33520,6 +33568,25 @@ function createSessionRuntime(options) {
|
|
|
33520
33568
|
contextWindow: selectedModel.contextWindow,
|
|
33521
33569
|
hardInputLimit: selectedModel.contextWindow - selectedModel.maxTokens
|
|
33522
33570
|
};
|
|
33571
|
+
},
|
|
33572
|
+
recoverAfterOverflow: async ({ tools, projectTools: projectTools2 }) => {
|
|
33573
|
+
const history = activeHistory(options.sessionController);
|
|
33574
|
+
const prepared = await createGovernor(history).recoverAfterOverflow({
|
|
33575
|
+
protectedFromSeq: attachmentTurnStart,
|
|
33576
|
+
entries: history.entries(),
|
|
33577
|
+
currentProvider: route.provider,
|
|
33578
|
+
currentModel: route.model,
|
|
33579
|
+
tools,
|
|
33580
|
+
projectTools: projectTools2,
|
|
33581
|
+
budget: modelBudget(selectedModel),
|
|
33582
|
+
policy: defaultContextPolicy()
|
|
33583
|
+
});
|
|
33584
|
+
return {
|
|
33585
|
+
messages: prepared.messages,
|
|
33586
|
+
contextTokens: prepared.tokens,
|
|
33587
|
+
contextWindow: selectedModel.contextWindow,
|
|
33588
|
+
hardInputLimit: selectedModel.contextWindow - selectedModel.maxTokens
|
|
33589
|
+
};
|
|
33523
33590
|
}
|
|
33524
33591
|
}
|
|
33525
33592
|
});
|
|
@@ -38703,64 +38770,7 @@ async function handleCommandResult(presenter, suggestCommand, result) {
|
|
|
38703
38770
|
return true;
|
|
38704
38771
|
}
|
|
38705
38772
|
async function runSessionRepl(session, options) {
|
|
38706
|
-
|
|
38707
|
-
return runPersistentSessionRepl(session, options);
|
|
38708
|
-
}
|
|
38709
|
-
return runClassicSessionRepl(session, options);
|
|
38710
|
-
}
|
|
38711
|
-
async function runClassicSessionRepl(session, options) {
|
|
38712
|
-
const { commandHandler, presenter, suggestCommand, ui } = options;
|
|
38713
|
-
ui.startEventRenderer?.();
|
|
38714
|
-
ui.showWelcome?.();
|
|
38715
|
-
let cleanShutdown = false;
|
|
38716
|
-
try {
|
|
38717
|
-
for (; ; ) {
|
|
38718
|
-
let userInput;
|
|
38719
|
-
try {
|
|
38720
|
-
const prompt = ui.prompt;
|
|
38721
|
-
if (typeof prompt !== "function") {
|
|
38722
|
-
throw new Error("Classic session UI requires a prompt function.");
|
|
38723
|
-
}
|
|
38724
|
-
userInput = await prompt.call(ui);
|
|
38725
|
-
if (!/^\s*\/skill:/.test(userInput)) userInput = userInput.trim();
|
|
38726
|
-
} catch (error) {
|
|
38727
|
-
if (isEofError(error)) {
|
|
38728
|
-
break;
|
|
38729
|
-
}
|
|
38730
|
-
if (isInterruptedError(error)) {
|
|
38731
|
-
presentNotice(presenter, "Interrupted.", "warning");
|
|
38732
|
-
continue;
|
|
38733
|
-
}
|
|
38734
|
-
throw error;
|
|
38735
|
-
}
|
|
38736
|
-
const keepGoing = await handleSessionInput(
|
|
38737
|
-
session,
|
|
38738
|
-
commandHandler,
|
|
38739
|
-
presenter,
|
|
38740
|
-
suggestCommand,
|
|
38741
|
-
userInput
|
|
38742
|
-
);
|
|
38743
|
-
if (!keepGoing) {
|
|
38744
|
-
break;
|
|
38745
|
-
}
|
|
38746
|
-
}
|
|
38747
|
-
} finally {
|
|
38748
|
-
cleanShutdown = await session.close({ wait: true, timeoutMs: 1e4 });
|
|
38749
|
-
if (cleanShutdown) {
|
|
38750
|
-
await session.eventBus.flush();
|
|
38751
|
-
ui.flushEventRenderer?.();
|
|
38752
|
-
}
|
|
38753
|
-
ui.stopEventRenderer?.();
|
|
38754
|
-
}
|
|
38755
|
-
if (cleanShutdown) {
|
|
38756
|
-
ui.showGoodbye?.();
|
|
38757
|
-
} else {
|
|
38758
|
-
presenter.notice({
|
|
38759
|
-
text: "Task worker did not stop before the shutdown timeout.",
|
|
38760
|
-
tone: "error"
|
|
38761
|
-
});
|
|
38762
|
-
}
|
|
38763
|
-
return cleanShutdown;
|
|
38773
|
+
return runPersistentSessionRepl(session, options);
|
|
38764
38774
|
}
|
|
38765
38775
|
function startCoordinator(session, commandHandler, presenter, suggestCommand) {
|
|
38766
38776
|
const queue = [];
|
|
@@ -39767,6 +39777,7 @@ async function main(argv, options = {}) {
|
|
|
39767
39777
|
let attachmentRuntime;
|
|
39768
39778
|
try {
|
|
39769
39779
|
modelPlatform = await createPiAiPlatform({
|
|
39780
|
+
// 附件运行时稍后才创建,通过回调取得届时可用的存储实例。
|
|
39770
39781
|
attachments: { store: () => attachmentRuntime?.store },
|
|
39771
39782
|
credentials,
|
|
39772
39783
|
modelCatalogStore,
|