@rubytech/create-maxy-code 0.1.188 → 0.1.190

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 (141) hide show
  1. package/dist/index.js +129 -38
  2. package/package.json +1 -1
  3. package/payload/platform/lib/graph-search/dist/index.d.ts +12 -0
  4. package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
  5. package/payload/platform/lib/graph-search/dist/index.js +4 -1
  6. package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
  7. package/payload/platform/lib/graph-search/src/index.ts +4 -2
  8. package/payload/platform/neo4j/schema.cypher +16 -1
  9. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  10. package/payload/platform/plugins/admin/PLUGIN.md +3 -5
  11. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.d.ts +2 -0
  12. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.d.ts.map +1 -0
  13. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.js +79 -0
  14. package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.js.map +1 -0
  15. package/payload/platform/plugins/admin/mcp/dist/index.js +21 -95
  16. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  17. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts +9 -0
  18. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.d.ts.map +1 -1
  19. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js +47 -0
  20. package/payload/platform/plugins/admin/mcp/dist/skill-resolution.js.map +1 -1
  21. package/payload/platform/plugins/admin/skills/file-presentation/SKILL.md +6 -12
  22. package/payload/platform/plugins/admin/skills/professional-document/SKILL.md +1 -1
  23. package/payload/platform/plugins/docs/references/admin-ui.md +1 -2
  24. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  25. package/payload/platform/plugins/docs/references/voice-mirror-guide.md +2 -0
  26. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
  27. package/payload/platform/plugins/memory/PLUGIN.md +4 -1
  28. package/payload/platform/plugins/memory/mcp/dist/index.js +63 -0
  29. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  30. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.d.ts +2 -0
  31. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.d.ts.map +1 -0
  32. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.js +135 -0
  33. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.js.map +1 -0
  34. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.d.ts +16 -0
  35. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.d.ts.map +1 -0
  36. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.js +56 -0
  37. package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.js.map +1 -0
  38. package/payload/platform/plugins/scheduling/PLUGIN.md +1 -1
  39. package/payload/platform/plugins/scheduling/mcp/dist/index.js +1 -1
  40. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  41. package/payload/platform/scripts/identity-forbidden-token-check.mjs +6 -5
  42. package/payload/platform/scripts/setup-account.sh +6 -1
  43. package/payload/platform/scripts/smoke-boot-services.sh +1 -0
  44. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -1
  45. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  46. package/payload/platform/services/claude-session-manager/dist/config.d.ts +4 -0
  47. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  48. package/payload/platform/services/claude-session-manager/dist/config.js +6 -1
  49. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  50. package/payload/platform/services/claude-session-manager/dist/index.js +1 -0
  51. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  52. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +4 -0
  53. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  54. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +8 -2
  55. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  56. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  57. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +7 -9
  58. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  59. package/payload/platform/templates/agents/admin/IDENTITY.md +14 -1
  60. package/payload/platform/templates/specialists/agents/content-producer.md +2 -2
  61. package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
  62. package/payload/platform/templates/specialists/agents/librarian.md +1 -0
  63. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  64. package/payload/premium-plugins/writer-craft/skills/voice-mirror/SKILL.md +6 -0
  65. package/payload/server/public/assets/{Checkbox-ChWmQ7if.js → Checkbox-g2WZRfCt.js} +1 -1
  66. package/payload/server/public/assets/{admin-BLi_fAKQ.js → admin-Cv2A5vnQ.js} +53 -53
  67. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DSqzB21V.js → architectureDiagram-Q4EWVU46-BVKxPUIS.js} +1 -1
  68. package/payload/server/public/assets/{blockDiagram-DXYQGD6D--otTO_UB.js → blockDiagram-DXYQGD6D-BpD-1G1V.js} +1 -1
  69. package/payload/server/public/assets/brand-BQW2DYy_.css +1 -0
  70. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CBszqa9W.js → c4Diagram-AHTNJAMY-CFl9Dr6U.js} +1 -1
  71. package/payload/server/public/assets/channel-BTEFjudQ.js +1 -0
  72. package/payload/server/public/assets/{chunk-336JU56O-ClAJP2KY.js → chunk-336JU56O-B2Uc6pEC.js} +2 -2
  73. package/payload/server/public/assets/{chunk-426QAEUC-CgLucS4H.js → chunk-426QAEUC-CcIGcm29.js} +1 -1
  74. package/payload/server/public/assets/{chunk-4TB4RGXK-BvOX6mSk.js → chunk-4TB4RGXK-Dvf5uiFR.js} +1 -1
  75. package/payload/server/public/assets/{chunk-5FUZZQ4R-uyN4XtrW.js → chunk-5FUZZQ4R-DUQR1rF9.js} +1 -1
  76. package/payload/server/public/assets/{chunk-5PVQY5BW-B6xHEzh2.js → chunk-5PVQY5BW-OTvNug7K.js} +1 -1
  77. package/payload/server/public/assets/{chunk-EDXVE4YY-9objw8tW.js → chunk-EDXVE4YY-CRAsAWbD.js} +1 -1
  78. package/payload/server/public/assets/{chunk-ENJZ2VHE-pQpbHIJL.js → chunk-ENJZ2VHE-BNllMoi_.js} +1 -1
  79. package/payload/server/public/assets/{chunk-ICPOFSXX-qS23jC3x.js → chunk-ICPOFSXX-vTeVS4qd.js} +1 -1
  80. package/payload/server/public/assets/{chunk-OYMX7WX6-C9YUwGqp.js → chunk-OYMX7WX6-BdSFcvNa.js} +1 -1
  81. package/payload/server/public/assets/{chunk-U2HBQHQK-D_pYedRJ.js → chunk-U2HBQHQK-BpFXup4D.js} +1 -1
  82. package/payload/server/public/assets/{chunk-X2U36JSP-nxf6GHD-.js → chunk-X2U36JSP-DF-6QHx4.js} +1 -1
  83. package/payload/server/public/assets/{chunk-YZCP3GAM-DqKT124V.js → chunk-YZCP3GAM-CKgDoLRT.js} +1 -1
  84. package/payload/server/public/assets/{chunk-ZZ45TVLE-CLwvpbvu.js → chunk-ZZ45TVLE-B0ACvZCZ.js} +1 -1
  85. package/payload/server/public/assets/classDiagram-6PBFFD2Q-ClkdniKF.js +1 -0
  86. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-kjJetfh2.js +1 -0
  87. package/payload/server/public/assets/clone-BllVm2iY.js +1 -0
  88. package/payload/server/public/assets/{dagre-COCXt23n.js → dagre-3yl9rfxR.js} +1 -1
  89. package/payload/server/public/assets/{dagre-KV5264BT-DmuVMrt4.js → dagre-KV5264BT-D-Ux4uwL.js} +1 -1
  90. package/payload/server/public/assets/data-DIa-MKNj.js +1 -0
  91. package/payload/server/public/assets/{diagram-5BDNPKRD-DOiLSgj_.js → diagram-5BDNPKRD-D-MOMikl.js} +1 -1
  92. package/payload/server/public/assets/{diagram-G4DWMVQ6-quY6PSZQ.js → diagram-G4DWMVQ6-DKdFcnhf.js} +1 -1
  93. package/payload/server/public/assets/{diagram-MMDJMWI5-tN2yiz0C.js → diagram-MMDJMWI5-ajamR766.js} +1 -1
  94. package/payload/server/public/assets/{diagram-TYMM5635-CjrRQNQ0.js → diagram-TYMM5635-D2Pbk2Kk.js} +1 -1
  95. package/payload/server/public/assets/{erDiagram-SMLLAGMA-CrNNMxkA.js → erDiagram-SMLLAGMA-v3o948pk.js} +1 -1
  96. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-CCUsJph7.js → flowDiagram-DWJPFMVM-byC1a6GE.js} +1 -1
  97. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-18276bri.js → ganttDiagram-T4ZO3ILL-Dybzs-Sw.js} +1 -1
  98. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-CsLsKMjN.js → gitGraphDiagram-UUTBAWPF-DvzXYLuW.js} +1 -1
  99. package/payload/server/public/assets/graph-Y5y3kw6J.js +1 -0
  100. package/payload/server/public/assets/graph-labels-BIRCh328.js +1 -0
  101. package/payload/server/public/assets/{graphlib-CmtUzIni.js → graphlib-DvH_spaA.js} +1 -1
  102. package/payload/server/public/assets/{infoDiagram-42DDH7IO-Dny_ZNz3.js → infoDiagram-42DDH7IO-C2FeU8nE.js} +1 -1
  103. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-kUhIUQE-.js → ishikawaDiagram-UXIWVN3A-CpY5W64P.js} +1 -1
  104. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DekMvAKB.js → journeyDiagram-VCZTEJTY-ymMAQVdm.js} +1 -1
  105. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-st0HNZZo.js → kanban-definition-6JOO6SKY-_NX9hNK3.js} +1 -1
  106. package/payload/server/public/assets/{lib-Ca7uCvl9.js → lib-BEvO-mE0.js} +1 -1
  107. package/payload/server/public/assets/{line-BaNk-I7J.js → line-Dz7zKWX-.js} +1 -1
  108. package/payload/server/public/assets/{mermaid-parser.core-CRCHYQ_F.js → mermaid-parser.core-BCWd1en6.js} +1 -1
  109. package/payload/server/public/assets/{mermaid.core-BaIYEciF.js → mermaid.core-gSoFkVoN.js} +3 -3
  110. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-D4u4KU2v.js → mindmap-definition-QFDTVHPH-QuIyK2bd.js} +1 -1
  111. package/payload/server/public/assets/page-BCCqlOmj.js +1 -0
  112. package/payload/server/public/assets/{page-DayPduMN.js → page-DwNvJOvr.js} +3 -3
  113. package/payload/server/public/assets/{pieDiagram-DEJITSTG-BItWEilY.js → pieDiagram-DEJITSTG-DHK0yy7U.js} +1 -1
  114. package/payload/server/public/assets/{public-Dze4yArS.js → public-BnS9zREj.js} +3 -3
  115. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CeWDBvmH.js → quadrantDiagram-34T5L4WZ-wK1jwWo5.js} +1 -1
  116. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CcosjedW.js → requirementDiagram-MS252O5E-W_mH85_d.js} +1 -1
  117. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DNGeFpUj.js → sankeyDiagram-XADWPNL6-nGAM-YLQ.js} +1 -1
  118. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-Cqy_deB6.js → sequenceDiagram-FGHM5R23-SMfUCwBH.js} +1 -1
  119. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-2yoAqEsA.js → stateDiagram-FHFEXIEX-CYKXFirH.js} +1 -1
  120. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B9ZwM8kx.js +1 -0
  121. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Dmeghpw1.js → timeline-definition-GMOUNBTQ-DethbNFa.js} +1 -1
  122. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-TX5D-Zzp.js → vennDiagram-DHZGUBPP-BUlJTe9Z.js} +1 -1
  123. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-B7mcpl5E.js → wardleyDiagram-NUSXRM2D-CL1TvZ7j.js} +1 -1
  124. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DH77CxKf.js → xychartDiagram-5P7HB3ND-Cav10l-Z.js} +1 -1
  125. package/payload/server/public/data.html +5 -5
  126. package/payload/server/public/graph.html +6 -6
  127. package/payload/server/public/index.html +8 -8
  128. package/payload/server/public/public.html +5 -5
  129. package/payload/server/server-init.cjs +12 -2
  130. package/payload/server/server.js +586 -292
  131. package/payload/server/public/assets/brand-DzacFNMk.css +0 -1
  132. package/payload/server/public/assets/channel-C-SJYogg.js +0 -1
  133. package/payload/server/public/assets/classDiagram-6PBFFD2Q-OBkxl5to.js +0 -1
  134. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CkTyus-1.js +0 -1
  135. package/payload/server/public/assets/clone-VufdPzJ-.js +0 -1
  136. package/payload/server/public/assets/data-TlJbMIfa.js +0 -1
  137. package/payload/server/public/assets/graph-D2Yvni5R.js +0 -1
  138. package/payload/server/public/assets/graph-labels-uksnCgSC.js +0 -1
  139. package/payload/server/public/assets/page-QQmuB04w.js +0 -1
  140. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-Dc5siYvu.js +0 -1
  141. /package/payload/server/public/assets/{brand-Djtb-tLQ.js → brand-BGvv6AYI.js} +0 -0
