@loopingai/core 0.1.1 → 0.2.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 (75) hide show
  1. package/README.md +131 -15
  2. package/dist/a2a/card.d.ts +35 -0
  3. package/dist/a2a/card.d.ts.map +1 -1
  4. package/dist/a2a/card.js +41 -3
  5. package/dist/a2a/card.js.map +1 -1
  6. package/dist/a2a/context.d.ts +9 -3
  7. package/dist/a2a/context.d.ts.map +1 -1
  8. package/dist/a2a/context.js +11 -4
  9. package/dist/a2a/context.js.map +1 -1
  10. package/dist/a2a/index.d.ts +1 -1
  11. package/dist/a2a/index.d.ts.map +1 -1
  12. package/dist/a2a/index.js +1 -1
  13. package/dist/a2a/index.js.map +1 -1
  14. package/dist/a2a/notify.d.ts +11 -2
  15. package/dist/a2a/notify.d.ts.map +1 -1
  16. package/dist/a2a/notify.js +12 -3
  17. package/dist/a2a/notify.js.map +1 -1
  18. package/dist/a2a/verify.d.ts +23 -2
  19. package/dist/a2a/verify.d.ts.map +1 -1
  20. package/dist/a2a/verify.js +26 -3
  21. package/dist/a2a/verify.js.map +1 -1
  22. package/dist/agent/history.d.ts +15 -0
  23. package/dist/agent/history.d.ts.map +1 -1
  24. package/dist/agent/history.js +17 -0
  25. package/dist/agent/history.js.map +1 -1
  26. package/dist/agent/index.d.ts +1 -1
  27. package/dist/agent/index.d.ts.map +1 -1
  28. package/dist/agent/index.js +1 -1
  29. package/dist/agent/index.js.map +1 -1
  30. package/dist/contract/index.d.ts +1 -1
  31. package/dist/contract/index.d.ts.map +1 -1
  32. package/dist/contract/index.js.map +1 -1
  33. package/dist/contract/plugin.d.ts +86 -3
  34. package/dist/contract/plugin.d.ts.map +1 -1
  35. package/dist/contract/plugin.js.map +1 -1
  36. package/dist/db/db.d.ts +32 -14
  37. package/dist/db/db.d.ts.map +1 -1
  38. package/dist/db/db.js.map +1 -1
  39. package/dist/env.d.ts +10 -2
  40. package/dist/env.d.ts.map +1 -1
  41. package/dist/env.js +10 -2
  42. package/dist/env.js.map +1 -1
  43. package/dist/index.d.ts +2 -2
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +1 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/runtime/index.d.ts +28 -3
  48. package/dist/runtime/index.d.ts.map +1 -1
  49. package/dist/runtime/index.js +39 -3
  50. package/dist/runtime/index.js.map +1 -1
  51. package/dist/subagent/workspace.d.ts +21 -0
  52. package/dist/subagent/workspace.d.ts.map +1 -1
  53. package/dist/subagent/workspace.js +80 -5
  54. package/dist/subagent/workspace.js.map +1 -1
  55. package/dist/testing/auth.d.ts +23 -0
  56. package/dist/testing/auth.d.ts.map +1 -1
  57. package/dist/testing/auth.js +11 -3
  58. package/dist/testing/auth.js.map +1 -1
  59. package/dist/testing/fixtures.d.ts +21 -0
  60. package/dist/testing/fixtures.d.ts.map +1 -1
  61. package/dist/testing/fixtures.js +21 -0
  62. package/dist/testing/fixtures.js.map +1 -1
  63. package/dist/testing/node.d.ts +23 -0
  64. package/dist/testing/node.d.ts.map +1 -1
  65. package/dist/testing/node.js +23 -0
  66. package/dist/testing/node.js.map +1 -1
  67. package/dist/testing/vcr-spec.d.ts +4 -4
  68. package/dist/testing/vcr-spec.d.ts.map +1 -1
  69. package/dist/testing/vcr-spec.js +32 -11
  70. package/dist/testing/vcr-spec.js.map +1 -1
  71. package/dist/worker/index.d.ts +142 -3
  72. package/dist/worker/index.d.ts.map +1 -1
  73. package/dist/worker/index.js +152 -29
  74. package/dist/worker/index.js.map +1 -1
  75. package/package.json +12 -4
@@ -1,5 +1,6 @@
1
1
  import { resolveConfig } from "../config.js";
2
2
  import { PLUGIN_CONTRACT_VERSION } from "../contract/plugin.js";
3
+ import { memoryWorkspaceBacking } from "../subagent/workspace.js";
3
4
  import { makeSubtaskTypes } from "../subtasks/subtask-types.js";
4
5
  import { collectToolFamilies } from "./tool-families.js";
5
6
  export { buildRecipeTools, collectToolFamilies } from "./tool-families.js";
