@particle-academy/agent-integrations 0.21.1 → 0.22.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.
package/dist/index.cjs CHANGED
@@ -1105,7 +1105,7 @@ function registerSceneBridge(host, options) {
1105
1105
  )
1106
1106
  );
1107
1107
  };
1108
- const newId = (kind) => `${kind}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
1108
+ const newId2 = (kind) => `${kind}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
1109
1109
  reg(
1110
1110
  "scene_describe",
1111
1111
  "Describe the scene \u2014 object count, kinds, camera position.",
@@ -1149,7 +1149,7 @@ function registerSceneBridge(host, options) {
1149
1149
  ["kind"],
1150
1150
  (args) => {
1151
1151
  const obj = {
1152
- id: newId(String(args.kind)),
1152
+ id: newId2(String(args.kind)),
1153
1153
  kind: String(args.kind),
1154
1154
  position: parseTriple(args.position),
1155
1155
  rotation: parseTriple(args.rotation),
@@ -1955,11 +1955,338 @@ function serialize(entry) {
1955
1955
  };
1956
1956
  }
1957
1957
 
1958
+ // src/bridges/map.ts
1959
+ var DEFAULT_AGENT8 = { id: "agent", name: "Agent", color: "#7c3aed" };
1960
+ var num2 = (v, fallback) => typeof v === "number" && Number.isFinite(v) ? v : 0;
1961
+ var str2 = (v, fallback = "") => typeof v === "string" ? v : fallback;
1962
+ var newId = (prefix) => `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;
1963
+ function registerMapBridge(host, options) {
1964
+ const { adapter } = options;
1965
+ const agent = { ...DEFAULT_AGENT8, ...options.agent ?? {} };
1966
+ const disposers = [];
1967
+ ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
1968
+ const mTarget = (args, result) => ({
1969
+ kind: "map",
1970
+ elementId: result?.structuredContent?.id ?? args?.id
1971
+ });
1972
+ const reg = (name, description, properties, required, handler, resolveTarget) => {
1973
+ const wrapped = async (args) => {
1974
+ try {
1975
+ return await handler(args);
1976
+ } catch (e) {
1977
+ return errorResult(e instanceof Error ? e.message : String(e));
1978
+ }
1979
+ };
1980
+ const final = resolveTarget ? wrapToolWithActivity(wrapped, {
1981
+ toolName: name,
1982
+ agent: { id: agent.id, name: agent.name, color: agent.color },
1983
+ kind: "map",
1984
+ resolveTarget: ({ args, result }) => resolveTarget(args, result)
1985
+ }) : wrapped;
1986
+ disposers.push(
1987
+ host.registerTool(
1988
+ {
1989
+ name,
1990
+ description,
1991
+ inputSchema: {
1992
+ type: "object",
1993
+ properties,
1994
+ required,
1995
+ additionalProperties: false
1996
+ }
1997
+ },
1998
+ final
1999
+ )
2000
+ );
2001
+ };
2002
+ reg("map_get_state", "Get the map's camera, markers, and current selection.", {}, [], () => {
2003
+ const state = {
2004
+ view: adapter.getView(),
2005
+ markers: adapter.getMarkers(),
2006
+ selectedId: adapter.getSelected()
2007
+ };
2008
+ return textResult(JSON.stringify(state, null, 2), state);
2009
+ });
2010
+ reg(
2011
+ "map_set_view",
2012
+ "Move the camera to an absolute position. Any omitted field is left unchanged.",
2013
+ {
2014
+ lat: { type: "number", description: "New center latitude." },
2015
+ lng: { type: "number", description: "New center longitude." },
2016
+ zoom: { type: "number", description: "New zoom level (higher = closer)." }
2017
+ },
2018
+ [],
2019
+ (args) => {
2020
+ const prev = adapter.getView();
2021
+ const next = {
2022
+ center: {
2023
+ lat: args.lat !== void 0 ? num2(args.lat) : prev.center.lat,
2024
+ lng: args.lng !== void 0 ? num2(args.lng) : prev.center.lng
2025
+ },
2026
+ zoom: args.zoom !== void 0 ? num2(args.zoom) : prev.zoom
2027
+ };
2028
+ adapter.setView(next);
2029
+ fancyAutoCommon.pushUndoEntry(agent.id, {
2030
+ timestamp: Date.now(),
2031
+ bridgeId: "map",
2032
+ action: "map_set_view",
2033
+ label: `Moved camera to ${next.center.lat.toFixed(4)},${next.center.lng.toFixed(4)} z${next.zoom}`,
2034
+ undo: () => adapter.setView(prev),
2035
+ redo: () => adapter.setView(next)
2036
+ });
2037
+ return textResult(`Camera \u2192 ${next.center.lat.toFixed(4)},${next.center.lng.toFixed(4)} z${next.zoom}`, next);
2038
+ },
2039
+ mTarget
2040
+ );
2041
+ reg(
2042
+ "map_pan",
2043
+ "Pan the camera by a relative offset in degrees (positive dLat = north, positive dLng = east).",
2044
+ { dLat: { type: "number" }, dLng: { type: "number" } },
2045
+ [],
2046
+ (args) => {
2047
+ const prev = adapter.getView();
2048
+ const next = {
2049
+ ...prev,
2050
+ center: { lat: prev.center.lat + num2(args.dLat), lng: prev.center.lng + num2(args.dLng) }
2051
+ };
2052
+ adapter.setView(next);
2053
+ fancyAutoCommon.pushUndoEntry(agent.id, {
2054
+ timestamp: Date.now(),
2055
+ bridgeId: "map",
2056
+ action: "map_pan",
2057
+ label: "Panned camera",
2058
+ undo: () => adapter.setView(prev),
2059
+ redo: () => adapter.setView(next)
2060
+ });
2061
+ return textResult(`Panned to ${next.center.lat.toFixed(4)},${next.center.lng.toFixed(4)}`, next);
2062
+ },
2063
+ mTarget
2064
+ );
2065
+ reg(
2066
+ "map_zoom",
2067
+ "Zoom the camera by a relative delta (e.g. +1 zooms in one level, -2 out two).",
2068
+ { delta: { type: "number" } },
2069
+ ["delta"],
2070
+ (args) => {
2071
+ const prev = adapter.getView();
2072
+ const next = { ...prev, zoom: prev.zoom + num2(args.delta) };
2073
+ adapter.setView(next);
2074
+ fancyAutoCommon.pushUndoEntry(agent.id, {
2075
+ timestamp: Date.now(),
2076
+ bridgeId: "map",
2077
+ action: "map_zoom",
2078
+ label: `Zoom \u2192 ${next.zoom}`,
2079
+ undo: () => adapter.setView(prev),
2080
+ redo: () => adapter.setView(next)
2081
+ });
2082
+ return textResult(`Zoom \u2192 ${next.zoom}`, next);
2083
+ }
2084
+ );
2085
+ reg(
2086
+ "map_fit_bounds",
2087
+ "Fit the camera to enclose points. Pass `points`, or omit to fit all current markers.",
2088
+ {
2089
+ points: {
2090
+ type: "array",
2091
+ description: "Points to enclose, e.g. [{lat,lng},\u2026].",
2092
+ items: {
2093
+ type: "object",
2094
+ properties: { lat: { type: "number" }, lng: { type: "number" } },
2095
+ required: ["lat", "lng"]
2096
+ }
2097
+ },
2098
+ padding: { type: "number", description: "Padding in pixels (default 40)." }
2099
+ },
2100
+ [],
2101
+ (args) => {
2102
+ if (!adapter.fitBounds) {
2103
+ return errorResult("Host did not wire fitBounds (pass the <Map onReady> handle's fitBounds).");
2104
+ }
2105
+ const points = Array.isArray(args.points) ? args.points.map((p) => ({ lat: num2(p?.lat), lng: num2(p?.lng) })) : adapter.getMarkers().map((m) => m.position);
2106
+ if (!points.length) {
2107
+ return errorResult("No points to fit (map has no markers).");
2108
+ }
2109
+ adapter.fitBounds(points, args.padding !== void 0 ? num2(args.padding) : void 0);
2110
+ return textResult(`Fit camera to ${points.length} point(s).`);
2111
+ }
2112
+ );
2113
+ reg(
2114
+ "map_add_marker",
2115
+ "Drop a marker. `id` is optional (auto-generated); `icon` is an emoji or 1\u20132 chars.",
2116
+ {
2117
+ id: { type: "string" },
2118
+ lat: { type: "number" },
2119
+ lng: { type: "number" },
2120
+ label: { type: "string" },
2121
+ color: { type: "string", description: "CSS color, e.g. #2563eb." },
2122
+ icon: { type: "string", description: "Emoji / short text in the pin." },
2123
+ draggable: { type: "boolean" },
2124
+ data: { type: "object", description: "Arbitrary JSON payload carried with the marker." }
2125
+ },
2126
+ ["lat", "lng"],
2127
+ (args) => {
2128
+ const id = args.id ? str2(args.id) : newId("m");
2129
+ if (adapter.getMarkers().some((m) => m.id === id)) {
2130
+ return errorResult(`A marker with id ${id} already exists \u2014 use map_update_marker.`);
2131
+ }
2132
+ const marker = {
2133
+ id,
2134
+ position: { lat: num2(args.lat), lng: num2(args.lng) },
2135
+ ...args.label !== void 0 ? { label: str2(args.label) } : {},
2136
+ ...args.color !== void 0 ? { color: str2(args.color) } : {},
2137
+ ...args.icon !== void 0 ? { icon: str2(args.icon) } : {},
2138
+ ...args.draggable !== void 0 ? { draggable: !!args.draggable } : {},
2139
+ ...args.data && typeof args.data === "object" ? { data: args.data } : {}
2140
+ };
2141
+ adapter.setMarkers((all) => [...all, marker]);
2142
+ fancyAutoCommon.pushUndoEntry(agent.id, {
2143
+ timestamp: Date.now(),
2144
+ bridgeId: "map",
2145
+ action: "map_add_marker",
2146
+ label: `Added marker ${id}`,
2147
+ undo: () => adapter.setMarkers((all) => all.filter((m) => m.id !== id)),
2148
+ redo: () => adapter.setMarkers((all) => [...all, marker])
2149
+ });
2150
+ return textResult(`Added marker ${id} at ${marker.position.lat.toFixed(4)},${marker.position.lng.toFixed(4)}`, marker);
2151
+ },
2152
+ mTarget
2153
+ );
2154
+ reg(
2155
+ "map_update_marker",
2156
+ "Update a marker. Only provided fields change \u2014 update lat/lng repeatedly to drive a live track.",
2157
+ {
2158
+ id: { type: "string" },
2159
+ lat: { type: "number" },
2160
+ lng: { type: "number" },
2161
+ label: { type: "string" },
2162
+ color: { type: "string" },
2163
+ icon: { type: "string" },
2164
+ draggable: { type: "boolean" }
2165
+ },
2166
+ ["id"],
2167
+ (args) => {
2168
+ const id = str2(args.id);
2169
+ const prev = adapter.getMarkers().find((m) => m.id === id);
2170
+ if (!prev) {
2171
+ return errorResult(`No marker with id ${id}`);
2172
+ }
2173
+ const next = {
2174
+ ...prev,
2175
+ position: {
2176
+ lat: args.lat !== void 0 ? num2(args.lat) : prev.position.lat,
2177
+ lng: args.lng !== void 0 ? num2(args.lng) : prev.position.lng
2178
+ },
2179
+ ...args.label !== void 0 ? { label: str2(args.label) } : {},
2180
+ ...args.color !== void 0 ? { color: str2(args.color) } : {},
2181
+ ...args.icon !== void 0 ? { icon: str2(args.icon) } : {},
2182
+ ...args.draggable !== void 0 ? { draggable: !!args.draggable } : {}
2183
+ };
2184
+ adapter.setMarkers((all) => all.map((m) => m.id === id ? next : m));
2185
+ fancyAutoCommon.pushUndoEntry(agent.id, {
2186
+ timestamp: Date.now(),
2187
+ bridgeId: "map",
2188
+ action: "map_update_marker",
2189
+ label: `Updated marker ${id}`,
2190
+ undo: () => adapter.setMarkers((all) => all.map((m) => m.id === id ? prev : m)),
2191
+ redo: () => adapter.setMarkers((all) => all.map((m) => m.id === id ? next : m))
2192
+ });
2193
+ return textResult(`Updated marker ${id}`, next);
2194
+ },
2195
+ mTarget
2196
+ );
2197
+ reg(
2198
+ "map_remove_marker",
2199
+ "Remove a marker by id.",
2200
+ { id: { type: "string" } },
2201
+ ["id"],
2202
+ (args) => {
2203
+ const id = str2(args.id);
2204
+ const prev = adapter.getMarkers().find((m) => m.id === id);
2205
+ if (!prev) {
2206
+ return errorResult(`No marker with id ${id}`);
2207
+ }
2208
+ adapter.setMarkers((all) => all.filter((m) => m.id !== id));
2209
+ fancyAutoCommon.pushUndoEntry(agent.id, {
2210
+ timestamp: Date.now(),
2211
+ bridgeId: "map",
2212
+ action: "map_remove_marker",
2213
+ label: `Removed marker ${id}`,
2214
+ undo: () => adapter.setMarkers((all) => [...all, prev]),
2215
+ redo: () => adapter.setMarkers((all) => all.filter((m) => m.id !== id))
2216
+ });
2217
+ return textResult(`Removed marker ${id}`);
2218
+ },
2219
+ mTarget
2220
+ );
2221
+ reg(
2222
+ "map_select",
2223
+ "Select a marker (or pass no id / null to clear the selection).",
2224
+ { id: { type: "string" } },
2225
+ [],
2226
+ (args) => {
2227
+ const prev = adapter.getSelected();
2228
+ const id = args.id === void 0 || args.id === null ? null : str2(args.id);
2229
+ if (id !== null && !adapter.getMarkers().some((m) => m.id === id)) {
2230
+ return errorResult(`No marker with id ${id}`);
2231
+ }
2232
+ adapter.setSelected(id);
2233
+ fancyAutoCommon.pushUndoEntry(agent.id, {
2234
+ timestamp: Date.now(),
2235
+ bridgeId: "map",
2236
+ action: "map_select",
2237
+ label: id ? `Selected ${id}` : "Cleared selection",
2238
+ undo: () => adapter.setSelected(prev),
2239
+ redo: () => adapter.setSelected(id)
2240
+ });
2241
+ return textResult(id ? `Selected marker ${id}` : "Cleared selection", { selectedId: id });
2242
+ },
2243
+ mTarget
2244
+ );
2245
+ reg(
2246
+ "map_start_track",
2247
+ "Make the camera follow a marker as its position updates (live tracking). Requires the host to wire setFollow.",
2248
+ { id: { type: "string" } },
2249
+ ["id"],
2250
+ (args) => {
2251
+ if (!adapter.setFollow) {
2252
+ return errorResult("Host did not wire setFollow (pass the map's `follow` setter).");
2253
+ }
2254
+ const id = str2(args.id);
2255
+ if (!adapter.getMarkers().some((m) => m.id === id)) {
2256
+ return errorResult(`No marker with id ${id}`);
2257
+ }
2258
+ adapter.setFollow(id);
2259
+ return textResult(`Camera now following ${id}`, { follow: id });
2260
+ },
2261
+ mTarget
2262
+ );
2263
+ reg(
2264
+ "map_stop_track",
2265
+ "Stop following any marker (releases the camera). Requires the host to wire setFollow.",
2266
+ {},
2267
+ [],
2268
+ () => {
2269
+ if (!adapter.setFollow) {
2270
+ return errorResult("Host did not wire setFollow.");
2271
+ }
2272
+ adapter.setFollow(null);
2273
+ return textResult("Camera released (no longer following).", { follow: null });
2274
+ }
2275
+ );
2276
+ return {
2277
+ id: "map",
2278
+ title: "Map",
2279
+ dispose: () => {
2280
+ for (const d of disposers) d();
2281
+ }
2282
+ };
2283
+ }
2284
+
1958
2285
  // src/bridges/terminal.ts
1959
- var DEFAULT_AGENT8 = { id: "agent", name: "Agent", color: "#a855f7" };
2286
+ var DEFAULT_AGENT9 = { id: "agent", name: "Agent", color: "#a855f7" };
1960
2287
  var truncate = (s, n = 60) => s.length > n ? s.slice(0, n) + "\u2026" : s;
1961
2288
  function registerTerminalBridge(host, options) {
1962
- const agent = { ...DEFAULT_AGENT8, ...options.agent ?? {} };
2289
+ const agent = { ...DEFAULT_AGENT9, ...options.agent ?? {} };
1963
2290
  const pendingMode = options.pendingMode ?? false;
1964
2291
  const screenId = options.screenId ?? options.adapter?.screenId;
1965
2292
  const disposers = [];
@@ -2224,10 +2551,10 @@ function registerTerminalBridge(host, options) {
2224
2551
  }
2225
2552
 
2226
2553
  // src/bridges/navigation.ts
2227
- var DEFAULT_AGENT9 = { id: "agent", name: "Agent", color: "#a855f7" };
2554
+ var DEFAULT_AGENT10 = { id: "agent", name: "Agent", color: "#a855f7" };
2228
2555
  function registerNavigationBridge(host, options) {
2229
2556
  const { adapter } = options;
2230
- const agent = { ...DEFAULT_AGENT9, ...options.agent ?? {} };
2557
+ const agent = { ...DEFAULT_AGENT10, ...options.agent ?? {} };
2231
2558
  const pendingMode = options.pendingMode ?? true;
2232
2559
  const disposers = [];
2233
2560
  ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
@@ -2432,12 +2759,12 @@ function registerNavigationBridge(host, options) {
2432
2759
  }
2433
2760
 
2434
2761
  // src/bridges/catalog.ts
2435
- var DEFAULT_AGENT10 = { id: "agent", name: "Agent", color: "#a855f7" };
2436
- var str2 = (v, fallback = "") => typeof v === "string" ? v : fallback;
2437
- var num2 = (v, fallback = 0) => typeof v === "number" && Number.isFinite(v) ? v : fallback;
2762
+ var DEFAULT_AGENT11 = { id: "agent", name: "Agent", color: "#a855f7" };
2763
+ var str3 = (v, fallback = "") => typeof v === "string" ? v : fallback;
2764
+ var num3 = (v, fallback = 0) => typeof v === "number" && Number.isFinite(v) ? v : fallback;
2438
2765
  function registerCatalogBridge(host, options) {
2439
2766
  const { adapter } = options;
2440
- const agent = { ...DEFAULT_AGENT10, ...options.agent ?? {} };
2767
+ const agent = { ...DEFAULT_AGENT11, ...options.agent ?? {} };
2441
2768
  const pendingMode = options.pendingMode ?? true;
2442
2769
  const catalogId = adapter.id ?? "catalog";
2443
2770
  const disposers = [];
@@ -2507,7 +2834,7 @@ function registerCatalogBridge(host, options) {
2507
2834
  { id: { type: "string" }, withTrashed: { type: "boolean" } },
2508
2835
  ["id"],
2509
2836
  async (args) => {
2510
- const id = str2(args.id);
2837
+ const id = str3(args.id);
2511
2838
  const product = await adapter.products.find(id, { withTrashed: args.withTrashed === true });
2512
2839
  if (!product) return errorResult(`No product with id ${id}`);
2513
2840
  const prices = await adapter.prices.forProduct(id, { withTrashed: args.withTrashed === true });
@@ -2523,7 +2850,7 @@ function registerCatalogBridge(host, options) {
2523
2850
  [],
2524
2851
  async (args) => {
2525
2852
  const withTrashed = args.withTrashed === true;
2526
- const prices = args.productId !== void 0 ? await adapter.prices.forProduct(str2(args.productId), { withTrashed }) : await adapter.prices.all({ withTrashed });
2853
+ const prices = args.productId !== void 0 ? await adapter.prices.forProduct(str3(args.productId), { withTrashed }) : await adapter.prices.all({ withTrashed });
2527
2854
  const list = prices.map((p) => ({
2528
2855
  id: p.id,
2529
2856
  productId: p.productId,
@@ -2549,13 +2876,13 @@ function registerCatalogBridge(host, options) {
2549
2876
  },
2550
2877
  ["name"],
2551
2878
  async (args) => {
2552
- const name = str2(args.name);
2879
+ const name = str3(args.name);
2553
2880
  if (!name) return errorResult("name is required.");
2554
2881
  const product = await adapter.createProduct({
2555
2882
  name,
2556
- ...args.description !== void 0 ? { description: str2(args.description) } : {},
2883
+ ...args.description !== void 0 ? { description: str3(args.description) } : {},
2557
2884
  ...args.active !== void 0 ? { active: args.active === true } : {},
2558
- ...args.lookupKey !== void 0 ? { lookupKey: str2(args.lookupKey) } : {},
2885
+ ...args.lookupKey !== void 0 ? { lookupKey: str3(args.lookupKey) } : {},
2559
2886
  ...args.metadata && typeof args.metadata === "object" ? { metadata: args.metadata } : {}
2560
2887
  });
2561
2888
  fancyAutoCommon.pushUndoEntry(agent.id, {
@@ -2568,7 +2895,7 @@ function registerCatalogBridge(host, options) {
2568
2895
  });
2569
2896
  return textResult(`Created product ${product.id} (${product.name})`, product);
2570
2897
  },
2571
- (args) => target(void 0, `create product ${str2(args.name)}`)
2898
+ (args) => target(void 0, `create product ${str3(args.name)}`)
2572
2899
  );
2573
2900
  reg(
2574
2901
  "catalog_create_price",
@@ -2585,19 +2912,19 @@ function registerCatalogBridge(host, options) {
2585
2912
  },
2586
2913
  ["productId", "currency", "unitAmount", "type"],
2587
2914
  async (args) => {
2588
- const productId = str2(args.productId);
2915
+ const productId = str3(args.productId);
2589
2916
  const product = await adapter.products.find(productId);
2590
2917
  if (!product) return errorResult(`No product with id ${productId}`);
2591
- const type = str2(args.type);
2918
+ const type = str3(args.type);
2592
2919
  if (type !== "recurring" && type !== "one_time") return errorResult("type must be 'recurring' or 'one_time'.");
2593
2920
  const price = await adapter.createPrice({
2594
2921
  productId,
2595
- currency: str2(args.currency),
2596
- unitAmount: num2(args.unitAmount),
2922
+ currency: str3(args.currency),
2923
+ unitAmount: num3(args.unitAmount),
2597
2924
  type,
2598
- ...args.recurringInterval !== void 0 ? { recurringInterval: str2(args.recurringInterval) } : {},
2599
- ...args.nickname !== void 0 ? { nickname: str2(args.nickname) } : {},
2600
- ...args.lookupKey !== void 0 ? { lookupKey: str2(args.lookupKey) } : {},
2925
+ ...args.recurringInterval !== void 0 ? { recurringInterval: str3(args.recurringInterval) } : {},
2926
+ ...args.nickname !== void 0 ? { nickname: str3(args.nickname) } : {},
2927
+ ...args.lookupKey !== void 0 ? { lookupKey: str3(args.lookupKey) } : {},
2601
2928
  ...args.metadata && typeof args.metadata === "object" ? { metadata: args.metadata } : {}
2602
2929
  });
2603
2930
  fancyAutoCommon.pushUndoEntry(agent.id, {
@@ -2610,7 +2937,7 @@ function registerCatalogBridge(host, options) {
2610
2937
  });
2611
2938
  return textResult(`Created ${type} price ${price.id} on ${productId}`, price);
2612
2939
  },
2613
- (args) => target(str2(args.productId), `create price on ${str2(args.productId)}`)
2940
+ (args) => target(str3(args.productId), `create price on ${str3(args.productId)}`)
2614
2941
  );
2615
2942
  reg(
2616
2943
  "catalog_delete_product",
@@ -2618,7 +2945,7 @@ function registerCatalogBridge(host, options) {
2618
2945
  { id: { type: "string" }, confirm: { type: "boolean" } },
2619
2946
  ["id"],
2620
2947
  async (args) => {
2621
- const id = str2(args.id);
2948
+ const id = str3(args.id);
2622
2949
  const product = await adapter.products.find(id, { withTrashed: true });
2623
2950
  if (!product) return errorResult(`No product with id ${id}`);
2624
2951
  const blocked = await guardDestructive("catalog_delete_product", id, product.name, args.confirm === true);
@@ -2635,7 +2962,7 @@ function registerCatalogBridge(host, options) {
2635
2962
  });
2636
2963
  return textResult(`Deleted product ${id}`, { id });
2637
2964
  },
2638
- (args) => target(str2(args.id), `delete product ${str2(args.id)}`)
2965
+ (args) => target(str3(args.id), `delete product ${str3(args.id)}`)
2639
2966
  );
2640
2967
  reg(
2641
2968
  "catalog_delete_price",
@@ -2643,7 +2970,7 @@ function registerCatalogBridge(host, options) {
2643
2970
  { id: { type: "string" }, confirm: { type: "boolean" } },
2644
2971
  ["id"],
2645
2972
  async (args) => {
2646
- const id = str2(args.id);
2973
+ const id = str3(args.id);
2647
2974
  const price = await adapter.prices.find(id, { withTrashed: true });
2648
2975
  if (!price) return errorResult(`No price with id ${id}`);
2649
2976
  const blocked = await guardDestructive("catalog_delete_price", id, id, args.confirm === true);
@@ -2660,7 +2987,7 @@ function registerCatalogBridge(host, options) {
2660
2987
  });
2661
2988
  return textResult(`Deleted price ${id}`, { id });
2662
2989
  },
2663
- (args) => target(str2(args.id), `delete price ${str2(args.id)}`)
2990
+ (args) => target(str3(args.id), `delete price ${str3(args.id)}`)
2664
2991
  );
2665
2992
  reg(
2666
2993
  "catalog_sync_product",
@@ -2669,13 +2996,13 @@ function registerCatalogBridge(host, options) {
2669
2996
  ["id"],
2670
2997
  async (args) => {
2671
2998
  if (!adapter.syncProductAndPrices) return errorResult("Host did not wire Stripe sync.");
2672
- const id = str2(args.id);
2999
+ const id = str3(args.id);
2673
3000
  const product = await adapter.products.find(id);
2674
3001
  if (!product) return errorResult(`No product with id ${id}`);
2675
3002
  const synced = await adapter.syncProductAndPrices(product);
2676
3003
  return textResult(`Synced product ${id} to Stripe (${synced.externalId ?? "no external id"})`, synced);
2677
3004
  },
2678
- (args) => target(str2(args.id), `sync product ${str2(args.id)}`)
3005
+ (args) => target(str3(args.id), `sync product ${str3(args.id)}`)
2679
3006
  );
2680
3007
  reg(
2681
3008
  "catalog_test_connection",
@@ -2702,13 +3029,13 @@ function registerCatalogBridge(host, options) {
2702
3029
  },
2703
3030
  ["priceId", "successUrl", "cancelUrl"],
2704
3031
  async (args) => {
2705
- const priceId = str2(args.priceId);
3032
+ const priceId = str3(args.priceId);
2706
3033
  const price = await adapter.prices.find(priceId);
2707
3034
  if (!price) return errorResult(`No price with id ${priceId}`);
2708
3035
  const checkoutArgs = {
2709
- successUrl: str2(args.successUrl),
2710
- cancelUrl: str2(args.cancelUrl),
2711
- ...args.customer !== void 0 ? { customer: str2(args.customer) } : {},
3036
+ successUrl: str3(args.successUrl),
3037
+ cancelUrl: str3(args.cancelUrl),
3038
+ ...args.customer !== void 0 ? { customer: str3(args.customer) } : {},
2712
3039
  ...args.metadata && typeof args.metadata === "object" ? { metadata: args.metadata } : {}
2713
3040
  };
2714
3041
  let url;
@@ -2717,11 +3044,11 @@ function registerCatalogBridge(host, options) {
2717
3044
  url = await adapter.getSubscriptionCheckoutUrl(price, checkoutArgs);
2718
3045
  } else {
2719
3046
  if (!adapter.getOneTimeCheckoutUrl) return errorResult("Host did not wire one-time checkout.");
2720
- url = await adapter.getOneTimeCheckoutUrl(price, { ...checkoutArgs, quantity: num2(args.quantity, 1) });
3047
+ url = await adapter.getOneTimeCheckoutUrl(price, { ...checkoutArgs, quantity: num3(args.quantity, 1) });
2721
3048
  }
2722
3049
  return textResult(url || "(no url)", { priceId, type: price.type, url });
2723
3050
  },
2724
- (args) => target(str2(args.priceId), `checkout ${str2(args.priceId)}`)
3051
+ (args) => target(str3(args.priceId), `checkout ${str3(args.priceId)}`)
2725
3052
  );
2726
3053
  return {
2727
3054
  id: `catalog:${catalogId}`,
@@ -2733,12 +3060,12 @@ function registerCatalogBridge(host, options) {
2733
3060
  }
2734
3061
 
2735
3062
  // src/bridges/features.ts
2736
- var DEFAULT_AGENT11 = { id: "agent", name: "Agent", color: "#a855f7" };
2737
- var str3 = (v, fallback = "") => typeof v === "string" ? v : fallback;
2738
- var num3 = (v, fallback = 0) => typeof v === "number" && Number.isFinite(v) ? v : fallback;
3063
+ var DEFAULT_AGENT12 = { id: "agent", name: "Agent", color: "#a855f7" };
3064
+ var str4 = (v, fallback = "") => typeof v === "string" ? v : fallback;
3065
+ var num4 = (v, fallback = 0) => typeof v === "number" && Number.isFinite(v) ? v : fallback;
2739
3066
  function registerFeaturesBridge(host, options) {
2740
3067
  const { adapter } = options;
2741
- const agent = { ...DEFAULT_AGENT11, ...options.agent ?? {} };
3068
+ const agent = { ...DEFAULT_AGENT12, ...options.agent ?? {} };
2742
3069
  const pendingMode = options.pendingMode ?? true;
2743
3070
  const featuresId = adapter.id ?? "features";
2744
3071
  const disposers = [];
@@ -2799,7 +3126,7 @@ function registerFeaturesBridge(host, options) {
2799
3126
  { feature: { type: "string" }, subject: { description: "Opaque subject." }, context: { description: "Optional context." } },
2800
3127
  ["feature"],
2801
3128
  async (args) => {
2802
- const feature = str3(args.feature);
3129
+ const feature = str4(args.feature);
2803
3130
  const allowed = await adapter.canAccess(feature, args.subject, args.context);
2804
3131
  const remaining = await adapter.remaining(feature, args.subject, args.context);
2805
3132
  const out = { feature, allowed, remaining };
@@ -2814,7 +3141,7 @@ function registerFeaturesBridge(host, options) {
2814
3141
  ["feature"],
2815
3142
  async (args) => {
2816
3143
  if (!adapter.explain) return errorResult("Host did not wire explain().");
2817
- const result = await adapter.explain(str3(args.feature), args.subject, args.context);
3144
+ const result = await adapter.explain(str4(args.feature), args.subject, args.context);
2818
3145
  return textResult(JSON.stringify(result, null, 2), result);
2819
3146
  },
2820
3147
  false
@@ -2843,15 +3170,15 @@ function registerFeaturesBridge(host, options) {
2843
3170
  },
2844
3171
  ["key"],
2845
3172
  (args) => {
2846
- const key = str3(args.key);
3173
+ const key = str4(args.key);
2847
3174
  if (!key) return errorResult("key is required.");
2848
3175
  const existed = adapter.registryKeys().includes(key);
2849
3176
  const definition = {
2850
- ...args.name !== void 0 ? { name: str3(args.name) } : {},
2851
- ...args.description !== void 0 ? { description: str3(args.description) } : {},
2852
- ...args.type !== void 0 ? { type: str3(args.type) } : {},
3177
+ ...args.name !== void 0 ? { name: str4(args.name) } : {},
3178
+ ...args.description !== void 0 ? { description: str4(args.description) } : {},
3179
+ ...args.type !== void 0 ? { type: str4(args.type) } : {},
2853
3180
  ...args.enabled !== void 0 ? { enabled: args.enabled === true } : {},
2854
- ...args.limit !== void 0 ? { limit: num3(args.limit) } : {}
3181
+ ...args.limit !== void 0 ? { limit: num4(args.limit) } : {}
2855
3182
  };
2856
3183
  adapter.registerFeature(key, definition);
2857
3184
  fancyAutoCommon.pushUndoEntry(agent.id, {
@@ -2866,7 +3193,7 @@ function registerFeaturesBridge(host, options) {
2866
3193
  });
2867
3194
  return textResult(`${existed ? "Redefined" : "Defined"} feature ${key} (${definition.type ?? "boolean"})`, { key, definition });
2868
3195
  },
2869
- (args) => target(str3(args.key), `define ${str3(args.key)}`)
3196
+ (args) => target(str4(args.key), `define ${str4(args.key)}`)
2870
3197
  );
2871
3198
  reg(
2872
3199
  "features_grant",
@@ -2874,7 +3201,7 @@ function registerFeaturesBridge(host, options) {
2874
3201
  { subject: { description: "Opaque subject." }, group: { type: "string", description: "Feature group key." }, confirm: { type: "boolean" } },
2875
3202
  ["subject", "group"],
2876
3203
  async (args) => {
2877
- const groupKey = str3(args.group);
3204
+ const groupKey = str4(args.group);
2878
3205
  if (!groupKey) return errorResult("group is required.");
2879
3206
  const blocked = await guardGrant("features_grant", args.subject, groupKey, args.confirm === true);
2880
3207
  if (blocked) return blocked;
@@ -2893,7 +3220,7 @@ function registerFeaturesBridge(host, options) {
2893
3220
  });
2894
3221
  return textResult(`Granted group ${groupKey}`, { subject: args.subject, group: groupKey });
2895
3222
  },
2896
- (args) => target(str3(args.group), `grant ${str3(args.group)}`)
3223
+ (args) => target(str4(args.group), `grant ${str4(args.group)}`)
2897
3224
  );
2898
3225
  reg(
2899
3226
  "features_revoke",
@@ -2901,7 +3228,7 @@ function registerFeaturesBridge(host, options) {
2901
3228
  { subject: { description: "Opaque subject." }, group: { type: "string" }, confirm: { type: "boolean" } },
2902
3229
  ["subject", "group"],
2903
3230
  async (args) => {
2904
- const groupKey = str3(args.group);
3231
+ const groupKey = str4(args.group);
2905
3232
  if (!groupKey) return errorResult("group is required.");
2906
3233
  const blocked = await guardGrant("features_revoke", args.subject, groupKey, args.confirm === true);
2907
3234
  if (blocked) return blocked;
@@ -2919,7 +3246,7 @@ function registerFeaturesBridge(host, options) {
2919
3246
  });
2920
3247
  return textResult(`Revoked group ${groupKey}`, { subject: args.subject, group: groupKey });
2921
3248
  },
2922
- (args) => target(str3(args.group), `revoke ${str3(args.group)}`)
3249
+ (args) => target(str4(args.group), `revoke ${str4(args.group)}`)
2923
3250
  );
2924
3251
  reg(
2925
3252
  "features_consume",
@@ -2928,14 +3255,14 @@ function registerFeaturesBridge(host, options) {
2928
3255
  ["feature", "subject"],
2929
3256
  async (args) => {
2930
3257
  if (!adapter.tryConsume) return errorResult("Host did not wire usage metering (tryConsume).");
2931
- const feature = str3(args.feature);
2932
- const amount = num3(args.amount, 1);
3258
+ const feature = str4(args.feature);
3259
+ const amount = num4(args.amount, 1);
2933
3260
  const ok = await adapter.tryConsume(feature, args.subject, amount, args.context);
2934
3261
  const remaining = await adapter.remaining(feature, args.subject, args.context);
2935
3262
  const out = { feature, ok, amount, remaining };
2936
3263
  return textResult(JSON.stringify(out), out);
2937
3264
  },
2938
- (args) => target(str3(args.feature), `consume ${str3(args.feature)}`)
3265
+ (args) => target(str4(args.feature), `consume ${str4(args.feature)}`)
2939
3266
  );
2940
3267
  return {
2941
3268
  id: `features:${featuresId}`,
@@ -3140,11 +3467,11 @@ function attachSseRelay(server, options) {
3140
3467
 
3141
3468
  // src/sharing/use-co-browse-session.ts
3142
3469
  init_registry();
3143
- var DEFAULT_AGENT12 = { id: "agent", name: "Agent", color: "#a855f7" };
3470
+ var DEFAULT_AGENT13 = { id: "agent", name: "Agent", color: "#a855f7" };
3144
3471
  var USER = { id: "human", name: "You" };
3145
3472
  function useCoBrowseSession(options) {
3146
3473
  const { adapter, extraBridges } = options;
3147
- const agent = { ...DEFAULT_AGENT12, ...options.agent ?? {} };
3474
+ const agent = { ...DEFAULT_AGENT13, ...options.agent ?? {} };
3148
3475
  const relayBaseUrl = options.relayBaseUrl ?? "/agent-relay";
3149
3476
  const serverRef = react.useRef(null);
3150
3477
  const relayRef = react.useRef(null);
@@ -4371,6 +4698,7 @@ exports.registerChartsBridge = registerChartsBridge;
4371
4698
  exports.registerCodeBridge = registerCodeBridge;
4372
4699
  exports.registerFeaturesBridge = registerFeaturesBridge;
4373
4700
  exports.registerFormBridge = registerFormBridge;
4701
+ exports.registerMapBridge = registerMapBridge;
4374
4702
  exports.registerNavigationBridge = registerNavigationBridge;
4375
4703
  exports.registerSceneBridge = registerSceneBridge;
4376
4704
  exports.registerScreensBridge = registerScreensBridge;