UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

93 lines • 4.18 kB
"use strict"; /** * toolChoice/compose — the tools slot's armed tail, behind the same `import()`. * * Pattern: one function the slot awaits under `.toolChoice()` — ask, decide, * file the row, hand back what to commit. * Role: core/ layer. Called ONLY by `slots/buildToolsSlot.ts · * composeStage` after `mergeWire`, through `import()` (the * optional-family law of docs-next's site budget: everything this * family adds to a model call lives off the default graph, and the * slot keeps six lines). What it returns is committed by the slot's * own `commitWire`, so the decoration, the receipt and the served * view see the narrowed list at the one site they always read. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.composeToolChoice = void 0; const pick_js_1 = require("./pick.js"); const record_js_1 = require("./record.js"); /** * Ask the classifier about the merged wire minus the doors, decide what is * served, file the `pick` / `pick-error` row (the row records the offer the * classifier read and the list really served), and return the list to * commit. A call with nothing to choose among makes no classifier call and * files no row. */ async function composeToolChoice(input) { const { merged, injections, injectionNames, iteration, prior } = input; const doors = (0, pick_js_1.alwaysServedNames)(input.alwaysServe); const offered = merged.filter((t) => !doors.has(t.name)); if (offered.length === 0) return { served: merged, servedInjections: injections, narrowedTo: undefined }; const pick = await (0, pick_js_1.pickTools)(input.classifier, { userMessage: input.userMessage, ...(input.currentSkillId !== undefined && { currentSkillId: input.currentSkillId }), candidates: offered.map((t) => ({ name: t.name, description: t.description ?? '' })), }, input.scope.$getEnv().signal); const narrowing = (0, pick_js_1.narrowServed)({ wire: merged.map((t) => t.name), doors, pick, top: input.top, iteration, prior, wrapUpAsked: input.wrapUpAsked, ...(input.toolsOff === true && { toolsOff: true }), }); const servedNames = new Set(narrowing.served); const row = pick.ok ? ({ kind: 'pick', iteration, source: 'classifier', classifier: pick.classifier, offered: offered.map((t) => t.name), ranked: pick.ranked, ...(pick.chosen !== undefined && { chosen: pick.chosen }), confidence: pick.confidence, ...(pick.usage !== undefined && { usage: pick.usage }), latencyMs: pick.latencyMs, served: [...narrowing.served], narrowed: narrowing.narrowed, ...(narrowing.narrowedSkipped !== undefined && { narrowedSkipped: narrowing.narrowedSkipped, }), }) : { kind: 'pick-error', iteration, source: 'classifier', classifier: pick.classifier, ...(pick.status !== undefined && { status: pick.status }), message: pick.message, latencyMs: pick.latencyMs, served: [...narrowing.served], ...(narrowing.narrowedSkipped !== undefined && { narrowedSkipped: narrowing.narrowedSkipped, }), }; (0, record_js_1.recordToolChoice)(input.scope, row, prior); if (!narrowing.narrowed) return { served: merged, servedInjections: injections, narrowedTo: undefined }; return { served: merged.filter((t) => servedNames.has(t.name)), // The slot record follows the served list: one InjectionRecord per tool // the model is handed, re-numbered so `position` is the served index. servedInjections: injections .filter((_, i) => servedNames.has(injectionNames[i] ?? '')) .map((r, i) => ({ ...r, position: i })), narrowedTo: servedNames, }; } exports.composeToolChoice = composeToolChoice; //# sourceMappingURL=compose.js.map