@assistant-ui/metro 0.0.4 → 0.0.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;AASA;;;;KAAY,eAAA;EACV,WAAA;IAEM,oBAAA;IAAA,CACC,GAAA;EAAA;EAAA,CAGN,GAAA;AAAA;;;;AAQkC;AAwBrC;cAxBa,wBAAA;;;;;;;;;;;;;AAwBmD;;;;;;;;;;iBAAhD,OAAA,WAAkB,eAAA,EAAiB,MAAA,EAAQ,CAAA,GAAI,CAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;KASY;EACV;IAEM;KACC;;GAGN;;;;;;;cAQU;;;;;;;;;;;;;;;;;;;;;;;iBAwBG,QAAQ,UAAU,iBAAiB,QAAQ,IAAI"}
@@ -40,7 +40,7 @@ _babel_types = __toESM(_babel_types, 1);
40
40
  const DIRECTIVE = "use generative";
41
41
  //#endregion
42
42
  //#region ../x-generative-compiler/dist/package.js
43
- var version = "0.0.6";
43
+ var version = "0.0.10";
44
44
  //#endregion
45
45
  //#region ../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/internal/constants.js
46
46
  var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
@@ -623,7 +623,11 @@ var require_coerce = /* @__PURE__ */ __commonJSMin(((exports, module) => {
623
623
  }
624
624
  if (match === null) return null;
625
625
  const major = match[2];
626
- return parse(`${major}.${match[3] || "0"}.${match[4] || "0"}${options.includePrerelease && match[5] ? `-${match[5]}` : ""}${options.includePrerelease && match[6] ? `+${match[6]}` : ""}`, options);
626
+ const minor = match[3] || "0";
627
+ const patch = match[4] || "0";
628
+ const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : "";
629
+ const build = options.includePrerelease && match[6] ? `+${match[6]}` : "";
630
+ return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options);
627
631
  };
628
632
  module.exports = coerce;
629
633
  }));
@@ -639,7 +643,8 @@ var require_truncate = /* @__PURE__ */ __commonJSMin(((exports, module) => {
639
643
  return clonedVersion && doTruncation(clonedVersion, truncation);
640
644
  };
641
645
  const cloneInputVersion = (version, options) => {
642
- return parse(version instanceof SemVer ? version.version : version, options);
646
+ const versionStringToParse = version instanceof SemVer ? version.version : version;
647
+ return parse(versionStringToParse, options);
643
648
  };
644
649
  const doTruncation = (version, truncation) => {
645
650
  if (isPrerelease(truncation)) return version.version;
@@ -1425,6 +1430,11 @@ var import_semver = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
1425
1430
  rcompareIdentifiers: identifiers.rcompareIdentifiers
1426
1431
  };
1427
1432
  })))();
1433
+ const parserPlugins = [
1434
+ "typescript",
1435
+ "jsx",
1436
+ "explicitResourceManagement"
1437
+ ];
1428
1438
  const traverse = typeof _babel_traverse.default === "function" ? _babel_traverse.default : _babel_traverse.default.default;
1429
1439
  const generate = typeof _babel_generator.default === "function" ? _babel_generator.default : _babel_generator.default.default;
1430
1440
  /** The required wrapper around a toolkit's tools (stripped at build time). */
@@ -1444,6 +1454,8 @@ const DISTRIBUTION_PACKAGES = [
1444
1454
  "@assistant-ui/react-native",
1445
1455
  "@assistant-ui/react-ink"
1446
1456
  ];
