fakeplane 0.0.0-stage → 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/LICENSE +202 -0
  2. package/NOTICE +12 -0
  3. package/README.md +225 -2
  4. package/demo/agents/careful.mjs +89 -0
  5. package/demo/agents/naive.mjs +50 -0
  6. package/demo/scenarios/large-refund-escalation.yaml +38 -0
  7. package/demo/scenarios/refund-ambiguous-timeout.yaml +40 -0
  8. package/demo/scenarios/refund-duplicate-webhook.yaml +40 -0
  9. package/dist/agent.d.ts +28 -0
  10. package/dist/agent.js +113 -0
  11. package/dist/agent.js.map +1 -0
  12. package/dist/assertions.d.ts +21 -0
  13. package/dist/assertions.js +180 -0
  14. package/dist/assertions.js.map +1 -0
  15. package/dist/backends/common.d.ts +13 -0
  16. package/dist/backends/common.js +37 -0
  17. package/dist/backends/common.js.map +1 -0
  18. package/dist/backends/generic.d.ts +79 -0
  19. package/dist/backends/generic.js +227 -0
  20. package/dist/backends/generic.js.map +1 -0
  21. package/dist/backends/graphql.d.ts +22 -0
  22. package/dist/backends/graphql.js +248 -0
  23. package/dist/backends/graphql.js.map +1 -0
  24. package/dist/backends/index.d.ts +24 -0
  25. package/dist/backends/index.js +27 -0
  26. package/dist/backends/index.js.map +1 -0
  27. package/dist/backends/linear.d.ts +123 -0
  28. package/dist/backends/linear.js +451 -0
  29. package/dist/backends/linear.js.map +1 -0
  30. package/dist/backends/slack.d.ts +92 -0
  31. package/dist/backends/slack.js +221 -0
  32. package/dist/backends/slack.js.map +1 -0
  33. package/dist/backends/zendesk.d.ts +94 -0
  34. package/dist/backends/zendesk.js +455 -0
  35. package/dist/backends/zendesk.js.map +1 -0
  36. package/dist/cli.d.ts +2 -0
  37. package/dist/cli.js +340 -0
  38. package/dist/cli.js.map +1 -0
  39. package/dist/index.d.ts +15 -0
  40. package/dist/index.js +16 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/matchers.d.ts +11 -0
  43. package/dist/matchers.js +156 -0
  44. package/dist/matchers.js.map +1 -0
  45. package/dist/mcp.d.ts +43 -0
  46. package/dist/mcp.js +116 -0
  47. package/dist/mcp.js.map +1 -0
  48. package/dist/pii.d.ts +17 -0
  49. package/dist/pii.js +79 -0
  50. package/dist/pii.js.map +1 -0
  51. package/dist/report.d.ts +13 -0
  52. package/dist/report.js +97 -0
  53. package/dist/report.js.map +1 -0
  54. package/dist/runner.d.ts +56 -0
  55. package/dist/runner.js +114 -0
  56. package/dist/runner.js.map +1 -0
  57. package/dist/scenario.d.ts +270 -0
  58. package/dist/scenario.js +270 -0
  59. package/dist/scenario.js.map +1 -0
  60. package/dist/server.d.ts +40 -0
  61. package/dist/server.js +241 -0
  62. package/dist/server.js.map +1 -0
  63. package/dist/trace.d.ts +42 -0
  64. package/dist/trace.js +432 -0
  65. package/dist/trace.js.map +1 -0
  66. package/dist/types.d.ts +70 -0
  67. package/dist/types.js +16 -0
  68. package/dist/types.js.map +1 -0
  69. package/dist/util.d.ts +13 -0
  70. package/dist/util.js +89 -0
  71. package/dist/util.js.map +1 -0
  72. package/dist/version.d.ts +1 -0
  73. package/dist/version.js +2 -0
  74. package/dist/version.js.map +1 -0
  75. package/dist/world.d.ts +149 -0
  76. package/dist/world.js +187 -0
  77. package/dist/world.js.map +1 -0
  78. package/package.json +68 -4
