@axiastudio/aioc 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/agent.d.ts +29 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +36 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +18 -0
- package/dist/errors.d.ts +37 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +46 -0
- package/dist/examples/basic/hello-world.d.ts +2 -0
- package/dist/examples/basic/hello-world.d.ts.map +1 -0
- package/dist/examples/basic/hello-world.js +20 -0
- package/dist/examples/basic/run-record-sink.d.ts +2 -0
- package/dist/examples/basic/run-record-sink.d.ts.map +1 -0
- package/dist/examples/basic/run-record-sink.js +103 -0
- package/dist/examples/basic/tools.d.ts +2 -0
- package/dist/examples/basic/tools.d.ts.map +1 -0
- package/dist/examples/basic/tools.js +84 -0
- package/dist/examples/guardrail-smoke.d.ts +2 -0
- package/dist/examples/guardrail-smoke.d.ts.map +1 -0
- package/dist/examples/guardrail-smoke.js +110 -0
- package/dist/examples/hello-run.d.ts +2 -0
- package/dist/examples/hello-run.d.ts.map +1 -0
- package/dist/examples/hello-run.js +20 -0
- package/dist/examples/learn-01-hello-run.d.ts +2 -0
- package/dist/examples/learn-01-hello-run.d.ts.map +1 -0
- package/dist/examples/learn-01-hello-run.js +29 -0
- package/dist/examples/learn-02-tool-policy.d.ts +2 -0
- package/dist/examples/learn-02-tool-policy.d.ts.map +1 -0
- package/dist/examples/learn-02-tool-policy.js +87 -0
- package/dist/examples/learn-03-controlled-handoff.d.ts +2 -0
- package/dist/examples/learn-03-controlled-handoff.d.ts.map +1 -0
- package/dist/examples/learn-03-controlled-handoff.js +84 -0
- package/dist/examples/learn-04-output-guardrail.d.ts +2 -0
- package/dist/examples/learn-04-output-guardrail.d.ts.map +1 -0
- package/dist/examples/learn-04-output-guardrail.js +61 -0
- package/dist/examples/learn-05-run-record-audit.d.ts +2 -0
- package/dist/examples/learn-05-run-record-audit.d.ts.map +1 -0
- package/dist/examples/learn-05-run-record-audit.js +135 -0
- package/dist/examples/mistral-smoke.d.ts +2 -0
- package/dist/examples/mistral-smoke.d.ts.map +1 -0
- package/dist/examples/mistral-smoke.js +63 -0
- package/dist/examples/onboarding-governance-smoke.d.ts +2 -0
- package/dist/examples/onboarding-governance-smoke.d.ts.map +1 -0
- package/dist/examples/onboarding-governance-smoke.js +477 -0
- package/dist/examples/onboarding-governance-tutorial.d.ts +2 -0
- package/dist/examples/onboarding-governance-tutorial.d.ts.map +1 -0
- package/dist/examples/onboarding-governance-tutorial.js +342 -0
- package/dist/examples/policy-smoke.d.ts +2 -0
- package/dist/examples/policy-smoke.d.ts.map +1 -0
- package/dist/examples/policy-smoke.js +137 -0
- package/dist/examples/support/scripted-provider.d.ts +8 -0
- package/dist/examples/support/scripted-provider.d.ts.map +1 -0
- package/dist/examples/support/scripted-provider.js +21 -0
- package/dist/examples/tool-policy-finance.d.ts +2 -0
- package/dist/examples/tool-policy-finance.d.ts.map +1 -0
- package/dist/examples/tool-policy-finance.js +77 -0
- package/dist/examples/tool-run.d.ts +2 -0
- package/dist/examples/tool-run.d.ts.map +1 -0
- package/dist/examples/tool-run.js +70 -0
- package/dist/guardrails.d.ts +20 -0
- package/dist/guardrails.d.ts.map +1 -0
- package/dist/guardrails.js +6 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/logger.d.ts +76 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +53 -0
- package/dist/messages.d.ts +5 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +21 -0
- package/dist/policy.d.ts +41 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +20 -0
- package/dist/provider-setup.d.ts +14 -0
- package/dist/provider-setup.d.ts.map +1 -0
- package/dist/provider-setup.js +43 -0
- package/dist/providers/base.d.ts +26 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +2 -0
- package/dist/providers/chat-completions.d.ts +13 -0
- package/dist/providers/chat-completions.d.ts.map +1 -0
- package/dist/providers/chat-completions.js +314 -0
- package/dist/providers/mistral.d.ts +8 -0
- package/dist/providers/mistral.d.ts.map +1 -0
- package/dist/providers/mistral.js +14 -0
- package/dist/providers/openai.d.ts +11 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +23 -0
- package/dist/run-context.d.ts +5 -0
- package/dist/run-context.d.ts.map +1 -0
- package/dist/run-context.js +10 -0
- package/dist/run-log-emitter.d.ts +21 -0
- package/dist/run-log-emitter.d.ts.map +1 -0
- package/dist/run-log-emitter.js +184 -0
- package/dist/run-record.d.ts +61 -0
- package/dist/run-record.d.ts.map +1 -0
- package/dist/run-record.js +2 -0
- package/dist/run-recorder-runtime.d.ts +38 -0
- package/dist/run-recorder-runtime.d.ts.map +1 -0
- package/dist/run-recorder-runtime.js +148 -0
- package/dist/run.d.ts +19 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +497 -0
- package/dist/tests/integration/chat-completions.integration.d.ts +2 -0
- package/dist/tests/integration/chat-completions.integration.d.ts.map +1 -0
- package/dist/tests/integration/chat-completions.integration.js +110 -0
- package/dist/tests/integration/index.d.ts +2 -0
- package/dist/tests/integration/index.d.ts.map +1 -0
- package/dist/tests/integration/index.js +12 -0
- package/dist/tests/regression/handoff-policy-trace.regression.d.ts +2 -0
- package/dist/tests/regression/handoff-policy-trace.regression.d.ts.map +1 -0
- package/dist/tests/regression/handoff-policy-trace.regression.js +92 -0
- package/dist/tests/regression/handoff-transition.regression.d.ts +2 -0
- package/dist/tests/regression/handoff-transition.regression.d.ts.map +1 -0
- package/dist/tests/regression/handoff-transition.regression.js +62 -0
- package/dist/tests/regression/index.d.ts +2 -0
- package/dist/tests/regression/index.d.ts.map +1 -0
- package/dist/tests/regression/index.js +14 -0
- package/dist/tests/regression/policy-default-deny.regression.d.ts +2 -0
- package/dist/tests/regression/policy-default-deny.regression.d.ts.map +1 -0
- package/dist/tests/regression/policy-default-deny.regression.js +106 -0
- package/dist/tests/support/handoff-name.d.ts +2 -0
- package/dist/tests/support/handoff-name.d.ts.map +1 -0
- package/dist/tests/support/handoff-name.js +14 -0
- package/dist/tests/support/scripted-provider.d.ts +8 -0
- package/dist/tests/support/scripted-provider.d.ts.map +1 -0
- package/dist/tests/support/scripted-provider.js +19 -0
- package/dist/tests/unit/guardrail.unit.d.ts +2 -0
- package/dist/tests/unit/guardrail.unit.d.ts.map +1 -0
- package/dist/tests/unit/guardrail.unit.js +48 -0
- package/dist/tests/unit/handoff.unit.d.ts +2 -0
- package/dist/tests/unit/handoff.unit.d.ts.map +1 -0
- package/dist/tests/unit/handoff.unit.js +178 -0
- package/dist/tests/unit/index.d.ts +2 -0
- package/dist/tests/unit/index.d.ts.map +1 -0
- package/dist/tests/unit/index.js +24 -0
- package/dist/tests/unit/logger.unit.d.ts +2 -0
- package/dist/tests/unit/logger.unit.d.ts.map +1 -0
- package/dist/tests/unit/logger.unit.js +65 -0
- package/dist/tests/unit/policy.unit.d.ts +2 -0
- package/dist/tests/unit/policy.unit.d.ts.map +1 -0
- package/dist/tests/unit/policy.unit.js +167 -0
- package/dist/tests/unit/provider-setup.unit.d.ts +2 -0
- package/dist/tests/unit/provider-setup.unit.d.ts.map +1 -0
- package/dist/tests/unit/provider-setup.unit.js +75 -0
- package/dist/tests/unit/run-record.unit.d.ts +2 -0
- package/dist/tests/unit/run-record.unit.d.ts.map +1 -0
- package/dist/tests/unit/run-record.unit.js +118 -0
- package/dist/tests/unit/run.unit.d.ts +2 -0
- package/dist/tests/unit/run.unit.d.ts.map +1 -0
- package/dist/tests/unit/run.unit.js +30 -0
- package/dist/tool.d.ts +16 -0
- package/dist/tool.d.ts.map +1 -0
- package/dist/tool.js +6 -0
- package/dist/types.d.ts +67 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/package.json +64 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runHandoffPolicyTraceRegressionTests = runHandoffPolicyTraceRegressionTests;
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const index_1 = require("../../index");
|
|
9
|
+
const handoff_name_1 = require("../support/handoff-name");
|
|
10
|
+
const scripted_provider_1 = require("../support/scripted-provider");
|
|
11
|
+
async function runHandoffPolicyTraceRegressionTests() {
|
|
12
|
+
const target = new index_1.Agent({
|
|
13
|
+
name: "TargetAgent",
|
|
14
|
+
model: "fake-model",
|
|
15
|
+
});
|
|
16
|
+
const source = new index_1.Agent({
|
|
17
|
+
name: "SourceAgent",
|
|
18
|
+
model: "fake-model",
|
|
19
|
+
handoffs: [target],
|
|
20
|
+
});
|
|
21
|
+
const handoffName = (0, handoff_name_1.toHandoffToolName)(target.name);
|
|
22
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider([
|
|
23
|
+
[
|
|
24
|
+
{
|
|
25
|
+
type: "tool_call",
|
|
26
|
+
callId: "handoff-call-1",
|
|
27
|
+
name: handoffName,
|
|
28
|
+
arguments: "{}",
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
]));
|
|
32
|
+
const denyEvents = [];
|
|
33
|
+
const denyLogger = {
|
|
34
|
+
log(event) {
|
|
35
|
+
denyEvents.push(event);
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
await strict_1.default.rejects(() => (0, index_1.run)(source, "hello", {
|
|
39
|
+
logger: denyLogger,
|
|
40
|
+
}), (error) => {
|
|
41
|
+
strict_1.default.ok(error instanceof index_1.HandoffPolicyDeniedError);
|
|
42
|
+
strict_1.default.equal(error.result.policyResult.reason, "policy_not_configured");
|
|
43
|
+
return true;
|
|
44
|
+
});
|
|
45
|
+
const denyPolicyEvent = denyEvents.find((event) => event.type === "handoff_policy_evaluated");
|
|
46
|
+
strict_1.default.ok(denyPolicyEvent);
|
|
47
|
+
strict_1.default.equal(denyPolicyEvent.handoffName, handoffName);
|
|
48
|
+
strict_1.default.equal(denyPolicyEvent.callId, "handoff-call-1");
|
|
49
|
+
strict_1.default.equal(denyPolicyEvent.toAgent, "TargetAgent");
|
|
50
|
+
strict_1.default.equal(denyPolicyEvent.decision, "deny");
|
|
51
|
+
strict_1.default.equal(denyPolicyEvent.reason, "policy_not_configured");
|
|
52
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider([
|
|
53
|
+
[
|
|
54
|
+
{
|
|
55
|
+
type: "tool_call",
|
|
56
|
+
callId: "handoff-call-2",
|
|
57
|
+
name: handoffName,
|
|
58
|
+
arguments: "{}",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
[{ type: "completed", message: "handled by target" }],
|
|
62
|
+
]));
|
|
63
|
+
const allowEvents = [];
|
|
64
|
+
const allowLogger = {
|
|
65
|
+
log(event) {
|
|
66
|
+
allowEvents.push(event);
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
const handoffPolicy = () => ({
|
|
70
|
+
decision: "allow",
|
|
71
|
+
reason: "allow_transition",
|
|
72
|
+
policyVersion: "v2",
|
|
73
|
+
metadata: {
|
|
74
|
+
gate: "strict",
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
const result = await (0, index_1.run)(source, "hello", {
|
|
78
|
+
logger: allowLogger,
|
|
79
|
+
policies: {
|
|
80
|
+
handoffPolicy,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
strict_1.default.equal(result.finalOutput, "handled by target");
|
|
84
|
+
strict_1.default.equal(result.lastAgent.name, "TargetAgent");
|
|
85
|
+
const allowPolicyEvent = allowEvents.find((event) => event.type === "handoff_policy_evaluated");
|
|
86
|
+
strict_1.default.ok(allowPolicyEvent);
|
|
87
|
+
strict_1.default.equal(allowPolicyEvent.callId, "handoff-call-2");
|
|
88
|
+
strict_1.default.equal(allowPolicyEvent.decision, "allow");
|
|
89
|
+
strict_1.default.equal(allowPolicyEvent.reason, "allow_transition");
|
|
90
|
+
strict_1.default.equal(allowPolicyEvent.policyVersion, "v2");
|
|
91
|
+
strict_1.default.equal(allowPolicyEvent.metadata?.gate, "strict");
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoff-transition.regression.d.ts","sourceRoot":"","sources":["../../../src/tests/regression/handoff-transition.regression.ts"],"names":[],"mappings":"AAWA,wBAAsB,mCAAmC,IAAI,OAAO,CAAC,IAAI,CAAC,CAmEzE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runHandoffTransitionRegressionTests = runHandoffTransitionRegressionTests;
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const index_1 = require("../../index");
|
|
9
|
+
const handoff_name_1 = require("../support/handoff-name");
|
|
10
|
+
const scripted_provider_1 = require("../support/scripted-provider");
|
|
11
|
+
async function runHandoffTransitionRegressionTests() {
|
|
12
|
+
const targetAgent = new index_1.Agent({
|
|
13
|
+
name: "Target Agent",
|
|
14
|
+
model: "fake-model",
|
|
15
|
+
});
|
|
16
|
+
const sourceAgent = new index_1.Agent({
|
|
17
|
+
name: "Source Agent",
|
|
18
|
+
model: "fake-model",
|
|
19
|
+
handoffs: [targetAgent],
|
|
20
|
+
});
|
|
21
|
+
const handoffToolName = (0, handoff_name_1.toHandoffToolName)(targetAgent.name);
|
|
22
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider([
|
|
23
|
+
[
|
|
24
|
+
{
|
|
25
|
+
type: "tool_call",
|
|
26
|
+
callId: "handoff-call-1",
|
|
27
|
+
name: handoffToolName,
|
|
28
|
+
arguments: "{}",
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
[{ type: "completed", message: "Done from target." }],
|
|
32
|
+
]));
|
|
33
|
+
const events = [];
|
|
34
|
+
const logger = {
|
|
35
|
+
log(event) {
|
|
36
|
+
events.push(event);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
const result = await (0, index_1.run)(sourceAgent, "hello", {
|
|
40
|
+
logger,
|
|
41
|
+
policies: {
|
|
42
|
+
handoffPolicy: () => ({
|
|
43
|
+
decision: "allow",
|
|
44
|
+
reason: "allow_transition",
|
|
45
|
+
policyVersion: "v1",
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
strict_1.default.equal(result.finalOutput, "Done from target.");
|
|
50
|
+
strict_1.default.equal(result.lastAgent.name, "Target Agent");
|
|
51
|
+
const activatedAgents = events
|
|
52
|
+
.filter((event) => event.type === "agent_activated")
|
|
53
|
+
.map((event) => event.agent);
|
|
54
|
+
strict_1.default.deepEqual(activatedAgents, ["Source Agent", "Target Agent"]);
|
|
55
|
+
const handoffPolicyEvent = events.find((event) => event.type === "handoff_policy_evaluated");
|
|
56
|
+
strict_1.default.ok(handoffPolicyEvent);
|
|
57
|
+
strict_1.default.equal(handoffPolicyEvent.handoffName, handoffToolName);
|
|
58
|
+
strict_1.default.equal(handoffPolicyEvent.callId, "handoff-call-1");
|
|
59
|
+
strict_1.default.equal(handoffPolicyEvent.decision, "allow");
|
|
60
|
+
strict_1.default.equal(handoffPolicyEvent.reason, "allow_transition");
|
|
61
|
+
strict_1.default.equal(handoffPolicyEvent.policyVersion, "v1");
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tests/regression/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const handoff_transition_regression_1 = require("./handoff-transition.regression");
|
|
4
|
+
const policy_default_deny_regression_1 = require("./policy-default-deny.regression");
|
|
5
|
+
async function main() {
|
|
6
|
+
await (0, policy_default_deny_regression_1.runPolicyDefaultDenyRegressionTests)();
|
|
7
|
+
await (0, handoff_transition_regression_1.runHandoffTransitionRegressionTests)();
|
|
8
|
+
process.stdout.write("Regression tests passed.\n");
|
|
9
|
+
}
|
|
10
|
+
main().catch((error) => {
|
|
11
|
+
const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
12
|
+
process.stderr.write(`${message}\n`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-default-deny.regression.d.ts","sourceRoot":"","sources":["../../../src/tests/regression/policy-default-deny.regression.ts"],"names":[],"mappings":"AAaA,wBAAsB,mCAAmC,IAAI,OAAO,CAAC,IAAI,CAAC,CAwHzE"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runPolicyDefaultDenyRegressionTests = runPolicyDefaultDenyRegressionTests;
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const zod_1 = require("zod");
|
|
9
|
+
const index_1 = require("../../index");
|
|
10
|
+
const scripted_provider_1 = require("../support/scripted-provider");
|
|
11
|
+
async function runPolicyDefaultDenyRegressionTests() {
|
|
12
|
+
let executions = 0;
|
|
13
|
+
const ping = (0, index_1.tool)({
|
|
14
|
+
name: "ping",
|
|
15
|
+
description: "Ping tool",
|
|
16
|
+
parameters: zod_1.z.object({}),
|
|
17
|
+
execute: () => {
|
|
18
|
+
executions += 1;
|
|
19
|
+
return { ok: true };
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
const agent = new index_1.Agent({
|
|
23
|
+
name: "Policy regression agent",
|
|
24
|
+
model: "fake-model",
|
|
25
|
+
tools: [ping],
|
|
26
|
+
});
|
|
27
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider([
|
|
28
|
+
[
|
|
29
|
+
{
|
|
30
|
+
type: "tool_call",
|
|
31
|
+
callId: "call-1",
|
|
32
|
+
name: "ping",
|
|
33
|
+
arguments: "{}",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
]));
|
|
37
|
+
const events = [];
|
|
38
|
+
const logger = {
|
|
39
|
+
log(event) {
|
|
40
|
+
events.push(event);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
await strict_1.default.rejects(() => (0, index_1.run)(agent, "hello", {
|
|
44
|
+
logger,
|
|
45
|
+
}), (error) => {
|
|
46
|
+
strict_1.default.ok(error instanceof index_1.ToolCallPolicyDeniedError);
|
|
47
|
+
strict_1.default.equal(error.result.policyResult.reason, "policy_not_configured");
|
|
48
|
+
return true;
|
|
49
|
+
});
|
|
50
|
+
strict_1.default.equal(executions, 0);
|
|
51
|
+
const eventTypes = events.map((event) => event.type);
|
|
52
|
+
strict_1.default.deepEqual(eventTypes, [
|
|
53
|
+
"run_started",
|
|
54
|
+
"agent_activated",
|
|
55
|
+
"turn_started",
|
|
56
|
+
"tool_call_started",
|
|
57
|
+
"tool_policy_evaluated",
|
|
58
|
+
"tool_call_failed",
|
|
59
|
+
"run_failed",
|
|
60
|
+
]);
|
|
61
|
+
const policyEvent = events.find((event) => event.type === "tool_policy_evaluated");
|
|
62
|
+
strict_1.default.ok(policyEvent);
|
|
63
|
+
strict_1.default.equal(policyEvent.toolName, "ping");
|
|
64
|
+
strict_1.default.equal(policyEvent.callId, "call-1");
|
|
65
|
+
strict_1.default.equal(policyEvent.decision, "deny");
|
|
66
|
+
strict_1.default.equal(policyEvent.reason, "policy_not_configured");
|
|
67
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider([
|
|
68
|
+
[
|
|
69
|
+
{
|
|
70
|
+
type: "tool_call",
|
|
71
|
+
callId: "call-2",
|
|
72
|
+
name: "ping",
|
|
73
|
+
arguments: "{}",
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
[{ type: "completed", message: "done" }],
|
|
77
|
+
]));
|
|
78
|
+
const allowEvents = [];
|
|
79
|
+
const allowLogger = {
|
|
80
|
+
log(event) {
|
|
81
|
+
allowEvents.push(event);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
const allowResult = await (0, index_1.run)(agent, "hello", {
|
|
85
|
+
logger: allowLogger,
|
|
86
|
+
policies: {
|
|
87
|
+
toolPolicy: () => ({
|
|
88
|
+
decision: "allow",
|
|
89
|
+
reason: "allow_ping",
|
|
90
|
+
policyVersion: "v1",
|
|
91
|
+
metadata: {
|
|
92
|
+
gate: "strict",
|
|
93
|
+
},
|
|
94
|
+
}),
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
strict_1.default.equal(allowResult.finalOutput, "done");
|
|
98
|
+
strict_1.default.equal(executions, 1);
|
|
99
|
+
const allowPolicyEvent = allowEvents.find((event) => event.type === "tool_policy_evaluated");
|
|
100
|
+
strict_1.default.ok(allowPolicyEvent);
|
|
101
|
+
strict_1.default.equal(allowPolicyEvent.callId, "call-2");
|
|
102
|
+
strict_1.default.equal(allowPolicyEvent.decision, "allow");
|
|
103
|
+
strict_1.default.equal(allowPolicyEvent.reason, "allow_ping");
|
|
104
|
+
strict_1.default.equal(allowPolicyEvent.policyVersion, "v1");
|
|
105
|
+
strict_1.default.equal(allowPolicyEvent.metadata?.gate, "strict");
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoff-name.d.ts","sourceRoot":"","sources":["../../../src/tests/support/handoff-name.ts"],"names":[],"mappings":"AASA,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toHandoffToolName = toHandoffToolName;
|
|
4
|
+
function sanitizeToolSegment(input) {
|
|
5
|
+
const sanitized = input
|
|
6
|
+
.trim()
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
9
|
+
.replace(/^_+|_+$/g, "");
|
|
10
|
+
return sanitized || "agent";
|
|
11
|
+
}
|
|
12
|
+
function toHandoffToolName(agentName) {
|
|
13
|
+
return `handoff_to_${sanitizeToolSegment(agentName)}`;
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ModelProvider, ProviderEvent, ProviderRequest } from "../../providers/base";
|
|
2
|
+
export declare class ScriptedProvider implements ModelProvider {
|
|
3
|
+
private readonly turns;
|
|
4
|
+
private index;
|
|
5
|
+
constructor(turns: ProviderEvent[][]);
|
|
6
|
+
stream<TContext = unknown>(_request: ProviderRequest<TContext>): AsyncIterable<ProviderEvent>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=scripted-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripted-provider.d.ts","sourceRoot":"","sources":["../../../src/tests/support/scripted-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAE9B,qBAAa,gBAAiB,YAAW,aAAa;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,KAAK,CAAK;gBAEN,KAAK,EAAE,aAAa,EAAE,EAAE;IAI7B,MAAM,CAAC,QAAQ,GAAG,OAAO,EAC9B,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC,GAClC,aAAa,CAAC,aAAa,CAAC;CAShC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScriptedProvider = void 0;
|
|
4
|
+
class ScriptedProvider {
|
|
5
|
+
turns;
|
|
6
|
+
index = 0;
|
|
7
|
+
constructor(turns) {
|
|
8
|
+
this.turns = turns;
|
|
9
|
+
}
|
|
10
|
+
async *stream(_request) {
|
|
11
|
+
void _request;
|
|
12
|
+
const events = this.turns[this.index] ?? [];
|
|
13
|
+
this.index += 1;
|
|
14
|
+
for (const event of events) {
|
|
15
|
+
yield event;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.ScriptedProvider = ScriptedProvider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guardrail.unit.d.ts","sourceRoot":"","sources":["../../../src/tests/unit/guardrail.unit.ts"],"names":[],"mappings":"AAkBA,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2C3D"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runGuardrailUnitTests = runGuardrailUnitTests;
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const index_1 = require("../../index");
|
|
9
|
+
const scripted_provider_1 = require("../support/scripted-provider");
|
|
10
|
+
const outputGuardrail = (0, index_1.defineOutputGuardrail)({
|
|
11
|
+
name: "block_unsafe_output",
|
|
12
|
+
execute: ({ outputText }) => ({
|
|
13
|
+
tripwireTriggered: outputText.toLowerCase().includes("unsafe"),
|
|
14
|
+
reason: "Output contains forbidden token 'unsafe'.",
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
async function runGuardrailUnitTests() {
|
|
18
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider([
|
|
19
|
+
[
|
|
20
|
+
{ type: "delta", delta: "Safe " },
|
|
21
|
+
{ type: "delta", delta: "output." },
|
|
22
|
+
{ type: "completed", message: "Safe output." },
|
|
23
|
+
],
|
|
24
|
+
]));
|
|
25
|
+
const passAgent = new index_1.Agent({
|
|
26
|
+
name: "Guardrail pass agent",
|
|
27
|
+
model: "fake-model",
|
|
28
|
+
outputGuardrails: [outputGuardrail],
|
|
29
|
+
});
|
|
30
|
+
const passResult = await (0, index_1.run)(passAgent, "hello");
|
|
31
|
+
strict_1.default.equal(passResult.finalOutput, "Safe output.");
|
|
32
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider([
|
|
33
|
+
[
|
|
34
|
+
{ type: "delta", delta: "unsafe output" },
|
|
35
|
+
{ type: "completed", message: "unsafe output" },
|
|
36
|
+
],
|
|
37
|
+
]));
|
|
38
|
+
const failAgent = new index_1.Agent({
|
|
39
|
+
name: "Guardrail fail agent",
|
|
40
|
+
model: "fake-model",
|
|
41
|
+
outputGuardrails: [outputGuardrail],
|
|
42
|
+
});
|
|
43
|
+
await strict_1.default.rejects(() => (0, index_1.run)(failAgent, "hello"), (error) => {
|
|
44
|
+
strict_1.default.ok(error instanceof index_1.OutputGuardrailTripwireTriggered);
|
|
45
|
+
strict_1.default.equal(error.result.guardrail, "block_unsafe_output");
|
|
46
|
+
return true;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoff.unit.d.ts","sourceRoot":"","sources":["../../../src/tests/unit/handoff.unit.ts"],"names":[],"mappings":"AAmDA,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAmMzD"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runHandoffUnitTests = runHandoffUnitTests;
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const zod_1 = require("zod");
|
|
9
|
+
const index_1 = require("../../index");
|
|
10
|
+
const handoff_name_1 = require("../support/handoff-name");
|
|
11
|
+
const scripted_provider_1 = require("../support/scripted-provider");
|
|
12
|
+
function createAgents() {
|
|
13
|
+
const targetAgent = new index_1.Agent({
|
|
14
|
+
name: "Target Agent",
|
|
15
|
+
model: "fake-model",
|
|
16
|
+
});
|
|
17
|
+
const sourceAgent = new index_1.Agent({
|
|
18
|
+
name: "Source Agent",
|
|
19
|
+
model: "fake-model",
|
|
20
|
+
handoffs: [targetAgent],
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
sourceAgent,
|
|
24
|
+
targetAgent,
|
|
25
|
+
handoffToolName: (0, handoff_name_1.toHandoffToolName)(targetAgent.name),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function createHandoffTurns(handoffToolName) {
|
|
29
|
+
return [
|
|
30
|
+
[
|
|
31
|
+
{
|
|
32
|
+
type: "tool_call",
|
|
33
|
+
callId: "handoff-call-1",
|
|
34
|
+
name: handoffToolName,
|
|
35
|
+
arguments: JSON.stringify({ reason: "route" }),
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
[{ type: "completed", message: "Handled by target." }],
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
async function runHandoffUnitTests() {
|
|
42
|
+
{
|
|
43
|
+
const { sourceAgent, handoffToolName } = createAgents();
|
|
44
|
+
const allowHandoffPolicy = () => ({
|
|
45
|
+
decision: "allow",
|
|
46
|
+
reason: "allow_transition",
|
|
47
|
+
});
|
|
48
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider(createHandoffTurns(handoffToolName)));
|
|
49
|
+
const result = await (0, index_1.run)(sourceAgent, "hello", {
|
|
50
|
+
policies: {
|
|
51
|
+
handoffPolicy: allowHandoffPolicy,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
strict_1.default.equal(result.finalOutput, "Handled by target.");
|
|
55
|
+
strict_1.default.equal(result.lastAgent.name, "Target Agent");
|
|
56
|
+
}
|
|
57
|
+
{
|
|
58
|
+
const { sourceAgent, handoffToolName } = createAgents();
|
|
59
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider(createHandoffTurns(handoffToolName)));
|
|
60
|
+
await strict_1.default.rejects(() => (0, index_1.run)(sourceAgent, "hello"), (error) => {
|
|
61
|
+
strict_1.default.ok(error instanceof index_1.HandoffPolicyDeniedError);
|
|
62
|
+
strict_1.default.equal(error.result.policyResult.reason, "policy_not_configured");
|
|
63
|
+
return true;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
{
|
|
67
|
+
const { sourceAgent, handoffToolName } = createAgents();
|
|
68
|
+
const denyHandoffPolicy = () => ({
|
|
69
|
+
decision: "deny",
|
|
70
|
+
reason: "target_not_allowlisted",
|
|
71
|
+
});
|
|
72
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider(createHandoffTurns(handoffToolName)));
|
|
73
|
+
await strict_1.default.rejects(() => (0, index_1.run)(sourceAgent, "hello", {
|
|
74
|
+
policies: {
|
|
75
|
+
handoffPolicy: denyHandoffPolicy,
|
|
76
|
+
},
|
|
77
|
+
}), (error) => {
|
|
78
|
+
strict_1.default.ok(error instanceof index_1.HandoffPolicyDeniedError);
|
|
79
|
+
strict_1.default.equal(error.result.policyResult.reason, "target_not_allowlisted");
|
|
80
|
+
return true;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
{
|
|
84
|
+
const { sourceAgent, handoffToolName } = createAgents();
|
|
85
|
+
const softDenyHandoffPolicy = () => (0, index_1.deny)("target_not_allowlisted", {
|
|
86
|
+
publicReason: "Escalation not permitted for this request.",
|
|
87
|
+
denyMode: "tool_result",
|
|
88
|
+
});
|
|
89
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider(createHandoffTurns(handoffToolName)));
|
|
90
|
+
const result = await (0, index_1.run)(sourceAgent, "hello", {
|
|
91
|
+
policies: {
|
|
92
|
+
handoffPolicy: softDenyHandoffPolicy,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
strict_1.default.equal(result.finalOutput, "Handled by target.");
|
|
96
|
+
strict_1.default.equal(result.lastAgent.name, "Source Agent");
|
|
97
|
+
const toolOutputItem = result.history.find((item) => item.type === "tool_call_output_item");
|
|
98
|
+
strict_1.default.deepEqual(toolOutputItem?.output, {
|
|
99
|
+
status: "denied",
|
|
100
|
+
code: "target_not_allowlisted",
|
|
101
|
+
publicReason: "Escalation not permitted for this request.",
|
|
102
|
+
data: null,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
{
|
|
106
|
+
const { sourceAgent, handoffToolName } = createAgents();
|
|
107
|
+
const failingHandoffPolicy = () => {
|
|
108
|
+
throw new Error("policy failed");
|
|
109
|
+
};
|
|
110
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider(createHandoffTurns(handoffToolName)));
|
|
111
|
+
await strict_1.default.rejects(() => (0, index_1.run)(sourceAgent, "hello", {
|
|
112
|
+
policies: {
|
|
113
|
+
handoffPolicy: failingHandoffPolicy,
|
|
114
|
+
},
|
|
115
|
+
}), (error) => {
|
|
116
|
+
strict_1.default.ok(error instanceof index_1.HandoffPolicyDeniedError);
|
|
117
|
+
strict_1.default.equal(error.result.policyResult.reason, "policy_error");
|
|
118
|
+
return true;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
{
|
|
122
|
+
const { sourceAgent, handoffToolName } = createAgents();
|
|
123
|
+
const invalidHandoffPolicy = (() => ({
|
|
124
|
+
decision: "allow",
|
|
125
|
+
}));
|
|
126
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider(createHandoffTurns(handoffToolName)));
|
|
127
|
+
await strict_1.default.rejects(() => (0, index_1.run)(sourceAgent, "hello", {
|
|
128
|
+
policies: {
|
|
129
|
+
handoffPolicy: invalidHandoffPolicy,
|
|
130
|
+
},
|
|
131
|
+
}), (error) => {
|
|
132
|
+
strict_1.default.ok(error instanceof index_1.HandoffPolicyDeniedError);
|
|
133
|
+
strict_1.default.equal(error.result.policyResult.reason, "invalid_policy_result");
|
|
134
|
+
return true;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
{
|
|
138
|
+
const targetAgent = new index_1.Agent({
|
|
139
|
+
name: "Target Agent",
|
|
140
|
+
model: "fake-model",
|
|
141
|
+
});
|
|
142
|
+
const collidingTool = (0, index_1.tool)({
|
|
143
|
+
name: (0, handoff_name_1.toHandoffToolName)(targetAgent.name),
|
|
144
|
+
description: "Colliding tool name",
|
|
145
|
+
parameters: zod_1.z.object({}),
|
|
146
|
+
execute: () => ({ ok: true }),
|
|
147
|
+
});
|
|
148
|
+
const sourceAgent = new index_1.Agent({
|
|
149
|
+
name: "Source Agent",
|
|
150
|
+
model: "fake-model",
|
|
151
|
+
tools: [collidingTool],
|
|
152
|
+
handoffs: [targetAgent],
|
|
153
|
+
});
|
|
154
|
+
const reservedHandoffName = (0, handoff_name_1.toHandoffToolName)(targetAgent.name);
|
|
155
|
+
const suffixedHandoffName = `${reservedHandoffName}_2`;
|
|
156
|
+
(0, index_1.setDefaultProvider)(new scripted_provider_1.ScriptedProvider([
|
|
157
|
+
[
|
|
158
|
+
{
|
|
159
|
+
type: "tool_call",
|
|
160
|
+
callId: "handoff-call-2",
|
|
161
|
+
name: suffixedHandoffName,
|
|
162
|
+
arguments: "{}",
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
[{ type: "completed", message: "Handled by target with suffix." }],
|
|
166
|
+
]));
|
|
167
|
+
const result = await (0, index_1.run)(sourceAgent, "hello", {
|
|
168
|
+
policies: {
|
|
169
|
+
handoffPolicy: () => ({
|
|
170
|
+
decision: "allow",
|
|
171
|
+
reason: "allow_transition",
|
|
172
|
+
}),
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
strict_1.default.equal(result.finalOutput, "Handled by target with suffix.");
|
|
176
|
+
strict_1.default.equal(result.lastAgent.name, "Target Agent");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tests/unit/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const handoff_unit_1 = require("./handoff.unit");
|
|
4
|
+
const guardrail_unit_1 = require("./guardrail.unit");
|
|
5
|
+
const logger_unit_1 = require("./logger.unit");
|
|
6
|
+
const policy_unit_1 = require("./policy.unit");
|
|
7
|
+
const provider_setup_unit_1 = require("./provider-setup.unit");
|
|
8
|
+
const run_record_unit_1 = require("./run-record.unit");
|
|
9
|
+
const run_unit_1 = require("./run.unit");
|
|
10
|
+
async function main() {
|
|
11
|
+
await (0, run_unit_1.runRunUnitTests)();
|
|
12
|
+
await (0, run_record_unit_1.runRunRecordUnitTests)();
|
|
13
|
+
await (0, logger_unit_1.runLoggerUnitTests)();
|
|
14
|
+
await (0, provider_setup_unit_1.runProviderSetupUnitTests)();
|
|
15
|
+
await (0, policy_unit_1.runPolicyUnitTests)();
|
|
16
|
+
await (0, handoff_unit_1.runHandoffUnitTests)();
|
|
17
|
+
await (0, guardrail_unit_1.runGuardrailUnitTests)();
|
|
18
|
+
process.stdout.write("Unit tests passed.\n");
|
|
19
|
+
}
|
|
20
|
+
main().catch((error) => {
|
|
21
|
+
const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
22
|
+
process.stderr.write(`${message}\n`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.unit.d.ts","sourceRoot":"","sources":["../../../src/tests/unit/logger.unit.ts"],"names":[],"mappings":"AAeA,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0DxD"}
|