@cef-ai/testing 0.1.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.
Files changed (78) hide show
  1. package/README.md +132 -0
  2. package/dist/harness/clock.d.ts +26 -0
  3. package/dist/harness/clock.d.ts.map +1 -0
  4. package/dist/harness/clock.js +17 -0
  5. package/dist/harness/clock.js.map +1 -0
  6. package/dist/harness/cubby.d.ts +57 -0
  7. package/dist/harness/cubby.d.ts.map +1 -0
  8. package/dist/harness/cubby.js +94 -0
  9. package/dist/harness/cubby.js.map +1 -0
  10. package/dist/harness/dispatch.d.ts +31 -0
  11. package/dist/harness/dispatch.d.ts.map +1 -0
  12. package/dist/harness/dispatch.js +37 -0
  13. package/dist/harness/dispatch.js.map +1 -0
  14. package/dist/harness/fetch-mock.d.ts +43 -0
  15. package/dist/harness/fetch-mock.d.ts.map +1 -0
  16. package/dist/harness/fetch-mock.js +58 -0
  17. package/dist/harness/fetch-mock.js.map +1 -0
  18. package/dist/harness/lifecycle.d.ts +29 -0
  19. package/dist/harness/lifecycle.d.ts.map +1 -0
  20. package/dist/harness/lifecycle.js +37 -0
  21. package/dist/harness/lifecycle.js.map +1 -0
  22. package/dist/harness/model-mock.d.ts +49 -0
  23. package/dist/harness/model-mock.d.ts.map +1 -0
  24. package/dist/harness/model-mock.js +56 -0
  25. package/dist/harness/model-mock.js.map +1 -0
  26. package/dist/harness/publish.d.ts +29 -0
  27. package/dist/harness/publish.d.ts.map +1 -0
  28. package/dist/harness/publish.js +20 -0
  29. package/dist/harness/publish.js.map +1 -0
  30. package/dist/harness/replay.d.ts +32 -0
  31. package/dist/harness/replay.d.ts.map +1 -0
  32. package/dist/harness/replay.js +72 -0
  33. package/dist/harness/replay.js.map +1 -0
  34. package/dist/harness/snapshot.d.ts +44 -0
  35. package/dist/harness/snapshot.d.ts.map +1 -0
  36. package/dist/harness/snapshot.js +58 -0
  37. package/dist/harness/snapshot.js.map +1 -0
  38. package/dist/index.d.ts +9 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +4 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/peers/from-marketplace.d.ts +19 -0
  43. package/dist/peers/from-marketplace.d.ts.map +1 -0
  44. package/dist/peers/from-marketplace.js +22 -0
  45. package/dist/peers/from-marketplace.js.map +1 -0
  46. package/dist/peers/mock-agent.d.ts +108 -0
  47. package/dist/peers/mock-agent.d.ts.map +1 -0
  48. package/dist/peers/mock-agent.js +113 -0
  49. package/dist/peers/mock-agent.js.map +1 -0
  50. package/dist/platform/event-runtime.d.ts +28 -0
  51. package/dist/platform/event-runtime.d.ts.map +1 -0
  52. package/dist/platform/event-runtime.js +38 -0
  53. package/dist/platform/event-runtime.js.map +1 -0
  54. package/dist/platform/orchestrator.d.ts +86 -0
  55. package/dist/platform/orchestrator.d.ts.map +1 -0
  56. package/dist/platform/orchestrator.js +164 -0
  57. package/dist/platform/orchestrator.js.map +1 -0
  58. package/dist/platform/runtime.d.ts +66 -0
  59. package/dist/platform/runtime.d.ts.map +1 -0
  60. package/dist/platform/runtime.js +116 -0
  61. package/dist/platform/runtime.js.map +1 -0
  62. package/dist/platform/targeting.d.ts +29 -0
  63. package/dist/platform/targeting.d.ts.map +1 -0
  64. package/dist/platform/targeting.js +64 -0
  65. package/dist/platform/targeting.js.map +1 -0
  66. package/dist/platform/vault.d.ts +185 -0
  67. package/dist/platform/vault.d.ts.map +1 -0
  68. package/dist/platform/vault.js +200 -0
  69. package/dist/platform/vault.js.map +1 -0
  70. package/dist/test-agent.d.ts +137 -0
  71. package/dist/test-agent.d.ts.map +1 -0
  72. package/dist/test-agent.js +223 -0
  73. package/dist/test-agent.js.map +1 -0
  74. package/dist/test-platform.d.ts +167 -0
  75. package/dist/test-platform.d.ts.map +1 -0
  76. package/dist/test-platform.js +352 -0
  77. package/dist/test-platform.js.map +1 -0
  78. package/package.json +28 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * `testAgent` — the single-agent simulator-mode harness.