@@ -0,0 +1,270 @@
1
+ import { z } from "zod";
2
+ import { BACKEND_NAMES, type Seed } from "./backends/index.js";
3
+ import type { FaultSpec } from "./world.js";
4
+ export declare const AgentSchema: z.ZodObject<{
5
+ command: z.ZodOptional<z.ZodString>;
6
+ url: z.ZodOptional<z.ZodString>;
7
+ module: z.ZodOptional<z.ZodString>;
8
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
9
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
10
+ cwd: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strict>;
12
+ export type AgentSpec = z.infer<typeof AgentSchema>;
13
+ declare const TurnObject: z.ZodObject<{
14
+ via: z.ZodOptional<z.ZodEnum<{
15
+ linear: "linear";
16
+ slack: "slack";
17
+ zendesk: "zendesk";
18
+ none: "none";
19
+ }>>;
20
+ text: z.ZodOptional<z.ZodString>;
21
+ ticket: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
22
+ subject: z.ZodOptional<z.ZodString>;
23
+ from: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
24
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
+ channel: z.ZodOptional<z.ZodString>;
26
+ user: z.ZodOptional<z.ZodString>;
27
+ thread_ts: z.ZodOptional<z.ZodString>;
28
+ mention: z.ZodOptional<z.ZodBoolean>;
29
+ issue: z.ZodOptional<z.ZodString>;
30
+ team: z.ZodOptional<z.ZodString>;
31
+ title: z.ZodOptional<z.ZodString>;
32
+ event: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
33
+ deliver: z.ZodOptional<z.ZodNumber>;
34
+ concurrent: z.ZodOptional<z.ZodBoolean>;
35
+ delayMs: z.ZodOptional<z.ZodNumber>;
36
+ }, z.core.$strict>;
37
+ export type TurnSpec = z.infer<typeof TurnObject>;
38
+ export declare const AssertionSchema: z.ZodObject<{
39
+ state: z.ZodOptional<z.ZodString>;
40
+ match: z.ZodOptional<z.ZodUnknown>;
41
+ exists: z.ZodOptional<z.ZodBoolean>;
42
+ no_pii: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodObject<{
43
+ effects: z.ZodOptional<z.ZodString>;
44
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
45
+ values: z.ZodOptional<z.ZodArray<z.ZodString>>;
46
+ seeded: z.ZodOptional<z.ZodBoolean>;
47
+ types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
48
+ email: "email";
49
+ phone: "phone";
50
+ value: "value";
51
+ card: "card";
52
+ ssn: "ssn";
53
+ iban: "iban";
54
+ }>>>;
55
+ }, z.core.$strict>]>>;
56
+ no_duplicate_effects: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodObject<{
57
+ effects: z.ZodOptional<z.ZodString>;
58
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
59
+ }, z.core.$strict>]>>;
60
+ agent_output: z.ZodOptional<z.ZodUnknown>;
61
+ script: z.ZodOptional<z.ZodString>;
62
+ count: z.ZodOptional<z.ZodNumber>;
63
+ min: z.ZodOptional<z.ZodNumber>;
64
+ max: z.ZodOptional<z.ZodNumber>;
65
+ name: z.ZodOptional<z.ZodString>;
66
+ effects: z.ZodOptional<z.ZodString>;
67
+ calls: z.ZodOptional<z.ZodString>;
68
+ where: z.ZodOptional<z.ZodUnknown>;
69
+ ok: z.ZodOptional<z.ZodBoolean>;
70
+ turn: z.ZodOptional<z.ZodNumber>;
71
+ }, z.core.$strict>;
72
+ export type Assertion = z.infer<typeof AssertionSchema>;
73
+ export declare const ScenarioSchema: z.ZodObject<{
74
+ name: z.ZodOptional<z.ZodString>;
75
+ description: z.ZodOptional<z.ZodString>;
76
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
77
+ clock: z.ZodOptional<z.ZodString>;
78
+ backends: z.ZodOptional<z.ZodArray<z.ZodEnum<{
79
+ generic: "generic";
80
+ linear: "linear";
81
+ slack: "slack";
82
+ zendesk: "zendesk";
83
+ }>>>;
84
+ agent: z.ZodOptional<z.ZodObject<{
85
+ command: z.ZodOptional<z.ZodString>;
86
+ url: z.ZodOptional<z.ZodString>;
87
+ module: z.ZodOptional<z.ZodString>;
88
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
89
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
90
+ cwd: z.ZodOptional<z.ZodString>;
91
+ }, z.core.$strict>>;
92
+ seed: z.ZodOptional<z.ZodObject<{
93
+ zendesk: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
94
+ slack: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
95
+ linear: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
96
+ generic: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
97
+ }, z.core.$strict>>;
98
+ turns: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
99
+ via: z.ZodOptional<z.ZodEnum<{
100
+ linear: "linear";
101
+ slack: "slack";
102
+ zendesk: "zendesk";
103
+ none: "none";
104
+ }>>;
105
+ text: z.ZodOptional<z.ZodString>;
106
+ ticket: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
107
+ subject: z.ZodOptional<z.ZodString>;
108
+ from: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
109
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
110
+ channel: z.ZodOptional<z.ZodString>;
111
+ user: z.ZodOptional<z.ZodString>;
112
+ thread_ts: z.ZodOptional<z.ZodString>;
113
+ mention: z.ZodOptional<z.ZodBoolean>;
114
+ issue: z.ZodOptional<z.ZodString>;
115
+ team: z.ZodOptional<z.ZodString>;
116
+ title: z.ZodOptional<z.ZodString>;
117
+ event: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
118
+ deliver: z.ZodOptional<z.ZodNumber>;
119
+ concurrent: z.ZodOptional<z.ZodBoolean>;
120
+ delayMs: z.ZodOptional<z.ZodNumber>;
121
+ }, z.core.$strict>]>>>;
122
+ faults: z.ZodOptional<z.ZodArray<z.ZodObject<{
123
+ op: z.ZodOptional<z.ZodString>;
124
+ backend: z.ZodOptional<z.ZodEnum<{
125
+ generic: "generic";
126
+ linear: "linear";
127
+ slack: "slack";
128
+ zendesk: "zendesk";
129
+ }>>;
130
+ where: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
131
+ kind: z.ZodEnum<{
132
+ timeout: "timeout";
133
+ rate_limit: "rate_limit";
134
+ error: "error";
135
+ partial: "partial";
136
+ latency: "latency";
137
+ duplicate_delivery: "duplicate_delivery";
138
+ }>;
139
+ after: z.ZodOptional<z.ZodNumber>;
140
+ times: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodLiteral<"always">]>>;
141
+ status: z.ZodOptional<z.ZodNumber>;
142
+ delayMs: z.ZodOptional<z.ZodNumber>;
143
+ retryAfter: z.ZodOptional<z.ZodNumber>;
144
+ committed: z.ZodOptional<z.ZodBoolean>;
145
+ drop: z.ZodOptional<z.ZodBoolean>;
146
+ message: z.ZodOptional<z.ZodString>;
147
+ turn: z.ZodOptional<z.ZodNumber>;
148
+ copies: z.ZodOptional<z.ZodNumber>;
149
+ concurrent: z.ZodOptional<z.ZodBoolean>;
150
+ }, z.core.$strict>>>;
151
+ assert: z.ZodOptional<z.ZodArray<z.ZodObject<{
152
+ state: z.ZodOptional<z.ZodString>;
153
+ match: z.ZodOptional<z.ZodUnknown>;
154
+ exists: z.ZodOptional<z.ZodBoolean>;
155
+ no_pii: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodObject<{
156
+ effects: z.ZodOptional<z.ZodString>;
157
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
158
+ values: z.ZodOptional<z.ZodArray<z.ZodString>>;
159
+ seeded: z.ZodOptional<z.ZodBoolean>;
160
+ types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
161
+ email: "email";
162
+ phone: "phone";
163
+ value: "value";
164
+ card: "card";
165
+ ssn: "ssn";
166
+ iban: "iban";
167
+ }>>>;
168
+ }, z.core.$strict>]>>;
169
+ no_duplicate_effects: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodObject<{
170
+ effects: z.ZodOptional<z.ZodString>;
171
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
172
+ }, z.core.$strict>]>>;
173
+ agent_output: z.ZodOptional<z.ZodUnknown>;
174
+ script: z.ZodOptional<z.ZodString>;
175
+ count: z.ZodOptional<z.ZodNumber>;
176
+ min: z.ZodOptional<z.ZodNumber>;
177
+ max: z.ZodOptional<z.ZodNumber>;
178
+ name: z.ZodOptional<z.ZodString>;
179
+ effects: z.ZodOptional<z.ZodString>;
180
+ calls: z.ZodOptional<z.ZodString>;
181
+ where: z.ZodOptional<z.ZodUnknown>;
182
+ ok: z.ZodOptional<z.ZodBoolean>;
183
+ turn: z.ZodOptional<z.ZodNumber>;
184
+ }, z.core.$strict>>>;
185
+ repeat: z.ZodOptional<z.ZodNumber>;
186
+ min_pass_rate: z.ZodOptional<z.ZodNumber>;
187
+ allow_agent_errors: z.ZodOptional<z.ZodBoolean>;
188
+ }, z.core.$strict>;
189
+ export declare const ConfigSchema: z.ZodObject<{
190
+ agent: z.ZodOptional<z.ZodObject<{
191
+ command: z.ZodOptional<z.ZodString>;
192
+ url: z.ZodOptional<z.ZodString>;
193
+ module: z.ZodOptional<z.ZodString>;
194
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
195
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
196
+ cwd: z.ZodOptional<z.ZodString>;
197
+ }, z.core.$strict>>;
198
+ assert: z.ZodOptional<z.ZodArray<z.ZodObject<{
199
+ state: z.ZodOptional<z.ZodString>;
200
+ match: z.ZodOptional<z.ZodUnknown>;
201
+ exists: z.ZodOptional<z.ZodBoolean>;
202
+ no_pii: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodObject<{
203
+ effects: z.ZodOptional<z.ZodString>;
204
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
205
+ values: z.ZodOptional<z.ZodArray<z.ZodString>>;
206
+ seeded: z.ZodOptional<z.ZodBoolean>;
207
+ types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
208
+ email: "email";
209
+ phone: "phone";
210
+ value: "value";
211
+ card: "card";
212
+ ssn: "ssn";
213
+ iban: "iban";
214
+ }>>>;
215
+ }, z.core.$strict>]>>;
216
+ no_duplicate_effects: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodObject<{
217
+ effects: z.ZodOptional<z.ZodString>;
218
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
219
+ }, z.core.$strict>]>>;
220
+ agent_output: z.ZodOptional<z.ZodUnknown>;
221
+ script: z.ZodOptional<z.ZodString>;
222
+ count: z.ZodOptional<z.ZodNumber>;
223
+ min: z.ZodOptional<z.ZodNumber>;
224
+ max: z.ZodOptional<z.ZodNumber>;
225
+ name: z.ZodOptional<z.ZodString>;
226
+ effects: z.ZodOptional<z.ZodString>;
227
+ calls: z.ZodOptional<z.ZodString>;
228
+ where: z.ZodOptional<z.ZodUnknown>;
229
+ ok: z.ZodOptional<z.ZodBoolean>;
230
+ turn: z.ZodOptional<z.ZodNumber>;
231
+ }, z.core.$strict>>>;
232
+ repeat: z.ZodOptional<z.ZodNumber>;
233
+ scenarios: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
234
+ }, z.core.$strict>;
235
+ export type FakeplaneConfig = z.infer<typeof ConfigSchema> & {
236
+ dir: string;
237
+ };
238
+ export interface Scenario {
239
+ name: string;
240
+ description?: string;
241
+ tags: string[];
242
+ clock?: string;
243
+ backends?: (typeof BACKEND_NAMES)[number][];
244
+ agent?: AgentSpec;
245
+ seed: Seed;
246
+ turns: (TurnSpec & {
247
+ via: NonNullable<TurnSpec["via"]>;
248
+ })[];
249
+ faults: FaultSpec[];
250
+ assert: Assertion[];
251
+ repeat: number;
252
+ minPassRate: number;
253
+ allowAgentErrors: boolean;
254
+ }
255
+ export interface LoadedScenario {
256
+ file: string;
257
+ dir: string;
258
+ index: number;
259
+ scenario: Scenario;
260
+ }
261
+ export declare class ScenarioError extends Error {
262
+ readonly file: string;
263
+ constructor(file: string, message: string);
264
+ }
265
+ export declare function normalizeScenario(raw: unknown, file: string, index?: number): Scenario;
266
+ export declare function parseDocuments(text: string, file: string): unknown[];
267
+ export declare function loadScenarioFile(file: string): LoadedScenario[];
268
+ export declare function loadScenarios(paths: string[]): LoadedScenario[];
269
+ export declare function loadConfig(explicit?: string, cwd?: string): FakeplaneConfig | undefined;
270
+ export {};
@@ -0,0 +1,270 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
2
+ import { basename, dirname, extname, join, resolve } from "node:path";
3
+ import { parseAllDocuments } from "yaml";
4
+ import { z } from "zod";
5
+ import { BACKEND_NAMES } from "./backends/index.js";
6
+ const id = z.union([z.string(), z.number()]);
7
+ const anyObject = z.record(z.string(), z.unknown());
8
+ export const AgentSchema = z
9
+ .object({
10
+ command: z.string().optional(),
11
+ url: z.string().optional(),
12
+ module: z.string().optional(),
13
+ timeoutMs: z.number().int().positive().optional(),
14
+ env: z.record(z.string(), z.string()).optional(),
15
+ cwd: z.string().optional(),
16
+ })
17
+ .strict();
18
+ const TurnObject = z
19
+ .object({
20
+ via: z.enum(["zendesk", "slack", "linear", "none"]).optional(),
21
+ text: z.string().optional(),
22
+ // zendesk
23
+ ticket: id.optional(),
24
+ subject: z.string().optional(),
25
+ from: z.union([z.string(), anyObject]).optional(),
26
+ tags: z.array(z.string()).optional(),
27
+ // slack
28
+ channel: z.string().optional(),
29
+ user: z.string().optional(),
30
+ thread_ts: z.string().optional(),
31
+ mention: z.boolean().optional(),
32
+ // linear
33
+ issue: z.string().optional(),
34
+ team: z.string().optional(),
35
+ title: z.string().optional(),
36
+ /** Send this event payload verbatim instead of deriving one from the backend. */
37
+ event: anyObject.optional(),
38
+ /** Deliver the same event this many times (duplicate webhooks). */
39
+ deliver: z.number().int().min(1).max(20).optional(),
40
+ /** Deliver duplicates at the same time instead of one after another. */
41
+ concurrent: z.boolean().optional(),
42
+ delayMs: z.number().int().min(0).optional(),
43
+ })
44
+ .strict();
45
+ const FaultObject = z
46
+ .object({
47
+ op: z.string().optional(),
48
+ backend: z.enum(BACKEND_NAMES).optional(),
49
+ where: anyObject.optional(),
50
+ kind: z.enum(["timeout", "rate_limit", "error", "partial", "latency", "duplicate_delivery"]),
51
+ after: z.number().int().min(0).optional(),
52
+ times: z.union([z.number().int().min(1), z.literal("always")]).optional(),
53
+ status: z.number().int().min(100).max(599).optional(),
54
+ delayMs: z.number().int().min(0).optional(),
55
+ retryAfter: z.number().min(0).optional(),
56
+ committed: z.boolean().optional(),
57
+ drop: z.boolean().optional(),
58
+ message: z.string().optional(),
59
+ // duplicate_delivery
60
+ turn: z.number().int().min(1).optional(),
61
+ copies: z.number().int().min(2).max(20).optional(),
62
+ concurrent: z.boolean().optional(),
63
+ })
64
+ .strict()
65
+ .superRefine((f, ctx) => {
66
+ if (f.kind === "duplicate_delivery" && f.turn === undefined)
67
+ ctx.addIssue({ code: "custom", message: "duplicate_delivery needs `turn`" });
68
+ if (f.kind !== "duplicate_delivery" && !f.op && !f.backend)
69
+ ctx.addIssue({ code: "custom", message: "fault needs `op` or `backend`" });
70
+ });
71
+ const matcher = z.unknown();
72
+ const countFields = {
73
+ count: z.number().int().min(0).optional(),
74
+ min: z.number().int().min(0).optional(),
75
+ max: z.number().int().min(0).optional(),
76
+ };
77
+ export const AssertionSchema = z
78
+ .object({
79
+ name: z.string().optional(),
80
+ effects: z.string().optional(),
81
+ calls: z.string().optional(),
82
+ where: matcher.optional(),
83
+ ok: z.boolean().optional(),
84
+ turn: z.number().int().min(1).optional(),
85
+ ...countFields,
86
+ state: z.string().optional(),
87
+ match: matcher.optional(),
88
+ exists: z.boolean().optional(),
89
+ no_pii: z
90
+ .union([
91
+ z.literal(true),
92
+ z
93
+ .object({
94
+ effects: z.string().optional(),
95
+ allow: z.array(z.string()).optional(),
96
+ values: z.array(z.string()).optional(),
97
+ seeded: z.boolean().optional(),
98
+ types: z.array(z.enum(["email", "phone", "card", "ssn", "iban", "value"])).optional(),
99
+ })
100
+ .strict(),
101
+ ])
102
+ .optional(),
103
+ no_duplicate_effects: z.union([z.literal(true), z.object({ effects: z.string().optional(), ignore: z.array(z.string()).optional() }).strict()]).optional(),
104
+ agent_output: matcher.optional(),
105
+ script: z.string().optional(),
106
+ })
107
+ .strict()
108
+ .superRefine((a, ctx) => {
109
+ const kinds = ["effects", "calls", "state", "no_pii", "no_duplicate_effects", "agent_output", "script"].filter((k) => a[k] !== undefined);
110
+ if (kinds.length !== 1) {
111
+ ctx.addIssue({ code: "custom", message: `each assertion needs exactly one of effects, calls, state, no_pii, no_duplicate_effects, agent_output, script (got ${kinds.join(", ") || "none"})` });
112
+ }
113
+ if (a.count !== undefined && (a.min !== undefined || a.max !== undefined))
114
+ ctx.addIssue({ code: "custom", message: "use `count` or `min`/`max`, not both" });
115
+ });
116
+ export const ScenarioSchema = z
117
+ .object({
118
+ name: z.string().optional(),
119
+ description: z.string().optional(),
120
+ tags: z.array(z.string()).optional(),
121
+ clock: z.string().optional(),
122
+ backends: z.array(z.enum(BACKEND_NAMES)).optional(),
123
+ agent: AgentSchema.optional(),
124
+ seed: z
125
+ .object({ zendesk: anyObject.optional(), slack: anyObject.optional(), linear: anyObject.optional(), generic: anyObject.optional() })
126
+ .strict()
127
+ .optional(),
128
+ turns: z.array(z.union([z.string(), TurnObject])).optional(),
129
+ faults: z.array(FaultObject).optional(),
130
+ assert: z.array(AssertionSchema).optional(),
131
+ repeat: z.number().int().min(1).max(100).optional(),
132
+ min_pass_rate: z.number().min(0).max(1).optional(),
133
+ allow_agent_errors: z.boolean().optional(),
134
+ })
135
+ .strict();
136
+ export const ConfigSchema = z
137
+ .object({
138
+ agent: AgentSchema.optional(),
139
+ assert: z.array(AssertionSchema).optional(),
140
+ repeat: z.number().int().min(1).max(100).optional(),
141
+ scenarios: z.union([z.string(), z.array(z.string())]).optional(),
142
+ })
143
+ .strict();
144
+ export class ScenarioError extends Error {
145
+ file;
146
+ constructor(file, message) {
147
+ super(`${file}: ${message}`);
148
+ this.file = file;
149
+ }
150
+ }
151
+ function formatZodError(err) {
152
+ return err.issues.map((i) => ` - ${i.path.length ? i.path.join(".") : "(root)"}: ${i.message}`).join("\n");
153
+ }
154
+ function inferVia(turn, seed) {
155
+ if (turn.via)
156
+ return turn.via;
157
+ if (turn.event)
158
+ return "none";
159
+ if (turn.ticket !== undefined || turn.subject !== undefined || turn.from !== undefined)
160
+ return "zendesk";
161
+ if (turn.channel !== undefined || turn.thread_ts !== undefined)
162
+ return "slack";
163
+ if (turn.issue !== undefined || turn.team !== undefined)
164
+ return "linear";
165
+ const seeded = ["zendesk", "slack", "linear"].filter((b) => seed[b] !== undefined);
166
+ return seeded.length === 1 ? seeded[0] : "none";
167
+ }
168
+ export function normalizeScenario(raw, file, index = 0) {
169
+ const parsed = ScenarioSchema.safeParse(raw ?? {});
170
+ if (!parsed.success)
171
+ throw new ScenarioError(file, `invalid scenario\n${formatZodError(parsed.error)}`);
172
+ const s = parsed.data;
173
+ const seed = (s.seed ?? {});
174
+ const turns = (s.turns ?? []).map((t) => (typeof t === "string" ? { text: t } : { ...t }));
175
+ const faults = [];
176
+ for (const f of s.faults ?? []) {
177
+ if (f.kind === "duplicate_delivery") {
178
+ const turn = turns[f.turn - 1];
179
+ if (!turn)
180
+ throw new ScenarioError(file, `duplicate_delivery refers to turn ${f.turn}, but there are ${turns.length} turns`);
181
+ turn.deliver = f.copies ?? 2;
182
+ if (f.concurrent !== undefined)
183
+ turn.concurrent = f.concurrent;
184
+ continue;
185
+ }
186
+ const { turn: _t, copies: _c, concurrent: _cc, ...rest } = f;
187
+ faults.push(rest);
188
+ }
189
+ const stem = basename(file, extname(file));
190
+ return {
191
+ name: s.name ?? (index > 0 ? `${stem} #${index + 1}` : stem),
192
+ description: s.description,
193
+ tags: s.tags ?? [],
194
+ clock: s.clock,
195
+ backends: s.backends,
196
+ agent: s.agent,
197
+ seed,
198
+ turns: turns.map((t) => ({ ...t, via: inferVia(t, seed) })),
199
+ faults,
200
+ assert: s.assert ?? [],
201
+ repeat: s.repeat ?? 1,
202
+ minPassRate: s.min_pass_rate ?? 1,
203
+ allowAgentErrors: s.allow_agent_errors ?? false,
204
+ };
205
+ }
206
+ const SCENARIO_EXT = new Set([".yaml", ".yml", ".json"]);
207
+ const CONFIG_NAMES = ["fakeplane.config.yaml", "fakeplane.config.yml", "fakeplane.config.json"];
208
+ function collectFiles(path, out) {
209
+ const st = statSync(path);
210
+ if (st.isDirectory()) {
211
+ for (const entry of readdirSync(path).sort()) {
212
+ if (entry.startsWith(".") || entry.startsWith("_") || entry === "node_modules")
213
+ continue;
214
+ const full = join(path, entry);
215
+ if (statSync(full).isDirectory())
216
+ collectFiles(full, out);
217
+ else if (SCENARIO_EXT.has(extname(entry)) && !CONFIG_NAMES.includes(entry))
218
+ out.push(full);
219
+ }
220
+ }
221
+ else {
222
+ out.push(path);
223
+ }
224
+ }
225
+ export function parseDocuments(text, file) {
226
+ if (file.endsWith(".json")) {
227
+ try {
228
+ return [JSON.parse(text)];
229
+ }
230
+ catch (err) {
231
+ throw new ScenarioError(file, `invalid JSON: ${err.message}`);
232
+ }
233
+ }
234
+ const docs = parseAllDocuments(text);
235
+ const list = Array.isArray(docs) ? docs : [docs];
236
+ return list
237
+ .map((doc) => {
238
+ if (doc.errors.length)
239
+ throw new ScenarioError(file, `invalid YAML: ${doc.errors[0].message}`);
240
+ return doc.toJS();
241
+ })
242
+ .filter((d) => d !== null && d !== undefined);
243
+ }
244
+ export function loadScenarioFile(file) {
245
+ const abs = resolve(file);
246
+ const docs = parseDocuments(readFileSync(abs, "utf8"), abs);
247
+ return docs.map((doc, index) => ({ file: abs, dir: dirname(abs), index, scenario: normalizeScenario(doc, abs, index) }));
248
+ }
249
+ export function loadScenarios(paths) {
250
+ const files = [];
251
+ for (const p of paths) {
252
+ if (!existsSync(p))
253
+ throw new ScenarioError(p, "no such file or directory");
254
+ collectFiles(resolve(p), files);
255
+ }
256
+ return files.flatMap((f) => loadScenarioFile(f));
257
+ }
258
+ export function loadConfig(explicit, cwd = process.cwd()) {
259
+ const file = explicit ? resolve(explicit) : CONFIG_NAMES.map((n) => join(cwd, n)).find((f) => existsSync(f));
260
+ if (!file)
261
+ return undefined;
262
+ if (!existsSync(file))
263
+ throw new ScenarioError(file, "config file not found");
264
+ const [doc] = parseDocuments(readFileSync(file, "utf8"), file);
265
+ const parsed = ConfigSchema.safeParse(doc ?? {});
266
+ if (!parsed.success)
267
+ throw new ScenarioError(file, `invalid config\n${formatZodError(parsed.error)}`);
268
+ return { ...parsed.data, dir: dirname(file) };
269
+ }
270
+ //# sourceMappingURL=scenario.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.js","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAa,MAAM,qBAAqB,CAAC;AAG/D,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC7C,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAEpD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC;KACzB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACjD,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAChD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC3B,CAAC;KACD,MAAM,EAAE,CAAC;AAGZ,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,CAAC;IACN,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC9D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,UAAU;IACV,MAAM,EAAE,EAAE,CAAC,QAAQ,EAAE;IACrB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE;IACjD,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,QAAQ;IACR,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC/B,SAAS;IACT,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,iFAAiF;IACjF,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE;IAC3B,mEAAmE;IACnE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACnD,wEAAwE;IACxE,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5C,CAAC;KACD,MAAM,EAAE,CAAC;AAGZ,MAAM,WAAW,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE;IACzC,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;IAC5F,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACzC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACzE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACrD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC3C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACxC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACjC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC5B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,qBAAqB;IACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACxC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IAClD,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CACnC,CAAC;KACD,MAAM,EAAE;KACR,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;IACtB,IAAI,CAAC,CAAC,IAAI,KAAK,oBAAoB,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;QAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC,CAAC;IAC1I,IAAI,CAAC,CAAC,IAAI,KAAK,oBAAoB,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO;QAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC,CAAC;AACzI,CAAC,CAAC,CAAC;AAEL,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;AAC5B,MAAM,WAAW,GAAG;IAClB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACzC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACxC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC;KAC7B,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE;IACzB,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACxC,GAAG,WAAW;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE;IACzB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC9B,MAAM,EAAE,CAAC;SACN,KAAK,CAAC;QACL,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QACf,CAAC;aACE,MAAM,CAAC;YACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC9B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;YACrC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;YACtC,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC9B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;SACtF,CAAC;aACD,MAAM,EAAE;KACZ,CAAC;SACD,QAAQ,EAAE;IACb,oBAAoB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC1J,YAAY,EAAE,OAAO,CAAC,QAAQ,EAAE;IAChC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC;KACD,MAAM,EAAE;KACR,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;IACtB,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IACnJ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,sHAAsH,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;IACjM,CAAC;IACD,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC;QAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC,CAAC;AAC/J,CAAC,CAAC,CAAC;AAGL,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC;KAC5B,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,EAAE;IACnD,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE;IAC7B,IAAI,EAAE,CAAC;SACJ,MAAM,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC;SACnI,MAAM,EAAE;SACR,QAAQ,EAAE;IACb,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5D,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE;IACvC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,QAAQ,EAAE;IAC3C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACnD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAClD,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAC3C,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE;IAC7B,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,QAAQ,EAAE;IAC3C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACnD,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACjE,CAAC;KACD,MAAM,EAAE,CAAC;AA0BZ,MAAM,OAAO,aAAc,SAAQ,KAAK;IAE3B;IADX,YACW,IAAY,EACrB,OAAe;QAEf,KAAK,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QAHpB,SAAI,GAAJ,IAAI,CAAQ;IAIvB,CAAC;CACF;AAED,SAAS,cAAc,CAAC,GAAe;IACrC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9G,CAAC;AAED,SAAS,QAAQ,CAAC,IAAc,EAAE,IAAU;IAC1C,IAAI,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC;IAC9B,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IAC9B,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzG,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAC/E,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzE,MAAM,MAAM,GAAI,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IAC9F,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAY,EAAE,IAAY,EAAE,KAAK,GAAG,CAAC;IACrE,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,MAAM,IAAI,aAAa,CAAC,IAAI,EAAE,qBAAqB,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACxG,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;IACtB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAS,CAAC;IACpC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3F,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC/B,IAAI,CAAC,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAK,GAAG,CAAC,CAAC,CAAC;YAChC,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,aAAa,CAAC,IAAI,EAAE,qCAAqC,CAAC,CAAC,IAAI,mBAAmB,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;YAC7H,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;YAC7B,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS;gBAAE,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;YAC/D,SAAS;QACX,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;QAC7D,MAAM,CAAC,IAAI,CAAC,IAAiB,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3C,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5D,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;QAClB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,IAAI;QACJ,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3D,MAAM;QACN,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;QACtB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;QACrB,WAAW,EAAE,CAAC,CAAC,aAAa,IAAI,CAAC;QACjC,gBAAgB,EAAE,CAAC,CAAC,kBAAkB,IAAI,KAAK;KAChD,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACzD,MAAM,YAAY,GAAG,CAAC,uBAAuB,EAAE,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;AAEhG,SAAS,YAAY,CAAC,IAAY,EAAE,GAAa;IAC/C,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACrB,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7C,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,KAAK,cAAc;gBAAE,SAAS;YACzF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC/B,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;iBACrD,IAAI,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAY;IACvD,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,aAAa,CAAC,IAAI,EAAE,iBAAkB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACjD,OAAO,IAAI;SACR,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM;YAAE,MAAM,IAAI,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/F,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,cAAc,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3H,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAe;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,aAAa,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAAC;QAC5E,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAiB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC/D,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7G,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,aAAa,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;IAC9E,MAAM,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,MAAM,IAAI,aAAa,CAAC,IAAI,EAAE,mBAAmB,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtG,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { McpHandler } from "./mcp.js";
2
+ import type { World } from "./world.js";
3
+ export interface ControlHooks {
4
+ /** Rebuild the world from its seed. */
5
+ reset?: () => World;
6
+ /** Evaluate assertions against the current world (used by `fakeplane report --assert`). */
7
+ assert?: (world: World, assertions: unknown[]) => unknown | Promise<unknown>;
8
+ /** Apply a user turn to the world and return the event the agent would receive. */
9
+ injectTurn?: (world: World, turn: Record<string, unknown>) => unknown;
10
+ }
11
+ export interface FakeServerOptions {
12
+ host?: string;
13
+ port?: number;
14
+ hooks?: ControlHooks;
15
+ }
16
+ export interface ServerUrls {
17
+ base: string;
18
+ mcp: string;
19
+ zendesk: string;
20
+ slack: string;
21
+ linear: string;
22
+ generic: string;
23
+ }
24
+ export declare class FakeServer {
25
+ world: World;
26
+ readonly mcp: McpHandler;
27
+ private server?;
28
+ private readonly hooks;
29
+ private readonly options;
30
+ constructor(world: World, options?: FakeServerOptions);
31
+ start(): Promise<ServerUrls>;
32
+ urls(): ServerUrls;
33
+ stop(): Promise<void>;
34
+ private handle;
35
+ private tryBackend;
36
+ private send;
37
+ private handleMcp;
38
+ private control;
39
+ }
40
+ export declare function matchPath(pattern: string, path: string): Record<string, string> | null;