la-machina-engine 0.19.6 → 0.20.0
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 +208 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +208 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2098,6 +2098,7 @@ var AnthropicClient = class {
|
|
|
2098
2098
|
if (betas.length > 0) {
|
|
2099
2099
|
requestOptions.headers = { "anthropic-beta": betas.join(",") };
|
|
2100
2100
|
}
|
|
2101
|
+
if (request.abortSignal !== void 0) requestOptions.signal = request.abortSignal;
|
|
2101
2102
|
let stream;
|
|
2102
2103
|
try {
|
|
2103
2104
|
stream = this.sdk.messages.stream(params, requestOptions);
|
|
@@ -2284,6 +2285,7 @@ var AISdkAdapter = class {
|
|
|
2284
2285
|
tools,
|
|
2285
2286
|
...request.maxTokens !== void 0 ? { maxOutputTokens: request.maxTokens } : {},
|
|
2286
2287
|
...request.temperature !== void 0 ? { temperature: request.temperature } : {},
|
|
2288
|
+
...request.abortSignal !== void 0 ? { abortSignal: request.abortSignal } : {},
|
|
2287
2289
|
// Plan 025 — pass through `'required'` so the AI SDK forwards it
|
|
2288
2290
|
// to the provider as that provider's "force tool call" flag.
|
|
2289
2291
|
...request.toolChoice === "required" ? { toolChoice: "required" } : {},
|
|
@@ -3305,6 +3307,9 @@ async function emitInspectTurn(args) {
|
|
|
3305
3307
|
...cacheRead !== void 0 ? { cacheReadInput: cacheRead } : {}
|
|
3306
3308
|
});
|
|
3307
3309
|
}
|
|
3310
|
+
function isAbortSignalAborted(signal) {
|
|
3311
|
+
return signal?.aborted === true;
|
|
3312
|
+
}
|
|
3308
3313
|
var DEFAULT_COMPACTION = {
|
|
3309
3314
|
strategy: "drop-middle",
|
|
3310
3315
|
threshold: 0.85,
|
|
@@ -3457,6 +3462,7 @@ async function agentLoop(options) {
|
|
|
3457
3462
|
messages: normalizedMessages,
|
|
3458
3463
|
system,
|
|
3459
3464
|
tools: anthropicTools,
|
|
3465
|
+
...options.runSignal !== void 0 ? { abortSignal: options.runSignal } : {},
|
|
3460
3466
|
...escalatedMaxTokens !== void 0 ? { maxTokens: escalatedMaxTokens } : {},
|
|
3461
3467
|
...options.toolChoice !== void 0 ? { toolChoice: options.toolChoice } : {}
|
|
3462
3468
|
})) {
|
|
@@ -3470,6 +3476,9 @@ async function agentLoop(options) {
|
|
|
3470
3476
|
}
|
|
3471
3477
|
}
|
|
3472
3478
|
} catch (err) {
|
|
3479
|
+
if (isAbortSignalAborted(options.runSignal)) {
|
|
3480
|
+
return failed(new RunTimeoutError(options.runTimeoutMs ?? 0), transcript);
|
|
3481
|
+
}
|
|
3473
3482
|
if (isPromptTooLong(err) && !compactedThisTurn) {
|
|
3474
3483
|
compactedThisTurn = true;
|
|
3475
3484
|
const emergency = await compactIfNeeded({
|
|
@@ -9069,6 +9078,123 @@ function describe(svc) {
|
|
|
9069
9078
|
endpoints
|
|
9070
9079
|
};
|
|
9071
9080
|
}
|
|
9081
|
+
function describeEndpoint(ep) {
|
|
9082
|
+
return {
|
|
9083
|
+
method: ep.method,
|
|
9084
|
+
path: ep.path,
|
|
9085
|
+
description: ep.description,
|
|
9086
|
+
...ep.inputSchema !== void 0 ? { inputSchema: ep.inputSchema } : {},
|
|
9087
|
+
...ep.outputHint !== void 0 ? { outputHint: ep.outputHint } : {},
|
|
9088
|
+
...ep.pagination !== void 0 ? { pagination: ep.pagination } : {},
|
|
9089
|
+
...ep.response !== void 0 ? { response: ep.response } : {}
|
|
9090
|
+
};
|
|
9091
|
+
}
|
|
9092
|
+
var DEFAULT_SEARCH_LIMIT = 8;
|
|
9093
|
+
var MAX_SEARCH_LIMIT = 20;
|
|
9094
|
+
var FIELD_WEIGHTS = {
|
|
9095
|
+
path: 3,
|
|
9096
|
+
method: 2,
|
|
9097
|
+
description: 2,
|
|
9098
|
+
inputKey: 1,
|
|
9099
|
+
outputHint: 1,
|
|
9100
|
+
response: 1
|
|
9101
|
+
};
|
|
9102
|
+
function tokenize(input) {
|
|
9103
|
+
return input.toLowerCase().split(/[\s/_-]+/).map((t) => t.trim()).filter((t) => t.length > 0);
|
|
9104
|
+
}
|
|
9105
|
+
function isObject(v) {
|
|
9106
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
9107
|
+
}
|
|
9108
|
+
function scoreEndpointMatch(ep, tokens, opts) {
|
|
9109
|
+
let score = 0;
|
|
9110
|
+
const matched = /* @__PURE__ */ new Set();
|
|
9111
|
+
const pathLower = ep.path.toLowerCase();
|
|
9112
|
+
const methodLower = ep.method.toLowerCase();
|
|
9113
|
+
const descriptionLower = ep.description.toLowerCase();
|
|
9114
|
+
const outputHintLower = ep.outputHint?.toLowerCase() ?? "";
|
|
9115
|
+
const responseBlob = [ep.response?.itemsPath, ep.response?.totalPath, ep.pagination?.mode].filter((s) => typeof s === "string" && s.length > 0).join(" ").toLowerCase();
|
|
9116
|
+
const inputKeys = [];
|
|
9117
|
+
if (isObject(ep.inputSchema)) {
|
|
9118
|
+
const props = ep.inputSchema.properties;
|
|
9119
|
+
if (isObject(props)) {
|
|
9120
|
+
for (const key of Object.keys(props)) inputKeys.push(key);
|
|
9121
|
+
}
|
|
9122
|
+
}
|
|
9123
|
+
const inputKeysLower = inputKeys.map((k) => k.toLowerCase());
|
|
9124
|
+
for (const t of tokens) {
|
|
9125
|
+
if (pathLower.includes(t)) {
|
|
9126
|
+
score += FIELD_WEIGHTS.path;
|
|
9127
|
+
matched.add("path");
|
|
9128
|
+
}
|
|
9129
|
+
if (opts.pathOnly) continue;
|
|
9130
|
+
if (t === methodLower) {
|
|
9131
|
+
score += FIELD_WEIGHTS.method;
|
|
9132
|
+
matched.add("method");
|
|
9133
|
+
}
|
|
9134
|
+
if (descriptionLower.includes(t)) {
|
|
9135
|
+
score += FIELD_WEIGHTS.description;
|
|
9136
|
+
matched.add("description");
|
|
9137
|
+
}
|
|
9138
|
+
if (inputKeysLower.some((k) => k.includes(t))) {
|
|
9139
|
+
score += FIELD_WEIGHTS.inputKey;
|
|
9140
|
+
matched.add("inputKey");
|
|
9141
|
+
}
|
|
9142
|
+
if (outputHintLower.length > 0 && outputHintLower.includes(t)) {
|
|
9143
|
+
score += FIELD_WEIGHTS.outputHint;
|
|
9144
|
+
matched.add("outputHint");
|
|
9145
|
+
}
|
|
9146
|
+
if (responseBlob.length > 0 && responseBlob.includes(t)) {
|
|
9147
|
+
score += FIELD_WEIGHTS.response;
|
|
9148
|
+
matched.add("response");
|
|
9149
|
+
}
|
|
9150
|
+
}
|
|
9151
|
+
if (score === 0) return { score: 0, matched: [] };
|
|
9152
|
+
return {
|
|
9153
|
+
score,
|
|
9154
|
+
matched: [...matched].sort(),
|
|
9155
|
+
...inputKeys.length > 0 ? { inputKeys } : {}
|
|
9156
|
+
};
|
|
9157
|
+
}
|
|
9158
|
+
function searchService(svc, opts) {
|
|
9159
|
+
const tokens = tokenize(opts.query);
|
|
9160
|
+
const endpoints = svc.endpoints ?? [];
|
|
9161
|
+
const scored = [];
|
|
9162
|
+
for (const ep of endpoints) {
|
|
9163
|
+
if (opts.method !== void 0 && ep.method !== opts.method) continue;
|
|
9164
|
+
const r = scoreEndpointMatch(ep, tokens, { pathOnly: opts.pathOnly });
|
|
9165
|
+
if (r.score === 0) continue;
|
|
9166
|
+
scored.push({
|
|
9167
|
+
ep,
|
|
9168
|
+
score: r.score,
|
|
9169
|
+
matched: r.matched,
|
|
9170
|
+
...r.inputKeys !== void 0 ? { inputKeys: r.inputKeys } : {}
|
|
9171
|
+
});
|
|
9172
|
+
}
|
|
9173
|
+
scored.sort((a, b) => {
|
|
9174
|
+
if (b.score !== a.score) return b.score - a.score;
|
|
9175
|
+
if (a.ep.method !== b.ep.method) {
|
|
9176
|
+
return a.ep.method < b.ep.method ? -1 : 1;
|
|
9177
|
+
}
|
|
9178
|
+
if (a.ep.path !== b.ep.path) return a.ep.path < b.ep.path ? -1 : 1;
|
|
9179
|
+
return 0;
|
|
9180
|
+
});
|
|
9181
|
+
const truncated = scored.length > opts.limit;
|
|
9182
|
+
const slice = scored.slice(0, opts.limit);
|
|
9183
|
+
return {
|
|
9184
|
+
service: svc.name,
|
|
9185
|
+
query: opts.query,
|
|
9186
|
+
matches: slice.map((s) => ({
|
|
9187
|
+
method: s.ep.method,
|
|
9188
|
+
path: s.ep.path,
|
|
9189
|
+
description: s.ep.description,
|
|
9190
|
+
score: s.score,
|
|
9191
|
+
matched: s.matched,
|
|
9192
|
+
...s.inputKeys !== void 0 && s.inputKeys.length > 0 ? { inputKeys: s.inputKeys } : {},
|
|
9193
|
+
...s.ep.outputHint !== void 0 ? { outputHint: s.ep.outputHint } : {}
|
|
9194
|
+
})),
|
|
9195
|
+
...truncated ? { truncated: true } : {}
|
|
9196
|
+
};
|
|
9197
|
+
}
|
|
9072
9198
|
function hasDescribableEndpoints(svc) {
|
|
9073
9199
|
return svc.endpoints !== void 0 && svc.endpoints.length > 0;
|
|
9074
9200
|
}
|
|
@@ -9084,18 +9210,39 @@ function createDescribeServiceTool(opts) {
|
|
|
9084
9210
|
const serviceNames = [...serviceMap.keys()];
|
|
9085
9211
|
const cache = /* @__PURE__ */ new Map();
|
|
9086
9212
|
const inputSchema19 = import_zod24.z.object({
|
|
9087
|
-
service: import_zod24.z.enum(serviceNames)
|
|
9213
|
+
service: import_zod24.z.enum(serviceNames),
|
|
9214
|
+
/**
|
|
9215
|
+
* Plan 054 — free-text query. When set with no `path`, returns
|
|
9216
|
+
* the compact ranked-match shape. Must be a non-empty string.
|
|
9217
|
+
*/
|
|
9218
|
+
query: import_zod24.z.string().min(1).optional(),
|
|
9219
|
+
/**
|
|
9220
|
+
* Plan 054 — narrow ranked matches to one HTTP verb. Also used
|
|
9221
|
+
* by the exact-endpoint branch in combination with `path`.
|
|
9222
|
+
*/
|
|
9223
|
+
method: import_zod24.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).optional(),
|
|
9224
|
+
/**
|
|
9225
|
+
* Plan 054 — paired with `method` returns full endpoint detail;
|
|
9226
|
+
* paired without `method` runs a path-only ranked search.
|
|
9227
|
+
*/
|
|
9228
|
+
path: import_zod24.z.string().min(1).optional(),
|
|
9229
|
+
/**
|
|
9230
|
+
* Plan 054 — defaults to 8, capped at 20. Only meaningful in
|
|
9231
|
+
* search modes; ignored when fetching the full catalog or one
|
|
9232
|
+
* exact endpoint.
|
|
9233
|
+
*/
|
|
9234
|
+
limit: import_zod24.z.number().int().min(1).max(MAX_SEARCH_LIMIT).optional()
|
|
9088
9235
|
});
|
|
9089
|
-
const description = `Look up
|
|
9236
|
+
const description = `Look up endpoints on one configured API service.
|
|
9237
|
+
1. Search: DescribeService({ service, query }) returns compact ranked matches with method, path, description, and a relevance score. Use this for broad services where only one endpoint slice is needed. Add { method } to filter.
|
|
9238
|
+
2. Detail: DescribeService({ service, method, path }) returns full endpoint detail including inputSchema. Call this after a search has picked a candidate.
|
|
9239
|
+
3. Execute: ApiCall(...) with the chosen method, path, and inputs.
|
|
9240
|
+
Legacy: DescribeService({ service }) returns the full endpoint catalog \u2014 expensive for large services and discouraged for new code. Services: ${serviceNames.join(", ")}.`;
|
|
9090
9241
|
return defineTool({
|
|
9091
9242
|
name: opts.toolName ?? "DescribeService",
|
|
9092
9243
|
description,
|
|
9093
9244
|
inputSchema: inputSchema19,
|
|
9094
9245
|
execute: async (input) => {
|
|
9095
|
-
const cached = cache.get(input.service);
|
|
9096
|
-
if (cached !== void 0) {
|
|
9097
|
-
return { content: JSON.stringify(cached), metadata: { cached: true } };
|
|
9098
|
-
}
|
|
9099
9246
|
const svc = serviceMap.get(input.service);
|
|
9100
9247
|
if (!svc) {
|
|
9101
9248
|
return {
|
|
@@ -9103,6 +9250,56 @@ function createDescribeServiceTool(opts) {
|
|
|
9103
9250
|
isError: true
|
|
9104
9251
|
};
|
|
9105
9252
|
}
|
|
9253
|
+
const limit = Math.min(input.limit ?? DEFAULT_SEARCH_LIMIT, MAX_SEARCH_LIMIT);
|
|
9254
|
+
if (input.method !== void 0 && input.path !== void 0) {
|
|
9255
|
+
const ep = (svc.endpoints ?? []).find(
|
|
9256
|
+
(e) => e.method === input.method && e.path === input.path
|
|
9257
|
+
);
|
|
9258
|
+
if (ep === void 0) {
|
|
9259
|
+
return {
|
|
9260
|
+
content: JSON.stringify({
|
|
9261
|
+
code: "ENDPOINT_NOT_FOUND",
|
|
9262
|
+
service: input.service,
|
|
9263
|
+
method: input.method,
|
|
9264
|
+
path: input.path,
|
|
9265
|
+
message: `No endpoint ${input.method} ${input.path} on service "${input.service}". Call DescribeService with { service, query } to search the catalog.`
|
|
9266
|
+
}),
|
|
9267
|
+
isError: true
|
|
9268
|
+
};
|
|
9269
|
+
}
|
|
9270
|
+
return {
|
|
9271
|
+
content: JSON.stringify(describeEndpoint(ep)),
|
|
9272
|
+
metadata: { mode: "detail" }
|
|
9273
|
+
};
|
|
9274
|
+
}
|
|
9275
|
+
if (input.query !== void 0) {
|
|
9276
|
+
const result = searchService(svc, {
|
|
9277
|
+
query: input.query,
|
|
9278
|
+
...input.method !== void 0 ? { method: input.method } : {},
|
|
9279
|
+
limit,
|
|
9280
|
+
pathOnly: false
|
|
9281
|
+
});
|
|
9282
|
+
return {
|
|
9283
|
+
content: JSON.stringify(result),
|
|
9284
|
+
metadata: { mode: "search" }
|
|
9285
|
+
};
|
|
9286
|
+
}
|
|
9287
|
+
if (input.path !== void 0) {
|
|
9288
|
+
const result = searchService(svc, {
|
|
9289
|
+
query: input.path,
|
|
9290
|
+
...input.method !== void 0 ? { method: input.method } : {},
|
|
9291
|
+
limit,
|
|
9292
|
+
pathOnly: true
|
|
9293
|
+
});
|
|
9294
|
+
return {
|
|
9295
|
+
content: JSON.stringify(result),
|
|
9296
|
+
metadata: { mode: "search" }
|
|
9297
|
+
};
|
|
9298
|
+
}
|
|
9299
|
+
const cached = cache.get(input.service);
|
|
9300
|
+
if (cached !== void 0) {
|
|
9301
|
+
return { content: JSON.stringify(cached), metadata: { cached: true } };
|
|
9302
|
+
}
|
|
9106
9303
|
const payload = describe(svc);
|
|
9107
9304
|
cache.set(input.service, payload);
|
|
9108
9305
|
return { content: JSON.stringify(payload), metadata: { cached: false } };
|
|
@@ -9179,7 +9376,7 @@ var STOP_WORDS = /* @__PURE__ */ new Set([
|
|
|
9179
9376
|
"he",
|
|
9180
9377
|
"she"
|
|
9181
9378
|
]);
|
|
9182
|
-
function
|
|
9379
|
+
function tokenize2(text2) {
|
|
9183
9380
|
if (typeof text2 !== "string" || text2.length === 0) return [];
|
|
9184
9381
|
const seen = /* @__PURE__ */ new Set();
|
|
9185
9382
|
for (const raw of text2.toLowerCase().split(/[\W_]+/)) {
|
|
@@ -9294,7 +9491,7 @@ function splitSections(content, relPath) {
|
|
|
9294
9491
|
heading: "",
|
|
9295
9492
|
slug: `${relPath}#`,
|
|
9296
9493
|
depth: 0,
|
|
9297
|
-
words:
|
|
9494
|
+
words: tokenize2(leadInBody),
|
|
9298
9495
|
preview: makePreview(leadInBody),
|
|
9299
9496
|
startLine: 1,
|
|
9300
9497
|
endLine: leadInEndLine
|
|
@@ -9310,7 +9507,7 @@ function splitSections(content, relPath) {
|
|
|
9310
9507
|
heading: h.heading,
|
|
9311
9508
|
slug: `${relPath}#${slugify(h.heading)}`,
|
|
9312
9509
|
depth: h.depth,
|
|
9313
|
-
words:
|
|
9510
|
+
words: tokenize2(body),
|
|
9314
9511
|
preview: makePreview(body),
|
|
9315
9512
|
startLine,
|
|
9316
9513
|
endLine
|
|
@@ -9427,7 +9624,7 @@ function createSearchKnowledgeTool(opts) {
|
|
|
9427
9624
|
inputSchema: inputSchema17,
|
|
9428
9625
|
execute: async ({ query, maxResults }) => {
|
|
9429
9626
|
const limit = Math.min(maxResults ?? cap, cap);
|
|
9430
|
-
const queryTokens =
|
|
9627
|
+
const queryTokens = tokenize2(query);
|
|
9431
9628
|
if (queryTokens.length === 0) {
|
|
9432
9629
|
return { content: "no searchable tokens in query", isError: false };
|
|
9433
9630
|
}
|
|
@@ -9452,7 +9649,7 @@ function createSearchKnowledgeTool(opts) {
|
|
|
9452
9649
|
}
|
|
9453
9650
|
const externalHits = [];
|
|
9454
9651
|
for (const link of externals) {
|
|
9455
|
-
const score = scoreOverlap(
|
|
9652
|
+
const score = scoreOverlap(tokenize2(link.description), queryTokens);
|
|
9456
9653
|
if (score > 0) externalHits.push({ link, score });
|
|
9457
9654
|
}
|
|
9458
9655
|
const all = [
|