@linnlabs/linnkit 0.8.0 → 0.9.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/CHANGELOG.md +18 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/cli.cjs +118 -28
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +118 -28
- package/dist/cli.js.map +1 -1
- package/dist/context-manager.cjs +0 -4
- package/dist/context-manager.cjs.map +1 -1
- package/dist/context-manager.js +0 -4
- package/dist/context-manager.js.map +1 -1
- package/dist/{index-Cm-JbzTH.d.cts → index-BanRABEt.d.cts} +14 -3
- package/dist/{index-DRBWi1fy.d.ts → index-Z8NXKNwI.d.ts} +14 -3
- package/dist/index.cjs +146 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +146 -30
- package/dist/index.js.map +1 -1
- package/dist/quickstart.cjs +115 -25
- package/dist/quickstart.cjs.map +1 -1
- package/dist/quickstart.js +115 -25
- package/dist/quickstart.js.map +1 -1
- package/dist/runtime-kernel.cjs +142 -26
- package/dist/runtime-kernel.cjs.map +1 -1
- package/dist/runtime-kernel.d.cts +1 -1
- package/dist/runtime-kernel.d.ts +1 -1
- package/dist/runtime-kernel.js +140 -27
- package/dist/runtime-kernel.js.map +1 -1
- package/dist/testkit.cjs +155 -39
- package/dist/testkit.cjs.map +1 -1
- package/dist/testkit.js +155 -39
- package/dist/testkit.js.map +1 -1
- package/package.json +3 -3
package/dist/runtime-kernel.cjs
CHANGED
|
@@ -42,7 +42,6 @@ var Logger = class {
|
|
|
42
42
|
constructor(moduleName) {
|
|
43
43
|
this.moduleName = moduleName;
|
|
44
44
|
}
|
|
45
|
-
moduleName;
|
|
46
45
|
debug(message, data) {
|
|
47
46
|
this.log(0 /* DEBUG */, "debug", message, data);
|
|
48
47
|
}
|
|
@@ -1030,7 +1029,6 @@ var GraphExecutor = class {
|
|
|
1030
1029
|
};
|
|
1031
1030
|
this.telemetryPort = config.telemetryPort ?? noopTelemetry;
|
|
1032
1031
|
}
|
|
1033
|
-
checkpointer;
|
|
1034
1032
|
nodes = /* @__PURE__ */ new Map();
|
|
1035
1033
|
ephemeralLocals = /* @__PURE__ */ new Map();
|
|
1036
1034
|
config;
|
|
@@ -4423,6 +4421,22 @@ var ToolNode = class {
|
|
|
4423
4421
|
});
|
|
4424
4422
|
}
|
|
4425
4423
|
async run(state) {
|
|
4424
|
+
const events = [];
|
|
4425
|
+
while (true) {
|
|
4426
|
+
const result = await this.runNextPendingToolCall(state);
|
|
4427
|
+
if (Array.isArray(result.events) && result.events.length > 0) {
|
|
4428
|
+
events.push(...result.events);
|
|
4429
|
+
}
|
|
4430
|
+
if (result.kind === "route" && result.nextNodeId === "tool") {
|
|
4431
|
+
continue;
|
|
4432
|
+
}
|
|
4433
|
+
return {
|
|
4434
|
+
...result,
|
|
4435
|
+
events
|
|
4436
|
+
};
|
|
4437
|
+
}
|
|
4438
|
+
}
|
|
4439
|
+
async runNextPendingToolCall(state) {
|
|
4426
4440
|
const calls = state.local?.pendingToolCalls ?? [];
|
|
4427
4441
|
const signalRaw = state.local?.signal;
|
|
4428
4442
|
if (isAbortSignal(signalRaw) && signalRaw.aborted) {
|
|
@@ -4630,18 +4644,25 @@ var ToolNode = class {
|
|
|
4630
4644
|
rawArguments: context.call.function?.arguments,
|
|
4631
4645
|
parsedArguments: context.toolArgs
|
|
4632
4646
|
});
|
|
4647
|
+
const remainingCalls = context.calls.slice(1);
|
|
4633
4648
|
context.state.local = buildErrorLocalState({
|
|
4634
4649
|
local: context.local,
|
|
4635
|
-
remainingCalls
|
|
4650
|
+
remainingCalls,
|
|
4636
4651
|
conversationId: context.conversationId,
|
|
4637
4652
|
turnId: context.turnId,
|
|
4638
4653
|
runtimeEvents: context.bridge.getRuntimeEvents(),
|
|
4639
4654
|
nextProtocolErrorCount: fuse.nextCount
|
|
4640
4655
|
});
|
|
4641
|
-
if (fuse.shouldFuse) {
|
|
4656
|
+
if (fuse.shouldFuse && remainingCalls.length === 0) {
|
|
4642
4657
|
throw createToolProtocolFuseError(fuse.nextCount, context.exec.error);
|
|
4643
4658
|
}
|
|
4644
|
-
return {
|
|
4659
|
+
return {
|
|
4660
|
+
kind: "route",
|
|
4661
|
+
// 同一个 assistant.tool_calls batch 必须为每个 call 产出 tool_output。
|
|
4662
|
+
// 出错时也继续消费剩余 call,ToolNode.run 会在本节点内 drain 完 batch 再回 LLM。
|
|
4663
|
+
nextNodeId: remainingCalls.length > 0 ? "tool" : "llm",
|
|
4664
|
+
events: context.bridge.getRuntimeEvents()
|
|
4665
|
+
};
|
|
4645
4666
|
}
|
|
4646
4667
|
};
|
|
4647
4668
|
|
|
@@ -5378,18 +5399,18 @@ function createClassification(category, reason, suggestedDelay, extras) {
|
|
|
5378
5399
|
}
|
|
5379
5400
|
var ErrorClassifier = class {
|
|
5380
5401
|
static classify(error, context) {
|
|
5381
|
-
const
|
|
5402
|
+
const isRecord24 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
5382
5403
|
const baseMsg = (error.message || "").toLowerCase();
|
|
5383
5404
|
const causeMsg = (() => {
|
|
5384
5405
|
const cause = error.cause;
|
|
5385
5406
|
if (typeof cause === "string") return cause.toLowerCase();
|
|
5386
5407
|
if (cause instanceof Error) return (cause.message || "").toLowerCase();
|
|
5387
|
-
if (
|
|
5408
|
+
if (isRecord24(cause) && typeof cause["message"] === "string") return String(cause["message"]).toLowerCase();
|
|
5388
5409
|
return "";
|
|
5389
5410
|
})();
|
|
5390
5411
|
const causeCode = (() => {
|
|
5391
5412
|
const cause = error.cause;
|
|
5392
|
-
if (
|
|
5413
|
+
if (isRecord24(cause) && typeof cause["code"] === "string") return String(cause["code"]);
|
|
5393
5414
|
return "";
|
|
5394
5415
|
})();
|
|
5395
5416
|
const errorMessage = `${baseMsg} ${causeMsg}`.trim();
|
|
@@ -5881,6 +5902,9 @@ __export(llm_exports, {
|
|
|
5881
5902
|
LLMPolicyEngine: () => LLMPolicyEngine,
|
|
5882
5903
|
LlmCaller: () => LlmCaller,
|
|
5883
5904
|
ModelResolver: () => ModelResolver,
|
|
5905
|
+
appendStreamingProviderReasoningDetails: () => appendStreamingProviderReasoningDetails,
|
|
5906
|
+
compactProviderReasoningDetails: () => compactProviderReasoningDetails,
|
|
5907
|
+
compactReasoningDetailsInValue: () => compactReasoningDetailsInValue,
|
|
5884
5908
|
createDefaultTokenizerPort: () => createDefaultTokenizerPort,
|
|
5885
5909
|
defaultPolicyEngine: () => defaultPolicyEngine
|
|
5886
5910
|
});
|
|
@@ -6270,6 +6294,90 @@ function assertToolCallsHaveValidJsonArguments(toolCalls) {
|
|
|
6270
6294
|
}
|
|
6271
6295
|
}
|
|
6272
6296
|
|
|
6297
|
+
// src/runtime-kernel/llm/reasoning-details.ts
|
|
6298
|
+
var mergeableTextFields = ["reasoning_content"];
|
|
6299
|
+
function isRecord20(value) {
|
|
6300
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
6301
|
+
}
|
|
6302
|
+
function findMergeableTextField(detail) {
|
|
6303
|
+
if (!isRecord20(detail)) return void 0;
|
|
6304
|
+
if (typeof detail.provider !== "string") return void 0;
|
|
6305
|
+
if (typeof detail.type !== "string") return void 0;
|
|
6306
|
+
for (const field of mergeableTextFields) {
|
|
6307
|
+
if (typeof detail[field] === "string") {
|
|
6308
|
+
return field;
|
|
6309
|
+
}
|
|
6310
|
+
}
|
|
6311
|
+
return void 0;
|
|
6312
|
+
}
|
|
6313
|
+
function hasOnlyStableTextDetailFields(detail, textField) {
|
|
6314
|
+
const allowedKeys = /* @__PURE__ */ new Set(["provider", "type", textField]);
|
|
6315
|
+
return Object.keys(detail).every((key) => allowedKeys.has(key));
|
|
6316
|
+
}
|
|
6317
|
+
function canMergeTextDetails(previous, incoming) {
|
|
6318
|
+
if (!isRecord20(previous) || !isRecord20(incoming)) return false;
|
|
6319
|
+
const previousField = findMergeableTextField(previous);
|
|
6320
|
+
const incomingField = findMergeableTextField(incoming);
|
|
6321
|
+
if (!previousField || previousField !== incomingField) return false;
|
|
6322
|
+
return previous.provider === incoming.provider && previous.type === incoming.type && hasOnlyStableTextDetailFields(previous, previousField) && hasOnlyStableTextDetailFields(incoming, incomingField);
|
|
6323
|
+
}
|
|
6324
|
+
function mergeStreamingText(previous, incoming) {
|
|
6325
|
+
if (!previous) return incoming;
|
|
6326
|
+
if (!incoming) return previous;
|
|
6327
|
+
if (incoming.startsWith(previous)) {
|
|
6328
|
+
return incoming;
|
|
6329
|
+
}
|
|
6330
|
+
if (previous.endsWith(incoming)) {
|
|
6331
|
+
return previous;
|
|
6332
|
+
}
|
|
6333
|
+
return `${previous}${incoming}`;
|
|
6334
|
+
}
|
|
6335
|
+
function appendStreamingProviderReasoningDetails(existing, incoming) {
|
|
6336
|
+
const next = [...existing];
|
|
6337
|
+
for (const detail of incoming) {
|
|
6338
|
+
const previous = next[next.length - 1];
|
|
6339
|
+
if (canMergeTextDetails(previous, detail)) {
|
|
6340
|
+
const textField = findMergeableTextField(previous);
|
|
6341
|
+
if (textField && isRecord20(detail)) {
|
|
6342
|
+
const mergedText = mergeStreamingText(String(previous[textField]), String(detail[textField]));
|
|
6343
|
+
if (mergedText === previous[textField]) {
|
|
6344
|
+
continue;
|
|
6345
|
+
}
|
|
6346
|
+
next[next.length - 1] = {
|
|
6347
|
+
...previous,
|
|
6348
|
+
[textField]: mergedText
|
|
6349
|
+
};
|
|
6350
|
+
continue;
|
|
6351
|
+
}
|
|
6352
|
+
}
|
|
6353
|
+
next.push(detail);
|
|
6354
|
+
}
|
|
6355
|
+
return next;
|
|
6356
|
+
}
|
|
6357
|
+
function compactProviderReasoningDetails(reasoningDetails) {
|
|
6358
|
+
return appendStreamingProviderReasoningDetails([], reasoningDetails);
|
|
6359
|
+
}
|
|
6360
|
+
function compactReasoningDetailsInValue(value) {
|
|
6361
|
+
return compactValue(value);
|
|
6362
|
+
}
|
|
6363
|
+
function compactValue(value) {
|
|
6364
|
+
if (Array.isArray(value)) {
|
|
6365
|
+
return value.map((item) => compactValue(item));
|
|
6366
|
+
}
|
|
6367
|
+
if (!isRecord20(value)) {
|
|
6368
|
+
return value;
|
|
6369
|
+
}
|
|
6370
|
+
const compacted = {};
|
|
6371
|
+
for (const [key, childValue] of Object.entries(value)) {
|
|
6372
|
+
if (key === "reasoning_details" && Array.isArray(childValue)) {
|
|
6373
|
+
compacted[key] = compactProviderReasoningDetails(childValue);
|
|
6374
|
+
continue;
|
|
6375
|
+
}
|
|
6376
|
+
compacted[key] = compactValue(childValue);
|
|
6377
|
+
}
|
|
6378
|
+
return compacted;
|
|
6379
|
+
}
|
|
6380
|
+
|
|
6273
6381
|
// src/runtime-kernel/llm/streaming-adapter.ts
|
|
6274
6382
|
async function callLlmStream(params) {
|
|
6275
6383
|
const {
|
|
@@ -6282,7 +6390,7 @@ async function callLlmStream(params) {
|
|
|
6282
6390
|
} = params;
|
|
6283
6391
|
let fullResponse = "";
|
|
6284
6392
|
let streamError = null;
|
|
6285
|
-
|
|
6393
|
+
let reasoningDetails = [];
|
|
6286
6394
|
const streamAnswerId = generateMessageId();
|
|
6287
6395
|
let streamChunkSeq = 0;
|
|
6288
6396
|
let capturedUsage = void 0;
|
|
@@ -6352,13 +6460,21 @@ async function callLlmStream(params) {
|
|
|
6352
6460
|
const reasoning = isRecord19(chunk) ? chunk["reasoning_details"] : void 0;
|
|
6353
6461
|
if (reasoning !== void 0) {
|
|
6354
6462
|
const newReasoningDetails = Array.isArray(reasoning) ? reasoning : [reasoning];
|
|
6355
|
-
reasoningDetails
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6463
|
+
const previousReasoningDetails = reasoningDetails;
|
|
6464
|
+
const previousLength = previousReasoningDetails.length;
|
|
6465
|
+
const compactedReasoningDetails = appendStreamingProviderReasoningDetails(reasoningDetails, newReasoningDetails);
|
|
6466
|
+
reasoningDetails = compactedReasoningDetails;
|
|
6467
|
+
const previousLastChanged = previousLength > 0 && compactedReasoningDetails[previousLength - 1] !== previousReasoningDetails[previousLength - 1];
|
|
6468
|
+
const emitFromIndex = previousLastChanged ? previousLength - 1 : previousLength;
|
|
6469
|
+
const emittedReasoningDetails = compactedReasoningDetails.slice(Math.max(0, emitFromIndex));
|
|
6470
|
+
if (emittedReasoningDetails.length > 0) {
|
|
6471
|
+
eventHandler({
|
|
6472
|
+
type: "provider_sidecar",
|
|
6473
|
+
id: generateMessageId(),
|
|
6474
|
+
timestamp: Date.now(),
|
|
6475
|
+
reasoning_details: emittedReasoningDetails
|
|
6476
|
+
});
|
|
6477
|
+
}
|
|
6362
6478
|
}
|
|
6363
6479
|
if (chunk.tool_calls) {
|
|
6364
6480
|
emitThoughtComplete(thoughtSegmenter.onBoundary());
|
|
@@ -6784,7 +6900,6 @@ var DefaultTokenizerPort = class {
|
|
|
6784
6900
|
constructor(config = {}) {
|
|
6785
6901
|
this.config = config;
|
|
6786
6902
|
}
|
|
6787
|
-
config;
|
|
6788
6903
|
estimateText(text, _modelId) {
|
|
6789
6904
|
return TokenCalculator.estimateTokens(text, {
|
|
6790
6905
|
encoding: this.config.encoding,
|
|
@@ -6926,8 +7041,6 @@ var FinalAnswerCollector = class {
|
|
|
6926
7041
|
this.conversationId = conversationId;
|
|
6927
7042
|
this.turnId = turnId;
|
|
6928
7043
|
}
|
|
6929
|
-
conversationId;
|
|
6930
|
-
turnId;
|
|
6931
7044
|
answerId;
|
|
6932
7045
|
chunks = [];
|
|
6933
7046
|
chunkCount = 0;
|
|
@@ -6975,7 +7088,7 @@ var FinalAnswerCollector = class {
|
|
|
6975
7088
|
};
|
|
6976
7089
|
|
|
6977
7090
|
// src/runtime-kernel/child-runs/childRunTraceSink.ts
|
|
6978
|
-
function
|
|
7091
|
+
function isRecord21(v) {
|
|
6979
7092
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
6980
7093
|
}
|
|
6981
7094
|
function getString2(obj, key) {
|
|
@@ -7008,7 +7121,7 @@ function createChildRunTraceSink(params) {
|
|
|
7008
7121
|
const { publisher, conversationId, turnId } = params;
|
|
7009
7122
|
const finalAnswerCollector = new FinalAnswerCollector(conversationId, turnId);
|
|
7010
7123
|
const sink = (evt) => {
|
|
7011
|
-
if (!
|
|
7124
|
+
if (!isRecord21(evt)) {
|
|
7012
7125
|
return [];
|
|
7013
7126
|
}
|
|
7014
7127
|
const type = getString2(evt, "type");
|
|
@@ -7677,7 +7790,7 @@ function runRecordToMeta(record) {
|
|
|
7677
7790
|
errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0
|
|
7678
7791
|
};
|
|
7679
7792
|
}
|
|
7680
|
-
function
|
|
7793
|
+
function isRecord22(value) {
|
|
7681
7794
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7682
7795
|
}
|
|
7683
7796
|
function readStringField(record, key) {
|
|
@@ -7698,7 +7811,7 @@ function getRunIdFromMetadata(event) {
|
|
|
7698
7811
|
return snakeCaseRunId;
|
|
7699
7812
|
}
|
|
7700
7813
|
const runContext = metadata["run_context"];
|
|
7701
|
-
if (
|
|
7814
|
+
if (isRecord22(runContext)) {
|
|
7702
7815
|
return readStringField(runContext, "runId") ?? readStringField(runContext, "run_id");
|
|
7703
7816
|
}
|
|
7704
7817
|
return void 0;
|
|
@@ -7916,7 +8029,7 @@ function runMetaFromRecord(record) {
|
|
|
7916
8029
|
}
|
|
7917
8030
|
|
|
7918
8031
|
// src/runtime-kernel/run-supervisor/runSupervisor.ts
|
|
7919
|
-
function
|
|
8032
|
+
function isRecord23(value) {
|
|
7920
8033
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7921
8034
|
}
|
|
7922
8035
|
function readStringField2(record, key) {
|
|
@@ -7933,7 +8046,7 @@ function readRunIdFromRuntimeEvent(event) {
|
|
|
7933
8046
|
return directRunId;
|
|
7934
8047
|
}
|
|
7935
8048
|
const runContext = metadata["run_context"];
|
|
7936
|
-
if (!
|
|
8049
|
+
if (!isRecord23(runContext)) {
|
|
7937
8050
|
return void 0;
|
|
7938
8051
|
}
|
|
7939
8052
|
return readStringField2(runContext, "runId") ?? readStringField2(runContext, "run_id");
|
|
@@ -7945,7 +8058,7 @@ function readAwaitingUserReason(event) {
|
|
|
7945
8058
|
if (typeof event.prompt === "string" && event.prompt.trim().length > 0) {
|
|
7946
8059
|
return event.prompt;
|
|
7947
8060
|
}
|
|
7948
|
-
if (
|
|
8061
|
+
if (isRecord23(event.form)) {
|
|
7949
8062
|
const prompt = readStringField2(event.form, "prompt");
|
|
7950
8063
|
if (prompt && prompt.trim().length > 0) {
|
|
7951
8064
|
return prompt;
|
|
@@ -8594,11 +8707,14 @@ exports.ToolNode = ToolNode;
|
|
|
8594
8707
|
exports.UserNode = UserNode;
|
|
8595
8708
|
exports.WaitUserNode = WaitUserNode;
|
|
8596
8709
|
exports.agentHasToolTrigger = agentHasToolTrigger;
|
|
8710
|
+
exports.appendStreamingProviderReasoningDetails = appendStreamingProviderReasoningDetails;
|
|
8597
8711
|
exports.applySystemReminders = applySystemReminders;
|
|
8598
8712
|
exports.audit = audit_exports;
|
|
8599
8713
|
exports.budgetWarningTrigger = budgetWarningTrigger;
|
|
8600
8714
|
exports.childRunTrace = child_run_trace_exports;
|
|
8601
8715
|
exports.childRuns = child_runs_exports;
|
|
8716
|
+
exports.compactProviderReasoningDetails = compactProviderReasoningDetails;
|
|
8717
|
+
exports.compactReasoningDetailsInValue = compactReasoningDetailsInValue;
|
|
8602
8718
|
exports.computeToolIdempotencyKey = computeToolIdempotencyKey;
|
|
8603
8719
|
exports.consoleAudit = consoleAudit;
|
|
8604
8720
|
exports.contextBudgetWarningTemplate = contextBudgetWarningTemplate;
|