@rubytech/create-maxy-code 0.1.264 → 0.1.266

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 (173) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/models/dist/index.d.ts +1 -1
  3. package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/models/dist/index.js +5 -2
  5. package/payload/platform/lib/models/dist/index.js.map +1 -1
  6. package/payload/platform/lib/models/src/index.ts +5 -2
  7. package/payload/platform/neo4j/schema.cypher +13 -0
  8. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  9. package/payload/platform/plugins/admin/PLUGIN.md +6 -1
  10. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.d.ts +2 -0
  11. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.d.ts.map +1 -0
  12. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.js +106 -0
  13. package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.js.map +1 -0
  14. package/payload/platform/plugins/admin/mcp/dist/index.js +36 -1
  15. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  16. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts +12 -0
  17. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts.map +1 -1
  18. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js +175 -1
  19. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js.map +1 -1
  20. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +11 -3
  21. package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +2 -2
  22. package/payload/platform/plugins/business-assistant/PLUGIN.md +1 -5
  23. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  24. package/payload/platform/plugins/docs/references/voice-mirror-guide.md +9 -1
  25. package/payload/platform/plugins/memory/references/schema-base.md +1 -1
  26. package/payload/platform/plugins/memory/references/schema-construction.md +1 -1
  27. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-login-start.test.d.ts +2 -0
  28. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-login-start.test.d.ts.map +1 -0
  29. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-login-start.test.js +16 -0
  30. package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-login-start.test.js.map +1 -0
  31. package/payload/platform/plugins/whatsapp/mcp/dist/format.d.ts +7 -0
  32. package/payload/platform/plugins/whatsapp/mcp/dist/format.d.ts.map +1 -0
  33. package/payload/platform/plugins/whatsapp/mcp/dist/format.js +21 -0
  34. package/payload/platform/plugins/whatsapp/mcp/dist/format.js.map +1 -0
  35. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +11 -19
  36. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  37. package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +15 -13
  38. package/payload/platform/scripts/check-skill-frontmatter.mjs +8 -5
  39. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  40. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  41. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  42. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  43. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +15 -15
  44. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  45. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +10 -0
  46. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  47. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +59 -0
  48. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  49. package/payload/platform/templates/account.json +1 -1
  50. package/payload/platform/templates/agents/admin/IDENTITY.md +3 -3
  51. package/payload/platform/templates/specialists/agents/content-producer.md +1 -1
  52. package/payload/platform/templates/specialists/agents/librarian.md +1 -1
  53. package/payload/platform/templates/specialists/agents/research-assistant.md +1 -1
  54. package/payload/premium-plugins/venture-studio/skills/investor-data-room/SKILL.md +1 -1
  55. package/payload/premium-plugins/writer-craft/PLUGIN.md +4 -4
  56. package/payload/premium-plugins/writer-craft/mcp/dist/index.d.ts.map +1 -1
  57. package/payload/premium-plugins/writer-craft/mcp/dist/index.js +44 -9
  58. package/payload/premium-plugins/writer-craft/mcp/dist/index.js.map +1 -1
  59. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts +31 -0
  60. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts.map +1 -1
  61. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js +28 -0
  62. package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js.map +1 -1
  63. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts +7 -1
  64. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts.map +1 -1
  65. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js +93 -44
  66. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js.map +1 -1
  67. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.d.ts.map +1 -1
  68. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js +1 -0
  69. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-ingest-session-text.js.map +1 -1
  70. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.d.ts +7 -1
  71. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.d.ts.map +1 -1
  72. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.js +14 -3
  73. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-record-feedback.js.map +1 -1
  74. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.d.ts +22 -8
  75. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.d.ts.map +1 -1
  76. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.js +93 -84
  77. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.js.map +1 -1
  78. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.d.ts +18 -0
  79. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.d.ts.map +1 -1
  80. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.js +32 -3
  81. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-tag-content.js.map +1 -1
  82. package/payload/premium-plugins/writer-craft/mcp/scripts/smoke.mjs +35 -2
  83. package/payload/premium-plugins/writer-craft/mcp/src/index.ts +52 -10
  84. package/payload/premium-plugins/writer-craft/mcp/src/lib/voice-corpus.ts +39 -0
  85. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-distil-profile.ts +108 -44
  86. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-ingest-session-text.ts +1 -0
  87. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-record-feedback.ts +24 -4
  88. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-retrieve-conditioning.ts +136 -102
  89. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-tag-content.ts +45 -3
  90. package/payload/premium-plugins/writer-craft/skills/voice-mirror/SKILL.md +34 -23
  91. package/payload/server/{adminuser-self-heal-YC47O34W.js → adminuser-self-heal-LC7HZAC6.js} +17 -9
  92. package/payload/server/{chunk-HYQNUVGO.js → chunk-PFF6I7KP.js} +1 -8
  93. package/payload/server/{chunk-ZC63DFWF.js → chunk-SOLVVUST.js} +1 -1
  94. package/payload/server/maxy-edge.js +2 -2
  95. package/payload/server/public/assets/{AdminShell-8JLQM1Mz.js → AdminShell-BcHJy_Y2.js} +1 -1
  96. package/payload/server/public/assets/{Checkbox-CuFJh7lI.js → Checkbox-BY2lndUH.js} +1 -1
  97. package/payload/server/public/assets/{admin-D4nsdmKU.js → admin-C364q_-g.js} +1 -1
  98. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-D-ODjJS5.js → architectureDiagram-Q4EWVU46-B9ik0JyO.js} +1 -1
  99. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DFuVe8f9.js → blockDiagram-DXYQGD6D-C-w-AMRJ.js} +1 -1
  100. package/payload/server/public/assets/{browser-DIKmvDl5.js → browser-D66JrDpx.js} +1 -1
  101. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CeVLfznT.js → c4Diagram-AHTNJAMY-BH-b0NZ1.js} +1 -1
  102. package/payload/server/public/assets/channel-5xoW3jfU.js +1 -0
  103. package/payload/server/public/assets/{chunk-336JU56O-BTaLfR3a.js → chunk-336JU56O-CZHLbmJj.js} +2 -2
  104. package/payload/server/public/assets/{chunk-426QAEUC-BzTbm4pP.js → chunk-426QAEUC-Qx6Ggp9s.js} +1 -1
  105. package/payload/server/public/assets/{chunk-4TB4RGXK-SiUyOXVG.js → chunk-4TB4RGXK-J1Raz9l0.js} +1 -1
  106. package/payload/server/public/assets/{chunk-5FUZZQ4R-BcQ33LnT.js → chunk-5FUZZQ4R-D6TFnJVF.js} +1 -1
  107. package/payload/server/public/assets/{chunk-5PVQY5BW-CT7C1Tik.js → chunk-5PVQY5BW-CC5aEdzK.js} +1 -1
  108. package/payload/server/public/assets/{chunk-EDXVE4YY-CK3uI2u6.js → chunk-EDXVE4YY-Bfbcdcbt.js} +1 -1
  109. package/payload/server/public/assets/{chunk-ENJZ2VHE-Ddp8Otnw.js → chunk-ENJZ2VHE-7EKi84Dw.js} +1 -1
  110. package/payload/server/public/assets/{chunk-ICPOFSXX-DHTxymk_.js → chunk-ICPOFSXX-DIH1FT8n.js} +1 -1
  111. package/payload/server/public/assets/{chunk-OYMX7WX6-Heg3hegz.js → chunk-OYMX7WX6-MgP02n7p.js} +1 -1
  112. package/payload/server/public/assets/{chunk-U2HBQHQK-Cw2PR7aJ.js → chunk-U2HBQHQK-Cwmbq3M7.js} +1 -1
  113. package/payload/server/public/assets/{chunk-X2U36JSP-C7vBCAQQ.js → chunk-X2U36JSP-D65N3MkW.js} +1 -1
  114. package/payload/server/public/assets/{chunk-YZCP3GAM-BS8Mybh1.js → chunk-YZCP3GAM-BkCiRhSG.js} +1 -1
  115. package/payload/server/public/assets/{chunk-ZZ45TVLE-DmnbQp47.js → chunk-ZZ45TVLE-3BQY1FWN.js} +1 -1
  116. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DRSNlIL5.js +1 -0
  117. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CYvRRfMp.js +1 -0
  118. package/payload/server/public/assets/clone-DvQUt_lq.js +1 -0
  119. package/payload/server/public/assets/{dagre-D4i6r8zi.js → dagre-DVhW13RD.js} +1 -1
  120. package/payload/server/public/assets/{dagre-KV5264BT-znWS6Wh2.js → dagre-KV5264BT-CtfjEgDz.js} +1 -1
  121. package/payload/server/public/assets/{data-CHqF4bkS.js → data-uiOcPh8T.js} +1 -1
  122. package/payload/server/public/assets/{diagram-5BDNPKRD-B6tQBN1Y.js → diagram-5BDNPKRD-C8AXEFch.js} +1 -1
  123. package/payload/server/public/assets/{diagram-G4DWMVQ6-t73WpYIY.js → diagram-G4DWMVQ6-B1P8Cwuz.js} +1 -1
  124. package/payload/server/public/assets/{diagram-MMDJMWI5-Cm63UOJm.js → diagram-MMDJMWI5-QBVBnPmO.js} +1 -1
  125. package/payload/server/public/assets/{diagram-TYMM5635-DuTSLjVB.js → diagram-TYMM5635-D2xE8fN8.js} +1 -1
  126. package/payload/server/public/assets/{erDiagram-SMLLAGMA-sbHunitX.js → erDiagram-SMLLAGMA-DMee1Yih.js} +1 -1
  127. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BWOrPuqz.js → flowDiagram-DWJPFMVM-DAd3JjoB.js} +1 -1
  128. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-WaLMGard.js → ganttDiagram-T4ZO3ILL-Bs33CmKo.js} +1 -1
  129. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-CsbIgKDn.js → gitGraphDiagram-UUTBAWPF-NXc8aeps.js} +1 -1
  130. package/payload/server/public/assets/{graph-kwyPyf_b.js → graph-BSHyF267.js} +1 -1
  131. package/payload/server/public/assets/{graph-labels-pX3uIQys.js → graph-labels-D5ecmK-Z.js} +1 -1
  132. package/payload/server/public/assets/{graphlib-B8yKFZvc.js → graphlib-DN7sm5nK.js} +1 -1
  133. package/payload/server/public/assets/{infoDiagram-42DDH7IO-Bd55TzsD.js → infoDiagram-42DDH7IO-D2g5STFr.js} +1 -1
  134. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BFdOsA9f.js → ishikawaDiagram-UXIWVN3A-DBgfV-LB.js} +1 -1
  135. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CMQ5XWO9.js → journeyDiagram-VCZTEJTY-Chh9lW9P.js} +1 -1
  136. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-_RpNNRN7.js → kanban-definition-6JOO6SKY-buI2AXpi.js} +1 -1
  137. package/payload/server/public/assets/{line-SkFxjGJ8.js → line-C8OFYjrW.js} +1 -1
  138. package/payload/server/public/assets/{mermaid-parser.core-Ddok2IAe.js → mermaid-parser.core-BI5Ythbv.js} +1 -1
  139. package/payload/server/public/assets/{mermaid.core-CihAjXBG.js → mermaid.core-C4dyl1Xw.js} +3 -3
  140. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CJsq3hrO.js → mindmap-definition-QFDTVHPH-BbXKSpiv.js} +1 -1
  141. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CSgg8lBB.js → pieDiagram-DEJITSTG-C8-OIoUW.js} +1 -1
  142. package/payload/server/public/assets/{public-BA9P-3ZV.js → public-DGlZwbyw.js} +3 -3
  143. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-TtHxMQtS.js → quadrantDiagram-34T5L4WZ-HOEtpu4n.js} +1 -1
  144. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DdYupKtL.js → requirementDiagram-MS252O5E-DLxjohCO.js} +1 -1
  145. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BVfdyUnO.js → sankeyDiagram-XADWPNL6-E_O_HiFL.js} +1 -1
  146. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-aFLOua6n.js → sequenceDiagram-FGHM5R23-C3-hhAup.js} +1 -1
  147. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-_3Ix8SPZ.js → stateDiagram-FHFEXIEX-BhAmQ0XX.js} +1 -1
  148. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-Dhrf9hq_.js +1 -0
  149. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Bs96WqZ7.js → timeline-definition-GMOUNBTQ-DpfZt7xI.js} +1 -1
  150. package/payload/server/public/assets/{useSelectionMode-L9uAHstA.css → useSelectionMode-98jrB9kD.css} +1 -1
  151. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-DE_SxsN2.js → vennDiagram-DHZGUBPP-Ck2Ago5q.js} +1 -1
  152. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-DTCdKs6v.js → wardleyDiagram-NUSXRM2D-Dgk8C9kF.js} +1 -1
  153. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CNIrxADs.js → xychartDiagram-5P7HB3ND-BRBSl8ID.js} +1 -1
  154. package/payload/server/public/browser.html +4 -4
  155. package/payload/server/public/data.html +5 -5
  156. package/payload/server/public/graph.html +6 -6
  157. package/payload/server/public/index.html +5 -5
  158. package/payload/server/public/public.html +4 -4
  159. package/payload/server/server.js +607 -5064
  160. package/payload/platform/plugins/business-assistant/references/quote-engine.md +0 -122
  161. package/payload/platform/plugins/business-assistant/references/quote-generation.md +0 -94
  162. package/payload/platform/plugins/business-assistant/references/quoting.md +0 -85
  163. package/payload/platform/plugins/business-assistant/skills/pricing-method/SKILL.md +0 -78
  164. package/payload/platform/plugins/business-assistant/skills/pricing-method/references/learning-from-history.md +0 -51
  165. package/payload/platform/plugins/business-assistant/skills/pricing-method/references/maintenance.md +0 -32
  166. package/payload/platform/plugins/business-assistant/skills/pricing-method/references/manual-definition.md +0 -42
  167. package/payload/platform/plugins/business-assistant/skills/pricing-method/references/verification.md +0 -37
  168. package/payload/server/public/assets/channel-Db8J_1Rl.js +0 -1
  169. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DjquNGFr.js +0 -1
  170. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CcE8sWEP.js +0 -1
  171. package/payload/server/public/assets/clone-xa7JZYoY.js +0 -1
  172. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-eVQQEyxx.js +0 -1
  173. /package/payload/server/public/assets/{useSelectionMode-Da9Glxvu.js → useSelectionMode-80iYuGPa.js} +0 -0
