@tangle-network/agent-app 0.60.180 → 0.60.182
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assistant/index.js +12 -12
- package/dist/chat-routes/index.js +23 -23
- package/dist/chat-store/index.js +4 -4
- package/dist/{chunk-6ZUVYAKB.js → chunk-6O2NQ7WD.js} +9 -9
- package/dist/{chunk-IIE3K2Y5.js → chunk-EOPFHXEA.js} +1 -1
- package/dist/{chunk-PYPWEXTD.js → chunk-J26IXWFK.js} +12 -12
- package/dist/chunk-LTWJYNEC.js +100 -0
- package/dist/chunk-LTWJYNEC.js.map +1 -0
- package/dist/{chunk-YR6TZ777.js → chunk-TNWDYAFX.js} +6 -6
- package/dist/{chunk-T5PPQPOD.js → chunk-TXUAGSFR.js} +1 -1
- package/dist/{chunk-T5PPQPOD.js.map → chunk-TXUAGSFR.js.map} +1 -1
- package/dist/{chunk-N3CYCSKK.js → chunk-ZBB5KQ6B.js} +1 -1
- package/dist/chunk-ZBB5KQ6B.js.map +1 -0
- package/dist/{chunk-XNKLQG26.js → chunk-ZGUXI5SI.js} +5 -5
- package/dist/design-canvas-react/index.js +4 -4
- package/dist/design-canvas-react/lazy.js +1 -1
- package/dist/model-resolution/allow-list.d.ts +64 -0
- package/dist/model-resolution/index.d.ts +1 -0
- package/dist/model-resolution/index.js +28 -0
- package/dist/model-resolution/index.js.map +1 -1
- package/dist/profile/index.js +2 -1
- package/dist/profile/index.js.map +1 -1
- package/dist/public-consultation/index.d.ts +1 -1
- package/dist/public-consultation/index.js +8 -8
- package/dist/skills/index.d.ts +1 -0
- package/dist/skills/index.js +26 -2
- package/dist/skills/marketplace-drizzle.d.ts +121 -0
- package/dist/skills/marketplace-drizzle.js +34 -0
- package/dist/skills/marketplace-drizzle.js.map +1 -0
- package/dist/skills/marketplace.d.ts +104 -0
- package/dist/skills-placement/index.js +2 -1
- package/dist/skills-placement/index.js.map +1 -1
- package/dist/spend/delegate-budget.d.ts +59 -0
- package/dist/spend/index.d.ts +1 -0
- package/dist/spend/index.js +43 -0
- package/dist/spend/index.js.map +1 -1
- package/dist/stream/index.js +2 -2
- package/dist/teams/drizzle/access.d.ts +4 -0
- package/dist/teams/drizzle.js.map +1 -1
- package/dist/teams/invitations-api.d.ts +6 -3
- package/dist/teams/invitations-api.js +72 -39
- package/dist/teams/invitations-api.js.map +1 -1
- package/dist/teams/members-api.d.ts +2 -2
- package/dist/teams/members-api.js +1 -1
- package/dist/toolbelt/index.d.ts +80 -0
- package/dist/toolbelt/index.js +178 -0
- package/dist/toolbelt/index.js.map +1 -0
- package/dist/web-react/index.js +25 -25
- package/package.json +11 -1
- package/dist/chunk-N3CYCSKK.js.map +0 -1
- /package/dist/{chunk-6ZUVYAKB.js.map → chunk-6O2NQ7WD.js.map} +0 -0
- /package/dist/{chunk-IIE3K2Y5.js.map → chunk-EOPFHXEA.js.map} +0 -0
- /package/dist/{chunk-PYPWEXTD.js.map → chunk-J26IXWFK.js.map} +0 -0
- /package/dist/{chunk-YR6TZ777.js.map → chunk-TNWDYAFX.js.map} +0 -0
- /package/dist/{chunk-XNKLQG26.js.map → chunk-ZGUXI5SI.js.map} +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/** One authored tool in the product's manifest — the ONE source of truth the
|
|
2
|
+
* generated program and every derived surface (allowlists, prompt tool
|
|
3
|
+
* tables, dashboards) must agree with. */
|
|
4
|
+
export interface ToolbeltManifestTool {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
/** AAA-standard description (what / example / when NOT). Parity requires the
|
|
7
|
+
* program to serve it byte-identical — truncation at a bundle boundary is
|
|
8
|
+
* drift, not formatting. */
|
|
9
|
+
readonly description: string;
|
|
10
|
+
/** JSON Schema for the tool's input. Compared structurally (key order
|
|
11
|
+
* insensitive) when either side declares one. */
|
|
12
|
+
readonly inputSchema?: unknown;
|
|
13
|
+
/** MCP tool annotations (readOnlyHint, …). Compared structurally when the
|
|
14
|
+
* manifest declares them. */
|
|
15
|
+
readonly annotations?: unknown;
|
|
16
|
+
/** Product-defined transport tag (`pure` | `http` | …). Not part of the
|
|
17
|
+
* wire surface; carried so derived surfaces can key off the manifest. */
|
|
18
|
+
readonly transport?: string;
|
|
19
|
+
}
|
|
20
|
+
/** A tool as the spawned program actually listed it. */
|
|
21
|
+
export interface ProbedTool {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly description?: string;
|
|
24
|
+
readonly inputSchema?: unknown;
|
|
25
|
+
readonly annotations?: unknown;
|
|
26
|
+
}
|
|
27
|
+
/** What `probeStdioToolProgram` saw. `serverInfo`/`raw` are included so a
|
|
28
|
+
* failed probe can name the layer (the diagnosability rule: never swallow). */
|
|
29
|
+
export interface ToolProgramProbe {
|
|
30
|
+
readonly tools: readonly ProbedTool[];
|
|
31
|
+
readonly initializeReply: Record<string, unknown> | null;
|
|
32
|
+
}
|
|
33
|
+
export interface ProbeStdioToolProgramOptions {
|
|
34
|
+
/** Path to the program to spawn. Spawned with the current Node executable. */
|
|
35
|
+
readonly program: string;
|
|
36
|
+
/** Extra argv after the program path. */
|
|
37
|
+
readonly args?: readonly string[];
|
|
38
|
+
/** Environment for the child. Defaults to `process.env`. */
|
|
39
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
40
|
+
/** Working directory for the child. */
|
|
41
|
+
readonly cwd?: string;
|
|
42
|
+
/** Wall-clock ceiling for the whole probe. Default 15s. */
|
|
43
|
+
readonly timeoutMs?: number;
|
|
44
|
+
}
|
|
45
|
+
/** Spawn the embedded tool program and read its REAL tool surface. */
|
|
46
|
+
export declare function probeStdioToolProgram(options: ProbeStdioToolProgramOptions): Promise<ToolProgramProbe>;
|
|
47
|
+
/** Field-level drift between the manifest and the program's real surface. */
|
|
48
|
+
export interface ToolbeltFieldDrift {
|
|
49
|
+
readonly name: string;
|
|
50
|
+
readonly manifest: unknown;
|
|
51
|
+
readonly program: unknown;
|
|
52
|
+
}
|
|
53
|
+
/** The named diff. Every array is sorted; empty arrays mean agreement. */
|
|
54
|
+
export interface ToolbeltParityDiff {
|
|
55
|
+
readonly ok: boolean;
|
|
56
|
+
/** Manifest tools the program did not list (the #10155 class: the verb
|
|
57
|
+
* exists in the manifest, absent from the running surface). */
|
|
58
|
+
readonly missingFromProgram: readonly string[];
|
|
59
|
+
/** Tools the program listed that no manifest entry owns. */
|
|
60
|
+
readonly unknownToManifest: readonly string[];
|
|
61
|
+
/** Tools whose served description is not byte-identical to the manifest. */
|
|
62
|
+
readonly descriptionDrift: readonly ToolbeltFieldDrift[];
|
|
63
|
+
/** Tools whose served input schema differs structurally from the manifest. */
|
|
64
|
+
readonly schemaDrift: readonly ToolbeltFieldDrift[];
|
|
65
|
+
/** Tools whose served annotations differ structurally from the manifest. */
|
|
66
|
+
readonly annotationDrift: readonly ToolbeltFieldDrift[];
|
|
67
|
+
}
|
|
68
|
+
/** Diff a spawned program's real surface against the authored manifest. */
|
|
69
|
+
export declare function toolbeltParityDiff(manifest: readonly ToolbeltManifestTool[], listed: readonly ProbedTool[]): ToolbeltParityDiff;
|
|
70
|
+
/** Render a diff as one actionable report — every drift named, never a bare count. */
|
|
71
|
+
export declare function formatToolbeltParityDiff(diff: ToolbeltParityDiff): string;
|
|
72
|
+
/** Thrown by {@link assertToolbeltParity} with the full formatted diff. */
|
|
73
|
+
export declare class ToolbeltParityError extends Error {
|
|
74
|
+
readonly diff: ToolbeltParityDiff;
|
|
75
|
+
constructor(diff: ToolbeltParityDiff);
|
|
76
|
+
}
|
|
77
|
+
/** Assert parity: same names, byte-identical descriptions, structurally equal
|
|
78
|
+
* schemas and annotations. Throws {@link ToolbeltParityError} with every
|
|
79
|
+
* disagreement named — a red build, not a production silence. */
|
|
80
|
+
export declare function assertToolbeltParity(manifest: readonly ToolbeltManifestTool[], listed: readonly ProbedTool[]): void;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// src/toolbelt/index.ts
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
function probeStdioToolProgram(options) {
|
|
4
|
+
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
const child = spawn(process.execPath, [options.program, ...options.args ?? []], {
|
|
7
|
+
env: options.env ?? process.env,
|
|
8
|
+
cwd: options.cwd,
|
|
9
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
10
|
+
});
|
|
11
|
+
let stdout = "";
|
|
12
|
+
let stderr = "";
|
|
13
|
+
let settled = false;
|
|
14
|
+
let initializeReply = null;
|
|
15
|
+
const lines = [];
|
|
16
|
+
const finish = (run) => {
|
|
17
|
+
if (settled) return;
|
|
18
|
+
settled = true;
|
|
19
|
+
clearTimeout(timer);
|
|
20
|
+
try {
|
|
21
|
+
child.kill();
|
|
22
|
+
} catch {
|
|
23
|
+
}
|
|
24
|
+
run();
|
|
25
|
+
};
|
|
26
|
+
const timer = setTimeout(
|
|
27
|
+
() => finish(() => reject(new Error(
|
|
28
|
+
`tool program probe timed out after ${timeoutMs}ms waiting for tools/list. stderr so far: ${stderr.trim().slice(0, 2e3) || "(empty)"}; stdout so far: ${stdout.trim().slice(0, 2e3) || "(empty)"}`
|
|
29
|
+
))),
|
|
30
|
+
timeoutMs
|
|
31
|
+
);
|
|
32
|
+
child.stdout.setEncoding("utf8");
|
|
33
|
+
child.stdout.on("data", (chunk) => {
|
|
34
|
+
stdout += chunk;
|
|
35
|
+
let index;
|
|
36
|
+
while ((index = stdout.indexOf("\n")) >= 0) {
|
|
37
|
+
const line = stdout.slice(0, index).trim();
|
|
38
|
+
stdout = stdout.slice(index + 1);
|
|
39
|
+
if (!line) continue;
|
|
40
|
+
lines.push(line);
|
|
41
|
+
let message;
|
|
42
|
+
try {
|
|
43
|
+
message = JSON.parse(line);
|
|
44
|
+
} catch {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (message.method !== void 0) continue;
|
|
48
|
+
if (message.id === 1) initializeReply = message.result ?? null;
|
|
49
|
+
if (message.id === 2 && message.result !== void 0 && message.error === void 0) {
|
|
50
|
+
const rawTools = message.result.tools;
|
|
51
|
+
const tools = Array.isArray(rawTools) ? rawTools.filter((t) => !!t && typeof t === "object" && typeof t.name === "string").map((t) => {
|
|
52
|
+
const tool = t;
|
|
53
|
+
return {
|
|
54
|
+
name: tool.name,
|
|
55
|
+
...tool.description !== void 0 ? { description: tool.description } : {},
|
|
56
|
+
...tool.inputSchema !== void 0 ? { inputSchema: tool.inputSchema } : {},
|
|
57
|
+
...tool.annotations !== void 0 ? { annotations: tool.annotations } : {}
|
|
58
|
+
};
|
|
59
|
+
}) : [];
|
|
60
|
+
finish(() => resolve({ tools, initializeReply }));
|
|
61
|
+
} else if (message.id === 2 && message.error !== void 0) {
|
|
62
|
+
finish(() => reject(new Error(
|
|
63
|
+
`tool program refused tools/list: ${JSON.stringify(message.error)}`
|
|
64
|
+
)));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
child.stderr.setEncoding("utf8");
|
|
69
|
+
child.stderr.on("data", (chunk) => {
|
|
70
|
+
stderr += chunk;
|
|
71
|
+
});
|
|
72
|
+
child.on("error", (error) => finish(() => reject(new Error(
|
|
73
|
+
`tool program probe failed to spawn ${options.program}: ${error.message}`
|
|
74
|
+
))));
|
|
75
|
+
child.on("exit", (code, signal) => finish(() => reject(new Error(
|
|
76
|
+
`tool program exited before answering tools/list (code ${code}${signal ? `, signal ${signal}` : ""}). stderr: ${stderr.trim().slice(0, 2e3) || "(empty)"}`
|
|
77
|
+
))));
|
|
78
|
+
const send = (payload) => {
|
|
79
|
+
try {
|
|
80
|
+
child.stdin.write(JSON.stringify(payload) + "\n");
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
send({ jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "2024-11-05", capabilities: {}, clientInfo: { name: "toolbelt-parity", version: "0.0.0" } } });
|
|
85
|
+
send({ jsonrpc: "2.0", method: "notifications/initialized" });
|
|
86
|
+
send({ jsonrpc: "2.0", id: 2, method: "tools/list" });
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function stableStringify(value) {
|
|
90
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
|
|
91
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
92
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
93
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
|
|
94
|
+
}
|
|
95
|
+
function toolbeltParityDiff(manifest, listed) {
|
|
96
|
+
const byName = new Map(manifest.map((tool) => [tool.name, tool]));
|
|
97
|
+
const listedByName = new Map(listed.map((tool) => [tool.name, tool]));
|
|
98
|
+
const missingFromProgram = manifest.filter((tool) => !listedByName.has(tool.name)).map((tool) => tool.name).sort();
|
|
99
|
+
const unknownToManifest = listed.filter((tool) => !byName.has(tool.name)).map((tool) => tool.name).sort();
|
|
100
|
+
const descriptionDrift = [];
|
|
101
|
+
const schemaDrift = [];
|
|
102
|
+
const annotationDrift = [];
|
|
103
|
+
for (const tool of manifest) {
|
|
104
|
+
const served = listedByName.get(tool.name);
|
|
105
|
+
if (!served) continue;
|
|
106
|
+
if (served.description !== tool.description) {
|
|
107
|
+
descriptionDrift.push({ name: tool.name, manifest: tool.description, program: served.description ?? null });
|
|
108
|
+
}
|
|
109
|
+
const manifestSchema = tool.inputSchema;
|
|
110
|
+
if (manifestSchema !== void 0 || served.inputSchema !== void 0) {
|
|
111
|
+
if (stableStringify(manifestSchema) !== stableStringify(served.inputSchema)) {
|
|
112
|
+
schemaDrift.push({ name: tool.name, manifest: manifestSchema ?? null, program: served.inputSchema ?? null });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const manifestAnnotations = tool.annotations;
|
|
116
|
+
if (manifestAnnotations !== void 0 || served.annotations !== void 0) {
|
|
117
|
+
if (stableStringify(manifestAnnotations) !== stableStringify(served.annotations)) {
|
|
118
|
+
annotationDrift.push({ name: tool.name, manifest: manifestAnnotations ?? null, program: served.annotations ?? null });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const ok = missingFromProgram.length === 0 && unknownToManifest.length === 0 && descriptionDrift.length === 0 && schemaDrift.length === 0 && annotationDrift.length === 0;
|
|
123
|
+
return {
|
|
124
|
+
ok,
|
|
125
|
+
missingFromProgram,
|
|
126
|
+
unknownToManifest,
|
|
127
|
+
descriptionDrift,
|
|
128
|
+
schemaDrift,
|
|
129
|
+
annotationDrift
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function formatToolbeltParityDiff(diff) {
|
|
133
|
+
if (diff.ok) return "toolbelt parity: the program is the manifest";
|
|
134
|
+
const lines = ["toolbelt parity FAILED \u2014 the program and the manifest disagree:"];
|
|
135
|
+
if (diff.missingFromProgram.length > 0) {
|
|
136
|
+
lines.push(` missing from the program (in the manifest, NOT served): ${diff.missingFromProgram.join(", ")}`);
|
|
137
|
+
}
|
|
138
|
+
if (diff.unknownToManifest.length > 0) {
|
|
139
|
+
lines.push(` unknown to the manifest (served, NOT authored): ${diff.unknownToManifest.join(", ")}`);
|
|
140
|
+
}
|
|
141
|
+
for (const drift of diff.descriptionDrift) {
|
|
142
|
+
lines.push(` description drift on "${drift.name}":`);
|
|
143
|
+
lines.push(` manifest: ${JSON.stringify(drift.manifest)}`);
|
|
144
|
+
lines.push(` program: ${JSON.stringify(drift.program)}`);
|
|
145
|
+
}
|
|
146
|
+
for (const drift of diff.schemaDrift) {
|
|
147
|
+
lines.push(` input-schema drift on "${drift.name}":`);
|
|
148
|
+
lines.push(` manifest: ${stableStringify(drift.manifest)}`);
|
|
149
|
+
lines.push(` program: ${stableStringify(drift.program)}`);
|
|
150
|
+
}
|
|
151
|
+
for (const drift of diff.annotationDrift) {
|
|
152
|
+
lines.push(` annotation drift on "${drift.name}":`);
|
|
153
|
+
lines.push(` manifest: ${stableStringify(drift.manifest)}`);
|
|
154
|
+
lines.push(` program: ${stableStringify(drift.program)}`);
|
|
155
|
+
}
|
|
156
|
+
lines.push(" Fix the ONE manifest (or the generator that derives the program from it) \u2014 never patch a second list.");
|
|
157
|
+
return lines.join("\n");
|
|
158
|
+
}
|
|
159
|
+
var ToolbeltParityError = class extends Error {
|
|
160
|
+
diff;
|
|
161
|
+
constructor(diff) {
|
|
162
|
+
super(formatToolbeltParityDiff(diff));
|
|
163
|
+
this.name = "ToolbeltParityError";
|
|
164
|
+
this.diff = diff;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
function assertToolbeltParity(manifest, listed) {
|
|
168
|
+
const diff = toolbeltParityDiff(manifest, listed);
|
|
169
|
+
if (!diff.ok) throw new ToolbeltParityError(diff);
|
|
170
|
+
}
|
|
171
|
+
export {
|
|
172
|
+
ToolbeltParityError,
|
|
173
|
+
assertToolbeltParity,
|
|
174
|
+
formatToolbeltParityDiff,
|
|
175
|
+
probeStdioToolProgram,
|
|
176
|
+
toolbeltParityDiff
|
|
177
|
+
};
|
|
178
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/toolbelt/index.ts"],"sourcesContent":["/**\n * The toolbelt parity gate — one manifest, every target, enforced at build time.\n *\n * A product with an embedded tool program (a stdio MCP the sandbox spawns)\n * has two representations of its tool surface: the manifest it authors and\n * the program that actually answers `tools/list`. Every hour of pain in the\n * fleet's toolbelt history was those two lists disagreeing — a verb present\n * in one target and absent from the other shipped green and failed in\n * production (hardware-agent #10155 class). This module turns that drift\n * class into a red test: spawn the program, read its real surface, diff it\n * against the manifest, and name every disagreement.\n *\n * Substrate-free by design: Node builtins only, no test-framework\n * dependency, no MCP SDK. `probeStdioToolProgram` speaks just enough\n * JSON-RPC (initialize → initialized → tools/list, replies matched by id,\n * notifications ignored) for a zero-dependency embedded program; the diff\n * and the assert are pure functions any runner (vitest, node:test, a tsx\n * script) can call.\n *\n * Canonical consumer shape:\n *\n * ```ts\n * import { assertToolbeltParity, probeStdioToolProgram } from '@tangle-network/agent-app/toolbelt'\n *\n * const probed = await probeStdioToolProgram({ program: programPath, env })\n * assertToolbeltParity(TOOLBELT, probed.tools) // throws with the named diff\n * ```\n */\nimport { spawn } from 'node:child_process'\n\n/** One authored tool in the product's manifest — the ONE source of truth the\n * generated program and every derived surface (allowlists, prompt tool\n * tables, dashboards) must agree with. */\nexport interface ToolbeltManifestTool {\n readonly name: string\n /** AAA-standard description (what / example / when NOT). Parity requires the\n * program to serve it byte-identical — truncation at a bundle boundary is\n * drift, not formatting. */\n readonly description: string\n /** JSON Schema for the tool's input. Compared structurally (key order\n * insensitive) when either side declares one. */\n readonly inputSchema?: unknown\n /** MCP tool annotations (readOnlyHint, …). Compared structurally when the\n * manifest declares them. */\n readonly annotations?: unknown\n /** Product-defined transport tag (`pure` | `http` | …). Not part of the\n * wire surface; carried so derived surfaces can key off the manifest. */\n readonly transport?: string\n}\n\n/** A tool as the spawned program actually listed it. */\nexport interface ProbedTool {\n readonly name: string\n readonly description?: string\n readonly inputSchema?: unknown\n readonly annotations?: unknown\n}\n\n/** What `probeStdioToolProgram` saw. `serverInfo`/`raw` are included so a\n * failed probe can name the layer (the diagnosability rule: never swallow). */\nexport interface ToolProgramProbe {\n readonly tools: readonly ProbedTool[]\n readonly initializeReply: Record<string, unknown> | null\n}\n\nexport interface ProbeStdioToolProgramOptions {\n /** Path to the program to spawn. Spawned with the current Node executable. */\n readonly program: string\n /** Extra argv after the program path. */\n readonly args?: readonly string[]\n /** Environment for the child. Defaults to `process.env`. */\n readonly env?: NodeJS.ProcessEnv\n /** Working directory for the child. */\n readonly cwd?: string\n /** Wall-clock ceiling for the whole probe. Default 15s. */\n readonly timeoutMs?: number\n}\n\n/** Spawn the embedded tool program and read its REAL tool surface. */\nexport function probeStdioToolProgram(options: ProbeStdioToolProgramOptions): Promise<ToolProgramProbe> {\n const timeoutMs = options.timeoutMs ?? 15_000\n return new Promise<ToolProgramProbe>((resolve, reject) => {\n const child = spawn(process.execPath, [options.program, ...(options.args ?? [])], {\n env: options.env ?? process.env,\n cwd: options.cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n let stdout = ''\n let stderr = ''\n let settled = false\n let initializeReply: Record<string, unknown> | null = null\n const lines: string[] = []\n\n const finish = (run: () => void) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n try { child.kill() } catch { /* already gone */ }\n run()\n }\n\n const timer = setTimeout(\n () => finish(() => reject(new Error(\n `tool program probe timed out after ${timeoutMs}ms waiting for tools/list. ` +\n `stderr so far: ${stderr.trim().slice(0, 2000) || '(empty)'}; ` +\n `stdout so far: ${stdout.trim().slice(0, 2000) || '(empty)'}`,\n ))),\n timeoutMs,\n )\n\n child.stdout.setEncoding('utf8')\n child.stdout.on('data', (chunk: string) => {\n stdout += chunk\n let index: number\n while ((index = stdout.indexOf('\\n')) >= 0) {\n const line = stdout.slice(0, index).trim()\n stdout = stdout.slice(index + 1)\n if (!line) continue\n lines.push(line)\n let message: Record<string, unknown>\n try {\n message = JSON.parse(line) as Record<string, unknown>\n } catch {\n continue // a banner line, not JSON-RPC\n }\n if (message.method !== undefined) continue // notification from server\n if (message.id === 1) initializeReply = message.result as Record<string, unknown> ?? null\n if (message.id === 2 && message.result !== undefined && message.error === undefined) {\n const rawTools = (message.result as { tools?: unknown }).tools\n const tools: ProbedTool[] = Array.isArray(rawTools)\n ? rawTools.filter((t): t is Record<string, unknown> => !!t && typeof t === 'object' && typeof (t as { name?: unknown }).name === 'string')\n .map((t) => {\n const tool = t as unknown as { name: string; description?: string; inputSchema?: unknown; annotations?: unknown }\n return {\n name: tool.name,\n ...(tool.description !== undefined ? { description: tool.description } : {}),\n ...(tool.inputSchema !== undefined ? { inputSchema: tool.inputSchema } : {}),\n ...(tool.annotations !== undefined ? { annotations: tool.annotations } : {}),\n }\n })\n : []\n finish(() => resolve({ tools, initializeReply }))\n } else if (message.id === 2 && message.error !== undefined) {\n finish(() => reject(new Error(\n `tool program refused tools/list: ${JSON.stringify(message.error)}`,\n )))\n }\n }\n })\n child.stderr.setEncoding('utf8')\n child.stderr.on('data', (chunk: string) => { stderr += chunk })\n child.on('error', (error) => finish(() => reject(new Error(\n `tool program probe failed to spawn ${options.program}: ${error.message}`,\n ))))\n child.on('exit', (code, signal) => finish(() => reject(new Error(\n `tool program exited before answering tools/list (code ${code}${signal ? `, signal ${signal}` : ''}). ` +\n `stderr: ${stderr.trim().slice(0, 2000) || '(empty)'}`,\n ))))\n\n // Minimal MCP handshake: initialize → initialized → tools/list. Replies\n // are matched by id; a program that never replies to initialize still\n // resolves the probe when its tools/list reply arrives.\n const send = (payload: unknown) => { try { child.stdin.write(JSON.stringify(payload) + '\\n') } catch { /* closed; exit handler reports */ } }\n send({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'toolbelt-parity', version: '0.0.0' } } })\n send({ jsonrpc: '2.0', method: 'notifications/initialized' })\n send({ jsonrpc: '2.0', id: 2, method: 'tools/list' })\n })\n}\n\n/** Structural equality with sorted keys — two JSON schemas are the same\n * contract regardless of key order. */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value) ?? 'null'\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(',')}}`\n}\n\n/** Field-level drift between the manifest and the program's real surface. */\nexport interface ToolbeltFieldDrift {\n readonly name: string\n readonly manifest: unknown\n readonly program: unknown\n}\n\n/** The named diff. Every array is sorted; empty arrays mean agreement. */\nexport interface ToolbeltParityDiff {\n readonly ok: boolean\n /** Manifest tools the program did not list (the #10155 class: the verb\n * exists in the manifest, absent from the running surface). */\n readonly missingFromProgram: readonly string[]\n /** Tools the program listed that no manifest entry owns. */\n readonly unknownToManifest: readonly string[]\n /** Tools whose served description is not byte-identical to the manifest. */\n readonly descriptionDrift: readonly ToolbeltFieldDrift[]\n /** Tools whose served input schema differs structurally from the manifest. */\n readonly schemaDrift: readonly ToolbeltFieldDrift[]\n /** Tools whose served annotations differ structurally from the manifest. */\n readonly annotationDrift: readonly ToolbeltFieldDrift[]\n}\n\n/** Diff a spawned program's real surface against the authored manifest. */\nexport function toolbeltParityDiff(\n manifest: readonly ToolbeltManifestTool[],\n listed: readonly ProbedTool[],\n): ToolbeltParityDiff {\n const byName = new Map(manifest.map((tool) => [tool.name, tool]))\n const listedByName = new Map(listed.map((tool) => [tool.name, tool]))\n const missingFromProgram = manifest\n .filter((tool) => !listedByName.has(tool.name))\n .map((tool) => tool.name)\n .sort()\n const unknownToManifest = listed\n .filter((tool) => !byName.has(tool.name))\n .map((tool) => tool.name)\n .sort()\n const descriptionDrift: ToolbeltFieldDrift[] = []\n const schemaDrift: ToolbeltFieldDrift[] = []\n const annotationDrift: ToolbeltFieldDrift[] = []\n for (const tool of manifest) {\n const served = listedByName.get(tool.name)\n if (!served) continue\n if (served.description !== tool.description) {\n descriptionDrift.push({ name: tool.name, manifest: tool.description, program: served.description ?? null })\n }\n const manifestSchema = tool.inputSchema\n if (manifestSchema !== undefined || served.inputSchema !== undefined) {\n if (stableStringify(manifestSchema) !== stableStringify(served.inputSchema)) {\n schemaDrift.push({ name: tool.name, manifest: manifestSchema ?? null, program: served.inputSchema ?? null })\n }\n }\n const manifestAnnotations = tool.annotations\n if (manifestAnnotations !== undefined || served.annotations !== undefined) {\n if (stableStringify(manifestAnnotations) !== stableStringify(served.annotations)) {\n annotationDrift.push({ name: tool.name, manifest: manifestAnnotations ?? null, program: served.annotations ?? null })\n }\n }\n }\n const ok = missingFromProgram.length === 0\n && unknownToManifest.length === 0\n && descriptionDrift.length === 0\n && schemaDrift.length === 0\n && annotationDrift.length === 0\n return {\n ok,\n missingFromProgram,\n unknownToManifest,\n descriptionDrift,\n schemaDrift,\n annotationDrift,\n }\n}\n\n/** Render a diff as one actionable report — every drift named, never a bare count. */\nexport function formatToolbeltParityDiff(diff: ToolbeltParityDiff): string {\n if (diff.ok) return 'toolbelt parity: the program is the manifest'\n const lines = ['toolbelt parity FAILED — the program and the manifest disagree:']\n if (diff.missingFromProgram.length > 0) {\n lines.push(` missing from the program (in the manifest, NOT served): ${diff.missingFromProgram.join(', ')}`)\n }\n if (diff.unknownToManifest.length > 0) {\n lines.push(` unknown to the manifest (served, NOT authored): ${diff.unknownToManifest.join(', ')}`)\n }\n for (const drift of diff.descriptionDrift) {\n lines.push(` description drift on \"${drift.name}\":`)\n lines.push(` manifest: ${JSON.stringify(drift.manifest)}`)\n lines.push(` program: ${JSON.stringify(drift.program)}`)\n }\n for (const drift of diff.schemaDrift) {\n lines.push(` input-schema drift on \"${drift.name}\":`)\n lines.push(` manifest: ${stableStringify(drift.manifest)}`)\n lines.push(` program: ${stableStringify(drift.program)}`)\n }\n for (const drift of diff.annotationDrift) {\n lines.push(` annotation drift on \"${drift.name}\":`)\n lines.push(` manifest: ${stableStringify(drift.manifest)}`)\n lines.push(` program: ${stableStringify(drift.program)}`)\n }\n lines.push(' Fix the ONE manifest (or the generator that derives the program from it) — never patch a second list.')\n return lines.join('\\n')\n}\n\n/** Thrown by {@link assertToolbeltParity} with the full formatted diff. */\nexport class ToolbeltParityError extends Error {\n readonly diff: ToolbeltParityDiff\n constructor(diff: ToolbeltParityDiff) {\n super(formatToolbeltParityDiff(diff))\n this.name = 'ToolbeltParityError'\n this.diff = diff\n }\n}\n\n/** Assert parity: same names, byte-identical descriptions, structurally equal\n * schemas and annotations. Throws {@link ToolbeltParityError} with every\n * disagreement named — a red build, not a production silence. */\nexport function assertToolbeltParity(\n manifest: readonly ToolbeltManifestTool[],\n listed: readonly ProbedTool[],\n): void {\n const diff = toolbeltParityDiff(manifest, listed)\n if (!diff.ok) throw new ToolbeltParityError(diff)\n}\n"],"mappings":"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","names":[]}
|
package/dist/web-react/index.js
CHANGED
|
@@ -143,7 +143,7 @@ import {
|
|
|
143
143
|
withoutRecordGridCreated,
|
|
144
144
|
withoutRecordGridRemoved,
|
|
145
145
|
withoutRecordGridUpdate
|
|
146
|
-
} from "../chunk-
|
|
146
|
+
} from "../chunk-6O2NQ7WD.js";
|
|
147
147
|
import {
|
|
148
148
|
SessionHistoryPanel,
|
|
149
149
|
formatSessionTimestamp,
|
|
@@ -155,20 +155,6 @@ import {
|
|
|
155
155
|
MENTION_PILL_CLASS
|
|
156
156
|
} from "../chunk-3HUFJ5LO.js";
|
|
157
157
|
import "../chunk-FBVLEGEG.js";
|
|
158
|
-
import {
|
|
159
|
-
WorkspaceInitial,
|
|
160
|
-
WorkspaceSwitcher
|
|
161
|
-
} from "../chunk-UDLA3NGY.js";
|
|
162
|
-
import "../chunk-A2GG4D4A.js";
|
|
163
|
-
import {
|
|
164
|
-
tabTerminalConnectionId,
|
|
165
|
-
useSandboxTerminalConnection
|
|
166
|
-
} from "../chunk-E4AY62T2.js";
|
|
167
|
-
import {
|
|
168
|
-
AGENT_PROFILE_EDITOR_SECTIONS,
|
|
169
|
-
AgentProfileEditor,
|
|
170
|
-
AgentProfileRegistryError
|
|
171
|
-
} from "../chunk-3RHAF2P5.js";
|
|
172
158
|
import {
|
|
173
159
|
EvidenceLineageTable,
|
|
174
160
|
ExceptionList,
|
|
@@ -182,9 +168,6 @@ import {
|
|
|
182
168
|
workProductStatusLabel,
|
|
183
169
|
workProductStatusTone
|
|
184
170
|
} from "../chunk-Y6PRDUFJ.js";
|
|
185
|
-
import {
|
|
186
|
-
parseReviewQueueItem
|
|
187
|
-
} from "../chunk-GEYACSFW.js";
|
|
188
171
|
import {
|
|
189
172
|
ChatComposer,
|
|
190
173
|
ComposerModeControls,
|
|
@@ -199,7 +182,21 @@ import {
|
|
|
199
182
|
useDictation
|
|
200
183
|
} from "../chunk-BBHVV37T.js";
|
|
201
184
|
import "../chunk-L7MB2LLM.js";
|
|
185
|
+
import {
|
|
186
|
+
WorkspaceInitial,
|
|
187
|
+
WorkspaceSwitcher
|
|
188
|
+
} from "../chunk-UDLA3NGY.js";
|
|
189
|
+
import "../chunk-A2GG4D4A.js";
|
|
190
|
+
import {
|
|
191
|
+
tabTerminalConnectionId,
|
|
192
|
+
useSandboxTerminalConnection
|
|
193
|
+
} from "../chunk-E4AY62T2.js";
|
|
202
194
|
import "../chunk-SJWIZT7B.js";
|
|
195
|
+
import {
|
|
196
|
+
AGENT_PROFILE_EDITOR_SECTIONS,
|
|
197
|
+
AgentProfileEditor,
|
|
198
|
+
AgentProfileRegistryError
|
|
199
|
+
} from "../chunk-3RHAF2P5.js";
|
|
203
200
|
import {
|
|
204
201
|
AgentSessionControls,
|
|
205
202
|
AgentSettingsPopover,
|
|
@@ -230,13 +227,16 @@ import {
|
|
|
230
227
|
usePopover
|
|
231
228
|
} from "../chunk-TJ4DYKF2.js";
|
|
232
229
|
import {
|
|
233
|
-
|
|
234
|
-
} from "../chunk-
|
|
235
|
-
import "../chunk-LN5RBVGP.js";
|
|
230
|
+
parseReviewQueueItem
|
|
231
|
+
} from "../chunk-GEYACSFW.js";
|
|
236
232
|
import {
|
|
237
233
|
ReviewFeedbackForm
|
|
238
234
|
} from "../chunk-ATQQCG4I.js";
|
|
239
235
|
import "../chunk-WSEXFTN4.js";
|
|
236
|
+
import {
|
|
237
|
+
ProviderLogo
|
|
238
|
+
} from "../chunk-RASGKEAL.js";
|
|
239
|
+
import "../chunk-LN5RBVGP.js";
|
|
240
240
|
import "../chunk-FQYAJYPW.js";
|
|
241
241
|
import {
|
|
242
242
|
ATTACHMENT_ACCEPT
|
|
@@ -252,8 +252,7 @@ import {
|
|
|
252
252
|
isChatAttachmentPart,
|
|
253
253
|
mentionInputToPart,
|
|
254
254
|
mentionPartsFromMessageParts
|
|
255
|
-
} from "../chunk-
|
|
256
|
-
import "../chunk-ZVEEWGDK.js";
|
|
255
|
+
} from "../chunk-TNWDYAFX.js";
|
|
257
256
|
import {
|
|
258
257
|
DISPATCH_MAX_MEDIA_PARTS,
|
|
259
258
|
DISPATCH_MAX_PARTS,
|
|
@@ -277,11 +276,11 @@ import {
|
|
|
277
276
|
mentionKindForPath,
|
|
278
277
|
settleTurnResponse
|
|
279
278
|
} from "../chunk-YHRWZZJN.js";
|
|
279
|
+
import "../chunk-ZVEEWGDK.js";
|
|
280
280
|
import "../chunk-TXD5HXLE.js";
|
|
281
281
|
import {
|
|
282
282
|
attachmentPartKey
|
|
283
|
-
} from "../chunk-
|
|
284
|
-
import "../chunk-LQYIBL3G.js";
|
|
283
|
+
} from "../chunk-ZGUXI5SI.js";
|
|
285
284
|
import {
|
|
286
285
|
INTERACTION_CANCEL_EVENT,
|
|
287
286
|
INTERACTION_EVENT,
|
|
@@ -307,6 +306,7 @@ import {
|
|
|
307
306
|
questionInteractionContentSignature,
|
|
308
307
|
stampInteractionAnswers
|
|
309
308
|
} from "../chunk-6VQCFJWP.js";
|
|
309
|
+
import "../chunk-LQYIBL3G.js";
|
|
310
310
|
export {
|
|
311
311
|
AGENT_PROFILE_EDITOR_SECTIONS,
|
|
312
312
|
ATTACHMENT_ACCEPT,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-app",
|
|
3
|
-
"version": "0.60.
|
|
3
|
+
"version": "0.60.182",
|
|
4
4
|
"packageManager": "pnpm@11.24.0",
|
|
5
5
|
"description": "Build agent applications with typed chat, tools, sandboxes, integrations, billing, and evaluation.",
|
|
6
6
|
"keywords": [
|
|
@@ -124,11 +124,21 @@
|
|
|
124
124
|
"import": "./dist/skills/index.js",
|
|
125
125
|
"default": "./dist/skills/index.js"
|
|
126
126
|
},
|
|
127
|
+
"./skills/marketplace-drizzle": {
|
|
128
|
+
"types": "./dist/skills/marketplace-drizzle.d.ts",
|
|
129
|
+
"import": "./dist/skills/marketplace-drizzle.js",
|
|
130
|
+
"default": "./dist/skills/marketplace-drizzle.js"
|
|
131
|
+
},
|
|
127
132
|
"./skills-placement": {
|
|
128
133
|
"types": "./dist/skills-placement/index.d.ts",
|
|
129
134
|
"import": "./dist/skills-placement/index.js",
|
|
130
135
|
"default": "./dist/skills-placement/index.js"
|
|
131
136
|
},
|
|
137
|
+
"./toolbelt": {
|
|
138
|
+
"types": "./dist/toolbelt/index.d.ts",
|
|
139
|
+
"import": "./dist/toolbelt/index.js",
|
|
140
|
+
"default": "./dist/toolbelt/index.js"
|
|
141
|
+
},
|
|
132
142
|
"./profile": {
|
|
133
143
|
"types": "./dist/profile/index.d.ts",
|
|
134
144
|
"import": "./dist/profile/index.js",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/teams/members-api.ts"],"sourcesContent":["/**\n * Framework-neutral members API for the teams module: the invite / list /\n * update-role / remove / accept-invite logic, lifted out of any one app's route\n * file. Each app mounts these in its own route with its own auth — the handlers\n * take an already-authenticated `actor`, the parsed inputs, the `db` + `tables`\n * from `createTeamTables`, the product's user + workspace tables, and the\n * workspace-access API from `createWorkspaceAccess`. They return web-standard\n * `Response`s (available in Workers, Node 18+, Deno, browsers), so\n * \"framework-neutral\" is literal: no Remix/React-Router/Express import anywhere.\n *\n * Two OPTIONAL seams an app wires only if it needs them:\n * - `enforceSeat` — billing/seat-limit gate, called at invite time only when\n * the invite would consume a NEW billable seat. An app without seat billing\n * passes nothing and seats are never checked.\n * - `memberSyncSeam` — fire-and-forget propagation of membership changes to a\n * sandbox/external system (add on accept, role on update, remove on\n * delete). An app without sandbox sync passes nothing. Fail-soft by\n * contract: a thrown sync is caught and never blocks the DB mutation.\n *\n * Imports `drizzle-orm`, so this is a subpath, never re-exported from root.\n */\n\nimport { and, eq, isNull } from 'drizzle-orm'\nimport { INVITATION_EMAIL_HINT, isInvitationEmail } from './invitations'\nimport {\n type AssignableWorkspaceRole,\n type WorkspaceRole,\n canManageWorkspaceMemberRole,\n hasWorkspaceRole,\n isAssignableWorkspaceRole,\n organizationRoleGrantsWorkspaceOwner,\n} from './roles'\nimport { generateInviteToken } from './invite'\nimport type { TeamDatabase, WorkspaceAccessApi } from './drizzle/access'\nimport type { TeamParentTable, TeamTables } from './drizzle/schema'\n\n/** The authenticated caller — apps resolve this from their own session layer. */\nexport interface MembersApiActor {\n id: string\n email?: string | null\n}\n\n/**\n * The product's user table, narrowed to the columns the member queries read.\n * Adopters pass their real drizzle user table.\n */\nexport interface UserLookupTable {\n id: any\n name: any\n email: any\n}\n\n/**\n * The product's workspace table, narrowed to the columns the member queries\n * read. The handlers join it to resolve a workspace's organization (the same\n * table passed to createTeamTables as workspaceTable).\n */\nexport interface WorkspaceLookupTable {\n id: any\n organizationId: any\n}\n\n/**\n * Optional billing seat gate. The seam resolves the count input itself (it\n * owns the plan/seat model) and throws when over the limit; the handler turns a\n * thrown `SeatLimitError` into a 402. Called only when an invite would consume\n * a NEW seat (invitee is not already an org member and has no pending org\n * invite) — the same guard gtm uses, so the seam never fires on a no-op invite.\n */\nexport interface EnforceSeatSeam {\n (input: { actorId: string; organizationId: string }): Promise<void> | void\n}\n\n/** Thrown by an `enforceSeat` seam to deny an invite; serialized to a 402. */\nexport class SeatLimitError extends Error {\n readonly status: number\n readonly capability?: string\n readonly requiredPlan?: string\n constructor(message: string, opts: { status?: number; capability?: string; requiredPlan?: string } = {}) {\n super(message)\n this.name = 'SeatLimitError'\n this.status = opts.status ?? 402\n this.capability = opts.capability\n this.requiredPlan = opts.requiredPlan\n }\n}\n\n/**\n * Optional membership-change propagation to an external system (e.g. sandbox).\n * Every method is fire-and-forget and fail-soft: the handler awaits nothing and\n * swallows rejections, so an unavailable downstream never blocks the mutation.\n * Each fires only for members with a real `userId` (never email-only invites).\n */\nexport interface MemberSyncSeam {\n add?(input: { workspaceId: string; userId: string; role: WorkspaceRole }): Promise<void> | void\n role?(input: { workspaceId: string; userId: string; role: WorkspaceRole }): Promise<void> | void\n remove?(input: { workspaceId: string; userId: string }): Promise<void> | void\n}\n\n/** Define configuration options for managing team members and workspace access APIs */\nexport interface MembersApiOptions {\n db: TeamDatabase\n tables: TeamTables\n /** The product's user table (FK target passed to createTeamTables). */\n userTable: TeamParentTable & UserLookupTable\n /** The product's workspace table (FK target passed to createTeamTables). */\n workspaceTable: TeamParentTable & WorkspaceLookupTable\n /** Workspace-access API from createWorkspaceAccess — RBAC stays one source. */\n access: Pick<WorkspaceAccessApi, 'getWorkspaceAccess'>\n enforceSeat?: EnforceSeatSeam\n memberSyncSeam?: MemberSyncSeam\n}\n\n/** Define the structure of a workspace member entry with identification, role, and status details */\nexport interface MemberListEntry {\n id: string\n userId: string | null\n organizationMemberId: string | null\n role: WorkspaceRole\n name: string | null\n email: string | null\n invitedAt: Date | number | null\n acceptedAt: Date | number | null\n inherited: boolean\n}\n\n/**\n * Build the members API bound to one product's db/tables/access. Returns five\n * handlers; an app maps its route methods onto them (GET→list, POST→invite,\n * PATCH→updateRole, DELETE→remove; accept on its own route).\n */\nexport function createMembersApi(opts: MembersApiOptions) {\n const { db, tables, userTable, workspaceTable, access, enforceSeat, memberSyncSeam } = opts\n const { organizations, organizationMembers, workspaceMembers } = tables\n const users = userTable\n const workspaces = workspaceTable\n\n function fireSync(op: () => Promise<void> | void) {\n try {\n Promise.resolve(op()).catch(() => {})\n } catch {\n // seam threw synchronously — swallow; sync is best-effort by contract.\n }\n }\n\n async function listMembers(input: { workspaceId: string; actor: MembersApiActor }): Promise<Response> {\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id)\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n\n const organizationId = (accessRow.workspace as { organizationId: string }).organizationId\n\n const [projectMembers, orgAdmins] = await Promise.all([\n db\n .select({\n id: workspaceMembers.id,\n organizationMemberId: workspaceMembers.organizationMemberId,\n userId: workspaceMembers.userId,\n role: workspaceMembers.role,\n invitedAt: workspaceMembers.invitedAt,\n acceptedAt: workspaceMembers.acceptedAt,\n inviteEmail: workspaceMembers.inviteEmail,\n userName: users.name,\n userEmail: users.email,\n })\n .from(workspaceMembers)\n .leftJoin(users, eq(users.id, workspaceMembers.userId))\n .where(eq(workspaceMembers.workspaceId, input.workspaceId)),\n db\n .select({\n id: organizationMembers.id,\n userId: organizationMembers.userId,\n orgRole: organizationMembers.role,\n userName: users.name,\n userEmail: users.email,\n createdAt: organizationMembers.createdAt,\n })\n .from(organizationMembers)\n .innerJoin(users, eq(users.id, organizationMembers.userId))\n .where(eq(organizationMembers.organizationId, organizationId)),\n ])\n\n const explicitOrgMemberIds = new Set(\n projectMembers.map((m: any) => m.organizationMemberId).filter(Boolean),\n )\n const members: MemberListEntry[] = [\n ...orgAdmins\n .filter((m: any) => organizationRoleGrantsWorkspaceOwner(m.orgRole) && !explicitOrgMemberIds.has(m.id))\n .map((m: any) => ({\n id: `org:${m.id}`,\n userId: m.userId,\n organizationMemberId: m.id,\n role: 'owner' as WorkspaceRole,\n name: m.userName,\n email: m.userEmail,\n invitedAt: m.createdAt,\n acceptedAt: m.createdAt,\n inherited: true,\n })),\n ...projectMembers.map((m: any) => ({\n id: m.id,\n userId: m.userId,\n organizationMemberId: m.organizationMemberId,\n role: m.role as WorkspaceRole,\n name: m.userName,\n email: m.userEmail ?? m.inviteEmail,\n invitedAt: m.invitedAt,\n acceptedAt: m.acceptedAt,\n inherited: false,\n })),\n ]\n\n return Response.json({ members, currentRole: accessRow.role, organizationId })\n }\n\n async function inviteMember(input: {\n workspaceId: string\n actor: MembersApiActor\n email?: string\n role?: string\n }): Promise<Response> {\n if (!input.email) return Response.json({ error: 'Missing email' }, { status: 400 })\n if (!isInvitationEmail(input.email)) return Response.json({ error: INVITATION_EMAIL_HINT }, { status: 400 })\n const requestedRole = input.role ?? 'editor'\n if (!isAssignableWorkspaceRole(requestedRole)) {\n return Response.json({ error: 'Invalid role. Must be viewer, editor, or admin.' }, { status: 400 })\n }\n const assignRole: AssignableWorkspaceRole = requestedRole\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id, 'admin')\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n if (!hasWorkspaceRole(accessRow.role, assignRole)) {\n return Response.json({ error: 'Cannot assign a role higher than your own' }, { status: 403 })\n }\n\n const organizationId = (accessRow.workspace as { organizationId: string }).organizationId\n const normalizedEmail = input.email.toLowerCase().trim()\n const invitee = await getUserByEmail(normalizedEmail)\n const existingOrgMember = invitee ? await getOrganizationMember(organizationId, invitee.id) : null\n\n if (organizationRoleGrantsWorkspaceOwner(existingOrgMember?.role)) {\n return Response.json({ error: 'Organization admins already have project access' }, { status: 409 })\n }\n\n const existingInvite = await findExistingProjectInvite(input.workspaceId, normalizedEmail, invitee?.id)\n if (existingInvite) {\n return Response.json({ error: 'This collaborator is already invited to this project' }, { status: 409 })\n }\n\n if (enforceSeat && !existingOrgMember && !(await hasPendingOrgInvite(organizationId, normalizedEmail))) {\n try {\n await enforceSeat({ actorId: input.actor.id, organizationId })\n } catch (err) {\n if (err instanceof SeatLimitError) {\n return Response.json(\n { error: err.message, capability: err.capability, requiredPlan: err.requiredPlan },\n { status: err.status },\n )\n }\n throw err\n }\n }\n\n const token = generateInviteToken()\n const [member] = await db\n .insert(workspaceMembers)\n .values({\n workspaceId: input.workspaceId,\n organizationMemberId: existingOrgMember?.id ?? null,\n userId: invitee?.id ?? null,\n role: assignRole,\n invitedBy: input.actor.id,\n inviteEmail: normalizedEmail,\n inviteToken: token,\n })\n .returning()\n\n return Response.json({ member, inviteToken: token })\n }\n\n async function updateMemberRole(input: {\n workspaceId: string\n actor: MembersApiActor\n memberId?: string\n role?: string\n }): Promise<Response> {\n if (!input.memberId || !input.role) {\n return Response.json({ error: 'Missing memberId or role' }, { status: 400 })\n }\n if (input.memberId.startsWith('org:')) {\n return Response.json({ error: 'Organization owner/admin project access is managed at the organization level' }, { status: 403 })\n }\n if (!isAssignableWorkspaceRole(input.role)) {\n return Response.json({ error: 'Invalid role' }, { status: 400 })\n }\n\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id, 'admin')\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n if (!hasWorkspaceRole(accessRow.role, input.role)) {\n return Response.json({ error: 'Cannot assign a role higher than your own' }, { status: 403 })\n }\n\n const [target] = await db\n .select({ id: workspaceMembers.id, role: workspaceMembers.role, userId: workspaceMembers.userId })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.id, input.memberId), eq(workspaceMembers.workspaceId, input.workspaceId)))\n .limit(1)\n\n if (!target) return Response.json({ error: 'Member not found' }, { status: 404 })\n if (target.userId === input.actor.id) return Response.json({ error: 'Cannot change your own role' }, { status: 403 })\n if (!canManageWorkspaceMemberRole(accessRow.role, target.role as WorkspaceRole)) {\n return Response.json({ error: 'Cannot modify a member with equal or higher role' }, { status: 403 })\n }\n\n await db.update(workspaceMembers).set({ role: input.role }).where(eq(workspaceMembers.id, input.memberId))\n if (target.userId && memberSyncSeam?.role) {\n const userId = target.userId\n const nextRole = input.role as WorkspaceRole\n fireSync(() => memberSyncSeam.role!({ workspaceId: input.workspaceId, userId, role: nextRole }))\n }\n return Response.json({ success: true })\n }\n\n async function removeMember(input: {\n workspaceId: string\n actor: MembersApiActor\n memberId?: string\n }): Promise<Response> {\n if (!input.memberId) return Response.json({ error: 'Missing memberId' }, { status: 400 })\n if (input.memberId.startsWith('org:')) {\n return Response.json({ error: 'Organization owner/admin project access is managed at the organization level' }, { status: 403 })\n }\n\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id, 'admin')\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n\n const [target] = await db\n .select({ id: workspaceMembers.id, role: workspaceMembers.role, userId: workspaceMembers.userId })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.id, input.memberId), eq(workspaceMembers.workspaceId, input.workspaceId)))\n .limit(1)\n\n if (!target) return Response.json({ error: 'Member not found' }, { status: 404 })\n if (target.userId === input.actor.id) return Response.json({ error: 'Cannot remove yourself from this project' }, { status: 403 })\n if (!canManageWorkspaceMemberRole(accessRow.role, target.role as WorkspaceRole)) {\n return Response.json({ error: 'Cannot remove a member with equal or higher role' }, { status: 403 })\n }\n\n await db.delete(workspaceMembers).where(eq(workspaceMembers.id, input.memberId))\n if (target.userId && memberSyncSeam?.remove) {\n const userId = target.userId\n fireSync(() => memberSyncSeam.remove!({ workspaceId: input.workspaceId, userId }))\n }\n return Response.json({ success: true })\n }\n\n async function acceptInvite(input: { token?: string; actor: MembersApiActor }): Promise<Response> {\n if (!input.token || typeof input.token !== 'string') {\n return Response.json({ error: 'Missing invite token' }, { status: 400 })\n }\n\n const [invite] = await db\n .select()\n .from(workspaceMembers)\n .where(eq(workspaceMembers.inviteToken, input.token))\n .limit(1)\n\n if (!invite) return Response.json({ error: 'Invalid or expired invite' }, { status: 404 })\n if (invite.acceptedAt) return Response.json({ error: 'Invite already accepted' }, { status: 409 })\n\n if (invite.inviteEmail && invite.inviteEmail.toLowerCase() !== input.actor.email?.toLowerCase()) {\n return Response.json(\n { error: `This invite was sent to ${invite.inviteEmail}. Please sign in with that email.` },\n { status: 403 },\n )\n }\n\n const [workspace] = await db\n .select({ id: workspaces.id, organizationId: workspaces.organizationId })\n .from(workspaces)\n .where(eq(workspaces.id, invite.workspaceId))\n .limit(1)\n\n if (!workspace) return Response.json({ error: 'Project not found' }, { status: 404 })\n const organizationId = (workspace as { organizationId: string }).organizationId\n\n // Atomic accept: only succeeds if the token still exists and is unaccepted,\n // so two concurrent accepts can't both win.\n const updated = await db\n .update(workspaceMembers)\n .set({\n userId: input.actor.id,\n acceptedAt: new Date(),\n inviteToken: null,\n })\n .where(and(\n eq(workspaceMembers.inviteToken, input.token),\n isNull(workspaceMembers.acceptedAt),\n ))\n .returning({ id: workspaceMembers.id })\n\n if (updated.length === 0) return Response.json({ error: 'Invite already accepted' }, { status: 409 })\n\n const [orgMember] = await db\n .insert(organizationMembers)\n .values({\n organizationId,\n userId: input.actor.id,\n role: 'member',\n })\n .onConflictDoUpdate({\n target: [organizationMembers.organizationId, organizationMembers.userId],\n set: { updatedAt: new Date() },\n })\n .returning()\n\n await db\n .update(workspaceMembers)\n .set({ organizationMemberId: invite.organizationMemberId ?? orgMember!.id })\n .where(eq(workspaceMembers.id, updated[0]!.id))\n\n if (memberSyncSeam?.add) {\n const role = invite.role as WorkspaceRole\n fireSync(() => memberSyncSeam.add!({ workspaceId: invite.workspaceId, userId: input.actor.id, role }))\n }\n\n return Response.json({\n success: true,\n workspaceId: invite.workspaceId,\n role: invite.role,\n })\n }\n\n // ── internal query helpers ──\n\n async function getUserByEmail(email: string) {\n const [user] = await db\n .select({ id: users.id, email: users.email })\n .from(users)\n .where(eq(users.email, email))\n .limit(1)\n return user ?? null\n }\n\n async function getOrganizationMember(organizationId: string, userId: string) {\n const [member] = await db\n .select()\n .from(organizationMembers)\n .where(and(eq(organizationMembers.organizationId, organizationId), eq(organizationMembers.userId, userId)))\n .limit(1)\n return member ?? null\n }\n\n async function findExistingProjectInvite(workspaceId: string, email: string, userId?: string) {\n const byEmail = await db\n .select({ id: workspaceMembers.id })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.workspaceId, workspaceId), eq(workspaceMembers.inviteEmail, email)))\n .limit(1)\n if (byEmail[0]) return byEmail[0]\n if (!userId) return null\n const byUser = await db\n .select({ id: workspaceMembers.id })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.workspaceId, workspaceId), eq(workspaceMembers.userId, userId)))\n .limit(1)\n return byUser[0] ?? null\n }\n\n async function hasPendingOrgInvite(organizationId: string, email: string): Promise<boolean> {\n const [row] = await db\n .select({ id: workspaceMembers.id })\n .from(workspaceMembers)\n .innerJoin(workspaces, eq(workspaces.id, workspaceMembers.workspaceId))\n .where(and(\n eq(workspaces.organizationId, organizationId),\n eq(workspaceMembers.inviteEmail, email),\n isNull(workspaceMembers.acceptedAt),\n ))\n .limit(1)\n return Boolean(row)\n }\n\n return { listMembers, inviteMember, updateMemberRole, removeMember, acceptInvite }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAsBA,SAAS,KAAK,IAAI,cAAc;AAoDzB,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACT,YAAY,SAAiB,OAAwE,CAAC,GAAG;AACvG,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS,KAAK,UAAU;AAC7B,SAAK,aAAa,KAAK;AACvB,SAAK,eAAe,KAAK;AAAA,EAC3B;AACF;AA8CO,SAAS,iBAAiB,MAAyB;AACxD,QAAM,EAAE,IAAI,QAAQ,WAAW,gBAAgB,QAAQ,aAAa,eAAe,IAAI;AACvF,QAAM,EAAE,eAAe,qBAAqB,iBAAiB,IAAI;AACjE,QAAM,QAAQ;AACd,QAAM,aAAa;AAEnB,WAAS,SAAS,IAAgC;AAChD,QAAI;AACF,cAAQ,QAAQ,GAAG,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACtC,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,iBAAe,YAAY,OAA2E;AACpG,UAAM,YAAY,MAAM,OAAO,mBAAmB,MAAM,aAAa,MAAM,MAAM,EAAE;AACnF,QAAI,CAAC,UAAW,QAAO,SAAS,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAEtF,UAAM,iBAAkB,UAAU,UAAyC;AAE3E,UAAM,CAAC,gBAAgB,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,MACpD,GACG,OAAO;AAAA,QACN,IAAI,iBAAiB;AAAA,QACrB,sBAAsB,iBAAiB;AAAA,QACvC,QAAQ,iBAAiB;AAAA,QACzB,MAAM,iBAAiB;AAAA,QACvB,WAAW,iBAAiB;AAAA,QAC5B,YAAY,iBAAiB;AAAA,QAC7B,aAAa,iBAAiB;AAAA,QAC9B,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,MACnB,CAAC,EACA,KAAK,gBAAgB,EACrB,SAAS,OAAO,GAAG,MAAM,IAAI,iBAAiB,MAAM,CAAC,EACrD,MAAM,GAAG,iBAAiB,aAAa,MAAM,WAAW,CAAC;AAAA,MAC5D,GACG,OAAO;AAAA,QACN,IAAI,oBAAoB;AAAA,QACxB,QAAQ,oBAAoB;AAAA,QAC5B,SAAS,oBAAoB;AAAA,QAC7B,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,QACjB,WAAW,oBAAoB;AAAA,MACjC,CAAC,EACA,KAAK,mBAAmB,EACxB,UAAU,OAAO,GAAG,MAAM,IAAI,oBAAoB,MAAM,CAAC,EACzD,MAAM,GAAG,oBAAoB,gBAAgB,cAAc,CAAC;AAAA,IACjE,CAAC;AAED,UAAM,uBAAuB,IAAI;AAAA,MAC/B,eAAe,IAAI,CAAC,MAAW,EAAE,oBAAoB,EAAE,OAAO,OAAO;AAAA,IACvE;AACA,UAAM,UAA6B;AAAA,MACjC,GAAG,UACA,OAAO,CAAC,MAAW,qCAAqC,EAAE,OAAO,KAAK,CAAC,qBAAqB,IAAI,EAAE,EAAE,CAAC,EACrG,IAAI,CAAC,OAAY;AAAA,QAChB,IAAI,OAAO,EAAE,EAAE;AAAA,QACf,QAAQ,EAAE;AAAA,QACV,sBAAsB,EAAE;AAAA,QACxB,MAAM;AAAA,QACN,MAAM,EAAE;AAAA,QACR,OAAO,EAAE;AAAA,QACT,WAAW,EAAE;AAAA,QACb,YAAY,EAAE;AAAA,QACd,WAAW;AAAA,MACb,EAAE;AAAA,MACJ,GAAG,eAAe,IAAI,CAAC,OAAY;AAAA,QACjC,IAAI,EAAE;AAAA,QACN,QAAQ,EAAE;AAAA,QACV,sBAAsB,EAAE;AAAA,QACxB,MAAM,EAAE;AAAA,QACR,MAAM,EAAE;AAAA,QACR,OAAO,EAAE,aAAa,EAAE;AAAA,QACxB,WAAW,EAAE;AAAA,QACb,YAAY,EAAE;AAAA,QACd,WAAW;AAAA,MACb,EAAE;AAAA,IACJ;AAEA,WAAO,SAAS,KAAK,EAAE,SAAS,aAAa,UAAU,MAAM,eAAe,CAAC;AAAA,EAC/E;AAEA,iBAAe,aAAa,OAKN;AACpB,QAAI,CAAC,MAAM,MAAO,QAAO,SAAS,KAAK,EAAE,OAAO,gBAAgB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAClF,QAAI,CAAC,kBAAkB,MAAM,KAAK,EAAG,QAAO,SAAS,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAC3G,UAAM,gBAAgB,MAAM,QAAQ;AACpC,QAAI,CAAC,0BAA0B,aAAa,GAAG;AAC7C,aAAO,SAAS,KAAK,EAAE,OAAO,kDAAkD,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACpG;AACA,UAAM,aAAsC;AAC5C,UAAM,YAAY,MAAM,OAAO,mBAAmB,MAAM,aAAa,MAAM,MAAM,IAAI,OAAO;AAC5F,QAAI,CAAC,UAAW,QAAO,SAAS,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AACtF,QAAI,CAAC,iBAAiB,UAAU,MAAM,UAAU,GAAG;AACjD,aAAO,SAAS,KAAK,EAAE,OAAO,4CAA4C,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC9F;AAEA,UAAM,iBAAkB,UAAU,UAAyC;AAC3E,UAAM,kBAAkB,MAAM,MAAM,YAAY,EAAE,KAAK;AACvD,UAAM,UAAU,MAAM,eAAe,eAAe;AACpD,UAAM,oBAAoB,UAAU,MAAM,sBAAsB,gBAAgB,QAAQ,EAAE,IAAI;AAE9F,QAAI,qCAAqC,mBAAmB,IAAI,GAAG;AACjE,aAAO,SAAS,KAAK,EAAE,OAAO,kDAAkD,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACpG;AAEA,UAAM,iBAAiB,MAAM,0BAA0B,MAAM,aAAa,iBAAiB,SAAS,EAAE;AACtG,QAAI,gBAAgB;AAClB,aAAO,SAAS,KAAK,EAAE,OAAO,uDAAuD,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACzG;AAEA,QAAI,eAAe,CAAC,qBAAqB,CAAE,MAAM,oBAAoB,gBAAgB,eAAe,GAAI;AACtG,UAAI;AACF,cAAM,YAAY,EAAE,SAAS,MAAM,MAAM,IAAI,eAAe,CAAC;AAAA,MAC/D,SAAS,KAAK;AACZ,YAAI,eAAe,gBAAgB;AACjC,iBAAO,SAAS;AAAA,YACd,EAAE,OAAO,IAAI,SAAS,YAAY,IAAI,YAAY,cAAc,IAAI,aAAa;AAAA,YACjF,EAAE,QAAQ,IAAI,OAAO;AAAA,UACvB;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,QAAQ,oBAAoB;AAClC,UAAM,CAAC,MAAM,IAAI,MAAM,GACpB,OAAO,gBAAgB,EACvB,OAAO;AAAA,MACN,aAAa,MAAM;AAAA,MACnB,sBAAsB,mBAAmB,MAAM;AAAA,MAC/C,QAAQ,SAAS,MAAM;AAAA,MACvB,MAAM;AAAA,MACN,WAAW,MAAM,MAAM;AAAA,MACvB,aAAa;AAAA,MACb,aAAa;AAAA,IACf,CAAC,EACA,UAAU;AAEb,WAAO,SAAS,KAAK,EAAE,QAAQ,aAAa,MAAM,CAAC;AAAA,EACrD;AAEA,iBAAe,iBAAiB,OAKV;AACpB,QAAI,CAAC,MAAM,YAAY,CAAC,MAAM,MAAM;AAClC,aAAO,SAAS,KAAK,EAAE,OAAO,2BAA2B,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7E;AACA,QAAI,MAAM,SAAS,WAAW,MAAM,GAAG;AACrC,aAAO,SAAS,KAAK,EAAE,OAAO,+EAA+E,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACjI;AACA,QAAI,CAAC,0BAA0B,MAAM,IAAI,GAAG;AAC1C,aAAO,SAAS,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACjE;AAEA,UAAM,YAAY,MAAM,OAAO,mBAAmB,MAAM,aAAa,MAAM,MAAM,IAAI,OAAO;AAC5F,QAAI,CAAC,UAAW,QAAO,SAAS,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AACtF,QAAI,CAAC,iBAAiB,UAAU,MAAM,MAAM,IAAI,GAAG;AACjD,aAAO,SAAS,KAAK,EAAE,OAAO,4CAA4C,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC9F;AAEA,UAAM,CAAC,MAAM,IAAI,MAAM,GACpB,OAAO,EAAE,IAAI,iBAAiB,IAAI,MAAM,iBAAiB,MAAM,QAAQ,iBAAiB,OAAO,CAAC,EAChG,KAAK,gBAAgB,EACrB,MAAM,IAAI,GAAG,iBAAiB,IAAI,MAAM,QAAQ,GAAG,GAAG,iBAAiB,aAAa,MAAM,WAAW,CAAC,CAAC,EACvG,MAAM,CAAC;AAEV,QAAI,CAAC,OAAQ,QAAO,SAAS,KAAK,EAAE,OAAO,mBAAmB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAChF,QAAI,OAAO,WAAW,MAAM,MAAM,GAAI,QAAO,SAAS,KAAK,EAAE,OAAO,8BAA8B,GAAG,EAAE,QAAQ,IAAI,CAAC;AACpH,QAAI,CAAC,6BAA6B,UAAU,MAAM,OAAO,IAAqB,GAAG;AAC/E,aAAO,SAAS,KAAK,EAAE,OAAO,mDAAmD,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACrG;AAEA,UAAM,GAAG,OAAO,gBAAgB,EAAE,IAAI,EAAE,MAAM,MAAM,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,IAAI,MAAM,QAAQ,CAAC;AACzG,QAAI,OAAO,UAAU,gBAAgB,MAAM;AACzC,YAAM,SAAS,OAAO;AACtB,YAAM,WAAW,MAAM;AACvB,eAAS,MAAM,eAAe,KAAM,EAAE,aAAa,MAAM,aAAa,QAAQ,MAAM,SAAS,CAAC,CAAC;AAAA,IACjG;AACA,WAAO,SAAS,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACxC;AAEA,iBAAe,aAAa,OAIN;AACpB,QAAI,CAAC,MAAM,SAAU,QAAO,SAAS,KAAK,EAAE,OAAO,mBAAmB,GAAG,EAAE,QAAQ,IAAI,CAAC;AACxF,QAAI,MAAM,SAAS,WAAW,MAAM,GAAG;AACrC,aAAO,SAAS,KAAK,EAAE,OAAO,+EAA+E,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACjI;AAEA,UAAM,YAAY,MAAM,OAAO,mBAAmB,MAAM,aAAa,MAAM,MAAM,IAAI,OAAO;AAC5F,QAAI,CAAC,UAAW,QAAO,SAAS,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAEtF,UAAM,CAAC,MAAM,IAAI,MAAM,GACpB,OAAO,EAAE,IAAI,iBAAiB,IAAI,MAAM,iBAAiB,MAAM,QAAQ,iBAAiB,OAAO,CAAC,EAChG,KAAK,gBAAgB,EACrB,MAAM,IAAI,GAAG,iBAAiB,IAAI,MAAM,QAAQ,GAAG,GAAG,iBAAiB,aAAa,MAAM,WAAW,CAAC,CAAC,EACvG,MAAM,CAAC;AAEV,QAAI,CAAC,OAAQ,QAAO,SAAS,KAAK,EAAE,OAAO,mBAAmB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAChF,QAAI,OAAO,WAAW,MAAM,MAAM,GAAI,QAAO,SAAS,KAAK,EAAE,OAAO,2CAA2C,GAAG,EAAE,QAAQ,IAAI,CAAC;AACjI,QAAI,CAAC,6BAA6B,UAAU,MAAM,OAAO,IAAqB,GAAG;AAC/E,aAAO,SAAS,KAAK,EAAE,OAAO,mDAAmD,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACrG;AAEA,UAAM,GAAG,OAAO,gBAAgB,EAAE,MAAM,GAAG,iBAAiB,IAAI,MAAM,QAAQ,CAAC;AAC/E,QAAI,OAAO,UAAU,gBAAgB,QAAQ;AAC3C,YAAM,SAAS,OAAO;AACtB,eAAS,MAAM,eAAe,OAAQ,EAAE,aAAa,MAAM,aAAa,OAAO,CAAC,CAAC;AAAA,IACnF;AACA,WAAO,SAAS,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACxC;AAEA,iBAAe,aAAa,OAAsE;AAChG,QAAI,CAAC,MAAM,SAAS,OAAO,MAAM,UAAU,UAAU;AACnD,aAAO,SAAS,KAAK,EAAE,OAAO,uBAAuB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACzE;AAEA,UAAM,CAAC,MAAM,IAAI,MAAM,GACpB,OAAO,EACP,KAAK,gBAAgB,EACrB,MAAM,GAAG,iBAAiB,aAAa,MAAM,KAAK,CAAC,EACnD,MAAM,CAAC;AAEV,QAAI,CAAC,OAAQ,QAAO,SAAS,KAAK,EAAE,OAAO,4BAA4B,GAAG,EAAE,QAAQ,IAAI,CAAC;AACzF,QAAI,OAAO,WAAY,QAAO,SAAS,KAAK,EAAE,OAAO,0BAA0B,GAAG,EAAE,QAAQ,IAAI,CAAC;AAEjG,QAAI,OAAO,eAAe,OAAO,YAAY,YAAY,MAAM,MAAM,MAAM,OAAO,YAAY,GAAG;AAC/F,aAAO,SAAS;AAAA,QACd,EAAE,OAAO,2BAA2B,OAAO,WAAW,oCAAoC;AAAA,QAC1F,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAEA,UAAM,CAAC,SAAS,IAAI,MAAM,GACvB,OAAO,EAAE,IAAI,WAAW,IAAI,gBAAgB,WAAW,eAAe,CAAC,EACvE,KAAK,UAAU,EACf,MAAM,GAAG,WAAW,IAAI,OAAO,WAAW,CAAC,EAC3C,MAAM,CAAC;AAEV,QAAI,CAAC,UAAW,QAAO,SAAS,KAAK,EAAE,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC;AACpF,UAAM,iBAAkB,UAAyC;AAIjE,UAAM,UAAU,MAAM,GACnB,OAAO,gBAAgB,EACvB,IAAI;AAAA,MACH,QAAQ,MAAM,MAAM;AAAA,MACpB,YAAY,oBAAI,KAAK;AAAA,MACrB,aAAa;AAAA,IACf,CAAC,EACA,MAAM;AAAA,MACL,GAAG,iBAAiB,aAAa,MAAM,KAAK;AAAA,MAC5C,OAAO,iBAAiB,UAAU;AAAA,IACpC,CAAC,EACA,UAAU,EAAE,IAAI,iBAAiB,GAAG,CAAC;AAExC,QAAI,QAAQ,WAAW,EAAG,QAAO,SAAS,KAAK,EAAE,OAAO,0BAA0B,GAAG,EAAE,QAAQ,IAAI,CAAC;AAEpG,UAAM,CAAC,SAAS,IAAI,MAAM,GACvB,OAAO,mBAAmB,EAC1B,OAAO;AAAA,MACN;AAAA,MACA,QAAQ,MAAM,MAAM;AAAA,MACpB,MAAM;AAAA,IACR,CAAC,EACA,mBAAmB;AAAA,MAClB,QAAQ,CAAC,oBAAoB,gBAAgB,oBAAoB,MAAM;AAAA,MACvE,KAAK,EAAE,WAAW,oBAAI,KAAK,EAAE;AAAA,IAC/B,CAAC,EACA,UAAU;AAEb,UAAM,GACH,OAAO,gBAAgB,EACvB,IAAI,EAAE,sBAAsB,OAAO,wBAAwB,UAAW,GAAG,CAAC,EAC1E,MAAM,GAAG,iBAAiB,IAAI,QAAQ,CAAC,EAAG,EAAE,CAAC;AAEhD,QAAI,gBAAgB,KAAK;AACvB,YAAM,OAAO,OAAO;AACpB,eAAS,MAAM,eAAe,IAAK,EAAE,aAAa,OAAO,aAAa,QAAQ,MAAM,MAAM,IAAI,KAAK,CAAC,CAAC;AAAA,IACvG;AAEA,WAAO,SAAS,KAAK;AAAA,MACnB,SAAS;AAAA,MACT,aAAa,OAAO;AAAA,MACpB,MAAM,OAAO;AAAA,IACf,CAAC;AAAA,EACH;AAIA,iBAAe,eAAe,OAAe;AAC3C,UAAM,CAAC,IAAI,IAAI,MAAM,GAClB,OAAO,EAAE,IAAI,MAAM,IAAI,OAAO,MAAM,MAAM,CAAC,EAC3C,KAAK,KAAK,EACV,MAAM,GAAG,MAAM,OAAO,KAAK,CAAC,EAC5B,MAAM,CAAC;AACV,WAAO,QAAQ;AAAA,EACjB;AAEA,iBAAe,sBAAsB,gBAAwB,QAAgB;AAC3E,UAAM,CAAC,MAAM,IAAI,MAAM,GACpB,OAAO,EACP,KAAK,mBAAmB,EACxB,MAAM,IAAI,GAAG,oBAAoB,gBAAgB,cAAc,GAAG,GAAG,oBAAoB,QAAQ,MAAM,CAAC,CAAC,EACzG,MAAM,CAAC;AACV,WAAO,UAAU;AAAA,EACnB;AAEA,iBAAe,0BAA0B,aAAqB,OAAe,QAAiB;AAC5F,UAAM,UAAU,MAAM,GACnB,OAAO,EAAE,IAAI,iBAAiB,GAAG,CAAC,EAClC,KAAK,gBAAgB,EACrB,MAAM,IAAI,GAAG,iBAAiB,aAAa,WAAW,GAAG,GAAG,iBAAiB,aAAa,KAAK,CAAC,CAAC,EACjG,MAAM,CAAC;AACV,QAAI,QAAQ,CAAC,EAAG,QAAO,QAAQ,CAAC;AAChC,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,SAAS,MAAM,GAClB,OAAO,EAAE,IAAI,iBAAiB,GAAG,CAAC,EAClC,KAAK,gBAAgB,EACrB,MAAM,IAAI,GAAG,iBAAiB,aAAa,WAAW,GAAG,GAAG,iBAAiB,QAAQ,MAAM,CAAC,CAAC,EAC7F,MAAM,CAAC;AACV,WAAO,OAAO,CAAC,KAAK;AAAA,EACtB;AAEA,iBAAe,oBAAoB,gBAAwB,OAAiC;AAC1F,UAAM,CAAC,GAAG,IAAI,MAAM,GACjB,OAAO,EAAE,IAAI,iBAAiB,GAAG,CAAC,EAClC,KAAK,gBAAgB,EACrB,UAAU,YAAY,GAAG,WAAW,IAAI,iBAAiB,WAAW,CAAC,EACrE,MAAM;AAAA,MACL,GAAG,WAAW,gBAAgB,cAAc;AAAA,MAC5C,GAAG,iBAAiB,aAAa,KAAK;AAAA,MACtC,OAAO,iBAAiB,UAAU;AAAA,IACpC,CAAC,EACA,MAAM,CAAC;AACV,WAAO,QAAQ,GAAG;AAAA,EACpB;AAEA,SAAO,EAAE,aAAa,cAAc,kBAAkB,cAAc,aAAa;AACnF;","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|