@@ -18,7 +18,7 @@ import { createConnection } from "node:net";
18
18
  import { homedir, hostname as osHostname } from "node:os";
19
19
  import QRCode from "qrcode";
20
20
  import { getSession, closeDriver } from "./lib/neo4j.js";
21
- import { findSkillOwners, computePluginReadHint, loadSkill, parseRequiredInputs } from "./skill-resolution.js";
21
+ import { findSkillOwners, computePluginReadHint, loadSkill, parseRequiredInputs, adminAuthoringSkillBlock, skillSlugFromReadArgs, AUTHORING_DISPATCH_HINT } from "./skill-resolution.js";
22
22
  import { resolvePublicHostname } from "./lib/public-hostname.js";
23
23
  import { publishSite } from "./tools/publish-site.js";
24
24
  function refusalGuidance(kind) {
@@ -1668,6 +1668,16 @@ eagerTool(server, "plugin-read", "Read a plugin definition (PLUGIN.md) or one of
1668
1668
  return refuseNoAccount("plugin-read");
1669
1669
  try {
1670
1670
  const resolvedFile = file ?? "PLUGIN.md";
1671
+ // Task 516 — plugin-read is the raw-SKILL.md read path that would
1672
+ // otherwise bypass the skill-load authoring gate. Block the admin seat
1673
+ // from reading any content-producer-owned authoring skill's files
1674
+ // (SKILL.md or its references); the slug is extracted from the file
1675
+ // path or pluginName. Same fail-open contract as skill-load.
1676
+ const authoringSlug = skillSlugFromReadArgs(pluginName, resolvedFile);
1677
+ if (adminAuthoringSkillBlock(authoringSlug, process.env)) {
1678
+ console.log(`[admin-skill-gate] role=admin skill=${authoringSlug} decision=block reason=content-producer-owned`);
1679
+ return { content: [{ type: "text", text: AUTHORING_DISPATCH_HINT }], isError: true };
1680
+ }
1671
1681
  const pluginPath = resolve(PLATFORM_ROOT, "plugins", pluginName, resolvedFile);
1672
1682
  if (!existsSync(pluginPath)) {
1673
1683
  // when the agent's pluginName/file combination misses
@@ -1796,6 +1806,15 @@ eagerTool(server, "skill-load", "Load a plugin skill's SKILL.md body by skill na
1796
1806
  }, async ({ skillName }) => {
1797
1807
  if (!ACCOUNT_ID)
1798
1808
  return refuseNoAccount("skill-load");
1809
+ // Task 516 — the admin seat may not load content-producer-owned
1810
+ // authoring skills inline; it must dispatch content-producer instead.
1811
+ // The gate is a pure name+env check before any filesystem read, and
1812
+ // fails open for non-admin / unidentified seats (content-producer's own
1813
+ // spawns carry MAXY_SPECIALIST and resolve normally).
1814
+ if (adminAuthoringSkillBlock(skillName, process.env)) {
1815
+ console.log(`[admin-skill-gate] role=admin skill=${skillName} decision=block reason=content-producer-owned`);
1816
+ return { content: [{ type: "text", text: AUTHORING_DISPATCH_HINT }], isError: true };
1817
+ }
1799
1818
  const start = Date.now();
1800
1819
  try {
1801
1820
  const outcome = await loadSkill(PLATFORM_ROOT, skillName);
@@ -1855,7 +1874,7 @@ eagerTool(server, "skill-load", "Load a plugin skill's SKILL.md body by skill na
1855
1874
  // sentinel that read like a successful render to the agent while the
1856
1875
  // chat surface saw nothing. Admin flows now use plain markdown for
1857
1876
  // reviewable artefacts and the `file-presentation` skill for downloadable
1858
- // artefacts (the skill picks `SendUserFile` or `file-attach` by inventory).
1877
+ // artefacts (delivered via `SendUserFile`, the native Claude Code surface).
1859
1878
  // The :Component / :KnowledgeDocument
1860
1879
  // persistence pipeline is preserved for historical conversations that
1861
1880
  // already carry the rows; no new conversations write to it.
@@ -2551,99 +2570,6 @@ server.tool("premium-deliver", "Deliver a purchased premium plugin. Copies plugi
2551
2570
  content: [{ type: "text", text: JSON.stringify(output, null, 2) }],
2552
2571
  };
2553
2572
  });
2554
- // ---------------------------------------------------------------------------
2555
- // file-attach — copy a generated file into the attachment store for download
2556
- // ---------------------------------------------------------------------------
2557
- eagerTool(server, "file-attach", "Attach a file from the account directory for delivery to the user on non-PTY chat " +
2558
- "surfaces (web chat, WhatsApp) where the platform UI mediates attachment rendering. " +
2559
- "On the native Claude Code PTY surface, `SendUserFile` is the delivery — `file-attach` " +
2560
- "returns an `attachmentId` envelope only and renders no chip there. Tool selection is " +
2561
- "by inventory: see the `file-presentation` skill. Copies the file into the attachment " +
2562
- "store and returns metadata the chat surface uses to present the download. The file " +
2563
- "must be within the account directory tree. The returned metadata is the operator-visible " +
2564
- "record of the attachment; quote it back to the user in plain text so they have the " +
2565
- "filename and size on screen.", {
2566
- filePath: z.string().describe("Absolute path to the file to attach"),
2567
- }, async ({ filePath }) => {
2568
- if (!ACCOUNT_ID)
2569
- return refuseNoAccount("file-attach");
2570
- const TAG = "[file-attach]";
2571
- if (!filePath || !filePath.trim()) {
2572
- return {
2573
- content: [{ type: "text", text: `${TAG} filePath is required` }],
2574
- isError: true,
2575
- };
2576
- }
2577
- const accountDir = getAccountDir();
2578
- // --- Path validation: must be within the account directory ---
2579
- let resolvedPath;
2580
- try {
2581
- const { realpathSync: rp } = await import("node:fs");
2582
- resolvedPath = rp(filePath);
2583
- const accountResolved = rp(accountDir);
2584
- if (!resolvedPath.startsWith(accountResolved + "/")) {
2585
- const sanitised = filePath.replace(accountDir, "<account>/");
2586
- console.error(`${TAG} REJECTED path=${sanitised} reason=outside_account_directory`);
2587
- return {
2588
- content: [{ type: "text", text: `${TAG} Access denied: file is outside the account directory.` }],
2589
- isError: true,
2590
- };
2591
- }
2592
- }
2593
- catch (err) {
2594
- const code = err.code;
2595
- if (code === "ENOENT") {
2596
- console.error(`${TAG} ENOENT path=${filePath}`);
2597
- return {
2598
- content: [{ type: "text", text: `${TAG} File not found: ${filePath}` }],
2599
- isError: true,
2600
- };
2601
- }
2602
- console.error(`${TAG} path validation error: ${err instanceof Error ? err.message : String(err)}`);
2603
- return {
2604
- content: [{ type: "text", text: `${TAG} Failed to validate file path: ${err instanceof Error ? err.message : String(err)}` }],
2605
- isError: true,
2606
- };
2607
- }
2608
- // --- Store in attachment store ---
2609
- const targetUrl = `http://127.0.0.1:${PLATFORM_PORT}/api/admin/file-attach`;
2610
- try {
2611
- const res = await fetch(targetUrl, {
2612
- method: "POST",
2613
- headers: { "Content-Type": "application/json" },
2614
- body: JSON.stringify({ filePath: resolvedPath, accountId: ACCOUNT_ID }),
2615
- });
2616
- const result = await res.json();
2617
- if (!res.ok || result.error) {
2618
- const msg = result.error || `HTTP ${res.status}`;
2619
- console.error(`${TAG} store failed url=${targetUrl} status=${res.status} error=${msg}`);
2620
- return {
2621
- content: [{ type: "text", text: `${TAG} Failed to attach file: ${msg} (url=${targetUrl})` }],
2622
- isError: true,
2623
- };
2624
- }
2625
- console.error(`${TAG} attached path=${resolvedPath} size=${result.sizeBytes} mime=${result.mimeType} id=${result.attachmentId}`);
2626
- return {
2627
- content: [{
2628
- type: "text",
2629
- text: JSON.stringify({
2630
- attachmentId: result.attachmentId,
2631
- filename: result.filename,
2632
- sizeBytes: result.sizeBytes,
2633
- mimeType: result.mimeType,
2634
- }),
2635
- }],
2636
- };
2637
- }
2638
- catch (err) {
2639
- const errMsg = err instanceof Error ? err.message : String(err);
2640
- console.error(`${TAG} fetch failed url=${targetUrl} error=${errMsg}`);
2641
- return {
2642
- content: [{ type: "text", text: `${TAG} Failed to attach file: could not reach platform server at ${targetUrl} (${errMsg})` }],
2643
- isError: true,
2644
- };
2645
- }
2646
- });
2647
2573
  // ===================================================================
2648
2574
  // Action approval tools (EU AI Act Article 14 — human oversight)
2649
2575
  //