@@ -9,7 +9,7 @@
9
9
  // Pure filesystem read — no network, no subprocess. The walk is two-level
10
10
  // (plugin dir → skill dir), never recursive, so deeper skill subtrees and
11
11
  // sibling references/ directories are ignored.
12
- import { existsSync, readdirSync, statSync } from "node:fs";
12
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
13
13
  import { readFile } from "node:fs/promises";
14
14
  import { resolve } from "node:path";
15
15
  const SKILL_FILE_PATH = /^skills\/([a-z0-9][a-z0-9-]*)\//;
@@ -171,6 +171,180 @@ export function parseRequiredInputs(skillBody) {
171
171
  }
172
172
  return slots.length > 0 ? slots : undefined;
173
173
  }
174
+ // Extract `name` and `description` from a SKILL.md frontmatter block. Handles
175
+ // the three shapes present in the tree: single-line (`description: text`),
176
+ // folded block scalar (`description: >`), and literal block scalar
177
+ // (`description: |`). For a block scalar the value is every indented
178
+ // continuation line up to the next column-0 key or the frontmatter close,
179
+ // joined with single spaces. Only the leading `---\n...\n---` block is read;
180
+ // returns empty strings for keys that are absent.
181
+ export function parseSkillFrontmatter(skillBody) {
182
+ const empty = { name: "", description: "" };
183
+ const m = skillBody.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
184
+ if (!m)
185
+ return empty;
186
+ const lines = m[1].split(/\r?\n/);
187
+ const readValue = (key) => {
188
+ const head = new RegExp(`^${key}:[ \\t]*(.*)$`);
189
+ for (let i = 0; i < lines.length; i++) {
190
+ const hit = lines[i].match(head);
191
+ if (!hit)
192
+ continue;
193
+ const inline = hit[1].trim();
194
+ // A block scalar indicator is `|` or `>`, optionally with a chomping
195
+ // (`+`/`-`) and/or explicit-indent (`1`-`9`) modifier and a trailing
196
+ // comment — e.g. `>`, `|-`, `>2`, `| # note`. Anything else on the line
197
+ // is an inline value.
198
+ const isBlockScalar = /^[|>][+-]?[1-9]?[ \t]*(?:#.*)?$/.test(inline);
199
+ if (inline !== "" && !isBlockScalar) {
200
+ return stripQuotes(inline);
201
+ }
202
+ // block scalar — gather indented continuation lines.
203
+ const parts = [];
204
+ for (let j = i + 1; j < lines.length; j++) {
205
+ if (/^[A-Za-z][\w-]*:/.test(lines[j]))
206
+ break; // next column-0 key
207
+ const trimmed = lines[j].trim();
208
+ if (trimmed === "")
209
+ continue;
210
+ parts.push(trimmed);
211
+ }
212
+ return parts.join(" ");
213
+ }
214
+ return "";
215
+ };
216
+ return { name: readValue("name"), description: readValue("description") };
217
+ }
218
+ function stripQuotes(s) {
219
+ if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
220
+ return s.slice(1, -1);
221
+ }
222
+ return s;
223
+ }
224
+ // Search every plugin skill by free-text query against frontmatter
225
+ // `name` + `description`, returning the top `limit` owners ranked by relevance.
226
+ //
227
+ // Walk: the same two-level, non-recursive shape as `findSkillOwners`
228
+ // (plugin dir → skill dir), but enumerating every skill rather than one named
229
+ // slug. Only the frontmatter is read.
230
+ //
231
+ // Ranking is frequency-aware so distinctive terms dominate. The query is
232
+ // tokenised on non-alphanumeric boundaries (tokens of length >= 2, deduped).
233
+ // Each skill scores the sum, over query terms present in its haystack, of an
234
+ // inverse-document-frequency weight `log((N+1)/(df+1)) + 1` — a term in nearly
235
+ // every description (e.g. "create") contributes almost nothing, a rare term
236
+ // (e.g. "quote", "algorithm") dominates. A name hit weighs double a
237
+ // description hit. Without this weighting a bare term count ties the intended
238
+ // skill against every skill that merely shares a common trigger word. Ties
239
+ // break by slug ascending so the order is deterministic. A query that matches
240
+ // nothing returns `[]` (not an error).
241
+ export function searchSkills(platformRoot, query, limit = 5) {
242
+ const terms = Array.from(new Set(query
243
+ .toLowerCase()
244
+ .split(/[^a-z0-9]+/)
245
+ .filter(t => t.length >= 2)));
246
+ if (terms.length === 0)
247
+ return [];
248
+ // Match each term on a word boundary at the start of a word (`\bterm`), not
249
+ // as an arbitrary substring. This keeps stemming (`quote` matches `quotes`,
250
+ // `quote-generation`) while rejecting incidental infix hits (`id` must not
251
+ // match `video`/`guide`, `art` must not match `start`/`smart`) that would
252
+ // otherwise flood results and collapse a term's IDF weight toward 1. Terms
253
+ // are alphanumeric (the tokenizer split on everything else), so no regex
254
+ // metacharacters can appear and no escaping is needed. Reused, flagless
255
+ // RegExps are stateless under `.test`.
256
+ const termRe = new Map(terms.map(t => [t, new RegExp(`\\b${t}`)]));
257
+ const matches = (hay, term) => termRe.get(term).test(hay);
258
+ const pluginsDir = resolve(platformRoot, "plugins");
259
+ if (!existsSync(pluginsDir))
260
+ return [];
261
+ let plugins;
262
+ try {
263
+ plugins = readdirSync(pluginsDir);
264
+ }
265
+ catch {
266
+ return [];
267
+ }
268
+ const candidates = [];
269
+ for (const pluginName of plugins) {
270
+ const skillsDir = resolve(pluginsDir, pluginName, "skills");
271
+ if (!existsSync(skillsDir))
272
+ continue;
273
+ let skills;
274
+ try {
275
+ skills = readdirSync(skillsDir);
276
+ }
277
+ catch {
278
+ continue;
279
+ }
280
+ for (const skillName of skills) {
281
+ const skillFile = resolve(skillsDir, skillName, "SKILL.md");
282
+ if (!existsSync(skillFile))
283
+ continue;
284
+ try {
285
+ if (!statSync(skillFile).isFile())
286
+ continue;
287
+ }
288
+ catch {
289
+ continue;
290
+ }
291
+ let body;
292
+ try {
293
+ body = readFileSync(skillFile, "utf-8");
294
+ }
295
+ catch {
296
+ continue;
297
+ }
298
+ const { name, description } = parseSkillFrontmatter(body);
299
+ candidates.push({
300
+ pluginName,
301
+ skillName,
302
+ description,
303
+ name,
304
+ nameHay: `${skillName} ${name}`.toLowerCase(),
305
+ descHay: description.toLowerCase(),
306
+ });
307
+ }
308
+ }
309
+ if (candidates.length === 0)
310
+ return [];
311
+ // document frequency per term across name+description haystacks.
312
+ const N = candidates.length;
313
+ const df = new Map();
314
+ for (const term of terms) {
315
+ let count = 0;
316
+ for (const c of candidates) {
317
+ if (matches(c.nameHay, term) || matches(c.descHay, term))
318
+ count++;
319
+ }
320
+ df.set(term, count);
321
+ }
322
+ const hits = [];
323
+ for (const c of candidates) {
324
+ let score = 0;
325
+ for (const term of terms) {
326
+ const inName = matches(c.nameHay, term);
327
+ const inDesc = matches(c.descHay, term);
328
+ if (!inName && !inDesc)
329
+ continue;
330
+ const idf = Math.log((N + 1) / ((df.get(term) ?? 0) + 1)) + 1;
331
+ score += idf * (inName ? 2 : 1);
332
+ }
333
+ if (score > 0) {
334
+ hits.push({
335
+ pluginName: c.pluginName,
336
+ skillName: c.skillName,
337
+ file: `skills/${c.skillName}/SKILL.md`,
338
+ description: c.description,
339
+ score,
340
+ });
341
+ }
342
+ }
343
+ hits.sort((a, b) => b.score - a.score ||
344
+ a.skillName.localeCompare(b.skillName) ||
345
+ a.pluginName.localeCompare(b.pluginName));
346
+ return hits.slice(0, limit);
347
+ }
174
348
  export async function loadSkill(platformRoot, skillName) {
175
349
  const result = findSkillOwners(platformRoot, skillName);
176
350
  if (result.status === "ambiguous") {
@@ -1 +1 @@
1
- {"version":3,"file":"skill-resolution.js","sourceRoot":"","sources":["../src/skill-resolution.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill-resolution.js","sourceRoot":"","sources":["../src/skill-resolution.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: platform-architecture
3
3
  description: Use when grounding any documented-surface claim about what Maxy ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
4
- content-hash: sha256:1a53491b6e8b0d6ee4c3e7d648e48e6599de88d5280e7b8b5851c7d2ce3f4b44
4
+ content-hash: sha256:0e8368ce205506dec22d5ed93f886c0cfc0f12b5306a6b953b4ddad19e8d3175
5
5
  brand: maxy-code
6
6
  product-name: Maxy
7
7
  ---
@@ -2185,6 +2185,14 @@ Maxy reads the corpus for each format, summarises your style as a YAML card, and
2185
2185
 
2186
2186
  The profile re-runs automatically when your corpus grows by ≥20% for any format or every 30 days, whichever comes first.
2187
2187
 
2188
+ ## Your Voice and the House Voice
2189
+
2190
+ There are two kinds of profile. **Your voice** is learned from your own writing — it's what an email drafted under your name should sound like. **The house voice** is learned from everyone's writing on the account as a whole — it's what something that goes out under the business's name should sound like, like a brochure or an investor document.
2191
+
2192
+ Drafting picks the right one for you: emails use your voice; brochures and investor documents use the house voice. If you ask for your own voice but haven't tagged any of your own writing yet, Maxy quietly uses the house voice instead, so drafts still sound right rather than generic.
2193
+
2194
+ When you tag content, it's attributed to you by default. On a shared account with more than one person, you can attribute a piece to whoever actually wrote it, so each person's voice stays their own while the house voice draws on all of it.
2195
+
2188
2196
  ## Feedback Loop
2189
2197
 
2190
2198
  When you edit an agent draft before sending — shorten a sentence, change a sign-off, swap a phrase — Maxy captures the edit and feeds it into the next distillation. The more you edit, the closer the voice gets.
@@ -2197,7 +2205,7 @@ Voice mirror is on by default for every drafting skill. To opt out for one, set
2197
2205
 
2198
2206
  ## What It Won't Do
2199
2207
 
2200
- - **Blend voices** — one profile set per person, no "Joel + Neo combined".
2208
+ - **Blend two named people** — you get a profile per person plus one house voice for the whole account, but not a bespoke "Joel + Neo combined" voice.
2201
2209
  - **Copy public figures** — voice mirror only learns from your own writing.
2202
2210
  - **Clone audio** — text only, no speech synthesis.
2203
2211
  - **Guess** — historical content stays `unknown` until you mark it. Maxy never auto-classifies your writing. (Automatic ingestion applies only to your live PTY sessions where authorship is certain.)
@@ -2261,7 +2269,7 @@ either is a regression.
2261
2269
  | `/session-rc-spawn` | POST `{ sessionId?, name? }` (Task 543). Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`, which waits up to **60 s** (Task 648, raised from 12 s) for the spawned PTY to bind and returns `{ spawnedPid, sessionId, bridgeSessionId, slug, outcome, reason }`. The Sidebar navigates the opened tab to `claude.ai/code/session_<id>` on `outcome=bound`; on `timeout` or `spawn-failed` it shows an error modal (reason + sessionId) and **never** opens a bare claude.ai/code tab. The new process registers itself as its own Remote Control entry in claude.ai/code. | `POST /` |
2262
2270
  | `/claude-sessions` | **Spawn surface only** (Task 500). `POST /` is the Sidebar new-session-with-prompt path, cookie-auth only (Task 626 removed the recorder loopback caller; LinkedIn ingest moved to `/rc-spawn`). The former UI-facing handlers (SSE row feed, list, resume, stop, rename, archive, delete, `/:id/meta`, `/:id/input`, `/:id/log`) were removed — the maxy dashboard no longer manages or displays sessions. | `POST /` |
2263
2271
 
2264
- Task 500 — **admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot. The maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
2272
+ Task 500 — **admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot; the reasoning-effort lever is `account.json.effort` → `settings.json "effortLevel"` (accepted values `low|medium|high|xhigh`; any other value, e.g. legacy `"auto"`, leaves the key unset so claude's own default governs), written by the same read-merge-write at boot. The maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
2265
2273
 
2266
2274
  **Row title resolution.** Both the sidebar (`/sidebar-sessions`) and the manager's own row payload resolve a row's title in the same order: operator rename → Claude Code `ai-title` → first non-CLI user message → 8-char sessionId prefix. The operator-rename tier is the on-disk `<accountDir>/session-titles.json` (the manager's `UserTitleStore`), keyed by the CC sessionId — the sidebar reads that same file, so a write to the store lights up both surfaces with one write.
2267
2275
 
@@ -81,7 +81,7 @@ Present as a `select` field within the agent configuration `form` during creatio
81
81
  |-------|-----|------------|------|
82
82
  | Haiku | `claude-haiku-4-5` | Fast, cost-effective. FAQ, routing, high-volume. | Low |
83
83
  | Sonnet | `claude-sonnet-4-6` | Balanced. Nuanced conversation, qualification, support. | Standard |
84
- | Opus | `claude-opus-4-7` | Maximum intelligence. Complex sales, consultative selling. | Premium |
84
+ | Opus | `claude-opus-4-8[1m]` | Maximum intelligence. Complex sales, consultative selling. | Premium |
85
85
 
86
86
  ## SOUL.md Scope Enforcement
87
87
 
@@ -160,7 +160,7 @@ After creation, no template metadata persists in the agent's files. The resultin
160
160
  - `model` (`select`): label "Model", options with descriptions:
161
161
  - `claude-haiku-4-5` — "Haiku — Fast, cost-effective. FAQ, routing, high-volume."
162
162
  - `claude-sonnet-4-6` — "Sonnet — Balanced. Nuanced conversation, qualification, support."
163
- - `claude-opus-4-7` — "Opus — Maximum intelligence. Complex sales, consultative selling."
163
+ - `claude-opus-4-8[1m]` — "Opus — Maximum intelligence. Complex sales, consultative selling."
164
164
  - `showAgentName` (`select`): label "Chat header title", options: `false` — "Business name (default)", `true` — "Agent display name", `"none"` — "None (logo only)"
165
165
  The `model` field should have a `defaultValue` of `"claude-haiku-4-5"`.
166
166
  Wait for the user's response before proceeding.
@@ -6,7 +6,7 @@ metadata: {"platform":{"always":true,"embed":["admin"],"pluginKey":"business-ass
6
6
 
7
7
  # Business Assistant
8
8
 
9
- You are a business assistant for a small business. You handle their customer communications, scheduling, quoting, invoicing, and admin — so they can focus on the work.
9
+ You are a business assistant for a small business. You handle their customer communications, scheduling, invoicing, and admin — so they can focus on the work.
10
10
 
11
11
  ## Core Principle: Memory First
12
12
 
@@ -54,10 +54,6 @@ Load the relevant reference when the task requires it:
54
54
 
55
55
  - **Triage & escalation** → `references/escalation.md` — urgency classification (RED/AMBER/GREEN), customer handoff protocol, voice IVR handling
56
56
  - **Scheduling & briefings** → `references/scheduling.md` — booking protocol, geographic clustering, travel time estimation, morning briefings, holiday mode, GPS integration
57
- - **Quotes (lightweight)** → `references/quoting.md` — photo-to-quote, formatting, follow-up timings
58
- - **Pricing method** → invoke the `pricing-method` skill (via the Skill tool) to build, edit, re-learn, or verify an operator's own pricing method — the items, quantity rules, pricing rules, and roll-up the quote flow consumes
59
- - **Priced quote compute** → `references/quote-engine.md` — generate & run the owner's bespoke pricing engine (measured/counted work → priced result), domain-agnostic compute contract
60
- - **Quote generation (engine-driven outputs)** → `references/quote-generation.md` — the output contract for a priced job: internal margin-bearing view + client breakdown + client quote, each reconciling to one engine total and rendered to PDF
61
57
  - **Invoices & payment** → `references/invoicing.md` — HTML invoice creation, PDF generation via `browser-navigate` + `browser-pdf-save`, sending, payment chase protocol
62
58
  - **Customer records** → `references/crm.md` — contact record management, `contact_lookup`/`contact_update` usage, pipeline tracking, when to create/update records
63
59
  - **Document filing** → `references/document-management.md` — dual-scope filing system, naming conventions, folder structure for customer-facing vs internal documents
@@ -49,7 +49,7 @@ either is a regression.
49
49
  | `/session-rc-spawn` | POST `{ sessionId?, name? }` (Task 543). Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`, which waits up to **60 s** (Task 648, raised from 12 s) for the spawned PTY to bind and returns `{ spawnedPid, sessionId, bridgeSessionId, slug, outcome, reason }`. The Sidebar navigates the opened tab to `claude.ai/code/session_<id>` on `outcome=bound`; on `timeout` or `spawn-failed` it shows an error modal (reason + sessionId) and **never** opens a bare claude.ai/code tab. The new process registers itself as its own Remote Control entry in claude.ai/code. | `POST /` |
50
50
  | `/claude-sessions` | **Spawn surface only** (Task 500). `POST /` is the Sidebar new-session-with-prompt path, cookie-auth only (Task 626 removed the recorder loopback caller; LinkedIn ingest moved to `/rc-spawn`). The former UI-facing handlers (SSE row feed, list, resume, stop, rename, archive, delete, `/:id/meta`, `/:id/input`, `/:id/log`) were removed — the maxy dashboard no longer manages or displays sessions. | `POST /` |
51
51
 
52
- Task 500 — **admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot. The maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
52
+ Task 500 — **admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot; the reasoning-effort lever is `account.json.effort` → `settings.json "effortLevel"` (accepted values `low|medium|high|xhigh`; any other value, e.g. legacy `"auto"`, leaves the key unset so claude's own default governs), written by the same read-merge-write at boot. The maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
53
53
 
54
54
  **Row title resolution.** Both the sidebar (`/sidebar-sessions`) and the manager's own row payload resolve a row's title in the same order: operator rename → Claude Code `ai-title` → first non-CLI user message → 8-char sessionId prefix. The operator-rename tier is the on-disk `<accountDir>/session-titles.json` (the manager's `UserTitleStore`), keyed by the CC sessionId — the sidebar reads that same file, so a write to the store lights up both surfaces with one write.
55
55
 
@@ -42,6 +42,14 @@ Once you have corpus entries tagged (or after automatic PTY ingestion fills the
42
42
 
43
43
  The profile re-runs automatically when your corpus grows by ≥20% for any format or every 30 days, whichever comes first.
44
44
 
45
+ ## Your Voice and the House Voice
46
+
47
+ There are two kinds of profile. **Your voice** is learned from your own writing — it's what an email drafted under your name should sound like. **The house voice** is learned from everyone's writing on the account as a whole — it's what something that goes out under the business's name should sound like, like a brochure or an investor document.
48
+
49
+ Drafting picks the right one for you: emails use your voice; brochures and investor documents use the house voice. If you ask for your own voice but haven't tagged any of your own writing yet, {{productName}} quietly uses the house voice instead, so drafts still sound right rather than generic.
50
+
51
+ When you tag content, it's attributed to you by default. On a shared account with more than one person, you can attribute a piece to whoever actually wrote it, so each person's voice stays their own while the house voice draws on all of it.
52
+
45
53
  ## Feedback Loop
46
54
 
47
55
  When you edit an agent draft before sending — shorten a sentence, change a sign-off, swap a phrase — {{productName}} captures the edit and feeds it into the next distillation. The more you edit, the closer the voice gets.
@@ -54,7 +62,7 @@ Voice mirror is on by default for every drafting skill. To opt out for one, set
54
62
 
55
63
  ## What It Won't Do
56
64
 
57
- - **Blend voices** — one profile set per person, no "Joel + Neo combined".
65
+ - **Blend two named people** — you get a profile per person plus one house voice for the whole account, but not a bespoke "Joel + Neo combined" voice.
58
66
  - **Copy public figures** — voice mirror only learns from your own writing.
59
67
  - **Clone audio** — text only, no speech synthesis.
60
68
  - **Guess** — historical content stays `unknown` until you mark it. {{productName}} never auto-classifies your writing. (Automatic ingestion applies only to your live PTY sessions where authorship is certain.)
@@ -18,7 +18,7 @@ When loading this reference, confirm which schema files were consulted by noting
18
18
  | Job | `Order` | `schema:Order` + `cdm:Opportunity` | — | `accountId`, `orderNumber`, `customer` (id), `orderStatus` |
19
19
  | Event | `Event` | `schema:Event` | iCalendar (RFC 5545) | `accountId`, `name`, `startDate`, `endDate` |
20
20
  | Invoice | `Invoice` | `schema:Invoice` | UBL 2.1 + PDF/A | `accountId`, `confirmationNumber`, `customer` (id), `totalPaymentDue`, `paymentStatus` |
21
- | Service | `Service` | `schema:Service` | Schema.org JSON-LD | `accountId`, `name`, `description`, `offers` (price) |
21
+ | Service | `Service` | `schema:Service` | Schema.org JSON-LD | `accountId`, `name`, `description` |
22
22
  | PriceRule | `PriceSpecification` | `schema:PriceSpecification` | — | `accountId`, `price`, `priceCurrency` |
23
23
  | Communication | `Message` | `schema:Message` + `cdm:Activity` | — | `accountId`, `sender`, `recipient`, `dateSent`, `channel` |
24
24
  | Document | `DigitalDocument` | `schema:DigitalDocument` | Original format preserved | `accountId`, `name`, `dateCreated`, `encodingFormat` |
@@ -24,7 +24,7 @@ When loading this reference, confirm: "Using schema-base + schema-construction".
24
24
  | SubInvoice | `SubInvoice` | `schema:Invoice` | `accountId`, `subContractorId`, `jobId`, `period`, `days`, `amount`, `status` |
25
25
  | WhatsAppGroup | `WhatsAppGroup` | `cdm:Channel` | `accountId`, `groupId`, `jobId`, `clientName` |
26
26
 
27
- These entities are grounded in real builder job folders (the G.L. Smith & Sons "1845 12 Hickman Close" job: the `Q-1845` quote, the `1845.xlsx` Val/BDS 40+ line-item sheet, supplier invoices, and the per-trade structure). The 40+ `LineItem` rows per `Job` mirror the Val/BDS trade structure: Groundworks, Sub-Structure, Superstructure, Roof, Structural Alterations & Envelope, First Fix, Drylining & Plastering, Floor Screed, 2nd Fixing, Knock Throughs, Windows & Doors, Completion Items, Preliminaries, plus sub-contractor trades (Scaffolding, Roofing, Electrical, Plumbing, Plastering, Tiling, Decorations).
27
+ These entities model a general builder job folder: a `Job` carries many `LineItem` rows organised by trade stage, a generated client `QuoteDocument`, supplier and sub-contractor invoices, and per-trade structure. A residential building job's line items typically span stages such as groundworks, sub-structure, superstructure, roof, structural alterations & envelope, first fix, drylining & plastering, floor screed, second fixing, knock-throughs, windows & doors, completion items and preliminaries, plus sub-contractor trades (scaffolding, roofing, electrical, plumbing, plastering, tiling, decorations). The schema carries no client, job, or pricing data of its own — those are per-account runtime values.
28
28
 
29
29
  ### Distinctions from schema-trades
30
30
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=format-login-start.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-login-start.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/format-login-start.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { buildLoginStartText } from "../format.js";
3
+ describe("buildLoginStartText", () => {
4
+ it("renders the pairing code and the phone-side steps", () => {
5
+ const text = buildLoginStartText({ message: "msg", pairingCode: "ABCD1234" });
6
+ expect(text).toContain("ABCD1234");
7
+ expect(text).toContain("Link with phone number instead");
8
+ expect(text).toContain("whatsapp-login-wait");
9
+ });
10
+ it("falls back to the message when no code is present", () => {
11
+ const text = buildLoginStartText({ message: "WhatsApp already linked (+44...)." });
12
+ expect(text).toContain("already linked");
13
+ expect(text).not.toContain("Link with phone number instead");
14
+ });
15
+ });
16
+ //# sourceMappingURL=format-login-start.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-login-start.test.js","sourceRoot":"","sources":["../../src/__tests__/format-login-start.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9E,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,CAAC;QACnF,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /** Pure formatters for WhatsApp MCP tool results (testable without booting the server). */
2
+ export declare function buildLoginStartText(result: {
3
+ message?: string;
4
+ pairingCode?: string;
5
+ selfPhone?: string;
6
+ }): string;
7
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAE3F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAkBT"}
@@ -0,0 +1,21 @@
1
+ /** Pure formatters for WhatsApp MCP tool results (testable without booting the server). */
2
+ export function buildLoginStartText(result) {
3
+ let response = result.message ?? "";
4
+ if (result.pairingCode) {
5
+ response = [
6
+ `WhatsApp pairing code: ${result.pairingCode}`,
7
+ "",
8
+ "Tell the operator, on the phone whose number this is:",
9
+ "1. Open WhatsApp → Settings → Linked Devices → Link a Device",
10
+ '2. Tap "Link with phone number instead"',
11
+ `3. Enter this code: ${result.pairingCode}`,
12
+ "",
13
+ "Then call whatsapp-login-wait to poll for completion.",
14
+ ].join("\n");
15
+ }
16
+ if (result.selfPhone) {
17
+ response += `\nLinked phone: ${result.selfPhone}`;
18
+ }
19
+ return response;
20
+ }
21
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAE3F,MAAM,UAAU,mBAAmB,CAAC,MAInC;IACC,IAAI,QAAQ,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IACpC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,QAAQ,GAAG;YACT,0BAA0B,MAAM,CAAC,WAAW,EAAE;YAC9C,EAAE;YACF,uDAAuD;YACvD,8DAA8D;YAC9D,yCAAyC;YACzC,uBAAuB,MAAM,CAAC,WAAW,EAAE;YAC3C,EAAE;YACF,uDAAuD;SACxD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,QAAQ,IAAI,mBAAmB,MAAM,CAAC,SAAS,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -10,6 +10,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
10
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
11
  import { z } from "zod";
12
12
  import { callApi as rawCallApi } from "./call-api.js";
13
+ import { buildLoginStartText } from "./format.js";
13
14
  import { requirePortEnv } from "../../../../lib/require-port-env/dist/index.js";
14
15
  // Task 142 — PLATFORM_PORT is the internal loopback port, stamped on
15
16
  // the claude-session-manager systemd unit and forwarded by the
@@ -49,36 +50,23 @@ function textResult(text, isError = false) {
49
50
  };
50
51
  }
51
52
  // ─── whatsapp-login-start ──────────────────────────────────────────────
52
- server.tool("whatsapp-login-start", "Start WhatsApp QR code pairing. Initiates a Baileys WebSocket and generates a QR code the user scans with their phone. The tool returns the QR as a scannable ASCII block in its resultshow that block verbatim to the operator so they can scan it.", {
53
+ server.tool("whatsapp-login-start", 'Start WhatsApp pairing. Requires the operator\'s WhatsApp phone number (E.164). Returns an 8-character pairing code the operator types into WhatsApp Linked Devices Link a Device "Link with phone number instead." No QR image this surface is an async chat where a rotating QR cannot be scanned in time.', {
54
+ phone: z.string().describe("WhatsApp phone number in E.164 (e.g. +441234567890) — the number being linked"),
53
55
  accountId: z.string().optional().describe('Account ID (default: "default")'),
54
56
  force: z.boolean().optional().describe("Force re-link even if already connected"),
55
- }, async ({ accountId, force }) => {
57
+ }, async ({ phone, accountId, force }) => {
56
58
  try {
57
- const result = await callApi("whatsapp-login-start", "/api/whatsapp/login/start", "POST", { accountId, force });
59
+ const result = await callApi("whatsapp-login-start", "/api/whatsapp/login/start", "POST", { phone, accountId, force });
58
60
  if (result.error)
59
61
  return textResult(`Login start failed: ${result.error}`, true);
60
- let response = result.message;
61
- if (result.qrTerminal) {
62
- // PTY stdout is the only surface — print the QR as a scannable ASCII
63
- // block (fenced so the operator's terminal renders it monospaced).
64
- // Show this block verbatim to the operator so they can scan it.
65
- response += `\n\nScan this QR in WhatsApp → Linked Devices:\n\n\`\`\`\n${result.qrTerminal}\`\`\``;
66
- response += "\n\nThen call whatsapp-login-wait to poll for scan completion.";
67
- }
68
- else if (result.qrRaw) {
69
- response += "\n\nQR generated but could not be rendered for the terminal. Call whatsapp-login-wait to poll for scan completion.";
70
- }
71
- if (result.selfPhone) {
72
- response += `\nLinked phone: ${result.selfPhone}`;
73
- }
74
- return textResult(response);
62
+ return textResult(buildLoginStartText(result));
75
63
  }
76
64
  catch (err) {
77
65
  return textResult(`Login start failed: ${err instanceof Error ? err.message : String(err)}`, true);
78
66
  }
79
67
  });
80
68
  // ─── whatsapp-login-wait ───────────────────────────────────────────────
81
- server.tool("whatsapp-login-wait", "Wait for WhatsApp QR code to be scanned and connection to be established. Call after whatsapp-login-start. Polls for up to 60 seconds.", {
69
+ server.tool("whatsapp-login-wait", "Wait for the operator to enter the WhatsApp pairing code and the connection to establish. Call after whatsapp-login-start. Polls for up to 60 seconds; the pairing code stays valid and the login stays alive across polls, so call again to keep waiting.", {
82
70
  accountId: z.string().optional().describe('Account ID (default: "default")'),
83
71
  timeoutMs: z.number().optional().describe("Max wait time in ms (default: 60000)"),
84
72
  }, async ({ accountId, timeoutMs }) => {
@@ -107,6 +95,10 @@ server.tool("whatsapp-status", "Get WhatsApp connection status for all linked ac
107
95
  return textResult("No WhatsApp accounts configured. Say \"connect WhatsApp\" to get started.");
108
96
  }
109
97
  const lines = accounts.map((a) => {
98
+ if (a.linkedUnconfigured) {
99
+ const phone = a.selfPhone ? ` (${a.selfPhone})` : "";
100
+ return `${a.accountId}${phone}: ⚠ Linked but config was missing — repaired automatically. Re-run whatsapp-status to confirm it now shows Connected; if not, reconnect with "connect WhatsApp".`;
101
+ }
110
102
  const status = a.connected ? "✓ Connected" : "✗ Disconnected";
111
103
  const phone = a.selfPhone ? ` (${a.selfPhone})` : "";
112
104
  const name = a.accountName ? ` — ${a.accountName}` : "";