1457
+ /** Package that exports the generative UI runtime split by export condition. */
1458
+ const GENERATIVE_UI_PACKAGE = "@assistant-ui/react-generative-ui";
1447
1459
  /**
1448
1460
  * The class whose instances expose split-by-condition tools (`present()`,
1449
1461
  * `promptUser()`). A toolkit entry that calls a method on one of these passes
@@ -1571,18 +1583,14 @@ function compileGenerative(code, options) {
1571
1583
  const { target, filename } = options;
1572
1584
  const ast = (0, _babel_parser.parse)(code, {
1573
1585
  sourceType: "module",
1574
- plugins: [
1575
- "typescript",
1576
- "jsx",
1577
- "explicitResourceManagement"
1578
- ]
1586
+ plugins: parserPlugins
1579
1587
  });
1580
1588
  if (!ast.program.directives.some((d) => d.value.value === "use generative")) throw new GenerativeCompileError(`missing "${DIRECTIVE}" directive`, filename);
1581
1589
  ensureCompilerCompatibleWithCore(ast, filename);
1582
1590
  ensureDefaultExport(ast, filename);
1583
1591
  const generativeInstances = collectGenerativeInstances(ast);
1584
1592
  const interactableToolImports = collectInteractableToolImports(ast);
1585
- const toolkitSpreadNames = collectToolkitSpreadNames(ast, filename, createToolkitNameContext());
1593
+ const { spreadNames: toolkitSpreadNames, namespaceImports } = collectToolkitSpreadNames(ast, filename, createToolkitNameContext());
1586
1594
  const flags = {
1587
1595
  keptRender: false,
1588
1596
  keptBackendExecute: false
@@ -1599,7 +1607,7 @@ function compileGenerative(code, options) {
1599
1607
  }
1600
1608
  if (_babel_types.isIdentifier(callee, { name: TOOLKIT_WRAPPER })) {
1601
1609
  if (!object) throw new GenerativeCompileError(`${TOOLKIT_WRAPPER}() takes an inline object literal of tools`, filename);
1602
- compileToolkit(object, target, generativeInstances, interactableToolImports, toolkitSpreadNames, flags, filename);
1610
+ compileToolkit(object, target, generativeInstances, interactableToolImports, toolkitSpreadNames, namespaceImports, flags, filename);
1603
1611
  path.replaceWith(object);
1604
1612
  path.skip();
1605
1613
  }
@@ -1611,7 +1619,7 @@ function compileGenerative(code, options) {
1611
1619
  if (target === "server" && keptBackendExecute && (options.injectServerOnly ?? true)) ast.program.body.unshift(_babel_types.importDeclaration([], _babel_types.stringLiteral("server-only")));
1612
1620
  const result = generate(ast, {
1613
1621
  sourceMaps: options.sourceMaps ?? false,
1614
- filename,
1622
+ ...filename ? { filename } : {},
1615
1623
  jsescOption: { minimal: true }
1616
1624
  }, code);
1617
1625
  return {
@@ -1733,6 +1741,15 @@ function unwrapToCall(node, name) {
1733
1741
  return null;
1734
1742
  }
1735
1743
  /**
1744
+ * Unwraps a statement to its variable declaration through an `export` wrapper,
1745
+ * or returns `null`.
1746
+ */
1747
+ function asVariableDeclaration(statement) {
1748
+ if (_babel_types.isVariableDeclaration(statement)) return statement;
1749
+ if (_babel_types.isExportNamedDeclaration(statement) && _babel_types.isVariableDeclaration(statement.declaration)) return statement.declaration;
1750
+ return null;
1751
+ }
1752
+ /**
1736
1753
  * Collects the names bound to `new JSONGenerativeUI(...)` (e.g.
1737
1754
  * `const generative = new JSONGenerativeUI({ library })`). A toolkit entry that
1738
1755
  * calls a method on one of these is a generative tool whose halves the library
@@ -1740,15 +1757,25 @@ function unwrapToCall(node, name) {
1740
1757
  */
