laohuang 0.9.6 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/bin.js +422 -188
- package/dist/bin.js.map +4 -4
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -7628,21 +7628,10 @@ function parseSessionItem(value, expectedSessionId) {
|
|
|
7628
7628
|
if (message["role"] !== "system" || !Array.isArray(message["toolDefinitions"]))
|
|
7629
7629
|
throw new SessionSchemaError("invalid tool definitions message");
|
|
7630
7630
|
for (const raw of message["toolDefinitions"]) {
|
|
7631
|
-
|
|
7632
|
-
requireString(definition, "version");
|
|
7633
|
-
const spec2 = objectOf(definition["spec"], "tool spec");
|
|
7634
|
-
requireString(spec2, "name");
|
|
7635
|
-
if (typeof spec2["description"] !== "string" || !Array.isArray(spec2["promptGuidelines"]) || spec2["promptGuidelines"].some((value2) => typeof value2 !== "string"))
|
|
7636
|
-
throw new SessionSchemaError("invalid tool spec");
|
|
7637
|
-
objectOf(spec2["parameters"], "tool parameters");
|
|
7638
|
-
if (spec2["catalog"] !== void 0) {
|
|
7639
|
-
const catalog = objectOf(spec2["catalog"], "tool catalog metadata");
|
|
7640
|
-
for (const key of ["source", "originalName", "binding"])
|
|
7641
|
-
requireString(catalog, key);
|
|
7642
|
-
if (catalog["exposure"] !== "direct" && catalog["exposure"] !== "deferred")
|
|
7643
|
-
throw new SessionSchemaError("invalid exposure");
|
|
7644
|
-
}
|
|
7631
|
+
assertStoredTool(raw, true);
|
|
7645
7632
|
}
|
|
7633
|
+
if (message["toolsRemoved"] !== void 0)
|
|
7634
|
+
assertToolReferences(message["toolsRemoved"]);
|
|
7646
7635
|
} else {
|
|
7647
7636
|
if (message["role"] !== "user")
|
|
7648
7637
|
throw new SessionSchemaError("invalid catalog message role");
|
|
@@ -7654,6 +7643,9 @@ function parseSessionItem(value, expectedSessionId) {
|
|
|
7654
7643
|
throw new SessionSchemaError("invalid tool version");
|
|
7655
7644
|
}
|
|
7656
7645
|
}
|
|
7646
|
+
if (entryType === "compaction" && entryPayload["toolState"] !== void 0) {
|
|
7647
|
+
assertToolSelectionSnapshot(entryPayload["toolState"]);
|
|
7648
|
+
}
|
|
7657
7649
|
return input;
|
|
7658
7650
|
}
|
|
7659
7651
|
if (kind === "record") {
|
|
@@ -7682,6 +7674,54 @@ function parseSessionItem(value, expectedSessionId) {
|
|
|
7682
7674
|
}
|
|
7683
7675
|
throw new SessionSchemaError("invalid session item kind");
|
|
7684
7676
|
}
|
|
7677
|
+
function assertStoredTool(value, activationOptional) {
|
|
7678
|
+
const definition = objectOf(value, "loaded tool");
|
|
7679
|
+
requireString(definition, "version");
|
|
7680
|
+
const activation = definition["activation"];
|
|
7681
|
+
if ((!activationOptional || activation !== void 0) && activation !== "baseline" && activation !== "search") {
|
|
7682
|
+
throw new SessionSchemaError("invalid tool activation");
|
|
7683
|
+
}
|
|
7684
|
+
const spec2 = objectOf(definition["spec"], "tool spec");
|
|
7685
|
+
requireString(spec2, "name");
|
|
7686
|
+
if (typeof spec2["description"] !== "string" || !Array.isArray(spec2["promptGuidelines"]) || spec2["promptGuidelines"].some((value2) => typeof value2 !== "string")) {
|
|
7687
|
+
throw new SessionSchemaError("invalid tool spec");
|
|
7688
|
+
}
|
|
7689
|
+
objectOf(spec2["parameters"], "tool parameters");
|
|
7690
|
+
if (spec2["catalog"] !== void 0) {
|
|
7691
|
+
const catalog = objectOf(spec2["catalog"], "tool catalog metadata");
|
|
7692
|
+
for (const key of ["source", "originalName", "binding"])
|
|
7693
|
+
requireString(catalog, key);
|
|
7694
|
+
if (catalog["exposure"] !== "direct" && catalog["exposure"] !== "deferred")
|
|
7695
|
+
throw new SessionSchemaError("invalid exposure");
|
|
7696
|
+
}
|
|
7697
|
+
}
|
|
7698
|
+
function assertToolReferences(value) {
|
|
7699
|
+
if (!Array.isArray(value))
|
|
7700
|
+
throw new SessionSchemaError("invalid removed tools");
|
|
7701
|
+
for (const raw of value) {
|
|
7702
|
+
const reference = objectOf(raw, "removed tool");
|
|
7703
|
+
requireString(reference, "name");
|
|
7704
|
+
if (reference["version"] !== void 0)
|
|
7705
|
+
requireString(reference, "version");
|
|
7706
|
+
}
|
|
7707
|
+
}
|
|
7708
|
+
function assertToolSelectionSnapshot(value) {
|
|
7709
|
+
const snapshot = objectOf(value, "tool state");
|
|
7710
|
+
const catalog = snapshot["catalog"];
|
|
7711
|
+
if (catalog !== null) {
|
|
7712
|
+
const state = objectOf(catalog, "tool state catalog");
|
|
7713
|
+
if (state["mode"] !== "full" && state["mode"] !== "deferred")
|
|
7714
|
+
throw new SessionSchemaError("invalid tool mode");
|
|
7715
|
+
for (const version of Object.values(objectOf(state["tools"], "tool versions"))) {
|
|
7716
|
+
if (typeof version !== "string")
|
|
7717
|
+
throw new SessionSchemaError("invalid tool version");
|
|
7718
|
+
}
|
|
7719
|
+
}
|
|
7720
|
+
if (!Array.isArray(snapshot["activeTools"]))
|
|
7721
|
+
throw new SessionSchemaError("invalid active tools");
|
|
7722
|
+
for (const tool of snapshot["activeTools"])
|
|
7723
|
+
assertStoredTool(tool, false);
|
|
7724
|
+
}
|
|
7685
7725
|
function contextResetBoundary(entries) {
|
|
7686
7726
|
return entries.reduce((boundary, entry) => entry.entryType === "context_reset" ? Math.max(boundary, entry.payload.resetThroughSeq) : boundary, 0);
|
|
7687
7727
|
}
|
|
@@ -8666,7 +8706,7 @@ var ConversationHistory = class _ConversationHistory {
|
|
|
8666
8706
|
payload: input
|
|
8667
8707
|
});
|
|
8668
8708
|
}
|
|
8669
|
-
|
|
8709
|
+
appendToolState(input) {
|
|
8670
8710
|
return this.append({ entryType: "tool_definitions", payload: input });
|
|
8671
8711
|
}
|
|
8672
8712
|
appendToolCatalog(input) {
|
|
@@ -9054,7 +9094,9 @@ function conversationTail(entries, activeCompaction) {
|
|
|
9054
9094
|
return entries.filter((entry) => entry.seq >= boundary && entry.entryType !== "system_context" && entry.entryType !== "project_instructions" && entry.entryType !== "compaction");
|
|
9055
9095
|
}
|
|
9056
9096
|
function modelMessageForEntry(entry, currentProvider, currentModel) {
|
|
9057
|
-
if (entry.entryType === "tool_definitions"
|
|
9097
|
+
if (entry.entryType === "tool_definitions")
|
|
9098
|
+
return null;
|
|
9099
|
+
if (entry.entryType === "tool_catalog" || entry.entryType === "skill_context")
|
|
9058
9100
|
return entry.payload.message;
|
|
9059
9101
|
if (entry.entryType === "user_message" || entry.entryType === "reminder") {
|
|
9060
9102
|
return entry.payload.message;
|
|
@@ -9105,7 +9147,7 @@ function validateToolPairs(selected) {
|
|
|
9105
9147
|
}
|
|
9106
9148
|
|
|
9107
9149
|
// ../../packages/session/session-context/dist/summary-prompt.js
|
|
9108
|
-
var COMPACTION_SYSTEM_PROMPT = "Summarize the conversation for continuation. Preserve user goals, explicit constraints, completed work, modified files, architectural decisions, tool outcomes, failures, current TODOs, and concrete state needed to continue. Do not include credentials. Do not invent results.";
|
|
9150
|
+
var COMPACTION_SYSTEM_PROMPT = "Summarize the conversation for continuation. If the input contains <previous_summary>, merge and update it with the newer conversation instead of discarding it. Preserve user goals, explicit constraints, completed work, modified files, architectural decisions, tool outcomes, failures, current TODOs, and concrete state needed to continue. Do not include credentials. Do not invent results.";
|
|
9109
9151
|
|
|
9110
9152
|
// ../../packages/session/session-context/dist/compaction.js
|
|
9111
9153
|
function selectCompactionPlan(input) {
|
|
@@ -9151,8 +9193,6 @@ function serializeConversation(entries) {
|
|
|
9151
9193
|
}
|
|
9152
9194
|
} else if (entry.entryType === "tool_result") {
|
|
9153
9195
|
lines2.push(`[tool-result ${entry.payload.message.toolCallId} ${entry.payload.message.toolName}] ${entry.payload.message.content}`);
|
|
9154
|
-
} else if (entry.entryType === "tool_definitions") {
|
|
9155
|
-
lines2.push(`[loaded tool definitions] ${(entry.payload.message.toolDefinitions ?? []).map((tool) => tool.spec.name).join(", ")}`);
|
|
9156
9196
|
} else if (entry.entryType === "user_message" || entry.entryType === "skill_context" || entry.entryType === "reminder" || entry.entryType === "project_instructions") {
|
|
9157
9197
|
lines2.push(`[${entry.payload.message.role}] ${entry.payload.message.content}`);
|
|
9158
9198
|
}
|
|
@@ -9167,12 +9207,9 @@ function serializeConversation(entries) {
|
|
|
9167
9207
|
}
|
|
9168
9208
|
function semanticUnits(entries) {
|
|
9169
9209
|
const units = [];
|
|
9170
|
-
const groupedDefinitions = /* @__PURE__ */ new Set();
|
|
9171
9210
|
for (let index = 0; index < entries.length; index += 1) {
|
|
9172
9211
|
const entry = entries[index];
|
|
9173
|
-
if (
|
|
9174
|
-
continue;
|
|
9175
|
-
if (entry.entryType === "context_reset" || entry.entryType === "image_offload" || entry.entryType === "system_context" || entry.entryType === "project_instructions" || entry.entryType === "compaction") {
|
|
9212
|
+
if (entry.entryType === "context_reset" || entry.entryType === "image_offload" || entry.entryType === "tool_definitions" || entry.entryType === "system_context" || entry.entryType === "project_instructions" || entry.entryType === "compaction") {
|
|
9176
9213
|
continue;
|
|
9177
9214
|
}
|
|
9178
9215
|
if (entry.entryType === "assistant_message") {
|
|
@@ -9186,12 +9223,6 @@ function semanticUnits(entries) {
|
|
|
9186
9223
|
}
|
|
9187
9224
|
grouped.push(entries[resultIndex]);
|
|
9188
9225
|
}
|
|
9189
|
-
const lastResultIndex = entries.findIndex((candidate) => candidate.id === grouped.at(-1).id);
|
|
9190
|
-
const definitions = entries[lastResultIndex + 1];
|
|
9191
|
-
if (definitions?.entryType === "tool_definitions") {
|
|
9192
|
-
grouped.push(definitions);
|
|
9193
|
-
groupedDefinitions.add(definitions.id);
|
|
9194
|
-
}
|
|
9195
9226
|
units.push({ entries: grouped, messages: grouped.map(messageForEntry) });
|
|
9196
9227
|
continue;
|
|
9197
9228
|
}
|
|
@@ -9204,7 +9235,7 @@ function semanticUnits(entries) {
|
|
|
9204
9235
|
return units;
|
|
9205
9236
|
}
|
|
9206
9237
|
function messageForEntry(entry) {
|
|
9207
|
-
if (entry.entryType === "
|
|
9238
|
+
if (entry.entryType === "tool_catalog" || entry.entryType === "skill_context")
|
|
9208
9239
|
return entry.payload.message;
|
|
9209
9240
|
if (entry.entryType === "assistant_message") {
|
|
9210
9241
|
return entry.payload.message;
|
|
@@ -9225,6 +9256,8 @@ var ContextBudgetError = class extends Error {
|
|
|
9225
9256
|
this.name = "ContextBudgetError";
|
|
9226
9257
|
}
|
|
9227
9258
|
};
|
|
9259
|
+
var NoCompactionAvailableError = class extends Error {
|
|
9260
|
+
};
|
|
9228
9261
|
var ContextGovernor = class {
|
|
9229
9262
|
#builder;
|
|
9230
9263
|
#estimator;
|
|
@@ -9245,7 +9278,17 @@ var ContextGovernor = class {
|
|
|
9245
9278
|
throw new ContextBudgetError("context exceeds hard input limit");
|
|
9246
9279
|
return { built, messages: built.messages, compacted: false, tokens };
|
|
9247
9280
|
}
|
|
9248
|
-
|
|
9281
|
+
let result;
|
|
9282
|
+
try {
|
|
9283
|
+
result = await this.compact({ ...input, trigger: "automatic" });
|
|
9284
|
+
} catch (error) {
|
|
9285
|
+
if (!(error instanceof NoCompactionAvailableError))
|
|
9286
|
+
throw error;
|
|
9287
|
+
if (tokens > calculated.hardInputLimit) {
|
|
9288
|
+
throw new ContextBudgetError("context exceeds hard input limit with no earlier messages to compact");
|
|
9289
|
+
}
|
|
9290
|
+
return { built, messages: built.messages, compacted: false, tokens };
|
|
9291
|
+
}
|
|
9249
9292
|
const entries = [...input.entries, result.entry];
|
|
9250
9293
|
built = this.#builder.build({ ...input, entries });
|
|
9251
9294
|
tokens = this.measure({ ...input, entries }, built);
|
|
@@ -9256,12 +9299,14 @@ var ContextGovernor = class {
|
|
|
9256
9299
|
}
|
|
9257
9300
|
async compact(input) {
|
|
9258
9301
|
const calculated = calculateModelBudget({ budget: input.budget, policy: input.policy });
|
|
9302
|
+
const built = this.#builder.build(input);
|
|
9303
|
+
const activeCompaction = input.entries.find((entry) => entry.id === built.activeCompactionId && entry.entryType === "compaction");
|
|
9304
|
+
const activeSourceEntryIds = new Set(built.sourceEntryIds);
|
|
9305
|
+
const projectedEntries = activeCompaction === void 0 ? input.entries : input.entries.filter((entry) => entry.id !== activeCompaction.id && activeSourceEntryIds.has(entry.id));
|
|
9259
9306
|
const plan = selectCompactionPlan({
|
|
9260
9307
|
protectedFromSeq: input.protectedFromSeq,
|
|
9261
|
-
entries:
|
|
9262
|
-
|
|
9263
|
-
// Keep the latest completed unit and summarize older units to make room.
|
|
9264
|
-
retainTokens: input.reserveTokens === void 0 ? calculated.retainTokens : 1,
|
|
9308
|
+
entries: projectedEntries,
|
|
9309
|
+
retainTokens: calculated.retainTokens,
|
|
9265
9310
|
estimator: this.#estimator
|
|
9266
9311
|
});
|
|
9267
9312
|
if (plan.summarizedEntries.length === 0) {
|
|
@@ -9270,19 +9315,14 @@ var ContextGovernor = class {
|
|
|
9270
9315
|
if (input.trigger === "provider_overflow") {
|
|
9271
9316
|
throw new ContextBudgetError("No earlier messages to compact after provider overflow.");
|
|
9272
9317
|
}
|
|
9318
|
+
throw new NoCompactionAvailableError();
|
|
9273
9319
|
}
|
|
9274
|
-
const summarizedFromSeq = plan.summarizedEntries[0]?.seq ?? 1;
|
|
9275
|
-
const summarizedThroughSeq = plan.summarizedEntries.at(-1)?.seq ?? Math.max(0, summarizedFromSeq - 1);
|
|
9276
|
-
const built = this.#builder.build(input);
|
|
9277
|
-
const activeCompaction = input.entries.find((entry) => entry.id === built.activeCompactionId);
|
|
9320
|
+
const summarizedFromSeq = activeCompaction?.payload.summarizedFromSeq ?? plan.summarizedEntries[0]?.seq ?? 1;
|
|
9321
|
+
const summarizedThroughSeq = plan.summarizedEntries.at(-1)?.seq ?? activeCompaction?.payload.summarizedThroughSeq ?? Math.max(0, summarizedFromSeq - 1);
|
|
9278
9322
|
const messagesBefore = built.messages;
|
|
9279
9323
|
const tokensBefore = this.#estimator.estimateMessages(messagesBefore) + this.#estimator.estimateTools(input.projectTools?.(messagesBefore) ?? input.tools);
|
|
9280
|
-
const summary =
|
|
9281
|
-
|
|
9282
|
-
inputTokens: 0,
|
|
9283
|
-
outputTokens: 0
|
|
9284
|
-
} : await this.#summarize({
|
|
9285
|
-
serialized: serializeConversation(plan.summarizedEntries),
|
|
9324
|
+
const summary = await this.#summarize({
|
|
9325
|
+
serialized: serializeCompactionInput(activeCompaction?.payload.summary, plan.summarizedEntries),
|
|
9286
9326
|
maxSummaryTokens: input.policy.maxSummaryTokens
|
|
9287
9327
|
});
|
|
9288
9328
|
const payload = {
|
|
@@ -9297,7 +9337,8 @@ var ContextGovernor = class {
|
|
|
9297
9337
|
summaryOutputTokens: summary.outputTokens,
|
|
9298
9338
|
provider: input.currentProvider,
|
|
9299
9339
|
model: input.currentModel,
|
|
9300
|
-
trigger: input.trigger
|
|
9340
|
+
trigger: input.trigger,
|
|
9341
|
+
...input.toolState === void 0 ? {} : { toolState: input.toolState }
|
|
9301
9342
|
};
|
|
9302
9343
|
return { entry: this.#appendCompaction(payload) };
|
|
9303
9344
|
}
|
|
@@ -9329,9 +9370,18 @@ var ContextGovernor = class {
|
|
|
9329
9370
|
systemFingerprint: fingerprintContextPart(built.messages.find((message) => message.role === "system") ?? null),
|
|
9330
9371
|
projectInstructionsFingerprint: fingerprintContextPart(built.messages.filter((message, index) => index > 0 && message.role === "user")),
|
|
9331
9372
|
toolsFingerprint: fingerprintContextPart(tools)
|
|
9332
|
-
}).totalTokens
|
|
9373
|
+
}).totalTokens;
|
|
9333
9374
|
}
|
|
9334
9375
|
};
|
|
9376
|
+
function serializeCompactionInput(previousSummary, entries) {
|
|
9377
|
+
const conversation = serializeConversation(entries);
|
|
9378
|
+
if (previousSummary === void 0)
|
|
9379
|
+
return conversation;
|
|
9380
|
+
return `<previous_summary>
|
|
9381
|
+
${previousSummary}
|
|
9382
|
+
</previous_summary>
|
|
9383
|
+
${conversation}`;
|
|
9384
|
+
}
|
|
9335
9385
|
function calculateModelBudget(input) {
|
|
9336
9386
|
const hardInputLimit = input.budget.contextWindow - input.budget.maxOutputTokens;
|
|
9337
9387
|
const safetyTokens = Math.ceil(input.budget.contextWindow * input.policy.safetyRatio);
|
|
@@ -9340,6 +9390,52 @@ function calculateModelBudget(input) {
|
|
|
9340
9390
|
return { hardInputLimit, safetyTokens, autoTrigger, retainTokens };
|
|
9341
9391
|
}
|
|
9342
9392
|
|
|
9393
|
+
// ../../packages/session/session-context/dist/tool-state.js
|
|
9394
|
+
function projectToolSelectionState(entries) {
|
|
9395
|
+
const sorted = [...entries].sort((left, right) => left.seq - right.seq);
|
|
9396
|
+
const latestCompaction2 = [...sorted].reverse().find((entry) => entry.entryType === "compaction");
|
|
9397
|
+
const checkpoint = latestCompaction2?.entryType === "compaction" && latestCompaction2.payload.toolState !== void 0 ? latestCompaction2 : void 0;
|
|
9398
|
+
let catalog = checkpoint?.entryType === "compaction" ? copyCatalog(checkpoint.payload.toolState.catalog) : null;
|
|
9399
|
+
const active = /* @__PURE__ */ new Map();
|
|
9400
|
+
if (checkpoint?.entryType === "compaction") {
|
|
9401
|
+
for (const tool of checkpoint.payload.toolState.activeTools) {
|
|
9402
|
+
active.set(tool.spec.name, copyActiveTool(tool));
|
|
9403
|
+
}
|
|
9404
|
+
}
|
|
9405
|
+
const afterSeq = checkpoint?.seq ?? 0;
|
|
9406
|
+
for (const entry of sorted) {
|
|
9407
|
+
if (entry.seq <= afterSeq)
|
|
9408
|
+
continue;
|
|
9409
|
+
if (entry.entryType === "tool_catalog") {
|
|
9410
|
+
catalog = copyCatalog(entry.payload.message.toolCatalog ?? null);
|
|
9411
|
+
continue;
|
|
9412
|
+
}
|
|
9413
|
+
if (entry.entryType !== "tool_definitions")
|
|
9414
|
+
continue;
|
|
9415
|
+
for (const removed of entry.payload.message.toolsRemoved ?? []) {
|
|
9416
|
+
const current = active.get(removed.name);
|
|
9417
|
+
if (current !== void 0 && (removed.version === void 0 || current.version === removed.version)) {
|
|
9418
|
+
active.delete(removed.name);
|
|
9419
|
+
}
|
|
9420
|
+
}
|
|
9421
|
+
for (const tool of entry.payload.message.toolDefinitions ?? []) {
|
|
9422
|
+
const activeTool = normalizeActiveTool(tool);
|
|
9423
|
+
active.set(activeTool.spec.name, activeTool);
|
|
9424
|
+
}
|
|
9425
|
+
}
|
|
9426
|
+
return { catalog, activeTools: [...active.values()] };
|
|
9427
|
+
}
|
|
9428
|
+
function normalizeActiveTool(tool) {
|
|
9429
|
+
const activation = "activation" in tool && (tool.activation === "baseline" || tool.activation === "search") ? tool.activation : "search";
|
|
9430
|
+
return { version: tool.version, spec: tool.spec, activation };
|
|
9431
|
+
}
|
|
9432
|
+
function copyCatalog(catalog) {
|
|
9433
|
+
return catalog === null ? null : { mode: catalog.mode, tools: { ...catalog.tools } };
|
|
9434
|
+
}
|
|
9435
|
+
function copyActiveTool(tool) {
|
|
9436
|
+
return { version: tool.version, spec: tool.spec, activation: tool.activation };
|
|
9437
|
+
}
|
|
9438
|
+
|
|
9343
9439
|
// ../../packages/llm/llm-pi-ai/dist/adapter.js
|
|
9344
9440
|
import { clampThinkingLevel, ModelsError } from "@earendil-works/pi-ai";
|
|
9345
9441
|
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
|
|
@@ -9520,8 +9616,22 @@ function parseToolArguments(raw) {
|
|
|
9520
9616
|
kind: "protocol"
|
|
9521
9617
|
});
|
|
9522
9618
|
}
|
|
9619
|
+
if (!Object.values(parsed).every(isJsonValue)) {
|
|
9620
|
+
throw new ModelError("tool-call arguments contain invalid JSON values", {
|
|
9621
|
+
kind: "protocol"
|
|
9622
|
+
});
|
|
9623
|
+
}
|
|
9523
9624
|
return parsed;
|
|
9524
9625
|
}
|
|
9626
|
+
function isJsonValue(value) {
|
|
9627
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
9628
|
+
return true;
|
|
9629
|
+
if (typeof value === "number")
|
|
9630
|
+
return Number.isFinite(value);
|
|
9631
|
+
if (Array.isArray(value))
|
|
9632
|
+
return value.every(isJsonValue);
|
|
9633
|
+
return isRecord(value) && Object.values(value).every(isJsonValue);
|
|
9634
|
+
}
|
|
9525
9635
|
function zeroUsage() {
|
|
9526
9636
|
return {
|
|
9527
9637
|
input: 0,
|
|
@@ -9959,7 +10069,10 @@ var PiModelsStore = class {
|
|
|
9959
10069
|
return void 0;
|
|
9960
10070
|
}
|
|
9961
10071
|
return {
|
|
9962
|
-
models: entry.models.
|
|
10072
|
+
models: entry.models.flatMap((model2) => {
|
|
10073
|
+
const restored = restoreModel(providerId, model2);
|
|
10074
|
+
return restored === void 0 ? [] : [restored];
|
|
10075
|
+
}),
|
|
9963
10076
|
...entry.lastModified === void 0 ? {} : { lastModified: entry.lastModified },
|
|
9964
10077
|
...entry.checkedAt === void 0 ? {} : { checkedAt: entry.checkedAt },
|
|
9965
10078
|
...entry.etag === void 0 ? {} : { etag: entry.etag }
|
|
@@ -9978,12 +10091,15 @@ var PiModelsStore = class {
|
|
|
9978
10091
|
}
|
|
9979
10092
|
};
|
|
9980
10093
|
function restoreModel(providerId, model2) {
|
|
10094
|
+
const type = model2["type"] ?? "chat";
|
|
10095
|
+
if (type !== "chat" && type !== "image" && type !== "classifier")
|
|
10096
|
+
return void 0;
|
|
9981
10097
|
const id = readString(model2, "id", providerId);
|
|
9982
10098
|
const name = readString(model2, "name", providerId);
|
|
9983
10099
|
const api2 = readString(model2, "api", providerId);
|
|
9984
10100
|
const provider2 = readString(model2, "provider", providerId);
|
|
9985
10101
|
const input = model2["input"];
|
|
9986
|
-
if (!Array.isArray(input) || !input.every((item) =>
|
|
10102
|
+
if (!Array.isArray(input) || !input.every((item) => item === "text" || item === "image")) {
|
|
9987
10103
|
throw new ModelError(`stored model for '${providerId}' has invalid input`, {
|
|
9988
10104
|
kind: "protocol"
|
|
9989
10105
|
});
|
|
@@ -9994,6 +10110,27 @@ function restoreModel(providerId, model2) {
|
|
|
9994
10110
|
kind: "protocol"
|
|
9995
10111
|
});
|
|
9996
10112
|
}
|
|
10113
|
+
const common = {
|
|
10114
|
+
...model2,
|
|
10115
|
+
id,
|
|
10116
|
+
name,
|
|
10117
|
+
api: api2,
|
|
10118
|
+
provider: provider2,
|
|
10119
|
+
input,
|
|
10120
|
+
cost: cost2,
|
|
10121
|
+
baseUrl: readString(model2, "baseUrl", providerId)
|
|
10122
|
+
};
|
|
10123
|
+
if (type === "image") {
|
|
10124
|
+
const output = model2["output"];
|
|
10125
|
+
if (!Array.isArray(output) || !output.includes("image") || !output.every((item) => item === "text" || item === "image")) {
|
|
10126
|
+
throw new ModelError(`stored model for '${providerId}' has invalid output`, { kind: "protocol" });
|
|
10127
|
+
}
|
|
10128
|
+
return { ...common, type, api: api2, output };
|
|
10129
|
+
}
|
|
10130
|
+
const contextWindow = readPositiveNumber(model2, "contextWindow", providerId);
|
|
10131
|
+
if (type === "classifier") {
|
|
10132
|
+
return { ...common, type, api: api2, contextWindow };
|
|
10133
|
+
}
|
|
9997
10134
|
const reasoning = model2["reasoning"];
|
|
9998
10135
|
if (typeof reasoning !== "boolean") {
|
|
9999
10136
|
throw new ModelError(`stored model for '${providerId}' has invalid reasoning`, {
|
|
@@ -10001,15 +10138,13 @@ function restoreModel(providerId, model2) {
|
|
|
10001
10138
|
});
|
|
10002
10139
|
}
|
|
10003
10140
|
return {
|
|
10004
|
-
...
|
|
10005
|
-
|
|
10006
|
-
name,
|
|
10141
|
+
...common,
|
|
10142
|
+
type,
|
|
10007
10143
|
api: api2,
|
|
10008
|
-
provider: provider2,
|
|
10009
10144
|
reasoning,
|
|
10010
10145
|
input,
|
|
10011
10146
|
cost: cost2,
|
|
10012
|
-
contextWindow
|
|
10147
|
+
contextWindow,
|
|
10013
10148
|
maxTokens: readPositiveNumber(model2, "maxTokens", providerId)
|
|
10014
10149
|
};
|
|
10015
10150
|
}
|
|
@@ -10043,11 +10178,11 @@ function isCost(value) {
|
|
|
10043
10178
|
}
|
|
10044
10179
|
|
|
10045
10180
|
// ../../packages/llm/llm-pi-ai/dist/platform.js
|
|
10046
|
-
import { defaultProviderAuthContext, getSupportedThinkingLevels } from "@earendil-works/pi-ai";
|
|
10181
|
+
import { defaultProviderAuthContext, getSupportedThinkingLevels, isModelType as isModelType2 } from "@earendil-works/pi-ai";
|
|
10047
10182
|
import { builtinModels as builtinModels2 } from "@earendil-works/pi-ai/providers/all";
|
|
10048
10183
|
|
|
10049
10184
|
// ../../packages/llm/llm-pi-ai/dist/custom-models.js
|
|
10050
|
-
import { createProvider, envApiKeyAuth } from "@earendil-works/pi-ai";
|
|
10185
|
+
import { createProvider, envApiKeyAuth, isModelType } from "@earendil-works/pi-ai";
|
|
10051
10186
|
import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completions.lazy";
|
|
10052
10187
|
import { openAIResponsesApi } from "@earendil-works/pi-ai/api/openai-responses.lazy";
|
|
10053
10188
|
import { anthropicMessagesApi } from "@earendil-works/pi-ai/api/anthropic-messages.lazy";
|
|
@@ -17873,6 +18008,8 @@ var completionsCompat = partial(typebox_exports.Object({
|
|
|
17873
18008
|
supportsOpenAIGrammarTools: typebox_exports.Boolean(),
|
|
17874
18009
|
supportsStrictMode: typebox_exports.Boolean(),
|
|
17875
18010
|
cacheControlFormat: typebox_exports.Literal("anthropic"),
|
|
18011
|
+
supportsMidConvoSystemMessages: typebox_exports.Boolean(),
|
|
18012
|
+
supportsMidConvoToolAdditions: typebox_exports.Boolean(),
|
|
17876
18013
|
sendSessionAffinityHeaders: typebox_exports.Boolean(),
|
|
17877
18014
|
deferredToolsMode: typebox_exports.Literal("kimi"),
|
|
17878
18015
|
sessionAffinityFormat: affinity,
|
|
@@ -17882,6 +18019,7 @@ var completionsCompat = partial(typebox_exports.Object({
|
|
|
17882
18019
|
var responsesCompat = partial(typebox_exports.Object({
|
|
17883
18020
|
supportsDeveloperRole: typebox_exports.Boolean(),
|
|
17884
18021
|
sessionAffinityFormat: affinity,
|
|
18022
|
+
supportsMidConvoSystemMessages: typebox_exports.Boolean(),
|
|
17885
18023
|
supportsLongCacheRetention: typebox_exports.Boolean(),
|
|
17886
18024
|
supportsStrictMode: typebox_exports.Boolean(),
|
|
17887
18025
|
supportsOpenAIGrammarTools: typebox_exports.Boolean(),
|
|
@@ -17901,6 +18039,9 @@ var anthropicCompat = partial(typebox_exports.Object({
|
|
|
17901
18039
|
supportsStrictTools: typebox_exports.Boolean(),
|
|
17902
18040
|
supportsMidConvoEffort: typebox_exports.Boolean(),
|
|
17903
18041
|
supportsToolReferences: typebox_exports.Boolean(),
|
|
18042
|
+
supportsMidConvoSystemMessages: typebox_exports.Boolean(),
|
|
18043
|
+
supportsMidConvoToolChanges: typebox_exports.Boolean(),
|
|
18044
|
+
sessionAffinityFormat: typebox_exports.Literal("openrouter"),
|
|
17904
18045
|
allowedFallbackModels: typebox_exports.Array(typebox_exports.Object({ provider: text, model: text, cost }, { additionalProperties: false }))
|
|
17905
18046
|
}, { additionalProperties: false }));
|
|
17906
18047
|
var api = typebox_exports.Union([
|
|
@@ -18073,6 +18214,10 @@ function customProvider(id, config, base) {
|
|
|
18073
18214
|
baseUrl: config.baseUrl ?? base?.baseUrl,
|
|
18074
18215
|
headers: { ...base?.headers, ...config.headers },
|
|
18075
18216
|
getModels,
|
|
18217
|
+
getAllModels: () => [
|
|
18218
|
+
...getModels(),
|
|
18219
|
+
...(base?.getAllModels?.() ?? []).filter((model2) => !isModelType(model2, "chat"))
|
|
18220
|
+
],
|
|
18076
18221
|
// Keep provider-owned refresh/cache logic; getModels reapplies user overrides afterwards.
|
|
18077
18222
|
...base?.filterModels === void 0 ? {} : {
|
|
18078
18223
|
filterModels: (models, credential) => {
|
|
@@ -18080,6 +18225,12 @@ function customProvider(id, config, base) {
|
|
|
18080
18225
|
return models.filter((model2) => available.has(model2.id) || additions.has(model2.id));
|
|
18081
18226
|
}
|
|
18082
18227
|
},
|
|
18228
|
+
...base?.filterAllModels === void 0 ? {} : {
|
|
18229
|
+
filterAllModels: (models, credential) => {
|
|
18230
|
+
const available = new Set(base.filterAllModels(models, credential).map((model2) => `${model2.type ?? "chat"}:${model2.id}`));
|
|
18231
|
+
return models.filter((model2) => available.has(`${model2.type ?? "chat"}:${model2.id}`) || isModelType(model2, "chat") && additions.has(model2.id));
|
|
18232
|
+
}
|
|
18233
|
+
},
|
|
18083
18234
|
stream: (model2, context, options) => dispatch(model2).stream(model2, context, options),
|
|
18084
18235
|
streamSimple: (model2, context, options) => dispatch(model2).streamSimple(model2, context, options)
|
|
18085
18236
|
};
|
|
@@ -18190,7 +18341,9 @@ var PiAiPlatform = class {
|
|
|
18190
18341
|
}
|
|
18191
18342
|
};
|
|
18192
18343
|
function isEligibleProvider(provider2, excludedProviderIds) {
|
|
18193
|
-
|
|
18344
|
+
const allModels = provider2.getAllModels?.() ?? provider2.getModels();
|
|
18345
|
+
return provider2.auth.apiKey?.login !== void 0 && !excludedProviderIds.has(provider2.id) && // Empty dynamic catalogs remain eligible; operation-only catalogs do not.
|
|
18346
|
+
(allModels.length === 0 || allModels.some((model2) => isModelType2(model2, "chat")));
|
|
18194
18347
|
}
|
|
18195
18348
|
var PiAiCatalog = class {
|
|
18196
18349
|
models;
|
|
@@ -18381,6 +18534,33 @@ function errorMessage3(error) {
|
|
|
18381
18534
|
return error instanceof Error ? error.message : String(error);
|
|
18382
18535
|
}
|
|
18383
18536
|
|
|
18537
|
+
// ../../packages/llm/llm-pi-ai/dist/tool-validation.js
|
|
18538
|
+
import { validateToolArguments } from "@earendil-works/pi-ai";
|
|
18539
|
+
var validatePiToolArguments = (spec2, call, args) => {
|
|
18540
|
+
const tool = {
|
|
18541
|
+
name: spec2.name,
|
|
18542
|
+
description: spec2.description,
|
|
18543
|
+
parameters: spec2.parameters
|
|
18544
|
+
};
|
|
18545
|
+
const toolCall = {
|
|
18546
|
+
type: "toolCall",
|
|
18547
|
+
id: call.id,
|
|
18548
|
+
name: call.name,
|
|
18549
|
+
arguments: args
|
|
18550
|
+
};
|
|
18551
|
+
let validated;
|
|
18552
|
+
try {
|
|
18553
|
+
validated = validateToolArguments(tool, toolCall);
|
|
18554
|
+
} catch (error) {
|
|
18555
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
18556
|
+
throw new Error(message.split("\n\nReceived arguments:\n")[0]);
|
|
18557
|
+
}
|
|
18558
|
+
if (typeof validated !== "object" || validated === null || Array.isArray(validated)) {
|
|
18559
|
+
throw new Error("Validated tool arguments must be a JSON object");
|
|
18560
|
+
}
|
|
18561
|
+
return validated;
|
|
18562
|
+
};
|
|
18563
|
+
|
|
18384
18564
|
// ../../packages/storage/local-config/dist/config.js
|
|
18385
18565
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
18386
18566
|
import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync, writeFileSync } from "node:fs";
|
|
@@ -28760,8 +28940,13 @@ var StdTerminalDriver = class {
|
|
|
28760
28940
|
var ToolRuntime = class {
|
|
28761
28941
|
tools;
|
|
28762
28942
|
createExecutionContext;
|
|
28763
|
-
|
|
28943
|
+
validateArguments;
|
|
28944
|
+
constructor(tools, options) {
|
|
28945
|
+
if (typeof options?.validateToolArguments !== "function") {
|
|
28946
|
+
throw new Error("Tool argument validator is required");
|
|
28947
|
+
}
|
|
28764
28948
|
this.tools = tools;
|
|
28949
|
+
this.validateArguments = options.validateToolArguments;
|
|
28765
28950
|
this.createExecutionContext = options.createExecutionContext ?? ((_, cancelToken) => ({
|
|
28766
28951
|
signal: cancelToken?.signal,
|
|
28767
28952
|
isCancelled: () => isCancelled(cancelToken),
|
|
@@ -28772,6 +28957,7 @@ var ToolRuntime = class {
|
|
|
28772
28957
|
}
|
|
28773
28958
|
async execute(request) {
|
|
28774
28959
|
const registry = request.registry ?? this.tools;
|
|
28960
|
+
const definitions = new Map(registry.definitions.map((tool) => [tool.name, tool]));
|
|
28775
28961
|
const results = new Array(request.toolCalls.length).fill(void 0);
|
|
28776
28962
|
const prepared = [];
|
|
28777
28963
|
for (let offset = 0; offset < request.toolCalls.length; offset += 1) {
|
|
@@ -28779,7 +28965,7 @@ var ToolRuntime = class {
|
|
|
28779
28965
|
if (toolCall === void 0) {
|
|
28780
28966
|
continue;
|
|
28781
28967
|
}
|
|
28782
|
-
let args;
|
|
28968
|
+
let args = { _raw: toolCall.arguments };
|
|
28783
28969
|
let result;
|
|
28784
28970
|
try {
|
|
28785
28971
|
const decoded = JSON.parse(toolCall.arguments);
|
|
@@ -28787,8 +28973,11 @@ var ToolRuntime = class {
|
|
|
28787
28973
|
throw new Error("Tool arguments must be a JSON object");
|
|
28788
28974
|
}
|
|
28789
28975
|
args = decoded;
|
|
28976
|
+
const tool = definitions.get(toolCall.name);
|
|
28977
|
+
if (tool === void 0)
|
|
28978
|
+
throw new Error(`Unknown tool: ${toolCall.name}`);
|
|
28979
|
+
args = this.validateArguments(tool, toolCall, args);
|
|
28790
28980
|
} catch (error) {
|
|
28791
|
-
args = { _raw: toolCall.arguments };
|
|
28792
28981
|
result = { ok: false, error: errorMessage7(error) };
|
|
28793
28982
|
}
|
|
28794
28983
|
const event = {
|
|
@@ -28961,23 +29150,92 @@ var TOOL_SEARCH_THRESHOLD = 20;
|
|
|
28961
29150
|
var ToolSelection = class {
|
|
28962
29151
|
indexKey = "";
|
|
28963
29152
|
index;
|
|
28964
|
-
|
|
29153
|
+
catalog = null;
|
|
29154
|
+
active = /* @__PURE__ */ new Map();
|
|
29155
|
+
apply(update) {
|
|
29156
|
+
if (update.catalog !== void 0)
|
|
29157
|
+
this.catalog = copyCatalog2(update.catalog);
|
|
29158
|
+
for (const removed of update.toolsRemoved) {
|
|
29159
|
+
const current = this.active.get(removed.name);
|
|
29160
|
+
if (current !== void 0 && (removed.version === void 0 || current.version === removed.version)) {
|
|
29161
|
+
this.active.delete(removed.name);
|
|
29162
|
+
}
|
|
29163
|
+
}
|
|
29164
|
+
for (const tool of update.toolsAdded)
|
|
29165
|
+
this.active.set(tool.spec.name, copyActiveTool2(tool));
|
|
29166
|
+
}
|
|
29167
|
+
restore(snapshot) {
|
|
29168
|
+
this.catalog = snapshot.catalog === null ? null : copyCatalog2(snapshot.catalog);
|
|
29169
|
+
this.active.clear();
|
|
29170
|
+
for (const tool of snapshot.activeTools)
|
|
29171
|
+
this.active.set(tool.spec.name, copyActiveTool2(tool));
|
|
29172
|
+
}
|
|
29173
|
+
snapshot() {
|
|
29174
|
+
return {
|
|
29175
|
+
catalog: this.catalog === null ? null : copyCatalog2(this.catalog),
|
|
29176
|
+
activeTools: [...this.active.values()].map(copyActiveTool2)
|
|
29177
|
+
};
|
|
29178
|
+
}
|
|
29179
|
+
prepare(registry) {
|
|
28965
29180
|
const all = registry.definitions.filter((spec2) => spec2.name !== SEARCH_TOOL_NAME);
|
|
28966
29181
|
const deferred = all.filter((spec2) => spec2.catalog?.exposure === "deferred");
|
|
28967
29182
|
const mode = all.length >= TOOL_SEARCH_THRESHOLD ? "deferred" : "full";
|
|
28968
|
-
const versions = new Map(
|
|
28969
|
-
const catalog = {
|
|
28970
|
-
|
|
28971
|
-
|
|
28972
|
-
|
|
28973
|
-
|
|
28974
|
-
|
|
29183
|
+
const versions = new Map(all.map((spec2) => [spec2.name, toolVersion(spec2)]));
|
|
29184
|
+
const catalog = {
|
|
29185
|
+
mode,
|
|
29186
|
+
tools: mode === "deferred" ? Object.fromEntries(deferred.map((spec2) => [spec2.name, versions.get(spec2.name)])) : {}
|
|
29187
|
+
};
|
|
29188
|
+
const current = new Map(all.map((spec2) => [spec2.name, spec2]));
|
|
29189
|
+
const desired = /* @__PURE__ */ new Map();
|
|
29190
|
+
const toolsAdded = [];
|
|
29191
|
+
const toolsRemoved = [];
|
|
29192
|
+
const missing = [];
|
|
29193
|
+
for (const [name, active] of this.active) {
|
|
29194
|
+
const spec2 = current.get(name);
|
|
29195
|
+
if (spec2 === void 0) {
|
|
29196
|
+
toolsRemoved.push({ name, version: active.version });
|
|
29197
|
+
missing.push(name);
|
|
29198
|
+
continue;
|
|
29199
|
+
}
|
|
29200
|
+
const baseline = mode === "full" || spec2.catalog?.exposure !== "deferred";
|
|
29201
|
+
const version = versions.get(name);
|
|
29202
|
+
if (version !== active.version) {
|
|
29203
|
+
toolsRemoved.push({ name, version: active.version });
|
|
29204
|
+
if (baseline || active.activation === "search") {
|
|
29205
|
+
const updated = {
|
|
29206
|
+
spec: spec2,
|
|
29207
|
+
version,
|
|
29208
|
+
activation: spec2.catalog?.exposure === "deferred" && active.activation === "search" ? "search" : "baseline"
|
|
29209
|
+
};
|
|
29210
|
+
desired.set(name, updated);
|
|
29211
|
+
toolsAdded.push(updated);
|
|
29212
|
+
}
|
|
29213
|
+
continue;
|
|
29214
|
+
}
|
|
29215
|
+
if (baseline || active.activation === "search") {
|
|
29216
|
+
desired.set(name, { spec: spec2, version, activation: active.activation });
|
|
29217
|
+
} else {
|
|
29218
|
+
toolsRemoved.push({ name, version: active.version });
|
|
28975
29219
|
}
|
|
28976
29220
|
}
|
|
28977
|
-
|
|
29221
|
+
for (const spec2 of all) {
|
|
29222
|
+
const baseline = mode === "full" || spec2.catalog?.exposure !== "deferred";
|
|
29223
|
+
if (!baseline || desired.has(spec2.name))
|
|
29224
|
+
continue;
|
|
29225
|
+
const added = { spec: spec2, version: versions.get(spec2.name), activation: "baseline" };
|
|
29226
|
+
desired.set(spec2.name, added);
|
|
29227
|
+
toolsAdded.push(added);
|
|
29228
|
+
}
|
|
29229
|
+
const catalogChanged = canonicalToolJson(this.catalog ?? { mode: "full", tools: {} }) !== canonicalToolJson(catalog);
|
|
29230
|
+
const update = {
|
|
29231
|
+
...catalogChanged ? { catalog } : {},
|
|
29232
|
+
toolsAdded,
|
|
29233
|
+
toolsRemoved
|
|
29234
|
+
};
|
|
29235
|
+
const loaded = new Map([...desired].map(([name, tool]) => [name, tool.version]));
|
|
28978
29236
|
let announcement;
|
|
28979
|
-
if (
|
|
28980
|
-
const before =
|
|
29237
|
+
if (catalogChanged) {
|
|
29238
|
+
const before = this.catalog?.mode === "deferred" && mode === "deferred" ? this.catalog.tools : {};
|
|
28981
29239
|
const added = Object.keys(catalog.tools).filter((name) => before[name] !== catalog.tools[name]);
|
|
28982
29240
|
const removed = Object.keys(before).filter((name) => before[name] !== catalog.tools[name]);
|
|
28983
29241
|
const sections = ["<system-reminder>", mode === "deferred" ? "Use tool_search to search and load tool definitions before calling deferred tools." : "All currently available tool definitions are now directly available."];
|
|
@@ -28996,8 +29254,10 @@ var ToolSelection = class {
|
|
|
28996
29254
|
}
|
|
28997
29255
|
}
|
|
28998
29256
|
const pending = /* @__PURE__ */ new Map();
|
|
28999
|
-
|
|
29000
|
-
|
|
29257
|
+
const definitions = [
|
|
29258
|
+
...all.filter((spec2) => desired.has(spec2.name)),
|
|
29259
|
+
...mode === "deferred" ? [SEARCH_TOOL_SPEC] : []
|
|
29260
|
+
];
|
|
29001
29261
|
const visible = new Set(definitions.map((spec2) => spec2.name));
|
|
29002
29262
|
const index = this.index;
|
|
29003
29263
|
const view = {
|
|
@@ -29021,55 +29281,29 @@ var ToolSelection = class {
|
|
|
29021
29281
|
name: name2,
|
|
29022
29282
|
description: spec2.description.length > 1024 ? `${spec2.description.slice(0, 1024)}...[truncated]` : spec2.description,
|
|
29023
29283
|
source: spec2.catalog?.source,
|
|
29024
|
-
status: "
|
|
29284
|
+
status: "loaded"
|
|
29025
29285
|
};
|
|
29026
29286
|
});
|
|
29027
|
-
|
|
29028
|
-
|
|
29029
|
-
|
|
29030
|
-
|
|
29031
|
-
|
|
29032
|
-
const { name: name2 } = match;
|
|
29033
|
-
if (pending.has(name2)) {
|
|
29034
|
-
match.status = previouslyPending.has(name2) ? "already_loaded" : "loaded";
|
|
29035
|
-
continue;
|
|
29036
|
-
}
|
|
29037
|
-
if (retained.has(name2)) {
|
|
29038
|
-
match.status = "already_loaded";
|
|
29039
|
-
continue;
|
|
29040
|
-
}
|
|
29041
|
-
if (pass > 0 && match.status === "not_loaded_budget")
|
|
29042
|
-
continue;
|
|
29043
|
-
const spec2 = deferred.find((tool2) => tool2.name === name2);
|
|
29044
|
-
const tool = { spec: spec2, version: versions.get(name2) };
|
|
29045
|
-
if (await canLoad([...pending.values(), tool], resultBytes)) {
|
|
29046
|
-
pending.set(name2, tool);
|
|
29047
|
-
match.status = "loaded";
|
|
29048
|
-
} else
|
|
29049
|
-
match.status = "not_loaded_budget";
|
|
29287
|
+
for (const match of matches) {
|
|
29288
|
+
const { name: name2 } = match;
|
|
29289
|
+
if (pending.has(name2) || loaded.has(name2)) {
|
|
29290
|
+
match.status = "already_loaded";
|
|
29291
|
+
continue;
|
|
29050
29292
|
}
|
|
29293
|
+
const spec2 = deferred.find((tool) => tool.name === name2);
|
|
29294
|
+
pending.set(name2, { spec: spec2, version: versions.get(name2), activation: "search" });
|
|
29051
29295
|
}
|
|
29052
29296
|
return { ok: true, matches, ...matches.length ? {} : { content: "No matching tools. Try an exact name, source, or different keywords." } };
|
|
29053
29297
|
}
|
|
29054
29298
|
};
|
|
29055
|
-
return { view, announcement, mode, pending: () => [...pending.values()] };
|
|
29299
|
+
return { view, announcement, mode, update, missing, pending: () => [...pending.values()] };
|
|
29056
29300
|
}
|
|
29057
29301
|
};
|
|
29058
|
-
function
|
|
29059
|
-
|
|
29060
|
-
|
|
29061
|
-
|
|
29062
|
-
|
|
29063
|
-
if (record.toolCatalog.tools[name] !== version)
|
|
29064
|
-
loaded.delete(name);
|
|
29065
|
-
}
|
|
29066
|
-
for (const tool of record.toolDefinitions ?? [])
|
|
29067
|
-
loaded.set(tool.spec.name, tool.version);
|
|
29068
|
-
}
|
|
29069
|
-
for (const [name, version] of loaded)
|
|
29070
|
-
if (versions.get(name) !== version)
|
|
29071
|
-
loaded.delete(name);
|
|
29072
|
-
return loaded;
|
|
29302
|
+
function copyCatalog2(catalog) {
|
|
29303
|
+
return { mode: catalog.mode, tools: { ...catalog.tools } };
|
|
29304
|
+
}
|
|
29305
|
+
function copyActiveTool2(tool) {
|
|
29306
|
+
return { version: tool.version, spec: tool.spec, activation: tool.activation };
|
|
29073
29307
|
}
|
|
29074
29308
|
|
|
29075
29309
|
// ../../packages/core/tools/dist/index.js
|
|
@@ -32506,44 +32740,22 @@ var AgentStepRunner = class {
|
|
|
32506
32740
|
this.options.onRequestId(requestId);
|
|
32507
32741
|
const registry = this.options.getTools();
|
|
32508
32742
|
const selection = this.options.selection ?? new ToolSelection();
|
|
32509
|
-
|
|
32510
|
-
|
|
32511
|
-
|
|
32512
|
-
|
|
32513
|
-
|
|
32514
|
-
|
|
32515
|
-
|
|
32516
|
-
|
|
32517
|
-
|
|
32518
|
-
|
|
32519
|
-
|
|
32520
|
-
|
|
32521
|
-
|
|
32522
|
-
|
|
32523
|
-
try {
|
|
32524
|
-
const projectTools = (retained) => selection.prepare(registry, [...retained.map((message) => message.role === "system" || message.role === "user" ? message : {}), { toolDefinitions: pending2 }]).view.definitions;
|
|
32525
|
-
const compacted = await this.options.contextGovernor.prepare({
|
|
32526
|
-
messages: snapshot.slice(0, -1),
|
|
32527
|
-
tools: projectTools(snapshot),
|
|
32528
|
-
projectTools,
|
|
32529
|
-
provider: this.options.provider,
|
|
32530
|
-
model: this.options.model,
|
|
32531
|
-
pendingToolCall: true,
|
|
32532
|
-
reserveTokens: reserve + 1024
|
|
32533
|
-
});
|
|
32534
|
-
history.retain([...compacted.messages, assistant]);
|
|
32535
|
-
remainingTokens = compacted.hardInputLimit === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, compacted.hardInputLimit - (compacted.contextTokens ?? 0)) + cost2;
|
|
32536
|
-
return cost2 <= remainingTokens;
|
|
32537
|
-
} catch (error) {
|
|
32538
|
-
if (error instanceof Error && error.name === "ContextBudgetError")
|
|
32539
|
-
return false;
|
|
32540
|
-
throw error;
|
|
32541
|
-
}
|
|
32542
|
-
}, () => history.snapshot().map((message) => message.role === "system" || message.role === "user" ? message : {}));
|
|
32743
|
+
const select = () => selection.prepare(registry);
|
|
32744
|
+
const synchronizeSelection = () => {
|
|
32745
|
+
const planned = select();
|
|
32746
|
+
if (planned.update.toolsAdded.length > 0 || planned.update.toolsRemoved.length > 0) {
|
|
32747
|
+
history.commitToolState(planned.update);
|
|
32748
|
+
}
|
|
32749
|
+
if (planned.announcement) {
|
|
32750
|
+
history.commitToolCatalog({ role: "user", ...planned.announcement });
|
|
32751
|
+
}
|
|
32752
|
+
selection.apply(planned.update);
|
|
32753
|
+
if (planned.missing.length > 0)
|
|
32754
|
+
this.options.onToolStateWarning?.(planned.missing);
|
|
32755
|
+
return select();
|
|
32756
|
+
};
|
|
32543
32757
|
const prepareRequest = async () => {
|
|
32544
|
-
let selected2 =
|
|
32545
|
-
if (selected2.announcement)
|
|
32546
|
-
history.commitToolContext({ role: "user", ...selected2.announcement });
|
|
32758
|
+
let selected2 = synchronizeSelection();
|
|
32547
32759
|
let prepared2 = { messages: history.snapshot() };
|
|
32548
32760
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
32549
32761
|
prepared2 = await this.options.contextGovernor?.prepare({
|
|
@@ -32551,23 +32763,23 @@ var AgentStepRunner = class {
|
|
|
32551
32763
|
tools: selected2.view.definitions,
|
|
32552
32764
|
provider: this.options.provider,
|
|
32553
32765
|
model: this.options.model,
|
|
32554
|
-
projectTools: (
|
|
32766
|
+
projectTools: () => select().view.definitions
|
|
32555
32767
|
}) ?? { messages: history.snapshot() };
|
|
32556
32768
|
history.retain(prepared2.messages);
|
|
32557
|
-
selected2 = select(
|
|
32769
|
+
selected2 = select();
|
|
32558
32770
|
const resources = await this.options.resources?.prepareContext(prepared2.messages, cancelToken?.signal) ?? [];
|
|
32559
32771
|
if (!selected2.announcement && resources.length === 0)
|
|
32560
32772
|
break;
|
|
32561
32773
|
if (attempt === 2)
|
|
32562
32774
|
throw this.options.createError("Resource catalog cannot fit the retained context.");
|
|
32563
|
-
if (selected2.announcement)
|
|
32564
|
-
|
|
32775
|
+
if (selected2.announcement || selected2.update.toolsAdded.length > 0 || selected2.update.toolsRemoved.length > 0) {
|
|
32776
|
+
selected2 = synchronizeSelection();
|
|
32777
|
+
}
|
|
32565
32778
|
for (const message of resources) {
|
|
32566
32779
|
history.commitSkillContext(message);
|
|
32567
32780
|
this.options.resources?.committed([message]);
|
|
32568
32781
|
}
|
|
32569
32782
|
}
|
|
32570
|
-
remainingTokens = prepared2.hardInputLimit === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, prepared2.hardInputLimit - (prepared2.contextTokens ?? 0) - 1024);
|
|
32571
32783
|
return { selected: selected2, prepared: prepared2 };
|
|
32572
32784
|
};
|
|
32573
32785
|
let { selected, prepared } = await prepareRequest();
|
|
@@ -32639,12 +32851,10 @@ var AgentStepRunner = class {
|
|
|
32639
32851
|
tools: definitions,
|
|
32640
32852
|
provider: this.options.provider,
|
|
32641
32853
|
model: this.options.model,
|
|
32642
|
-
projectTools: (
|
|
32854
|
+
projectTools: () => select().view.definitions
|
|
32643
32855
|
});
|
|
32644
32856
|
this.raiseIfCancelled();
|
|
32645
32857
|
history.retain(recovered.messages);
|
|
32646
|
-
remainingTokens = Number.POSITIVE_INFINITY;
|
|
32647
|
-
preflightCompacted = false;
|
|
32648
32858
|
({ selected, prepared } = await prepareRequest());
|
|
32649
32859
|
this.raiseIfCancelled();
|
|
32650
32860
|
tools = selected.view;
|
|
@@ -32728,13 +32938,16 @@ Authentication failed for ${this.options.provider}. Run /login ${this.options.pr
|
|
|
32728
32938
|
onToolResult: (event) => this.completeToolEvent(event, modelRound)
|
|
32729
32939
|
})).results;
|
|
32730
32940
|
const repeated = repeatToolPolicy.record(toolCalls, toolResults);
|
|
32941
|
+
const current = new Map(this.options.getTools().definitions.map((spec2) => [spec2.name, toolVersion(spec2)]));
|
|
32942
|
+
const pending = selected.pending().filter((tool) => current.get(tool.spec.name) === tool.version);
|
|
32943
|
+
if (pending.length) {
|
|
32944
|
+
const update = { toolsAdded: pending, toolsRemoved: [] };
|
|
32945
|
+
history.commitToolState(update);
|
|
32946
|
+
selection.apply(update);
|
|
32947
|
+
}
|
|
32731
32948
|
history.commitToolResults(toolCalls, toolResults);
|
|
32732
32949
|
this.options.resources?.committed(history.snapshot().slice(-toolResults.length));
|
|
32733
32950
|
this.raiseIfCancelled();
|
|
32734
|
-
const current = new Map(this.options.getTools().definitions.map((spec2) => [spec2.name, toolVersion(spec2)]));
|
|
32735
|
-
const pending = selected.pending().filter((tool) => current.get(tool.spec.name) === tool.version);
|
|
32736
|
-
if (pending.length)
|
|
32737
|
-
history.commitToolContext({ role: "system", content: "", toolDefinitions: pending });
|
|
32738
32951
|
const touchedPaths = [];
|
|
32739
32952
|
for (const toolResult of toolResults) {
|
|
32740
32953
|
const touched = touchedPathOf(toolResult);
|
|
@@ -32971,12 +33184,20 @@ var HistoryCommitter = class {
|
|
|
32971
33184
|
this.conversationHistory?.appendSkillContext?.({ message });
|
|
32972
33185
|
this.messages.push(message);
|
|
32973
33186
|
}
|
|
32974
|
-
|
|
33187
|
+
commitToolState(update) {
|
|
32975
33188
|
this.raiseIfCancelled();
|
|
32976
|
-
|
|
32977
|
-
|
|
32978
|
-
|
|
32979
|
-
|
|
33189
|
+
this.conversationHistory?.appendToolState?.({
|
|
33190
|
+
message: {
|
|
33191
|
+
role: "system",
|
|
33192
|
+
content: "",
|
|
33193
|
+
toolDefinitions: update.toolsAdded,
|
|
33194
|
+
toolsRemoved: update.toolsRemoved
|
|
33195
|
+
}
|
|
33196
|
+
});
|
|
33197
|
+
}
|
|
33198
|
+
commitToolCatalog(message) {
|
|
33199
|
+
this.raiseIfCancelled();
|
|
33200
|
+
this.conversationHistory?.appendToolCatalog?.({ message });
|
|
32980
33201
|
this.messages.push(message);
|
|
32981
33202
|
}
|
|
32982
33203
|
/** Adopt the governor's retained context without rewriting the append-only journal. */
|
|
@@ -33045,7 +33266,7 @@ var CodingAgent = class {
|
|
|
33045
33266
|
modelRuntime;
|
|
33046
33267
|
reasoningEffort;
|
|
33047
33268
|
toolRuntime;
|
|
33048
|
-
selection
|
|
33269
|
+
selection;
|
|
33049
33270
|
tools;
|
|
33050
33271
|
repeatToolReminderThresholds;
|
|
33051
33272
|
toolExecution;
|
|
@@ -33066,9 +33287,11 @@ var CodingAgent = class {
|
|
|
33066
33287
|
contextGovernor;
|
|
33067
33288
|
prepareTools;
|
|
33068
33289
|
resources;
|
|
33290
|
+
onToolStateWarning;
|
|
33069
33291
|
constructor(options) {
|
|
33070
33292
|
this.repeatToolReminderThresholds = normalizeReminderThresholds(options.repeatToolReminderThresholds ?? [3, 5, 8]);
|
|
33071
33293
|
this.model = options.model;
|
|
33294
|
+
this.selection = options.toolSelection ?? new ToolSelection();
|
|
33072
33295
|
this.tools = options.tools;
|
|
33073
33296
|
this.onToolEvent = options.onToolEvent ?? null;
|
|
33074
33297
|
this.onAgentEvent = options.onAgentEvent ?? null;
|
|
@@ -33082,9 +33305,11 @@ var CodingAgent = class {
|
|
|
33082
33305
|
this.contextGovernor = options.contextGovernor ?? null;
|
|
33083
33306
|
this.prepareTools = options.prepareTools;
|
|
33084
33307
|
this.resources = options.resources;
|
|
33308
|
+
this.onToolStateWarning = options.onToolStateWarning;
|
|
33085
33309
|
this.modelRuntime = new ModelRuntime(this.adapter);
|
|
33086
33310
|
this.toolExecution = options.toolExecution ?? "parallel";
|
|
33087
33311
|
this.toolRuntime = new ToolRuntime(this.tools, {
|
|
33312
|
+
validateToolArguments: options.validateToolArguments,
|
|
33088
33313
|
createExecutionContext: (toolCallId, cancelToken) => makeToolContext(this.activeContext, toolCallId, cancelToken)
|
|
33089
33314
|
});
|
|
33090
33315
|
this.instructionRoot = options.projectRoot == null ? null : realpathOrSelf(options.projectRoot);
|
|
@@ -33167,6 +33392,7 @@ var CodingAgent = class {
|
|
|
33167
33392
|
onToolEvent: (name, args, result) => {
|
|
33168
33393
|
this.onToolEvent?.(name, args, result);
|
|
33169
33394
|
},
|
|
33395
|
+
onToolStateWarning: this.onToolStateWarning,
|
|
33170
33396
|
createError: (message, cause) => new AgentError(message, { cause }),
|
|
33171
33397
|
createCancelled: (message, cause) => new AgentCancelled(message, { cause })
|
|
33172
33398
|
});
|
|
@@ -33477,7 +33703,7 @@ function createSessionRuntime(options) {
|
|
|
33477
33703
|
let releaseAttachments;
|
|
33478
33704
|
const activeConversationHistory = {
|
|
33479
33705
|
appendSkillContext: (input) => activeHistory(options.sessionController).appendSkillContext(input),
|
|
33480
|
-
|
|
33706
|
+
appendToolState: (input) => activeHistory(options.sessionController).appendToolState(input),
|
|
33481
33707
|
appendToolCatalog: (input) => activeHistory(options.sessionController).appendToolCatalog(input),
|
|
33482
33708
|
appendUser: (input) => activeHistory(options.sessionController).appendUser(input),
|
|
33483
33709
|
appendAssistant: (input) => activeHistory(options.sessionController).appendAssistant(input),
|
|
@@ -33508,6 +33734,7 @@ function createSessionRuntime(options) {
|
|
|
33508
33734
|
};
|
|
33509
33735
|
}
|
|
33510
33736
|
});
|
|
33737
|
+
const toolSelection = new ToolSelection();
|
|
33511
33738
|
const agent = new CodingAgent({
|
|
33512
33739
|
resources: {
|
|
33513
33740
|
prepareInput: async (input, signal, inputs) => {
|
|
@@ -33535,7 +33762,10 @@ function createSessionRuntime(options) {
|
|
|
33535
33762
|
modelAdapter: adapter,
|
|
33536
33763
|
model: route.model,
|
|
33537
33764
|
tools: options.tools,
|
|
33765
|
+
validateToolArguments: validatePiToolArguments,
|
|
33538
33766
|
prepareTools: options.prepareTools,
|
|
33767
|
+
toolSelection,
|
|
33768
|
+
onToolStateWarning: (names) => options.presentation?.toolStateWarning?.(names),
|
|
33539
33769
|
cliName: "laohuang",
|
|
33540
33770
|
cliVersion: options.version,
|
|
33541
33771
|
provider: route.provider,
|
|
@@ -33544,21 +33774,20 @@ function createSessionRuntime(options) {
|
|
|
33544
33774
|
startupCwd: options.startupCwd,
|
|
33545
33775
|
conversationHistory: activeConversationHistory,
|
|
33546
33776
|
contextGovernor: {
|
|
33547
|
-
prepare: async ({ tools, projectTools: projectTools2
|
|
33777
|
+
prepare: async ({ tools, projectTools: projectTools2 }) => {
|
|
33548
33778
|
const history = options.sessionController.history;
|
|
33549
33779
|
if (history === null) {
|
|
33550
33780
|
return { messages: [], contextTokens: 0, contextWindow: 0, hardInputLimit: 0 };
|
|
33551
33781
|
}
|
|
33552
33782
|
const entries = history.entries();
|
|
33553
|
-
const pendingAssistant = pendingToolCall ? [...entries].reverse().find((entry) => entry.entryType === "assistant_message") : void 0;
|
|
33554
33783
|
const prepared = await createGovernor(history).prepare({
|
|
33555
33784
|
protectedFromSeq: attachmentTurnStart,
|
|
33556
|
-
entries
|
|
33785
|
+
entries,
|
|
33557
33786
|
currentProvider: route.provider,
|
|
33558
33787
|
currentModel: route.model,
|
|
33559
33788
|
tools,
|
|
33560
33789
|
projectTools: projectTools2,
|
|
33561
|
-
|
|
33790
|
+
toolState: toolSelection.snapshot(),
|
|
33562
33791
|
budget: modelBudget(selectedModel),
|
|
33563
33792
|
policy: defaultContextPolicy()
|
|
33564
33793
|
});
|
|
@@ -33578,6 +33807,7 @@ function createSessionRuntime(options) {
|
|
|
33578
33807
|
currentModel: route.model,
|
|
33579
33808
|
tools,
|
|
33580
33809
|
projectTools: projectTools2,
|
|
33810
|
+
toolState: toolSelection.snapshot(),
|
|
33581
33811
|
budget: modelBudget(selectedModel),
|
|
33582
33812
|
policy: defaultContextPolicy()
|
|
33583
33813
|
});
|
|
@@ -33603,10 +33833,7 @@ function createSessionRuntime(options) {
|
|
|
33603
33833
|
eventBus: session.eventBus,
|
|
33604
33834
|
journal: () => options.sessionController.currentJournal
|
|
33605
33835
|
});
|
|
33606
|
-
const projectTools = (
|
|
33607
|
-
options.tools,
|
|
33608
|
-
messages.map((message) => message.role === "system" || message.role === "user" ? message : {})
|
|
33609
|
-
).view.definitions;
|
|
33836
|
+
const projectTools = (_messages) => toolSelection.prepare(options.tools).view.definitions;
|
|
33610
33837
|
const refreshContextUsage = () => {
|
|
33611
33838
|
const notify = options.presentation?.contextUsageChanged;
|
|
33612
33839
|
if (notify === void 0) {
|
|
@@ -33632,6 +33859,7 @@ function createSessionRuntime(options) {
|
|
|
33632
33859
|
options.skills?.selectSession(sessionId);
|
|
33633
33860
|
options.presentation?.sessionChanged?.(sessionId);
|
|
33634
33861
|
let entries = history.entries();
|
|
33862
|
+
toolSelection.restore(projectToolSelectionState(entries));
|
|
33635
33863
|
if (entries.length === 0) {
|
|
33636
33864
|
const system = agent.messages.find(
|
|
33637
33865
|
(message) => message.role === "system"
|
|
@@ -33661,6 +33889,7 @@ function createSessionRuntime(options) {
|
|
|
33661
33889
|
currentModel: route.model,
|
|
33662
33890
|
tools: options.tools.definitions,
|
|
33663
33891
|
projectTools,
|
|
33892
|
+
toolState: toolSelection.snapshot(),
|
|
33664
33893
|
budget: modelBudget(selectedModel),
|
|
33665
33894
|
policy: defaultContextPolicy(),
|
|
33666
33895
|
trigger: "manual"
|
|
@@ -40082,17 +40311,22 @@ Submit an empty line to retry, or enter a replacement.`);
|
|
|
40082
40311
|
projectRoot: instructionRoot,
|
|
40083
40312
|
startupCwd: process.cwd(),
|
|
40084
40313
|
version: VERSION,
|
|
40085
|
-
presentation:
|
|
40086
|
-
|
|
40087
|
-
|
|
40088
|
-
|
|
40089
|
-
|
|
40090
|
-
|
|
40091
|
-
|
|
40092
|
-
|
|
40093
|
-
|
|
40094
|
-
|
|
40095
|
-
|
|
40314
|
+
presentation: {
|
|
40315
|
+
toolStateWarning: (names) => runtimeForCleanup?.publishNotice(
|
|
40316
|
+
`Previously active tools are no longer available and were removed: ${names.join(", ")}`
|
|
40317
|
+
),
|
|
40318
|
+
...terminalUi === null ? {} : {
|
|
40319
|
+
sessionChanged: (sessionId) => terminalUi?.setSessionId(sessionId),
|
|
40320
|
+
historyChanged: (entries) => {
|
|
40321
|
+
const transcript = projectTranscript(entries);
|
|
40322
|
+
if (transcript.length > 0) {
|
|
40323
|
+
terminalUi?.replaceTranscript(transcript);
|
|
40324
|
+
} else if (runtimeInitialized) {
|
|
40325
|
+
resetEmptySessionTranscript(terminalUi);
|
|
40326
|
+
}
|
|
40327
|
+
},
|
|
40328
|
+
contextUsageChanged: ({ contextTokens, contextWindow }) => terminalUi?.setContextUsage(contextTokens, contextWindow)
|
|
40329
|
+
}
|
|
40096
40330
|
},
|
|
40097
40331
|
commandDispatcher: (command) => commandDispatcher?.(command) ?? { status: "not_found", command }
|
|
40098
40332
|
});
|