@particle-academy/agent-integrations 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/README.md +30 -1
  2. package/dist/bridges/files.d.cts +20 -1
  3. package/dist/bridges/files.d.ts +20 -1
  4. package/dist/bridges/forms.d.cts +22 -1
  5. package/dist/bridges/forms.d.ts +22 -1
  6. package/dist/bridges/git.d.cts +44 -0
  7. package/dist/bridges/git.d.ts +44 -0
  8. package/dist/bridges/terminal.d.cts +21 -1
  9. package/dist/bridges/terminal.d.ts +21 -1
  10. package/dist/bridges-artboard.cjs +1 -1
  11. package/dist/bridges-artboard.cjs.map +1 -1
  12. package/dist/bridges-artboard.js +1 -1
  13. package/dist/bridges-catalog.cjs +1 -1
  14. package/dist/bridges-catalog.cjs.map +1 -1
  15. package/dist/bridges-catalog.js +2 -2
  16. package/dist/bridges-charts.cjs +1 -1
  17. package/dist/bridges-charts.cjs.map +1 -1
  18. package/dist/bridges-charts.js +2 -2
  19. package/dist/bridges-cms.cjs +1 -1
  20. package/dist/bridges-cms.cjs.map +1 -1
  21. package/dist/bridges-cms.js +3 -3
  22. package/dist/bridges-code.cjs +38 -3
  23. package/dist/bridges-code.cjs.map +1 -1
  24. package/dist/bridges-code.js +2 -2
  25. package/dist/bridges-doc.cjs +1 -1
  26. package/dist/bridges-doc.cjs.map +1 -1
  27. package/dist/bridges-doc.js +2 -2
  28. package/dist/bridges-features.cjs +1 -1
  29. package/dist/bridges-features.cjs.map +1 -1
  30. package/dist/bridges-features.js +2 -2
  31. package/dist/bridges-files.cjs +29 -8
  32. package/dist/bridges-files.cjs.map +1 -1
  33. package/dist/bridges-files.js +2 -2
  34. package/dist/bridges-flow.cjs +1 -1
  35. package/dist/bridges-flow.cjs.map +1 -1
  36. package/dist/bridges-flow.js +1 -1
  37. package/dist/bridges-forms.cjs +12 -2
  38. package/dist/bridges-forms.cjs.map +1 -1
  39. package/dist/bridges-forms.js +2 -2
  40. package/dist/bridges-git.cjs +214 -0
  41. package/dist/bridges-git.cjs.map +1 -0
  42. package/dist/bridges-git.js +7 -0
  43. package/dist/bridges-git.js.map +1 -0
  44. package/dist/bridges-map.cjs +1 -1
  45. package/dist/bridges-map.cjs.map +1 -1
  46. package/dist/bridges-map.js +2 -2
  47. package/dist/bridges-scene.cjs +1 -1
  48. package/dist/bridges-scene.cjs.map +1 -1
  49. package/dist/bridges-scene.js +2 -2
  50. package/dist/bridges-screens.cjs +1 -1
  51. package/dist/bridges-screens.cjs.map +1 -1
  52. package/dist/bridges-screens.js +2 -2
  53. package/dist/bridges-sheets.cjs +1 -1
  54. package/dist/bridges-sheets.cjs.map +1 -1
  55. package/dist/bridges-sheets.js +2 -2
  56. package/dist/bridges-slides.cjs +1 -1
  57. package/dist/bridges-slides.cjs.map +1 -1
  58. package/dist/bridges-slides.js +2 -2
  59. package/dist/bridges-terminal.cjs +70 -45
  60. package/dist/bridges-terminal.cjs.map +1 -1
  61. package/dist/bridges-terminal.js +2 -2
  62. package/dist/bridges-tui.js +1 -1
  63. package/dist/bridges-whiteboard.cjs +1 -1
  64. package/dist/bridges-whiteboard.cjs.map +1 -1
  65. package/dist/bridges-whiteboard.js +2 -2
  66. package/dist/{chunk-OFCR6JY3.js → chunk-2U5JB6ZA.js} +3 -3
  67. package/dist/{chunk-OFCR6JY3.js.map → chunk-2U5JB6ZA.js.map} +1 -1
  68. package/dist/{chunk-ULJL53DL.js → chunk-2VENWGLZ.js} +3 -3
  69. package/dist/chunk-2VENWGLZ.js.map +1 -0
  70. package/dist/chunk-4D3II37O.js +94 -0
  71. package/dist/chunk-4D3II37O.js.map +1 -0
  72. package/dist/{chunk-BE2XS577.js → chunk-6YUBWQTS.js} +3 -3
  73. package/dist/{chunk-BE2XS577.js.map → chunk-6YUBWQTS.js.map} +1 -1
  74. package/dist/{chunk-OHUDEA6R.js → chunk-BHQJJ2YG.js} +3 -3
  75. package/dist/{chunk-OHUDEA6R.js.map → chunk-BHQJJ2YG.js.map} +1 -1
  76. package/dist/{chunk-LZJI7EKQ.js → chunk-CA7GIJJC.js} +3 -3
  77. package/dist/{chunk-LZJI7EKQ.js.map → chunk-CA7GIJJC.js.map} +1 -1
  78. package/dist/{chunk-7VBB2FJB.js → chunk-DKSR4R4O.js} +3 -3
  79. package/dist/{chunk-7VBB2FJB.js.map → chunk-DKSR4R4O.js.map} +1 -1
  80. package/dist/{chunk-2Y7Y5PTR.js → chunk-G5EZNWXJ.js} +3 -3
  81. package/dist/{chunk-2Y7Y5PTR.js.map → chunk-G5EZNWXJ.js.map} +1 -1
  82. package/dist/{chunk-OIX2ANFS.js → chunk-GRHPEK6M.js} +45 -9
  83. package/dist/chunk-GRHPEK6M.js.map +1 -0
  84. package/dist/{chunk-VMCG3PJD.js → chunk-HRHC5GM5.js} +31 -11
  85. package/dist/chunk-HRHC5GM5.js.map +1 -0
  86. package/dist/{chunk-5KLUYF4D.js → chunk-HSI5RVF4.js} +3 -3
  87. package/dist/{chunk-5KLUYF4D.js.map → chunk-HSI5RVF4.js.map} +1 -1
  88. package/dist/{chunk-AF454WRD.js → chunk-LQZKRBWR.js} +3 -3
  89. package/dist/{chunk-AF454WRD.js.map → chunk-LQZKRBWR.js.map} +1 -1
  90. package/dist/{chunk-KMSRG5KH.js → chunk-N6RLSLOF.js} +7 -7
  91. package/dist/chunk-N6RLSLOF.js.map +1 -0
  92. package/dist/{chunk-NSPL5TVF.js → chunk-OAFJ53X3.js} +3 -3
  93. package/dist/{chunk-NSPL5TVF.js.map → chunk-OAFJ53X3.js.map} +1 -1
  94. package/dist/{chunk-3PKHJ4IV.js → chunk-PR4SXFZH.js} +3 -3
  95. package/dist/{chunk-3PKHJ4IV.js.map → chunk-PR4SXFZH.js.map} +1 -1
  96. package/dist/{chunk-KYMEDV6E.js → chunk-RIXYCFDO.js} +41 -6
  97. package/dist/chunk-RIXYCFDO.js.map +1 -0
  98. package/dist/{chunk-TNU6AWUO.js → chunk-USQGA672.js} +14 -4
  99. package/dist/chunk-USQGA672.js.map +1 -0
  100. package/dist/{chunk-KKGC4ERF.js → chunk-UZHNKUER.js} +72 -47
  101. package/dist/chunk-UZHNKUER.js.map +1 -0
  102. package/dist/{chunk-UTUVN6HQ.js → chunk-WCKSDFTM.js} +3 -3
  103. package/dist/{chunk-UTUVN6HQ.js.map → chunk-WCKSDFTM.js.map} +1 -1
  104. package/dist/{chunk-HFLHLS2N.js → chunk-ZNGTC4CO.js} +3 -3
  105. package/dist/{chunk-HFLHLS2N.js.map → chunk-ZNGTC4CO.js.map} +1 -1
  106. package/dist/components/SharedWhiteboard/index.d.cts +1 -1
  107. package/dist/components/SharedWhiteboard/index.d.ts +1 -1
  108. package/dist/components-shared-whiteboard.cjs +2 -3
  109. package/dist/components-shared-whiteboard.cjs.map +1 -1
  110. package/dist/components-shared-whiteboard.js +4 -4
  111. package/dist/heuristics.js +1 -1
  112. package/dist/index.cjs +244 -60
  113. package/dist/index.cjs.map +1 -1
  114. package/dist/index.d.cts +3 -2
  115. package/dist/index.d.ts +3 -2
  116. package/dist/index.js +31 -24
  117. package/dist/index.js.map +1 -1
  118. package/dist/presence/index.d.cts +7 -0
  119. package/dist/presence/index.d.ts +7 -0
  120. package/dist/presence.cjs +1 -1
  121. package/dist/presence.cjs.map +1 -1
  122. package/dist/presence.js +1 -1
  123. package/dist/relay-server/index.d.cts +20 -0
  124. package/dist/relay-server/index.d.ts +20 -0
  125. package/dist/relay-server-cli.cjs +53 -9
  126. package/dist/relay-server-cli.cjs.map +1 -1
  127. package/dist/relay-server-cli.js +11 -3
  128. package/dist/relay-server-cli.js.map +1 -1
  129. package/dist/relay-server.cjs +43 -7
  130. package/dist/relay-server.cjs.map +1 -1
  131. package/dist/relay-server.js +1 -1
  132. package/dist/sharing/index.d.cts +1 -1
  133. package/dist/sharing/index.d.ts +1 -1
  134. package/dist/sharing.cjs +5 -5
  135. package/dist/sharing.cjs.map +1 -1
  136. package/dist/sharing.js +1 -1
  137. package/dist/{token-CrJF76oH.d.ts → token-BZ8doMam.d.cts} +15 -2
  138. package/dist/{token-CrJF76oH.d.cts → token-BZ8doMam.d.ts} +15 -2
  139. package/package.json +35 -7
  140. package/dist/chunk-KKGC4ERF.js.map +0 -1
  141. package/dist/chunk-KMSRG5KH.js.map +0 -1
  142. package/dist/chunk-KYMEDV6E.js.map +0 -1
  143. package/dist/chunk-OIX2ANFS.js.map +0 -1
  144. package/dist/chunk-TNU6AWUO.js.map +0 -1
  145. package/dist/chunk-ULJL53DL.js.map +0 -1
  146. package/dist/chunk-VMCG3PJD.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bridges/forms.ts"],"names":[],"mappings":"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","file":"chunk-USQGA672.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\nimport type { AgentTarget } from \"../presence/types\";\n\n/**\n * Field descriptor — what the host says about each form field. Mirrors the\n * subset of HTML / react-fancy input shapes agents care about.\n */\nexport type FormFieldDescriptor = {\n /** Form-local field name. Matches the key the host uses in its values map. */\n name: string;\n /** Display label. */\n label?: string;\n /** Logical type. Drives validation + agent expectations. */\n type:\n | \"text\"\n | \"textarea\"\n | \"number\"\n | \"email\"\n | \"password\"\n | \"url\"\n | \"date\"\n | \"select\"\n | \"multi-select\"\n | \"checkbox\"\n | \"switch\"\n | \"radio\"\n | \"file\"\n | \"json\";\n /** Allowed values for select / radio. */\n options?: Array<{ value: string; label: string }>;\n /** Whether the field must be filled before submit. */\n required?: boolean;\n /** Free-text hint surfaced to the agent. */\n description?: string;\n /** Default value (presented in get_value when nothing set). */\n defaultValue?: unknown;\n};\n\n/**\n * Adapter the host wires per form. Matches the controlled-state pattern\n * react-fancy already uses (`value` / `onValueChange`); this adapter just\n * exposes those state slots in a form-shaped way the bridge can call.\n */\nexport type FormBridgeAdapter = {\n /** Stable id for the form (used in form_describe + presence target). */\n id: string;\n /** Display title for human-readable logs. */\n title?: string;\n /** Optional fancy-screens screen id this form belongs to. */\n screenId?: string;\n /** Field descriptors. The bridge uses these for schema introspection\n * (form_describe). Agents call this first to know what to fill. */\n getFields: () => FormFieldDescriptor[];\n /** Read a single field's current value. */\n getValue: (name: string) => unknown;\n /** Read all values as { fieldName: value }. */\n getValues: () => Record<string, unknown>;\n /** Set a single field's value. The host wires this to its setState. */\n setValue: (name: string, value: unknown) => void;\n /** Set many at once. Defaults to calling setValue in a loop. */\n setValues?: (values: Record<string, unknown>) => void;\n /** Programmatically focus a field (host implements DOM focus). Optional. */\n focus?: (name: string) => void;\n /** Submit the form. Returns the values that were submitted (or rejection). */\n submit?: () => Promise<{ ok: boolean; values?: Record<string, unknown>; error?: string }>;\n /**\n * Human confirm gate for `form_submit` (trust-but-verify). When `pendingMode`\n * is on, the bridge calls this before submitting; return false to decline.\n * Wire it to a human control — submitting a form is a human-visible,\n * often-destructive action (checkout, delete, invite).\n */\n confirm?: (request: FormConfirmRequest) => Promise<boolean> | boolean;\n};\n\n/** What a `form_submit` confirm gate is asked to approve. */\nexport type FormConfirmRequest = {\n action: \"submit\";\n form: string;\n title?: string;\n values: Record<string, unknown>;\n};\n\nexport type FormBridgeOptions = {\n adapter: FormBridgeAdapter;\n /** Identity tagged into activity events. */\n agent?: { id: string; name?: string; color?: string };\n /**\n * Stage `form_submit` for human confirmation via `adapter.confirm` instead of\n * submitting immediately. **Default: ON** (matches the navigation bridge and\n * the Human+ trust-but-verify contract). Set false only when auto-submit is\n * safe. If on without an `adapter.confirm`, submit proceeds (nothing to gate).\n */\n pendingMode?: boolean;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * registerFormBridge — wires schema-driven MCP access to a single form.\n * Hosts can register multiple bridges (one per form on the screen) by\n * giving each adapter a distinct `id`.\n */\nexport function registerFormBridge(\n host: ToolHost,\n options: FormBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const pendingMode = options.pendingMode ?? true;\n const disposers: Array<() => void> = [];\n\n // agent_undo / agent_redo / agent_history are registered whenever any bridge\n // mounts, so undo availability doesn't hinge on which bridges are co-present.\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n const formId = adapter.id;\n\n const target = (args: any): AgentTarget => ({\n kind: \"form\",\n screenId: adapter.screenId,\n elementId: typeof args?.field === \"string\" ? `${formId}:${args.field}` : formId,\n label: typeof args?.field === \"string\"\n ? `${adapter.title ?? formId} → ${args.field}`\n : adapter.title ?? formId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n isMutation: boolean,\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = isMutation\n ? wrapToolWithActivity(wrapped, {\n toolName: name,\n agent: { id: agent.id, name: agent.name, color: agent.color },\n kind: \"form\",\n screenId: adapter.screenId,\n resolveTarget: ({ args }) => target(args),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false },\n },\n final as any,\n ),\n );\n };\n\n // ───────────── Read tools ─────────────\n\n reg(\n \"form_describe\",\n `Describe the form \"${formId}\" — fields, types, options, required flags. Call this first to know what's fillable.`,\n {},\n [],\n () => {\n const fields = adapter.getFields();\n const text = fields\n .map((f) => `${f.name}${f.required ? \"*\" : \"\"} (${f.type})${f.label ? ` — ${f.label}` : \"\"}`)\n .join(\"\\n\");\n return textResult(text || \"(no fields)\", { id: formId, title: adapter.title, fields });\n },\n false,\n );\n\n reg(\n \"form_get_value\",\n \"Read a single field's current value.\",\n { field: { type: \"string\" } },\n [\"field\"],\n (args) => {\n const name = String(args.field ?? \"\");\n if (!adapter.getFields().find((f) => f.name === name)) {\n return errorResult(`Unknown field: ${name}`);\n }\n const value = adapter.getValue(name);\n return textResult(JSON.stringify(value), { field: name, value });\n },\n false,\n );\n\n reg(\n \"form_get_values\",\n \"Read every field's current value as a JSON object.\",\n {},\n [],\n () => {\n const values = adapter.getValues();\n return textResult(JSON.stringify(values, null, 2), values);\n },\n false,\n );\n\n // ───────────── Mutation tools ─────────────\n\n reg(\n \"form_set_value\",\n \"Set one field's value. The host's controlled state updates and the human sees the field change.\",\n {\n field: { type: \"string\" },\n value: { description: \"Value to set. Type depends on the field's `type`.\" },\n },\n [\"field\", \"value\"],\n (args) => {\n const name = String(args.field ?? \"\");\n const fieldDef = adapter.getFields().find((f) => f.name === name);\n if (!fieldDef) return errorResult(`Unknown field: ${name}`);\n adapter.setValue(name, args.value);\n return textResult(`${name} ← ${JSON.stringify(args.value)}`, { field: name, value: args.value });\n },\n true,\n );\n\n reg(\n \"form_set_values\",\n \"Set multiple fields atomically. Pass a `values` object keyed by field name.\",\n { values: { type: \"object\" } },\n [\"values\"],\n (args) => {\n const values = (args.values && typeof args.values === \"object\") ? args.values as Record<string, unknown> : {};\n const fields = adapter.getFields();\n const known = new Set(fields.map((f) => f.name));\n const unknownKeys = Object.keys(values).filter((k) => !known.has(k));\n if (unknownKeys.length) return errorResult(`Unknown fields: ${unknownKeys.join(\", \")}`);\n if (adapter.setValues) {\n adapter.setValues(values);\n } else {\n for (const [k, v] of Object.entries(values)) adapter.setValue(k, v);\n }\n return textResult(`Set ${Object.keys(values).length} field(s)`, { values });\n },\n true,\n );\n\n reg(\n \"form_focus\",\n \"Move browser focus to a field (host-implemented). Useful before streaming text into it.\",\n { field: { type: \"string\" } },\n [\"field\"],\n (args) => {\n const name = String(args.field ?? \"\");\n if (!adapter.focus) return errorResult(\"Host did not provide a focus implementation.\");\n if (!adapter.getFields().find((f) => f.name === name)) {\n return errorResult(`Unknown field: ${name}`);\n }\n adapter.focus(name);\n return textResult(`Focused ${name}`, { field: name });\n },\n true,\n );\n\n reg(\n \"form_submit\",\n \"Submit the form. Host returns ok + values (or an error). In pendingMode this is staged for the human to confirm first.\",\n {},\n [],\n async () => {\n if (!adapter.submit) return errorResult(\"Host did not provide a submit implementation.\");\n // Trust-but-verify: a form submit is a human-visible / often-destructive\n // action, so gate it on a human confirm when one is wired.\n if (pendingMode && adapter.confirm) {\n const ok = await adapter.confirm({\n action: \"submit\",\n form: formId,\n title: adapter.title,\n values: adapter.getValues(),\n });\n if (!ok) return errorResult(\"Declined by user\");\n }\n const result = await adapter.submit();\n if (!result.ok) return errorResult(result.error ?? \"Submit failed\");\n return textResult(\"Submitted\", { values: result.values });\n },\n true,\n );\n\n return {\n id: `form:${formId}`,\n title: adapter.title ?? formId,\n dispose: () => {\n for (const d of disposers) d();\n },\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { ensureUndoToolsRegistered } from './chunk-CT3LRNH7.js';