1741
1758
  function collectGenerativeInstances(ast) {
1742
1759
  const names = /* @__PURE__ */ new Set();
1760
+ const generativeFactories = collectGenerativeFactoryImports(ast);
1743
1761
  for (const statement of ast.program.body) {
1744
- if (!_babel_types.isVariableDeclaration(statement)) continue;
1745
- for (const declaration of statement.declarations) {
1762
+ const variableDeclaration = asVariableDeclaration(statement);
1763
+ if (!variableDeclaration) continue;
1764
+ for (const declaration of variableDeclaration.declarations) {
1746
1765
  const { id, init } = declaration;
1747
- if (_babel_types.isIdentifier(id) && _babel_types.isNewExpression(init) && _babel_types.isIdentifier(init.callee, { name: GENERATIVE_FACTORY })) names.add(id.name);
1766
+ if (_babel_types.isIdentifier(id) && _babel_types.isNewExpression(init) && _babel_types.isIdentifier(init.callee) && generativeFactories.has(init.callee.name)) names.add(id.name);
1748
1767
  }
1749
1768
  }
1750
1769
  return names;
1751
1770
  }
1771
+ function collectGenerativeFactoryImports(ast) {
1772
+ const names = /* @__PURE__ */ new Set();
1773
+ for (const statement of ast.program.body) {
1774
+ if (!_babel_types.isImportDeclaration(statement) || statement.source.value !== GENERATIVE_UI_PACKAGE) continue;
1775
+ for (const specifier of statement.specifiers) if (_babel_types.isImportSpecifier(specifier) && _babel_types.isIdentifier(specifier.imported, { name: GENERATIVE_FACTORY })) names.add(specifier.local.name);
1776
+ }
1777
+ return names;
1778
+ }
1752
1779
  /**
1753
1780
  * Collects the local names `unstable_interactableTool` is imported under from a
1754
1781
  * distribution package, so toolkit entries calling it can be recognized
@@ -1791,13 +1818,20 @@ function interactableToolConfig(value, imports) {
1791
1818
  * toolkit can't leak a backend `execute` to the client. Only the default
1792
1819
  * export crosses the generative-module boundary, so named imports don't
1793
1820
  * qualify — they would be `undefined` once that module is build-split.
1821
+ *
1822
+ * A namespace import (`import * as kit from "..."`) of a generative module is
1823
+ * tracked separately in `namespaceImports` so a `...kit` / `...kit.default`
1824
+ * spread can be rejected with a specific callout: only the default export
1825
+ * crosses the boundary, so a namespace spread is never safe.
1794
1826
  */
1795
1827
  function collectToolkitSpreadNames(ast, filename, context) {
1796
1828
  const spreadNames = /* @__PURE__ */ new Map();
1829
+ const namespaceImports = /* @__PURE__ */ new Set();
1797
1830
  const localToolkitCalls = /* @__PURE__ */ new Map();
1798
1831
  for (const statement of ast.program.body) {
1799
- if (_babel_types.isVariableDeclaration(statement)) {
1800
- for (const declaration of statement.declarations) {
1832
+ const localDeclaration = asVariableDeclaration(statement);
1833
+ if (localDeclaration) {
1834
+ for (const declaration of localDeclaration.declarations) {
1801
1835
  const { id, init } = declaration;
1802
1836
  if (_babel_types.isIdentifier(id) && init) {
1803
1837
  const toolkitCall = unwrapToToolkitCall(init);
@@ -1808,9 +1842,12 @@ function collectToolkitSpreadNames(ast, filename, context) {
1808
1842
  }
1809
1843
  if (_babel_types.isImportDeclaration(statement)) {
1810
1844
  const defaultSpecifier = statement.specifiers.find((specifier) => _babel_types.isImportDefaultSpecifier(specifier));
1811
- if (!defaultSpecifier) continue;
1845
+ const namespaceSpecifier = statement.specifiers.find((specifier) => _babel_types.isImportNamespaceSpecifier(specifier));
1846
+ if (!defaultSpecifier && !namespaceSpecifier) continue;
1812
1847
  const names = getGenerativeImportToolkitNames(statement.source.value, filename, context);
1813
- if (names !== void 0) spreadNames.set(defaultSpecifier.local.name, names);
1848
+ if (names === void 0) continue;
1849
+ if (defaultSpecifier) spreadNames.set(defaultSpecifier.local.name, names);
1850
+ if (namespaceSpecifier) namespaceImports.add(namespaceSpecifier.local.name);
1814
1851
  }
1815
1852
  }
1816
1853
  const resolveLocal = (name) => {
@@ -1823,7 +1860,10 @@ function collectToolkitSpreadNames(ast, filename, context) {
1823
1860
  return publicNames;
1824
1861
  };
1825
1862
  for (const name of localToolkitCalls.keys()) resolveLocal(name);
1826
- return spreadNames;
1863
+ return {
1864
+ spreadNames,
1865
+ namespaceImports
1866
+ };
1827
1867
  }
1828
1868
  const MODULE_EXTENSIONS = [
1829
1869
  ".ts",
@@ -1870,11 +1910,7 @@ function getGenerativeImportToolkitNames(source, filename, context) {
1870
1910
  try {
1871
1911
  const names = getDefaultExportToolkitNames((0, _babel_parser.parse)(code, {
1872
1912
  sourceType: "module",
1873
- plugins: [
1874
- "typescript",
1875
- "jsx",
1876
- "explicitResourceManagement"
1877
- ]
1913
+ plugins: parserPlugins
1878
1914
  }), resolved, context);
1879
1915
  context.importedToolkitNamesByFile.set(resolved, names);
1880
1916
  return names;
@@ -1891,7 +1927,7 @@ function getDefaultExportToolkitNames(ast, filename, context) {
1891
1927
  if (!def) return null;
1892
1928
  const toolkitCall = unwrapToToolkitCall(def.declaration);
1893
1929
  if (!toolkitCall || !_babel_types.isObjectExpression(toolkitCall.arguments[0])) return null;
1894
- const spreadNames = collectToolkitSpreadNames(ast, filename, context);
1930
+ const { spreadNames } = collectToolkitSpreadNames(ast, filename, context);
1895
1931
  return uniqueToolkitNames(collectToolkitObjectNames(toolkitCall.arguments[0], spreadNames));
1896
1932
  }
1897
1933
  /** Resolves an import specifier (relative or `tsconfig`-aliased) to a file on disk. */
@@ -2080,6 +2116,25 @@ function isSafeToolkitSpread(entry, toolkitSpreadNames) {
2080
2116
  const directMcpToolkit = unwrapToCall(entry.argument, MCP_TOOLKIT_WRAPPER);
2081
2117
  return !!directMcpToolkit && _babel_types.isObjectExpression(directMcpToolkit.arguments[0]);
2082
2118
  }
2119
+ function genericUnsafeToolkitEntryMessage() {
2120
+ return "each tool must be an inline object literal (`name: { ... }`) or a compiler-visible toolkit spread / generative tool (e.g. `...defineMcpToolkit(...)`, `...baseToolkit`, `generative.present()`, or `unstable_interactableTool(...)`) so its `execute` can be routed";
2121
+ }
2122
+ function describeUnsafeToolkitEntry(entry) {
2123
+ if (!_babel_types.isObjectProperty(entry)) return genericUnsafeToolkitEntryMessage();
2124
+ const toolName = memberName(entry.key, entry.computed);
2125
+ const raw = entryRawValue(entry);
2126
+ if (!toolName || !raw) return genericUnsafeToolkitEntryMessage();
2127
+ return `tool "${toolName}" cannot be \`${generate(raw).code}\`; use an inline object literal (\`${toolName}: { ... }\`) or a compiler-visible toolkit spread / generative tool so its \`execute\` can be routed`;
2128
+ }
2129
+ function namespaceToolkitSpreadMessage() {
2130
+ return `a namespace import (\`import * as kit from "..."\`) can't be spread into ${TOOLKIT_WRAPPER}({ ... }); only a generative module's default export crosses the build-split boundary, so import it as a default (\`import kit from "..."\`) and spread \`...kit\` instead`;
2131
+ }
2132
+ /** The `kit` in `...kit` or `...kit.default`, or null for a computed/opaque base. */
2133
+ function namespaceSpreadBaseName(argument) {
2134
+ if (_babel_types.isIdentifier(argument)) return argument.name;
2135
+ if (_babel_types.isMemberExpression(argument) && !argument.computed && _babel_types.isIdentifier(argument.object)) return argument.object.name;
2136
+ return null;
2137
+ }
2083
2138
  /** The `JSONGenerativeUI` methods that produce a split-by-condition tool. */
2084
2139
  const GENERATIVE_TOOL_METHODS = /* @__PURE__ */ new Set(["present", "promptUser"]);
2085
2140
  /**
@@ -2112,7 +2167,7 @@ function compileComponents(object, target, flags, filename) {
2112
2167
  * `generative.present()` passes through, the library having already split it.
2113
2168
  * Mutates the object in place and records outcomes in {@link TargetFlags}.
2114
2169
  */
2115
- function compileToolkit(object, target, instances, interactableToolImports, toolkitSpreadNames, flags, filename) {
2170
+ function compileToolkit(object, target, instances, interactableToolImports, toolkitSpreadNames, namespaceImports, flags, filename) {
2116
2171
  if (target === "client") warnDuplicateToolkitNames(object, toolkitSpreadNames, filename);
2117
2172
  const nextProperties = [];
2118
2173
  for (const entry of object.properties) {
@@ -2134,19 +2189,24 @@ function compileToolkit(object, target, instances, interactableToolImports, tool
2134
2189
  nextProperties.push(entry);
2135
2190
  continue;
2136
2191
  }
2137
- throw new GenerativeCompileError("each tool must be an inline object literal (`name: { ... }`) or a compiler-visible toolkit spread / generative tool (e.g. `...defineMcpToolkit(...)`, `...baseToolkit`, `generative.present()`, or `unstable_interactableTool(...)`) so its `execute` can be routed", filename);
2192
+ if (_babel_types.isSpreadElement(entry)) {
2193
+ const namespaceBase = namespaceSpreadBaseName(entry.argument);
2194
+ if (namespaceBase && namespaceImports.has(namespaceBase)) throw new GenerativeCompileError(namespaceToolkitSpreadMessage(), filename);
2195
+ }
2196
+ throw new GenerativeCompileError(describeUnsafeToolkitEntry(entry), filename);
2138
2197
  }
2198
+ const toolName = _babel_types.isObjectProperty(entry) ? memberName(entry.key, entry.computed) : void 0;
2139
2199
  const execute = findMember(value, "execute");
2140
2200
  const isStub = execute ? executeIsStubTool(execute) : false;
2141
2201
  const isExternal = execute ? executeIsExternalTool(execute) : false;
2142
- const type = inferToolType(value, filename);
2202
+ const type = inferToolType(value, toolName, filename);
2143
2203
  const hasRender = !!findMember(value, "render");
2144
2204
  const hasRenderText = !!findMember(value, "renderText");
2145
- if (type === "frontend" && !hasRender && !hasRenderText) throw new GenerativeCompileError("a frontend tool must declare a `render` or `renderText` (it has no server execute to show otherwise)", filename);
2146
- if (type === "human" && !hasRender) throw new GenerativeCompileError("a human tool must declare a `render` so it can collect input", filename);
2147
- if (type === "provider" && execute) applyProviderToolConfig(value, execute, _babel_types.isObjectProperty(entry) ? memberName(entry.key, entry.computed) : void 0, filename);
2205
+ if (type === "frontend" && !hasRender && !hasRenderText) throw new GenerativeCompileError(`${typedToolSubject("frontend", toolName)} must declare a \`render\` or \`renderText\` (it has no server execute to show otherwise)`, filename);
2206
+ if (type === "human" && !hasRender) throw new GenerativeCompileError(`${typedToolSubject("human", toolName)} must declare a \`render\` so it can collect input`, filename);
2207
+ if (type === "provider" && execute) applyProviderToolConfig(value, execute, toolName, filename);
2148
2208
  if (isExternal) {
2149
- if (!hasRender && !hasRenderText) throw new GenerativeCompileError("an external tool must declare a `render` or `renderText` (assistant-ui only renders calls for tools defined elsewhere)", filename);
2209
+ if (!hasRender && !hasRenderText) throw new GenerativeCompileError(`${typedToolSubject("external", toolName)} must declare a \`render\` or \`renderText\` (assistant-ui only renders calls for tools defined elsewhere)`, filename);
2150
2210
  if (target === "server") continue;
2151
2211
  stripExternalToolMetadata(value);
2152
2212
  }
@@ -2242,15 +2302,22 @@ function stripUseClient(member) {
2242
2302
  * The loader writes the result back as a `type` field (see {@link setToolType})
2243
2303
  * so the runtime keeps it.
2244
2304
  */
2245
- function inferToolType(object, filename) {
2305
+ function inferToolType(object, toolName, filename) {
2246
2306
  const execute = findMember(object, "execute");
2247
- if (!execute) throw new GenerativeCompileError("every tool must declare an `execute`; use `humanTool()` for a human-in-the-loop tool", filename);
2307
+ if (!execute) throw new GenerativeCompileError(`${toolSubject(toolName)} must declare an \`execute\`; use \`humanTool()\` for a human-in-the-loop tool`, filename);
2248
2308
  if (executeIsHumanTool(execute)) return "human";
2249
2309
  if (executeIsProviderTool(execute)) return "provider";
2250
2310
  if (executeIsStubTool(execute)) return "frontend";
2251
2311
  if (executeIsExternalTool(execute)) return "backend";
2252
2312
  return executeIsClient(execute) ? "frontend" : "backend";
2253
2313
  }
2314
+ function toolSubject(toolName) {
2315
+ return toolName ? `tool "${toolName}"` : "every tool";
2316
+ }
2317
+ function typedToolSubject(type, toolName) {
2318
+ if (toolName) return `${type} tool "${toolName}"`;
2319
+ return `${/^[aeiou]/i.test(type) ? "an" : "a"} ${type} tool`;
2320
+ }
2254
2321
  function stripExternalToolMetadata(object) {
2255
2322
  removeMember(object, "description");
2256
2323
  removeMember(object, "parameters");