@kortyx/agent 0.26.2 → 0.27.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 +15 -0
- package/dist/{browser-wjeg_MwV.d.ts → browser-EVWVR9BO.d.ts} +1 -0
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +1 -0
- package/dist/browser.js.map +1 -1
- package/dist/index.d.ts +87 -17
- package/dist/index.js +435 -207
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -61,7 +61,7 @@ var require_internal = __commonJS({
|
|
|
61
61
|
withSafeTraceSpan: () => withSafeTraceSpan2
|
|
62
62
|
});
|
|
63
63
|
module2.exports = __toCommonJS2(internal_exports);
|
|
64
|
-
var
|
|
64
|
+
var import_errors8 = require("@kortyx/core/errors");
|
|
65
65
|
var MAX_STACK_LENGTH = 32768;
|
|
66
66
|
var MAX_CAUSE_DEPTH = 4;
|
|
67
67
|
var projectDetails = (value, depth, seen) => {
|
|
@@ -71,16 +71,16 @@ var require_internal = __commonJS({
|
|
|
71
71
|
return { type: "Error", message: "Circular error cause." };
|
|
72
72
|
seen.add(objectValue);
|
|
73
73
|
}
|
|
74
|
-
const name = (0,
|
|
75
|
-
const message = (0,
|
|
76
|
-
const stack = (0,
|
|
74
|
+
const name = (0, import_errors8.errorProperty)(value, "name") ?? (value instanceof Error ? value.name : void 0);
|
|
75
|
+
const message = (0, import_errors8.errorProperty)(value, "message");
|
|
76
|
+
const stack = (0, import_errors8.errorProperty)(value, "stack") ?? (value instanceof Error ? (() => {
|
|
77
77
|
try {
|
|
78
78
|
return value.stack;
|
|
79
79
|
} catch {
|
|
80
80
|
return void 0;
|
|
81
81
|
}
|
|
82
82
|
})() : void 0);
|
|
83
|
-
const cause = depth < MAX_CAUSE_DEPTH ? (0,
|
|
83
|
+
const cause = depth < MAX_CAUSE_DEPTH ? (0, import_errors8.errorProperty)(value, "cause") : null;
|
|
84
84
|
return {
|
|
85
85
|
type: typeof name === "string" ? name.slice(0, 256) : "Error",
|
|
86
86
|
message: (typeof value === "string" ? value : typeof message === "string" ? message : "Execution reported a fault.").slice(0, 8192),
|
|
@@ -789,14 +789,14 @@ var require_dist = __commonJS({
|
|
|
789
789
|
workflowState: args.workflowState
|
|
790
790
|
}
|
|
791
791
|
});
|
|
792
|
-
var
|
|
792
|
+
var import_errors8 = require("@kortyx/core/errors");
|
|
793
793
|
var parseWithSchema = (schema, value, label) => {
|
|
794
794
|
if (!schema) return value;
|
|
795
795
|
const parsed = schema.safeParse(value);
|
|
796
796
|
if (parsed.success) return parsed.data;
|
|
797
797
|
const parsedError = "error" in parsed && parsed.error ? parsed.error : void 0;
|
|
798
798
|
const reason = typeof parsedError?.message === "string" && parsedError.message.length > 0 ? parsedError.message : "invalid payload";
|
|
799
|
-
throw new
|
|
799
|
+
throw new import_errors8.ValidationError(
|
|
800
800
|
label === "useReason output" ? "MODEL_OUTPUT_SCHEMA" : "SCHEMA_VALIDATION",
|
|
801
801
|
`${label} validation failed: ${reason}`,
|
|
802
802
|
parsedError
|
|
@@ -3950,7 +3950,7 @@ ${tryStringify2(args.response)}`
|
|
|
3950
3950
|
return [getValue(), setValue];
|
|
3951
3951
|
}
|
|
3952
3952
|
var import_core7 = require("@kortyx/core");
|
|
3953
|
-
var
|
|
3953
|
+
var import_errors72 = require("@kortyx/core/errors");
|
|
3954
3954
|
var ParallelChildWaiting = class extends Error {
|
|
3955
3955
|
name = "ParallelChildWaiting";
|
|
3956
3956
|
};
|
|
@@ -3964,14 +3964,14 @@ ${tryStringify2(args.response)}`
|
|
|
3964
3964
|
);
|
|
3965
3965
|
this.results = results;
|
|
3966
3966
|
this.name = "ParallelError";
|
|
3967
|
-
this.failure = (0,
|
|
3967
|
+
this.failure = (0, import_errors72.serializeFailure)({
|
|
3968
3968
|
version: 1,
|
|
3969
3969
|
code: this.code,
|
|
3970
3970
|
category: "workflow",
|
|
3971
3971
|
message: this.message,
|
|
3972
3972
|
retryable: null,
|
|
3973
3973
|
results: results.map(
|
|
3974
|
-
(result) => result.status === "fulfilled" ? { status: "fulfilled" } : { status: "rejected", failure: (0,
|
|
3974
|
+
(result) => result.status === "fulfilled" ? { status: "fulfilled" } : { status: "rejected", failure: (0, import_errors72.serializeFailure)(result.reason) }
|
|
3975
3975
|
)
|
|
3976
3976
|
});
|
|
3977
3977
|
}
|
|
@@ -3979,7 +3979,7 @@ ${tryStringify2(args.response)}`
|
|
|
3979
3979
|
code = "PARALLEL_FAILED";
|
|
3980
3980
|
failure;
|
|
3981
3981
|
toJSON() {
|
|
3982
|
-
return (0,
|
|
3982
|
+
return (0, import_errors72.serializeFailure)(this);
|
|
3983
3983
|
}
|
|
3984
3984
|
};
|
|
3985
3985
|
function registerWorkflowTask(id) {
|
|
@@ -4124,11 +4124,11 @@ ${tryStringify2(args.response)}`
|
|
|
4124
4124
|
}
|
|
4125
4125
|
var import_node_crypto6 = require("crypto");
|
|
4126
4126
|
var import_core8 = require("@kortyx/core");
|
|
4127
|
-
var
|
|
4128
|
-
var WorkflowCallError = class extends
|
|
4127
|
+
var import_errors82 = require("@kortyx/core/errors");
|
|
4128
|
+
var WorkflowCallError = class extends import_errors82.KortyxError {
|
|
4129
4129
|
constructor(workflow, message, cause, failure) {
|
|
4130
|
-
const detail = (0,
|
|
4131
|
-
failure ?? cause ?? new
|
|
4130
|
+
const detail = (0, import_errors82.serializeFailure)(
|
|
4131
|
+
failure ?? cause ?? new import_errors82.WorkflowContractError(message)
|
|
4132
4132
|
);
|
|
4133
4133
|
super(detail.code, `Workflow '${workflow}': ${message}`, {
|
|
4134
4134
|
...detail,
|
|
@@ -4149,12 +4149,12 @@ ${tryStringify2(args.response)}`
|
|
|
4149
4149
|
if (v === null || typeof v === "string" || typeof v === "boolean") return v;
|
|
4150
4150
|
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
4151
4151
|
if (typeof v !== "object" || !v || seen.has(v)) {
|
|
4152
|
-
throw new
|
|
4152
|
+
throw new import_errors82.WorkflowContractError(
|
|
4153
4153
|
"Workflow input and output must be JSON serializable."
|
|
4154
4154
|
);
|
|
4155
4155
|
}
|
|
4156
4156
|
if (!Array.isArray(v) && Object.getPrototypeOf(v) !== Object.prototype) {
|
|
4157
|
-
throw new
|
|
4157
|
+
throw new import_errors82.WorkflowContractError(
|
|
4158
4158
|
"Workflow input and output must contain plain JSON objects."
|
|
4159
4159
|
);
|
|
4160
4160
|
}
|
|
@@ -4175,7 +4175,7 @@ ${tryStringify2(args.response)}`
|
|
|
4175
4175
|
useWorkflow: (args) => {
|
|
4176
4176
|
const workflow = workflows[args.workflow];
|
|
4177
4177
|
if (!workflow || workflow.id !== args.workflow)
|
|
4178
|
-
throw new
|
|
4178
|
+
throw new import_errors82.WorkflowContractError(
|
|
4179
4179
|
"Workflow registry keys must match definition ids."
|
|
4180
4180
|
);
|
|
4181
4181
|
return useWorkflow({ ...args, workflow });
|
|
@@ -4201,23 +4201,23 @@ ${tryStringify2(args.response)}`
|
|
|
4201
4201
|
(0, import_core8.throwIfExecutionAborted)(ctx.node.abortSignal);
|
|
4202
4202
|
const service = ctx.node.callWorkflow;
|
|
4203
4203
|
if (!service)
|
|
4204
|
-
throw new
|
|
4204
|
+
throw new import_errors82.WorkflowContractError(
|
|
4205
4205
|
"useWorkflow requires an agent workflow registry."
|
|
4206
4206
|
);
|
|
4207
4207
|
if (!args.id.trim())
|
|
4208
|
-
throw new
|
|
4208
|
+
throw new import_errors82.WorkflowContractError(
|
|
4209
4209
|
"useWorkflow requires a stable, nonempty id."
|
|
4210
4210
|
);
|
|
4211
4211
|
if (ctx.workflowCallActive && !task.group)
|
|
4212
|
-
throw new
|
|
4212
|
+
throw new import_errors82.WorkflowContractError(
|
|
4213
4213
|
"Concurrent workflow calls require parallel([...]); otherwise await each call."
|
|
4214
4214
|
);
|
|
4215
4215
|
if (ctx.workflowCallIds.has(args.id))
|
|
4216
|
-
throw new
|
|
4216
|
+
throw new import_errors82.WorkflowContractError(
|
|
4217
4217
|
`Duplicate workflow call id '${args.id}' in one node activation.`
|
|
4218
4218
|
);
|
|
4219
4219
|
if (ctx.workflowCallIds.size >= 64)
|
|
4220
|
-
throw new
|
|
4220
|
+
throw new import_errors82.WorkflowContractError(
|
|
4221
4221
|
"A node may call at most 64 child workflows per activation."
|
|
4222
4222
|
);
|
|
4223
4223
|
ctx.workflowCallIds.add(args.id);
|
|
@@ -4298,7 +4298,7 @@ ${tryStringify2(args.response)}`
|
|
|
4298
4298
|
workflow,
|
|
4299
4299
|
record.error ?? "child failed",
|
|
4300
4300
|
void 0,
|
|
4301
|
-
record.failure ?? (0,
|
|
4301
|
+
record.failure ?? (0, import_errors82.serializeFailure)(void 0)
|
|
4302
4302
|
);
|
|
4303
4303
|
if (task.group && record.status === "interrupted" && record.interrupts.at(-1)?.response === void 0)
|
|
4304
4304
|
throw new ParallelChildWaiting();
|
|
@@ -4334,7 +4334,7 @@ ${tryStringify2(args.response)}`
|
|
|
4334
4334
|
throw error;
|
|
4335
4335
|
}
|
|
4336
4336
|
record.status = "failed";
|
|
4337
|
-
record.failure = (0,
|
|
4337
|
+
record.failure = (0, import_errors82.serializeFailure)(error);
|
|
4338
4338
|
record.error = record.failure.message;
|
|
4339
4339
|
report("failed", { error: "Child workflow failed" });
|
|
4340
4340
|
throw new WorkflowCallError(
|
|
@@ -4395,6 +4395,7 @@ ${tryStringify2(args.response)}`
|
|
|
4395
4395
|
// src/index.ts
|
|
4396
4396
|
var index_exports = {};
|
|
4397
4397
|
__export(index_exports, {
|
|
4398
|
+
ChatLifecycleHookError: () => ChatLifecycleHookError,
|
|
4398
4399
|
ExecutionRequestError: () => ExecutionRequestError,
|
|
4399
4400
|
createAgent: () => createAgent,
|
|
4400
4401
|
createChatRouteHandler: () => createChatRouteHandler,
|
|
@@ -4417,183 +4418,29 @@ __export(index_exports, {
|
|
|
4417
4418
|
module.exports = __toCommonJS(index_exports);
|
|
4418
4419
|
|
|
4419
4420
|
// src/adapters/http.ts
|
|
4421
|
+
var import_errors5 = require("@kortyx/core/errors");
|
|
4422
|
+
var import_stream2 = require("@kortyx/stream");
|
|
4423
|
+
var import_zod2 = require("zod");
|
|
4424
|
+
|
|
4425
|
+
// src/chat/lifecycle.ts
|
|
4420
4426
|
var import_errors = require("@kortyx/core/errors");
|
|
4421
|
-
var
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
id: import_zod.z.string().optional(),
|
|
4428
|
-
timestamp: import_zod.z.number().refine(Number.isFinite).optional()
|
|
4429
|
-
}).strict();
|
|
4430
|
-
var chatRequestBodySchema = import_zod.z.looseObject({
|
|
4431
|
-
sessionId: import_zod.z.string().optional(),
|
|
4432
|
-
workflowId: import_zod.z.string().optional(),
|
|
4433
|
-
stream: import_zod.z.boolean().optional(),
|
|
4434
|
-
context: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional(),
|
|
4435
|
-
messages: import_zod.z.array(chatMessageSchema)
|
|
4436
|
-
});
|
|
4437
|
-
var checkpointRequestBodySchema = import_zod.z.discriminatedUnion("action", [
|
|
4438
|
-
import_zod.z.object({
|
|
4439
|
-
action: import_zod.z.literal("list"),
|
|
4440
|
-
sessionId: import_zod.z.string().min(1)
|
|
4441
|
-
}).strict(),
|
|
4442
|
-
import_zod.z.object({
|
|
4443
|
-
action: import_zod.z.literal("get"),
|
|
4444
|
-
checkpointId: import_zod.z.string().min(1)
|
|
4445
|
-
}).strict(),
|
|
4446
|
-
import_zod.z.object({
|
|
4447
|
-
action: import_zod.z.literal("rollback"),
|
|
4448
|
-
checkpointId: import_zod.z.string().min(1)
|
|
4449
|
-
}).strict(),
|
|
4450
|
-
import_zod.z.object({
|
|
4451
|
-
action: import_zod.z.literal("fork"),
|
|
4452
|
-
checkpointId: import_zod.z.string().min(1),
|
|
4453
|
-
newSessionId: import_zod.z.string().min(1).optional()
|
|
4454
|
-
}).strict()
|
|
4455
|
-
]);
|
|
4456
|
-
async function readRequestJson(request) {
|
|
4457
|
-
try {
|
|
4458
|
-
const value = await request.json();
|
|
4459
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
4460
|
-
throw new Error("Expected a JSON object.");
|
|
4461
|
-
return value;
|
|
4462
|
-
} catch (cause) {
|
|
4463
|
-
throw new import_errors.KortyxError(
|
|
4464
|
-
"INVALID_REQUEST",
|
|
4465
|
-
"Request body is not valid JSON.",
|
|
4427
|
+
var ChatLifecycleHookError = class extends import_errors.KortyxError {
|
|
4428
|
+
phase;
|
|
4429
|
+
constructor(phase, cause) {
|
|
4430
|
+
super(
|
|
4431
|
+
"CHAT_LIFECYCLE_HOOK_FAILED",
|
|
4432
|
+
`Chat lifecycle hook failed: ${phase}`,
|
|
4466
4433
|
{
|
|
4467
|
-
category: "
|
|
4468
|
-
retryable:
|
|
4469
|
-
safeMessage: "
|
|
4434
|
+
category: "persistence",
|
|
4435
|
+
retryable: null,
|
|
4436
|
+
safeMessage: "Chat state could not be saved.",
|
|
4470
4437
|
cause
|
|
4471
4438
|
}
|
|
4472
4439
|
);
|
|
4440
|
+
this.name = "ChatLifecycleHookError";
|
|
4441
|
+
this.phase = phase;
|
|
4473
4442
|
}
|
|
4474
|
-
}
|
|
4475
|
-
function createFailureResponse(error, status) {
|
|
4476
|
-
const failure = (0, import_errors.serializeFailure)(error);
|
|
4477
|
-
return Response.json(
|
|
4478
|
-
{ error: failure.message, failure },
|
|
4479
|
-
{ status: status ?? (0, import_errors.failureHttpStatus)(failure) }
|
|
4480
|
-
);
|
|
4481
|
-
}
|
|
4482
|
-
function parseChatRequestBody(value) {
|
|
4483
|
-
const parsed = chatRequestBodySchema.safeParse(value);
|
|
4484
|
-
if (!parsed.success) {
|
|
4485
|
-
const [firstIssue] = parsed.error.issues;
|
|
4486
|
-
throw new import_errors.KortyxError("INVALID_REQUEST", firstIssue.message, {
|
|
4487
|
-
category: "request",
|
|
4488
|
-
retryable: false,
|
|
4489
|
-
safeMessage: "The request body is invalid."
|
|
4490
|
-
});
|
|
4491
|
-
}
|
|
4492
|
-
const sessionId = parsed.data.sessionId?.trim();
|
|
4493
|
-
const workflowId = parsed.data.workflowId?.trim();
|
|
4494
|
-
return {
|
|
4495
|
-
...sessionId ? { sessionId } : {},
|
|
4496
|
-
...workflowId ? { workflowId } : {},
|
|
4497
|
-
...typeof parsed.data.stream === "boolean" ? { stream: parsed.data.stream } : {},
|
|
4498
|
-
...parsed.data.context ? { context: parsed.data.context } : {},
|
|
4499
|
-
messages: parsed.data.messages
|
|
4500
|
-
};
|
|
4501
|
-
}
|
|
4502
|
-
function parseCheckpointRequestBody(value) {
|
|
4503
|
-
const parsed = checkpointRequestBodySchema.safeParse(value);
|
|
4504
|
-
if (parsed.success) return parsed.data;
|
|
4505
|
-
const [firstIssue] = parsed.error.issues;
|
|
4506
|
-
throw new import_errors.KortyxError("INVALID_REQUEST", firstIssue.message, {
|
|
4507
|
-
category: "request",
|
|
4508
|
-
retryable: false,
|
|
4509
|
-
safeMessage: "The request body is invalid."
|
|
4510
|
-
});
|
|
4511
|
-
}
|
|
4512
|
-
async function handleChatRequestBody(args) {
|
|
4513
|
-
const { agent, body } = args;
|
|
4514
|
-
const stream = await agent.streamChat(body.messages, {
|
|
4515
|
-
...args.onExecution ? { onExecution: args.onExecution } : {},
|
|
4516
|
-
...args.abortSignal ? { abortSignal: args.abortSignal } : {},
|
|
4517
|
-
sessionId: body.sessionId,
|
|
4518
|
-
workflowId: body.workflowId,
|
|
4519
|
-
context: body.context
|
|
4520
|
-
});
|
|
4521
|
-
if (body.stream === false) {
|
|
4522
|
-
const buffered = await (0, import_stream.collectBufferedStream)(stream);
|
|
4523
|
-
return new Response(JSON.stringify(buffered), {
|
|
4524
|
-
headers: {
|
|
4525
|
-
"content-type": "application/json"
|
|
4526
|
-
}
|
|
4527
|
-
});
|
|
4528
|
-
}
|
|
4529
|
-
return (0, import_stream.toSSE)(stream);
|
|
4530
|
-
}
|
|
4531
|
-
function createChatRouteHandler(args) {
|
|
4532
|
-
const { agent, errorStatus } = args;
|
|
4533
|
-
return async function POST(request) {
|
|
4534
|
-
try {
|
|
4535
|
-
const body = parseChatRequestBody(await readRequestJson(request));
|
|
4536
|
-
return await handleChatRequestBody({
|
|
4537
|
-
agent,
|
|
4538
|
-
body,
|
|
4539
|
-
abortSignal: request.signal,
|
|
4540
|
-
onExecution: args.onExecution
|
|
4541
|
-
});
|
|
4542
|
-
} catch (error) {
|
|
4543
|
-
return createFailureResponse(error, errorStatus);
|
|
4544
|
-
}
|
|
4545
|
-
};
|
|
4546
|
-
}
|
|
4547
|
-
async function handleCheckpointRequestBody(args) {
|
|
4548
|
-
const { agent, body } = args;
|
|
4549
|
-
const result = body.action === "list" ? await agent.listCheckpoints(body.sessionId) : body.action === "get" ? await agent.getCheckpoint(body.checkpointId) : body.action === "rollback" ? await agent.rollbackTo(body.checkpointId) : await agent.fork(body.checkpointId, {
|
|
4550
|
-
...body.newSessionId ? { newSessionId: body.newSessionId } : {}
|
|
4551
|
-
});
|
|
4552
|
-
return new Response(JSON.stringify(result), {
|
|
4553
|
-
headers: {
|
|
4554
|
-
"content-type": "application/json"
|
|
4555
|
-
}
|
|
4556
|
-
});
|
|
4557
|
-
}
|
|
4558
|
-
function createCheckpointRouteHandler(args) {
|
|
4559
|
-
const { agent, errorStatus } = args;
|
|
4560
|
-
return async function POST(request) {
|
|
4561
|
-
try {
|
|
4562
|
-
const body = parseCheckpointRequestBody(await readRequestJson(request));
|
|
4563
|
-
return await handleCheckpointRequestBody({ agent, body });
|
|
4564
|
-
} catch (error) {
|
|
4565
|
-
return createFailureResponse(error, errorStatus);
|
|
4566
|
-
}
|
|
4567
|
-
};
|
|
4568
|
-
}
|
|
4569
|
-
|
|
4570
|
-
// src/adapters/http-client.ts
|
|
4571
|
-
var import_browser = require("@kortyx/stream/browser");
|
|
4572
|
-
async function* streamChatFromRoute(args) {
|
|
4573
|
-
yield* (0, import_browser.streamFromRoute)({
|
|
4574
|
-
endpoint: args.endpoint,
|
|
4575
|
-
...args.fetchImpl ? { fetchImpl: args.fetchImpl } : {},
|
|
4576
|
-
...args.headers ? { headers: args.headers } : {},
|
|
4577
|
-
body: {
|
|
4578
|
-
sessionId: args.sessionId,
|
|
4579
|
-
workflowId: args.workflowId,
|
|
4580
|
-
messages: args.messages
|
|
4581
|
-
}
|
|
4582
|
-
});
|
|
4583
|
-
}
|
|
4584
|
-
|
|
4585
|
-
// src/chat/create-agent.ts
|
|
4586
|
-
var import_node_path = require("path");
|
|
4587
|
-
var import_core5 = require("@kortyx/core");
|
|
4588
|
-
var import_providers = require("@kortyx/providers");
|
|
4589
|
-
var import_runtime5 = require("@kortyx/runtime");
|
|
4590
|
-
var import_zod5 = require("zod");
|
|
4591
|
-
|
|
4592
|
-
// src/execution/execute.ts
|
|
4593
|
-
var import_core4 = require("@kortyx/core");
|
|
4594
|
-
var import_errors5 = require("@kortyx/core/errors");
|
|
4595
|
-
var import_runtime3 = require("@kortyx/runtime");
|
|
4596
|
-
var import_zod3 = require("zod");
|
|
4443
|
+
};
|
|
4597
4444
|
|
|
4598
4445
|
// src/interrupt/resume-handler.ts
|
|
4599
4446
|
var import_core3 = require("@kortyx/core");
|
|
@@ -4619,11 +4466,12 @@ var import_core2 = require("@kortyx/core");
|
|
|
4619
4466
|
var import_errors4 = require("@kortyx/core/errors");
|
|
4620
4467
|
var import_internal = __toESM(require_internal());
|
|
4621
4468
|
var import_runtime = require("@kortyx/runtime");
|
|
4469
|
+
var import_stream = require("@kortyx/stream");
|
|
4622
4470
|
var import_langgraph = require("@langchain/langgraph");
|
|
4623
4471
|
|
|
4624
4472
|
// src/execution/contracts.ts
|
|
4625
4473
|
var import_errors3 = require("@kortyx/core/errors");
|
|
4626
|
-
var
|
|
4474
|
+
var import_zod = require("zod");
|
|
4627
4475
|
async function resolveExecutionWorkflow(select, reference) {
|
|
4628
4476
|
const id = typeof reference === "string" ? reference : reference.id;
|
|
4629
4477
|
let workflow;
|
|
@@ -4655,12 +4503,12 @@ async function resolveExecutionWorkflow(select, reference) {
|
|
|
4655
4503
|
}
|
|
4656
4504
|
function parseExecutionInput(workflow, input) {
|
|
4657
4505
|
try {
|
|
4658
|
-
|
|
4506
|
+
import_zod.z.json().parse(input);
|
|
4659
4507
|
const parsed = workflow.inputSchema ? workflow.inputSchema.parse(input) : input;
|
|
4660
|
-
|
|
4508
|
+
import_zod.z.json().parse(parsed);
|
|
4661
4509
|
return parsed;
|
|
4662
4510
|
} catch (error) {
|
|
4663
|
-
if (!(error instanceof
|
|
4511
|
+
if (!(error instanceof import_zod.z.ZodError)) throw error;
|
|
4664
4512
|
throw new ExecutionRequestError("INVALID_INPUT", error.message, error);
|
|
4665
4513
|
}
|
|
4666
4514
|
}
|
|
@@ -4678,9 +4526,9 @@ async function validateExecutionOutput(state, select) {
|
|
|
4678
4526
|
for (const schema of /* @__PURE__ */ new Set([terminal.outputSchema, root.outputSchema])) {
|
|
4679
4527
|
if (schema) data = schema.parse(data);
|
|
4680
4528
|
}
|
|
4681
|
-
if (terminal.outputSchema || root.outputSchema)
|
|
4529
|
+
if (terminal.outputSchema || root.outputSchema) import_zod.z.json().parse(data);
|
|
4682
4530
|
} catch (error) {
|
|
4683
|
-
if (!(error instanceof
|
|
4531
|
+
if (!(error instanceof import_zod.z.ZodError)) throw error;
|
|
4684
4532
|
const failure = new import_errors3.ValidationError(
|
|
4685
4533
|
"INVALID_OUTPUT",
|
|
4686
4534
|
`Workflow output validation failed: ${error.message}`,
|
|
@@ -5091,6 +4939,9 @@ async function orchestrateGraphStream({
|
|
|
5091
4939
|
abortSignal: requestSignal,
|
|
5092
4940
|
executionSignal,
|
|
5093
4941
|
onExecution,
|
|
4942
|
+
clientTurnId,
|
|
4943
|
+
continueOnDisconnect = false,
|
|
4944
|
+
onResponseFinalized,
|
|
5094
4945
|
emitOutput = true,
|
|
5095
4946
|
onOutcome,
|
|
5096
4947
|
selectWorkflow,
|
|
@@ -5099,12 +4950,34 @@ async function orchestrateGraphStream({
|
|
|
5099
4950
|
executionLeaseRelease
|
|
5100
4951
|
}) {
|
|
5101
4952
|
const out = new import_node_stream.PassThrough({ objectMode: true });
|
|
4953
|
+
const visibleMessage = emitOutput && clientTurnId && onResponseFinalized && initialConfig.responseCompleted !== true ? (0, import_stream.createFinalizedChatMessageAccumulator)(clientTurnId) : void 0;
|
|
4954
|
+
let responseFinalized = false;
|
|
4955
|
+
const finalizeVisibleResponse = async (status) => {
|
|
4956
|
+
if (!visibleMessage || !onResponseFinalized || !clientTurnId || !sessionId || responseFinalized)
|
|
4957
|
+
return;
|
|
4958
|
+
responseFinalized = true;
|
|
4959
|
+
try {
|
|
4960
|
+
await onResponseFinalized({
|
|
4961
|
+
sessionId,
|
|
4962
|
+
runId,
|
|
4963
|
+
clientTurnId,
|
|
4964
|
+
status,
|
|
4965
|
+
message: visibleMessage.message(),
|
|
4966
|
+
...sessionCheckpointId ? { checkpointId: sessionCheckpointId } : {}
|
|
4967
|
+
});
|
|
4968
|
+
} catch (error) {
|
|
4969
|
+
console.error("[chat:onResponseFinalized]", (0, import_errors4.serializeFailure)(error));
|
|
4970
|
+
}
|
|
4971
|
+
};
|
|
5102
4972
|
const write = (chunk) => {
|
|
5103
4973
|
if (isRecord3(chunk) && chunk.type === "done" && isGraphState(chunk.data)) {
|
|
5104
4974
|
const { __kortyxParallelGraph: _journal, ...runtime } = chunk.data.runtime;
|
|
5105
4975
|
chunk = { ...chunk, data: { ...chunk.data, runtime } };
|
|
5106
4976
|
}
|
|
5107
|
-
if (emitOutput && !response.closed
|
|
4977
|
+
if (emitOutput && !response.closed) {
|
|
4978
|
+
visibleMessage?.apply(chunk);
|
|
4979
|
+
if (!out.destroyed) out.write(chunk);
|
|
4980
|
+
}
|
|
5108
4981
|
};
|
|
5109
4982
|
let outcomeState = state;
|
|
5110
4983
|
let outcomeError;
|
|
@@ -5119,7 +4992,7 @@ async function orchestrateGraphStream({
|
|
|
5119
4992
|
const response = createResponseLifecycle({
|
|
5120
4993
|
enabled: emitOutput,
|
|
5121
4994
|
restored: initialConfig.responseCompleted === true,
|
|
5122
|
-
requestSignal,
|
|
4995
|
+
requestSignal: continueOnDisconnect ? void 0 : requestSignal,
|
|
5123
4996
|
executionSignal: executionSignal ? AbortSignal.any([executionSignal, leaseAbort.signal]) : leaseAbort.signal,
|
|
5124
4997
|
onClosed: () => {
|
|
5125
4998
|
out.write({ type: "done" });
|
|
@@ -5183,11 +5056,12 @@ async function orchestrateGraphStream({
|
|
|
5183
5056
|
},
|
|
5184
5057
|
flush: true
|
|
5185
5058
|
});
|
|
5059
|
+
await finalizeVisibleResponse("completed");
|
|
5186
5060
|
}
|
|
5187
5061
|
});
|
|
5188
5062
|
const abortSignal = response.signal;
|
|
5189
5063
|
out.on("close", () => {
|
|
5190
|
-
if (!finished) response.disconnect();
|
|
5064
|
+
if (!finished && !continueOnDisconnect) response.disconnect();
|
|
5191
5065
|
});
|
|
5192
5066
|
let structuredSeq = 0;
|
|
5193
5067
|
const debugEnabled = Boolean(config?.features?.tracing);
|
|
@@ -5940,6 +5814,9 @@ async function orchestrateGraphStream({
|
|
|
5940
5814
|
);
|
|
5941
5815
|
}
|
|
5942
5816
|
}
|
|
5817
|
+
await finalizeVisibleResponse(
|
|
5818
|
+
outcomeError ? "failed" : shouldKeepFrameworkState ? "interrupted" : "completed"
|
|
5819
|
+
);
|
|
5943
5820
|
write({ type: "done", data: workflowFinalState });
|
|
5944
5821
|
out.end();
|
|
5945
5822
|
return;
|
|
@@ -6017,6 +5894,9 @@ async function orchestrateGraphStream({
|
|
|
6017
5894
|
});
|
|
6018
5895
|
finished = true;
|
|
6019
5896
|
runTraceSpan.end?.(runTraceEndArgs());
|
|
5897
|
+
await finalizeVisibleResponse(
|
|
5898
|
+
outcomeError ? "failed" : pendingRecordToken || naturalFinalState.awaitingHumanInput ? "interrupted" : "completed"
|
|
5899
|
+
);
|
|
6020
5900
|
write({ type: "done", data: naturalFinalState });
|
|
6021
5901
|
out.end();
|
|
6022
5902
|
return;
|
|
@@ -6077,6 +5957,7 @@ async function orchestrateGraphStream({
|
|
|
6077
5957
|
fallbackRunSpan?.setAttributes?.({ "kortyx.run.cancelled": true });
|
|
6078
5958
|
fallbackRunSpan?.end?.();
|
|
6079
5959
|
write({ type: "cancelled", runId, reason: "Execution cancelled." });
|
|
5960
|
+
await finalizeVisibleResponse("cancelled");
|
|
6080
5961
|
write({ type: "done" });
|
|
6081
5962
|
finished = true;
|
|
6082
5963
|
out.end();
|
|
@@ -6223,6 +6104,9 @@ async function orchestrateGraphStream({
|
|
|
6223
6104
|
console.error("[execution:releaseLease]", (0, import_errors4.serializeFailure)(error));
|
|
6224
6105
|
}
|
|
6225
6106
|
response.dispose();
|
|
6107
|
+
await finalizeVisibleResponse(
|
|
6108
|
+
outcomeError ? (0, import_core2.isExecutionCancelled)(outcomeError) ? "cancelled" : "failed" : pendingRecordToken || outcomeState.awaitingHumanInput ? "interrupted" : "completed"
|
|
6109
|
+
);
|
|
6226
6110
|
onOutcome?.({
|
|
6227
6111
|
state: outcomeState,
|
|
6228
6112
|
pending: pendingRecordToken ? activePendingRequests.get(pendingRecordToken) : void 0,
|
|
@@ -6272,6 +6156,9 @@ async function tryPrepareResumeStream({
|
|
|
6272
6156
|
abortSignal,
|
|
6273
6157
|
executionSignal,
|
|
6274
6158
|
onExecution,
|
|
6159
|
+
clientTurnId,
|
|
6160
|
+
continueOnDisconnect,
|
|
6161
|
+
onResponseFinalized,
|
|
6275
6162
|
lastMessage,
|
|
6276
6163
|
meta: suppliedMeta,
|
|
6277
6164
|
emitOutput,
|
|
@@ -6490,6 +6377,9 @@ async function tryPrepareResumeStream({
|
|
|
6490
6377
|
executionSignal: continuedSignal ? AbortSignal.any([continuedSignal, leaseAbort.signal]) : leaseAbort.signal,
|
|
6491
6378
|
executionLeaseRelease: releaseLease,
|
|
6492
6379
|
onExecution,
|
|
6380
|
+
clientTurnId,
|
|
6381
|
+
continueOnDisconnect,
|
|
6382
|
+
onResponseFinalized,
|
|
6493
6383
|
emitOutput,
|
|
6494
6384
|
onOutcome,
|
|
6495
6385
|
sessionId,
|
|
@@ -6526,7 +6416,316 @@ async function tryPrepareResumeStream({
|
|
|
6526
6416
|
}
|
|
6527
6417
|
}
|
|
6528
6418
|
|
|
6419
|
+
// src/adapters/http.ts
|
|
6420
|
+
var reportLifecycleError = async (callback, event) => {
|
|
6421
|
+
if (!callback) {
|
|
6422
|
+
console.error("[chat:lifecycle]", event.error);
|
|
6423
|
+
return;
|
|
6424
|
+
}
|
|
6425
|
+
try {
|
|
6426
|
+
await callback(event);
|
|
6427
|
+
} catch (error) {
|
|
6428
|
+
console.error("[chat:onLifecycleError]", (0, import_errors5.serializeFailure)(error));
|
|
6429
|
+
}
|
|
6430
|
+
};
|
|
6431
|
+
var chatMessageSchema = import_zod2.z.object({
|
|
6432
|
+
role: import_zod2.z.enum(["user", "assistant", "system"]),
|
|
6433
|
+
content: import_zod2.z.string(),
|
|
6434
|
+
metadata: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
|
|
6435
|
+
id: import_zod2.z.string().optional(),
|
|
6436
|
+
timestamp: import_zod2.z.number().refine(Number.isFinite).optional()
|
|
6437
|
+
}).strict();
|
|
6438
|
+
var chatRequestBodySchema = import_zod2.z.looseObject({
|
|
6439
|
+
sessionId: import_zod2.z.string().optional(),
|
|
6440
|
+
clientTurnId: import_zod2.z.string().max(128).optional(),
|
|
6441
|
+
workflowId: import_zod2.z.string().optional(),
|
|
6442
|
+
stream: import_zod2.z.boolean().optional(),
|
|
6443
|
+
context: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
|
|
6444
|
+
messages: import_zod2.z.array(chatMessageSchema)
|
|
6445
|
+
});
|
|
6446
|
+
var checkpointRequestBodySchema = import_zod2.z.discriminatedUnion("action", [
|
|
6447
|
+
import_zod2.z.object({
|
|
6448
|
+
action: import_zod2.z.literal("list"),
|
|
6449
|
+
sessionId: import_zod2.z.string().min(1)
|
|
6450
|
+
}).strict(),
|
|
6451
|
+
import_zod2.z.object({
|
|
6452
|
+
action: import_zod2.z.literal("get"),
|
|
6453
|
+
checkpointId: import_zod2.z.string().min(1)
|
|
6454
|
+
}).strict(),
|
|
6455
|
+
import_zod2.z.object({
|
|
6456
|
+
action: import_zod2.z.literal("rollback"),
|
|
6457
|
+
checkpointId: import_zod2.z.string().min(1)
|
|
6458
|
+
}).strict(),
|
|
6459
|
+
import_zod2.z.object({
|
|
6460
|
+
action: import_zod2.z.literal("fork"),
|
|
6461
|
+
checkpointId: import_zod2.z.string().min(1),
|
|
6462
|
+
newSessionId: import_zod2.z.string().min(1).optional()
|
|
6463
|
+
}).strict()
|
|
6464
|
+
]);
|
|
6465
|
+
async function readRequestJson(request) {
|
|
6466
|
+
try {
|
|
6467
|
+
const value = await request.json();
|
|
6468
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
6469
|
+
throw new Error("Expected a JSON object.");
|
|
6470
|
+
return value;
|
|
6471
|
+
} catch (cause) {
|
|
6472
|
+
throw new import_errors5.KortyxError(
|
|
6473
|
+
"INVALID_REQUEST",
|
|
6474
|
+
"Request body is not valid JSON.",
|
|
6475
|
+
{
|
|
6476
|
+
category: "request",
|
|
6477
|
+
retryable: false,
|
|
6478
|
+
safeMessage: "The request body must contain a valid JSON object.",
|
|
6479
|
+
cause
|
|
6480
|
+
}
|
|
6481
|
+
);
|
|
6482
|
+
}
|
|
6483
|
+
}
|
|
6484
|
+
function createFailureResponse(error, status) {
|
|
6485
|
+
const failure = (0, import_errors5.serializeFailure)(error);
|
|
6486
|
+
return Response.json(
|
|
6487
|
+
{ error: failure.message, failure },
|
|
6488
|
+
{ status: status ?? (0, import_errors5.failureHttpStatus)(failure) }
|
|
6489
|
+
);
|
|
6490
|
+
}
|
|
6491
|
+
function parseChatRequestBody(value) {
|
|
6492
|
+
const parsed = chatRequestBodySchema.safeParse(value);
|
|
6493
|
+
if (!parsed.success) {
|
|
6494
|
+
const [firstIssue] = parsed.error.issues;
|
|
6495
|
+
throw new import_errors5.KortyxError("INVALID_REQUEST", firstIssue.message, {
|
|
6496
|
+
category: "request",
|
|
6497
|
+
retryable: false,
|
|
6498
|
+
safeMessage: "The request body is invalid."
|
|
6499
|
+
});
|
|
6500
|
+
}
|
|
6501
|
+
const sessionId = parsed.data.sessionId?.trim();
|
|
6502
|
+
const workflowId = parsed.data.workflowId?.trim();
|
|
6503
|
+
const clientTurnId = parsed.data.clientTurnId?.trim();
|
|
6504
|
+
return {
|
|
6505
|
+
...sessionId ? { sessionId } : {},
|
|
6506
|
+
...workflowId ? { workflowId } : {},
|
|
6507
|
+
...clientTurnId ? { clientTurnId } : {},
|
|
6508
|
+
...typeof parsed.data.stream === "boolean" ? { stream: parsed.data.stream } : {},
|
|
6509
|
+
...parsed.data.context ? { context: parsed.data.context } : {},
|
|
6510
|
+
messages: parsed.data.messages
|
|
6511
|
+
};
|
|
6512
|
+
}
|
|
6513
|
+
function parseCheckpointRequestBody(value) {
|
|
6514
|
+
const parsed = checkpointRequestBodySchema.safeParse(value);
|
|
6515
|
+
if (parsed.success) return parsed.data;
|
|
6516
|
+
const [firstIssue] = parsed.error.issues;
|
|
6517
|
+
throw new import_errors5.KortyxError("INVALID_REQUEST", firstIssue.message, {
|
|
6518
|
+
category: "request",
|
|
6519
|
+
retryable: false,
|
|
6520
|
+
safeMessage: "The request body is invalid."
|
|
6521
|
+
});
|
|
6522
|
+
}
|
|
6523
|
+
async function handleChatRequestBody(args) {
|
|
6524
|
+
const { agent, body } = args;
|
|
6525
|
+
if (args.onResponseFinalized && (!body.sessionId || !body.clientTurnId)) {
|
|
6526
|
+
throw new import_errors5.KortyxError(
|
|
6527
|
+
"INVALID_REQUEST",
|
|
6528
|
+
"sessionId and clientTurnId are required with onResponseFinalized.",
|
|
6529
|
+
{
|
|
6530
|
+
category: "request",
|
|
6531
|
+
retryable: false,
|
|
6532
|
+
safeMessage: "This chat request needs a session and turn ID."
|
|
6533
|
+
}
|
|
6534
|
+
);
|
|
6535
|
+
}
|
|
6536
|
+
const stream = await agent.streamChat(body.messages, {
|
|
6537
|
+
...args.onExecution ? { onExecution: args.onExecution } : {},
|
|
6538
|
+
...body.clientTurnId ? { clientTurnId: body.clientTurnId } : {},
|
|
6539
|
+
...args.continueOnDisconnect ? { continueOnDisconnect: true } : {},
|
|
6540
|
+
...args.onResponseFinalized ? { onResponseFinalized: args.onResponseFinalized } : {},
|
|
6541
|
+
...args.abortSignal && !args.continueOnDisconnect ? { abortSignal: args.abortSignal } : {},
|
|
6542
|
+
sessionId: body.sessionId,
|
|
6543
|
+
workflowId: body.workflowId,
|
|
6544
|
+
context: body.context
|
|
6545
|
+
});
|
|
6546
|
+
if (body.stream === false) {
|
|
6547
|
+
const buffered = await (0, import_stream2.collectBufferedStream)(stream);
|
|
6548
|
+
return new Response(JSON.stringify(buffered), {
|
|
6549
|
+
headers: {
|
|
6550
|
+
"content-type": "application/json"
|
|
6551
|
+
}
|
|
6552
|
+
});
|
|
6553
|
+
}
|
|
6554
|
+
return (0, import_stream2.toSSE)(stream);
|
|
6555
|
+
}
|
|
6556
|
+
function createChatRouteHandler(args) {
|
|
6557
|
+
const { agent, errorStatus } = args;
|
|
6558
|
+
if (args.disconnect === "continue" && !args.onExecution) {
|
|
6559
|
+
throw new Error(
|
|
6560
|
+
'disconnect: "continue" requires onExecution to retain host lifetime.'
|
|
6561
|
+
);
|
|
6562
|
+
}
|
|
6563
|
+
return async function POST(request) {
|
|
6564
|
+
try {
|
|
6565
|
+
const body = parseChatRequestBody(await readRequestJson(request));
|
|
6566
|
+
if (args.onTurnAccepted || args.onResponseFinalized) {
|
|
6567
|
+
if (!body.sessionId || !body.clientTurnId) {
|
|
6568
|
+
throw new import_errors5.KortyxError(
|
|
6569
|
+
"INVALID_REQUEST",
|
|
6570
|
+
"sessionId and clientTurnId are required with chat lifecycle hooks.",
|
|
6571
|
+
{
|
|
6572
|
+
category: "request",
|
|
6573
|
+
retryable: false,
|
|
6574
|
+
safeMessage: "This chat request needs a session and turn ID."
|
|
6575
|
+
}
|
|
6576
|
+
);
|
|
6577
|
+
}
|
|
6578
|
+
const userMessage = body.messages.at(-1);
|
|
6579
|
+
if (!userMessage || userMessage.role !== "user") {
|
|
6580
|
+
throw new import_errors5.KortyxError(
|
|
6581
|
+
"INVALID_REQUEST",
|
|
6582
|
+
"The last chat message must be from the user.",
|
|
6583
|
+
{
|
|
6584
|
+
category: "request",
|
|
6585
|
+
retryable: false,
|
|
6586
|
+
safeMessage: "The chat request needs a user message."
|
|
6587
|
+
}
|
|
6588
|
+
);
|
|
6589
|
+
}
|
|
6590
|
+
if (args.onTurnAccepted) {
|
|
6591
|
+
try {
|
|
6592
|
+
await args.onTurnAccepted({
|
|
6593
|
+
request,
|
|
6594
|
+
sessionId: body.sessionId,
|
|
6595
|
+
clientTurnId: body.clientTurnId,
|
|
6596
|
+
userMessage: { ...userMessage, role: "user" },
|
|
6597
|
+
kind: parseResumeMeta(userMessage) ? "interrupt-response" : "prompt"
|
|
6598
|
+
});
|
|
6599
|
+
} catch (cause) {
|
|
6600
|
+
const error = new ChatLifecycleHookError("turn-accepted", cause);
|
|
6601
|
+
await reportLifecycleError(args.onLifecycleError, {
|
|
6602
|
+
phase: "turn-accepted",
|
|
6603
|
+
clientTurnId: body.clientTurnId,
|
|
6604
|
+
error
|
|
6605
|
+
});
|
|
6606
|
+
throw error;
|
|
6607
|
+
}
|
|
6608
|
+
}
|
|
6609
|
+
}
|
|
6610
|
+
return await handleChatRequestBody({
|
|
6611
|
+
agent,
|
|
6612
|
+
body,
|
|
6613
|
+
abortSignal: request.signal,
|
|
6614
|
+
onExecution: args.onExecution,
|
|
6615
|
+
continueOnDisconnect: args.disconnect === "continue",
|
|
6616
|
+
...args.onResponseFinalized ? {
|
|
6617
|
+
onResponseFinalized: async (event) => {
|
|
6618
|
+
try {
|
|
6619
|
+
await args.onResponseFinalized?.({ ...event, request });
|
|
6620
|
+
} catch (cause) {
|
|
6621
|
+
await reportLifecycleError(args.onLifecycleError, {
|
|
6622
|
+
phase: "response-finalized",
|
|
6623
|
+
clientTurnId: event.clientTurnId,
|
|
6624
|
+
error: new ChatLifecycleHookError(
|
|
6625
|
+
"response-finalized",
|
|
6626
|
+
cause
|
|
6627
|
+
)
|
|
6628
|
+
});
|
|
6629
|
+
}
|
|
6630
|
+
}
|
|
6631
|
+
} : {}
|
|
6632
|
+
});
|
|
6633
|
+
} catch (error) {
|
|
6634
|
+
return createFailureResponse(error, errorStatus);
|
|
6635
|
+
}
|
|
6636
|
+
};
|
|
6637
|
+
}
|
|
6638
|
+
async function handleCheckpointRequestBody(args) {
|
|
6639
|
+
const { agent, body } = args;
|
|
6640
|
+
const result = body.action === "list" ? await agent.listCheckpoints(body.sessionId) : body.action === "get" ? await agent.getCheckpoint(body.checkpointId) : body.action === "rollback" ? await agent.rollbackTo(body.checkpointId) : await agent.fork(body.checkpointId, {
|
|
6641
|
+
...body.newSessionId ? { newSessionId: body.newSessionId } : {}
|
|
6642
|
+
});
|
|
6643
|
+
if (args.request && body.action === "fork" && args.onForked) {
|
|
6644
|
+
const fork = result;
|
|
6645
|
+
try {
|
|
6646
|
+
await args.onForked({
|
|
6647
|
+
request: args.request,
|
|
6648
|
+
sourceSessionId: fork.parentSessionId,
|
|
6649
|
+
newSessionId: fork.sessionId,
|
|
6650
|
+
sourceCheckpointId: fork.forkedFrom,
|
|
6651
|
+
newCheckpointId: fork.checkpoint.id
|
|
6652
|
+
});
|
|
6653
|
+
} catch (cause) {
|
|
6654
|
+
await reportLifecycleError(args.onLifecycleError, {
|
|
6655
|
+
phase: "forked",
|
|
6656
|
+
error: new ChatLifecycleHookError("forked", cause)
|
|
6657
|
+
});
|
|
6658
|
+
}
|
|
6659
|
+
}
|
|
6660
|
+
if (args.request && body.action === "rollback" && args.onRolledBack) {
|
|
6661
|
+
const rollback = result;
|
|
6662
|
+
try {
|
|
6663
|
+
await args.onRolledBack({
|
|
6664
|
+
request: args.request,
|
|
6665
|
+
sessionId: rollback.sessionId,
|
|
6666
|
+
headCheckpointId: rollback.head,
|
|
6667
|
+
invalidatedStructuredStreamIds: rollback.invalidatedStructuredStreamIds
|
|
6668
|
+
});
|
|
6669
|
+
} catch (cause) {
|
|
6670
|
+
await reportLifecycleError(args.onLifecycleError, {
|
|
6671
|
+
phase: "rolled-back",
|
|
6672
|
+
error: new ChatLifecycleHookError("rolled-back", cause)
|
|
6673
|
+
});
|
|
6674
|
+
}
|
|
6675
|
+
}
|
|
6676
|
+
return new Response(JSON.stringify(result), {
|
|
6677
|
+
headers: {
|
|
6678
|
+
"content-type": "application/json"
|
|
6679
|
+
}
|
|
6680
|
+
});
|
|
6681
|
+
}
|
|
6682
|
+
function createCheckpointRouteHandler(args) {
|
|
6683
|
+
const { agent, errorStatus } = args;
|
|
6684
|
+
return async function POST(request) {
|
|
6685
|
+
try {
|
|
6686
|
+
const body = parseCheckpointRequestBody(await readRequestJson(request));
|
|
6687
|
+
return await handleCheckpointRequestBody({
|
|
6688
|
+
agent,
|
|
6689
|
+
body,
|
|
6690
|
+
request,
|
|
6691
|
+
onForked: args.onForked,
|
|
6692
|
+
onRolledBack: args.onRolledBack,
|
|
6693
|
+
onLifecycleError: args.onLifecycleError
|
|
6694
|
+
});
|
|
6695
|
+
} catch (error) {
|
|
6696
|
+
return createFailureResponse(error, errorStatus);
|
|
6697
|
+
}
|
|
6698
|
+
};
|
|
6699
|
+
}
|
|
6700
|
+
|
|
6701
|
+
// src/adapters/http-client.ts
|
|
6702
|
+
var import_browser = require("@kortyx/stream/browser");
|
|
6703
|
+
async function* streamChatFromRoute(args) {
|
|
6704
|
+
yield* (0, import_browser.streamFromRoute)({
|
|
6705
|
+
endpoint: args.endpoint,
|
|
6706
|
+
...args.fetchImpl ? { fetchImpl: args.fetchImpl } : {},
|
|
6707
|
+
...args.headers ? { headers: args.headers } : {},
|
|
6708
|
+
body: {
|
|
6709
|
+
sessionId: args.sessionId,
|
|
6710
|
+
clientTurnId: args.clientTurnId,
|
|
6711
|
+
workflowId: args.workflowId,
|
|
6712
|
+
messages: args.messages
|
|
6713
|
+
}
|
|
6714
|
+
});
|
|
6715
|
+
}
|
|
6716
|
+
|
|
6717
|
+
// src/chat/create-agent.ts
|
|
6718
|
+
var import_node_path = require("path");
|
|
6719
|
+
var import_core5 = require("@kortyx/core");
|
|
6720
|
+
var import_providers = require("@kortyx/providers");
|
|
6721
|
+
var import_runtime5 = require("@kortyx/runtime");
|
|
6722
|
+
var import_zod5 = require("zod");
|
|
6723
|
+
|
|
6529
6724
|
// src/execution/execute.ts
|
|
6725
|
+
var import_core4 = require("@kortyx/core");
|
|
6726
|
+
var import_errors6 = require("@kortyx/core/errors");
|
|
6727
|
+
var import_runtime3 = require("@kortyx/runtime");
|
|
6728
|
+
var import_zod3 = require("zod");
|
|
6530
6729
|
var handleSchema = import_zod3.z.object({
|
|
6531
6730
|
token: import_zod3.z.string().min(1),
|
|
6532
6731
|
requestId: import_zod3.z.string().min(1),
|
|
@@ -6557,7 +6756,7 @@ function resultFromOutcome(outcome, runId, sessionId) {
|
|
|
6557
6756
|
return {
|
|
6558
6757
|
...info,
|
|
6559
6758
|
status: "failed",
|
|
6560
|
-
error: (0,
|
|
6759
|
+
error: (0, import_errors6.serializeFailure)(error)
|
|
6561
6760
|
};
|
|
6562
6761
|
}
|
|
6563
6762
|
if (outcome.cancelled)
|
|
@@ -6738,7 +6937,7 @@ async function resumeWorkflow(services, args) {
|
|
|
6738
6937
|
);
|
|
6739
6938
|
}).catch(
|
|
6740
6939
|
(error) => reject(
|
|
6741
|
-
error instanceof Error ? error : new
|
|
6940
|
+
error instanceof Error ? error : new import_errors6.KortyxError("RESUME_FAILED", "Resume failed.", {
|
|
6742
6941
|
category: "persistence",
|
|
6743
6942
|
cause: error,
|
|
6744
6943
|
safeMessage: "The saved execution could not be resumed."
|
|
@@ -6941,6 +7140,7 @@ function restoreWorkflowCallBranch(requests, telemetry, sourceRunId) {
|
|
|
6941
7140
|
}
|
|
6942
7141
|
|
|
6943
7142
|
// src/chat/process-chat.ts
|
|
7143
|
+
var import_errors7 = require("@kortyx/core/errors");
|
|
6944
7144
|
var import_runtime4 = require("@kortyx/runtime");
|
|
6945
7145
|
|
|
6946
7146
|
// src/utils/extract-latest-message.ts
|
|
@@ -6961,6 +7161,9 @@ async function streamChat({
|
|
|
6961
7161
|
abortSignal,
|
|
6962
7162
|
executionSignal,
|
|
6963
7163
|
onExecution,
|
|
7164
|
+
clientTurnId,
|
|
7165
|
+
continueOnDisconnect,
|
|
7166
|
+
onResponseFinalized,
|
|
6964
7167
|
options,
|
|
6965
7168
|
sessionId,
|
|
6966
7169
|
defaultWorkflowId,
|
|
@@ -6972,6 +7175,18 @@ async function streamChat({
|
|
|
6972
7175
|
getProvider,
|
|
6973
7176
|
applyResumeSelection
|
|
6974
7177
|
}) {
|
|
7178
|
+
const suppliedSessionId = sessionId || options?.sessionId;
|
|
7179
|
+
if (onResponseFinalized && (!suppliedSessionId || !clientTurnId?.trim() || clientTurnId.length > 128)) {
|
|
7180
|
+
throw new import_errors7.KortyxError(
|
|
7181
|
+
"INVALID_REQUEST",
|
|
7182
|
+
"sessionId and clientTurnId are required with onResponseFinalized.",
|
|
7183
|
+
{
|
|
7184
|
+
category: "request",
|
|
7185
|
+
retryable: false,
|
|
7186
|
+
safeMessage: "This chat request needs a session and turn ID."
|
|
7187
|
+
}
|
|
7188
|
+
);
|
|
7189
|
+
}
|
|
6975
7190
|
const config = await loadRuntimeConfig(options);
|
|
6976
7191
|
let runtimeConfig2 = {
|
|
6977
7192
|
...config,
|
|
@@ -7010,6 +7225,9 @@ async function streamChat({
|
|
|
7010
7225
|
abortSignal,
|
|
7011
7226
|
executionSignal,
|
|
7012
7227
|
onExecution,
|
|
7228
|
+
clientTurnId,
|
|
7229
|
+
continueOnDisconnect,
|
|
7230
|
+
onResponseFinalized,
|
|
7013
7231
|
lastMessage: last,
|
|
7014
7232
|
sessionId: resolvedSessionId,
|
|
7015
7233
|
config: runtimeConfig2,
|
|
@@ -7083,6 +7301,9 @@ async function streamChat({
|
|
|
7083
7301
|
abortSignal,
|
|
7084
7302
|
executionSignal,
|
|
7085
7303
|
onExecution,
|
|
7304
|
+
clientTurnId,
|
|
7305
|
+
continueOnDisconnect,
|
|
7306
|
+
onResponseFinalized,
|
|
7086
7307
|
sessionId: resolvedSessionId,
|
|
7087
7308
|
runId,
|
|
7088
7309
|
graph,
|
|
@@ -7101,6 +7322,9 @@ var agentProcessOptionsSchema = import_zod5.z.object({
|
|
|
7101
7322
|
onExecution: import_zod5.z.custom(
|
|
7102
7323
|
(value) => typeof value === "function"
|
|
7103
7324
|
).optional(),
|
|
7325
|
+
clientTurnId: import_zod5.z.string().min(1).max(128).optional(),
|
|
7326
|
+
continueOnDisconnect: import_zod5.z.boolean().optional(),
|
|
7327
|
+
onResponseFinalized: import_zod5.z.custom((value) => typeof value === "function").optional(),
|
|
7104
7328
|
limits: import_core5.ExecutionLimitsSchema.optional(),
|
|
7105
7329
|
abortSignal: import_zod5.z.custom((value) => value instanceof AbortSignal).optional(),
|
|
7106
7330
|
sessionId: import_zod5.z.string().optional(),
|
|
@@ -7247,6 +7471,9 @@ function createAgent(args) {
|
|
|
7247
7471
|
abortSignal: parsedOptions?.abortSignal,
|
|
7248
7472
|
executionSignal: parsedOptions?.executionSignal,
|
|
7249
7473
|
onExecution: parsedOptions?.onExecution,
|
|
7474
|
+
clientTurnId: parsedOptions?.clientTurnId,
|
|
7475
|
+
continueOnDisconnect: parsedOptions?.continueOnDisconnect,
|
|
7476
|
+
onResponseFinalized: parsedOptions?.onResponseFinalized,
|
|
7250
7477
|
options: parsedOptions,
|
|
7251
7478
|
workflowRegistry: registry,
|
|
7252
7479
|
...knownWorkflowIds ? { knownWorkflowIds } : {},
|
|
@@ -7403,6 +7630,7 @@ function createAgent(args) {
|
|
|
7403
7630
|
}
|
|
7404
7631
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7405
7632
|
0 && (module.exports = {
|
|
7633
|
+
ChatLifecycleHookError,
|
|
7406
7634
|
ExecutionRequestError,
|
|
7407
7635
|
createAgent,
|
|
7408
7636
|
createChatRouteHandler,
|