la-machina-engine 0.7.2 → 0.7.4
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.cjs +94 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +65 -8
- package/dist/index.d.ts +65 -8
- package/dist/index.js +94 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1817,7 +1817,11 @@ var AnthropicClient = class {
|
|
|
1817
1817
|
messages: request.messages,
|
|
1818
1818
|
stream: true,
|
|
1819
1819
|
...request.system !== void 0 ? { system: request.system } : {},
|
|
1820
|
-
...request.tools !== void 0 ? { tools: request.tools } : {}
|
|
1820
|
+
...request.tools !== void 0 ? { tools: request.tools } : {},
|
|
1821
|
+
// Plan 025 — `'required'` maps to Anthropic's `tool_choice: { type: 'any' }`,
|
|
1822
|
+
// which forces the model to call SOME tool but doesn't pin which.
|
|
1823
|
+
// `'auto'` is the SDK default — omit to let it through unchanged.
|
|
1824
|
+
...request.toolChoice === "required" ? { tool_choice: { type: "any" } } : {}
|
|
1821
1825
|
};
|
|
1822
1826
|
const requestOptions = {};
|
|
1823
1827
|
if (betas.length > 0) {
|
|
@@ -1999,6 +2003,9 @@ var AISdkAdapter = class {
|
|
|
1999
2003
|
tools,
|
|
2000
2004
|
...request.maxTokens !== void 0 ? { maxOutputTokens: request.maxTokens } : {},
|
|
2001
2005
|
...request.temperature !== void 0 ? { temperature: request.temperature } : {},
|
|
2006
|
+
// Plan 025 — pass through `'required'` so the AI SDK forwards it
|
|
2007
|
+
// to the provider as that provider's "force tool call" flag.
|
|
2008
|
+
...request.toolChoice === "required" ? { toolChoice: "required" } : {},
|
|
2002
2009
|
maxRetries: this.options.maxRetries ?? 2
|
|
2003
2010
|
});
|
|
2004
2011
|
for await (const event of result.fullStream) {
|
|
@@ -2618,6 +2625,17 @@ function ensureToolResultPairing(messages) {
|
|
|
2618
2625
|
return messages;
|
|
2619
2626
|
}
|
|
2620
2627
|
|
|
2628
|
+
// src/engine/lastTurnGuard.ts
|
|
2629
|
+
init_cjs_shims();
|
|
2630
|
+
var LAST_TURN_INSTRUCTION_JSON = "SYSTEM NOTE: This is your final allowed turn. Emit ONLY the JSON object that satisfies the output schema in the system prompt. Do not call any more tools. Do not write any explanation, narration, or markdown \u2014 only the raw JSON.";
|
|
2631
|
+
var LAST_TURN_INSTRUCTION_TEXT = "SYSTEM NOTE: This is your final allowed turn. Stop calling tools and deliver your final answer now. The next turn will not happen.";
|
|
2632
|
+
function lastTurnInstruction(outputFormat) {
|
|
2633
|
+
return outputFormat === "json" ? LAST_TURN_INSTRUCTION_JSON : LAST_TURN_INSTRUCTION_TEXT;
|
|
2634
|
+
}
|
|
2635
|
+
function shouldInjectLastTurnInstruction(opts) {
|
|
2636
|
+
return opts.turnCount + 1 === opts.maxTurns;
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2621
2639
|
// src/compact/compactor.ts
|
|
2622
2640
|
init_cjs_shims();
|
|
2623
2641
|
|
|
@@ -3109,15 +3127,29 @@ async function agentLoop(options) {
|
|
|
3109
3127
|
const toolCalls = [];
|
|
3110
3128
|
let stopReason = null;
|
|
3111
3129
|
let turnUsage = { input: 0, output: 0 };
|
|
3130
|
+
let messagesForApi = messages;
|
|
3131
|
+
if (shouldInjectLastTurnInstruction({
|
|
3132
|
+
turnCount: ctx.getTurnCount(),
|
|
3133
|
+
maxTurns: ctx.getMaxTurns()
|
|
3134
|
+
})) {
|
|
3135
|
+
messagesForApi = [
|
|
3136
|
+
...messages,
|
|
3137
|
+
{
|
|
3138
|
+
role: "user",
|
|
3139
|
+
content: [{ type: "text", text: lastTurnInstruction(options.outputFormat) }]
|
|
3140
|
+
}
|
|
3141
|
+
];
|
|
3142
|
+
}
|
|
3112
3143
|
const normalizedMessages = normalizeMessages(
|
|
3113
|
-
|
|
3144
|
+
messagesForApi
|
|
3114
3145
|
);
|
|
3115
3146
|
try {
|
|
3116
3147
|
for await (const event of client.streamMessage({
|
|
3117
3148
|
messages: normalizedMessages,
|
|
3118
3149
|
system,
|
|
3119
3150
|
tools: anthropicTools,
|
|
3120
|
-
...escalatedMaxTokens !== void 0 ? { maxTokens: escalatedMaxTokens } : {}
|
|
3151
|
+
...escalatedMaxTokens !== void 0 ? { maxTokens: escalatedMaxTokens } : {},
|
|
3152
|
+
...options.toolChoice !== void 0 ? { toolChoice: options.toolChoice } : {}
|
|
3121
3153
|
})) {
|
|
3122
3154
|
const handled = consumeEvent(event);
|
|
3123
3155
|
if (handled.text !== void 0) textBlocks.push(handled.text);
|
|
@@ -3668,6 +3700,9 @@ var RunContext = class {
|
|
|
3668
3700
|
getTurnCount() {
|
|
3669
3701
|
return this.turnCount;
|
|
3670
3702
|
}
|
|
3703
|
+
getMaxTurns() {
|
|
3704
|
+
return this.maxTurns;
|
|
3705
|
+
}
|
|
3671
3706
|
getTokensUsed() {
|
|
3672
3707
|
return this.tokensUsed;
|
|
3673
3708
|
}
|
|
@@ -7866,6 +7901,9 @@ async function collectSkills(storage, skillsDir) {
|
|
|
7866
7901
|
// src/engine/jsonOutput.ts
|
|
7867
7902
|
init_cjs_shims();
|
|
7868
7903
|
var import_zod_to_json_schema2 = require("zod-to-json-schema");
|
|
7904
|
+
function isZodSchema(s) {
|
|
7905
|
+
return s !== null && typeof s === "object" && "_def" in s && typeof s.safeParse === "function";
|
|
7906
|
+
}
|
|
7869
7907
|
function buildSchemaPrompt(schema) {
|
|
7870
7908
|
const lines = [
|
|
7871
7909
|
"# Output Format",
|
|
@@ -7875,11 +7913,18 @@ function buildSchemaPrompt(schema) {
|
|
|
7875
7913
|
"Do NOT wrap in ```json ... ```. Just raw JSON."
|
|
7876
7914
|
];
|
|
7877
7915
|
if (schema) {
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7916
|
+
let clean;
|
|
7917
|
+
if (isZodSchema(schema)) {
|
|
7918
|
+
const jsonSchema2 = (0, import_zod_to_json_schema2.zodToJsonSchema)(schema, {
|
|
7919
|
+
target: "jsonSchema7",
|
|
7920
|
+
$refStrategy: "none"
|
|
7921
|
+
});
|
|
7922
|
+
const { $schema: _z, ...rest } = jsonSchema2;
|
|
7923
|
+
clean = rest;
|
|
7924
|
+
} else {
|
|
7925
|
+
const { $schema: _j, ...rest } = schema;
|
|
7926
|
+
clean = rest;
|
|
7927
|
+
}
|
|
7883
7928
|
lines.push("", "The JSON MUST conform to this schema:", JSON.stringify(clean, null, 2));
|
|
7884
7929
|
} else {
|
|
7885
7930
|
lines.push("", "Return a JSON object with the relevant data.");
|
|
@@ -7915,6 +7960,9 @@ function tryParseJSON2(text2) {
|
|
|
7915
7960
|
return { ok: false, error: "No valid JSON found in response" };
|
|
7916
7961
|
}
|
|
7917
7962
|
function validateOutput(value, schema) {
|
|
7963
|
+
if (!isZodSchema(schema)) {
|
|
7964
|
+
return { ok: true, data: value };
|
|
7965
|
+
}
|
|
7918
7966
|
const result = schema.safeParse(value);
|
|
7919
7967
|
if (result.success) {
|
|
7920
7968
|
return { ok: true, data: result.data };
|
|
@@ -9644,6 +9692,35 @@ var TranscriptReader = class {
|
|
|
9644
9692
|
}
|
|
9645
9693
|
};
|
|
9646
9694
|
|
|
9695
|
+
// src/engine/runToolFilter.ts
|
|
9696
|
+
init_cjs_shims();
|
|
9697
|
+
function applyRunToolFilter(registry, options) {
|
|
9698
|
+
const stripAll = options.toolChoice === "none" || options.tools !== void 0 && options.tools.length === 0;
|
|
9699
|
+
if (stripAll) {
|
|
9700
|
+
if (options.toolChoice === "required") {
|
|
9701
|
+
throw new EngineError(
|
|
9702
|
+
"ERR_TOOL_CHOICE_CONFLICT",
|
|
9703
|
+
"toolChoice: 'required' is incompatible with an empty tool set (received tools: [] or toolChoice: 'none')."
|
|
9704
|
+
);
|
|
9705
|
+
}
|
|
9706
|
+
for (const tool of registry.list()) {
|
|
9707
|
+
registry.unregister(tool.name);
|
|
9708
|
+
}
|
|
9709
|
+
return;
|
|
9710
|
+
}
|
|
9711
|
+
if (options.tools === void 0) return;
|
|
9712
|
+
const allow = new Set(options.tools);
|
|
9713
|
+
for (const tool of registry.list()) {
|
|
9714
|
+
if (!allow.has(tool.name)) registry.unregister(tool.name);
|
|
9715
|
+
}
|
|
9716
|
+
if (options.toolChoice === "required" && registry.count() === 0) {
|
|
9717
|
+
throw new EngineError(
|
|
9718
|
+
"ERR_TOOL_CHOICE_CONFLICT",
|
|
9719
|
+
"toolChoice: 'required' was requested but no tools matched the per-run allowlist after applying config filters."
|
|
9720
|
+
);
|
|
9721
|
+
}
|
|
9722
|
+
}
|
|
9723
|
+
|
|
9647
9724
|
// src/engine/rehydrate.ts
|
|
9648
9725
|
init_cjs_shims();
|
|
9649
9726
|
function rebuildMessagesFromEntries(entries) {
|
|
@@ -10120,6 +10197,7 @@ var Engine = class {
|
|
|
10120
10197
|
...knowledgeRuntime !== void 0 ? { knowledge: knowledgeRuntime } : {},
|
|
10121
10198
|
...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
|
|
10122
10199
|
});
|
|
10200
|
+
applyRunToolFilter(registry, options);
|
|
10123
10201
|
const writer = new TranscriptWriter({
|
|
10124
10202
|
storage: storage.workspace,
|
|
10125
10203
|
logPath,
|
|
@@ -10174,7 +10252,14 @@ var Engine = class {
|
|
|
10174
10252
|
...runTimeout.signal !== void 0 ? { runSignal: runTimeout.signal, runTimeoutMs: this.config.execution.runTimeoutMs } : {},
|
|
10175
10253
|
...gate !== void 0 ? { gateBeforeTool: gate } : {},
|
|
10176
10254
|
..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {},
|
|
10177
|
-
...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {}
|
|
10255
|
+
...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {},
|
|
10256
|
+
// Plan 025 — output mode + tool-choice plumbed down so the
|
|
10257
|
+
// last-turn guard picks the right instruction text and the
|
|
10258
|
+
// model adapter can pass `'required'` to the provider. `'none'`
|
|
10259
|
+
// is already handled above by stripping the tool list, so the
|
|
10260
|
+
// loop only ever sees `'auto'` or `'required'`.
|
|
10261
|
+
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|
|
10262
|
+
...options.toolChoice === "required" ? { toolChoice: "required" } : {}
|
|
10178
10263
|
});
|
|
10179
10264
|
const result = await this.finalizeResult(loopResult, writer, logPath, {
|
|
10180
10265
|
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|