@kortyx/hooks 0.34.1 → 0.34.2
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 +6 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +66 -13
- package/dist/index.js.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/internal.js.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.34.2](https://github.com/kortyx-io/kortyx/compare/hooks-v0.34.1...hooks-v0.34.2) (2026-10-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **evals:** preserve diagnostics and separate postcondition failures ([#337](https://github.com/kortyx-io/kortyx/issues/337)) ([d4fce4e](https://github.com/kortyx-io/kortyx/commit/d4fce4e670971d3b755835fc681c8125f67a9c70))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @kortyx/core bumped to 0.14.0
|
|
16
|
+
* @kortyx/providers bumped to 0.9.3
|
|
17
|
+
* @kortyx/telemetry-contracts bumped to 0.17.2
|
|
18
|
+
* @kortyx/prompts bumped to 0.2.1
|
|
19
|
+
* @kortyx/usage-telemetry bumped to 0.3.0
|
|
20
|
+
|
|
3
21
|
## [0.34.1](https://github.com/kortyx-io/kortyx/compare/hooks-v0.34.0...hooks-v0.34.1) (2026-10-13)
|
|
4
22
|
|
|
5
23
|
|
package/README.md
CHANGED
|
@@ -137,3 +137,9 @@ Await groups sequentially within one node; children may contain nested groups.
|
|
|
137
137
|
Native `Promise.all` calls and parallel graph edges remain unsupported.
|
|
138
138
|
|
|
139
139
|
See [the execution and replay contract](../../docs/design-specs/child-workflows.md).
|
|
140
|
+
|
|
141
|
+
When a required `outputs.return` is missing, `useReason` raises the typed
|
|
142
|
+
`REASON_TERMINAL_OUTPUT_MISSING` validation error. Optional
|
|
143
|
+
`toolExecution: { maxSteps: 4, missingReturnCorrections: 1 }` allows an output-only
|
|
144
|
+
correction within the existing step budget, without replaying business tools.
|
|
145
|
+
The correction budget defaults to zero.
|
package/dist/index.d.ts
CHANGED
|
@@ -262,6 +262,8 @@ type UseReasonInterruptConfig<TRequest extends InterruptInput = InterruptInput,
|
|
|
262
262
|
schemaVersion?: string | undefined;
|
|
263
263
|
};
|
|
264
264
|
type UseReasonToolExecution = {
|
|
265
|
+
/** Extra model corrections for a missing terminal return; defaults to zero and shares maxSteps. Completed calls are not replayed. */
|
|
266
|
+
missingReturnCorrections?: number | undefined;
|
|
265
267
|
/** Model-pass budget, including output generation and correction across resume. */
|
|
266
268
|
maxSteps?: number | undefined;
|
|
267
269
|
approval?: boolean | Record<string, boolean> | undefined;
|
package/dist/index.js
CHANGED
|
@@ -245,7 +245,7 @@ var import_node = require("@kortyx/usage-telemetry/node");
|
|
|
245
245
|
// package.json
|
|
246
246
|
var package_default = {
|
|
247
247
|
name: "@kortyx/hooks",
|
|
248
|
-
version: "0.34.
|
|
248
|
+
version: "0.34.2",
|
|
249
249
|
private: false,
|
|
250
250
|
description: "Lifecycle hooks and extension points for Kortyx.",
|
|
251
251
|
keywords: [
|
|
@@ -3167,6 +3167,18 @@ var runReasonToolLoop = async (args) => {
|
|
|
3167
3167
|
let finalizing = checkpoint?.finalizing ?? false;
|
|
3168
3168
|
let completed = false;
|
|
3169
3169
|
const maxSteps = Math.max(1, useReasonArgs.toolExecution?.maxSteps ?? 3);
|
|
3170
|
+
const missingReturnCorrections = useReasonArgs.toolExecution?.missingReturnCorrections ?? 0;
|
|
3171
|
+
if (!Number.isSafeInteger(missingReturnCorrections) || missingReturnCorrections < 0)
|
|
3172
|
+
throw new import_errors6.KortyxError(
|
|
3173
|
+
"INVALID_REASON_CORRECTION_POLICY",
|
|
3174
|
+
"Invalid missing return correction budget.",
|
|
3175
|
+
{
|
|
3176
|
+
category: "configuration",
|
|
3177
|
+
retryable: false,
|
|
3178
|
+
safeMessage: "toolExecution.missingReturnCorrections must be a nonnegative safe integer."
|
|
3179
|
+
}
|
|
3180
|
+
);
|
|
3181
|
+
let missingReturnAttempts = checkpoint?.missingReturnAttempts ?? 0;
|
|
3170
3182
|
const messages = checkpoint?.messages ?? createInitialMessages({
|
|
3171
3183
|
messages: useReasonArgs.messages,
|
|
3172
3184
|
inputOverride: Boolean(useReasonArgs.outputSchema),
|
|
@@ -3218,13 +3230,17 @@ var runReasonToolLoop = async (args) => {
|
|
|
3218
3230
|
let outputContractCorrections = checkpoint?.outputContractCorrections ?? 0;
|
|
3219
3231
|
const correctionExhausted = () => {
|
|
3220
3232
|
const message = `useReason could not complete output-contract correction within toolExecution.maxSteps (${maxSteps}). Select exactly one terminal return contract; multiple emit contracts are allowed. Increase maxSteps to allow correction and output generation.`;
|
|
3221
|
-
return new import_errors6.
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3233
|
+
return new import_errors6.KortyxError(
|
|
3234
|
+
"REASON_OUTPUT_CONTRACT_CORRECTION_EXHAUSTED",
|
|
3235
|
+
message,
|
|
3236
|
+
{
|
|
3237
|
+
category: "validation",
|
|
3238
|
+
operation: "useReason",
|
|
3239
|
+
safeMessage: message,
|
|
3240
|
+
retryable: false,
|
|
3241
|
+
details: { maxSteps, outputContractCorrections }
|
|
3242
|
+
}
|
|
3243
|
+
);
|
|
3228
3244
|
};
|
|
3229
3245
|
const resolvedInterrupts = checkpoint?.resolvedInterrupts ?? [];
|
|
3230
3246
|
for (const request of resolvedInterrupts) ctx.node.replayInterrupt?.(request);
|
|
@@ -3243,6 +3259,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
3243
3259
|
interruptHistory,
|
|
3244
3260
|
emissions,
|
|
3245
3261
|
outputContractCorrections,
|
|
3262
|
+
missingReturnAttempts,
|
|
3246
3263
|
...returned ? { returned } : {},
|
|
3247
3264
|
finalizing,
|
|
3248
3265
|
...pending ? { pending } : {},
|
|
@@ -3278,7 +3295,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
3278
3295
|
const step = pending ?? await reasonEngine(
|
|
3279
3296
|
{
|
|
3280
3297
|
...useReasonArgs,
|
|
3281
|
-
tools: finalizing ? [] : toolDefinitions,
|
|
3298
|
+
tools: finalizing ? [] : missingReturnAttempts > 0 ? outputDefinitions : toolDefinitions,
|
|
3282
3299
|
...separateOutput && !finalizing ? { responseFormat: { type: "text" } } : {},
|
|
3283
3300
|
messages,
|
|
3284
3301
|
emit: false,
|
|
@@ -3309,6 +3326,16 @@ var runReasonToolLoop = async (args) => {
|
|
|
3309
3326
|
);
|
|
3310
3327
|
aggregatedWarnings = mergeWarnings(aggregatedWarnings, step.warnings);
|
|
3311
3328
|
const toolCalls = step.toolCalls ?? [];
|
|
3329
|
+
if (missingReturnAttempts > 0 && toolCalls.some((call) => !outputByToolName.has(call.name)))
|
|
3330
|
+
throw new import_errors6.KortyxError(
|
|
3331
|
+
"REASON_OUTPUT_CORRECTION_TOOL_DISALLOWED",
|
|
3332
|
+
"A return correction requested a non-output tool.",
|
|
3333
|
+
{
|
|
3334
|
+
category: "validation",
|
|
3335
|
+
retryable: false,
|
|
3336
|
+
safeMessage: "A terminal output correction cannot rerun tools or human-input requests."
|
|
3337
|
+
}
|
|
3338
|
+
);
|
|
3312
3339
|
const ids = /* @__PURE__ */ new Set();
|
|
3313
3340
|
for (const call of toolCalls) {
|
|
3314
3341
|
if (!call.id || ids.has(call.id) || !reused && knownToolCallIds.has(call.id))
|
|
@@ -3329,10 +3356,32 @@ var runReasonToolLoop = async (args) => {
|
|
|
3329
3356
|
});
|
|
3330
3357
|
if (!reused) for (const call of toolCalls) knownToolCallIds.add(call.id);
|
|
3331
3358
|
if (toolCalls.length === 0) {
|
|
3332
|
-
if (Object.keys(useReasonArgs.outputs?.return ?? {}).length > 0 && !returned)
|
|
3333
|
-
|
|
3334
|
-
|
|
3359
|
+
if (Object.keys(useReasonArgs.outputs?.return ?? {}).length > 0 && !returned) {
|
|
3360
|
+
if (missingReturnAttempts < missingReturnCorrections) {
|
|
3361
|
+
messages.push({ role: "assistant", content: step.text });
|
|
3362
|
+
messages.push({
|
|
3363
|
+
role: "user",
|
|
3364
|
+
content: "MISSING_TERMINAL_OUTPUT: No terminal output was published. Select exactly one configured return contract using the completed tool and human-input results. Do not repeat completed calls."
|
|
3365
|
+
});
|
|
3366
|
+
missingReturnAttempts += 1;
|
|
3367
|
+
outputContractCorrections += 1;
|
|
3368
|
+
pending = void 0;
|
|
3369
|
+
pendingStepIndex = void 0;
|
|
3370
|
+
save();
|
|
3371
|
+
continue;
|
|
3372
|
+
}
|
|
3373
|
+
throw new import_errors6.KortyxError(
|
|
3374
|
+
"REASON_TERMINAL_OUTPUT_MISSING",
|
|
3375
|
+
"useReason outputs.return requires one terminal output contract call.",
|
|
3376
|
+
{
|
|
3377
|
+
category: "validation",
|
|
3378
|
+
operation: "useReason",
|
|
3379
|
+
retryable: false,
|
|
3380
|
+
safeMessage: "useReason outputs.return requires one terminal output contract call.",
|
|
3381
|
+
details: { missingReturnAttempts }
|
|
3382
|
+
}
|
|
3335
3383
|
);
|
|
3384
|
+
}
|
|
3336
3385
|
if (interruptConfig?.mode === "required" && interruptHistory.length === 0)
|
|
3337
3386
|
throw new Error(
|
|
3338
3387
|
"useReason interrupts.mode is required, but the model returned a final answer without requesting human input."
|
|
@@ -3847,11 +3896,15 @@ var runReasonToolLoop = async (args) => {
|
|
|
3847
3896
|
toolResults.push(result2);
|
|
3848
3897
|
allToolResults.push(result2);
|
|
3849
3898
|
if (shouldEmitTool) {
|
|
3899
|
+
const diagnosticId = steps[stepIndex]?.toolObservations?.slice().reverse().find(
|
|
3900
|
+
(observation) => observation.toolCallId === `${opId}:${toolCall.id}`
|
|
3901
|
+
)?.diagnosticId;
|
|
3850
3902
|
emitToolEvent("tool-call-error", {
|
|
3851
3903
|
tool: tool.name,
|
|
3852
3904
|
toolCallId: toolCall.id,
|
|
3853
3905
|
message: result2.content,
|
|
3854
|
-
failure: result2.failure
|
|
3906
|
+
failure: result2.failure,
|
|
3907
|
+
...diagnosticId ? { diagnosticId } : {}
|
|
3855
3908
|
});
|
|
3856
3909
|
}
|
|
3857
3910
|
}
|