@@ -43,6 +44,14 @@ export function createAgentRuntime(options) {
43
44
  const displacementListeners = plugins.flatMap((p) => p.onMessagesDisplaced
44
45
  ? [{ key: p.key, notify: p.onMessagesDisplaced.bind(p) }]
45
46
  : []);
47
+ const turnGates = plugins.flatMap((p) => p.shouldHandleTurn ? [{ key: p.key, gate: p.shouldHandleTurn.bind(p) }] : []);
48
+ // At most one backend: two would mean two answers to "where did that file go".
49
+ const backings = plugins.flatMap((p) => p.workspaceBacking ? [{ key: p.key, make: p.workspaceBacking.bind(p) }] : []);
50
+ if (backings.length > 1) {
51
+ throw new RuntimeSetupError(`plugins ${backings.map((b) => `"${b.key}"`).join(" and ")} both declare a ` +
52
+ "workspaceBacking — an execution has one workspace, so only one plugin may back it");
53
+ }
54
+ const workspaceBacking = backings[0]?.make ?? memoryWorkspaceBacking;
46
55
  const secrets = [
47
56
  ...new Set(plugins.flatMap((p) => [...(p.requires?.secrets ?? [])]))
48
57
  ];
@@ -50,13 +59,14 @@ export function createAgentRuntime(options) {
50
59
  ...new Set(plugins.flatMap((p) => [...(p.requires?.bindings ?? [])]))
51
60
  ];
52
61
  if (options.env) {
62
+ const env = options.env;
53
63
  const missing = [];
54
64
  for (const plugin of plugins) {
55
65
  for (const name of [
56
66
  ...(plugin.requires?.secrets ?? []),
57
67
  ...(plugin.requires?.bindings ?? [])
58
68
  ]) {
59
- const value = options.env[name];
69
+ const value = env[name];
60
70
  if (value === undefined || value === null || value === "") {
61
71
  missing.push(`${name} (required by "${plugin.key}")`);
62
72
  }
@@ -87,12 +97,16 @@ export function createAgentRuntime(options) {
87
97
  policy,
88
98
  stores,
89
99
  requirements: { secrets, bindings },
100
+ workspaceBacking,
90
101
  pluginForType,
91
- mainAgentTools() {
102
+ async mainAgentTools(ctx) {
92
103
  const tools = {};
104
+ // Sequential rather than fanned out: this is a handful of plugins reading
105
+ // one session, and merging in declaration order is what makes a name
106
+ // collision resolve the same way on every call.
93
107
  for (const plugin of plugins) {
94
108
  if (plugin.mainAgentTools)
95
- Object.assign(tools, plugin.mainAgentTools());
109
+ Object.assign(tools, await plugin.mainAgentTools(ctx));
96
110
  }
97
111
  return tools;
98
112
  },
@@ -104,6 +118,28 @@ export function createAgentRuntime(options) {
104
118
  }
105
119
  return blocks.join("\n\n");
106
120
  },
121
+ async shouldHandleTurn(ctx) {
122
+ if (turnGates.length === 0)
123
+ return true;
124
+ // Same `allSettled` + `async`-wrapped-callback discipline as
125
+ // `onMessagesDisplaced` below, and for the same two reasons: every gate is
126
+ // consulted even when one throws, and a gate that throws *synchronously*
127
+ // (reading a binding before its first await) is caught rather than
128
+ // escaping past the aggregation.
129
+ //
130
+ // A rejection resolves to `true`. That is not leniency — it is the only
131
+ // safe default here. A wrong reply is noise the user sees and ignores; a
132
+ // wrong silence is invisible to the person who needed an answer, so a
133
+ // broken gate must degrade to "run the turn" and never to a mute agent.
134
+ const results = await Promise.allSettled(turnGates.map(async (g) => g.gate(ctx)));
135
+ return results.every((result, i) => {
136
+ if (result.status === "rejected") {
137
+ console.warn(`[runtime] plugin "${turnGates[i].key}" turn gate failed, handling the turn`, result.reason);
138
+ return true;
139
+ }
140
+ return result.value;
141
+ });
142
+ },
107
143
  async onMessagesDisplaced(messages) {
108
144
  // allSettled, not all: `all` rejects at the first listener to throw and
109
145
  // stops awaiting the rest, so every other plugin's write is still in
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
@@ -48,6 +48,27 @@ export interface WorkspaceBacking {
48
48
  fileCount: number;
49
49
  }>;
50
50
  }
51
+ /**
52
+ * An in-memory {@link WorkspaceBacking} — the fallback when no installed plugin
53
+ * declares one.
54
+ *
55
+ * Deliberately **not durable**, and that is the honest behaviour rather than a
56
+ * shortcut: a durable stand-in would have to invent a storage layout that a real
57
+ * backend would then have to migrate away from. An agent that delegates file
58
+ * work installs a backend; one that does not never writes a file, and pays
59
+ * nothing for the option. What this buys is that `createAgentRuntime` composes
60
+ * without a workspace plugin at all, so `SubagentRuntime.workspaceBacking` can
61
+ * stay required and a host never writes a null check.
62
+ *
63
+ * Scoped per call, so each execution gets its own map, exactly as a facet's own
64
+ * SQLite would give it its own tables. Contents are lost on isolate eviction —
65
+ * the resumable runner treats a lost workspace as a resumable state everywhere
66
+ * it matters.
67
+ *
68
+ * Signature matches {@link AgentPlugin.workspaceBacking}; both arguments are
69
+ * ignored.
70
+ */
71
+ export declare function memoryWorkspaceBacking(_sql?: SqlStorage, _name?: () => string | undefined): WorkspaceBacking;
51
72
  /** Per-file byte ceiling — safely under the 2 MB Durable Object SQLite row limit. */
52
73
  export declare const WORKSPACE_MAX_FILE_BYTES: number;
53
74
  /** Max number of files in one workspace — a cheap guard against runaway writes. */
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/subagent/workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3C,+EAA+E;IAC/E,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,sDAAsD;IACtD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,yDAAyD;IACzD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,8EAA8E;IAC9E,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9C,iFAAiF;IACjF,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7C,yDAAyD;IACzD,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/C,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;IAC1D,gBAAgB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,qFAAqF;AACrF,eAAO,MAAM,wBAAwB,QAAa,CAAC;AACnD,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,gBAAgB,GAAG,eAAe,CA8CzE"}
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/subagent/workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3C,+EAA+E;IAC/E,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,sDAAsD;IACtD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,yDAAyD;IACzD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,8EAA8E;IAC9E,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9C,iFAAiF;IACjF,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7C,yDAAyD;IACzD,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/C,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;IAC1D,gBAAgB,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,CAAC,EAAE,UAAU,EACjB,KAAK,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAC/B,gBAAgB,CA2ClB;AAOD,qFAAqF;AACrF,eAAO,MAAM,wBAAwB,QAAa,CAAC;AACnD,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,gBAAgB,GAAG,eAAe,CAsDzE"}
@@ -1,3 +1,72 @@
1
+ /**
2
+ * An in-memory {@link WorkspaceBacking} — the fallback when no installed plugin
3
+ * declares one.
4
+ *
5
+ * Deliberately **not durable**, and that is the honest behaviour rather than a
6
+ * shortcut: a durable stand-in would have to invent a storage layout that a real
7
+ * backend would then have to migrate away from. An agent that delegates file
8
+ * work installs a backend; one that does not never writes a file, and pays
9
+ * nothing for the option. What this buys is that `createAgentRuntime` composes
10
+ * without a workspace plugin at all, so `SubagentRuntime.workspaceBacking` can
11
+ * stay required and a host never writes a null check.
12
+ *
13
+ * Scoped per call, so each execution gets its own map, exactly as a facet's own
14
+ * SQLite would give it its own tables. Contents are lost on isolate eviction —
15
+ * the resumable runner treats a lost workspace as a resumable state everywhere
16
+ * it matters.
17
+ *
18
+ * Signature matches {@link AgentPlugin.workspaceBacking}; both arguments are
19
+ * ignored.
20
+ */
21
+ export function memoryWorkspaceBacking(_sql, _name) {
22
+ const files = new Map();
23
+ /** Immediate children of `dir`, as `readDir` reports them. */
24
+ const entriesUnder = (dir) => {
25
+ const prefix = dir === "" ? "" : `${dir}/`;
26
+ const seen = new Map();
27
+ for (const [path, content] of files) {
28
+ if (!path.startsWith(prefix))
29
+ continue;
30
+ const rest = path.slice(prefix.length);
31
+ if (rest === "")
32
+ continue;
33
+ const slash = rest.indexOf("/");
34
+ if (slash === -1) {
35
+ seen.set(path, {
36
+ path,
37
+ type: "file",
38
+ size: new TextEncoder().encode(content).length
39
+ });
40
+ }
41
+ else {
42
+ // A directory exists only because something under it does, so report it
43
+ // once and say nothing about its size.
44
+ const child = `${prefix}${rest.slice(0, slash)}`;
45
+ seen.set(child, { path: child, type: "directory", size: 0 });
46
+ }
47
+ }
48
+ return [...seen.values()];
49
+ };
50
+ return {
51
+ readFile: async (path) => files.get(normalize(path)) ?? null,
52
+ writeFile: async (path, content) => {
53
+ files.set(normalize(path), content);
54
+ },
55
+ // Directories are implied by their contents, so a path with anything under
56
+ // it exists even though nothing ever created it.
57
+ exists: async (path) => {
58
+ const key = normalize(path);
59
+ return files.has(key) || entriesUnder(key).length > 0;
60
+ },
61
+ deleteFile: async (path) => files.delete(normalize(path)),
62
+ readDir: async (dir) => entriesUnder(normalize(dir ?? "")),
63
+ getWorkspaceInfo: async () => ({ fileCount: files.size })
64
+ };
65
+ }
66
+ /** Strip the leading/trailing slashes that would otherwise key two paths apart. */
67
+ function normalize(path) {
68
+ return path.replace(/^\/+|\/+$/g, "");
69
+ }
1
70
  /** Per-file byte ceiling — safely under the 2 MB Durable Object SQLite row limit. */
2
71
  export const WORKSPACE_MAX_FILE_BYTES = 512 * 1024;
3
72
  /** Max number of files in one workspace — a cheap guard against runaway writes. */
@@ -23,11 +92,17 @@ export function makeWorkspaceHandle(ws) {
23
92
  if (bytes > WORKSPACE_MAX_FILE_BYTES) {
24
93
  throw new WorkspaceLimitError(`file "${path}" is ${bytes} bytes, over the ${WORKSPACE_MAX_FILE_BYTES}-byte limit`);
25
94
  }
26
- if (!(await ws.exists(path))) {
27
- const { fileCount } = await ws.getWorkspaceInfo();
28
- if (fileCount >= WORKSPACE_MAX_FILES) {
29
- throw new WorkspaceLimitError(`workspace already holds ${fileCount} files (max ${WORKSPACE_MAX_FILES})`);
30
- }
95
+ // The cap bounds how many files exist, so it may only refuse a write that
96
+ // *creates* one. `exists` is the wrong question: it is true for a
97
+ // directory too (filesystem semantics, which every real backing has), so
98
+ // at the cap a write to `notes` with `notes/a.txt` present read as an
99
+ // overwrite and added a 201st file. `readFile` returning null is the only
100
+ // honest test for "there is no file here", and it runs solely when the
101
+ // workspace is already full, so the ordinary write still costs one call.
102
+ const { fileCount } = await ws.getWorkspaceInfo();
103
+ if (fileCount >= WORKSPACE_MAX_FILES &&
104
+ (await ws.readFile(path)) === null) {
105
+ throw new WorkspaceLimitError(`workspace already holds ${fileCount} files (max ${WORKSPACE_MAX_FILES})`);
31
106
  }
32
107
  await ws.writeFile(path, content);
33
108
  },
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/subagent/workspace.ts"],"names":[],"mappings":"AAmDA,qFAAqF;AACrF,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,GAAG,IAAI,CAAC;AACnD,mFAAmF;AACnF,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAoB;IACtD,MAAM,UAAU,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAE7E,OAAO;QACL,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;QAEjC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO;YACvB,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,KAAK,GAAG,wBAAwB,EAAE,CAAC;gBACrC,MAAM,IAAI,mBAAmB,CAC3B,SAAS,IAAI,QAAQ,KAAK,oBAAoB,wBAAwB,aAAa,CACpF,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAC7B,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;gBAClD,IAAI,SAAS,IAAI,mBAAmB,EAAE,CAAC;oBACrC,MAAM,IAAI,mBAAmB,CAC3B,2BAA2B,SAAS,eAAe,mBAAmB,GAAG,CAC1E,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;QAEjC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAErC,KAAK,CAAC,IAAI,CAAC,GAAG;YACZ,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACtC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACzB,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;aACb,CAAC,CAAC,CAAC;QACN,CAAC;QAED,KAAK,CAAC,QAAQ,CAAI,IAAY;YAC5B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAO,CAAC;QACtD,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK;YACzB,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/subagent/workspace.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,13 @@
1
1
  export interface GatewayTokenOptions {
2
+ /**
3
+ * Who the token is for. Defaults to an agent at the default RPC path
4
+ * (`${AGENT_ORIGIN}${A2A_RPC_PATH}`), which is what a gateway mints: the
5
+ * agent's **endpoint**, not its origin.
6
+ *
7
+ * Pass this explicitly when a spec mounts an agent somewhere else — an agent
8
+ * at `/proactive/a2a` expects that string and refuses this default, which is
9
+ * the whole point of scoping the audience to the endpoint.
10
+ */
2
11
  audience?: string;
3
12
  issuer?: string;
4
13
  /** Relative string ("5m"), absolute epoch seconds, or Date. Past values expire the token. */
@@ -6,7 +15,21 @@ export interface GatewayTokenOptions {
6
15
  identity?: Record<string, unknown>;
7
16
  /** Claim the identity is carried in. Defaults to core's `IDENTITY_CLAIM`. */
8
17
  identityClaim?: string;
18
+ /**
19
+ * Which agent on the target origin this token authorizes, defaulting to
20
+ * `"main"`.
21
+ *
22
+ * The tenants of one deployment share an endpoint and therefore an audience,
23
+ * so this claim is the only thing distinguishing them. Set it to a *different*
24
+ * tenant than the request addresses to exercise the replay case; set it to
25
+ * `""` to mint a token carrying no tenant at all, which is rejected.
26
+ */
27
+ tenant?: string;
28
+ /** Claim the tenant is carried in. Defaults to core's `TENANT_CLAIM`. */
29
+ tenantClaim?: string;
9
30
  }
31
+ /** The tenant `makeGatewayToken` authorizes unless a spec says otherwise. */
32
+ export declare const TEST_TENANT = "main";
10
33
  /** Sign a short-lived EdDSA gateway JWT using the test gateway key. */
11
34
  export declare function makeGatewayToken(options?: GatewayTokenOptions): Promise<string>;
12
35
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/testing/auth.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,uEAAuE;AACvE,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/testing/auth.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,6EAA6E;AAC7E,eAAO,MAAM,WAAW,SAAS,CAAC;AAElC,uEAAuE;AACvE,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,CAAC,CAwBjB"}
@@ -1,16 +1,24 @@
1
1
  import { importJWK, SignJWT } from "jose";
2
- import { IDENTITY_CLAIM } from "../a2a/verify.js";
2
+ import { IDENTITY_CLAIM, TENANT_CLAIM } from "../a2a/verify.js";
3
+ import { A2A_RPC_PATH } from "../a2a/card.js";
3
4
  import { TEST_GATEWAY_PRIVATE_JWK, GATEWAY_ORIGIN, AGENT_ORIGIN } from "./fixtures.js";
5
+ /** The tenant `makeGatewayToken` authorizes unless a spec says otherwise. */
6
+ export const TEST_TENANT = "main";
4
7
  /** Sign a short-lived EdDSA gateway JWT using the test gateway key. */
5
8
  export async function makeGatewayToken(options = {}) {
6
9
  const privateKey = await importJWK(TEST_GATEWAY_PRIVATE_JWK, "EdDSA");
10
+ const tenant = options.tenant ?? TEST_TENANT;
7
11
  return new SignJWT({
8
12
  [options.identityClaim ?? IDENTITY_CLAIM]: options.identity ?? {
9
13
  key: "custom:1:test-agent",
10
14
  name: "Test Agent",
11
15
  kind: "custom",
12
16
  workspaceId: 1
13
- }
17
+ },
18
+ // An empty tenant omits the claim entirely rather than signing `""` — that
19
+ // is the "gateway too old to scope its tokens" case, and it must be
20
+ // rejected rather than treated as a wildcard.
21
+ ...(tenant ? { [options.tenantClaim ?? TENANT_CLAIM]: tenant } : {})
14
22
  })
15
23
  .setProtectedHeader({
16
24
  alg: "EdDSA",
@@ -18,7 +26,7 @@ export async function makeGatewayToken(options = {}) {
18
26
  jku: `${GATEWAY_ORIGIN}/.well-known/jwks.json`
19
27
  })
20
28
  .setIssuer(options.issuer ?? GATEWAY_ORIGIN)
21
- .setAudience(options.audience ?? AGENT_ORIGIN)
29
+ .setAudience(options.audience ?? `${AGENT_ORIGIN}${A2A_RPC_PATH}`)
22
30
  .setExpirationTime(options.expiresIn ?? "5m")
23
31
  .sign(privateKey);
24
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/testing/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EACL,wBAAwB,EACxB,cAAc,EACd,YAAY,EACb,MAAM,eAAe,CAAC;AAYvB,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAA+B,EAAE;IAEjC,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;IACtE,OAAO,IAAI,OAAO,CAAC;QACjB,CAAC,OAAO,CAAC,aAAa,IAAI,cAAc,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI;YAC7D,GAAG,EAAE,qBAAqB;YAC1B,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,CAAC;SACf;KACF,CAAC;SACC,kBAAkB,CAAC;QAClB,GAAG,EAAE,OAAO;QACZ,GAAG,EAAE,wBAAwB,CAAC,GAAG;QACjC,GAAG,EAAE,GAAG,cAAc,wBAAwB;KAC/C,CAAC;SACD,SAAS,CAAC,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC;SAC3C,WAAW,CAAC,OAAO,CAAC,QAAQ,IAAI,YAAY,CAAC;SAC7C,iBAAiB,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;SAC5C,IAAI,CAAC,UAAU,CAAC,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/testing/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EACL,wBAAwB,EACxB,cAAc,EACd,YAAY,EACb,MAAM,eAAe,CAAC;AAiCvB,6EAA6E;AAC7E,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAElC,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAA+B,EAAE;IAEjC,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC;IAC7C,OAAO,IAAI,OAAO,CAAC;QACjB,CAAC,OAAO,CAAC,aAAa,IAAI,cAAc,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI;YAC7D,GAAG,EAAE,qBAAqB;YAC1B,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,CAAC;SACf;QACD,2EAA2E;QAC3E,oEAAoE;QACpE,8CAA8C;QAC9C,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,WAAW,IAAI,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC;SACC,kBAAkB,CAAC;QAClB,GAAG,EAAE,OAAO;QACZ,GAAG,EAAE,wBAAwB,CAAC,GAAG;QACjC,GAAG,EAAE,GAAG,cAAc,wBAAwB;KAC/C,CAAC;SACD,SAAS,CAAC,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC;SAC3C,WAAW,CAAC,OAAO,CAAC,QAAQ,IAAI,GAAG,YAAY,GAAG,YAAY,EAAE,CAAC;SACjE,iBAAiB,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;SAC5C,IAAI,CAAC,UAAU,CAAC,CAAC;AACtB,CAAC"}
@@ -1,3 +1,24 @@
1
+ /**
2
+ * `@loopingai/core/testing/fixtures` — the **realm-neutral** slice of the
3
+ * harness: fixed keys, origins, and task/message builders.
4
+ *
5
+ * Its own subpath because it is the one part a consumer's `vitest.config.ts`
6
+ * needs, and that file runs in **Node**. The `/testing` barrel pulls in
7
+ * `cloudflare:test` (DO helpers) and `vitest` (the VCR spec hooks), so importing
8
+ * it from a config fails at load with `ERR_UNSUPPORTED_ESM_URL_SCHEME` before a
9
+ * single test runs. Nothing here imports either, so it is safe from a config, a
10
+ * spec, or a plain Node script.
11
+ *
12
+ * Seeding the required secrets from these values is the intended use:
13
+ *
14
+ * ```ts
15
+ * // vitest.config.ts
16
+ * import { GATEWAY_ORIGIN, TEST_AGENT_PRIVATE_JWK } from "@loopingai/core/testing/fixtures";
17
+ *
18
+ * process.env.A2A_SIGNING_KEY ??= JSON.stringify(TEST_AGENT_PRIVATE_JWK);
19
+ * process.env.GATEWAY_ORIGINS ??= JSON.stringify([GATEWAY_ORIGIN]);
20
+ * ```
21
+ */
1
22
  import { type JWK } from "jose";
2
23
  import { type Message, type Task, type TaskState } from "@a2a-js/sdk";
3
24
  /** The gateway origin used in all tests. Must match vitest.config.ts and the MockAgent setup. */
@@ -1 +1 @@
1
- {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/testing/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAQ,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE5E,iGAAiG;AACjG,eAAO,MAAM,cAAc,yBAAyB,CAAC;AAErD,6EAA6E;AAC7E,eAAO,MAAM,YAAY,qBAAqB,CAAC;AAE/C,kEAAkE;AAClE,eAAO,MAAM,sBAAsB,EAAE,GAAG,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAMvD,CAAC;AAEF,mEAAmE;AACnE,eAAO,MAAM,wBAAwB,EAAE,GAAG,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAMzD,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAE7B;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,SAAK,EACd,MAAM,SAAK,GACV,OAAO,CAkBT;AAED,iDAAiD;AACjD,wBAAgB,QAAQ,CACtB,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,IAAI,CASN"}
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/testing/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAQ,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE5E,iGAAiG;AACjG,eAAO,MAAM,cAAc,yBAAyB,CAAC;AAErD,6EAA6E;AAC7E,eAAO,MAAM,YAAY,qBAAqB,CAAC;AAE/C,kEAAkE;AAClE,eAAO,MAAM,sBAAsB,EAAE,GAAG,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAMvD,CAAC;AAEF,mEAAmE;AACnE,eAAO,MAAM,wBAAwB,EAAE,GAAG,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAMzD,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAE7B;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,SAAK,EACd,MAAM,SAAK,GACV,OAAO,CAkBT;AAED,iDAAiD;AACjD,wBAAgB,QAAQ,CACtB,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,IAAI,CASN"}
@@ -1,3 +1,24 @@
1
+ /**
2
+ * `@loopingai/core/testing/fixtures` — the **realm-neutral** slice of the
3
+ * harness: fixed keys, origins, and task/message builders.
4
+ *
5
+ * Its own subpath because it is the one part a consumer's `vitest.config.ts`
6
+ * needs, and that file runs in **Node**. The `/testing` barrel pulls in
7
+ * `cloudflare:test` (DO helpers) and `vitest` (the VCR spec hooks), so importing
8
+ * it from a config fails at load with `ERR_UNSUPPORTED_ESM_URL_SCHEME` before a
9
+ * single test runs. Nothing here imports either, so it is safe from a config, a
10
+ * spec, or a plain Node script.
11
+ *
12
+ * Seeding the required secrets from these values is the intended use:
13
+ *
14
+ * ```ts
15
+ * // vitest.config.ts
16
+ * import { GATEWAY_ORIGIN, TEST_AGENT_PRIVATE_JWK } from "@loopingai/core/testing/fixtures";
17
+ *
18
+ * process.env.A2A_SIGNING_KEY ??= JSON.stringify(TEST_AGENT_PRIVATE_JWK);
19
+ * process.env.GATEWAY_ORIGINS ??= JSON.stringify([GATEWAY_ORIGIN]);
20
+ * ```
21
+ */
1
22
  import {} from "jose";
2
23
  import { Role } from "@a2a-js/sdk";
3
24
  /** The gateway origin used in all tests. Must match vitest.config.ts and the MockAgent setup. */
@@ -1 +1 @@
1
- {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/testing/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,IAAI,EAA2C,MAAM,aAAa,CAAC;AAE5E,iGAAiG;AACjG,MAAM,CAAC,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAErD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAE/C,kEAAkE;AAClE,MAAM,CAAC,MAAM,sBAAsB,GAA0B;IAC3D,GAAG,EAAE,SAAS;IACd,CAAC,EAAE,6CAA6C;IAChD,CAAC,EAAE,6CAA6C;IAChD,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,kBAAkB;CACxB,CAAC;AAEF,mEAAmE;AACnE,MAAM,CAAC,MAAM,wBAAwB,GAA0B;IAC7D,GAAG,EAAE,SAAS;IACd,CAAC,EAAE,6CAA6C;IAChD,CAAC,EAAE,6CAA6C;IAChD,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,eAAe;CACrB,CAAC;AAEF,oFAAoF;AACpF,MAAM,UAAU,iBAAiB;IAC/B,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,GAAG,wBAAwB,CAAC;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,KAAgB,EAChB,OAAiB;IAEjB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;AACjE,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,gBAAgB,CAC9B,SAAiB,EACjB,IAAY,EACZ,SAAS,GAAG,EAAE,EACd,MAAM,GAAG,EAAE;IAEX,OAAO;QACL,SAAS;QACT,SAAS;QACT,MAAM;QACN,IAAI,EAAE,IAAI,CAAC,UAAU;QACrB,KAAK,EAAE;YACL;gBACE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;gBACvC,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,EAAE;gBACZ,SAAS,EAAE,YAAY;aACxB;SACF;QACD,QAAQ,EAAE,SAAS;QACnB,UAAU,EAAE,EAAE;QACd,gBAAgB,EAAE,EAAE;KACrB,CAAC;AACJ,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,QAAQ,CACtB,EAAU,EACV,SAAiB,EACjB,KAAgB,EAChB,OAAiB;IAEjB,OAAO;QACL,EAAE;QACF,SAAS;QACT,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC;QAClC,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,SAAS;KACpB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/testing/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAY,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,IAAI,EAA2C,MAAM,aAAa,CAAC;AAE5E,iGAAiG;AACjG,MAAM,CAAC,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAErD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAE/C,kEAAkE;AAClE,MAAM,CAAC,MAAM,sBAAsB,GAA0B;IAC3D,GAAG,EAAE,SAAS;IACd,CAAC,EAAE,6CAA6C;IAChD,CAAC,EAAE,6CAA6C;IAChD,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,kBAAkB;CACxB,CAAC;AAEF,mEAAmE;AACnE,MAAM,CAAC,MAAM,wBAAwB,GAA0B;IAC7D,GAAG,EAAE,SAAS;IACd,CAAC,EAAE,6CAA6C;IAChD,CAAC,EAAE,6CAA6C;IAChD,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,eAAe;CACrB,CAAC;AAEF,oFAAoF;AACpF,MAAM,UAAU,iBAAiB;IAC/B,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,GAAG,wBAAwB,CAAC;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,KAAgB,EAChB,OAAiB;IAEjB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;AACjE,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,gBAAgB,CAC9B,SAAiB,EACjB,IAAY,EACZ,SAAS,GAAG,EAAE,EACd,MAAM,GAAG,EAAE;IAEX,OAAO;QACL,SAAS;QACT,SAAS;QACT,MAAM;QACN,IAAI,EAAE,IAAI,CAAC,UAAU;QACrB,KAAK,EAAE;YACL;gBACE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;gBACvC,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,EAAE;gBACZ,SAAS,EAAE,YAAY;aACxB;SACF;QACD,QAAQ,EAAE,SAAS;QACnB,UAAU,EAAE,EAAE;QACd,gBAAgB,EAAE,EAAE;KACrB,CAAC;AACJ,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,QAAQ,CACtB,EAAU,EACV,SAAiB,EACjB,KAAgB,EAChB,OAAiB;IAEjB,OAAO;QACL,EAAE;QACF,SAAS;QACT,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC;QAClC,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,SAAS;KACpB,CAAC;AACJ,CAAC"}
@@ -12,8 +12,31 @@
12
12
  * ```ts
13
13
  * // vitest.config.ts
14
14
  * import { createVcrAgent } from "@loopingai/core/testing/node";
15
+ *
16
+ * export default defineConfig({
17
+ * plugins: [cloudflareTest({ miniflare: { fetchMock: createVcrAgent({ … }) } })],
18
+ * test: { globalSetup: ["@loopingai/core/testing/vcr-global-setup"] }
19
+ * });
15
20
  * ```
16
21
  *
22
+ * ## Two version constraints, both of which fail unreadably
23
+ *
24
+ * **1. `@cloudflare/vitest-pool-workers` must be `^0.18`.** The recorder is
25
+ * installed as Miniflare's `fetchMock`, and that option **does not exist in
26
+ * Miniflare 5**, which pool `0.19`+ depends on — only `outboundService` remains.
27
+ * On a newer pool the option is silently ignored rather than rejected, so
28
+ * `disableNetConnect()` never takes effect, every request goes to the real
29
+ * network, and each one fails as `internal error; reference = …` naming nothing.
30
+ * That is why the peer range is pinned rather than open.
31
+ *
32
+ * **2. Your `undici` must be the copy Miniflare uses.** `fetchMock` is an undici
33
+ * `MockAgent` and Miniflare validates it against *its own* undici, so two copies
34
+ * in one `node_modules` fail with `Input not instance of MockAgent`. Miniflare
35
+ * pins an exact version (7.28.0 at the time of writing) and this package's
36
+ * `undici` peer range tracks it. Check with
37
+ * `ls node_modules/miniflare/node_modules/undici` — anything there means a
38
+ * second copy, and the fix is to align yours rather than to debug the message.
39
+ *
17
40
  * For the common case — wiring cassette flush/teardown — you do not need this
18
41
  * subpath at all. Point `globalSetup` at
19
42
  * `@loopingai/core/testing/vcr-global-setup`, which is this module's `setup`/
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/testing/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EACL,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,KAAK,qBAAqB,EAC3B,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/testing/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EACL,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,KAAK,qBAAqB,EAC3B,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -12,8 +12,31 @@
12
12
  * ```ts
13
13
  * // vitest.config.ts
14
14
  * import { createVcrAgent } from "@loopingai/core/testing/node";
15
+ *
16
+ * export default defineConfig({
17
+ * plugins: [cloudflareTest({ miniflare: { fetchMock: createVcrAgent({ … }) } })],
18
+ * test: { globalSetup: ["@loopingai/core/testing/vcr-global-setup"] }
19
+ * });
15
20
  * ```
16
21
  *
22
+ * ## Two version constraints, both of which fail unreadably
23
+ *
24
+ * **1. `@cloudflare/vitest-pool-workers` must be `^0.18`.** The recorder is
25
+ * installed as Miniflare's `fetchMock`, and that option **does not exist in
26
+ * Miniflare 5**, which pool `0.19`+ depends on — only `outboundService` remains.
27
+ * On a newer pool the option is silently ignored rather than rejected, so
28
+ * `disableNetConnect()` never takes effect, every request goes to the real
29
+ * network, and each one fails as `internal error; reference = …` naming nothing.
30
+ * That is why the peer range is pinned rather than open.
31
+ *
32
+ * **2. Your `undici` must be the copy Miniflare uses.** `fetchMock` is an undici
33
+ * `MockAgent` and Miniflare validates it against *its own* undici, so two copies
34
+ * in one `node_modules` fail with `Input not instance of MockAgent`. Miniflare
35
+ * pins an exact version (7.28.0 at the time of writing) and this package's
36
+ * `undici` peer range tracks it. Check with
37
+ * `ls node_modules/miniflare/node_modules/undici` — anything there means a
38
+ * second copy, and the fix is to align yours rather than to debug the message.
39
+ *
17
40
  * For the common case — wiring cassette flush/teardown — you do not need this
18
41
  * subpath at all. Point `globalSetup` at
19
42
  * `@loopingai/core/testing/vcr-global-setup`, which is this module's `setup`/
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/testing/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EACL,cAAc,EACd,QAAQ,EACR,QAAQ,EAET,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/testing/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EACL,cAAc,EACd,QAAQ,EACR,QAAQ,EAET,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import type { RunnerTestCase } from "vitest";
2
2
  /**
3
- * Cassette filename for a test: `kebab(<file rel to test/, minus .spec.ts>)`
4
- * then each describe level then the test name, all kebab-cased and joined by
5
- * `--`, plus `.snapshot.json`. Example:
6
- * `recipes-arc-game-recorded--arc-game-recorded-real-api--starts-a-real-game-and-closes-the-scorecard-on-abort.snapshot.json`.
3
+ * Cassette filename for a test: `kebab(<project-relative path, minus
4
+ * .spec.ts>)` then each describe level then the test name, all kebab-cased and
5
+ * joined by `--`, plus `.snapshot.json`. Example:
6
+ * `test-arc-agi-recorded--arc-recorded-real-api--plays-a-real-game.snapshot.json`.
7
7
  * Exported for debugging / the cassette-rename step.
8
8
  */
9
9
  export declare function cassetteNameFor(task: RunnerTestCase): string;
@@ -1 +1 @@
1
- {"version":3,"file":"vcr-spec.d.ts","sourceRoot":"","sources":["../../src/testing/vcr-spec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,QAAQ,CAAC;AA0B9D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAc5D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,IAAI,CA8BrC"}
1
+ {"version":3,"file":"vcr-spec.d.ts","sourceRoot":"","sources":["../../src/testing/vcr-spec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,QAAQ,CAAC;AAkD9D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAW5D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,IAAI,CA8BrC"}
@@ -20,17 +20,38 @@ function isFileTask(suite) {
20
20
  return typeof suite.filepath === "string";
21
21
  }
22
22
  /**
23
- * Cassette filename for a test: `kebab(<file rel to test/, minus .spec.ts>)`
24
- * then each describe level then the test name, all kebab-cased and joined by
25
- * `--`, plus `.snapshot.json`. Example:
26
- * `recipes-arc-game-recorded--arc-game-recorded-real-api--starts-a-real-game-and-closes-the-scorecard-on-abort.snapshot.json`.
23
+ * The spec's path relative to the project root.
24
+ *
25
+ * Vitest already computes this as `file.name`, which is the whole answer: it is
26
+ * stable across machines and checkouts, and it is *unique per spec file*, which
27
+ * is what a cassette name has to be.
28
+ *
29
+ * Deriving it from `filepath` instead — by stripping a leading `test/` or
30
+ * `src/` — got this wrong twice. Splitting on a segment that never matched
31
+ * returned the absolute path unchanged, so a cassette was named after the
32
+ * developer's home directory; and stripping *both* roots collapsed
33
+ * `test/api.spec.ts` and `src/api.spec.ts` onto one name, which for a store
34
+ * keyed solely by filename means one recording silently overwrites the other
35
+ * and playback serves the wrong responses.
36
+ *
37
+ * The fallback is only for a runner that does not populate `name`; a bare
38
+ * filename can still collide, but it is strictly better than an absolute path
39
+ * and nothing here reaches it.
40
+ */
41
+ function relativeSpecPath(file) {
42
+ if (typeof file.name === "string" && file.name !== "")
43
+ return file.name;
44
+ return file.filepath.replace(/\\/g, "/").split("/").pop();
45
+ }
46
+ /**
47
+ * Cassette filename for a test: `kebab(<project-relative path, minus
48
+ * .spec.ts>)` then each describe level then the test name, all kebab-cased and
49
+ * joined by `--`, plus `.snapshot.json`. Example:
50
+ * `test-arc-agi-recorded--arc-recorded-real-api--plays-a-real-game.snapshot.json`.
27
51
  * Exported for debugging / the cassette-rename step.
28
52
  */
29
53
  export function cassetteNameFor(task) {
30
- const rel = task.file.filepath
31
- .split(/[\\/]test[\\/]/)
32
- .pop()
33
- .replace(/\.spec\.ts$/, "");
54
+ const rel = relativeSpecPath(task.file).replace(/\.spec\.ts$/, "");
34
55
  const suites = [];
35
56
  let suite = task.suite;
36
57
  while (suite && !isFileTask(suite)) {
@@ -52,9 +73,9 @@ export function setupRecording() {
52
73
  method: "POST"
53
74
  });
54
75
  if (res.status === 404) {
55
- throw new Error(`No VCR cassette "${cassette}". Record it with \`npm run test:record\` ` +
56
- `(add \`-- -t "${ctx.task.name}"\` to record only this test), which ` +
57
- `needs a real ARC_API_KEY in .env.test.`);
76
+ throw new Error(`No VCR cassette "${cassette}". Record it with \`RECORD=1\` ` +
77
+ `(add \`-t "${ctx.task.name}"\` to record only this test), which needs ` +
78
+ `whatever real credentials the recorded API calls require.`);
58
79
  }
59
80
  if (res.status === 409) {
60
81
  throw new Error(`VCR cassette "${cassette}" could not activate: another recorded test is ` +
@@ -1 +1 @@
1
- {"version":3,"file":"vcr-spec.js","sourceRoot":"","sources":["../../src/testing/vcr-spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;GAUG;AAEH,MAAM,KAAK,GAAG,CAAC,CAAS,EAAU,EAAE,CAClC,CAAC;KACE,WAAW,EAAE;KACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;KAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAE7B,kFAAkF;AAClF,SAAS,UAAU,CAAC,KAAsB;IACxC,OAAO,OAAQ,KAA+B,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,IAAoB;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ;SAC3B,KAAK,CAAC,gBAAgB,CAAC;SACvB,GAAG,EAAG;SACN,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAE9B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAgC,IAAI,CAAC,KAAK,CAAC;IACpD,OAAO,KAAK,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc;IAC5B,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACvB,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,kBAAkB,iBAAiB,QAAQ,EAAE,EAAE;YACxE,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,oBAAoB,QAAQ,4CAA4C;gBACtE,iBAAiB,GAAG,CAAC,IAAI,CAAC,IAAI,uCAAuC;gBACrE,wCAAwC,CAC3C,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,iBAAiB,QAAQ,iDAAiD;gBACxE,iEAAiE;gBACjE,kCAAkC,CACrC,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,mCAAmC,GAAG,CAAC,MAAM,iBAAiB,QAAQ,IAAI,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,KAAK,CAAC,GAAG,kBAAkB,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"vcr-spec.js","sourceRoot":"","sources":["../../src/testing/vcr-spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;GAUG;AAEH,MAAM,KAAK,GAAG,CAAC,CAAS,EAAU,EAAE,CAClC,CAAC;KACE,WAAW,EAAE;KACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;KAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAE7B,kFAAkF;AAClF,SAAS,UAAU,CAAC,KAAsB;IACxC,OAAO,OAAQ,KAA+B,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvE,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,gBAAgB,CAAC,IAA4B;IACpD,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC;IACxE,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC;AAC7D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,IAAoB;IAClD,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAgC,IAAI,CAAC,KAAK,CAAC;IACpD,OAAO,KAAK,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc;IAC5B,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACvB,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,kBAAkB,iBAAiB,QAAQ,EAAE,EAAE;YACxE,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,oBAAoB,QAAQ,iCAAiC;gBAC3D,cAAc,GAAG,CAAC,IAAI,CAAC,IAAI,6CAA6C;gBACxE,2DAA2D,CAC9D,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,iBAAiB,QAAQ,iDAAiD;gBACxE,iEAAiE;gBACjE,kCAAkC,CACrC,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,mCAAmC,GAAG,CAAC,MAAM,iBAAiB,QAAQ,IAAI,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,KAAK,CAAC,GAAG,kBAAkB,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC"}