@corbat-tech/coco 2.40.0 → 2.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/index.d.ts +81 -3
- package/dist/adapters/index.js +179 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/{agent-runtime-Cd6pB640.d.ts → agent-runtime-BJeNjVuk.d.ts} +20 -2
- package/dist/{blueprints-Dmdaw6_I.d.ts → blueprints-Dw5-uWU9.d.ts} +28 -4
- package/dist/cli/index.js +474 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/{workflow-engine-DleSoUhy.d.ts → context-BLPsKYxc.d.ts} +247 -129
- package/dist/{index-BD5_a3Q8.d.ts → index-DhUKtM2p.d.ts} +2 -2
- package/dist/index.d.ts +10 -10
- package/dist/index.js +1324 -128
- package/dist/index.js.map +1 -1
- package/dist/presets/index.d.ts +5 -5
- package/dist/presets/index.js +521 -17
- package/dist/presets/index.js.map +1 -1
- package/dist/{profiles-BA9dvyaF.d.ts → profiles-GRoVNorK.d.ts} +3 -3
- package/dist/{rag-D-Zo1oyo.d.ts → rag-B2oGudNb.d.ts} +68 -2
- package/dist/runtime/index.d.ts +278 -8
- package/dist/runtime/index.js +1113 -122
- package/dist/runtime/index.js.map +1 -1
- package/dist/tools/index.d.ts +4 -4
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/runtime-tool-executor-L5i8QWzn.d.ts +0 -174
package/dist/runtime/index.js
CHANGED
|
@@ -1704,6 +1704,53 @@ var init_auth = __esm({
|
|
|
1704
1704
|
|
|
1705
1705
|
// src/runtime/agent-runtime.ts
|
|
1706
1706
|
init_env();
|
|
1707
|
+
|
|
1708
|
+
// src/providers/pricing.ts
|
|
1709
|
+
init_catalog();
|
|
1710
|
+
var MODEL_PRICING = getCatalogModelPricingMap();
|
|
1711
|
+
var DEFAULT_PRICING = {
|
|
1712
|
+
anthropic: { inputPerMillion: 3, outputPerMillion: 15, contextWindow: 2e5 },
|
|
1713
|
+
openai: { inputPerMillion: 2.5, outputPerMillion: 10, contextWindow: 128e3 },
|
|
1714
|
+
codex: { inputPerMillion: 0, outputPerMillion: 0, contextWindow: 128e3 },
|
|
1715
|
+
// ChatGPT Plus/Pro subscription
|
|
1716
|
+
gemini: { inputPerMillion: 0.1, outputPerMillion: 0.4, contextWindow: 1e6 },
|
|
1717
|
+
vertex: { inputPerMillion: 0.1, outputPerMillion: 0.4, contextWindow: 1048576 },
|
|
1718
|
+
kimi: { inputPerMillion: 1.2, outputPerMillion: 1.2, contextWindow: 8192 },
|
|
1719
|
+
"kimi-code": { inputPerMillion: 0, outputPerMillion: 0, contextWindow: 131072 },
|
|
1720
|
+
// Included in subscription
|
|
1721
|
+
copilot: { inputPerMillion: 0, outputPerMillion: 0, contextWindow: 2e5 },
|
|
1722
|
+
// Included in subscription
|
|
1723
|
+
lmstudio: { inputPerMillion: 0, outputPerMillion: 0, contextWindow: 32768 },
|
|
1724
|
+
// Free - local models
|
|
1725
|
+
ollama: { inputPerMillion: 0, outputPerMillion: 0, contextWindow: 128e3 },
|
|
1726
|
+
// Free - local models
|
|
1727
|
+
groq: { inputPerMillion: 0.05, outputPerMillion: 0.08, contextWindow: 128e3 },
|
|
1728
|
+
// Free tier available
|
|
1729
|
+
openrouter: { inputPerMillion: 2, outputPerMillion: 8, contextWindow: 2e5 },
|
|
1730
|
+
// Varies by model
|
|
1731
|
+
mistral: { inputPerMillion: 0.25, outputPerMillion: 0.75, contextWindow: 32768 },
|
|
1732
|
+
deepseek: { inputPerMillion: 0.14, outputPerMillion: 0.28, contextWindow: 128e3 },
|
|
1733
|
+
// Very cheap
|
|
1734
|
+
together: { inputPerMillion: 0.2, outputPerMillion: 0.2, contextWindow: 32768 },
|
|
1735
|
+
huggingface: { inputPerMillion: 0, outputPerMillion: 0, contextWindow: 32768 },
|
|
1736
|
+
// Free tier
|
|
1737
|
+
qwen: { inputPerMillion: 0.3, outputPerMillion: 1.2, contextWindow: 131072 }
|
|
1738
|
+
// qwen-coder-plus pricing
|
|
1739
|
+
};
|
|
1740
|
+
function estimateCost(model2, inputTokens, outputTokens, provider) {
|
|
1741
|
+
const pricing = MODEL_PRICING[model2] ?? (provider ? DEFAULT_PRICING[provider] : DEFAULT_PRICING.anthropic);
|
|
1742
|
+
const inputCost = inputTokens / 1e6 * pricing.inputPerMillion;
|
|
1743
|
+
const outputCost = outputTokens / 1e6 * pricing.outputPerMillion;
|
|
1744
|
+
return {
|
|
1745
|
+
inputCost,
|
|
1746
|
+
outputCost,
|
|
1747
|
+
totalCost: inputCost + outputCost,
|
|
1748
|
+
inputTokens,
|
|
1749
|
+
outputTokens,
|
|
1750
|
+
model: model2,
|
|
1751
|
+
currency: "USD"
|
|
1752
|
+
};
|
|
1753
|
+
}
|
|
1707
1754
|
var DEFAULT_CONFIG = {
|
|
1708
1755
|
name: "coco",
|
|
1709
1756
|
level: "info",
|
|
@@ -2172,6 +2219,22 @@ function isAgentMode(value) {
|
|
|
2172
2219
|
}
|
|
2173
2220
|
|
|
2174
2221
|
// src/runtime/context.ts
|
|
2222
|
+
var RuntimePolicyViolation = class extends Error {
|
|
2223
|
+
code;
|
|
2224
|
+
subject;
|
|
2225
|
+
tenantId;
|
|
2226
|
+
policyPath;
|
|
2227
|
+
severity;
|
|
2228
|
+
constructor(input) {
|
|
2229
|
+
super(input.message);
|
|
2230
|
+
this.name = "RuntimePolicyViolation";
|
|
2231
|
+
this.code = input.code;
|
|
2232
|
+
this.subject = input.subject;
|
|
2233
|
+
this.tenantId = input.tenantId;
|
|
2234
|
+
this.policyPath = input.policyPath;
|
|
2235
|
+
this.severity = input.severity ?? "blocked";
|
|
2236
|
+
}
|
|
2237
|
+
};
|
|
2175
2238
|
function createRuntimeRequestContext(input = {}) {
|
|
2176
2239
|
return {
|
|
2177
2240
|
surface: input.surface ?? "api",
|
|
@@ -2214,6 +2277,27 @@ function runtimeContextToMetadata(context) {
|
|
|
2214
2277
|
dataClassification: context.policy?.dataBoundary?.classification
|
|
2215
2278
|
};
|
|
2216
2279
|
}
|
|
2280
|
+
function createRuntimeTenantBoundary(context, hostMode = "local") {
|
|
2281
|
+
return {
|
|
2282
|
+
hostMode,
|
|
2283
|
+
surface: context?.surface ?? "api",
|
|
2284
|
+
tenantId: context?.tenant?.id,
|
|
2285
|
+
required: hostMode === "hosted" && context?.surface !== "cli"
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
function assertRuntimeTenantBoundary(context, hostMode = "local", subject = "runtime operation") {
|
|
2289
|
+
const boundary = createRuntimeTenantBoundary(context, hostMode);
|
|
2290
|
+
if (boundary.required && !boundary.tenantId) {
|
|
2291
|
+
throw new RuntimePolicyViolation({
|
|
2292
|
+
code: "tenant_required",
|
|
2293
|
+
subject,
|
|
2294
|
+
tenantId: boundary.tenantId,
|
|
2295
|
+
policyPath: "runtimeContext.tenant.id",
|
|
2296
|
+
message: `Runtime tenant is required for hosted ${boundary.surface} operations.`
|
|
2297
|
+
});
|
|
2298
|
+
}
|
|
2299
|
+
return boundary;
|
|
2300
|
+
}
|
|
2217
2301
|
function evaluateRuntimeToolPolicy(policy, input) {
|
|
2218
2302
|
if (policy?.allowedTools && !policy.allowedTools.includes(input.toolName)) {
|
|
2219
2303
|
return {
|
|
@@ -2257,23 +2341,65 @@ function evaluateRuntimeRiskPolicy(policy, input) {
|
|
|
2257
2341
|
}
|
|
2258
2342
|
return { allowed: true, risk: input.risk };
|
|
2259
2343
|
}
|
|
2344
|
+
function assertRuntimeTurnWithinPolicy(policy, input) {
|
|
2345
|
+
const maxTurns = policy?.costBudget?.maxTurns;
|
|
2346
|
+
if (maxTurns !== void 0 && input.currentTurns >= maxTurns) {
|
|
2347
|
+
throw new RuntimePolicyViolation({
|
|
2348
|
+
code: "max_turns_exceeded",
|
|
2349
|
+
subject: input.subject,
|
|
2350
|
+
tenantId: input.tenantId,
|
|
2351
|
+
policyPath: "runtimePolicy.costBudget.maxTurns",
|
|
2352
|
+
message: `Runtime policy turn budget exceeded: ${input.currentTurns}/${maxTurns}`
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2260
2356
|
function assertRuntimeUsageWithinPolicy(policy, usage) {
|
|
2261
2357
|
const budget = policy?.costBudget;
|
|
2358
|
+
const subject = usage.subject ?? "runtime usage";
|
|
2262
2359
|
if (!budget) return;
|
|
2263
2360
|
if (budget.maxInputTokens !== void 0 && (usage.inputTokens ?? 0) > budget.maxInputTokens) {
|
|
2264
|
-
throw new
|
|
2265
|
-
|
|
2266
|
-
|
|
2361
|
+
throw new RuntimePolicyViolation({
|
|
2362
|
+
code: "input_tokens_exceeded",
|
|
2363
|
+
subject,
|
|
2364
|
+
tenantId: usage.tenantId,
|
|
2365
|
+
policyPath: "runtimePolicy.costBudget.maxInputTokens",
|
|
2366
|
+
message: `Runtime policy input token budget exceeded: ${usage.inputTokens ?? 0}/${budget.maxInputTokens}`
|
|
2367
|
+
});
|
|
2267
2368
|
}
|
|
2268
2369
|
if (budget.maxOutputTokens !== void 0 && (usage.outputTokens ?? 0) > budget.maxOutputTokens) {
|
|
2269
|
-
throw new
|
|
2270
|
-
|
|
2271
|
-
|
|
2370
|
+
throw new RuntimePolicyViolation({
|
|
2371
|
+
code: "output_tokens_exceeded",
|
|
2372
|
+
subject,
|
|
2373
|
+
tenantId: usage.tenantId,
|
|
2374
|
+
policyPath: "runtimePolicy.costBudget.maxOutputTokens",
|
|
2375
|
+
message: `Runtime policy output token budget exceeded: ${usage.outputTokens ?? 0}/${budget.maxOutputTokens}`
|
|
2376
|
+
});
|
|
2377
|
+
}
|
|
2378
|
+
if (budget.maxEstimatedCostUsd !== void 0 && (usage.estimatedCostUsd ?? 0) > budget.maxEstimatedCostUsd) {
|
|
2379
|
+
throw new RuntimePolicyViolation({
|
|
2380
|
+
code: "estimated_cost_exceeded",
|
|
2381
|
+
subject,
|
|
2382
|
+
tenantId: usage.tenantId,
|
|
2383
|
+
policyPath: "runtimePolicy.costBudget.maxEstimatedCostUsd",
|
|
2384
|
+
message: `Runtime policy estimated cost budget exceeded: ${usage.estimatedCostUsd ?? 0}/${budget.maxEstimatedCostUsd}`
|
|
2385
|
+
});
|
|
2272
2386
|
}
|
|
2273
2387
|
}
|
|
2388
|
+
function createRetentionCutoffs(policy, now = /* @__PURE__ */ new Date()) {
|
|
2389
|
+
const retention = policy?.retention;
|
|
2390
|
+
return {
|
|
2391
|
+
conversationBefore: cutoffIso(now, retention?.conversationDays),
|
|
2392
|
+
eventBefore: cutoffIso(now, retention?.eventDays),
|
|
2393
|
+
artifactBefore: cutoffIso(now, retention?.artifactDays)
|
|
2394
|
+
};
|
|
2395
|
+
}
|
|
2274
2396
|
function cloneRuntimePolicy(policy) {
|
|
2275
2397
|
return mergeRuntimePolicy(void 0, policy) ?? {};
|
|
2276
2398
|
}
|
|
2399
|
+
function cutoffIso(now, days) {
|
|
2400
|
+
if (days === void 0) return void 0;
|
|
2401
|
+
return new Date(now.getTime() - days * 24 * 60 * 60 * 1e3).toISOString();
|
|
2402
|
+
}
|
|
2277
2403
|
function riskRank(risk) {
|
|
2278
2404
|
switch (risk) {
|
|
2279
2405
|
case "read-only":
|
|
@@ -6602,10 +6728,6 @@ var VertexProvider = class {
|
|
|
6602
6728
|
}
|
|
6603
6729
|
};
|
|
6604
6730
|
|
|
6605
|
-
// src/providers/pricing.ts
|
|
6606
|
-
init_catalog();
|
|
6607
|
-
getCatalogModelPricingMap();
|
|
6608
|
-
|
|
6609
6731
|
// src/providers/circuit-breaker.ts
|
|
6610
6732
|
init_errors();
|
|
6611
6733
|
var DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
|
@@ -7262,6 +7384,7 @@ var LEGACY_ROLE_MAPPINGS = [
|
|
|
7262
7384
|
{ legacy: "coder", role: "coder", reason: "legacy executor role" },
|
|
7263
7385
|
{ legacy: "test", role: "tester", reason: "test authoring/execution" },
|
|
7264
7386
|
{ legacy: "tester", role: "tester", reason: "legacy executor role" },
|
|
7387
|
+
{ legacy: "verifier", role: "tester", reason: "verification maps to tester capability" },
|
|
7265
7388
|
{ legacy: "tdd", role: "tester", reason: "test-first implementation" },
|
|
7266
7389
|
{ legacy: "e2e", role: "tester", reason: "end-to-end testing" },
|
|
7267
7390
|
{ legacy: "review", role: "reviewer", reason: "code review" },
|
|
@@ -7997,7 +8120,7 @@ var NULL_EVENT_LOG = {
|
|
|
7997
8120
|
function graphNodeToTask(node, workflowInput) {
|
|
7998
8121
|
return {
|
|
7999
8122
|
id: node.id,
|
|
8000
|
-
role: node.agentRole ?? "coder",
|
|
8123
|
+
role: node.agentRole ?? mapLegacyAgentRole(node.id, "coder"),
|
|
8001
8124
|
objective: node.description,
|
|
8002
8125
|
context: {
|
|
8003
8126
|
workflowInput,
|
|
@@ -8183,6 +8306,239 @@ function cloneArtifact(artifact) {
|
|
|
8183
8306
|
};
|
|
8184
8307
|
}
|
|
8185
8308
|
|
|
8309
|
+
// src/runtime/agent-runner.ts
|
|
8310
|
+
var AgentRunner = class {
|
|
8311
|
+
constructor(options = {}) {
|
|
8312
|
+
this.options = options;
|
|
8313
|
+
}
|
|
8314
|
+
options;
|
|
8315
|
+
async run(input) {
|
|
8316
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8317
|
+
const trace = input.trace ?? createAgentTraceContext({ taskId: input.task.id });
|
|
8318
|
+
this.options.eventLog?.record("agent.started", {
|
|
8319
|
+
taskId: input.task.id,
|
|
8320
|
+
role: input.task.role,
|
|
8321
|
+
trace
|
|
8322
|
+
});
|
|
8323
|
+
try {
|
|
8324
|
+
const raw = await (this.options.executor ?? defaultExecutor)({
|
|
8325
|
+
task: input.task,
|
|
8326
|
+
capability: input.capability,
|
|
8327
|
+
trace,
|
|
8328
|
+
assertToolAllowed: (toolName) => {
|
|
8329
|
+
const decision = evaluateAgentToolPolicy({
|
|
8330
|
+
capability: input.capability,
|
|
8331
|
+
toolName,
|
|
8332
|
+
manifest: input.toolRiskManifest
|
|
8333
|
+
});
|
|
8334
|
+
this.options.eventLog?.record("agent.tool.called", {
|
|
8335
|
+
taskId: input.task.id,
|
|
8336
|
+
role: input.task.role,
|
|
8337
|
+
toolName,
|
|
8338
|
+
decision,
|
|
8339
|
+
trace
|
|
8340
|
+
});
|
|
8341
|
+
if (!decision.allowed) {
|
|
8342
|
+
throw new Error(decision.reason ?? `Tool '${toolName}' is not allowed.`);
|
|
8343
|
+
}
|
|
8344
|
+
}
|
|
8345
|
+
});
|
|
8346
|
+
const result = normalizeAgentRunResult({
|
|
8347
|
+
id: `${input.task.id}-run-${Date.now().toString(36)}`,
|
|
8348
|
+
taskId: input.task.id,
|
|
8349
|
+
role: input.task.role,
|
|
8350
|
+
success: raw.success ?? true,
|
|
8351
|
+
output: raw.output,
|
|
8352
|
+
turns: raw.turns,
|
|
8353
|
+
toolsUsed: raw.toolsUsed,
|
|
8354
|
+
usage: {
|
|
8355
|
+
inputTokens: raw.inputTokens ?? 0,
|
|
8356
|
+
outputTokens: raw.outputTokens ?? 0,
|
|
8357
|
+
estimated: raw.inputTokens === void 0 || raw.outputTokens === void 0
|
|
8358
|
+
},
|
|
8359
|
+
startedAt,
|
|
8360
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8361
|
+
durationMs: Date.now() - Date.parse(startedAt),
|
|
8362
|
+
error: raw.error,
|
|
8363
|
+
metadata: { ...raw.metadata, trace }
|
|
8364
|
+
});
|
|
8365
|
+
this.options.eventLog?.record(result.success ? "agent.completed" : "agent.failed", {
|
|
8366
|
+
taskId: input.task.id,
|
|
8367
|
+
role: input.task.role,
|
|
8368
|
+
agentRunId: result.id,
|
|
8369
|
+
trace,
|
|
8370
|
+
error: result.error
|
|
8371
|
+
});
|
|
8372
|
+
return result;
|
|
8373
|
+
} catch (error) {
|
|
8374
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8375
|
+
const result = normalizeAgentRunResult({
|
|
8376
|
+
id: `${input.task.id}-run-${Date.now().toString(36)}`,
|
|
8377
|
+
taskId: input.task.id,
|
|
8378
|
+
role: input.task.role,
|
|
8379
|
+
success: false,
|
|
8380
|
+
output: message,
|
|
8381
|
+
startedAt,
|
|
8382
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8383
|
+
durationMs: Date.now() - Date.parse(startedAt),
|
|
8384
|
+
error: message,
|
|
8385
|
+
metadata: { trace }
|
|
8386
|
+
});
|
|
8387
|
+
this.options.eventLog?.record("agent.failed", {
|
|
8388
|
+
taskId: input.task.id,
|
|
8389
|
+
role: input.task.role,
|
|
8390
|
+
agentRunId: result.id,
|
|
8391
|
+
trace,
|
|
8392
|
+
error: message
|
|
8393
|
+
});
|
|
8394
|
+
return result;
|
|
8395
|
+
}
|
|
8396
|
+
}
|
|
8397
|
+
};
|
|
8398
|
+
function createAgentRunner(options) {
|
|
8399
|
+
return new AgentRunner(options);
|
|
8400
|
+
}
|
|
8401
|
+
async function defaultExecutor(context) {
|
|
8402
|
+
return {
|
|
8403
|
+
output: `Agent ${context.capability.role} accepted task '${context.task.objective}'.`
|
|
8404
|
+
};
|
|
8405
|
+
}
|
|
8406
|
+
|
|
8407
|
+
// src/runtime/runtime-agent-node-executor.ts
|
|
8408
|
+
var AgentDefinitionRegistry = class {
|
|
8409
|
+
definitionsByRole = /* @__PURE__ */ new Map();
|
|
8410
|
+
definitionsById = /* @__PURE__ */ new Map();
|
|
8411
|
+
constructor(definitions = []) {
|
|
8412
|
+
for (const definition of definitions) {
|
|
8413
|
+
this.register(definition);
|
|
8414
|
+
}
|
|
8415
|
+
}
|
|
8416
|
+
register(definition) {
|
|
8417
|
+
this.definitionsById.set(definition.id, cloneDefinition(definition));
|
|
8418
|
+
this.definitionsByRole.set(definition.role, cloneDefinition(definition));
|
|
8419
|
+
}
|
|
8420
|
+
get(id) {
|
|
8421
|
+
const definition = this.definitionsById.get(id);
|
|
8422
|
+
return definition ? cloneDefinition(definition) : void 0;
|
|
8423
|
+
}
|
|
8424
|
+
getByRole(role) {
|
|
8425
|
+
const definition = this.definitionsByRole.get(role);
|
|
8426
|
+
return definition ? cloneDefinition(definition) : void 0;
|
|
8427
|
+
}
|
|
8428
|
+
list() {
|
|
8429
|
+
return [...this.definitionsById.values()].map(cloneDefinition);
|
|
8430
|
+
}
|
|
8431
|
+
};
|
|
8432
|
+
var RuntimeAgentNodeExecutor = class {
|
|
8433
|
+
constructor(options) {
|
|
8434
|
+
this.options = options;
|
|
8435
|
+
this.runner = options.runner ?? new AgentRunner(options.runnerOptions);
|
|
8436
|
+
}
|
|
8437
|
+
options;
|
|
8438
|
+
runner;
|
|
8439
|
+
execute = async (execution) => {
|
|
8440
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8441
|
+
const definition = this.options.registry.getByRole(execution.task.role);
|
|
8442
|
+
if (!definition) {
|
|
8443
|
+
return normalizeAgentRunResult({
|
|
8444
|
+
id: `${execution.workflowRunId}-${execution.node.id}-missing-definition`,
|
|
8445
|
+
taskId: execution.task.id,
|
|
8446
|
+
role: execution.task.role,
|
|
8447
|
+
success: false,
|
|
8448
|
+
output: "",
|
|
8449
|
+
startedAt,
|
|
8450
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8451
|
+
error: `No agent definition registered for role '${execution.task.role}'.`,
|
|
8452
|
+
metadata: {
|
|
8453
|
+
workflowRunId: execution.workflowRunId,
|
|
8454
|
+
nodeId: execution.node.id,
|
|
8455
|
+
trace: execution.trace
|
|
8456
|
+
}
|
|
8457
|
+
});
|
|
8458
|
+
}
|
|
8459
|
+
const blockedTool = this.findBlockedTool(definition, execution);
|
|
8460
|
+
if (blockedTool) {
|
|
8461
|
+
return normalizeAgentRunResult({
|
|
8462
|
+
id: `${execution.workflowRunId}-${execution.node.id}-policy-blocked`,
|
|
8463
|
+
taskId: execution.task.id,
|
|
8464
|
+
role: execution.task.role,
|
|
8465
|
+
success: false,
|
|
8466
|
+
output: "",
|
|
8467
|
+
startedAt,
|
|
8468
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8469
|
+
error: blockedTool,
|
|
8470
|
+
metadata: {
|
|
8471
|
+
workflowRunId: execution.workflowRunId,
|
|
8472
|
+
nodeId: execution.node.id,
|
|
8473
|
+
agentDefinitionId: definition.id,
|
|
8474
|
+
trace: execution.trace
|
|
8475
|
+
}
|
|
8476
|
+
});
|
|
8477
|
+
}
|
|
8478
|
+
const input = {
|
|
8479
|
+
task: {
|
|
8480
|
+
...execution.task,
|
|
8481
|
+
context: {
|
|
8482
|
+
...execution.task.context,
|
|
8483
|
+
instructions: definition.instructions,
|
|
8484
|
+
sharedState: execution.sharedState.readForRole(definition.role)
|
|
8485
|
+
}
|
|
8486
|
+
},
|
|
8487
|
+
capability: definition.capability,
|
|
8488
|
+
trace: execution.trace,
|
|
8489
|
+
toolRiskManifest: this.options.toolRiskManifest
|
|
8490
|
+
};
|
|
8491
|
+
const result = await this.runner.run(input);
|
|
8492
|
+
return normalizeAgentRunResult({
|
|
8493
|
+
...result,
|
|
8494
|
+
metadata: {
|
|
8495
|
+
...result.metadata,
|
|
8496
|
+
workflowRunId: execution.workflowRunId,
|
|
8497
|
+
nodeId: execution.node.id,
|
|
8498
|
+
agentDefinitionId: definition.id
|
|
8499
|
+
}
|
|
8500
|
+
});
|
|
8501
|
+
};
|
|
8502
|
+
findBlockedTool(definition, execution) {
|
|
8503
|
+
for (const toolName of execution.node.requiredTools ?? []) {
|
|
8504
|
+
const agentDecision = evaluateAgentToolPolicy({
|
|
8505
|
+
capability: definition.capability,
|
|
8506
|
+
toolName,
|
|
8507
|
+
manifest: this.options.toolRiskManifest
|
|
8508
|
+
});
|
|
8509
|
+
execution.eventLog.record("agent.tool.called", {
|
|
8510
|
+
workflowRunId: execution.workflowRunId,
|
|
8511
|
+
nodeId: execution.node.id,
|
|
8512
|
+
taskId: execution.task.id,
|
|
8513
|
+
role: execution.task.role,
|
|
8514
|
+
toolName,
|
|
8515
|
+
decision: agentDecision,
|
|
8516
|
+
trace: execution.trace
|
|
8517
|
+
});
|
|
8518
|
+
if (!agentDecision.allowed) {
|
|
8519
|
+
return agentDecision.reason ?? `Tool '${toolName}' is not allowed for agent.`;
|
|
8520
|
+
}
|
|
8521
|
+
const runtimeDecision = evaluateRuntimeToolPolicy(this.options.runtimePolicy, {
|
|
8522
|
+
toolName,
|
|
8523
|
+
risk: agentDecision.risk
|
|
8524
|
+
});
|
|
8525
|
+
if (!runtimeDecision.allowed) {
|
|
8526
|
+
return runtimeDecision.reason ?? `Tool '${toolName}' is blocked by runtime policy.`;
|
|
8527
|
+
}
|
|
8528
|
+
}
|
|
8529
|
+
return void 0;
|
|
8530
|
+
}
|
|
8531
|
+
};
|
|
8532
|
+
function createAgentDefinitionRegistry(definitions = []) {
|
|
8533
|
+
return new AgentDefinitionRegistry(definitions);
|
|
8534
|
+
}
|
|
8535
|
+
function createRuntimeAgentNodeExecutor(options) {
|
|
8536
|
+
return new RuntimeAgentNodeExecutor(options).execute;
|
|
8537
|
+
}
|
|
8538
|
+
function cloneDefinition(definition) {
|
|
8539
|
+
return structuredClone(definition);
|
|
8540
|
+
}
|
|
8541
|
+
|
|
8186
8542
|
// src/runtime/workflow-registry.ts
|
|
8187
8543
|
function cloneWorkflow(workflow) {
|
|
8188
8544
|
return {
|
|
@@ -8516,14 +8872,22 @@ var WorkflowEngine = class {
|
|
|
8516
8872
|
this.catalog = catalog;
|
|
8517
8873
|
this.eventLog = eventLog;
|
|
8518
8874
|
this.sharedState = options.sharedState ?? new InMemorySharedWorkspaceStore();
|
|
8519
|
-
this.nodeExecutor = options.nodeExecutor;
|
|
8520
8875
|
this.runtimePolicy = options.runtimePolicy;
|
|
8876
|
+
this.runtimeContext = options.runtimeContext;
|
|
8877
|
+
this.runtimeHostMode = options.runtimeHostMode ?? "local";
|
|
8878
|
+
this.nodeExecutor = options.nodeExecutor ?? (options.agentDefinitionRegistry ? createRuntimeAgentNodeExecutor({
|
|
8879
|
+
...options.agentNodeExecutorOptions,
|
|
8880
|
+
registry: options.agentDefinitionRegistry,
|
|
8881
|
+
runtimePolicy: options.runtimePolicy
|
|
8882
|
+
}) : void 0);
|
|
8521
8883
|
}
|
|
8522
8884
|
catalog;
|
|
8523
8885
|
eventLog;
|
|
8524
8886
|
handlers = /* @__PURE__ */ new Map();
|
|
8525
8887
|
sharedState;
|
|
8526
8888
|
runtimePolicy;
|
|
8889
|
+
runtimeContext;
|
|
8890
|
+
runtimeHostMode;
|
|
8527
8891
|
nodeExecutor;
|
|
8528
8892
|
registerHandler(workflowId, handler) {
|
|
8529
8893
|
if (!this.catalog.get(workflowId)) {
|
|
@@ -8538,6 +8902,7 @@ var WorkflowEngine = class {
|
|
|
8538
8902
|
return this.catalog.createPlan(workflowId, input, this.eventLog);
|
|
8539
8903
|
}
|
|
8540
8904
|
async run(request) {
|
|
8905
|
+
assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "workflow.run");
|
|
8541
8906
|
const workflow = this.catalog.get(request.workflowId);
|
|
8542
8907
|
if (!workflow) {
|
|
8543
8908
|
throw new Error(`Unknown workflow: ${request.workflowId}`);
|
|
@@ -8657,7 +9022,14 @@ var AgentRuntime = class {
|
|
|
8657
9022
|
this.model = options.model ?? options.providerConfig?.model ?? getDefaultModel(options.providerType);
|
|
8658
9023
|
this.runtimeContext = options.runtimeContext ? createRuntimeRequestContext(options.runtimeContext) : void 0;
|
|
8659
9024
|
this.runtimePolicy = mergeRuntimePolicy(this.runtimeContext?.policy, options.runtimePolicy);
|
|
8660
|
-
this.
|
|
9025
|
+
this.runtimeHostMode = options.runtimeHostMode ?? "local";
|
|
9026
|
+
assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "runtime.initialize");
|
|
9027
|
+
this.workflowEngine = options.workflowEngine ?? createWorkflowEngine(void 0, this.eventLog, {
|
|
9028
|
+
runtimePolicy: this.runtimePolicy,
|
|
9029
|
+
runtimeContext: this.runtimeContext,
|
|
9030
|
+
runtimeHostMode: this.runtimeHostMode,
|
|
9031
|
+
agentDefinitionRegistry: options.agentDefinitionRegistry
|
|
9032
|
+
});
|
|
8661
9033
|
}
|
|
8662
9034
|
options;
|
|
8663
9035
|
providerRegistry;
|
|
@@ -8673,6 +9045,9 @@ var AgentRuntime = class {
|
|
|
8673
9045
|
provider;
|
|
8674
9046
|
runtimeContext;
|
|
8675
9047
|
runtimePolicy;
|
|
9048
|
+
runtimeHostMode;
|
|
9049
|
+
requestTimestampsBySubject = /* @__PURE__ */ new Map();
|
|
9050
|
+
activeRuns = 0;
|
|
8676
9051
|
async initialize() {
|
|
8677
9052
|
const providerInjected = Boolean(this.options.provider);
|
|
8678
9053
|
const provider = this.options.provider ?? await this.providerRegistry.createProvider(this.providerType, {
|
|
@@ -8721,10 +9096,12 @@ var AgentRuntime = class {
|
|
|
8721
9096
|
},
|
|
8722
9097
|
modes: listAgentModes(),
|
|
8723
9098
|
context: this.runtimeContext,
|
|
8724
|
-
policy: this.runtimePolicy
|
|
9099
|
+
policy: this.runtimePolicy,
|
|
9100
|
+
hostMode: this.runtimeHostMode
|
|
8725
9101
|
};
|
|
8726
9102
|
}
|
|
8727
9103
|
createSession(options = {}) {
|
|
9104
|
+
assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "session.create");
|
|
8728
9105
|
const session = this.runtimeSessionStore.create({
|
|
8729
9106
|
...options,
|
|
8730
9107
|
metadata: {
|
|
@@ -8748,6 +9125,27 @@ var AgentRuntime = class {
|
|
|
8748
9125
|
listSessions() {
|
|
8749
9126
|
return this.runtimeSessionStore.list();
|
|
8750
9127
|
}
|
|
9128
|
+
cleanupRetention(options = {}) {
|
|
9129
|
+
assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "retention.cleanup");
|
|
9130
|
+
const dryRun = options.dryRun ?? true;
|
|
9131
|
+
const cutoffs = createRetentionCutoffs(this.runtimePolicy, options.now);
|
|
9132
|
+
const expiredSessionIds = cutoffs.conversationBefore ? this.runtimeSessionStore.list().filter((session) => session.updatedAt < cutoffs.conversationBefore).map((session) => session.id) : [];
|
|
9133
|
+
const deletedSessionIds = dryRun ? [] : expiredSessionIds.filter((id) => this.runtimeSessionStore.delete(id));
|
|
9134
|
+
this.eventLog.record("retention.cleanup", {
|
|
9135
|
+
dryRun,
|
|
9136
|
+
cutoffs,
|
|
9137
|
+
expiredSessionIds,
|
|
9138
|
+
deletedSessionIds,
|
|
9139
|
+
tenantId: this.runtimeContext?.tenant?.id,
|
|
9140
|
+
runtimeApi: true
|
|
9141
|
+
});
|
|
9142
|
+
return {
|
|
9143
|
+
dryRun,
|
|
9144
|
+
cutoffs,
|
|
9145
|
+
expiredSessionIds,
|
|
9146
|
+
deletedSessionIds
|
|
9147
|
+
};
|
|
9148
|
+
}
|
|
8751
9149
|
async runTurn(input) {
|
|
8752
9150
|
const provider = this.provider;
|
|
8753
9151
|
if (!provider) {
|
|
@@ -8758,6 +9156,12 @@ var AgentRuntime = class {
|
|
|
8758
9156
|
throw new Error(`Runtime session not found: ${input.sessionId}`);
|
|
8759
9157
|
}
|
|
8760
9158
|
const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
|
|
9159
|
+
assertRuntimeTurnWithinPolicy(this.runtimePolicy, {
|
|
9160
|
+
subject: "turn.run",
|
|
9161
|
+
currentTurns: countUserTurns(effectiveSession),
|
|
9162
|
+
tenantId: this.runtimeContext?.tenant?.id
|
|
9163
|
+
});
|
|
9164
|
+
const releaseRuntimeRequest = this.beginRuntimeRequest("turn.run");
|
|
8761
9165
|
this.eventLog.record("turn.started", {
|
|
8762
9166
|
sessionId: effectiveSession.id,
|
|
8763
9167
|
provider: this.providerType,
|
|
@@ -8774,7 +9178,13 @@ var AgentRuntime = class {
|
|
|
8774
9178
|
permissionPolicy: this.permissionPolicy,
|
|
8775
9179
|
eventLog: this.eventLog
|
|
8776
9180
|
});
|
|
8777
|
-
|
|
9181
|
+
const estimatedCostUsd = this.estimateTurnCost(result);
|
|
9182
|
+
assertRuntimeUsageWithinPolicy(this.runtimePolicy, {
|
|
9183
|
+
...result.usage,
|
|
9184
|
+
estimatedCostUsd,
|
|
9185
|
+
tenantId: this.runtimeContext?.tenant?.id,
|
|
9186
|
+
subject: "turn.run"
|
|
9187
|
+
});
|
|
8778
9188
|
const updatedSession = this.runtimeSessionStore.update({
|
|
8779
9189
|
...effectiveSession,
|
|
8780
9190
|
messages: [
|
|
@@ -8791,6 +9201,7 @@ var AgentRuntime = class {
|
|
|
8791
9201
|
sessionId: updatedSession.id,
|
|
8792
9202
|
inputTokens: result.usage.inputTokens,
|
|
8793
9203
|
outputTokens: result.usage.outputTokens,
|
|
9204
|
+
estimatedCostUsd,
|
|
8794
9205
|
model: result.model,
|
|
8795
9206
|
runtimeApi: true
|
|
8796
9207
|
});
|
|
@@ -8802,6 +9213,8 @@ var AgentRuntime = class {
|
|
|
8802
9213
|
runtimeApi: true
|
|
8803
9214
|
});
|
|
8804
9215
|
throw error;
|
|
9216
|
+
} finally {
|
|
9217
|
+
releaseRuntimeRequest();
|
|
8805
9218
|
}
|
|
8806
9219
|
}
|
|
8807
9220
|
async *streamTurn(input) {
|
|
@@ -8814,6 +9227,12 @@ var AgentRuntime = class {
|
|
|
8814
9227
|
throw new Error(`Runtime session not found: ${input.sessionId}`);
|
|
8815
9228
|
}
|
|
8816
9229
|
const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
|
|
9230
|
+
assertRuntimeTurnWithinPolicy(this.runtimePolicy, {
|
|
9231
|
+
subject: "turn.stream",
|
|
9232
|
+
currentTurns: countUserTurns(effectiveSession),
|
|
9233
|
+
tenantId: this.runtimeContext?.tenant?.id
|
|
9234
|
+
});
|
|
9235
|
+
const releaseRuntimeRequest = this.beginRuntimeRequest("turn.stream");
|
|
8817
9236
|
const messages = [
|
|
8818
9237
|
...effectiveSession.messages,
|
|
8819
9238
|
{
|
|
@@ -8863,7 +9282,13 @@ var AgentRuntime = class {
|
|
|
8863
9282
|
model: input.options?.model ?? this.getModel(),
|
|
8864
9283
|
mode: effectiveSession.mode
|
|
8865
9284
|
};
|
|
8866
|
-
|
|
9285
|
+
const estimatedCostUsd = this.estimateTurnCost(result);
|
|
9286
|
+
assertRuntimeUsageWithinPolicy(this.runtimePolicy, {
|
|
9287
|
+
...result.usage,
|
|
9288
|
+
estimatedCostUsd,
|
|
9289
|
+
tenantId: this.runtimeContext?.tenant?.id,
|
|
9290
|
+
subject: "turn.stream"
|
|
9291
|
+
});
|
|
8867
9292
|
const updatedSession = this.runtimeSessionStore.update({
|
|
8868
9293
|
...effectiveSession,
|
|
8869
9294
|
messages: [
|
|
@@ -8882,6 +9307,7 @@ var AgentRuntime = class {
|
|
|
8882
9307
|
sessionId: updatedSession.id,
|
|
8883
9308
|
inputTokens: result.usage.inputTokens,
|
|
8884
9309
|
outputTokens: result.usage.outputTokens,
|
|
9310
|
+
estimatedCostUsd,
|
|
8885
9311
|
model: result.model,
|
|
8886
9312
|
streaming: true,
|
|
8887
9313
|
runtimeApi: true
|
|
@@ -8911,9 +9337,11 @@ var AgentRuntime = class {
|
|
|
8911
9337
|
runtimeApi: true
|
|
8912
9338
|
});
|
|
8913
9339
|
}
|
|
9340
|
+
releaseRuntimeRequest();
|
|
8914
9341
|
}
|
|
8915
9342
|
}
|
|
8916
9343
|
async executeTool(input) {
|
|
9344
|
+
assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "tool.execute");
|
|
8917
9345
|
const startedAt = performance.now();
|
|
8918
9346
|
const session = input.sessionId ? this.getSession(input.sessionId) : void 0;
|
|
8919
9347
|
if (input.sessionId && !session) {
|
|
@@ -9024,6 +9452,7 @@ var AgentRuntime = class {
|
|
|
9024
9452
|
};
|
|
9025
9453
|
}
|
|
9026
9454
|
assertToolAllowed(mode, toolName, input) {
|
|
9455
|
+
assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, "tool.assertAllowed");
|
|
9027
9456
|
const tool = this.toolRegistry.get(toolName);
|
|
9028
9457
|
if (!tool) {
|
|
9029
9458
|
this.eventLog.record("tool.blocked", {
|
|
@@ -9053,109 +9482,69 @@ var AgentRuntime = class {
|
|
|
9053
9482
|
});
|
|
9054
9483
|
return allowed;
|
|
9055
9484
|
}
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9485
|
+
beginRuntimeRequest(subject) {
|
|
9486
|
+
assertRuntimeTenantBoundary(this.runtimeContext, this.runtimeHostMode, subject);
|
|
9487
|
+
this.assertWithinRateLimit(subject);
|
|
9488
|
+
this.assertWithinConcurrencyLimit(subject);
|
|
9489
|
+
this.activeRuns += 1;
|
|
9490
|
+
let released = false;
|
|
9491
|
+
return () => {
|
|
9492
|
+
if (released) return;
|
|
9493
|
+
released = true;
|
|
9494
|
+
this.activeRuns = Math.max(0, this.activeRuns - 1);
|
|
9495
|
+
};
|
|
9067
9496
|
}
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
const
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
toolName,
|
|
9086
|
-
manifest: input.toolRiskManifest
|
|
9087
|
-
});
|
|
9088
|
-
this.options.eventLog?.record("agent.tool.called", {
|
|
9089
|
-
taskId: input.task.id,
|
|
9090
|
-
role: input.task.role,
|
|
9091
|
-
toolName,
|
|
9092
|
-
decision,
|
|
9093
|
-
trace
|
|
9094
|
-
});
|
|
9095
|
-
if (!decision.allowed) {
|
|
9096
|
-
throw new Error(decision.reason ?? `Tool '${toolName}' is not allowed.`);
|
|
9097
|
-
}
|
|
9098
|
-
}
|
|
9099
|
-
});
|
|
9100
|
-
const result = normalizeAgentRunResult({
|
|
9101
|
-
id: `${input.task.id}-run-${Date.now().toString(36)}`,
|
|
9102
|
-
taskId: input.task.id,
|
|
9103
|
-
role: input.task.role,
|
|
9104
|
-
success: raw.success ?? true,
|
|
9105
|
-
output: raw.output,
|
|
9106
|
-
turns: raw.turns,
|
|
9107
|
-
toolsUsed: raw.toolsUsed,
|
|
9108
|
-
usage: {
|
|
9109
|
-
inputTokens: raw.inputTokens ?? 0,
|
|
9110
|
-
outputTokens: raw.outputTokens ?? 0,
|
|
9111
|
-
estimated: raw.inputTokens === void 0 || raw.outputTokens === void 0
|
|
9112
|
-
},
|
|
9113
|
-
startedAt,
|
|
9114
|
-
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9115
|
-
durationMs: Date.now() - Date.parse(startedAt),
|
|
9116
|
-
error: raw.error,
|
|
9117
|
-
metadata: { ...raw.metadata, trace }
|
|
9118
|
-
});
|
|
9119
|
-
this.options.eventLog?.record(result.success ? "agent.completed" : "agent.failed", {
|
|
9120
|
-
taskId: input.task.id,
|
|
9121
|
-
role: input.task.role,
|
|
9122
|
-
agentRunId: result.id,
|
|
9123
|
-
trace,
|
|
9124
|
-
error: result.error
|
|
9125
|
-
});
|
|
9126
|
-
return result;
|
|
9127
|
-
} catch (error) {
|
|
9128
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
9129
|
-
const result = normalizeAgentRunResult({
|
|
9130
|
-
id: `${input.task.id}-run-${Date.now().toString(36)}`,
|
|
9131
|
-
taskId: input.task.id,
|
|
9132
|
-
role: input.task.role,
|
|
9133
|
-
success: false,
|
|
9134
|
-
output: message,
|
|
9135
|
-
startedAt,
|
|
9136
|
-
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9137
|
-
durationMs: Date.now() - Date.parse(startedAt),
|
|
9138
|
-
error: message,
|
|
9139
|
-
metadata: { trace }
|
|
9497
|
+
assertWithinRateLimit(subject) {
|
|
9498
|
+
const maxRequestsPerMinute = this.runtimePolicy?.rateLimit?.maxRequestsPerMinute;
|
|
9499
|
+
if (maxRequestsPerMinute === void 0) return;
|
|
9500
|
+
const now = Date.now();
|
|
9501
|
+
const windowStart = now - 6e4;
|
|
9502
|
+
const key = `${this.runtimeContext?.tenant?.id ?? "global"}:${subject}`;
|
|
9503
|
+
const recent = (this.requestTimestampsBySubject.get(key) ?? []).filter(
|
|
9504
|
+
(timestamp) => timestamp > windowStart
|
|
9505
|
+
);
|
|
9506
|
+
if (recent.length >= maxRequestsPerMinute) {
|
|
9507
|
+
this.requestTimestampsBySubject.set(key, recent);
|
|
9508
|
+
throw new RuntimePolicyViolation({
|
|
9509
|
+
code: "rate_limit_exceeded",
|
|
9510
|
+
subject,
|
|
9511
|
+
tenantId: this.runtimeContext?.tenant?.id,
|
|
9512
|
+
policyPath: "runtimePolicy.rateLimit.maxRequestsPerMinute",
|
|
9513
|
+
message: `Runtime policy rate limit exceeded: ${recent.length}/${maxRequestsPerMinute} requests per minute.`
|
|
9140
9514
|
});
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9515
|
+
}
|
|
9516
|
+
recent.push(now);
|
|
9517
|
+
this.requestTimestampsBySubject.set(key, recent);
|
|
9518
|
+
}
|
|
9519
|
+
assertWithinConcurrencyLimit(subject) {
|
|
9520
|
+
const maxConcurrentRuns = this.runtimePolicy?.rateLimit?.maxConcurrentRuns;
|
|
9521
|
+
if (maxConcurrentRuns === void 0) return;
|
|
9522
|
+
if (this.activeRuns >= maxConcurrentRuns) {
|
|
9523
|
+
throw new RuntimePolicyViolation({
|
|
9524
|
+
code: "concurrency_limit_exceeded",
|
|
9525
|
+
subject,
|
|
9526
|
+
tenantId: this.runtimeContext?.tenant?.id,
|
|
9527
|
+
policyPath: "runtimePolicy.rateLimit.maxConcurrentRuns",
|
|
9528
|
+
message: `Runtime policy concurrency limit exceeded: ${this.activeRuns}/${maxConcurrentRuns} active runs.`
|
|
9147
9529
|
});
|
|
9148
|
-
return result;
|
|
9149
9530
|
}
|
|
9150
9531
|
}
|
|
9532
|
+
estimateTurnCost(result) {
|
|
9533
|
+
return estimateCost(
|
|
9534
|
+
result.model,
|
|
9535
|
+
result.usage.inputTokens,
|
|
9536
|
+
result.usage.outputTokens,
|
|
9537
|
+
this.providerType
|
|
9538
|
+
).totalCost;
|
|
9539
|
+
}
|
|
9151
9540
|
};
|
|
9152
|
-
function
|
|
9153
|
-
return
|
|
9541
|
+
function countUserTurns(session) {
|
|
9542
|
+
return session.messages.filter((message) => message.role === "user").length;
|
|
9154
9543
|
}
|
|
9155
|
-
async function
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9544
|
+
async function createAgentRuntime(options) {
|
|
9545
|
+
const runtime = new AgentRuntime(options);
|
|
9546
|
+
await runtime.initialize();
|
|
9547
|
+
return runtime;
|
|
9159
9548
|
}
|
|
9160
9549
|
|
|
9161
9550
|
// src/runtime/tool-calling-turn-runner.ts
|
|
@@ -9398,10 +9787,24 @@ function rowToEvent(row) {
|
|
|
9398
9787
|
function persistBestEffort(promise) {
|
|
9399
9788
|
void promise.catch(() => void 0);
|
|
9400
9789
|
}
|
|
9790
|
+
function assertPostgresSyncStoreNotHosted(options) {
|
|
9791
|
+
if (options.hostMode === "hosted") {
|
|
9792
|
+
throw new Error(
|
|
9793
|
+
"Postgres sync runtime stores are local/cache-compatible only. Use async hosted Postgres stores in hosted mode."
|
|
9794
|
+
);
|
|
9795
|
+
}
|
|
9796
|
+
}
|
|
9797
|
+
function requireTenantId(options) {
|
|
9798
|
+
if (!options.tenantId) {
|
|
9799
|
+
throw new Error("Postgres hosted runtime stores require tenantId.");
|
|
9800
|
+
}
|
|
9801
|
+
return options.tenantId;
|
|
9802
|
+
}
|
|
9401
9803
|
var PostgresRuntimeSessionStore = class {
|
|
9402
9804
|
constructor(client, options = {}) {
|
|
9403
9805
|
this.client = client;
|
|
9404
9806
|
this.options = options;
|
|
9807
|
+
assertPostgresSyncStoreNotHosted(options);
|
|
9405
9808
|
}
|
|
9406
9809
|
client;
|
|
9407
9810
|
options;
|
|
@@ -9482,6 +9885,104 @@ var PostgresRuntimeSessionStore = class {
|
|
|
9482
9885
|
return deleted;
|
|
9483
9886
|
}
|
|
9484
9887
|
};
|
|
9888
|
+
var AsyncPostgresRuntimeSessionStore = class {
|
|
9889
|
+
constructor(client, options) {
|
|
9890
|
+
this.client = client;
|
|
9891
|
+
this.tenantId = requireTenantId(options);
|
|
9892
|
+
}
|
|
9893
|
+
client;
|
|
9894
|
+
tenantId;
|
|
9895
|
+
async create(options = {}) {
|
|
9896
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9897
|
+
const session = {
|
|
9898
|
+
id: options.id ?? createSessionId2(),
|
|
9899
|
+
createdAt: now,
|
|
9900
|
+
updatedAt: now,
|
|
9901
|
+
mode: options.mode ?? "ask",
|
|
9902
|
+
messages: options.messages ? options.messages.map((message) => ({ ...message })) : [],
|
|
9903
|
+
instructions: options.instructions,
|
|
9904
|
+
metadata: { ...options.metadata, tenantId: this.tenantId }
|
|
9905
|
+
};
|
|
9906
|
+
const result = await this.client.query(
|
|
9907
|
+
`insert into coco_runtime_sessions
|
|
9908
|
+
(id, tenant_id, created_at, updated_at, mode, messages, instructions, metadata)
|
|
9909
|
+
values ($1, $2, $3, $4, $5, $6::jsonb, $7, $8::jsonb)
|
|
9910
|
+
on conflict (id) do update set
|
|
9911
|
+
updated_at = excluded.updated_at,
|
|
9912
|
+
mode = excluded.mode,
|
|
9913
|
+
messages = excluded.messages,
|
|
9914
|
+
instructions = excluded.instructions,
|
|
9915
|
+
metadata = excluded.metadata
|
|
9916
|
+
where coco_runtime_sessions.tenant_id = excluded.tenant_id`,
|
|
9917
|
+
[
|
|
9918
|
+
session.id,
|
|
9919
|
+
this.tenantId,
|
|
9920
|
+
session.createdAt,
|
|
9921
|
+
session.updatedAt,
|
|
9922
|
+
session.mode,
|
|
9923
|
+
JSON.stringify(session.messages),
|
|
9924
|
+
session.instructions ?? null,
|
|
9925
|
+
JSON.stringify(session.metadata)
|
|
9926
|
+
]
|
|
9927
|
+
);
|
|
9928
|
+
if (result.rowCount === 0) {
|
|
9929
|
+
throw new Error(`Runtime session id is already owned by another tenant: ${session.id}`);
|
|
9930
|
+
}
|
|
9931
|
+
return structuredClone(session);
|
|
9932
|
+
}
|
|
9933
|
+
async get(id) {
|
|
9934
|
+
const result = await this.client.query(
|
|
9935
|
+
`select * from coco_runtime_sessions
|
|
9936
|
+
where id = $1 and tenant_id = $2
|
|
9937
|
+
limit 1`,
|
|
9938
|
+
[id, this.tenantId]
|
|
9939
|
+
);
|
|
9940
|
+
const row = result.rows[0];
|
|
9941
|
+
return row ? rowToSession(row) : void 0;
|
|
9942
|
+
}
|
|
9943
|
+
async update(session) {
|
|
9944
|
+
const updated = {
|
|
9945
|
+
...session,
|
|
9946
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9947
|
+
messages: session.messages.map((message) => ({ ...message })),
|
|
9948
|
+
metadata: { ...session.metadata, tenantId: this.tenantId }
|
|
9949
|
+
};
|
|
9950
|
+
const result = await this.client.query(
|
|
9951
|
+
`update coco_runtime_sessions
|
|
9952
|
+
set updated_at = $3, mode = $4, messages = $5::jsonb, instructions = $6, metadata = $7::jsonb
|
|
9953
|
+
where id = $1 and tenant_id = $2`,
|
|
9954
|
+
[
|
|
9955
|
+
updated.id,
|
|
9956
|
+
this.tenantId,
|
|
9957
|
+
updated.updatedAt,
|
|
9958
|
+
updated.mode,
|
|
9959
|
+
JSON.stringify(updated.messages),
|
|
9960
|
+
updated.instructions ?? null,
|
|
9961
|
+
JSON.stringify(updated.metadata)
|
|
9962
|
+
]
|
|
9963
|
+
);
|
|
9964
|
+
if (result.rowCount === 0) {
|
|
9965
|
+
throw new Error(`Runtime session not found for tenant ${this.tenantId}: ${updated.id}`);
|
|
9966
|
+
}
|
|
9967
|
+
return structuredClone(updated);
|
|
9968
|
+
}
|
|
9969
|
+
async list() {
|
|
9970
|
+
const result = await this.client.query(
|
|
9971
|
+
`select * from coco_runtime_sessions
|
|
9972
|
+
where tenant_id = $1
|
|
9973
|
+
order by updated_at desc`,
|
|
9974
|
+
[this.tenantId]
|
|
9975
|
+
);
|
|
9976
|
+
return result.rows.map(rowToSession);
|
|
9977
|
+
}
|
|
9978
|
+
async delete(id) {
|
|
9979
|
+
const result = await this.client.query(
|
|
9980
|
+
"delete from coco_runtime_sessions where id = $1 and tenant_id = $2",
|
|
9981
|
+
[id, this.tenantId]
|
|
9982
|
+
);
|
|
9983
|
+
return (result.rowCount ?? 0) > 0;
|
|
9984
|
+
}
|
|
9985
|
+
};
|
|
9485
9986
|
function createPostgresRuntimeSessionQueries(client, options = {}) {
|
|
9486
9987
|
return {
|
|
9487
9988
|
async get(id) {
|
|
@@ -9509,6 +10010,7 @@ var PostgresEventLog = class {
|
|
|
9509
10010
|
constructor(client, options = {}) {
|
|
9510
10011
|
this.client = client;
|
|
9511
10012
|
this.options = options;
|
|
10013
|
+
assertPostgresSyncStoreNotHosted(options);
|
|
9512
10014
|
}
|
|
9513
10015
|
client;
|
|
9514
10016
|
options;
|
|
@@ -9546,12 +10048,106 @@ var PostgresEventLog = class {
|
|
|
9546
10048
|
this.events = [];
|
|
9547
10049
|
}
|
|
9548
10050
|
};
|
|
10051
|
+
var AsyncPostgresEventLog = class {
|
|
10052
|
+
constructor(client, options) {
|
|
10053
|
+
this.client = client;
|
|
10054
|
+
this.tenantId = requireTenantId(options);
|
|
10055
|
+
}
|
|
10056
|
+
client;
|
|
10057
|
+
tenantId;
|
|
10058
|
+
async record(type, data = {}) {
|
|
10059
|
+
const event = {
|
|
10060
|
+
id: randomUUID(),
|
|
10061
|
+
type,
|
|
10062
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10063
|
+
data: { ...data, tenantId: this.tenantId }
|
|
10064
|
+
};
|
|
10065
|
+
await this.client.query(
|
|
10066
|
+
`insert into coco_runtime_events (id, tenant_id, type, timestamp, data)
|
|
10067
|
+
values ($1, $2, $3, $4, $5::jsonb)`,
|
|
10068
|
+
[event.id, this.tenantId, event.type, event.timestamp, JSON.stringify(event.data)]
|
|
10069
|
+
);
|
|
10070
|
+
return event;
|
|
10071
|
+
}
|
|
10072
|
+
async list() {
|
|
10073
|
+
return listPostgresRuntimeEvents(this.client, { tenantId: this.tenantId });
|
|
10074
|
+
}
|
|
10075
|
+
async count() {
|
|
10076
|
+
const result = await this.client.query(
|
|
10077
|
+
"select count(*)::int as count from coco_runtime_events where tenant_id = $1",
|
|
10078
|
+
[this.tenantId]
|
|
10079
|
+
);
|
|
10080
|
+
return Number(result.rows[0]?.count ?? 0);
|
|
10081
|
+
}
|
|
10082
|
+
async clear() {
|
|
10083
|
+
await this.client.query("delete from coco_runtime_events where tenant_id = $1", [
|
|
10084
|
+
this.tenantId
|
|
10085
|
+
]);
|
|
10086
|
+
}
|
|
10087
|
+
};
|
|
10088
|
+
var PostgresRuntimeAuditStore = class {
|
|
10089
|
+
constructor(client, options) {
|
|
10090
|
+
this.client = client;
|
|
10091
|
+
this.tenantId = requireTenantId(options);
|
|
10092
|
+
}
|
|
10093
|
+
client;
|
|
10094
|
+
tenantId;
|
|
10095
|
+
async record(input) {
|
|
10096
|
+
const record = {
|
|
10097
|
+
id: randomUUID(),
|
|
10098
|
+
tenantId: this.tenantId,
|
|
10099
|
+
type: input.type,
|
|
10100
|
+
subject: input.subject,
|
|
10101
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10102
|
+
data: { ...input.data }
|
|
10103
|
+
};
|
|
10104
|
+
await this.client.query(
|
|
10105
|
+
`insert into coco_runtime_audit_events
|
|
10106
|
+
(id, tenant_id, type, subject, timestamp, data)
|
|
10107
|
+
values ($1, $2, $3, $4, $5, $6::jsonb)`,
|
|
10108
|
+
[
|
|
10109
|
+
record.id,
|
|
10110
|
+
record.tenantId,
|
|
10111
|
+
record.type,
|
|
10112
|
+
record.subject ?? null,
|
|
10113
|
+
record.timestamp,
|
|
10114
|
+
JSON.stringify(record.data)
|
|
10115
|
+
]
|
|
10116
|
+
);
|
|
10117
|
+
return record;
|
|
10118
|
+
}
|
|
10119
|
+
async list() {
|
|
10120
|
+
const result = await this.client.query(
|
|
10121
|
+
`select * from coco_runtime_audit_events
|
|
10122
|
+
where tenant_id = $1
|
|
10123
|
+
order by timestamp asc`,
|
|
10124
|
+
[this.tenantId]
|
|
10125
|
+
);
|
|
10126
|
+
return result.rows.map((row) => ({
|
|
10127
|
+
id: row.id,
|
|
10128
|
+
tenantId: row.tenant_id,
|
|
10129
|
+
type: row.type,
|
|
10130
|
+
subject: row.subject ?? void 0,
|
|
10131
|
+
timestamp: dateToIso(row.timestamp),
|
|
10132
|
+
data: parseJson(row.data, {})
|
|
10133
|
+
}));
|
|
10134
|
+
}
|
|
10135
|
+
};
|
|
9549
10136
|
function createPostgresRuntimeSessionStore(client, options) {
|
|
9550
10137
|
return new PostgresRuntimeSessionStore(client, options);
|
|
9551
10138
|
}
|
|
9552
10139
|
function createPostgresEventLog(client, options) {
|
|
9553
10140
|
return new PostgresEventLog(client, options);
|
|
9554
10141
|
}
|
|
10142
|
+
function createAsyncPostgresRuntimeSessionStore(client, options) {
|
|
10143
|
+
return new AsyncPostgresRuntimeSessionStore(client, options);
|
|
10144
|
+
}
|
|
10145
|
+
function createAsyncPostgresEventLog(client, options) {
|
|
10146
|
+
return new AsyncPostgresEventLog(client, options);
|
|
10147
|
+
}
|
|
10148
|
+
function createPostgresRuntimeAuditStore(client, options) {
|
|
10149
|
+
return new PostgresRuntimeAuditStore(client, options);
|
|
10150
|
+
}
|
|
9555
10151
|
async function listPostgresRuntimeEvents(client, options = {}) {
|
|
9556
10152
|
const result = await client.query(
|
|
9557
10153
|
`select * from coco_runtime_events
|
|
@@ -9563,6 +10159,76 @@ async function listPostgresRuntimeEvents(client, options = {}) {
|
|
|
9563
10159
|
return result.rows.map(rowToEvent);
|
|
9564
10160
|
}
|
|
9565
10161
|
|
|
10162
|
+
// src/runtime/tenant-scope.ts
|
|
10163
|
+
var TenantScopedRuntimeSessionStore = class {
|
|
10164
|
+
constructor(inner, options) {
|
|
10165
|
+
this.inner = inner;
|
|
10166
|
+
this.options = options;
|
|
10167
|
+
}
|
|
10168
|
+
inner;
|
|
10169
|
+
options;
|
|
10170
|
+
create(options = {}) {
|
|
10171
|
+
return this.inner.create({
|
|
10172
|
+
...options,
|
|
10173
|
+
metadata: this.withTenant(options.metadata)
|
|
10174
|
+
});
|
|
10175
|
+
}
|
|
10176
|
+
get(id) {
|
|
10177
|
+
const session = this.inner.get(id);
|
|
10178
|
+
return session && this.belongsToTenant(session) ? session : void 0;
|
|
10179
|
+
}
|
|
10180
|
+
update(session) {
|
|
10181
|
+
if (!this.belongsToTenant(session)) {
|
|
10182
|
+
throw new Error(
|
|
10183
|
+
`Runtime session ${session.id} does not belong to tenant ${this.options.tenantId}.`
|
|
10184
|
+
);
|
|
10185
|
+
}
|
|
10186
|
+
return this.inner.update({
|
|
10187
|
+
...session,
|
|
10188
|
+
metadata: this.withTenant(session.metadata)
|
|
10189
|
+
});
|
|
10190
|
+
}
|
|
10191
|
+
list() {
|
|
10192
|
+
return this.inner.list().filter((session) => this.belongsToTenant(session));
|
|
10193
|
+
}
|
|
10194
|
+
delete(id) {
|
|
10195
|
+
if (!this.get(id)) return false;
|
|
10196
|
+
return this.inner.delete(id);
|
|
10197
|
+
}
|
|
10198
|
+
withTenant(metadata) {
|
|
10199
|
+
return { ...metadata, tenantId: this.options.tenantId };
|
|
10200
|
+
}
|
|
10201
|
+
belongsToTenant(session) {
|
|
10202
|
+
return session.metadata["tenantId"] === this.options.tenantId;
|
|
10203
|
+
}
|
|
10204
|
+
};
|
|
10205
|
+
var TenantScopedEventLog = class {
|
|
10206
|
+
constructor(inner, options) {
|
|
10207
|
+
this.inner = inner;
|
|
10208
|
+
this.options = options;
|
|
10209
|
+
}
|
|
10210
|
+
inner;
|
|
10211
|
+
options;
|
|
10212
|
+
record(type, data = {}) {
|
|
10213
|
+
return this.inner.record(type, { ...data, tenantId: this.options.tenantId });
|
|
10214
|
+
}
|
|
10215
|
+
list() {
|
|
10216
|
+
return this.inner.list().filter((event) => event.data["tenantId"] === this.options.tenantId);
|
|
10217
|
+
}
|
|
10218
|
+
count() {
|
|
10219
|
+
return this.list().length;
|
|
10220
|
+
}
|
|
10221
|
+
clear() {
|
|
10222
|
+
throw new Error("Tenant-scoped event logs do not support partial clear.");
|
|
10223
|
+
}
|
|
10224
|
+
};
|
|
10225
|
+
function createTenantScopedRuntimeSessionStore(inner, tenantId) {
|
|
10226
|
+
return new TenantScopedRuntimeSessionStore(inner, { tenantId });
|
|
10227
|
+
}
|
|
10228
|
+
function createTenantScopedEventLog(inner, tenantId) {
|
|
10229
|
+
return new TenantScopedEventLog(inner, { tenantId });
|
|
10230
|
+
}
|
|
10231
|
+
|
|
9566
10232
|
// src/runtime/extension-manifests.ts
|
|
9567
10233
|
function createMcpToolPolicy(server, tool, risk, allowedModes = ["ask", "plan", "build", "debug", "review", "architect"]) {
|
|
9568
10234
|
return {
|
|
@@ -9655,7 +10321,7 @@ function runGuardrails(stage, content, config = {}) {
|
|
|
9655
10321
|
findings.push({
|
|
9656
10322
|
id,
|
|
9657
10323
|
stage,
|
|
9658
|
-
severity: "
|
|
10324
|
+
severity: actionToSeverity(config.promptInjectionAction ?? "warn"),
|
|
9659
10325
|
message: `Potential prompt-injection pattern detected: ${id}`
|
|
9660
10326
|
});
|
|
9661
10327
|
}
|
|
@@ -9678,6 +10344,26 @@ function runGuardrails(stage, content, config = {}) {
|
|
|
9678
10344
|
findings
|
|
9679
10345
|
};
|
|
9680
10346
|
}
|
|
10347
|
+
async function runGuardrailPipeline(steps, config = {}) {
|
|
10348
|
+
const outputs = [];
|
|
10349
|
+
const findings = [];
|
|
10350
|
+
for (const step of steps) {
|
|
10351
|
+
const effectiveConfig = { ...config, ...step.config };
|
|
10352
|
+
const result = runGuardrails(step.stage, step.content, effectiveConfig);
|
|
10353
|
+
const policyFindings = await effectiveConfig.policyProvider?.evaluate({
|
|
10354
|
+
stage: step.stage,
|
|
10355
|
+
content: result.content,
|
|
10356
|
+
findings: result.findings
|
|
10357
|
+
}) ?? [];
|
|
10358
|
+
outputs.push({ stage: step.stage, content: result.content });
|
|
10359
|
+
findings.push(...result.findings, ...policyFindings);
|
|
10360
|
+
}
|
|
10361
|
+
return {
|
|
10362
|
+
allowed: !findings.some((finding) => finding.severity === "blocked"),
|
|
10363
|
+
outputs,
|
|
10364
|
+
findings
|
|
10365
|
+
};
|
|
10366
|
+
}
|
|
9681
10367
|
function validateStructuredOutput(output, schema) {
|
|
9682
10368
|
if (!schema) return [];
|
|
9683
10369
|
const result = schema.safeParse(output);
|
|
@@ -9691,6 +10377,16 @@ function validateStructuredOutput(output, schema) {
|
|
|
9691
10377
|
}
|
|
9692
10378
|
];
|
|
9693
10379
|
}
|
|
10380
|
+
function actionToSeverity(action) {
|
|
10381
|
+
switch (action) {
|
|
10382
|
+
case "allow":
|
|
10383
|
+
return "info";
|
|
10384
|
+
case "warn":
|
|
10385
|
+
return "warning";
|
|
10386
|
+
case "block":
|
|
10387
|
+
return "blocked";
|
|
10388
|
+
}
|
|
10389
|
+
}
|
|
9694
10390
|
|
|
9695
10391
|
// src/runtime/blueprints.ts
|
|
9696
10392
|
function mapActionModeToRuntimeMode(mode) {
|
|
@@ -9788,7 +10484,7 @@ var InMemoryKnowledgeRetriever = class {
|
|
|
9788
10484
|
const limit = options.limit ?? 5;
|
|
9789
10485
|
const minScore = options.minScore ?? 0;
|
|
9790
10486
|
const tenantId = tenantIdFromRetrievalOptions(options);
|
|
9791
|
-
return this.documents.filter((document) =>
|
|
10487
|
+
return this.documents.filter((document) => sourceAccessible(document, { ...options, tenantId })).map((document) => ({
|
|
9792
10488
|
...document,
|
|
9793
10489
|
score: scoreDocument(document, terms)
|
|
9794
10490
|
})).filter((source) => source.score >= minScore && source.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
@@ -9813,7 +10509,24 @@ var SimpleTextChunker = class {
|
|
|
9813
10509
|
title: document.title,
|
|
9814
10510
|
content,
|
|
9815
10511
|
url: document.url,
|
|
9816
|
-
|
|
10512
|
+
tenantId: document.tenantId,
|
|
10513
|
+
sourceId: document.sourceId,
|
|
10514
|
+
acl: document.acl,
|
|
10515
|
+
classification: document.classification,
|
|
10516
|
+
version: document.version,
|
|
10517
|
+
updatedAt: document.updatedAt,
|
|
10518
|
+
deletedAt: document.deletedAt,
|
|
10519
|
+
metadata: {
|
|
10520
|
+
...document.metadata,
|
|
10521
|
+
tenantId: document.tenantId ?? document.metadata?.["tenantId"],
|
|
10522
|
+
sourceId: document.sourceId ?? document.metadata?.["sourceId"],
|
|
10523
|
+
acl: document.acl ?? document.metadata?.["acl"],
|
|
10524
|
+
classification: document.classification ?? document.metadata?.["classification"],
|
|
10525
|
+
version: document.version ?? document.metadata?.["version"],
|
|
10526
|
+
updatedAt: document.updatedAt ?? document.metadata?.["updatedAt"],
|
|
10527
|
+
deletedAt: document.deletedAt ?? document.metadata?.["deletedAt"],
|
|
10528
|
+
chunkIndex: index
|
|
10529
|
+
}
|
|
9817
10530
|
});
|
|
9818
10531
|
index++;
|
|
9819
10532
|
offset += maxChars - overlapChars;
|
|
@@ -9832,16 +10545,104 @@ var InMemoryVectorStore = class {
|
|
|
9832
10545
|
const limit = options.limit ?? 5;
|
|
9833
10546
|
const minScore = options.minScore ?? 0;
|
|
9834
10547
|
const tenantId = tenantIdFromRetrievalOptions(options);
|
|
9835
|
-
return this.chunks.filter((chunk2) =>
|
|
10548
|
+
return this.chunks.filter((chunk2) => sourceAccessible(chunk2, { ...options, tenantId })).map((chunk2) => ({
|
|
9836
10549
|
id: chunk2.id,
|
|
9837
10550
|
title: chunk2.title,
|
|
9838
10551
|
content: chunk2.content,
|
|
9839
10552
|
url: chunk2.url,
|
|
9840
10553
|
score: cosineSimilarity(embedding, chunk2.embedding),
|
|
9841
|
-
metadata: {
|
|
10554
|
+
metadata: {
|
|
10555
|
+
...chunk2.metadata,
|
|
10556
|
+
tenantId: chunk2.tenantId ?? chunk2.metadata?.["tenantId"],
|
|
10557
|
+
sourceId: chunk2.sourceId ?? chunk2.metadata?.["sourceId"],
|
|
10558
|
+
acl: chunk2.acl ?? chunk2.metadata?.["acl"],
|
|
10559
|
+
classification: chunk2.classification ?? chunk2.metadata?.["classification"],
|
|
10560
|
+
version: chunk2.version ?? chunk2.metadata?.["version"],
|
|
10561
|
+
updatedAt: chunk2.updatedAt ?? chunk2.metadata?.["updatedAt"],
|
|
10562
|
+
deletedAt: chunk2.deletedAt ?? chunk2.metadata?.["deletedAt"],
|
|
10563
|
+
documentId: chunk2.documentId
|
|
10564
|
+
}
|
|
9842
10565
|
})).filter((source) => source.score >= minScore).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
9843
10566
|
}
|
|
9844
10567
|
};
|
|
10568
|
+
function createDocumentAccessPolicy(input) {
|
|
10569
|
+
return {
|
|
10570
|
+
canAccess({ document, options }) {
|
|
10571
|
+
const tenantId = options.tenantId ?? input.tenantId;
|
|
10572
|
+
const userId = options.userId ?? input.userId;
|
|
10573
|
+
const roles = options.roles ?? input.roles ?? [];
|
|
10574
|
+
const groups = options.groups ?? input.groups ?? [];
|
|
10575
|
+
const metadata = document.metadata ?? {};
|
|
10576
|
+
if (document.deletedAt ?? metadata["deletedAt"]) return false;
|
|
10577
|
+
const documentTenantId = document.tenantId ?? stringMetadata(metadata, "tenantId");
|
|
10578
|
+
const visibility = stringMetadata(metadata, "visibility");
|
|
10579
|
+
if (tenantId && documentTenantId !== tenantId && visibility !== "global") return false;
|
|
10580
|
+
const acl = document.acl ?? metadata["acl"];
|
|
10581
|
+
if (!acl) return input.requireAcl !== true;
|
|
10582
|
+
if (acl.public === true) return true;
|
|
10583
|
+
if (userId && acl.userIds?.includes(userId)) return true;
|
|
10584
|
+
if (acl.roles?.some((role) => roles.includes(role))) return true;
|
|
10585
|
+
if (acl.groups?.some((group) => groups.includes(group))) return true;
|
|
10586
|
+
return false;
|
|
10587
|
+
}
|
|
10588
|
+
};
|
|
10589
|
+
}
|
|
10590
|
+
function createRagIngestionJob(id, pipeline) {
|
|
10591
|
+
const job = {
|
|
10592
|
+
id,
|
|
10593
|
+
status: "pending",
|
|
10594
|
+
async run() {
|
|
10595
|
+
job.status = "running";
|
|
10596
|
+
job.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
10597
|
+
try {
|
|
10598
|
+
job.result = await pipeline.ingest();
|
|
10599
|
+
job.status = "completed";
|
|
10600
|
+
} catch (error) {
|
|
10601
|
+
job.status = "failed";
|
|
10602
|
+
job.error = error instanceof Error ? error.message : String(error);
|
|
10603
|
+
} finally {
|
|
10604
|
+
job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
10605
|
+
}
|
|
10606
|
+
return { ...job };
|
|
10607
|
+
}
|
|
10608
|
+
};
|
|
10609
|
+
return job;
|
|
10610
|
+
}
|
|
10611
|
+
function verifyCitations(citations, sources) {
|
|
10612
|
+
const byId = new Map(sources.map((source) => [source.id, source]));
|
|
10613
|
+
const unsupportedCitations = [];
|
|
10614
|
+
const missingSourceIds = [];
|
|
10615
|
+
for (const citation of citations) {
|
|
10616
|
+
const source = byId.get(citation.sourceId);
|
|
10617
|
+
if (!source) {
|
|
10618
|
+
missingSourceIds.push(citation.sourceId);
|
|
10619
|
+
unsupportedCitations.push(citation);
|
|
10620
|
+
}
|
|
10621
|
+
}
|
|
10622
|
+
return {
|
|
10623
|
+
valid: unsupportedCitations.length === 0,
|
|
10624
|
+
unsupportedCitations,
|
|
10625
|
+
missingSourceIds
|
|
10626
|
+
};
|
|
10627
|
+
}
|
|
10628
|
+
function evaluateGroundedness(answer, sources) {
|
|
10629
|
+
const answerTerms = new Set(tokenize(answer));
|
|
10630
|
+
const sourceTerms = new Set(sources.flatMap((source) => tokenize(source.content)));
|
|
10631
|
+
const overlap = [...answerTerms].filter((term) => sourceTerms.has(term)).length;
|
|
10632
|
+
const score = answerTerms.size === 0 ? 0 : overlap / answerTerms.size;
|
|
10633
|
+
const injection = /ignore|override|bypass|reveal|exfiltrate/i.test(
|
|
10634
|
+
sources.map((source) => source.content).join("\n")
|
|
10635
|
+
);
|
|
10636
|
+
const reasons = [];
|
|
10637
|
+
if (score < 0.2) reasons.push("Answer has low lexical support in retrieved sources.");
|
|
10638
|
+
if (injection) reasons.push("Retrieved sources contain prompt-injection indicators.");
|
|
10639
|
+
return {
|
|
10640
|
+
grounded: score >= 0.2 && !injection,
|
|
10641
|
+
score,
|
|
10642
|
+
blocked: injection,
|
|
10643
|
+
reasons
|
|
10644
|
+
};
|
|
10645
|
+
}
|
|
9845
10646
|
function createInMemoryKnowledgeRetriever(documents) {
|
|
9846
10647
|
return new InMemoryKnowledgeRetriever(documents);
|
|
9847
10648
|
}
|
|
@@ -9908,10 +10709,15 @@ function mergeRetrievalOptionsWithRuntimeContext(options, runtimeContext) {
|
|
|
9908
10709
|
function tenantIdFromRetrievalOptions(options) {
|
|
9909
10710
|
return options.tenantId ?? options.runtimeContext?.tenant?.id;
|
|
9910
10711
|
}
|
|
9911
|
-
function
|
|
9912
|
-
if (
|
|
9913
|
-
|
|
9914
|
-
|
|
10712
|
+
function sourceAccessible(document, options) {
|
|
10713
|
+
if (options.documentAccessPolicy) {
|
|
10714
|
+
return options.documentAccessPolicy.canAccess({ document, options });
|
|
10715
|
+
}
|
|
10716
|
+
const metadata = document.metadata ?? {};
|
|
10717
|
+
if (document.deletedAt ?? metadata["deletedAt"]) return false;
|
|
10718
|
+
if (!options.tenantId || options.dataBoundary?.allowCrossTenantMemory === true) return true;
|
|
10719
|
+
const sourceTenantId = document.tenantId ?? metadata["tenantId"];
|
|
10720
|
+
return sourceTenantId === options.tenantId || metadata["visibility"] === "global";
|
|
9915
10721
|
}
|
|
9916
10722
|
async function retrieveFromVectorPipeline(query, options, retrievalOptions) {
|
|
9917
10723
|
if (!options.embeddingProvider || !options.vectorStore) return [];
|
|
@@ -9919,6 +10725,10 @@ async function retrieveFromVectorPipeline(query, options, retrievalOptions) {
|
|
|
9919
10725
|
if (!embedding) return [];
|
|
9920
10726
|
return options.vectorStore.search(embedding, retrievalOptions);
|
|
9921
10727
|
}
|
|
10728
|
+
function stringMetadata(metadata, key) {
|
|
10729
|
+
const value = metadata[key];
|
|
10730
|
+
return typeof value === "string" ? value : void 0;
|
|
10731
|
+
}
|
|
9922
10732
|
function cosineSimilarity(a, b) {
|
|
9923
10733
|
if (a.length === 0 || b.length === 0 || a.length !== b.length) return 0;
|
|
9924
10734
|
let dot = 0;
|
|
@@ -10043,7 +10853,188 @@ var RuntimeToolExecutor = class {
|
|
|
10043
10853
|
function createRuntimeToolExecutor(options) {
|
|
10044
10854
|
return new RuntimeToolExecutor(options);
|
|
10045
10855
|
}
|
|
10856
|
+
var InMemoryTraceExporter = class {
|
|
10857
|
+
spans = [];
|
|
10858
|
+
async export(span) {
|
|
10859
|
+
this.spans.push(structuredClone(span));
|
|
10860
|
+
}
|
|
10861
|
+
list() {
|
|
10862
|
+
return this.spans.map((span) => structuredClone(span));
|
|
10863
|
+
}
|
|
10864
|
+
clear() {
|
|
10865
|
+
this.spans = [];
|
|
10866
|
+
}
|
|
10867
|
+
};
|
|
10868
|
+
var FileTraceExporter = class {
|
|
10869
|
+
constructor(filePath) {
|
|
10870
|
+
this.filePath = filePath;
|
|
10871
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
10872
|
+
}
|
|
10873
|
+
filePath;
|
|
10874
|
+
async export(span) {
|
|
10875
|
+
appendFileSync(this.filePath, JSON.stringify(span) + "\n", "utf-8");
|
|
10876
|
+
}
|
|
10877
|
+
list() {
|
|
10878
|
+
try {
|
|
10879
|
+
return readFileSync(this.filePath, "utf-8").split("\n").filter(Boolean).map((line) => JSON.parse(line));
|
|
10880
|
+
} catch {
|
|
10881
|
+
return [];
|
|
10882
|
+
}
|
|
10883
|
+
}
|
|
10884
|
+
clear() {
|
|
10885
|
+
writeFileSync(this.filePath, "", "utf-8");
|
|
10886
|
+
}
|
|
10887
|
+
};
|
|
10888
|
+
var OpenTelemetryTraceExporter = class {
|
|
10889
|
+
spans = [];
|
|
10890
|
+
async export(span) {
|
|
10891
|
+
this.spans.push(structuredClone(span));
|
|
10892
|
+
}
|
|
10893
|
+
toOtlpJson() {
|
|
10894
|
+
return {
|
|
10895
|
+
resourceSpans: [
|
|
10896
|
+
{
|
|
10897
|
+
scopeSpans: [
|
|
10898
|
+
{
|
|
10899
|
+
spans: this.spans.map((span) => ({
|
|
10900
|
+
traceId: span.traceId,
|
|
10901
|
+
spanId: span.spanId,
|
|
10902
|
+
parentSpanId: span.parentSpanId,
|
|
10903
|
+
name: span.name,
|
|
10904
|
+
kind: span.kind,
|
|
10905
|
+
startTimeUnixNano: Date.parse(span.timestamp) * 1e6,
|
|
10906
|
+
endTimeUnixNano: Date.parse(span.timestamp) * 1e6,
|
|
10907
|
+
attributes: Object.entries(span.attributes).map(([key, value]) => ({
|
|
10908
|
+
key,
|
|
10909
|
+
value: { stringValue: JSON.stringify(value) }
|
|
10910
|
+
}))
|
|
10911
|
+
}))
|
|
10912
|
+
}
|
|
10913
|
+
]
|
|
10914
|
+
}
|
|
10915
|
+
]
|
|
10916
|
+
};
|
|
10917
|
+
}
|
|
10918
|
+
};
|
|
10919
|
+
async function exportRuntimeEventsAsSpans(events, exporter) {
|
|
10920
|
+
const spans = events.map(eventToSpan);
|
|
10921
|
+
for (const span of spans) {
|
|
10922
|
+
await exporter.export(span);
|
|
10923
|
+
}
|
|
10924
|
+
await exporter.flush?.();
|
|
10925
|
+
return spans;
|
|
10926
|
+
}
|
|
10927
|
+
function eventToSpan(event) {
|
|
10928
|
+
const trace = isRecord(event.data["trace"]) ? event.data["trace"] : {};
|
|
10929
|
+
const traceId = stringValue(trace["traceId"]) ?? stringValue(event.data["traceId"]) ?? event.id;
|
|
10930
|
+
const spanId = stringValue(trace["spanId"]) ?? stringValue(event.data["spanId"]) ?? event.id;
|
|
10931
|
+
return {
|
|
10932
|
+
id: event.id,
|
|
10933
|
+
traceId,
|
|
10934
|
+
spanId,
|
|
10935
|
+
parentSpanId: stringValue(trace["parentSpanId"]) ?? stringValue(event.data["parentSpanId"]),
|
|
10936
|
+
kind: inferSpanKind(event),
|
|
10937
|
+
name: event.type,
|
|
10938
|
+
timestamp: event.timestamp,
|
|
10939
|
+
attributes: redactTraceAttributes(event.data)
|
|
10940
|
+
};
|
|
10941
|
+
}
|
|
10942
|
+
function collectRuntimeMetrics(events) {
|
|
10943
|
+
const snapshot = {
|
|
10944
|
+
events: events.length,
|
|
10945
|
+
byKind: {
|
|
10946
|
+
workflow: 0,
|
|
10947
|
+
agent: 0,
|
|
10948
|
+
llm: 0,
|
|
10949
|
+
tool: 0,
|
|
10950
|
+
rag: 0,
|
|
10951
|
+
gate: 0,
|
|
10952
|
+
handoff: 0,
|
|
10953
|
+
state: 0,
|
|
10954
|
+
runtime: 0
|
|
10955
|
+
},
|
|
10956
|
+
tokens: { input: 0, output: 0 },
|
|
10957
|
+
estimatedCostUsd: 0,
|
|
10958
|
+
retries: 0,
|
|
10959
|
+
policyBlocks: 0,
|
|
10960
|
+
errorsByClass: {},
|
|
10961
|
+
toolsUsed: {},
|
|
10962
|
+
gatesFailed: 0,
|
|
10963
|
+
tenantUsage: {}
|
|
10964
|
+
};
|
|
10965
|
+
for (const event of events) {
|
|
10966
|
+
const kind = inferSpanKind(event);
|
|
10967
|
+
snapshot.byKind[kind] += 1;
|
|
10968
|
+
const inputTokens = numberValue(event.data["inputTokens"]);
|
|
10969
|
+
const outputTokens = numberValue(event.data["outputTokens"]);
|
|
10970
|
+
const estimatedCostUsd = numberValue(event.data["estimatedCostUsd"]);
|
|
10971
|
+
snapshot.tokens.input += inputTokens;
|
|
10972
|
+
snapshot.tokens.output += outputTokens;
|
|
10973
|
+
snapshot.estimatedCostUsd += estimatedCostUsd;
|
|
10974
|
+
if (event.data["attempt"] && numberValue(event.data["attempt"]) > 1) snapshot.retries += 1;
|
|
10975
|
+
if (event.type === "tool.blocked" || event.data["runtimePolicyBlocked"] === true) {
|
|
10976
|
+
snapshot.policyBlocks += 1;
|
|
10977
|
+
}
|
|
10978
|
+
if (event.type.endsWith(".failed") || event.type === "error") {
|
|
10979
|
+
const key = stringValue(event.data["error"]) ?? event.type;
|
|
10980
|
+
snapshot.errorsByClass[key] = (snapshot.errorsByClass[key] ?? 0) + 1;
|
|
10981
|
+
}
|
|
10982
|
+
const tool = stringValue(event.data["tool"]) ?? stringValue(event.data["toolName"]);
|
|
10983
|
+
if (tool) snapshot.toolsUsed[tool] = (snapshot.toolsUsed[tool] ?? 0) + 1;
|
|
10984
|
+
if (event.type === "workflow.gate.failed") snapshot.gatesFailed += 1;
|
|
10985
|
+
const tenantId = stringValue(event.data["tenantId"]);
|
|
10986
|
+
if (tenantId) {
|
|
10987
|
+
snapshot.tenantUsage[tenantId] ??= {
|
|
10988
|
+
events: 0,
|
|
10989
|
+
inputTokens: 0,
|
|
10990
|
+
outputTokens: 0,
|
|
10991
|
+
estimatedCostUsd: 0
|
|
10992
|
+
};
|
|
10993
|
+
snapshot.tenantUsage[tenantId].events += 1;
|
|
10994
|
+
snapshot.tenantUsage[tenantId].inputTokens += inputTokens;
|
|
10995
|
+
snapshot.tenantUsage[tenantId].outputTokens += outputTokens;
|
|
10996
|
+
snapshot.tenantUsage[tenantId].estimatedCostUsd += estimatedCostUsd;
|
|
10997
|
+
}
|
|
10998
|
+
}
|
|
10999
|
+
return snapshot;
|
|
11000
|
+
}
|
|
11001
|
+
function redactTraceAttributes(input) {
|
|
11002
|
+
return redactUnknown(input);
|
|
11003
|
+
}
|
|
11004
|
+
function inferSpanKind(event) {
|
|
11005
|
+
if (event.type.startsWith("workflow.gate")) return "gate";
|
|
11006
|
+
if (event.type.startsWith("workflow.")) return "workflow";
|
|
11007
|
+
if (event.type.startsWith("agent.handoff")) return "handoff";
|
|
11008
|
+
if (event.type.startsWith("agent.")) return "agent";
|
|
11009
|
+
if (event.type.startsWith("tool.") || event.type === "agent.tool.called") return "tool";
|
|
11010
|
+
if (event.type.startsWith("shared_state.") || event.type.startsWith("checkpoint.")) {
|
|
11011
|
+
return "state";
|
|
11012
|
+
}
|
|
11013
|
+
if (event.type.startsWith("turn.")) return "llm";
|
|
11014
|
+
return "runtime";
|
|
11015
|
+
}
|
|
11016
|
+
function redactUnknown(value) {
|
|
11017
|
+
if (typeof value === "string") {
|
|
11018
|
+
return redactSecrets(value, { enabled: true }).content;
|
|
11019
|
+
}
|
|
11020
|
+
if (Array.isArray(value)) return value.map(redactUnknown);
|
|
11021
|
+
if (isRecord(value)) {
|
|
11022
|
+
return Object.fromEntries(
|
|
11023
|
+
Object.entries(value).map(([key, nested]) => [key, redactUnknown(nested)])
|
|
11024
|
+
);
|
|
11025
|
+
}
|
|
11026
|
+
return value;
|
|
11027
|
+
}
|
|
11028
|
+
function isRecord(value) {
|
|
11029
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11030
|
+
}
|
|
11031
|
+
function stringValue(value) {
|
|
11032
|
+
return typeof value === "string" ? value : void 0;
|
|
11033
|
+
}
|
|
11034
|
+
function numberValue(value) {
|
|
11035
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
11036
|
+
}
|
|
10046
11037
|
|
|
10047
|
-
export { AGENT_MODES, AgentGraphEngine, AgentRunner, AgentRuntime, DEFAULT_WORKFLOWS, DefaultPermissionPolicy, DefaultRuntimeTurnRunner, FileEventLog, FileRuntimeSessionStore, FileSharedWorkspaceStore, InMemoryEventLog, InMemoryKnowledgeRetriever, InMemoryRuntimeSessionStore, InMemorySharedWorkspaceStore, InMemoryVectorStore, PostgresEventLog, PostgresRuntimeSessionStore, ProviderRegistry, RuntimeToolExecutor, SharedWorkspaceState, SimpleTextChunker, ToolCallingRuntimeTurnRunner, WorkflowCatalog, WorkflowEngine, WorkflowRegistry, createAgentArtifact, createAgentFromBlueprint, createAgentGraphEngine, createAgentRunner, createAgentRuntime, createAgentTraceContext, createBaseBlueprint, createDefaultRuntimeTurnRunner, createEventLog, createFileEventLog, createFileRuntimeSessionStore, createInMemoryKnowledgeRetriever, createInMemoryVectorStore, createMcpToolPolicy, createPermissionPolicy, createPostgresEventLog, createPostgresRuntimeSessionQueries, createPostgresRuntimeSessionStore, createProviderRegistry, createRagPipeline, createRuntimeHttpServer, createRuntimeRequestContext, createRuntimeSessionStore, createRuntimeToolExecutor, createSafeToolRegistry, createSimpleTextChunker, createSummaryArtifact, createToolCallingRuntimeTurnRunner, createWorkflowCatalog, createWorkflowEngine, createWorkflowRegistry, defaultPublicGuardrails, dryRunAgentGraphNodeExecutor, evaluateAgentToolPolicy, formatRetrievedSourcesForPrompt, getAgentMode, isAgentMode, listAgentModes, listLegacyAgentRoleMappings, listPostgresRuntimeEvents, mapActionModeToRuntimeMode, mapLegacyAgentRole, mergeRuntimePolicy, normalizeAgentRunResult, redactSecrets, runGuardrails, runtimeContextToMetadata, validateAgentCapabilities, validateAgentGraph, validateStructuredOutput, workflowToAgentGraph };
|
|
11038
|
+
export { AGENT_MODES, AgentDefinitionRegistry, AgentGraphEngine, AgentRunner, AgentRuntime, AsyncPostgresEventLog, AsyncPostgresRuntimeSessionStore, DEFAULT_WORKFLOWS, DefaultPermissionPolicy, DefaultRuntimeTurnRunner, FileEventLog, FileRuntimeSessionStore, FileSharedWorkspaceStore, FileTraceExporter, InMemoryEventLog, InMemoryKnowledgeRetriever, InMemoryRuntimeSessionStore, InMemorySharedWorkspaceStore, InMemoryTraceExporter, InMemoryVectorStore, OpenTelemetryTraceExporter, PostgresEventLog, PostgresRuntimeAuditStore, PostgresRuntimeSessionStore, ProviderRegistry, RuntimeAgentNodeExecutor, RuntimePolicyViolation, RuntimeToolExecutor, SharedWorkspaceState, SimpleTextChunker, TenantScopedEventLog, TenantScopedRuntimeSessionStore, ToolCallingRuntimeTurnRunner, WorkflowCatalog, WorkflowEngine, WorkflowRegistry, assertRuntimeTenantBoundary, assertRuntimeTurnWithinPolicy, collectRuntimeMetrics, createAgentArtifact, createAgentDefinitionRegistry, createAgentFromBlueprint, createAgentGraphEngine, createAgentRunner, createAgentRuntime, createAgentTraceContext, createAsyncPostgresEventLog, createAsyncPostgresRuntimeSessionStore, createBaseBlueprint, createDefaultRuntimeTurnRunner, createDocumentAccessPolicy, createEventLog, createFileEventLog, createFileRuntimeSessionStore, createInMemoryKnowledgeRetriever, createInMemoryVectorStore, createMcpToolPolicy, createPermissionPolicy, createPostgresEventLog, createPostgresRuntimeAuditStore, createPostgresRuntimeSessionQueries, createPostgresRuntimeSessionStore, createProviderRegistry, createRagIngestionJob, createRagPipeline, createRetentionCutoffs, createRuntimeAgentNodeExecutor, createRuntimeHttpServer, createRuntimeRequestContext, createRuntimeSessionStore, createRuntimeTenantBoundary, createRuntimeToolExecutor, createSafeToolRegistry, createSimpleTextChunker, createSummaryArtifact, createTenantScopedEventLog, createTenantScopedRuntimeSessionStore, createToolCallingRuntimeTurnRunner, createWorkflowCatalog, createWorkflowEngine, createWorkflowRegistry, defaultPublicGuardrails, dryRunAgentGraphNodeExecutor, evaluateAgentToolPolicy, evaluateGroundedness, eventToSpan, exportRuntimeEventsAsSpans, formatRetrievedSourcesForPrompt, getAgentMode, isAgentMode, listAgentModes, listLegacyAgentRoleMappings, listPostgresRuntimeEvents, mapActionModeToRuntimeMode, mapLegacyAgentRole, mergeRuntimePolicy, normalizeAgentRunResult, redactSecrets, redactTraceAttributes, runGuardrailPipeline, runGuardrails, runtimeContextToMetadata, validateAgentCapabilities, validateAgentGraph, validateStructuredOutput, verifyCitations, workflowToAgentGraph };
|
|
10048
11039
|
//# sourceMappingURL=index.js.map
|
|
10049
11040
|
//# sourceMappingURL=index.js.map
|