@contractspec/lib.ai-agent 7.0.10 → 8.0.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/README.md +45 -4
- package/dist/agent/agent-factory.d.ts +14 -3
- package/dist/agent/agent-factory.js +653 -113
- package/dist/agent/contract-spec-agent.d.ts +16 -2
- package/dist/agent/contract-spec-agent.js +649 -112
- package/dist/agent/index.js +660 -118
- package/dist/agent/json-runner.d.ts +1 -1
- package/dist/agent/json-runner.js +649 -112
- package/dist/agent/unified-agent.d.ts +2 -2
- package/dist/agent/unified-agent.js +660 -118
- package/dist/approval/index.js +6 -1
- package/dist/approval/workflow.js +5 -1
- package/dist/exporters/claude-agent-exporter.d.ts +1 -1
- package/dist/exporters/claude-agent-exporter.js +3 -51
- package/dist/exporters/index.js +8 -54
- package/dist/exporters/opencode-exporter.d.ts +1 -1
- package/dist/exporters/opencode-exporter.js +3 -51
- package/dist/exporters/types.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3805 -71
- package/dist/interop/index.js +3 -51
- package/dist/interop/spec-consumer.d.ts +1 -1
- package/dist/interop/spec-consumer.js +3 -51
- package/dist/interop/tool-consumer.d.ts +1 -1
- package/dist/interop/types.d.ts +1 -1
- package/dist/knowledge/injector.d.ts +1 -1
- package/dist/node/agent/agent-factory.js +653 -113
- package/dist/node/agent/contract-spec-agent.js +649 -112
- package/dist/node/agent/index.js +660 -118
- package/dist/node/agent/json-runner.js +649 -112
- package/dist/node/agent/unified-agent.js +660 -118
- package/dist/node/approval/index.js +6 -1
- package/dist/node/approval/workflow.js +5 -1
- package/dist/node/exporters/claude-agent-exporter.js +3 -51
- package/dist/node/exporters/index.js +8 -54
- package/dist/node/exporters/opencode-exporter.js +3 -51
- package/dist/node/index.js +3805 -71
- package/dist/node/interop/index.js +3 -51
- package/dist/node/interop/spec-consumer.js +3 -51
- package/dist/node/providers/claude-agent-sdk/adapter.js +3 -51
- package/dist/node/providers/claude-agent-sdk/index.js +3 -51
- package/dist/node/providers/index.js +8 -53
- package/dist/node/providers/opencode-sdk/adapter.js +4 -51
- package/dist/node/providers/opencode-sdk/index.js +4 -51
- package/dist/node/telemetry/adapter.js +2 -0
- package/dist/node/telemetry/index.js +2 -0
- package/dist/providers/claude-agent-sdk/adapter.d.ts +1 -1
- package/dist/providers/claude-agent-sdk/adapter.js +3 -51
- package/dist/providers/claude-agent-sdk/index.js +3 -51
- package/dist/providers/claude-agent-sdk/tool-bridge.d.ts +1 -8
- package/dist/providers/index.js +8 -53
- package/dist/providers/opencode-sdk/adapter.d.ts +1 -13
- package/dist/providers/opencode-sdk/adapter.js +4 -51
- package/dist/providers/opencode-sdk/agent-bridge.d.ts +1 -10
- package/dist/providers/opencode-sdk/index.js +4 -51
- package/dist/providers/opencode-sdk/tool-bridge.d.ts +1 -4
- package/dist/providers/types.d.ts +1 -8
- package/dist/session/store.d.ts +2 -2
- package/dist/telemetry/adapter.d.ts +1 -0
- package/dist/telemetry/adapter.js +2 -0
- package/dist/telemetry/index.js +2 -0
- package/dist/tools/knowledge-tool.d.ts +1 -1
- package/dist/tools/mcp-server.d.ts +1 -1
- package/dist/tools/operation-tool-handler.d.ts +1 -1
- package/dist/tools/tool-adapter.d.ts +1 -1
- package/dist/types.d.ts +13 -0
- package/package.json +7 -43
- package/dist/node/spec/index.js +0 -2233
- package/dist/node/spec/registry.js +0 -2178
- package/dist/node/spec/spec.js +0 -2188
- package/dist/spec/index.d.ts +0 -2
- package/dist/spec/index.js +0 -2233
- package/dist/spec/registry.d.ts +0 -41
- package/dist/spec/registry.js +0 -2178
- package/dist/spec/spec.d.ts +0 -218
- package/dist/spec/spec.js +0 -2188
- package/dist/spec/spec.test.d.ts +0 -1
|
@@ -2131,6 +2131,148 @@ var init_i18n = __esm(() => {
|
|
|
2131
2131
|
init_messages();
|
|
2132
2132
|
});
|
|
2133
2133
|
|
|
2134
|
+
// src/approval/workflow.ts
|
|
2135
|
+
import { randomUUID } from "node:crypto";
|
|
2136
|
+
|
|
2137
|
+
class InMemoryApprovalStore {
|
|
2138
|
+
items = new Map;
|
|
2139
|
+
maxItems;
|
|
2140
|
+
constructor(options = {}) {
|
|
2141
|
+
this.maxItems = options.maxItems ?? 1000;
|
|
2142
|
+
}
|
|
2143
|
+
async create(request) {
|
|
2144
|
+
this.evictIfNeeded();
|
|
2145
|
+
this.items.set(request.id, request);
|
|
2146
|
+
}
|
|
2147
|
+
async get(id) {
|
|
2148
|
+
return this.items.get(id) ?? null;
|
|
2149
|
+
}
|
|
2150
|
+
async getByToolCallId(toolCallId) {
|
|
2151
|
+
for (const request of this.items.values()) {
|
|
2152
|
+
if (request.toolCallId === toolCallId) {
|
|
2153
|
+
return request;
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
return null;
|
|
2157
|
+
}
|
|
2158
|
+
async update(id, updates) {
|
|
2159
|
+
const existing = this.items.get(id);
|
|
2160
|
+
if (existing) {
|
|
2161
|
+
this.items.set(id, { ...existing, ...updates });
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
async list(options) {
|
|
2165
|
+
let results = [...this.items.values()];
|
|
2166
|
+
if (options?.status) {
|
|
2167
|
+
results = results.filter((r) => r.status === options.status);
|
|
2168
|
+
}
|
|
2169
|
+
if (options?.agentId) {
|
|
2170
|
+
results = results.filter((r) => r.agentId === options.agentId);
|
|
2171
|
+
}
|
|
2172
|
+
if (options?.tenantId) {
|
|
2173
|
+
results = results.filter((r) => r.tenantId === options.tenantId);
|
|
2174
|
+
}
|
|
2175
|
+
return results.sort((a, b) => b.requestedAt.getTime() - a.requestedAt.getTime());
|
|
2176
|
+
}
|
|
2177
|
+
clear() {
|
|
2178
|
+
this.items.clear();
|
|
2179
|
+
}
|
|
2180
|
+
evictIfNeeded() {
|
|
2181
|
+
if (this.items.size < this.maxItems) {
|
|
2182
|
+
return;
|
|
2183
|
+
}
|
|
2184
|
+
let oldestId = null;
|
|
2185
|
+
let oldestTimestamp = Number.POSITIVE_INFINITY;
|
|
2186
|
+
for (const [id, request] of this.items.entries()) {
|
|
2187
|
+
const ts = request.requestedAt.getTime();
|
|
2188
|
+
if (ts < oldestTimestamp) {
|
|
2189
|
+
oldestTimestamp = ts;
|
|
2190
|
+
oldestId = id;
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
if (oldestId) {
|
|
2194
|
+
this.items.delete(oldestId);
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
class ApprovalWorkflow {
|
|
2200
|
+
store;
|
|
2201
|
+
constructor(store = new InMemoryApprovalStore) {
|
|
2202
|
+
this.store = store;
|
|
2203
|
+
}
|
|
2204
|
+
async requestApproval(params) {
|
|
2205
|
+
const request = {
|
|
2206
|
+
id: randomUUID(),
|
|
2207
|
+
sessionId: params.sessionId,
|
|
2208
|
+
agentId: params.agentId,
|
|
2209
|
+
tenantId: params.tenantId,
|
|
2210
|
+
toolName: params.toolName,
|
|
2211
|
+
toolCallId: params.toolCallId,
|
|
2212
|
+
toolArgs: params.toolArgs,
|
|
2213
|
+
reason: params.reason,
|
|
2214
|
+
requestedAt: new Date,
|
|
2215
|
+
status: "pending",
|
|
2216
|
+
payload: params.payload
|
|
2217
|
+
};
|
|
2218
|
+
await this.store.create(request);
|
|
2219
|
+
return request;
|
|
2220
|
+
}
|
|
2221
|
+
async requestApprovalFromToolCall(toolCall, context) {
|
|
2222
|
+
return this.requestApproval({
|
|
2223
|
+
sessionId: context.sessionId,
|
|
2224
|
+
agentId: context.agentId,
|
|
2225
|
+
tenantId: context.tenantId,
|
|
2226
|
+
toolName: toolCall.toolName,
|
|
2227
|
+
toolCallId: toolCall.toolCallId,
|
|
2228
|
+
toolArgs: toolCall.args,
|
|
2229
|
+
reason: context.reason ?? createAgentI18n(context.locale).t("approval.toolRequiresApproval", {
|
|
2230
|
+
name: toolCall.toolName
|
|
2231
|
+
})
|
|
2232
|
+
});
|
|
2233
|
+
}
|
|
2234
|
+
async approve(id, reviewer, notes) {
|
|
2235
|
+
await this.store.update(id, {
|
|
2236
|
+
status: "approved",
|
|
2237
|
+
reviewer,
|
|
2238
|
+
resolvedAt: new Date,
|
|
2239
|
+
notes
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
async reject(id, reviewer, notes) {
|
|
2243
|
+
await this.store.update(id, {
|
|
2244
|
+
status: "rejected",
|
|
2245
|
+
reviewer,
|
|
2246
|
+
resolvedAt: new Date,
|
|
2247
|
+
notes
|
|
2248
|
+
});
|
|
2249
|
+
}
|
|
2250
|
+
async getStatus(toolCallId) {
|
|
2251
|
+
const request = await this.store.getByToolCallId(toolCallId);
|
|
2252
|
+
return request?.status ?? null;
|
|
2253
|
+
}
|
|
2254
|
+
async isApproved(toolCallId) {
|
|
2255
|
+
const status = await this.getStatus(toolCallId);
|
|
2256
|
+
return status === "approved";
|
|
2257
|
+
}
|
|
2258
|
+
async listPending(options) {
|
|
2259
|
+
return this.store.list({ ...options, status: "pending" });
|
|
2260
|
+
}
|
|
2261
|
+
async get(id) {
|
|
2262
|
+
return this.store.get(id);
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
function createApprovalWorkflow(store) {
|
|
2266
|
+
if (store && typeof store === "object" && "create" in store && typeof store.create === "function") {
|
|
2267
|
+
return new ApprovalWorkflow(store);
|
|
2268
|
+
}
|
|
2269
|
+
const options = store;
|
|
2270
|
+
return new ApprovalWorkflow(new InMemoryApprovalStore(options));
|
|
2271
|
+
}
|
|
2272
|
+
var init_workflow = __esm(() => {
|
|
2273
|
+
init_i18n();
|
|
2274
|
+
});
|
|
2275
|
+
|
|
2134
2276
|
// src/knowledge/injector.ts
|
|
2135
2277
|
async function injectStaticKnowledge(instructions, knowledgeRefs, retriever, locale) {
|
|
2136
2278
|
if (!retriever)
|
|
@@ -2317,56 +2459,6 @@ function generateSessionId() {
|
|
|
2317
2459
|
return `sess_${createSecureSessionToken()}`;
|
|
2318
2460
|
}
|
|
2319
2461
|
|
|
2320
|
-
// src/spec/spec.ts
|
|
2321
|
-
function defineAgent(spec) {
|
|
2322
|
-
const i18n = createAgentI18n(spec.locale);
|
|
2323
|
-
if (!spec.meta?.key) {
|
|
2324
|
-
throw new Error(i18n.t("error.agentKeyRequired"));
|
|
2325
|
-
}
|
|
2326
|
-
if (typeof spec.meta.version !== "string") {
|
|
2327
|
-
throw new Error(i18n.t("error.agentMissingVersion", { key: spec.meta.key }));
|
|
2328
|
-
}
|
|
2329
|
-
if (!spec.instructions?.trim()) {
|
|
2330
|
-
throw new Error(i18n.t("error.agentRequiresInstructions", { key: spec.meta.key }));
|
|
2331
|
-
}
|
|
2332
|
-
if (!spec.tools?.length) {
|
|
2333
|
-
throw new Error(i18n.t("error.agentRequiresTool", { key: spec.meta.key }));
|
|
2334
|
-
}
|
|
2335
|
-
for (const [portName, portRef] of Object.entries(spec.runtime?.ports ?? {})) {
|
|
2336
|
-
if (portRef !== undefined && portRef.trim().length === 0) {
|
|
2337
|
-
throw new Error(`Agent ${spec.meta.key} has invalid runtime config: port "${portName}" must not be empty`);
|
|
2338
|
-
}
|
|
2339
|
-
}
|
|
2340
|
-
const toolNames = new Set;
|
|
2341
|
-
for (const tool of spec.tools) {
|
|
2342
|
-
if (toolNames.has(tool.name)) {
|
|
2343
|
-
throw new Error(i18n.t("error.agentDuplicateTool", {
|
|
2344
|
-
key: spec.meta.key,
|
|
2345
|
-
name: tool.name
|
|
2346
|
-
}));
|
|
2347
|
-
}
|
|
2348
|
-
toolNames.add(tool.name);
|
|
2349
|
-
if (tool.subagentRef && tool.operationRef) {
|
|
2350
|
-
throw new Error(`Agent ${spec.meta.key} tool "${tool.name}" cannot have both subagentRef and operationRef. Use one.`);
|
|
2351
|
-
}
|
|
2352
|
-
const outputRefCount = [
|
|
2353
|
-
tool.outputPresentation,
|
|
2354
|
-
tool.outputForm,
|
|
2355
|
-
tool.outputDataView
|
|
2356
|
-
].filter(Boolean).length;
|
|
2357
|
-
if (outputRefCount > 1) {
|
|
2358
|
-
throw new Error(`Agent ${spec.meta.key} tool "${tool.name}" has multiple output refs (outputPresentation, outputForm, outputDataView). Use at most one.`);
|
|
2359
|
-
}
|
|
2360
|
-
}
|
|
2361
|
-
return Object.freeze(spec);
|
|
2362
|
-
}
|
|
2363
|
-
function agentKey(meta) {
|
|
2364
|
-
return `${meta.key}.v${meta.version}`;
|
|
2365
|
-
}
|
|
2366
|
-
var init_spec = __esm(() => {
|
|
2367
|
-
init_i18n();
|
|
2368
|
-
});
|
|
2369
|
-
|
|
2370
2462
|
// src/telemetry/adapter.ts
|
|
2371
2463
|
function parseAgentId(agentId) {
|
|
2372
2464
|
const match = agentId.match(/^(.+)\.v(\d+)$/);
|
|
@@ -2434,6 +2526,7 @@ async function trackAgentStep(collector, agentId, step, durationMs, context) {
|
|
|
2434
2526
|
agentId,
|
|
2435
2527
|
actorId: context?.actorId,
|
|
2436
2528
|
tenantId: context?.tenantId,
|
|
2529
|
+
workflowId: context?.workflowId,
|
|
2437
2530
|
stepIndex: context?.stepIndex,
|
|
2438
2531
|
toolName: toolCall.toolName,
|
|
2439
2532
|
toolCallArgs: toolCall.input,
|
|
@@ -2459,6 +2552,7 @@ async function trackAgentStep(collector, agentId, step, durationMs, context) {
|
|
|
2459
2552
|
agentId,
|
|
2460
2553
|
actorId: context?.actorId,
|
|
2461
2554
|
tenantId: context?.tenantId,
|
|
2555
|
+
workflowId: context?.workflowId,
|
|
2462
2556
|
stepIndex: context?.stepIndex,
|
|
2463
2557
|
stepStartedAt: context?.stepStartedAt,
|
|
2464
2558
|
finishReason: step.finishReason,
|
|
@@ -3377,7 +3471,10 @@ var exports_contract_spec_agent = {};
|
|
|
3377
3471
|
__export(exports_contract_spec_agent, {
|
|
3378
3472
|
ContractSpecAgent: () => ContractSpecAgent
|
|
3379
3473
|
});
|
|
3380
|
-
import { randomUUID } from "node:crypto";
|
|
3474
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
3475
|
+
import {
|
|
3476
|
+
agentKey
|
|
3477
|
+
} from "@contractspec/lib.contracts-spec/agent";
|
|
3381
3478
|
import {
|
|
3382
3479
|
stepCountIs,
|
|
3383
3480
|
Experimental_Agent as ToolLoopAgent
|
|
@@ -3402,7 +3499,10 @@ class ContractSpecAgent {
|
|
|
3402
3499
|
this.mcpCleanup = mcpCleanup;
|
|
3403
3500
|
}
|
|
3404
3501
|
static async create(config) {
|
|
3405
|
-
const effectiveConfig =
|
|
3502
|
+
const effectiveConfig = {
|
|
3503
|
+
...config,
|
|
3504
|
+
approvalWorkflow: config.approvalWorkflow ?? (config.spec.policy?.escalation?.approvalWorkflow ? createApprovalWorkflow() : undefined)
|
|
3505
|
+
};
|
|
3406
3506
|
let mcpToolset = null;
|
|
3407
3507
|
if ((effectiveConfig.mcpServers?.length ?? 0) > 0) {
|
|
3408
3508
|
mcpToolset = await createMcpToolsets(effectiveConfig.mcpServers ?? [], {
|
|
@@ -3455,34 +3555,27 @@ class ContractSpecAgent {
|
|
|
3455
3555
|
}
|
|
3456
3556
|
async generate(params) {
|
|
3457
3557
|
const sessionId = params.options?.sessionId ?? generateSessionId();
|
|
3458
|
-
const traceId = params.options?.metadata?.["traceId"] ?? this.config.posthogConfig?.tracingOptions?.posthogTraceId ??
|
|
3558
|
+
const traceId = params.options?.metadata?.["traceId"] ?? this.config.posthogConfig?.tracingOptions?.posthogTraceId ?? randomUUID2();
|
|
3559
|
+
const workflowId = params.options?.workflowId ?? params.options?.metadata?.["workflowId"];
|
|
3560
|
+
const threadId = params.options?.threadId ?? params.options?.metadata?.["threadId"];
|
|
3561
|
+
const runtimeAdapter = this.resolveRuntimeAdapter();
|
|
3459
3562
|
this.activeStepContexts.set(sessionId, {
|
|
3460
3563
|
traceId,
|
|
3461
3564
|
tenantId: params.options?.tenantId,
|
|
3462
3565
|
actorId: params.options?.actorId,
|
|
3566
|
+
workflowId,
|
|
3567
|
+
threadId,
|
|
3463
3568
|
stepIndex: 0,
|
|
3464
3569
|
stepStartedAt: new Date
|
|
3465
3570
|
});
|
|
3466
|
-
if (
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
tenantId: params.options?.tenantId,
|
|
3473
|
-
actorId: params.options?.actorId,
|
|
3474
|
-
status: "running",
|
|
3475
|
-
messages: [],
|
|
3476
|
-
steps: [],
|
|
3477
|
-
metadata: params.options?.metadata
|
|
3478
|
-
});
|
|
3479
|
-
} else if (existing.status !== "running") {
|
|
3480
|
-
await this.config.sessionStore.update(sessionId, { status: "running" });
|
|
3481
|
-
}
|
|
3482
|
-
await this.config.sessionStore.appendMessage(sessionId, {
|
|
3483
|
-
role: "user",
|
|
3484
|
-
content: params.prompt ?? ""
|
|
3571
|
+
if (!params.messages?.length) {
|
|
3572
|
+
await this.ensureSession({
|
|
3573
|
+
sessionId,
|
|
3574
|
+
prompt: params.prompt ?? "",
|
|
3575
|
+
options: params.options,
|
|
3576
|
+
traceId
|
|
3485
3577
|
});
|
|
3578
|
+
await this.runSessionMiddleware(sessionId, runtimeAdapter?.middleware?.beforeModel);
|
|
3486
3579
|
}
|
|
3487
3580
|
const model = await this.resolveModelForCall({
|
|
3488
3581
|
sessionId,
|
|
@@ -3497,6 +3590,8 @@ class ContractSpecAgent {
|
|
|
3497
3590
|
tenantId: params.options?.tenantId,
|
|
3498
3591
|
actorId: params.options?.actorId,
|
|
3499
3592
|
sessionId,
|
|
3593
|
+
workflowId,
|
|
3594
|
+
threadId,
|
|
3500
3595
|
metadata: params.options?.metadata
|
|
3501
3596
|
}
|
|
3502
3597
|
};
|
|
@@ -3519,26 +3614,94 @@ ${params.prompt}` : params.prompt ?? "";
|
|
|
3519
3614
|
});
|
|
3520
3615
|
}
|
|
3521
3616
|
} catch (error) {
|
|
3617
|
+
const executionError = toAgentExecutionError(error);
|
|
3522
3618
|
if (this.config.sessionStore) {
|
|
3523
3619
|
await this.config.sessionStore.update(sessionId, {
|
|
3524
|
-
status: "failed"
|
|
3620
|
+
status: "failed",
|
|
3621
|
+
traceId,
|
|
3622
|
+
workflowId,
|
|
3623
|
+
threadId,
|
|
3624
|
+
lastError: executionError
|
|
3525
3625
|
});
|
|
3626
|
+
await this.syncSessionCheckpoint(sessionId);
|
|
3526
3627
|
}
|
|
3628
|
+
await this.emitAgentEvent("agent.failed", {
|
|
3629
|
+
sessionId,
|
|
3630
|
+
tenantId: params.options?.tenantId,
|
|
3631
|
+
workflowId,
|
|
3632
|
+
traceId,
|
|
3633
|
+
metadata: {
|
|
3634
|
+
error: executionError.message,
|
|
3635
|
+
code: executionError.code ?? executionError.kind
|
|
3636
|
+
}
|
|
3637
|
+
});
|
|
3527
3638
|
this.activeStepContexts.delete(sessionId);
|
|
3528
3639
|
throw error;
|
|
3529
3640
|
}
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3641
|
+
if (!params.messages?.length) {
|
|
3642
|
+
await this.runSessionMiddleware(sessionId, runtimeAdapter?.middleware?.afterModel);
|
|
3643
|
+
}
|
|
3644
|
+
let pendingApproval = this.activeStepContexts.get(sessionId)?.pendingApproval;
|
|
3645
|
+
const escalationError = pendingApproval ? undefined : resolveEscalationError(this.spec, result.finishReason);
|
|
3646
|
+
if (this.config.sessionStore && result.text.trim().length > 0) {
|
|
3647
|
+
const currentSession = await this.config.sessionStore.get(sessionId);
|
|
3648
|
+
const lastMessage = currentSession?.messages.at(-1);
|
|
3649
|
+
const lastContent = lastMessage && "content" in lastMessage ? lastMessage.content : undefined;
|
|
3650
|
+
if (lastMessage?.role !== "assistant" || lastContent !== result.text) {
|
|
3651
|
+
await this.config.sessionStore.appendMessage(sessionId, {
|
|
3652
|
+
role: "assistant",
|
|
3653
|
+
content: result.text
|
|
3654
|
+
});
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
if (!pendingApproval && escalationError) {
|
|
3658
|
+
pendingApproval = await this.requestApproval(sessionId, {
|
|
3659
|
+
toolName: this.spec.policy?.escalation?.approvalWorkflow ?? "approval_required",
|
|
3660
|
+
toolCallId: `approval_${sessionId}`,
|
|
3661
|
+
args: {
|
|
3662
|
+
finishReason: result.finishReason,
|
|
3663
|
+
threshold: this.spec.policy?.escalation?.confidenceThreshold ?? this.spec.policy?.confidence?.min
|
|
3664
|
+
},
|
|
3665
|
+
reason: escalationError.message,
|
|
3666
|
+
error: escalationError
|
|
3536
3667
|
});
|
|
3668
|
+
}
|
|
3669
|
+
const finalStatus = pendingApproval ? "escalated" : "completed";
|
|
3670
|
+
if (this.config.sessionStore) {
|
|
3537
3671
|
await this.config.sessionStore.update(sessionId, {
|
|
3538
|
-
status:
|
|
3672
|
+
status: finalStatus,
|
|
3673
|
+
traceId,
|
|
3674
|
+
workflowId,
|
|
3675
|
+
threadId,
|
|
3676
|
+
pendingApprovalRequestId: pendingApproval?.id,
|
|
3677
|
+
lastError: pendingApproval ? escalationError : undefined
|
|
3678
|
+
});
|
|
3679
|
+
await this.syncSessionCheckpoint(sessionId);
|
|
3680
|
+
}
|
|
3681
|
+
if (pendingApproval) {
|
|
3682
|
+
await this.emitAgentEvent("agent.escalated", {
|
|
3683
|
+
sessionId,
|
|
3684
|
+
tenantId: params.options?.tenantId,
|
|
3685
|
+
workflowId,
|
|
3686
|
+
traceId,
|
|
3687
|
+
metadata: {
|
|
3688
|
+
approvalRequestId: pendingApproval.id,
|
|
3689
|
+
reason: pendingApproval.reason
|
|
3690
|
+
}
|
|
3691
|
+
});
|
|
3692
|
+
} else {
|
|
3693
|
+
await this.emitAgentEvent("agent.completed", {
|
|
3694
|
+
sessionId,
|
|
3695
|
+
tenantId: params.options?.tenantId,
|
|
3696
|
+
workflowId,
|
|
3697
|
+
traceId,
|
|
3698
|
+
metadata: {
|
|
3699
|
+
finishReason: result.finishReason
|
|
3700
|
+
}
|
|
3539
3701
|
});
|
|
3540
3702
|
}
|
|
3541
3703
|
const session = this.config.sessionStore ? await this.config.sessionStore.get(sessionId) : null;
|
|
3704
|
+
this.activeStepContexts.delete(sessionId);
|
|
3542
3705
|
return {
|
|
3543
3706
|
text: result.text,
|
|
3544
3707
|
steps: result.steps,
|
|
@@ -3557,23 +3720,25 @@ ${params.prompt}` : params.prompt ?? "";
|
|
|
3557
3720
|
finishReason: result.finishReason,
|
|
3558
3721
|
usage: result.usage,
|
|
3559
3722
|
session: session ?? undefined,
|
|
3560
|
-
pendingApproval:
|
|
3561
|
-
toolName:
|
|
3562
|
-
toolCallId:
|
|
3563
|
-
args:
|
|
3564
|
-
reason: escalationError.message,
|
|
3565
|
-
code: escalationError.code
|
|
3566
|
-
}
|
|
3723
|
+
pendingApproval: pendingApproval ? {
|
|
3724
|
+
toolName: pendingApproval.toolName,
|
|
3725
|
+
toolCallId: pendingApproval.toolCallId,
|
|
3726
|
+
args: pendingApproval.toolArgs
|
|
3567
3727
|
} : undefined
|
|
3568
3728
|
};
|
|
3569
3729
|
}
|
|
3570
3730
|
async stream(params) {
|
|
3571
3731
|
const sessionId = params.options?.sessionId ?? generateSessionId();
|
|
3572
|
-
const traceId = params.options?.metadata?.["traceId"] ?? this.config.posthogConfig?.tracingOptions?.posthogTraceId ??
|
|
3732
|
+
const traceId = params.options?.metadata?.["traceId"] ?? this.config.posthogConfig?.tracingOptions?.posthogTraceId ?? randomUUID2();
|
|
3733
|
+
const workflowId = params.options?.workflowId ?? params.options?.metadata?.["workflowId"];
|
|
3734
|
+
const threadId = params.options?.threadId ?? params.options?.metadata?.["threadId"];
|
|
3735
|
+
const runtimeAdapter = this.resolveRuntimeAdapter();
|
|
3573
3736
|
this.activeStepContexts.set(sessionId, {
|
|
3574
3737
|
traceId,
|
|
3575
3738
|
tenantId: params.options?.tenantId,
|
|
3576
3739
|
actorId: params.options?.actorId,
|
|
3740
|
+
workflowId,
|
|
3741
|
+
threadId,
|
|
3577
3742
|
stepIndex: 0,
|
|
3578
3743
|
stepStartedAt: new Date
|
|
3579
3744
|
});
|
|
@@ -3582,6 +3747,13 @@ ${params.prompt}` : params.prompt ?? "";
|
|
|
3582
3747
|
${params.systemOverride}
|
|
3583
3748
|
|
|
3584
3749
|
${params.prompt}` : params.prompt ?? "";
|
|
3750
|
+
await this.ensureSession({
|
|
3751
|
+
sessionId,
|
|
3752
|
+
prompt,
|
|
3753
|
+
options: params.options,
|
|
3754
|
+
traceId
|
|
3755
|
+
});
|
|
3756
|
+
await this.runSessionMiddleware(sessionId, runtimeAdapter?.middleware?.beforeModel);
|
|
3585
3757
|
const model = await this.resolveModelForCall({
|
|
3586
3758
|
sessionId,
|
|
3587
3759
|
traceId,
|
|
@@ -3589,26 +3761,6 @@ ${params.prompt}` : params.prompt ?? "";
|
|
|
3589
3761
|
});
|
|
3590
3762
|
const effectiveMaxSteps = resolveMaxSteps(params.maxSteps, this.spec.maxSteps);
|
|
3591
3763
|
const inner = this.createInnerAgent(model, effectiveMaxSteps);
|
|
3592
|
-
if (this.config.sessionStore) {
|
|
3593
|
-
const existing = await this.config.sessionStore.get(sessionId);
|
|
3594
|
-
if (!existing) {
|
|
3595
|
-
await this.config.sessionStore.create({
|
|
3596
|
-
sessionId,
|
|
3597
|
-
agentId: this.id,
|
|
3598
|
-
tenantId: params.options?.tenantId,
|
|
3599
|
-
actorId: params.options?.actorId,
|
|
3600
|
-
status: "running",
|
|
3601
|
-
messages: [],
|
|
3602
|
-
steps: [],
|
|
3603
|
-
metadata: params.options?.metadata
|
|
3604
|
-
});
|
|
3605
|
-
}
|
|
3606
|
-
await this.config.sessionStore.appendMessage(sessionId, {
|
|
3607
|
-
role: "user",
|
|
3608
|
-
content: prompt
|
|
3609
|
-
});
|
|
3610
|
-
await this.config.sessionStore.update(sessionId, { status: "running" });
|
|
3611
|
-
}
|
|
3612
3764
|
return inner.stream({
|
|
3613
3765
|
prompt,
|
|
3614
3766
|
abortSignal: params.signal,
|
|
@@ -3616,21 +3768,92 @@ ${params.prompt}` : params.prompt ?? "";
|
|
|
3616
3768
|
tenantId: params.options?.tenantId,
|
|
3617
3769
|
actorId: params.options?.actorId,
|
|
3618
3770
|
sessionId,
|
|
3771
|
+
workflowId,
|
|
3772
|
+
threadId,
|
|
3619
3773
|
metadata: params.options?.metadata
|
|
3620
3774
|
}
|
|
3621
3775
|
});
|
|
3622
3776
|
}
|
|
3623
3777
|
async handleStepFinish(step) {
|
|
3624
3778
|
const sessionId = step.options?.sessionId;
|
|
3779
|
+
const context = sessionId ? this.activeStepContexts.get(sessionId) : undefined;
|
|
3625
3780
|
if (sessionId && this.config.sessionStore) {
|
|
3626
3781
|
await this.config.sessionStore.appendStep(sessionId, step);
|
|
3782
|
+
if (step.text.trim().length > 0) {
|
|
3783
|
+
await this.config.sessionStore.appendMessage(sessionId, {
|
|
3784
|
+
role: "assistant",
|
|
3785
|
+
content: step.text
|
|
3786
|
+
});
|
|
3787
|
+
}
|
|
3788
|
+
for (const toolCall of step.toolCalls ?? []) {
|
|
3789
|
+
await this.emitAgentEvent("agent.tool.called", {
|
|
3790
|
+
sessionId,
|
|
3791
|
+
tenantId: context?.tenantId,
|
|
3792
|
+
workflowId: context?.workflowId,
|
|
3793
|
+
traceId: context?.traceId,
|
|
3794
|
+
stepIndex: context?.stepIndex,
|
|
3795
|
+
toolName: toolCall.toolName,
|
|
3796
|
+
metadata: {
|
|
3797
|
+
toolCallId: toolCall.toolCallId
|
|
3798
|
+
}
|
|
3799
|
+
});
|
|
3800
|
+
}
|
|
3801
|
+
for (const toolResult of step.toolResults ?? []) {
|
|
3802
|
+
const toolCall = step.toolCalls?.find((candidate) => candidate.toolCallId === toolResult.toolCallId);
|
|
3803
|
+
const toolError = extractToolExecutionError(toolResult.output);
|
|
3804
|
+
await this.config.sessionStore.appendMessage(sessionId, {
|
|
3805
|
+
role: "tool",
|
|
3806
|
+
content: stringifyToolResult(toolResult.toolName, toolResult.output)
|
|
3807
|
+
});
|
|
3808
|
+
if (toolError) {
|
|
3809
|
+
await this.emitAgentEvent("agent.tool.failed", {
|
|
3810
|
+
sessionId,
|
|
3811
|
+
tenantId: context?.tenantId,
|
|
3812
|
+
workflowId: context?.workflowId,
|
|
3813
|
+
traceId: context?.traceId,
|
|
3814
|
+
stepIndex: context?.stepIndex,
|
|
3815
|
+
toolName: toolResult.toolName,
|
|
3816
|
+
metadata: {
|
|
3817
|
+
toolCallId: toolResult.toolCallId,
|
|
3818
|
+
error: toolError.message,
|
|
3819
|
+
code: toolError.code
|
|
3820
|
+
}
|
|
3821
|
+
});
|
|
3822
|
+
const shouldEscalate = toolError.kind === "timeout" && this.spec.policy?.escalation?.onTimeout || toolError.kind !== "timeout" && this.spec.policy?.escalation?.onToolFailure;
|
|
3823
|
+
if (shouldEscalate && toolCall && !context?.pendingApproval) {
|
|
3824
|
+
await this.requestApproval(sessionId, {
|
|
3825
|
+
toolName: toolCall.toolName,
|
|
3826
|
+
toolCallId: toolCall.toolCallId,
|
|
3827
|
+
args: toolCall.input,
|
|
3828
|
+
reason: toolError.message,
|
|
3829
|
+
error: toolError
|
|
3830
|
+
});
|
|
3831
|
+
}
|
|
3832
|
+
} else {
|
|
3833
|
+
await this.emitAgentEvent("agent.tool.completed", {
|
|
3834
|
+
sessionId,
|
|
3835
|
+
tenantId: context?.tenantId,
|
|
3836
|
+
workflowId: context?.workflowId,
|
|
3837
|
+
traceId: context?.traceId,
|
|
3838
|
+
stepIndex: context?.stepIndex,
|
|
3839
|
+
toolName: toolResult.toolName,
|
|
3840
|
+
metadata: {
|
|
3841
|
+
toolCallId: toolResult.toolCallId
|
|
3842
|
+
}
|
|
3843
|
+
});
|
|
3844
|
+
}
|
|
3845
|
+
}
|
|
3627
3846
|
await this.config.sessionStore.update(sessionId, {
|
|
3628
|
-
status: step.finishReason === "tool-calls" ? "waiting" : "running"
|
|
3847
|
+
status: context?.pendingApproval ? "escalated" : step.finishReason === "tool-calls" ? "waiting" : "running",
|
|
3848
|
+
workflowId: context?.workflowId,
|
|
3849
|
+
threadId: context?.threadId,
|
|
3850
|
+
traceId: context?.traceId,
|
|
3851
|
+
pendingApprovalRequestId: context?.pendingApproval?.id
|
|
3629
3852
|
});
|
|
3853
|
+
await this.syncSessionCheckpoint(sessionId);
|
|
3630
3854
|
}
|
|
3631
3855
|
if (this.config.telemetryCollector) {
|
|
3632
3856
|
const now = new Date;
|
|
3633
|
-
const context = sessionId ? this.activeStepContexts.get(sessionId) : undefined;
|
|
3634
3857
|
const stepStartedAt = context?.stepStartedAt ?? now;
|
|
3635
3858
|
const durationMs = Math.max(now.getTime() - stepStartedAt.getTime(), 0);
|
|
3636
3859
|
if (context) {
|
|
@@ -3641,6 +3864,7 @@ ${params.prompt}` : params.prompt ?? "";
|
|
|
3641
3864
|
sessionId,
|
|
3642
3865
|
tenantId: context?.tenantId,
|
|
3643
3866
|
actorId: context?.actorId,
|
|
3867
|
+
workflowId: context?.workflowId,
|
|
3644
3868
|
traceId: context?.traceId,
|
|
3645
3869
|
stepIndex: context?.stepIndex,
|
|
3646
3870
|
stepStartedAt
|
|
@@ -3650,6 +3874,215 @@ ${params.prompt}` : params.prompt ?? "";
|
|
|
3650
3874
|
}
|
|
3651
3875
|
}
|
|
3652
3876
|
}
|
|
3877
|
+
async ensureSession(params) {
|
|
3878
|
+
if (!this.config.sessionStore) {
|
|
3879
|
+
return;
|
|
3880
|
+
}
|
|
3881
|
+
const runtimeAdapter = this.resolveRuntimeAdapter();
|
|
3882
|
+
let session = await this.config.sessionStore.get(params.sessionId);
|
|
3883
|
+
const previousStatus = session?.status;
|
|
3884
|
+
if (!session && runtimeAdapter?.checkpoint) {
|
|
3885
|
+
const checkpoint = await runtimeAdapter.checkpoint.load(params.sessionId);
|
|
3886
|
+
if (checkpoint) {
|
|
3887
|
+
session = await this.config.sessionStore.create({
|
|
3888
|
+
...omitSessionTimestamps(checkpoint.state),
|
|
3889
|
+
workflowId: params.options?.workflowId ?? checkpoint.state.workflowId,
|
|
3890
|
+
threadId: params.options?.threadId ?? checkpoint.state.threadId,
|
|
3891
|
+
traceId: params.traceId,
|
|
3892
|
+
checkpointId: checkpoint.checkpointId,
|
|
3893
|
+
status: "running",
|
|
3894
|
+
pendingApprovalRequestId: undefined,
|
|
3895
|
+
lastError: undefined,
|
|
3896
|
+
metadata: params.options?.metadata ?? checkpoint.state.metadata
|
|
3897
|
+
});
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
if (!session) {
|
|
3901
|
+
session = await this.config.sessionStore.create({
|
|
3902
|
+
sessionId: params.sessionId,
|
|
3903
|
+
agentId: this.id,
|
|
3904
|
+
tenantId: params.options?.tenantId,
|
|
3905
|
+
actorId: params.options?.actorId,
|
|
3906
|
+
workflowId: params.options?.workflowId,
|
|
3907
|
+
threadId: params.options?.threadId,
|
|
3908
|
+
traceId: params.traceId,
|
|
3909
|
+
status: "running",
|
|
3910
|
+
messages: [],
|
|
3911
|
+
steps: [],
|
|
3912
|
+
metadata: params.options?.metadata
|
|
3913
|
+
});
|
|
3914
|
+
await this.emitAgentEvent("agent.session.created", {
|
|
3915
|
+
sessionId: params.sessionId,
|
|
3916
|
+
tenantId: params.options?.tenantId,
|
|
3917
|
+
workflowId: params.options?.workflowId,
|
|
3918
|
+
traceId: params.traceId
|
|
3919
|
+
});
|
|
3920
|
+
} else {
|
|
3921
|
+
await this.config.sessionStore.update(params.sessionId, {
|
|
3922
|
+
status: "running",
|
|
3923
|
+
workflowId: params.options?.workflowId ?? session.workflowId,
|
|
3924
|
+
threadId: params.options?.threadId ?? session.threadId,
|
|
3925
|
+
traceId: params.traceId,
|
|
3926
|
+
metadata: params.options?.metadata ?? session.metadata,
|
|
3927
|
+
pendingApprovalRequestId: undefined,
|
|
3928
|
+
lastError: undefined
|
|
3929
|
+
});
|
|
3930
|
+
await this.emitAgentEvent("agent.session.updated", {
|
|
3931
|
+
sessionId: params.sessionId,
|
|
3932
|
+
tenantId: params.options?.tenantId ?? session.tenantId,
|
|
3933
|
+
workflowId: params.options?.workflowId ?? session.workflowId,
|
|
3934
|
+
traceId: params.traceId,
|
|
3935
|
+
metadata: {
|
|
3936
|
+
previousStatus: previousStatus ?? "idle",
|
|
3937
|
+
nextStatus: "running"
|
|
3938
|
+
}
|
|
3939
|
+
});
|
|
3940
|
+
}
|
|
3941
|
+
await this.config.sessionStore.appendMessage(params.sessionId, {
|
|
3942
|
+
role: "user",
|
|
3943
|
+
content: params.prompt
|
|
3944
|
+
});
|
|
3945
|
+
if (runtimeAdapter?.suspendResume && (previousStatus === "waiting" || previousStatus === "escalated")) {
|
|
3946
|
+
await runtimeAdapter.suspendResume.resume({
|
|
3947
|
+
sessionId: params.sessionId,
|
|
3948
|
+
input: params.prompt,
|
|
3949
|
+
metadata: compactStringRecord({
|
|
3950
|
+
traceId: params.traceId,
|
|
3951
|
+
workflowId: params.options?.workflowId,
|
|
3952
|
+
threadId: params.options?.threadId
|
|
3953
|
+
})
|
|
3954
|
+
});
|
|
3955
|
+
}
|
|
3956
|
+
await this.syncSessionCheckpoint(params.sessionId);
|
|
3957
|
+
}
|
|
3958
|
+
resolveRuntimeAdapter() {
|
|
3959
|
+
return resolveRuntimeAdapterBundle(this.spec, this.config.runtimeAdapters);
|
|
3960
|
+
}
|
|
3961
|
+
async syncSessionCheckpoint(sessionId) {
|
|
3962
|
+
if (!this.config.sessionStore) {
|
|
3963
|
+
return null;
|
|
3964
|
+
}
|
|
3965
|
+
const runtimeAdapter = this.resolveRuntimeAdapter();
|
|
3966
|
+
const session = await this.config.sessionStore.get(sessionId);
|
|
3967
|
+
if (!runtimeAdapter?.checkpoint || !session) {
|
|
3968
|
+
return session;
|
|
3969
|
+
}
|
|
3970
|
+
const checkpointId = `${sessionId}:${Date.now()}`;
|
|
3971
|
+
await runtimeAdapter.checkpoint.save({
|
|
3972
|
+
sessionId,
|
|
3973
|
+
threadId: session.threadId,
|
|
3974
|
+
state: session,
|
|
3975
|
+
checkpointId,
|
|
3976
|
+
createdAt: new Date
|
|
3977
|
+
});
|
|
3978
|
+
await this.config.sessionStore.update(sessionId, {
|
|
3979
|
+
checkpointId
|
|
3980
|
+
});
|
|
3981
|
+
return this.config.sessionStore.get(sessionId);
|
|
3982
|
+
}
|
|
3983
|
+
async runSessionMiddleware(sessionId, hook) {
|
|
3984
|
+
if (!hook || !this.config.sessionStore) {
|
|
3985
|
+
return;
|
|
3986
|
+
}
|
|
3987
|
+
const session = await this.config.sessionStore.get(sessionId);
|
|
3988
|
+
if (!session) {
|
|
3989
|
+
return;
|
|
3990
|
+
}
|
|
3991
|
+
const next = await hook(session);
|
|
3992
|
+
if (!next) {
|
|
3993
|
+
return;
|
|
3994
|
+
}
|
|
3995
|
+
await this.config.sessionStore.update(sessionId, {
|
|
3996
|
+
status: next.status,
|
|
3997
|
+
metadata: next.metadata,
|
|
3998
|
+
workflowId: next.workflowId,
|
|
3999
|
+
threadId: next.threadId,
|
|
4000
|
+
traceId: next.traceId,
|
|
4001
|
+
checkpointId: next.checkpointId,
|
|
4002
|
+
pendingApprovalRequestId: next.pendingApprovalRequestId,
|
|
4003
|
+
lastError: next.lastError
|
|
4004
|
+
});
|
|
4005
|
+
await this.syncSessionCheckpoint(sessionId);
|
|
4006
|
+
}
|
|
4007
|
+
async requestApproval(sessionId, params) {
|
|
4008
|
+
const approvalWorkflow = this.config.approvalWorkflow;
|
|
4009
|
+
const context = this.activeStepContexts.get(sessionId);
|
|
4010
|
+
if (!approvalWorkflow || !context || context.pendingApproval) {
|
|
4011
|
+
return context?.pendingApproval;
|
|
4012
|
+
}
|
|
4013
|
+
const request = await approvalWorkflow.requestApproval({
|
|
4014
|
+
sessionId,
|
|
4015
|
+
agentId: this.id,
|
|
4016
|
+
tenantId: context.tenantId,
|
|
4017
|
+
toolName: params.toolName,
|
|
4018
|
+
toolCallId: params.toolCallId,
|
|
4019
|
+
toolArgs: params.args,
|
|
4020
|
+
reason: params.reason,
|
|
4021
|
+
payload: {
|
|
4022
|
+
traceId: context.traceId,
|
|
4023
|
+
workflowId: context.workflowId,
|
|
4024
|
+
threadId: context.threadId,
|
|
4025
|
+
code: params.error?.code
|
|
4026
|
+
}
|
|
4027
|
+
});
|
|
4028
|
+
context.pendingApproval = request;
|
|
4029
|
+
if (this.config.sessionStore) {
|
|
4030
|
+
await this.config.sessionStore.update(sessionId, {
|
|
4031
|
+
status: "escalated",
|
|
4032
|
+
pendingApprovalRequestId: request.id,
|
|
4033
|
+
lastError: params.error
|
|
4034
|
+
});
|
|
4035
|
+
await this.syncSessionCheckpoint(sessionId);
|
|
4036
|
+
}
|
|
4037
|
+
await this.emitAgentEvent("agent.tool.approval_requested", {
|
|
4038
|
+
sessionId,
|
|
4039
|
+
tenantId: context.tenantId,
|
|
4040
|
+
workflowId: context.workflowId,
|
|
4041
|
+
traceId: context.traceId,
|
|
4042
|
+
stepIndex: context.stepIndex,
|
|
4043
|
+
toolName: params.toolName,
|
|
4044
|
+
metadata: {
|
|
4045
|
+
approvalRequestId: request.id,
|
|
4046
|
+
toolCallId: params.toolCallId,
|
|
4047
|
+
reason: params.reason
|
|
4048
|
+
}
|
|
4049
|
+
});
|
|
4050
|
+
await this.emitAgentEvent("agent.escalated", {
|
|
4051
|
+
sessionId,
|
|
4052
|
+
tenantId: context.tenantId,
|
|
4053
|
+
workflowId: context.workflowId,
|
|
4054
|
+
traceId: context.traceId,
|
|
4055
|
+
stepIndex: context.stepIndex,
|
|
4056
|
+
toolName: params.toolName,
|
|
4057
|
+
metadata: {
|
|
4058
|
+
approvalRequestId: request.id,
|
|
4059
|
+
reason: params.reason
|
|
4060
|
+
}
|
|
4061
|
+
});
|
|
4062
|
+
const runtimeAdapter = this.resolveRuntimeAdapter();
|
|
4063
|
+
if (runtimeAdapter?.suspendResume) {
|
|
4064
|
+
await runtimeAdapter.suspendResume.suspend({
|
|
4065
|
+
sessionId,
|
|
4066
|
+
reason: params.reason,
|
|
4067
|
+
metadata: compactStringRecord({
|
|
4068
|
+
traceId: context.traceId,
|
|
4069
|
+
workflowId: context.workflowId,
|
|
4070
|
+
threadId: context.threadId,
|
|
4071
|
+
approvalRequestId: request.id
|
|
4072
|
+
})
|
|
4073
|
+
});
|
|
4074
|
+
}
|
|
4075
|
+
return request;
|
|
4076
|
+
}
|
|
4077
|
+
async emitAgentEvent(event, payload) {
|
|
4078
|
+
if (!this.config.eventEmitter) {
|
|
4079
|
+
return;
|
|
4080
|
+
}
|
|
4081
|
+
await this.config.eventEmitter(event, {
|
|
4082
|
+
agentId: this.id,
|
|
4083
|
+
...payload
|
|
4084
|
+
});
|
|
4085
|
+
}
|
|
3653
4086
|
createInnerAgent(model, maxSteps) {
|
|
3654
4087
|
return new ToolLoopAgent({
|
|
3655
4088
|
model,
|
|
@@ -3679,7 +4112,9 @@ ${params.prompt}` : params.prompt ?? "";
|
|
|
3679
4112
|
contractspec_trace_id: params.traceId,
|
|
3680
4113
|
contractspec_agent_id: this.id,
|
|
3681
4114
|
contractspec_tenant_id: params.options?.tenantId,
|
|
3682
|
-
contractspec_actor_id: params.options?.actorId
|
|
4115
|
+
contractspec_actor_id: params.options?.actorId,
|
|
4116
|
+
contractspec_workflow_id: params.options?.workflowId,
|
|
4117
|
+
contractspec_thread_id: params.options?.threadId
|
|
3683
4118
|
};
|
|
3684
4119
|
const tracingOptions = {
|
|
3685
4120
|
...posthogConfig.tracingOptions,
|
|
@@ -3691,6 +4126,106 @@ ${params.prompt}` : params.prompt ?? "";
|
|
|
3691
4126
|
return createPostHogTracedModel2(this.config.model, posthogConfig, tracingOptions);
|
|
3692
4127
|
}
|
|
3693
4128
|
}
|
|
4129
|
+
function omitSessionTimestamps(session) {
|
|
4130
|
+
const { createdAt: _createdAt, updatedAt: _updatedAt, ...rest } = session;
|
|
4131
|
+
return rest;
|
|
4132
|
+
}
|
|
4133
|
+
function resolveRuntimeAdapterBundle(spec, runtimeAdapters) {
|
|
4134
|
+
if (!runtimeAdapters) {
|
|
4135
|
+
return;
|
|
4136
|
+
}
|
|
4137
|
+
const preferredKeys = [
|
|
4138
|
+
"langgraph",
|
|
4139
|
+
"langchain",
|
|
4140
|
+
"workflow-devkit"
|
|
4141
|
+
];
|
|
4142
|
+
for (const key of preferredKeys) {
|
|
4143
|
+
if (spec.runtime?.capabilities?.adapters?.[key] && runtimeAdapters[key]) {
|
|
4144
|
+
return runtimeAdapters[key];
|
|
4145
|
+
}
|
|
4146
|
+
}
|
|
4147
|
+
for (const key of preferredKeys) {
|
|
4148
|
+
if (runtimeAdapters[key]) {
|
|
4149
|
+
return runtimeAdapters[key];
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4152
|
+
return;
|
|
4153
|
+
}
|
|
4154
|
+
function compactStringRecord(input) {
|
|
4155
|
+
return Object.fromEntries(Object.entries(input).filter((entry) => typeof entry[1] === "string" && entry[1].length > 0));
|
|
4156
|
+
}
|
|
4157
|
+
function toAgentExecutionError(error) {
|
|
4158
|
+
if (error && typeof error === "object" && "kind" in error && typeof error.kind === "string" && "message" in error && typeof error.message === "string") {
|
|
4159
|
+
return {
|
|
4160
|
+
kind: error.kind,
|
|
4161
|
+
message: error.message,
|
|
4162
|
+
code: "code" in error && typeof error.code === "string" ? error.code : undefined,
|
|
4163
|
+
retryAfterMs: "retryAfterMs" in error && typeof error.retryAfterMs === "number" ? error.retryAfterMs : undefined
|
|
4164
|
+
};
|
|
4165
|
+
}
|
|
4166
|
+
if (error instanceof Error) {
|
|
4167
|
+
return {
|
|
4168
|
+
kind: error.message.toLowerCase().includes("timeout") || error.code === "TOOL_EXECUTION_TIMEOUT" ? "timeout" : "fatal",
|
|
4169
|
+
message: error.message,
|
|
4170
|
+
code: error.code
|
|
4171
|
+
};
|
|
4172
|
+
}
|
|
4173
|
+
return {
|
|
4174
|
+
kind: "fatal",
|
|
4175
|
+
message: String(error)
|
|
4176
|
+
};
|
|
4177
|
+
}
|
|
4178
|
+
function extractToolExecutionError(output) {
|
|
4179
|
+
if (!output) {
|
|
4180
|
+
return;
|
|
4181
|
+
}
|
|
4182
|
+
if (typeof output === "string") {
|
|
4183
|
+
if (output.toLowerCase().includes("error")) {
|
|
4184
|
+
return {
|
|
4185
|
+
kind: output.toLowerCase().includes("timeout") ? "timeout" : "retryable",
|
|
4186
|
+
message: output
|
|
4187
|
+
};
|
|
4188
|
+
}
|
|
4189
|
+
return;
|
|
4190
|
+
}
|
|
4191
|
+
if (typeof output !== "object") {
|
|
4192
|
+
return;
|
|
4193
|
+
}
|
|
4194
|
+
const record2 = output;
|
|
4195
|
+
const nestedError = record2["error"];
|
|
4196
|
+
if (nestedError instanceof Error) {
|
|
4197
|
+
return toAgentExecutionError(nestedError);
|
|
4198
|
+
}
|
|
4199
|
+
if (nestedError && typeof nestedError === "object") {
|
|
4200
|
+
return toAgentExecutionError(nestedError);
|
|
4201
|
+
}
|
|
4202
|
+
if (typeof record2["message"] === "string" && typeof record2["kind"] === "string") {
|
|
4203
|
+
return {
|
|
4204
|
+
kind: record2["kind"],
|
|
4205
|
+
message: record2["message"],
|
|
4206
|
+
code: typeof record2["code"] === "string" ? record2["code"] : undefined,
|
|
4207
|
+
retryAfterMs: typeof record2["retryAfterMs"] === "number" ? record2["retryAfterMs"] : undefined
|
|
4208
|
+
};
|
|
4209
|
+
}
|
|
4210
|
+
if (typeof record2["errorMessage"] === "string") {
|
|
4211
|
+
return {
|
|
4212
|
+
kind: typeof record2["errorCode"] === "string" && record2["errorCode"].includes("TIMEOUT") ? "timeout" : "retryable",
|
|
4213
|
+
message: record2["errorMessage"],
|
|
4214
|
+
code: typeof record2["errorCode"] === "string" ? record2["errorCode"] : undefined
|
|
4215
|
+
};
|
|
4216
|
+
}
|
|
4217
|
+
return;
|
|
4218
|
+
}
|
|
4219
|
+
function stringifyToolResult(toolName, output) {
|
|
4220
|
+
if (typeof output === "string") {
|
|
4221
|
+
return `[${toolName}] ${output}`;
|
|
4222
|
+
}
|
|
4223
|
+
try {
|
|
4224
|
+
return `[${toolName}] ${JSON.stringify(output)}`;
|
|
4225
|
+
} catch {
|
|
4226
|
+
return `[${toolName}] [unserializable result]`;
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
3694
4229
|
function resolveMaxSteps(overrideMaxSteps, specMaxSteps) {
|
|
3695
4230
|
const candidate = overrideMaxSteps ?? specMaxSteps ?? 10;
|
|
3696
4231
|
if (!Number.isFinite(candidate)) {
|
|
@@ -3733,8 +4268,8 @@ function resolveEscalationError(spec, finishReason) {
|
|
|
3733
4268
|
}
|
|
3734
4269
|
var ContractSpecCallOptionsSchema;
|
|
3735
4270
|
var init_contract_spec_agent = __esm(() => {
|
|
4271
|
+
init_workflow();
|
|
3736
4272
|
init_injector();
|
|
3737
|
-
init_spec();
|
|
3738
4273
|
init_adapter();
|
|
3739
4274
|
init_knowledge_tool();
|
|
3740
4275
|
init_mcp_client();
|
|
@@ -3744,6 +4279,8 @@ var init_contract_spec_agent = __esm(() => {
|
|
|
3744
4279
|
tenantId: z4.string().optional(),
|
|
3745
4280
|
actorId: z4.string().optional(),
|
|
3746
4281
|
sessionId: z4.string().optional(),
|
|
4282
|
+
workflowId: z4.string().optional(),
|
|
4283
|
+
threadId: z4.string().optional(),
|
|
3747
4284
|
metadata: z4.record(z4.string(), z4.unknown()).optional()
|
|
3748
4285
|
});
|
|
3749
4286
|
});
|
|
@@ -3789,7 +4326,10 @@ class AgentFactory {
|
|
|
3789
4326
|
posthogConfig: this.config.posthogConfig,
|
|
3790
4327
|
additionalTools: mergedTools,
|
|
3791
4328
|
mcpServers: mergedMcpServers.length > 0 ? mergedMcpServers : undefined,
|
|
3792
|
-
modelSelector: this.config.modelSelector
|
|
4329
|
+
modelSelector: this.config.modelSelector,
|
|
4330
|
+
runtimeAdapters: options?.runtimeAdapters ?? this.config.runtimeAdapters,
|
|
4331
|
+
approvalWorkflow: options?.approvalWorkflow ?? this.config.approvalWorkflow,
|
|
4332
|
+
eventEmitter: this.config.eventEmitter
|
|
3793
4333
|
});
|
|
3794
4334
|
}
|
|
3795
4335
|
async getOrCreate(name, version) {
|