3
+ *
4
+ * Wires together the pieces in `./harness/*` to produce a deterministic,
5
+ * in-process environment for an agent class:
6
+ *
7
+ * - dispatch a single event and capture its publishes;
8
+ * - drive `@OnStart` / `@OnClose` lifecycle hooks;
9
+ * - back `ctx.cubby` with per-alias in-memory SQLite (with optional
10
+ * migration directories);
11
+ * - back `ctx.fetch` with a URL-pattern mock;
12
+ * - back `ctx.models[alias]` with stubs or expectation builders;
13
+ * - thread an injectable clock through everything timestamp-related.
14
+ *
15
+ * Public surface mirrors `agent-sdk.md` §9. Two `close` concerns are
16
+ * separated: `harness.close(reason)` is the lifecycle hook, while
17
+ * `harness.dispose()` releases test resources (SQLite handles).
18
+ *
19
+ * Per ADR-019 H4 the harness is engagement-aware:
20
+ * - single-class shorthand `testAgent(SomeClass, opts)` produces one
21
+ * engagement with id `"default"` (or `meta.id` from `@Engagement` if set)
22
+ * — equivalent to the pre-H4 behaviour for back-compat;
23
+ * - multi-engagement form `testAgent({ engagements: [...], targeting? }, opts)`
24
+ * accepts multiple source classes plus a targeting decision table; the
25
+ * harness evaluates targeting on first dispatch (or first start/close),
26
+ * pins the chosen engagement for the harness's life, and routes to that
27
+ * engagement's instance.
28
+ */
29
+ import { ENGAGEMENT_METADATA, } from "@cef-ai/agent-sdk";
30
+ import { createClock } from "./harness/clock.js";
31
+ import { createCubby } from "./harness/cubby.js";
32
+ import { createPublishCollector, } from "./harness/publish.js";
33
+ import { createLifecycle } from "./harness/lifecycle.js";
34
+ import { createFetchMock } from "./harness/fetch-mock.js";
35
+ import { isModelHandle, } from "./harness/model-mock.js";
36
+ import { dispatchEvent, makeEvent } from "./harness/dispatch.js";
37
+ import { captureSnapshot, restoreSnapshot, } from "./harness/snapshot.js";
38
+ import { runReplay } from "./harness/replay.js";
39
+ import { evaluateTargeting } from "./platform/targeting.js";
40
+ export function testAgent(arg, opts = {}) {
41
+ // ---- Normalise the input into a uniform engagement table ---------------
42
+ const engagements = normaliseEngagements(arg);
43
+ // ---- Wire harness primitives -------------------------------------------
44
+ const clock = createClock(opts.clock?.now);
45
+ const collector = createPublishCollector(clock.now);
46
+ const lifecycle = createLifecycle();
47
+ const fetchMock = createFetchMock();
48
+ // ---- Build cubbies ------------------------------------------------------
49
+ const cubbies = new Map();
50
+ for (const spec of opts.cubbies ?? []) {
51
+ const s = typeof spec === "string" ? { alias: spec } : spec;
52
+ if (cubbies.has(s.alias)) {
53
+ throw new Error(`[testAgent] duplicate cubby alias "${s.alias}" in opts.cubbies`);
54
+ }
55
+ cubbies.set(s.alias, createCubby(s.alias, s.migrations));
56
+ }
57
+ // ---- Validate / surface model handles ----------------------------------
58
+ // We accept both expectation-style mocks and plain `{ infer, stream }`
59
+ // stubs; `isModelHandle` enforces the shape so a typo'd handle fails
60
+ // loud at construction rather than mid-dispatch.
61
+ const models = {};
62
+ for (const [alias, handle] of Object.entries(opts.models ?? {})) {
63
+ if (!isModelHandle(handle)) {
64
+ throw new Error(`[testAgent] models["${alias}"] is not a ModelHandle (missing infer())`);
65
+ }
66
+ models[alias] = handle;
67
+ }
68
+ // ---- Frozen settings ----------------------------------------------------
69
+ const settings = Object.freeze({ ...(opts.settings ?? {}) });
70
+ // ---- Pin the engagement -------------------------------------------------
71
+ // For single-engagement harnesses we pin immediately. For multi-engagement
72
+ // harnesses we defer until first dispatch/start/close — at which point we
73
+ // evaluate targeting against `settings`.
74
+ let pinnedEngagementId = engagements.kind === "single" ? engagements.entry.id : undefined;
75
+ function pickEngagement() {
76
+ if (!pinnedEngagementId) {
77
+ pinnedEngagementId = evaluateTargeting(engagements.targeting, settings);
78
+ }
79
+ const entry = engagements.byId.get(pinnedEngagementId);
80
+ if (!entry) {
81
+ throw new Error(`[testAgent] targeting resolved engagement "${pinnedEngagementId}" but no such engagement was declared`);
82
+ }
83
+ return entry;
84
+ }
85
+ // ---- Build the ctx visible to the agent --------------------------------
86
+ // ctx is rebuilt per pickEngagement to thread the right instance into
87
+ // ctx.close(). For dispatch we just close over `pickEngagement()` to look
88
+ // up the chosen instance dynamically; this keeps the ctx shape stable.
89
+ const ctx = {
90
+ cubby(alias) {
91
+ const c = cubbies.get(alias);
92
+ if (!c) {
93
+ throw new Error(`[testAgent] cubby "${alias}" not declared in opts.cubbies`);
94
+ }
95
+ return { query: c.query.bind(c), exec: c.exec.bind(c) };
96
+ },
97
+ models: models,
98
+ fetch: fetchMock.fetch,
99
+ publish: collector.publish,
100
+ settings,
101
+ async close(reason) {
102
+ const picked = pickEngagement();
103
+ await lifecycle.close(picked.instance, ctx, picked.meta, reason ?? "closed_by_agent");
104
+ },
105
+ log: {
106
+ info() { },
107
+ warn() { },
108
+ error() { },
109
+ debug() { },
110
+ },
111
+ };
112
+ // ---- Public harness ----------------------------------------------------
113
+ const harness = {
114
+ published: collector.events,
115
+ cubby(alias) {
116
+ const c = cubbies.get(alias);
117
+ if (!c) {
118
+ throw new Error(`[testAgent] cubby "${alias}" not declared in opts.cubbies`);
119
+ }
120
+ return { query: c.query.bind(c), exec: c.exec.bind(c) };
121
+ },
122
+ async start() {
123
+ const picked = pickEngagement();
124
+ await lifecycle.start(picked.instance, ctx, picked.meta);
125
+ },
126
+ async close(reason) {
127
+ const picked = pickEngagement();
128
+ await lifecycle.close(picked.instance, ctx, picked.meta, reason ?? "closed_by_agent");
129
+ },
130
+ get lifecycle() {
131
+ return {
132
+ state: lifecycle.state,
133
+ terminalReason: lifecycle.terminalReason,
134
+ };
135
+ },
136
+ get engagement() {
137
+ return pinnedEngagementId;
138
+ },
139
+ advanceTime: clock.advanceTime,
140
+ now: clock.now,
141
+ fetchMock: () => fetchMock,
142
+ models,
143
+ async dispatch(input) {
144
+ const before = collector.events.length;
145
+ const event = makeEvent(input.type, input.payload, {
146
+ now: clock.now,
147
+ from: input.from,
148
+ });
149
+ const picked = pickEngagement();
150
+ await dispatchEvent(picked.instance, picked.meta, event, ctx);
151
+ return collector.events.slice(before);
152
+ },
153
+ async runInCubby(alias, fn) {
154
+ const c = cubbies.get(alias);
155
+ if (!c) {
156
+ throw new Error(`[testAgent] cubby "${alias}" not declared in opts.cubbies`);
157
+ }
158
+ return await fn({ query: c.query.bind(c), exec: c.exec.bind(c) }, c.raw);
159
+ },
160
+ snapshot() {
161
+ return captureSnapshot(cubbies, collector.events, clock.now());
162
+ },
163
+ restore(snap) {
164
+ restoreSnapshot(cubbies, collector.events, clock.setNow, snap);
165
+ },
166
+ replay(jsonlPath) {
167
+ return runReplay(harness, jsonlPath, cubbies);
168
+ },
169
+ dispose() {
170
+ for (const c of cubbies.values())
171
+ c.close();
172
+ },
173
+ };
174
+ return harness;
175
+ }
176
+ function normaliseEngagements(arg) {
177
+ if (typeof arg === "function") {
178
+ // Single class shorthand.
179
+ const meta = readMeta(arg);
180
+ const id = meta.id ?? "default";
181
+ const entry = { id, instance: new arg(), meta };
182
+ const byId = new Map([[id, entry]]);
183
+ return {
184
+ kind: "single",
185
+ entry,
186
+ byId,
187
+ targeting: { engagements: [{ id, rules: [] }] },
188
+ };
189
+ }
190
+ // Multi-engagement spec.
191
+ if (!Array.isArray(arg.engagements) || arg.engagements.length === 0) {
192
+ throw new Error("[testAgent] multi-engagement spec requires a non-empty engagements[]");
193
+ }
194
+ const byId = new Map();
195
+ for (const e of arg.engagements) {
196
+ if (!e.id) {
197
+ throw new Error("[testAgent] engagement entry has no id");
198
+ }
199
+ if (byId.has(e.id)) {
200
+ throw new Error(`[testAgent] duplicate engagement id "${e.id}"`);
201
+ }
202
+ const meta = readMeta(e.source);
203
+ byId.set(e.id, { id: e.id, instance: new e.source(), meta });
204
+ }
205
+ const firstId = arg.engagements[0].id;
206
+ const targeting = arg.targeting ?? {
207
+ engagements: [{ id: firstId, rules: [] }],
208
+ };
209
+ for (const entry of targeting.engagements) {
210
+ if (!byId.has(entry.id)) {
211
+ throw new Error(`[testAgent] targeting references unknown engagement "${entry.id}"`);
212
+ }
213
+ }
214
+ return { kind: "multi", byId, targeting };
215
+ }
216
+ function readMeta(ctor) {
217
+ const meta = ctor[ENGAGEMENT_METADATA];
218
+ if (!meta) {
219
+ throw new Error("[testAgent] class has no @OnEvent/@OnStart/@OnClose decorators (missing ENGAGEMENT_METADATA)");
220
+ }
221
+ return meta;
222
+ }
223
+ //# sourceMappingURL=test-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-agent.js","sourceRoot":"","sources":["../src/test-agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * `testPlatform({...})` — multi-agent + vault simulator harness.
3
+ *
4
+ * Wires the `./platform/*` pieces together so a test can:
5
+ * - spin up multiple peer agents (typed `Agent` classes or `mockAgent({...})`);
6
+ * - publish to a shared in-memory vault and watch events route between agents;
7
+ * - inspect jobs / activities created by the orchestrator;
8
+ * - run cubby-level assertions per agent via {@link TestPlatform.runInCubby}.
9
+ *
10
+ * Per ADR-019 H4 the simulator is engagement-aware: each registered agent has
11
+ * one or more engagements; targeting picks one at Job creation; the chosen
12
+ * engagement is pinned for the Job's life. Single-class registrations remain
13
+ * equivalent to one engagement with id `"default"` for back-compat.
14
+ *
15
+ * Public surface mirrors `agent-sdk.md` §10 and the contract docs so app-side
16
+ * test code uses the same vault API it would in production.
17
+ */
18
+ import { type CubbyHandle, type ModelHandle, type Targeting } from "@cef-ai/agent-sdk";
19
+ import type Database from "better-sqlite3";
20
+ import { type TestClock } from "./harness/clock.js";
21
+ import { type FetchMock } from "./harness/fetch-mock.js";
22
+ import { type ModelMockHandle } from "./harness/model-mock.js";
23
+ import { type MockAgentDescriptor, type MockSettingSpec } from "./peers/mock-agent.js";
24
+ import { type Job, type JobsFilter } from "./platform/orchestrator.js";
25
+ import { type UserAccessor, type Vault } from "./platform/vault.js";
26
+ /** Agent class with `@OnEvent` / `@OnStart` / `@OnClose` (and optionally `@Engagement`). */
27
+ export type AgentClass = new (...args: unknown[]) => object;
28
+ /** Multi-engagement source-class registration (ADR-019 H4). */
29
+ export interface MultiEngagementSpec {
30
+ /**
31
+ * One source class per engagement. Each class is independently
32
+ * instantiated; its metadata supplies handler + lifecycle method names.
33
+ */
34
+ engagements: Array<{
35
+ id: string;
36
+ source: AgentClass;
37
+ goal?: string;
38
+ }>;
39
+ /** Cubby aliases provisioned at the agent level (shared across engagements). */
40
+ cubbies?: PlatformCubbySpec[];
41
+ /** Default settings record (overridable at connect time). */
42
+ settings?: Record<string, unknown>;
43
+ /** Targeting decision table; defaults to `{ rules: [], default: <first id> }`. */
44
+ targeting?: Targeting;
45
+ /** Settings schema (forward-looking; simulator does not enforce). */
46
+ settingsSchema?: MockSettingSpec[];
47
+ }
48
+ /**
49
+ * What may be passed for each entry of `testPlatform({ agents })`.
50
+ *
51
+ * - A class with `@OnEvent` / `@OnStart` / `@OnClose` decorators
52
+ * (introspected via `ENGAGEMENT_METADATA`); single-engagement shorthand,
53
+ * id `"default"`.
54
+ * - A `mockAgent({...})` descriptor for stunt-double peers.
55
+ * - A long-form single-class registration (existing) for cubbies / settings.
56
+ * - A multi-engagement registration `{ engagements: [...], targeting?, ... }`.
57
+ */
58
+ export type AgentSource = AgentClass | MockAgentDescriptor;
59
+ /** Per-agent cubby spec (mirrors {@link CubbySpec} from `testAgent`). */
60
+ export type PlatformCubbySpec = string | {
61
+ alias: string;
62
+ migrations?: string;
63
+ };
64
+ /** Long-form single-class registration. */
65
+ export interface SingleAgentRegistration {
66
+ /** The class or mock descriptor backing this agent. */
67
+ source: AgentSource;
68
+ /** Optional cubby aliases (with optional migration dirs) to provision. */
69
+ cubbies?: PlatformCubbySpec[];
70
+ /** Optional per-agent settings record (frozen and exposed via `ctx.settings`). */
71
+ settings?: Record<string, unknown>;
72
+ }
73
+ /** Anything accepted in the `agents` map. */
74
+ export type AgentRegistration = AgentSource | SingleAgentRegistration | MultiEngagementSpec;
75
+ /** Wallet stub passed via `users[id].wallet`. ADR-019 H5. */
76
+ export interface TestWallet {
77
+ publicKey: string;
78
+ }
79
+ /**
80
+ * Per-user spec passed via `testPlatform({ users })`. The wallet is a stub
81
+ * today (the simulator only reads `publicKey` for diagnostics) but is
82
+ * accepted so test code mirrors the production shape.
83
+ */
84
+ export interface TestUser {
85
+ wallet?: TestWallet;
86
+ }
87
+ /**
88
+ * Convenience wallet stub — `testWallet("alice")` produces a deterministic
89
+ * `{ publicKey: "wallet-alice" }`. The simulator does not verify signatures.
90
+ */
91
+ export declare function testWallet(id: string): TestWallet;
92
+ export interface TestPlatformOptions {
93
+ /**
94
+ * Map of user id → user spec. Each entry gets a dedicated per-user vault
95
+ * accessible via `platform.user(id)` (ADR-019 H5). When omitted, the
96
+ * platform creates a single implicit user (id `"default"`) so legacy
97
+ * `platform.vault.scope(...)` keeps working.
98
+ */
99
+ users?: Record<string, TestUser>;
100
+ /**
101
+ * Implicit-user id when `users` is empty. Defaults to `"default"`. Kept
102
+ * for back-compat with v0.1.0 testPlatform fixtures that pre-date the
103
+ * `users` map.
104
+ */
105
+ vaultId?: string;
106
+ /** Default scope used when callers omit `vault.scope(...)` arguments. */
107
+ scope?: string;
108
+ /** Default context applied to publishes that omit `opts.context`. */
109
+ context?: string;
110
+ /**
111
+ * Map of `agentId` → registration. Plain classes / mock descriptors are
112
+ * single-engagement shorthand; the long-form variants are for cubbies,
113
+ * settings, and multi-engagement targeting.
114
+ */
115
+ agents: Record<string, AgentRegistration>;
116
+ /** Shared model handles across every agent's `ctx.models`. */
117
+ models?: Record<string, ModelHandle | ModelMockHandle>;
118
+ /** Optional initial unix-millis. */
119
+ clock?: {
120
+ now?: number;
121
+ };
122
+ }
123
+ export interface TestPlatform {
124
+ /**
125
+ * Back-compat shorthand: when 0 or 1 users are declared, returns the
126
+ * single user's vault. Throws when 2+ users are declared — callers must
127
+ * disambiguate via `platform.user(id).vault` (ADR-019 H5).
128
+ */
129
+ vault: Vault;
130
+ /**
131
+ * Per-user accessor. The id must appear in `users` or be the implicit
132
+ * default user when `users` is omitted.
133
+ */
134
+ user(id: string): UserAccessor;
135
+ /**
136
+ * Read-only view of jobs across ALL users (mirror of the orchestrator).
137
+ * For per-user views, use `platform.user(id).vault.jobs`.
138
+ */
139
+ orchestrator: {
140
+ jobs: Map<string, Job>;
141
+ list(filter?: JobsFilter): Job[];
142
+ get(jobId: string): Job | undefined;
143
+ };
144
+ /** Shared monotonic clock. */
145
+ clock: TestClock;
146
+ /** Shared fetch mock. */
147
+ fetchMock(): FetchMock;
148
+ /** Shared model handle map. */
149
+ models: Record<string, ModelHandle | ModelMockHandle>;
150
+ /**
151
+ * Run `fn` against an agent's cubby. Same shape as
152
+ * `testAgent.runInCubby(alias, fn)` but threaded through the multi-agent
153
+ * platform via `agentId`. The optional `userId` selects which user's
154
+ * cubby to inspect (ADR-019 H5); defaults to the single implicit user
155
+ * when 0 or 1 users are declared, throws when ambiguous.
156
+ */
157
+ runInCubby<T>(agentId: string, alias: string, fn: (handle: CubbyHandle, raw: Database.Database) => T | Promise<T>, userId?: string): Promise<T>;
158
+ /** Release SQLite handles across all agents. Idempotent. */
159
+ dispose(): void;
160
+ }
161
+ export declare function testPlatform(opts: TestPlatformOptions): TestPlatform;
162
+ export { mockAgent } from "./peers/mock-agent.js";
163
+ export type { MockAgentDescriptor, MockAgentSpec, MockAgentSingleSpec, MockAgentMultiEngagementSpec, MockEngagementSpec, MockEngagementDescriptor, MockSettingSpec, } from "./peers/mock-agent.js";
164
+ export { fromMarketplace } from "./peers/from-marketplace.js";
165
+ export type { AgentConnection, ConnectionEngagement, ConnectionManifest, UserAccessor, Vault, VaultEvent, VaultScope, VaultStream, } from "./platform/vault.js";
166
+ export type { Activity, ActivityStatus, Job, JobsFilter, JobState, } from "./platform/orchestrator.js";
167
+ //# sourceMappingURL=test-platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-platform.d.ts","sourceRoot":"","sources":["../src/test-platform.ts"],"names":[],"mappings":"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"}