2
- import { wrapToolWithActivity } from './chunk-ULJL53DL.js';
2
+ import { wrapToolWithActivity } from './chunk-2VENWGLZ.js';
3
3
  import { textResult, errorResult } from './chunk-DF3PLL2E.js';
4
4
 
5
5
  // src/bridges/terminal.ts
@@ -7,16 +7,15 @@ var DEFAULT_AGENT = { id: "agent", name: "Agent", color: "#a855f7" };
7
7
  var truncate = (s, n = 60) => s.length > n ? s.slice(0, n) + "\u2026" : s;
8
8
  function registerTerminalBridge(host, options) {
9
9
  const agent = { ...DEFAULT_AGENT, ...options.agent ?? {} };
10
- const pendingMode = options.pendingMode ?? false;
10
+ const pendingMode = options.pendingMode ?? true;
11
11
  const screenId = options.screenId ?? options.adapter?.screenId;
12
12
  const disposers = [];
13
13
  const staged = /* @__PURE__ */ new Map();
14
14
  let seq = 0;
15
15
  ensureUndoToolsRegistered(host);
16
16
  const listTerminals = () => {
17
- if (options.terminals) return options.terminals();
18
- if (options.adapter) return [{ id: "terminal", label: "Terminal", active: true, ...options.adapter }];
19
- return [];
17
+ const all = options.terminals ? options.terminals() : options.adapter ? [{ id: "terminal", label: "Terminal", active: true, ...options.adapter }] : [];
18
+ return options.canAccess ? all.filter((t) => options.canAccess(t.id)) : all;
20
19
  };
21
20
  const resolve = (id) => {
22
21
  const list = listTerminals();
@@ -33,6 +32,17 @@ function registerTerminalBridge(host, options) {
33
32
  elementId: terminalId ?? screenId ?? "terminal",
34
33
  label: label ?? "terminal"
35
34
  });
35
+ const redactMeta = (result) => {
36
+ const sc = result.structuredContent;
37
+ if (!sc || typeof sc !== "object") return void 0;
38
+ return {
39
+ terminal: sc.terminal,
40
+ kind: sc.kind,
41
+ length: typeof sc.data === "string" ? sc.data.length : void 0,
42
+ executed: sc.executed,
43
+ pending: sc.pending
44
+ };
45
+ };
36
46
  const TERMINAL_ARG = {
37
47
  terminal: {
38
48
  type: "string",
@@ -52,7 +62,12 @@ function registerTerminalBridge(host, options) {
52
62
  agent,
53
63
  kind: "terminal",
54
64
  screenId,
55
- resolveTarget: ({ args, result }) => resolveTarget?.(args, result) ?? target()
65
+ // A per-call resolver may return null to SKIP the broadcast (e.g. a
66
+ // merely-staged command); only fall back to the default target when no
67
+ // resolver was supplied.
68
+ resolveTarget: ({ args, result }) => resolveTarget ? resolveTarget(args, result) : target(),
69
+ // Never fan raw command/keystroke bytes to peers — broadcast shape only.
70
+ buildMeta: redactMeta
56
71
  }) : wrapped;
57
72
  disposers.push(
58
73
  host.registerTool(
@@ -89,6 +104,7 @@ function registerTerminalBridge(host, options) {
89
104
  return textResult(`${kind === "run" ? "ran" : "wrote"} on ${t.id}: ${truncate(data)}`, {
90
105
  kind,
91
106
  data,
107
+ length: data.length,
92
108
  terminal: t.id,
93
109
  executed: true
94
110
  });
@@ -99,7 +115,7 @@ function registerTerminalBridge(host, options) {
99
115
  options.onPending?.(entry);
100
116
  return textResult(
101
117
  `Staged ${kind} on ${t.id} (id ${id}) \u2014 awaiting human confirmation: ${truncate(data)}`,
102
- { ...entry, pending: true }
118
+ { ...entry, length: data.length, pending: true }
103
119
  );
104
120
  }
105
121
  reg(
@@ -144,12 +160,13 @@ function registerTerminalBridge(host, options) {
144
160
  );
145
161
  reg(
146
162
  "terminal_write",
147
- "Write raw data / keystrokes to a terminal (input, control chars, ANSI). Pass `terminal` to target a specific one. In pendingMode this stages instead of executing.",
163
+ "Write raw data / keystrokes to a terminal (input, control chars, ANSI). Pass `terminal` to target a specific one. In pendingMode this stages instead of executing. NOTE: bytes are written verbatim \u2014 an embedded CR runs a command, and ANSI/OSC sequences reach the terminal; treat this exactly like terminal_run for gating.",
148
164
  { ...TERMINAL_ARG, data: { type: "string", description: "Raw bytes to write." } },
149
165
  ["data"],
150
166
  (args) => stageOrExec(need(args), "write", String(args.data)),
151
167
  true,
152
- (args) => target(`write:${String(args.terminal ?? "")}`, resolve(args.terminal)?.id)
168
+ // Skip the peer broadcast while only staged; emit once it actually executes.
169
+ (args, result) => result?.structuredContent?.pending ? null : target(`write:${String(args.terminal ?? "")}`, resolve(args.terminal)?.id)
153
170
  );
154
171
  reg(
155
172
  "terminal_run",
@@ -158,41 +175,47 @@ function registerTerminalBridge(host, options) {
158
175
  ["command"],
159
176
  (args) => stageOrExec(need(args), "run", String(args.command)),
160
177
  true,
161
- (args) => target(truncate(String(args.command ?? "")), resolve(args.terminal)?.id)
162
- );
163
- reg(
164
- "terminal_confirm",
165
- "Confirm + execute a staged command by id (pendingMode).",
166
- { id: { type: "string" } },
167
- ["id"],
168
- async (args) => {
169
- const id = String(args.id);
170
- const entry = staged.get(id);
171
- if (!entry) return errorResult(`No staged command ${id}`);
172
- const t = resolve(entry.terminalId);
173
- if (!t) return errorResult(`Terminal '${entry.terminalId}' is gone \u2014 cannot run ${id}`);
174
- staged.delete(id);
175
- await exec(t, entry.kind, entry.data);
176
- return textResult(`Confirmed ${id}: ${entry.kind} on ${t.id} ${truncate(entry.data)}`, { ...entry, executed: true });
177
- },
178
- true,
179
- (args) => {
180
- const e = staged.get(String(args.id));
181
- return target(`confirm:${String(args.id ?? "")}`, e?.terminalId);
182
- }
183
- );
184
- reg(
185
- "terminal_reject",
186
- "Drop a staged command by id without executing it.",
187
- { id: { type: "string" } },
188
- ["id"],
189
- (args) => {
190
- const id = String(args.id);
191
- if (!staged.delete(id)) return errorResult(`No staged command ${id}`);
192
- return textResult(`Rejected ${id}`, { id, rejected: true });
193
- },
194
- false
178
+ (args, result) => result?.structuredContent?.pending ? null : target(truncate(String(args.command ?? "")), resolve(args.terminal)?.id)
195
179
  );
180
+ if (options.allowAgentConfirm) {
181
+ reg(
182
+ "terminal_confirm",
183
+ "Confirm + execute a staged command by id (pendingMode).",
184
+ { id: { type: "string" } },
185
+ ["id"],
186
+ async (args) => {
187
+ const id = String(args.id);
188
+ const entry = staged.get(id);
189
+ if (!entry) return errorResult(`No staged command ${id}`);
190
+ const t = resolve(entry.terminalId);
191
+ if (!t) return errorResult(`Terminal '${entry.terminalId}' is gone \u2014 cannot run ${id}`);
192
+ staged.delete(id);
193
+ await exec(t, entry.kind, entry.data);
194
+ return textResult(`Confirmed ${id}: ${entry.kind} on ${t.id} ${truncate(entry.data)}`, {
195
+ ...entry,
196
+ length: entry.data.length,
197
+ executed: true
198
+ });
199
+ },
200
+ true,
201
+ (args) => {
202
+ const e = staged.get(String(args.id));
203
+ return target(`confirm:${String(args.id ?? "")}`, e?.terminalId);
204
+ }
205
+ );
206
+ reg(
207
+ "terminal_reject",
208
+ "Drop a staged command by id without executing it.",
209
+ { id: { type: "string" } },
210
+ ["id"],
211
+ (args) => {
212
+ const id = String(args.id);
213
+ if (!staged.delete(id)) return errorResult(`No staged command ${id}`);
214
+ return textResult(`Rejected ${id}`, { id, rejected: true });
215
+ },
216
+ false
217
+ );
218
+ }
196
219
  if (canClear) {
197
220
  reg(
198
221
  "terminal_clear",
@@ -237,8 +260,10 @@ function registerTerminalBridge(host, options) {
237
260
  if (!t.setShell) return errorResult(`Terminal '${t.id}' can't switch shells.`);
238
261
  const id = String(args.id);
239
262
  const shells = t.listShells?.();
240
- if (shells && shells.length && !shells.some((s) => s.id === id)) {
241
- return errorResult(`Unknown shell '${id}' for ${t.id}. Use terminal_list_shells for valid ids.`);
263
+ if (!shells || !shells.some((s) => s.id === id)) {
264
+ return errorResult(
265
+ `Unknown or unlisted shell '${id}' for ${t.id}. Call terminal_list_shells for valid ids.`
266
+ );
242
267
  }
243
268
  await t.setShell(id);
244
269
  return textResult(`Switched ${t.id} shell to ${id}`, { shell: id, terminal: t.id });
@@ -271,5 +296,5 @@ function registerTerminalBridge(host, options) {
271
296
  }
272
297
 
273
298
  export { registerTerminalBridge };
274
- //# sourceMappingURL=chunk-KKGC4ERF.js.map
275
- //# sourceMappingURL=chunk-KKGC4ERF.js.map
299
+ //# sourceMappingURL=chunk-UZHNKUER.js.map
300
+ //# sourceMappingURL=chunk-UZHNKUER.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bridges/terminal.ts"],"names":[],"mappings":"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","file":"chunk-UZHNKUER.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { CallToolResult, JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\nimport type { AgentTarget } from \"../presence/types\";\n\n/**\n * A shell/profile an agent can switch a terminal to. Mirrors fancy-term's\n * `ShellProfile` (kept local so the bridge never imports fancy-term).\n */\nexport type TerminalShell = { id: string; label: string; icon?: string };\n\n/**\n * One terminal the bridge can drive. A Human+ app often hosts **several**\n * terminals on a screen (a build pane, a server pane, an agent scratch shell);\n * each is a `TerminalRef` with a stable `id` so an agent can read/write any of\n * them — not just \"its own\". Wire the function fields to that terminal's\n * fancy-term `TerminalHandle`.\n */\nexport type TerminalRef = {\n /** Stable id used to address this terminal (`terminal_list` enumerates them). */\n id: string;\n /** Human label, e.g. \"Build\", \"Server\". Defaults to the id. */\n label?: string;\n /** True for the focused terminal — the default target when no id is passed. */\n active?: boolean;\n /** Read the visible buffer as text (wire to `TerminalHandle.getBuffer`). */\n getBuffer: () => string;\n /** Write raw data / keystrokes (wire to `TerminalHandle.write`). */\n write: (data: string) => void;\n /** Run a command. Defaults to writing `${command}\\r`; override for a real runner. */\n runCommand?: (command: string) => void | Promise<void>;\n /** Clear the viewport (wire to `TerminalHandle.clear`). */\n clear?: () => void;\n /** Current text selection (wire to `TerminalHandle.getSelection`). */\n getSelection?: () => string;\n /** Shells this terminal offers (cmd, PowerShell, …). */\n listShells?: () => TerminalShell[];\n /** Switch this terminal's active shell by id. */\n setShell?: (id: string) => void | Promise<void>;\n /** This terminal's active shell id. */\n getShell?: () => string | undefined;\n};\n\n/**\n * Single-terminal adapter (back-compat). A `TerminalRef` without the\n * `id`/`label`/`active` bookkeeping — pass it as `{ adapter }` and the bridge\n * treats it as the one (active) terminal. Use `{ terminals }` for multiple.\n */\nexport type TerminalBridgeAdapter = Omit<TerminalRef, \"id\" | \"label\" | \"active\"> & {\n /** fancy-screens screen id (optional) so activity events know which screen the terminal lives in. */\n screenId?: string;\n};\n\ntype StagedKind = \"write\" | \"run\";\ntype Staged = { id: string; kind: StagedKind; data: string; terminalId: string };\n\nexport type TerminalBridgeOptions = {\n /** A single terminal (back-compat). Mutually exclusive with `terminals`. */\n adapter?: TerminalBridgeAdapter;\n /**\n * The live list of terminals on the screen. Use this when the app hosts more\n * than one terminal so an agent can `terminal_list` then target any of them by\n * id — i.e. reach into another terminal in the same screen.\n */\n terminals?: () => TerminalRef[];\n /** fancy-screens screen id for activity events (defaults to `adapter.screenId`). */\n screenId?: string;\n agent?: { id: string; name?: string; color?: string };\n /**\n * Trust-but-verify (Human+ contract for inhabited surfaces). When on,\n * `terminal_write` + `terminal_run` don't execute — they **stage** the command\n * (returning a pending id) and fire `onPending`. A human confirms via the\n * returned bridge's `confirm(id)` (wire it to a human-only control).\n *\n * **Default: ON.** The terminal is the most dangerous surface (arbitrary shell),\n * and possession of the relay session token = permission to call every tool, so\n * it must fail SAFE. Pass `false` only for a fully-trusted, non-shared terminal\n * where auto-execution is acceptable. A host that leaves this on MUST wire a\n * human confirm path (`onPending` + `bridge.confirm`), or staged commands never run.\n */\n pendingMode?: boolean;\n /** Notified when a command is staged (pendingMode) — show it + offer confirm / reject. */\n onPending?: (pending: Staged) => void;\n /**\n * Expose `terminal_confirm` / `terminal_reject` as agent-callable tools.\n * **Default: false** — otherwise the *same* agent that staged a command could\n * confirm it, defeating the human-in-the-loop. Leave off and confirm via the\n * returned `bridge.confirm(id)` wired to a human control.\n */\n allowAgentConfirm?: boolean;\n /**\n * Per-terminal authorization. Return false to hide a terminal id from this\n * agent entirely (it won't appear in `terminal_list` and can't be targeted).\n * Use it to scope an agent to its own pane(s); without it, `{ terminals }`\n * grants the agent full read/write over EVERY terminal in the list.\n */\n canAccess?: (terminalId: string) => boolean;\n};\n\nexport type TerminalBridge = Bridge & {\n /** Execute a staged command by id — wire a host confirm button to this. No-op if not pending. */\n confirm: (id: string) => void;\n /** Drop a staged command by id without executing. */\n reject: (id: string) => void;\n /** Commands currently awaiting confirmation. */\n pending: () => Staged[];\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\nconst truncate = (s: string, n = 60): string => (s.length > n ? s.slice(0, n) + \"…\" : s);\n\n/**\n * registerTerminalBridge — MCP access to one **or many** terminal surfaces on a\n * screen. An agent reads the visible buffer (`terminal_read`), writes input\n * (`terminal_write`), and runs commands (`terminal_run`) through the host; every\n * mutation broadcasts an `AgentActivity` event. With `pendingMode`, destructive\n * actions are staged for human confirmation (`terminal_confirm` / `terminal_reject`\n * / `terminal_pending`).\n *\n * **Multi-terminal:** pass `{ terminals }` (vs a single `{ adapter }`) and every\n * tool takes an optional `terminal` id; `terminal_list` enumerates them. This is\n * how an agent **reaches into another terminal in the same screen** rather than\n * being stuck in one. When a terminal offers shells, the agent can also list\n * (`terminal_list_shells`) and switch (`terminal_set_shell`) its shell. Tool\n * prefix `terminal_*`.\n */\nexport function registerTerminalBridge(host: ToolHost, options: TerminalBridgeOptions): TerminalBridge {\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n // Safe-by-default: the terminal stages for human confirmation unless a host\n // explicitly opts a trusted, non-shared terminal into auto-exec (see the\n // pendingMode docs). Every other write bridge already defaults to staged.\n const pendingMode = options.pendingMode ?? true;\n const screenId = options.screenId ?? options.adapter?.screenId;\n const disposers: Array<() => void> = [];\n const staged = new Map<string, Staged>();\n let seq = 0;\n\n // Enables agent_history (a log of what agents did across every bridge).\n ensureUndoToolsRegistered(host);\n\n // The live terminal list — from `terminals()` (multi) or the single `adapter`\n // normalized to one active ref with the id \"terminal\".\n const listTerminals = (): TerminalRef[] => {\n const all = options.terminals\n ? options.terminals()\n : options.adapter\n ? [{ id: \"terminal\", label: \"Terminal\", active: true, ...options.adapter }]\n : [];\n // Per-terminal ACL: an agent can only see/target terminals it's allowed to.\n return options.canAccess ? all.filter((t) => options.canAccess!(t.id)) : all;\n };\n\n /** Resolve a terminal by id; with no id, the active one, else the first. */\n const resolve = (id?: unknown): TerminalRef | undefined => {\n const list = listTerminals();\n if (typeof id === \"string\" && id !== \"\") return list.find((t) => t.id === id);\n return list.find((t) => t.active) ?? list[0];\n };\n\n // Whether any host config can offer these capabilities (gates tool registration;\n // per-call we still check the *resolved* terminal supports it).\n const anyMulti = !!options.terminals;\n const canClear = anyMulti || !!options.adapter?.clear;\n const canShells = anyMulti || !!options.adapter?.listShells;\n const canSetShell = anyMulti || !!options.adapter?.setShell;\n\n const target = (label?: string, terminalId?: string): AgentTarget => ({\n kind: \"terminal\",\n screenId,\n elementId: terminalId ?? screenId ?? \"terminal\",\n label: label ?? \"terminal\",\n });\n\n // Broadcast meta for terminal mutations: shape only, never the raw command /\n // keystroke bytes (those may hold secrets, and the relay fans meta to every\n // peer). Full data stays local to the tool result + onPending / bridge.confirm.\n const redactMeta = (result: CallToolResult): Record<string, unknown> | undefined => {\n const sc = result.structuredContent as Record<string, unknown> | undefined;\n if (!sc || typeof sc !== \"object\") return undefined;\n return {\n terminal: sc.terminal,\n kind: sc.kind,\n length: typeof sc.data === \"string\" ? (sc.data as string).length : undefined,\n executed: sc.executed,\n pending: sc.pending,\n };\n };\n\n const TERMINAL_ARG = {\n terminal: {\n type: \"string\",\n description: \"Terminal id to target (call terminal_list for ids). Omit for the active / only terminal.\",\n },\n };\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n isMutation: boolean,\n resolveTarget?: (args: JsonObject, result: any) => AgentTarget | null,\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = isMutation\n ? wrapToolWithActivity(wrapped, {\n toolName: name,\n agent,\n kind: \"terminal\",\n screenId,\n // A per-call resolver may return null to SKIP the broadcast (e.g. a\n // merely-staged command); only fall back to the default target when no\n // resolver was supplied.\n resolveTarget: ({ args, result }) => (resolveTarget ? resolveTarget(args, result) : target()),\n // Never fan raw command/keystroke bytes to peers — broadcast shape only.\n buildMeta: redactMeta,\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false },\n },\n final as any,\n ),\n );\n };\n\n /** Resolve the targeted terminal or throw a clear error for the agent. */\n const need = (args: JsonObject): TerminalRef => {\n const t = resolve(args.terminal);\n if (!t) {\n const ids = listTerminals().map((x) => x.id).join(\", \") || \"(none)\";\n throw new Error(\n typeof args.terminal === \"string\" && args.terminal\n ? `Unknown terminal '${args.terminal}'. Available: ${ids}. Use terminal_list.`\n : \"No terminal available.\",\n );\n }\n return t;\n };\n\n async function exec(t: TerminalRef, kind: StagedKind, data: string): Promise<void> {\n if (kind === \"run\") {\n if (t.runCommand) await t.runCommand(data);\n else t.write(data + \"\\r\");\n } else {\n t.write(data);\n }\n }\n\n async function stageOrExec(t: TerminalRef, kind: StagedKind, data: string) {\n // The human-facing summary truncates for readability, but the full payload\n // + its length ride in structuredContent / onPending so a confirm UI never\n // silently under-shows a long escape/injection payload.\n if (!pendingMode) {\n await exec(t, kind, data);\n return textResult(`${kind === \"run\" ? \"ran\" : \"wrote\"} on ${t.id}: ${truncate(data)}`, {\n kind,\n data,\n length: data.length,\n terminal: t.id,\n executed: true,\n });\n }\n const id = `t${++seq}`;\n const entry: Staged = { id, kind, data, terminalId: t.id };\n staged.set(id, entry);\n options.onPending?.(entry);\n return textResult(\n `Staged ${kind} on ${t.id} (id ${id}) — awaiting human confirmation: ${truncate(data)}`,\n { ...entry, length: data.length, pending: true },\n );\n }\n\n // ── List ──────────────────────────────────────────────────────────────────\n reg(\n \"terminal_list\",\n \"List the terminals on this screen (id, label, which is active) — so you can reach into another terminal, not just the active one. Pass the chosen id as `terminal` to the other tools.\",\n {},\n [],\n () => {\n const list = listTerminals().map((t) => ({ id: t.id, label: t.label ?? t.id, active: !!t.active }));\n const text = list.length\n ? list.map((t) => `${t.active ? \"* \" : \" \"}${t.id} — ${t.label}`).join(\"\\n\")\n : \"(no terminals)\";\n return textResult(text, { terminals: list });\n },\n false,\n );\n\n // ── Read ──────────────────────────────────────────────────────────────────\n reg(\n \"terminal_read\",\n \"Read a terminal's visible buffer as text — what the user sees. Pass `tail` for only the last N lines, `terminal` to read a specific one.\",\n { ...TERMINAL_ARG, tail: { type: \"number\", description: \"Return only the last N lines.\" } },\n [],\n (args) => {\n const t = need(args);\n let buf = t.getBuffer();\n const tail = typeof args.tail === \"number\" ? args.tail : undefined;\n if (tail && tail > 0) buf = buf.split(\"\\n\").slice(-tail).join(\"\\n\");\n return textResult(buf, { buffer: buf, terminal: t.id });\n },\n false,\n );\n\n reg(\n \"terminal_pending\",\n \"List commands staged for human confirmation (pendingMode).\",\n {},\n [],\n () => {\n const list = [...staged.values()];\n return textResult(\n list.length ? list.map((s) => `${s.id}: ${s.kind} on ${s.terminalId} ${truncate(s.data)}`).join(\"\\n\") : \"(none)\",\n { pending: list },\n );\n },\n false,\n );\n\n // ── Mutations ───────────────────────────────────────────────────────────────\n reg(\n \"terminal_write\",\n \"Write raw data / keystrokes to a terminal (input, control chars, ANSI). Pass `terminal` to target a specific one. In pendingMode this stages instead of executing. NOTE: bytes are written verbatim — an embedded CR runs a command, and ANSI/OSC sequences reach the terminal; treat this exactly like terminal_run for gating.\",\n { ...TERMINAL_ARG, data: { type: \"string\", description: \"Raw bytes to write.\" } },\n [\"data\"],\n (args) => stageOrExec(need(args), \"write\", String(args.data)),\n true,\n // Skip the peer broadcast while only staged; emit once it actually executes.\n (args, result) =>\n result?.structuredContent?.pending ? null : target(`write:${String(args.terminal ?? \"\")}`, resolve(args.terminal)?.id),\n );\n\n reg(\n \"terminal_run\",\n \"Run a shell command in a terminal — writes the command + Enter (or the host's runner). Pass `terminal` to target a specific one. In pendingMode this stages it for confirmation.\",\n { ...TERMINAL_ARG, command: { type: \"string\", description: \"The command line to run.\" } },\n [\"command\"],\n (args) => stageOrExec(need(args), \"run\", String(args.command)),\n true,\n (args, result) =>\n result?.structuredContent?.pending ? null : target(truncate(String(args.command ?? \"\")), resolve(args.terminal)?.id),\n );\n\n // Confirmation is HUMAN-driven by default: the acting agent must not be able to\n // confirm its own staged command (that would defeat pendingMode). Hosts confirm\n // via the returned `bridge.confirm(id)` wired to a human control. Only expose\n // the agent-callable tools when a host explicitly opts in.\n if (options.allowAgentConfirm) {\n reg(\n \"terminal_confirm\",\n \"Confirm + execute a staged command by id (pendingMode).\",\n { id: { type: \"string\" } },\n [\"id\"],\n async (args) => {\n const id = String(args.id);\n const entry = staged.get(id);\n if (!entry) return errorResult(`No staged command ${id}`);\n const t = resolve(entry.terminalId);\n if (!t) return errorResult(`Terminal '${entry.terminalId}' is gone — cannot run ${id}`);\n staged.delete(id);\n await exec(t, entry.kind, entry.data);\n return textResult(`Confirmed ${id}: ${entry.kind} on ${t.id} ${truncate(entry.data)}`, {\n ...entry,\n length: entry.data.length,\n executed: true,\n });\n },\n true,\n (args) => {\n const e = staged.get(String(args.id));\n return target(`confirm:${String(args.id ?? \"\")}`, e?.terminalId);\n },\n );\n\n reg(\n \"terminal_reject\",\n \"Drop a staged command by id without executing it.\",\n { id: { type: \"string\" } },\n [\"id\"],\n (args) => {\n const id = String(args.id);\n if (!staged.delete(id)) return errorResult(`No staged command ${id}`);\n return textResult(`Rejected ${id}`, { id, rejected: true });\n },\n false,\n );\n }\n\n if (canClear) {\n reg(\n \"terminal_clear\",\n \"Clear a terminal's viewport. Pass `terminal` to target a specific one.\",\n { ...TERMINAL_ARG },\n [],\n (args) => {\n const t = need(args);\n if (!t.clear) return errorResult(`Terminal '${t.id}' can't be cleared.`);\n t.clear();\n return textResult(`cleared ${t.id}`, { terminal: t.id });\n },\n true,\n (args) => target(`clear:${String(args.terminal ?? \"\")}`, resolve(args.terminal)?.id),\n );\n }\n\n // ── Shells ──────────────────────────────────────────────────────────────────\n if (canShells) {\n reg(\n \"terminal_list_shells\",\n \"List the shells a terminal can switch to (cmd, PowerShell, Git Bash, …) — id + label, active one marked. Pass `terminal` to target a specific one.\",\n { ...TERMINAL_ARG },\n [],\n (args) => {\n const t = need(args);\n if (!t.listShells) return errorResult(`Terminal '${t.id}' has no switchable shells.`);\n const shells = t.listShells();\n const active = t.getShell?.();\n const text = shells.length\n ? shells.map((s) => `${s.id === active ? \"* \" : \" \"}${s.id} — ${s.label}`).join(\"\\n\")\n : \"(none)\";\n return textResult(text, { shells, active, terminal: t.id });\n },\n false,\n );\n }\n\n if (canSetShell) {\n reg(\n \"terminal_set_shell\",\n \"Switch a terminal's active shell by id (e.g. 'powershell', 'git-bash'). Call terminal_list_shells first for valid ids. Pass `terminal` to target a specific one.\",\n { ...TERMINAL_ARG, id: { type: \"string\", description: \"Shell id to switch to.\" } },\n [\"id\"],\n async (args) => {\n const t = need(args);\n if (!t.setShell) return errorResult(`Terminal '${t.id}' can't switch shells.`);\n const id = String(args.id);\n // Fail closed: only allow a shell that is explicitly listed. A terminal\n // exposing setShell without listShells (or with an empty list) rejects\n // every id, so an unvalidated agent string can never reach setShell\n // (which a host may map to an executable = arbitrary-binary launch).\n const shells = t.listShells?.();\n if (!shells || !shells.some((s) => s.id === id)) {\n return errorResult(\n `Unknown or unlisted shell '${id}' for ${t.id}. Call terminal_list_shells for valid ids.`,\n );\n }\n await t.setShell(id);\n return textResult(`Switched ${t.id} shell to ${id}`, { shell: id, terminal: t.id });\n },\n true,\n (args) => target(`shell:${String(args.id ?? \"\")}`, resolve(args.terminal)?.id),\n );\n }\n\n return {\n id: \"terminal\",\n title: \"Terminal\",\n dispose: () => {\n disposers.forEach((d) => d());\n disposers.length = 0;\n staged.clear();\n },\n confirm: (id: string) => {\n const e = staged.get(id);\n if (e) {\n const t = resolve(e.terminalId);\n staged.delete(id);\n if (t) void exec(t, e.kind, e.data);\n }\n },\n reject: (id: string) => {\n staged.delete(id);\n },\n pending: () => [...staged.values()],\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { ensureUndoToolsRegistered } from './chunk-CT3LRNH7.js';
2
- import { wrapToolWithActivity } from './chunk-ULJL53DL.js';
2
+ import { wrapToolWithActivity } from './chunk-2VENWGLZ.js';
3
3
  import { textResult, errorResult } from './chunk-DF3PLL2E.js';
4
4
 
5
5
  // src/bridges/sheets.ts
@@ -271,5 +271,5 @@ function readRange(sheet, startAddr, endAddr) {
271
271
  }
272
272
 
273
273
  export { registerSheetsBridge };
274
- //# sourceMappingURL=chunk-UTUVN6HQ.js.map
275
- //# sourceMappingURL=chunk-UTUVN6HQ.js.map
274
+ //# sourceMappingURL=chunk-WCKSDFTM.js.map
275
+ //# sourceMappingURL=chunk-WCKSDFTM.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bridges/sheets.ts"],"names":[],"mappings":"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","file":"chunk-UTUVN6HQ.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\nimport type { AgentTarget } from \"../presence/types\";\nimport type { CellValue, SheetData, SheetOp, WorkbookData } from \"@particle-academy/fancy-sheets\";\n\n/**\n * Cell writes funnel through fancy-sheets' own `reduceWorkbook` + `SheetOp` —\n * the same reducer that drives `<SheetWorkbook>` — so agent edits recalculate\n * formulas and land byte-identical to human edits, mirroring how the slides\n * bridge works. Types come straight from the package (no drift); the reducer\n * VALUE is lazy-imported inside the mutation handlers so the package barrel\n * never statically pulls this optional peer (see issue #3).\n */\n\nexport type SheetsBridgeAdapter = {\n /** fancy-screens screen id (optional) so activity events know which screen the sheet lives in. */\n screenId?: string;\n /** Read the current workbook. */\n getWorkbook: () => WorkbookData;\n /** Replace the workbook. Host wires this to its onChange. */\n setWorkbook: (next: WorkbookData) => void;\n /** Optional: programmatically change the active cell. */\n setActiveCell?: (sheetId: string, address: string) => void;\n};\n\nexport type SheetsBridgeOptions = {\n adapter: SheetsBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * registerSheetsBridge — schema-aware MCP access to a fancy-sheets workbook.\n * Tools are sheet-aware (every mutator takes an explicit `sheet` id, defaulting\n * to the active sheet when omitted) so an agent can author multi-sheet docs.\n */\nexport function registerSheetsBridge(\n host: ToolHost,\n options: SheetsBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const disposers: Array<() => void> = [];\n\n // agent_undo / agent_redo / agent_history are registered whenever any bridge\n // mounts, so undo availability doesn't hinge on which bridges are co-present.\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (sheetId: string, address?: string): AgentTarget => ({\n kind: \"sheet\",\n screenId: adapter.screenId,\n elementId: address ? `${sheetId}!${address}` : sheetId,\n label: address ? `${sheetId}!${address}` : sheetId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n isMutation: boolean,\n resolveTarget?: (args: JsonObject, result: any) => AgentTarget | null,\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = isMutation\n ? wrapToolWithActivity(wrapped, {\n toolName: name,\n agent,\n kind: \"sheet\",\n screenId: adapter.screenId,\n resolveTarget: ({ args, result }) =>\n resolveTarget?.(args, result) ?? target(getSheetId(args)),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false },\n },\n final as any,\n ),\n );\n };\n\n function activeSheetId(): string {\n return adapter.getWorkbook().activeSheetId;\n }\n function getSheetId(args: JsonObject): string {\n return typeof args.sheet === \"string\" ? args.sheet : activeSheetId();\n }\n function getSheet(workbook: WorkbookData, sheetId: string): SheetData | undefined {\n return workbook.sheets.find((s) => s.id === sheetId);\n }\n\n // ───────────── Read tools ─────────────\n\n reg(\n \"sheet_describe\",\n \"Describe the workbook: every sheet's id, name, dimensions, cell count, active sheet. Call before reading or writing.\",\n {},\n [],\n () => {\n const wb = adapter.getWorkbook();\n const summary = {\n activeSheetId: wb.activeSheetId,\n sheets: wb.sheets.map((s) => ({\n id: s.id,\n name: s.name,\n cellCount: Object.keys(s.cells).length,\n columnCount: Object.keys(s.columnWidths).length,\n frozenRows: s.frozenRows,\n frozenCols: s.frozenCols,\n })),\n };\n const text = `Active: ${summary.activeSheetId}\\n` + summary.sheets\n .map((s) => `${s.id} \"${s.name}\" — ${s.cellCount} cells`)\n .join(\"\\n\");\n return textResult(text, summary);\n },\n false,\n );\n\n reg(\n \"sheet_get_cell\",\n \"Read a single cell's raw + computed value.\",\n {\n sheet: { type: \"string\", description: \"Sheet id (defaults to active).\" },\n address: { type: \"string\", description: \"A1-style address, e.g. \\\"B12\\\".\" },\n },\n [\"address\"],\n (args) => {\n const sheetId = getSheetId(args);\n const address = String(args.address);\n const sheet = getSheet(adapter.getWorkbook(), sheetId);\n if (!sheet) return errorResult(`No sheet ${sheetId}`);\n const cell = sheet.cells[address];\n if (!cell) {\n return textResult(`(empty)`, { sheet: sheetId, address, value: null });\n }\n return textResult(`${address} = ${JSON.stringify(cell.computedValue ?? cell.value)}`, { ...cell, sheet: sheetId, address });\n },\n false,\n );\n\n reg(\n \"sheet_get_range\",\n \"Read a rectangular range as a 2D array of values.\",\n {\n sheet: { type: \"string\" },\n start: { type: \"string\", description: \"Top-left A1 address.\" },\n end: { type: \"string\", description: \"Bottom-right A1 address.\" },\n },\n [\"start\", \"end\"],\n (args) => {\n const sheetId = getSheetId(args);\n const sheet = getSheet(adapter.getWorkbook(), sheetId);\n if (!sheet) return errorResult(`No sheet ${sheetId}`);\n const grid = readRange(sheet, String(args.start), String(args.end));\n return textResult(JSON.stringify(grid), { sheet: sheetId, start: args.start, end: args.end, values: grid });\n },\n false,\n );\n\n // ───────────── Mutation tools ─────────────\n\n reg(\n \"sheet_set_cell\",\n \"Set a single cell's value. To set a formula, pass a string starting with '='.\",\n {\n sheet: { type: \"string\" },\n address: { type: \"string\" },\n value: { description: \"string | number | boolean | null. Strings starting with '=' are stored as formulas.\" },\n },\n [\"address\", \"value\"],\n async (args) => {\n const sheetId = getSheetId(args);\n const address = String(args.address);\n const value = args.value as CellValue;\n const wb = adapter.getWorkbook();\n if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n const { reduceWorkbook } = await import(\"@particle-academy/fancy-sheets\");\n adapter.setWorkbook(reduceWorkbook(wb, setCellOp(sheetId, address, value)));\n return textResult(`${sheetId}!${address} ← ${JSON.stringify(value)}`, { sheet: sheetId, address, value });\n },\n true,\n (args) => target(getSheetId(args), String(args.address ?? \"\")),\n );\n\n reg(\n \"sheet_set_range\",\n \"Set many cells atomically. `cells` is an object map of { \\\"A1\\\": value, \\\"B2\\\": value, ... }.\",\n {\n sheet: { type: \"string\" },\n cells: { type: \"object\" },\n },\n [\"cells\"],\n async (args) => {\n const sheetId = getSheetId(args);\n const wb = adapter.getWorkbook();\n if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n const cells = (args.cells && typeof args.cells === \"object\") ? args.cells as Record<string, CellValue> : {};\n const { reduceWorkbook } = await import(\"@particle-academy/fancy-sheets\");\n let next = wb;\n for (const [addr, v] of Object.entries(cells)) next = reduceWorkbook(next, setCellOp(sheetId, addr, v));\n adapter.setWorkbook(next);\n return textResult(`Set ${Object.keys(cells).length} cells in ${sheetId}`, { sheet: sheetId, count: Object.keys(cells).length });\n },\n true,\n );\n\n reg(\n \"sheet_add_sheet\",\n \"Add a new sheet (tab) to the workbook.\",\n { id: { type: \"string\" }, name: { type: \"string\" } },\n [\"id\", \"name\"],\n (args) => {\n const wb = adapter.getWorkbook();\n const id = String(args.id);\n const name = String(args.name);\n if (wb.sheets.find((s) => s.id === id)) return errorResult(`Sheet ${id} already exists`);\n const next: WorkbookData = {\n ...wb,\n sheets: [\n ...wb.sheets,\n {\n id, name, cells: {}, columnWidths: {}, mergedRegions: [],\n columnFilters: {}, frozenRows: 0, frozenCols: 0,\n },\n ],\n };\n adapter.setWorkbook(next);\n return textResult(`Added sheet ${id} (\"${name}\")`, { id, name });\n },\n true,\n (args) => target(String(args.id ?? \"\")),\n );\n\n reg(\n \"sheet_set_active\",\n \"Switch to a different sheet tab.\",\n { sheet: { type: \"string\" } },\n [\"sheet\"],\n (args) => {\n const sheetId = String(args.sheet);\n const wb = adapter.getWorkbook();\n if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n adapter.setWorkbook({ ...wb, activeSheetId: sheetId });\n return textResult(`Active sheet → ${sheetId}`, { sheet: sheetId });\n },\n true,\n );\n\n reg(\n \"sheet_set_active_cell\",\n \"Move the active cell selection (host implements DOM focus + scroll).\",\n { sheet: { type: \"string\" }, address: { type: \"string\" } },\n [\"address\"],\n (args) => {\n if (!adapter.setActiveCell) return errorResult(\"Host did not provide setActiveCell.\");\n const sheetId = getSheetId(args);\n adapter.setActiveCell(sheetId, String(args.address));\n return textResult(`Active cell → ${sheetId}!${args.address}`, { sheet: sheetId, address: args.address });\n },\n true,\n (args) => target(getSheetId(args), String(args.address ?? \"\")),\n );\n\n return {\n id: \"sheets\",\n title: \"Sheets\",\n dispose: () => {\n for (const d of disposers) d();\n },\n };\n}\n\n// ───────────── helpers ─────────────\n\n/** Build a `set_cell` op, treating a leading-\"=\" string as a formula — matching\n * the in-app editor (value keeps the raw \"=…\"; formula drops the \"=\"). */\nfunction setCellOp(sheet: string, address: string, value: CellValue): SheetOp {\n if (typeof value === \"string\" && value.startsWith(\"=\")) {\n return { type: \"set_cell\", sheet, address, value, formula: value.slice(1) };\n }\n return { type: \"set_cell\", sheet, address, value };\n}\n\n/** Parse \"B12\" → { col: 1, row: 11 }. Letters are 1-based, rows 1-based. */\nfunction parseAddress(addr: string): { col: number; row: number } {\n const m = /^([A-Za-z]+)(\\d+)$/.exec(addr.trim());\n if (!m) throw new Error(`Bad address: ${addr}`);\n const letters = m[1].toUpperCase();\n let col = 0;\n for (let i = 0; i < letters.length; i++) {\n col = col * 26 + (letters.charCodeAt(i) - 64);\n }\n return { col: col - 1, row: parseInt(m[2], 10) - 1 };\n}\n\nfunction colToLetter(col: number): string {\n let s = \"\";\n let n = col + 1;\n while (n > 0) {\n const r = (n - 1) % 26;\n s = String.fromCharCode(65 + r) + s;\n n = Math.floor((n - 1) / 26);\n }\n return s;\n}\n\nfunction readRange(sheet: SheetData, startAddr: string, endAddr: string): CellValue[][] {\n const start = parseAddress(startAddr);\n const end = parseAddress(endAddr);\n const r0 = Math.min(start.row, end.row);\n const r1 = Math.max(start.row, end.row);\n const c0 = Math.min(start.col, end.col);\n const c1 = Math.max(start.col, end.col);\n const grid: CellValue[][] = [];\n for (let r = r0; r <= r1; r++) {\n const row: CellValue[] = [];\n for (let c = c0; c <= c1; c++) {\n const addr = `${colToLetter(c)}${r + 1}`;\n const cell = sheet.cells[addr];\n row.push(cell?.computedValue ?? cell?.value ?? null);\n }\n grid.push(row);\n }\n return grid;\n}\n"]}
1
+ {"version":3,"sources":["../src/bridges/sheets.ts"],"names":[],"mappings":"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","file":"chunk-WCKSDFTM.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\nimport type { AgentTarget } from \"../presence/types\";\nimport type { CellValue, SheetData, SheetOp, WorkbookData } from \"@particle-academy/fancy-sheets\";\n\n/**\n * Cell writes funnel through fancy-sheets' own `reduceWorkbook` + `SheetOp` —\n * the same reducer that drives `<SheetWorkbook>` — so agent edits recalculate\n * formulas and land byte-identical to human edits, mirroring how the slides\n * bridge works. Types come straight from the package (no drift); the reducer\n * VALUE is lazy-imported inside the mutation handlers so the package barrel\n * never statically pulls this optional peer (see issue #3).\n */\n\nexport type SheetsBridgeAdapter = {\n /** fancy-screens screen id (optional) so activity events know which screen the sheet lives in. */\n screenId?: string;\n /** Read the current workbook. */\n getWorkbook: () => WorkbookData;\n /** Replace the workbook. Host wires this to its onChange. */\n setWorkbook: (next: WorkbookData) => void;\n /** Optional: programmatically change the active cell. */\n setActiveCell?: (sheetId: string, address: string) => void;\n};\n\nexport type SheetsBridgeOptions = {\n adapter: SheetsBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * registerSheetsBridge — schema-aware MCP access to a fancy-sheets workbook.\n * Tools are sheet-aware (every mutator takes an explicit `sheet` id, defaulting\n * to the active sheet when omitted) so an agent can author multi-sheet docs.\n */\nexport function registerSheetsBridge(\n host: ToolHost,\n options: SheetsBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const disposers: Array<() => void> = [];\n\n // agent_undo / agent_redo / agent_history are registered whenever any bridge\n // mounts, so undo availability doesn't hinge on which bridges are co-present.\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (sheetId: string, address?: string): AgentTarget => ({\n kind: \"sheet\",\n screenId: adapter.screenId,\n elementId: address ? `${sheetId}!${address}` : sheetId,\n label: address ? `${sheetId}!${address}` : sheetId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n isMutation: boolean,\n resolveTarget?: (args: JsonObject, result: any) => AgentTarget | null,\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = isMutation\n ? wrapToolWithActivity(wrapped, {\n toolName: name,\n agent,\n kind: \"sheet\",\n screenId: adapter.screenId,\n resolveTarget: ({ args, result }) =>\n resolveTarget?.(args, result) ?? target(getSheetId(args)),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false },\n },\n final as any,\n ),\n );\n };\n\n function activeSheetId(): string {\n return adapter.getWorkbook().activeSheetId;\n }\n function getSheetId(args: JsonObject): string {\n return typeof args.sheet === \"string\" ? args.sheet : activeSheetId();\n }\n function getSheet(workbook: WorkbookData, sheetId: string): SheetData | undefined {\n return workbook.sheets.find((s) => s.id === sheetId);\n }\n\n // ───────────── Read tools ─────────────\n\n reg(\n \"sheet_describe\",\n \"Describe the workbook: every sheet's id, name, dimensions, cell count, active sheet. Call before reading or writing.\",\n {},\n [],\n () => {\n const wb = adapter.getWorkbook();\n const summary = {\n activeSheetId: wb.activeSheetId,\n sheets: wb.sheets.map((s) => ({\n id: s.id,\n name: s.name,\n cellCount: Object.keys(s.cells).length,\n columnCount: Object.keys(s.columnWidths).length,\n frozenRows: s.frozenRows,\n frozenCols: s.frozenCols,\n })),\n };\n const text = `Active: ${summary.activeSheetId}\\n` + summary.sheets\n .map((s) => `${s.id} \"${s.name}\" — ${s.cellCount} cells`)\n .join(\"\\n\");\n return textResult(text, summary);\n },\n false,\n );\n\n reg(\n \"sheet_get_cell\",\n \"Read a single cell's raw + computed value.\",\n {\n sheet: { type: \"string\", description: \"Sheet id (defaults to active).\" },\n address: { type: \"string\", description: \"A1-style address, e.g. \\\"B12\\\".\" },\n },\n [\"address\"],\n (args) => {\n const sheetId = getSheetId(args);\n const address = String(args.address);\n const sheet = getSheet(adapter.getWorkbook(), sheetId);\n if (!sheet) return errorResult(`No sheet ${sheetId}`);\n const cell = sheet.cells[address];\n if (!cell) {\n return textResult(`(empty)`, { sheet: sheetId, address, value: null });\n }\n return textResult(`${address} = ${JSON.stringify(cell.computedValue ?? cell.value)}`, { ...cell, sheet: sheetId, address });\n },\n false,\n );\n\n reg(\n \"sheet_get_range\",\n \"Read a rectangular range as a 2D array of values.\",\n {\n sheet: { type: \"string\" },\n start: { type: \"string\", description: \"Top-left A1 address.\" },\n end: { type: \"string\", description: \"Bottom-right A1 address.\" },\n },\n [\"start\", \"end\"],\n (args) => {\n const sheetId = getSheetId(args);\n const sheet = getSheet(adapter.getWorkbook(), sheetId);\n if (!sheet) return errorResult(`No sheet ${sheetId}`);\n const grid = readRange(sheet, String(args.start), String(args.end));\n return textResult(JSON.stringify(grid), { sheet: sheetId, start: args.start, end: args.end, values: grid });\n },\n false,\n );\n\n // ───────────── Mutation tools ─────────────\n\n reg(\n \"sheet_set_cell\",\n \"Set a single cell's value. To set a formula, pass a string starting with '='.\",\n {\n sheet: { type: \"string\" },\n address: { type: \"string\" },\n value: { description: \"string | number | boolean | null. Strings starting with '=' are stored as formulas.\" },\n },\n [\"address\", \"value\"],\n async (args) => {\n const sheetId = getSheetId(args);\n const address = String(args.address);\n const value = args.value as CellValue;\n const wb = adapter.getWorkbook();\n if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n const { reduceWorkbook } = await import(\"@particle-academy/fancy-sheets\");\n adapter.setWorkbook(reduceWorkbook(wb, setCellOp(sheetId, address, value)));\n return textResult(`${sheetId}!${address} ← ${JSON.stringify(value)}`, { sheet: sheetId, address, value });\n },\n true,\n (args) => target(getSheetId(args), String(args.address ?? \"\")),\n );\n\n reg(\n \"sheet_set_range\",\n \"Set many cells atomically. `cells` is an object map of { \\\"A1\\\": value, \\\"B2\\\": value, ... }.\",\n {\n sheet: { type: \"string\" },\n cells: { type: \"object\" },\n },\n [\"cells\"],\n async (args) => {\n const sheetId = getSheetId(args);\n const wb = adapter.getWorkbook();\n if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n const cells = (args.cells && typeof args.cells === \"object\") ? args.cells as Record<string, CellValue> : {};\n const { reduceWorkbook } = await import(\"@particle-academy/fancy-sheets\");\n let next = wb;\n for (const [addr, v] of Object.entries(cells)) next = reduceWorkbook(next, setCellOp(sheetId, addr, v));\n adapter.setWorkbook(next);\n return textResult(`Set ${Object.keys(cells).length} cells in ${sheetId}`, { sheet: sheetId, count: Object.keys(cells).length });\n },\n true,\n );\n\n reg(\n \"sheet_add_sheet\",\n \"Add a new sheet (tab) to the workbook.\",\n { id: { type: \"string\" }, name: { type: \"string\" } },\n [\"id\", \"name\"],\n (args) => {\n const wb = adapter.getWorkbook();\n const id = String(args.id);\n const name = String(args.name);\n if (wb.sheets.find((s) => s.id === id)) return errorResult(`Sheet ${id} already exists`);\n const next: WorkbookData = {\n ...wb,\n sheets: [\n ...wb.sheets,\n {\n id, name, cells: {}, columnWidths: {}, mergedRegions: [],\n columnFilters: {}, frozenRows: 0, frozenCols: 0,\n },\n ],\n };\n adapter.setWorkbook(next);\n return textResult(`Added sheet ${id} (\"${name}\")`, { id, name });\n },\n true,\n (args) => target(String(args.id ?? \"\")),\n );\n\n reg(\n \"sheet_set_active\",\n \"Switch to a different sheet tab.\",\n { sheet: { type: \"string\" } },\n [\"sheet\"],\n (args) => {\n const sheetId = String(args.sheet);\n const wb = adapter.getWorkbook();\n if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n adapter.setWorkbook({ ...wb, activeSheetId: sheetId });\n return textResult(`Active sheet → ${sheetId}`, { sheet: sheetId });\n },\n true,\n );\n\n reg(\n \"sheet_set_active_cell\",\n \"Move the active cell selection (host implements DOM focus + scroll).\",\n { sheet: { type: \"string\" }, address: { type: \"string\" } },\n [\"address\"],\n (args) => {\n if (!adapter.setActiveCell) return errorResult(\"Host did not provide setActiveCell.\");\n const sheetId = getSheetId(args);\n adapter.setActiveCell(sheetId, String(args.address));\n return textResult(`Active cell → ${sheetId}!${args.address}`, { sheet: sheetId, address: args.address });\n },\n true,\n (args) => target(getSheetId(args), String(args.address ?? \"\")),\n );\n\n return {\n id: \"sheets\",\n title: \"Sheets\",\n dispose: () => {\n for (const d of disposers) d();\n },\n };\n}\n\n// ───────────── helpers ─────────────\n\n/** Build a `set_cell` op, treating a leading-\"=\" string as a formula — matching\n * the in-app editor (value keeps the raw \"=…\"; formula drops the \"=\"). */\nfunction setCellOp(sheet: string, address: string, value: CellValue): SheetOp {\n if (typeof value === \"string\" && value.startsWith(\"=\")) {\n return { type: \"set_cell\", sheet, address, value, formula: value.slice(1) };\n }\n return { type: \"set_cell\", sheet, address, value };\n}\n\n/** Parse \"B12\" → { col: 1, row: 11 }. Letters are 1-based, rows 1-based. */\nfunction parseAddress(addr: string): { col: number; row: number } {\n const m = /^([A-Za-z]+)(\\d+)$/.exec(addr.trim());\n if (!m) throw new Error(`Bad address: ${addr}`);\n const letters = m[1].toUpperCase();\n let col = 0;\n for (let i = 0; i < letters.length; i++) {\n col = col * 26 + (letters.charCodeAt(i) - 64);\n }\n return { col: col - 1, row: parseInt(m[2], 10) - 1 };\n}\n\nfunction colToLetter(col: number): string {\n let s = \"\";\n let n = col + 1;\n while (n > 0) {\n const r = (n - 1) % 26;\n s = String.fromCharCode(65 + r) + s;\n n = Math.floor((n - 1) / 26);\n }\n return s;\n}\n\nfunction readRange(sheet: SheetData, startAddr: string, endAddr: string): CellValue[][] {\n const start = parseAddress(startAddr);\n const end = parseAddress(endAddr);\n const r0 = Math.min(start.row, end.row);\n const r1 = Math.max(start.row, end.row);\n const c0 = Math.min(start.col, end.col);\n const c1 = Math.max(start.col, end.col);\n const grid: CellValue[][] = [];\n for (let r = r0; r <= r1; r++) {\n const row: CellValue[] = [];\n for (let c = c0; c <= c1; c++) {\n const addr = `${colToLetter(c)}${r + 1}`;\n const cell = sheet.cells[addr];\n row.push(cell?.computedValue ?? cell?.value ?? null);\n }\n grid.push(row);\n }\n return grid;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { ensureUndoToolsRegistered, pushUndoEntry } from './chunk-CT3LRNH7.js';
2
- import { wrapToolWithActivity } from './chunk-ULJL53DL.js';
2
+ import { wrapToolWithActivity } from './chunk-2VENWGLZ.js';
3
3
  import { textResult, errorResult } from './chunk-DF3PLL2E.js';
4
4
 
5
5
  // src/bridges/features.ts
@@ -217,5 +217,5 @@ function registerFeaturesBridge(host, options) {
217
217
  }
218
218
 
219
219
  export { registerFeaturesBridge };
220
- //# sourceMappingURL=chunk-HFLHLS2N.js.map
221
- //# sourceMappingURL=chunk-HFLHLS2N.js.map
220
+ //# sourceMappingURL=chunk-ZNGTC4CO.js.map
221
+ //# sourceMappingURL=chunk-ZNGTC4CO.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bridges/features.ts"],"names":[],"mappings":"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","file":"chunk-HFLHLS2N.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport type { AgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * Headless bridge for `@particle-academy/fancy-features` — feature management\n * with NO UI surface. The adapter is the `FeatureManager` (a `FeatureSource`\n * consumer): define features in the registry, check access for a subject,\n * grant/revoke via group assignment, and meter resource usage. Mutations\n * funnel through `wrapToolWithActivity` so presence + undo compose; `grant` /\n * `revoke` are `pendingMode`-gated (they change what a real user can do).\n *\n * The adapter shapes mirror fancy-features' public `FeatureManager` +\n * `FeatureRegistry` + `GroupStore`, defined LOCALLY so the bridge builds with\n * the sibling absent (optional peer). A live `FeatureManager` (plus its\n * `.registry` / `.groupStore`) satisfies this structurally with no import.\n *\n * SUBJECTS over the wire: `Subject` is opaque (`unknown`) in fancy-features.\n * Agents pass a JSON-serializable subject (string id or `{ id, … }` object);\n * the host's stores key on it via their `defaultSubjectKey`.\n */\n\nexport type FeatureGrant = {\n key: string;\n type: \"boolean\" | \"resource\";\n enabled: boolean;\n includedQuantity?: number | null;\n overageLimit?: number | null;\n source?: string;\n config?: Record<string, unknown>;\n};\n\n/** Normalized feature definition (mirror of fancy-features `FeatureDefinition`). */\nexport type FeatureDefinition = {\n key?: string;\n name?: string;\n description?: string;\n type?: \"boolean\" | \"resource\";\n enabled?: boolean;\n limit?: number;\n [k: string]: unknown;\n};\n\n/**\n * Adapter = the `FeatureManager` + its registry + group store. The bridge only\n * needs these members; a real manager exposes them directly.\n */\nexport type FeaturesBridgeAdapter = {\n /** Stable id for this feature manager instance. */\n id?: string;\n title?: string;\n screenId?: string;\n\n // ── Access checks (FeatureManager) ──\n /** Can the subject access the feature now? `manager.canAccess`. */\n canAccess(feature: string, subject?: unknown, context?: unknown): boolean | Promise<boolean>;\n /** Remaining quota for a resource feature (null = unlimited / n-a). `manager.remaining`. */\n remaining(feature: string, subject?: unknown, context?: unknown): number | null | Promise<number | null>;\n /** All enabled feature keys for the subject. `manager.enabled`. */\n enabled(subject?: unknown, context?: unknown): string[] | Promise<string[]>;\n /** Trace a feature's resolution to an AccessResult. `manager.explain`. */\n explain?(feature: string, subject?: unknown, context?: unknown): Promise<unknown> | unknown;\n\n // ── Registry (define) ──\n /** Register a programmatic feature. `manager.registerFeature` / `manager.registry.register`. */\n registerFeature(key: string, definition: FeatureDefinition): void;\n /** Registered feature keys. `manager.registry.keys`. */\n registryKeys(): string[];\n /** Resolve a registered definition (or null). `manager.registry.definition`. */\n definition?(key: string): FeatureDefinition | null | Promise<FeatureDefinition | null>;\n\n // ── Group store (grant / revoke) ──\n /** Assign a subject to a feature group (the grant primitive). `manager.groupStore.assign`. */\n assignGroup(subject: unknown, groupKey: string): void | Promise<void>;\n /** Detach a subject from a group (the revoke primitive). `manager.groupStore.detach`. */\n detachGroup(subject: unknown, groupKey: string): void | Promise<void>;\n /** Group keys assigned to a subject. `manager.groupStore.list`. */\n listGroups(subject: unknown): string[] | Promise<string[]>;\n\n // ── Usage / metering (resource features) ──\n /** Current usage for a resource feature. `manager.usageFor`. Optional. */\n usageFor?(feature: string, subject: unknown): number | Promise<number>;\n /** Atomic check-and-increment quota. `manager.tryConsume`. Optional. */\n tryConsume?(feature: string, subject: unknown, amount?: number, context?: unknown): boolean | Promise<boolean>;\n};\n\nexport type FeaturesBridgeOptions = {\n adapter: FeaturesBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n /**\n * Trust-but-verify. When on (default), `features_grant` / `features_revoke`\n * (they change a real subject's entitlements) require `confirm:true` OR a\n * host `confirm` hook. Checks + define + usage are unaffected.\n */\n pendingMode?: boolean;\n confirm?: (req: { action: string; subject: unknown; groupKey: string }) => Promise<boolean> | boolean;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\nconst str = (v: unknown, fallback = \"\"): string => (typeof v === \"string\" ? v : fallback);\nconst num = (v: unknown, fallback = 0): number => (typeof v === \"number\" && Number.isFinite(v) ? v : fallback);\n\n/**\n * registerFeaturesBridge — full MCP tool set over a headless feature manager.\n *\n * features_list enabled feature keys for a subject\n * features_check can a subject access a feature? (+ remaining for resources)\n * features_explain trace why a feature is on/off for a subject\n * features_define register a feature definition (boolean / resource)\n * features_grant assign a subject to a group (pendingMode-gated, undoable)\n * features_revoke detach a subject from a group (pendingMode-gated, undoable)\n * features_groups list a subject's assigned groups\n * features_consume meter a resource feature (atomic check-and-increment)\n */\nexport function registerFeaturesBridge(host: ToolHost, options: FeaturesBridgeOptions): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const pendingMode = options.pendingMode ?? true;\n const featuresId = adapter.id ?? \"features\";\n const disposers: Array<() => void> = [];\n\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (elementId?: string, label?: string): AgentTarget => ({\n kind: \"custom\",\n screenId: adapter.screenId,\n elementId,\n label: label ?? featuresId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<unknown> | unknown,\n resolveTarget: false | ((args: JsonObject) => AgentTarget),\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = resolveTarget\n ? wrapToolWithActivity(wrapped as never, {\n toolName: name,\n agent,\n kind: \"custom\",\n screenId: adapter.screenId,\n resolveTarget: ({ args }) => resolveTarget(args as JsonObject),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n { name, description, inputSchema: { type: \"object\", properties: properties as Record<string, never>, required, additionalProperties: false } },\n final as never,\n ),\n );\n };\n\n const guardGrant = async (action: string, subject: unknown, groupKey: string, hasConfirmArg: boolean) => {\n if (!pendingMode) return null;\n if (options.confirm) {\n const ok = await options.confirm({ action, subject, groupKey });\n return ok ? null : errorResult(`Declined: ${action} ${groupKey} (human did not confirm).`);\n }\n if (!hasConfirmArg) {\n return errorResult(`${action} is staged (pendingMode). Re-call with confirm:true to apply, or wire a host confirm hook.`);\n }\n return null;\n };\n\n // ─── Read / check tools ──────────────────────────────────────────────────\n\n reg(\n \"features_list\",\n \"List the feature keys enabled for a subject. Pass `subject` (a string id or object).\",\n { subject: { description: \"Opaque subject — string id or { id, … } object.\" }, context: { description: \"Optional resolution context.\" } },\n [],\n async (args) => {\n const keys = await adapter.enabled(args.subject, args.context);\n return textResult(JSON.stringify(keys, null, 2), { subject: args.subject, enabled: keys });\n },\n false,\n );\n\n reg(\n \"features_check\",\n \"Check whether a subject can access a feature. For resource features also returns the remaining quota.\",\n { feature: { type: \"string\" }, subject: { description: \"Opaque subject.\" }, context: { description: \"Optional context.\" } },\n [\"feature\"],\n async (args) => {\n const feature = str(args.feature);\n const allowed = await adapter.canAccess(feature, args.subject, args.context);\n const remaining = await adapter.remaining(feature, args.subject, args.context);\n const out = { feature, allowed, remaining };\n return textResult(JSON.stringify(out), out);\n },\n false,\n );\n\n reg(\n \"features_explain\",\n \"Trace why a feature is on/off for a subject — returns the AccessResult (source, remaining, limit, used).\",\n { feature: { type: \"string\" }, subject: { description: \"Opaque subject.\" }, context: { description: \"Optional context.\" } },\n [\"feature\"],\n async (args) => {\n if (!adapter.explain) return errorResult(\"Host did not wire explain().\");\n const result = await adapter.explain(str(args.feature), args.subject, args.context);\n return textResult(JSON.stringify(result, null, 2), result as Record<string, unknown>);\n },\n false,\n );\n\n reg(\n \"features_groups\",\n \"List the feature groups a subject is assigned to.\",\n { subject: { description: \"Opaque subject.\" } },\n [\"subject\"],\n async (args) => {\n const groups = await adapter.listGroups(args.subject);\n return textResult(JSON.stringify(groups, null, 2), { subject: args.subject, groups });\n },\n false,\n );\n\n // ─── Define ──────────────────────────────────────────────────────────────\n\n reg(\n \"features_define\",\n \"Register a feature definition. type 'boolean' (on/off) or 'resource' (metered with a `limit`). `enabled` sets the default gate.\",\n {\n key: { type: \"string\" },\n name: { type: \"string\" },\n description: { type: \"string\" },\n type: { type: \"string\", enum: [\"boolean\", \"resource\"] },\n enabled: { type: \"boolean\" },\n limit: { type: \"number\", description: \"Resource quota per period (resource type).\" },\n },\n [\"key\"],\n (args) => {\n const key = str(args.key);\n if (!key) return errorResult(\"key is required.\");\n const existed = adapter.registryKeys().includes(key);\n const definition: FeatureDefinition = {\n ...(args.name !== undefined ? { name: str(args.name) } : {}),\n ...(args.description !== undefined ? { description: str(args.description) } : {}),\n ...(args.type !== undefined ? { type: str(args.type) as \"boolean\" | \"resource\" } : {}),\n ...(args.enabled !== undefined ? { enabled: args.enabled === true } : {}),\n ...(args.limit !== undefined ? { limit: num(args.limit) } : {}),\n };\n adapter.registerFeature(key, definition);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: featuresId,\n action: \"features_define\",\n // Registry has no unregister; undo re-registers the prior definition when we had one.\n label: existed ? `Redefined feature ${key}` : `Defined feature ${key}`,\n undo: () => {},\n redo: () => adapter.registerFeature(key, definition),\n });\n return textResult(`${existed ? \"Redefined\" : \"Defined\"} feature ${key} (${definition.type ?? \"boolean\"})`, { key, definition });\n },\n (args) => target(str(args.key), `define ${str(args.key)}`),\n );\n\n // ─── Grant / revoke (pendingMode-gated) ──────────────────────────────────\n\n reg(\n \"features_grant\",\n \"Grant a subject access by assigning it to a feature group. Staged in pendingMode — pass confirm:true or wire a host confirm hook.\",\n { subject: { description: \"Opaque subject.\" }, group: { type: \"string\", description: \"Feature group key.\" }, confirm: { type: \"boolean\" } },\n [\"subject\", \"group\"],\n async (args) => {\n const groupKey = str(args.group);\n if (!groupKey) return errorResult(\"group is required.\");\n const blocked = await guardGrant(\"features_grant\", args.subject, groupKey, args.confirm === true);\n if (blocked) return blocked;\n const already = (await adapter.listGroups(args.subject)).includes(groupKey);\n await adapter.assignGroup(args.subject, groupKey);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: featuresId,\n action: \"features_grant\",\n label: `Granted group ${groupKey}`,\n // Only reverse if WE added it (idempotent assign — don't revoke a pre-existing grant).\n undo: () => { if (!already) void adapter.detachGroup(args.subject, groupKey); },\n redo: () => void adapter.assignGroup(args.subject, groupKey),\n });\n return textResult(`Granted group ${groupKey}`, { subject: args.subject, group: groupKey });\n },\n (args) => target(str(args.group), `grant ${str(args.group)}`),\n );\n\n reg(\n \"features_revoke\",\n \"Revoke access by detaching a subject from a feature group. Staged in pendingMode — pass confirm:true or wire a host confirm hook.\",\n { subject: { description: \"Opaque subject.\" }, group: { type: \"string\" }, confirm: { type: \"boolean\" } },\n [\"subject\", \"group\"],\n async (args) => {\n const groupKey = str(args.group);\n if (!groupKey) return errorResult(\"group is required.\");\n const blocked = await guardGrant(\"features_revoke\", args.subject, groupKey, args.confirm === true);\n if (blocked) return blocked;\n const had = (await adapter.listGroups(args.subject)).includes(groupKey);\n await adapter.detachGroup(args.subject, groupKey);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: featuresId,\n action: \"features_revoke\",\n label: `Revoked group ${groupKey}`,\n undo: () => { if (had) void adapter.assignGroup(args.subject, groupKey); },\n redo: () => void adapter.detachGroup(args.subject, groupKey),\n });\n return textResult(`Revoked group ${groupKey}`, { subject: args.subject, group: groupKey });\n },\n (args) => target(str(args.group), `revoke ${str(args.group)}`),\n );\n\n // ─── Usage / metering ────────────────────────────────────────────────────\n\n reg(\n \"features_consume\",\n \"Meter a resource feature: atomic check-and-increment. Returns ok:false if the quota would be exceeded (nothing recorded).\",\n { feature: { type: \"string\" }, subject: { description: \"Opaque subject.\" }, amount: { type: \"number\", description: \"Units to consume. Default 1.\" }, context: { description: \"Optional context.\" } },\n [\"feature\", \"subject\"],\n async (args) => {\n if (!adapter.tryConsume) return errorResult(\"Host did not wire usage metering (tryConsume).\");\n const feature = str(args.feature);\n const amount = num(args.amount, 1);\n const ok = await adapter.tryConsume(feature, args.subject, amount, args.context);\n const remaining = await adapter.remaining(feature, args.subject, args.context);\n const out = { feature, ok, amount, remaining };\n return textResult(JSON.stringify(out), out);\n },\n (args) => target(str(args.feature), `consume ${str(args.feature)}`),\n );\n\n return {\n id: `features:${featuresId}`,\n title: adapter.title ?? \"Features\",\n dispose: () => {\n for (const d of disposers.splice(0)) d();\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/bridges/features.ts"],"names":[],"mappings":";;;;;AAuGA,IAAM,gBAAgB,EAAE,EAAA,EAAI,SAAS,IAAA,EAAM,OAAA,EAAS,OAAO,SAAA,EAAU;AAErE,IAAM,GAAA,GAAM,CAAC,CAAA,EAAY,QAAA,GAAW,OAAgB,OAAO,CAAA,KAAM,WAAW,CAAA,GAAI,QAAA;AAChF,IAAM,GAAA,GAAM,CAAC,CAAA,EAAY,QAAA,GAAW,CAAA,KAAe,OAAO,CAAA,KAAM,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,GAAI,CAAA,GAAI,QAAA;AAc9F,SAAS,sBAAA,CAAuB,MAAgB,OAAA,EAAwC;AAC7F,EAAA,MAAM,EAAE,SAAQ,GAAI,OAAA;AACpB,EAAA,MAAM,KAAA,GAAQ,EAAE,GAAG,aAAA,EAAe,GAAI,OAAA,CAAQ,KAAA,IAAS,EAAC,EAAG;AAC3D,EAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,IAAe,IAAA;AAC3C,EAAA,MAAM,UAAA,GAAa,QAAQ,EAAA,IAAM,UAAA;AACjC,EAAA,MAAM,YAA+B,EAAC;AAEtC,EAAA,yBAAA,CAA0B,IAAA,EAAM,EAAE,cAAA,EAAgB,KAAA,CAAM,IAAI,CAAA;AAE5D,EAAA,MAAM,MAAA,GAAS,CAAC,SAAA,EAAoB,KAAA,MAAiC;AAAA,IACnE,IAAA,EAAM,QAAA;AAAA,IACN,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,SAAA;AAAA,IACA,OAAO,KAAA,IAAS;AAAA,GAClB,CAAA;AAEA,EAAA,MAAM,MAAM,CACV,IAAA,EACA,aACA,UAAA,EACA,QAAA,EACA,SACA,aAAA,KACG;AACH,IAAA,MAAM,OAAA,GAAU,OAAO,IAAA,KAAqB;AAC1C,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,QAAQ,IAAI,CAAA;AAAA,MAC3B,SAAS,CAAA,EAAG;AACV,QAAA,OAAO,YAAY,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MAC/D;AAAA,IACF,CAAA;AACA,IAAA,MAAM,KAAA,GAAQ,aAAA,GACV,oBAAA,CAAqB,OAAA,EAAkB;AAAA,MACrC,QAAA,EAAU,IAAA;AAAA,MACV,KAAA;AAAA,MACA,IAAA,EAAM,QAAA;AAAA,MACN,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,eAAe,CAAC,EAAE,IAAA,EAAK,KAAM,cAAc,IAAkB;AAAA,KAC9D,CAAA,GACD,OAAA;AACJ,IAAA,SAAA,CAAU,IAAA;AAAA,MACR,IAAA,CAAK,YAAA;AAAA,QACH,EAAE,IAAA,EAAM,WAAA,EAAa,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAU,UAAA,EAAiD,QAAA,EAAU,oBAAA,EAAsB,KAAA,EAAM,EAAE;AAAA,QAC7I;AAAA;AACF,KACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,UAAA,GAAa,OAAO,MAAA,EAAgB,OAAA,EAAkB,UAAkB,aAAA,KAA2B;AACvG,IAAA,IAAI,CAAC,aAAa,OAAO,IAAA;AACzB,IAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,MAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAQ,OAAA,CAAQ,EAAE,MAAA,EAAQ,OAAA,EAAS,UAAU,CAAA;AAC9D,MAAA,OAAO,KAAK,IAAA,GAAO,WAAA,CAAY,aAAa,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAA,yBAAA,CAA2B,CAAA;AAAA,IAC3F;AACA,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,OAAO,WAAA,CAAY,CAAA,EAAG,MAAM,CAAA,0FAAA,CAA4F,CAAA;AAAA,IAC1H;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAIA,EAAA,GAAA;AAAA,IACE,eAAA;AAAA,IACA,sFAAA;AAAA,IACA,EAAE,OAAA,EAAS,EAAE,WAAA,EAAa,2DAAA,IAAqD,OAAA,EAAS,EAAE,WAAA,EAAa,8BAAA,EAA+B,EAAE;AAAA,IACxI,EAAC;AAAA,IACD,OAAO,IAAA,KAAS;AACd,MAAA,MAAM,OAAO,MAAM,OAAA,CAAQ,QAAQ,IAAA,CAAK,OAAA,EAAS,KAAK,OAAO,CAAA;AAC7D,MAAA,OAAO,UAAA,CAAW,IAAA,CAAK,SAAA,CAAU,IAAA,EAAM,IAAA,EAAM,CAAC,CAAA,EAAG,EAAE,OAAA,EAAS,IAAA,CAAK,OAAA,EAAS,OAAA,EAAS,MAAM,CAAA;AAAA,IAC3F,CAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,GAAA;AAAA,IACE,gBAAA;AAAA,IACA,uGAAA;AAAA,IACA,EAAE,OAAA,EAAS,EAAE,IAAA,EAAM,UAAS,EAAG,OAAA,EAAS,EAAE,WAAA,EAAa,mBAAkB,EAAG,OAAA,EAAS,EAAE,WAAA,EAAa,qBAAoB,EAAE;AAAA,IAC1H,CAAC,SAAS,CAAA;AAAA,IACV,OAAO,IAAA,KAAS;AACd,MAAA,MAAM,OAAA,GAAU,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA;AAChC,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,SAAA,CAAU,SAAS,IAAA,CAAK,OAAA,EAAS,KAAK,OAAO,CAAA;AAC3E,MAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,SAAA,CAAU,SAAS,IAAA,CAAK,OAAA,EAAS,KAAK,OAAO,CAAA;AAC7E,MAAA,MAAM,GAAA,GAAM,EAAE,OAAA,EAAS,OAAA,EAAS,SAAA,EAAU;AAC1C,MAAA,OAAO,UAAA,CAAW,IAAA,CAAK,SAAA,CAAU,GAAG,GAAG,GAAG,CAAA;AAAA,IAC5C,CAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,GAAA;AAAA,IACE,kBAAA;AAAA,IACA,+GAAA;AAAA,IACA,EAAE,OAAA,EAAS,EAAE,IAAA,EAAM,UAAS,EAAG,OAAA,EAAS,EAAE,WAAA,EAAa,mBAAkB,EAAG,OAAA,EAAS,EAAE,WAAA,EAAa,qBAAoB,EAAE;AAAA,IAC1H,CAAC,SAAS,CAAA;AAAA,IACV,OAAO,IAAA,KAAS;AACd,MAAA,IAAI,CAAC,OAAA,CAAQ,OAAA,EAAS,OAAO,YAAY,8BAA8B,CAAA;AACvE,MAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA,EAAG,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,OAAO,CAAA;AAClF,MAAA,OAAO,WAAW,IAAA,CAAK,SAAA,CAAU,QAAQ,IAAA,EAAM,CAAC,GAAG,MAAiC,CAAA;AAAA,IACtF,CAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,GAAA;AAAA,IACE,iBAAA;AAAA,IACA,mDAAA;AAAA,IACA,EAAE,OAAA,EAAS,EAAE,WAAA,EAAa,mBAAkB,EAAE;AAAA,IAC9C,CAAC,SAAS,CAAA;AAAA,IACV,OAAO,IAAA,KAAS;AACd,MAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,UAAA,CAAW,KAAK,OAAO,CAAA;AACpD,MAAA,OAAO,UAAA,CAAW,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAA,EAAG,EAAE,OAAA,EAAS,IAAA,CAAK,OAAA,EAAS,MAAA,EAAQ,CAAA;AAAA,IACtF,CAAA;AAAA,IACA;AAAA,GACF;AAIA,EAAA,GAAA;AAAA,IACE,iBAAA;AAAA,IACA,iIAAA;AAAA,IACA;AAAA,MACE,GAAA,EAAK,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACtB,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACvB,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC9B,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAU,MAAM,CAAC,SAAA,EAAW,UAAU,CAAA,EAAE;AAAA,MACtD,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAU;AAAA,MAC3B,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,4CAAA;AAA6C,KACrF;AAAA,IACA,CAAC,KAAK,CAAA;AAAA,IACN,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA;AACxB,MAAA,IAAI,CAAC,GAAA,EAAK,OAAO,WAAA,CAAY,kBAAkB,CAAA;AAC/C,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,YAAA,EAAa,CAAE,SAAS,GAAG,CAAA;AACnD,MAAA,MAAM,UAAA,GAAgC;AAAA,QACpC,GAAI,IAAA,CAAK,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,EAAE,GAAI,EAAC;AAAA,QAC1D,GAAI,IAAA,CAAK,WAAA,KAAgB,MAAA,GAAY,EAAE,WAAA,EAAa,GAAA,CAAI,IAAA,CAAK,WAAW,CAAA,EAAE,GAAI,EAAC;AAAA,QAC/E,GAAI,IAAA,CAAK,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,EAA4B,GAAI,EAAC;AAAA,QACpF,GAAI,IAAA,CAAK,OAAA,KAAY,MAAA,GAAY,EAAE,SAAS,IAAA,CAAK,OAAA,KAAY,IAAA,EAAK,GAAI,EAAC;AAAA,QACvE,GAAI,IAAA,CAAK,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA,EAAE,GAAI;AAAC,OAC/D;AACA,MAAA,OAAA,CAAQ,eAAA,CAAgB,KAAK,UAAU,CAAA;AACvC,MAAA,aAAA,CAAc,MAAM,EAAA,EAAI;AAAA,QACtB,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,QACpB,QAAA,EAAU,UAAA;AAAA,QACV,MAAA,EAAQ,iBAAA;AAAA;AAAA,QAER,OAAO,OAAA,GAAU,CAAA,kBAAA,EAAqB,GAAG,CAAA,CAAA,GAAK,mBAAmB,GAAG,CAAA,CAAA;AAAA,QACpE,MAAM,MAAM;AAAA,QAAC,CAAA;AAAA,QACb,IAAA,EAAM,MAAM,OAAA,CAAQ,eAAA,CAAgB,KAAK,UAAU;AAAA,OACpD,CAAA;AACD,MAAA,OAAO,UAAA,CAAW,CAAA,EAAG,OAAA,GAAU,WAAA,GAAc,SAAS,CAAA,SAAA,EAAY,GAAG,CAAA,EAAA,EAAK,UAAA,CAAW,QAAQ,SAAS,CAAA,CAAA,CAAA,EAAK,EAAE,GAAA,EAAK,YAAY,CAAA;AAAA,IAChI,CAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA,EAAG,CAAA,OAAA,EAAU,GAAA,CAAI,IAAA,CAAK,GAAG,CAAC,CAAA,CAAE;AAAA,GAC3D;AAIA,EAAA,GAAA;AAAA,IACE,gBAAA;AAAA,IACA,wIAAA;AAAA,IACA,EAAE,OAAA,EAAS,EAAE,WAAA,EAAa,iBAAA,IAAqB,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,oBAAA,EAAqB,EAAG,SAAS,EAAE,IAAA,EAAM,WAAU,EAAE;AAAA,IAC1I,CAAC,WAAW,OAAO,CAAA;AAAA,IACnB,OAAO,IAAA,KAAS;AACd,MAAA,MAAM,QAAA,GAAW,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA;AAC/B,MAAA,IAAI,CAAC,QAAA,EAAU,OAAO,WAAA,CAAY,oBAAoB,CAAA;AACtD,MAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,gBAAA,EAAkB,KAAK,OAAA,EAAS,QAAA,EAAU,IAAA,CAAK,OAAA,KAAY,IAAI,CAAA;AAChG,MAAA,IAAI,SAAS,OAAO,OAAA;AACpB,MAAA,MAAM,OAAA,GAAA,CAAW,MAAM,OAAA,CAAQ,UAAA,CAAW,KAAK,OAAO,CAAA,EAAG,SAAS,QAAQ,CAAA;AAC1E,MAAA,MAAM,OAAA,CAAQ,WAAA,CAAY,IAAA,CAAK,OAAA,EAAS,QAAQ,CAAA;AAChD,MAAA,aAAA,CAAc,MAAM,EAAA,EAAI;AAAA,QACtB,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,QACpB,QAAA,EAAU,UAAA;AAAA,QACV,MAAA,EAAQ,gBAAA;AAAA,QACR,KAAA,EAAO,iBAAiB,QAAQ,CAAA,CAAA;AAAA;AAAA,QAEhC,MAAM,MAAM;AAAE,UAAA,IAAI,CAAC,OAAA,EAAS,KAAK,QAAQ,WAAA,CAAY,IAAA,CAAK,SAAS,QAAQ,CAAA;AAAA,QAAG,CAAA;AAAA,QAC9E,MAAM,MAAM,KAAK,QAAQ,WAAA,CAAY,IAAA,CAAK,SAAS,QAAQ;AAAA,OAC5D,CAAA;AACD,MAAA,OAAO,UAAA,CAAW,CAAA,cAAA,EAAiB,QAAQ,CAAA,CAAA,EAAI,EAAE,SAAS,IAAA,CAAK,OAAA,EAAS,KAAA,EAAO,QAAA,EAAU,CAAA;AAAA,IAC3F,CAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA,EAAG,CAAA,MAAA,EAAS,GAAA,CAAI,IAAA,CAAK,KAAK,CAAC,CAAA,CAAE;AAAA,GAC9D;AAEA,EAAA,GAAA;AAAA,IACE,iBAAA;AAAA,IACA,wIAAA;AAAA,IACA,EAAE,OAAA,EAAS,EAAE,WAAA,EAAa,mBAAkB,EAAG,KAAA,EAAO,EAAE,IAAA,EAAM,UAAS,EAAG,OAAA,EAAS,EAAE,IAAA,EAAM,WAAU,EAAE;AAAA,IACvG,CAAC,WAAW,OAAO,CAAA;AAAA,IACnB,OAAO,IAAA,KAAS;AACd,MAAA,MAAM,QAAA,GAAW,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA;AAC/B,MAAA,IAAI,CAAC,QAAA,EAAU,OAAO,WAAA,CAAY,oBAAoB,CAAA;AACtD,MAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,iBAAA,EAAmB,KAAK,OAAA,EAAS,QAAA,EAAU,IAAA,CAAK,OAAA,KAAY,IAAI,CAAA;AACjG,MAAA,IAAI,SAAS,OAAO,OAAA;AACpB,MAAA,MAAM,GAAA,GAAA,CAAO,MAAM,OAAA,CAAQ,UAAA,CAAW,KAAK,OAAO,CAAA,EAAG,SAAS,QAAQ,CAAA;AACtE,MAAA,MAAM,OAAA,CAAQ,WAAA,CAAY,IAAA,CAAK,OAAA,EAAS,QAAQ,CAAA;AAChD,MAAA,aAAA,CAAc,MAAM,EAAA,EAAI;AAAA,QACtB,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,QACpB,QAAA,EAAU,UAAA;AAAA,QACV,MAAA,EAAQ,iBAAA;AAAA,QACR,KAAA,EAAO,iBAAiB,QAAQ,CAAA,CAAA;AAAA,QAChC,MAAM,MAAM;AAAE,UAAA,IAAI,KAAK,KAAK,OAAA,CAAQ,WAAA,CAAY,IAAA,CAAK,SAAS,QAAQ,CAAA;AAAA,QAAG,CAAA;AAAA,QACzE,MAAM,MAAM,KAAK,QAAQ,WAAA,CAAY,IAAA,CAAK,SAAS,QAAQ;AAAA,OAC5D,CAAA;AACD,MAAA,OAAO,UAAA,CAAW,CAAA,cAAA,EAAiB,QAAQ,CAAA,CAAA,EAAI,EAAE,SAAS,IAAA,CAAK,OAAA,EAAS,KAAA,EAAO,QAAA,EAAU,CAAA;AAAA,IAC3F,CAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA,EAAG,CAAA,OAAA,EAAU,GAAA,CAAI,IAAA,CAAK,KAAK,CAAC,CAAA,CAAE;AAAA,GAC/D;AAIA,EAAA,GAAA;AAAA,IACE,kBAAA;AAAA,IACA,2HAAA;AAAA,IACA,EAAE,SAAS,EAAE,IAAA,EAAM,UAAS,EAAG,OAAA,EAAS,EAAE,WAAA,EAAa,iBAAA,EAAkB,EAAG,QAAQ,EAAE,IAAA,EAAM,UAAU,WAAA,EAAa,8BAAA,IAAkC,OAAA,EAAS,EAAE,WAAA,EAAa,mBAAA,EAAoB,EAAE;AAAA,IACnM,CAAC,WAAW,SAAS,CAAA;AAAA,IACrB,OAAO,IAAA,KAAS;AACd,MAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,EAAY,OAAO,YAAY,gDAAgD,CAAA;AAC5F,MAAA,MAAM,OAAA,GAAU,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA;AAChC,MAAA,MAAM,MAAA,GAAS,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ,CAAC,CAAA;AACjC,MAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAQ,UAAA,CAAW,SAAS,IAAA,CAAK,OAAA,EAAS,MAAA,EAAQ,IAAA,CAAK,OAAO,CAAA;AAC/E,MAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,SAAA,CAAU,SAAS,IAAA,CAAK,OAAA,EAAS,KAAK,OAAO,CAAA;AAC7E,MAAA,MAAM,GAAA,GAAM,EAAE,OAAA,EAAS,EAAA,EAAI,QAAQ,SAAA,EAAU;AAC7C,MAAA,OAAO,UAAA,CAAW,IAAA,CAAK,SAAA,CAAU,GAAG,GAAG,GAAG,CAAA;AAAA,IAC5C,CAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA,EAAG,CAAA,QAAA,EAAW,GAAA,CAAI,IAAA,CAAK,OAAO,CAAC,CAAA,CAAE;AAAA,GACpE;AAEA,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,YAAY,UAAU,CAAA,CAAA;AAAA,IAC1B,KAAA,EAAO,QAAQ,KAAA,IAAS,UAAA;AAAA,IACxB,SAAS,MAAM;AACb,MAAA,KAAA,MAAW,CAAA,IAAK,SAAA,CAAU,MAAA,CAAO,CAAC,GAAG,CAAA,EAAE;AAAA,IACzC;AAAA,GACF;AACF","file":"chunk-ZNGTC4CO.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport type { AgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * Headless bridge for `@particle-academy/fancy-features` — feature management\n * with NO UI surface. The adapter is the `FeatureManager` (a `FeatureSource`\n * consumer): define features in the registry, check access for a subject,\n * grant/revoke via group assignment, and meter resource usage. Mutations\n * funnel through `wrapToolWithActivity` so presence + undo compose; `grant` /\n * `revoke` are `pendingMode`-gated (they change what a real user can do).\n *\n * The adapter shapes mirror fancy-features' public `FeatureManager` +\n * `FeatureRegistry` + `GroupStore`, defined LOCALLY so the bridge builds with\n * the sibling absent (optional peer). A live `FeatureManager` (plus its\n * `.registry` / `.groupStore`) satisfies this structurally with no import.\n *\n * SUBJECTS over the wire: `Subject` is opaque (`unknown`) in fancy-features.\n * Agents pass a JSON-serializable subject (string id or `{ id, … }` object);\n * the host's stores key on it via their `defaultSubjectKey`.\n */\n\nexport type FeatureGrant = {\n key: string;\n type: \"boolean\" | \"resource\";\n enabled: boolean;\n includedQuantity?: number | null;\n overageLimit?: number | null;\n source?: string;\n config?: Record<string, unknown>;\n};\n\n/** Normalized feature definition (mirror of fancy-features `FeatureDefinition`). */\nexport type FeatureDefinition = {\n key?: string;\n name?: string;\n description?: string;\n type?: \"boolean\" | \"resource\";\n enabled?: boolean;\n limit?: number;\n [k: string]: unknown;\n};\n\n/**\n * Adapter = the `FeatureManager` + its registry + group store. The bridge only\n * needs these members; a real manager exposes them directly.\n */\nexport type FeaturesBridgeAdapter = {\n /** Stable id for this feature manager instance. */\n id?: string;\n title?: string;\n screenId?: string;\n\n // ── Access checks (FeatureManager) ──\n /** Can the subject access the feature now? `manager.canAccess`. */\n canAccess(feature: string, subject?: unknown, context?: unknown): boolean | Promise<boolean>;\n /** Remaining quota for a resource feature (null = unlimited / n-a). `manager.remaining`. */\n remaining(feature: string, subject?: unknown, context?: unknown): number | null | Promise<number | null>;\n /** All enabled feature keys for the subject. `manager.enabled`. */\n enabled(subject?: unknown, context?: unknown): string[] | Promise<string[]>;\n /** Trace a feature's resolution to an AccessResult. `manager.explain`. */\n explain?(feature: string, subject?: unknown, context?: unknown): Promise<unknown> | unknown;\n\n // ── Registry (define) ──\n /** Register a programmatic feature. `manager.registerFeature` / `manager.registry.register`. */\n registerFeature(key: string, definition: FeatureDefinition): void;\n /** Registered feature keys. `manager.registry.keys`. */\n registryKeys(): string[];\n /** Resolve a registered definition (or null). `manager.registry.definition`. */\n definition?(key: string): FeatureDefinition | null | Promise<FeatureDefinition | null>;\n\n // ── Group store (grant / revoke) ──\n /** Assign a subject to a feature group (the grant primitive). `manager.groupStore.assign`. */\n assignGroup(subject: unknown, groupKey: string): void | Promise<void>;\n /** Detach a subject from a group (the revoke primitive). `manager.groupStore.detach`. */\n detachGroup(subject: unknown, groupKey: string): void | Promise<void>;\n /** Group keys assigned to a subject. `manager.groupStore.list`. */\n listGroups(subject: unknown): string[] | Promise<string[]>;\n\n // ── Usage / metering (resource features) ──\n /** Current usage for a resource feature. `manager.usageFor`. Optional. */\n usageFor?(feature: string, subject: unknown): number | Promise<number>;\n /** Atomic check-and-increment quota. `manager.tryConsume`. Optional. */\n tryConsume?(feature: string, subject: unknown, amount?: number, context?: unknown): boolean | Promise<boolean>;\n};\n\nexport type FeaturesBridgeOptions = {\n adapter: FeaturesBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n /**\n * Trust-but-verify. When on (default), `features_grant` / `features_revoke`\n * (they change a real subject's entitlements) require `confirm:true` OR a\n * host `confirm` hook. Checks + define + usage are unaffected.\n */\n pendingMode?: boolean;\n confirm?: (req: { action: string; subject: unknown; groupKey: string }) => Promise<boolean> | boolean;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\nconst str = (v: unknown, fallback = \"\"): string => (typeof v === \"string\" ? v : fallback);\nconst num = (v: unknown, fallback = 0): number => (typeof v === \"number\" && Number.isFinite(v) ? v : fallback);\n\n/**\n * registerFeaturesBridge — full MCP tool set over a headless feature manager.\n *\n * features_list enabled feature keys for a subject\n * features_check can a subject access a feature? (+ remaining for resources)\n * features_explain trace why a feature is on/off for a subject\n * features_define register a feature definition (boolean / resource)\n * features_grant assign a subject to a group (pendingMode-gated, undoable)\n * features_revoke detach a subject from a group (pendingMode-gated, undoable)\n * features_groups list a subject's assigned groups\n * features_consume meter a resource feature (atomic check-and-increment)\n */\nexport function registerFeaturesBridge(host: ToolHost, options: FeaturesBridgeOptions): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const pendingMode = options.pendingMode ?? true;\n const featuresId = adapter.id ?? \"features\";\n const disposers: Array<() => void> = [];\n\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (elementId?: string, label?: string): AgentTarget => ({\n kind: \"custom\",\n screenId: adapter.screenId,\n elementId,\n label: label ?? featuresId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<unknown> | unknown,\n resolveTarget: false | ((args: JsonObject) => AgentTarget),\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = resolveTarget\n ? wrapToolWithActivity(wrapped as never, {\n toolName: name,\n agent,\n kind: \"custom\",\n screenId: adapter.screenId,\n resolveTarget: ({ args }) => resolveTarget(args as JsonObject),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n { name, description, inputSchema: { type: \"object\", properties: properties as Record<string, never>, required, additionalProperties: false } },\n final as never,\n ),\n );\n };\n\n const guardGrant = async (action: string, subject: unknown, groupKey: string, hasConfirmArg: boolean) => {\n if (!pendingMode) return null;\n if (options.confirm) {\n const ok = await options.confirm({ action, subject, groupKey });\n return ok ? null : errorResult(`Declined: ${action} ${groupKey} (human did not confirm).`);\n }\n if (!hasConfirmArg) {\n return errorResult(`${action} is staged (pendingMode). Re-call with confirm:true to apply, or wire a host confirm hook.`);\n }\n return null;\n };\n\n // ─── Read / check tools ──────────────────────────────────────────────────\n\n reg(\n \"features_list\",\n \"List the feature keys enabled for a subject. Pass `subject` (a string id or object).\",\n { subject: { description: \"Opaque subject — string id or { id, … } object.\" }, context: { description: \"Optional resolution context.\" } },\n [],\n async (args) => {\n const keys = await adapter.enabled(args.subject, args.context);\n return textResult(JSON.stringify(keys, null, 2), { subject: args.subject, enabled: keys });\n },\n false,\n );\n\n reg(\n \"features_check\",\n \"Check whether a subject can access a feature. For resource features also returns the remaining quota.\",\n { feature: { type: \"string\" }, subject: { description: \"Opaque subject.\" }, context: { description: \"Optional context.\" } },\n [\"feature\"],\n async (args) => {\n const feature = str(args.feature);\n const allowed = await adapter.canAccess(feature, args.subject, args.context);\n const remaining = await adapter.remaining(feature, args.subject, args.context);\n const out = { feature, allowed, remaining };\n return textResult(JSON.stringify(out), out);\n },\n false,\n );\n\n reg(\n \"features_explain\",\n \"Trace why a feature is on/off for a subject — returns the AccessResult (source, remaining, limit, used).\",\n { feature: { type: \"string\" }, subject: { description: \"Opaque subject.\" }, context: { description: \"Optional context.\" } },\n [\"feature\"],\n async (args) => {\n if (!adapter.explain) return errorResult(\"Host did not wire explain().\");\n const result = await adapter.explain(str(args.feature), args.subject, args.context);\n return textResult(JSON.stringify(result, null, 2), result as Record<string, unknown>);\n },\n false,\n );\n\n reg(\n \"features_groups\",\n \"List the feature groups a subject is assigned to.\",\n { subject: { description: \"Opaque subject.\" } },\n [\"subject\"],\n async (args) => {\n const groups = await adapter.listGroups(args.subject);\n return textResult(JSON.stringify(groups, null, 2), { subject: args.subject, groups });\n },\n false,\n );\n\n // ─── Define ──────────────────────────────────────────────────────────────\n\n reg(\n \"features_define\",\n \"Register a feature definition. type 'boolean' (on/off) or 'resource' (metered with a `limit`). `enabled` sets the default gate.\",\n {\n key: { type: \"string\" },\n name: { type: \"string\" },\n description: { type: \"string\" },\n type: { type: \"string\", enum: [\"boolean\", \"resource\"] },\n enabled: { type: \"boolean\" },\n limit: { type: \"number\", description: \"Resource quota per period (resource type).\" },\n },\n [\"key\"],\n (args) => {\n const key = str(args.key);\n if (!key) return errorResult(\"key is required.\");\n const existed = adapter.registryKeys().includes(key);\n const definition: FeatureDefinition = {\n ...(args.name !== undefined ? { name: str(args.name) } : {}),\n ...(args.description !== undefined ? { description: str(args.description) } : {}),\n ...(args.type !== undefined ? { type: str(args.type) as \"boolean\" | \"resource\" } : {}),\n ...(args.enabled !== undefined ? { enabled: args.enabled === true } : {}),\n ...(args.limit !== undefined ? { limit: num(args.limit) } : {}),\n };\n adapter.registerFeature(key, definition);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: featuresId,\n action: \"features_define\",\n // Registry has no unregister; undo re-registers the prior definition when we had one.\n label: existed ? `Redefined feature ${key}` : `Defined feature ${key}`,\n undo: () => {},\n redo: () => adapter.registerFeature(key, definition),\n });\n return textResult(`${existed ? \"Redefined\" : \"Defined\"} feature ${key} (${definition.type ?? \"boolean\"})`, { key, definition });\n },\n (args) => target(str(args.key), `define ${str(args.key)}`),\n );\n\n // ─── Grant / revoke (pendingMode-gated) ──────────────────────────────────\n\n reg(\n \"features_grant\",\n \"Grant a subject access by assigning it to a feature group. Staged in pendingMode — pass confirm:true or wire a host confirm hook.\",\n { subject: { description: \"Opaque subject.\" }, group: { type: \"string\", description: \"Feature group key.\" }, confirm: { type: \"boolean\" } },\n [\"subject\", \"group\"],\n async (args) => {\n const groupKey = str(args.group);\n if (!groupKey) return errorResult(\"group is required.\");\n const blocked = await guardGrant(\"features_grant\", args.subject, groupKey, args.confirm === true);\n if (blocked) return blocked;\n const already = (await adapter.listGroups(args.subject)).includes(groupKey);\n await adapter.assignGroup(args.subject, groupKey);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: featuresId,\n action: \"features_grant\",\n label: `Granted group ${groupKey}`,\n // Only reverse if WE added it (idempotent assign — don't revoke a pre-existing grant).\n undo: () => { if (!already) void adapter.detachGroup(args.subject, groupKey); },\n redo: () => void adapter.assignGroup(args.subject, groupKey),\n });\n return textResult(`Granted group ${groupKey}`, { subject: args.subject, group: groupKey });\n },\n (args) => target(str(args.group), `grant ${str(args.group)}`),\n );\n\n reg(\n \"features_revoke\",\n \"Revoke access by detaching a subject from a feature group. Staged in pendingMode — pass confirm:true or wire a host confirm hook.\",\n { subject: { description: \"Opaque subject.\" }, group: { type: \"string\" }, confirm: { type: \"boolean\" } },\n [\"subject\", \"group\"],\n async (args) => {\n const groupKey = str(args.group);\n if (!groupKey) return errorResult(\"group is required.\");\n const blocked = await guardGrant(\"features_revoke\", args.subject, groupKey, args.confirm === true);\n if (blocked) return blocked;\n const had = (await adapter.listGroups(args.subject)).includes(groupKey);\n await adapter.detachGroup(args.subject, groupKey);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: featuresId,\n action: \"features_revoke\",\n label: `Revoked group ${groupKey}`,\n undo: () => { if (had) void adapter.assignGroup(args.subject, groupKey); },\n redo: () => void adapter.detachGroup(args.subject, groupKey),\n });\n return textResult(`Revoked group ${groupKey}`, { subject: args.subject, group: groupKey });\n },\n (args) => target(str(args.group), `revoke ${str(args.group)}`),\n );\n\n // ─── Usage / metering ────────────────────────────────────────────────────\n\n reg(\n \"features_consume\",\n \"Meter a resource feature: atomic check-and-increment. Returns ok:false if the quota would be exceeded (nothing recorded).\",\n { feature: { type: \"string\" }, subject: { description: \"Opaque subject.\" }, amount: { type: \"number\", description: \"Units to consume. Default 1.\" }, context: { description: \"Optional context.\" } },\n [\"feature\", \"subject\"],\n async (args) => {\n if (!adapter.tryConsume) return errorResult(\"Host did not wire usage metering (tryConsume).\");\n const feature = str(args.feature);\n const amount = num(args.amount, 1);\n const ok = await adapter.tryConsume(feature, args.subject, amount, args.context);\n const remaining = await adapter.remaining(feature, args.subject, args.context);\n const out = { feature, ok, amount, remaining };\n return textResult(JSON.stringify(out), out);\n },\n (args) => target(str(args.feature), `consume ${str(args.feature)}`),\n );\n\n return {\n id: `features:${featuresId}`,\n title: adapter.title ?? \"Features\",\n dispose: () => {\n for (const d of disposers.splice(0)) d();\n },\n };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, CSSProperties } from 'react';
3
3
  import { StickyNoteItem, ShapeItem, ConnectorItem, Stroke, Viewport } from '@particle-academy/fancy-whiteboard';
4
- import { S as SessionDescriptor } from '../../token-CrJF76oH.cjs';
4
+ import { S as SessionDescriptor } from '../../token-BZ8doMam.cjs';
5
5
 
6
6
  type SharedWhiteboardProps = {
7
7
  /** Initial board contents. */