@diffohq/diffo 0.4.0 → 0.5.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 (99) hide show
  1. package/dist/cli.mjs +136 -25
  2. package/dist/client/assets/{abnfDiagram-O67JEVCF-b6l_FGHi.js → abnfDiagram-O67JEVCF-Eku-JiMb.js} +1 -1
  3. package/dist/client/assets/{arc-Cz0jZwLH.js → arc-lV5GSLJD.js} +1 -1
  4. package/dist/client/assets/architecture-7GRP2DOG-Cjj-qeXa.js +1 -0
  5. package/dist/client/assets/{architectureDiagram-NJMV4G6O-CJdtqKce.js → architectureDiagram-NJMV4G6O-DIH1VGVe.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-BEXU5L5S-Ci-lnLGN.js → blockDiagram-BEXU5L5S-CaCCdXJr.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-YGBWAQC7-DDO2mTMB.js → c4Diagram-YGBWAQC7-DmnVa0_m.js} +1 -1
  8. package/dist/client/assets/channel-wy7dEM75.js +1 -0
  9. package/dist/client/assets/{chunk-3FUC2YCW-VyswqFt3.js → chunk-3FUC2YCW-DDROCT3x.js} +1 -1
  10. package/dist/client/assets/{chunk-5DYCD2WN-B4MBZW5P.js → chunk-5DYCD2WN-CL5xMelX.js} +1 -1
  11. package/dist/client/assets/{chunk-742MDFTN-Cxvmvrid.js → chunk-742MDFTN-CTz8pFT1.js} +1 -1
  12. package/dist/client/assets/{chunk-7INBJB4K-DkBnRFbH.js → chunk-7INBJB4K-mTzp3uc7.js} +1 -1
  13. package/dist/client/assets/{chunk-7M6MHVWA-BvJgBwEi.js → chunk-7M6MHVWA-AyZcKoA0.js} +1 -1
  14. package/dist/client/assets/{chunk-7PRAP22T-OfiMNi_y.js → chunk-7PRAP22T-CEPNl3r7.js} +1 -1
  15. package/dist/client/assets/{chunk-GTNCS2PH-BodN5cRQ.js → chunk-GTNCS2PH-DnfAIbaL.js} +1 -1
  16. package/dist/client/assets/{chunk-GWA4HPMP-KifxxZcy.js → chunk-GWA4HPMP-DuzmSd5n.js} +1 -1
  17. package/dist/client/assets/{chunk-MBY4JIJT-rw02bHlj.js → chunk-MBY4JIJT-BGNKEJZT.js} +1 -1
  18. package/dist/client/assets/{chunk-NETBCI7D-CWjhZoou.js → chunk-NETBCI7D-CXPYvz5G.js} +1 -1
  19. package/dist/client/assets/{chunk-O7XYJQB3-CyxnSfZ3.js → chunk-O7XYJQB3-CYftULw7.js} +1 -1
  20. package/dist/client/assets/{chunk-UA2S7LBM-BReIFgsu.js → chunk-UA2S7LBM-DQbf9Dl1.js} +1 -1
  21. package/dist/client/assets/{chunk-WEXAMYUT-DHwMy8v7.js → chunk-WEXAMYUT-CcNQw347.js} +1 -1
  22. package/dist/client/assets/{chunk-XXDRQBXY-C398QZbS.js → chunk-XXDRQBXY-Bf1t_xv6.js} +1 -1
  23. package/dist/client/assets/{chunk-Z7XXMR3K-hEV1GU64.js → chunk-Z7XXMR3K-pRmpdAOe.js} +1 -1
  24. package/dist/client/assets/{chunk-ZIGJFQKS-DJJL7llO.js → chunk-ZIGJFQKS-B5DDwrRj.js} +1 -1
  25. package/dist/client/assets/{classDiagram-v2-NBCMYWYE-pSGZI880.js → classDiagram-v2-NBCMYWYE-DCpEkxmb.js} +1 -1
  26. package/dist/client/assets/{core-C05I4wHV.js → core-Cl3AV7cB.js} +1 -1
  27. package/dist/client/assets/{cose-bilkent-JH36ORCC-DNV8Dqd8.js → cose-bilkent-JH36ORCC-DQEwYOPh.js} +1 -1
  28. package/dist/client/assets/{cynefin-OW5HDTMX-DF-6FOgS.js → cynefin-OW5HDTMX-B8MfDKLI.js} +1 -1
  29. package/dist/client/assets/{cynefinDiagram-VND7K2PF-D3-iJq2J.js → cynefinDiagram-VND7K2PF-B4WvhUhO.js} +1 -1
  30. package/dist/client/assets/{dagre-6A5THRUB-C9FDZkaa.js → dagre-6A5THRUB-B9IMFM72.js} +1 -1
  31. package/dist/client/assets/{diagram-22UHCM2B-CfSJBDyN.js → diagram-22UHCM2B-DB0QnlzY.js} +1 -1
  32. package/dist/client/assets/{diagram-3UASUU5V-D946baYo.js → diagram-3UASUU5V-DW2JbaXS.js} +1 -1
  33. package/dist/client/assets/{diagram-ATOU4E4O-CGrjukoA.js → diagram-ATOU4E4O-kELWjFhd.js} +1 -1
  34. package/dist/client/assets/{diagram-CDSNMT55-B47UPtWq.js → diagram-CDSNMT55-DHJN8X6p.js} +1 -1
  35. package/dist/client/assets/{diagram-MLGK6HIB-D06yEd5R.js → diagram-MLGK6HIB-3hlAEcUl.js} +1 -1
  36. package/dist/client/assets/{diagram-MPIPVDR6-BRUBT2B9.js → diagram-MPIPVDR6-BmI2ylfG.js} +1 -1
  37. package/dist/client/assets/{dist-DVw88SBM.js → dist-DNMzTuVG.js} +1 -1
  38. package/dist/client/assets/{dist-BfTRyLGm.js → dist-DOT26anA.js} +1 -1
  39. package/dist/client/assets/{ebnfDiagram-ZINNZB2B-BnuExfrd.js → ebnfDiagram-ZINNZB2B-lJT30vWx.js} +1 -1
  40. package/dist/client/assets/{elk-276RUBZZ-BmdcLjR9.js → elk-276RUBZZ-Y2ie1QZI.js} +1 -1
  41. package/dist/client/assets/{engine-oniguruma-Bw1dOuOO.js → engine-oniguruma-qcHcQ7gy.js} +1 -1
  42. package/dist/client/assets/{erDiagram-OPXOYQCR-CKCR3jQT.js → erDiagram-OPXOYQCR-BBPmg1YD.js} +1 -1
  43. package/dist/client/assets/eventmodeling-NTZA5JFV-BDUZgpVa.js +1 -0
  44. package/dist/client/assets/flowDiagram-KWPJA3E3-B8jw0PgP.js +1 -0
  45. package/dist/client/assets/{ganttDiagram-FUAMR5RP-BwkoweG7.js → ganttDiagram-FUAMR5RP-xPVj2AwG.js} +1 -1
  46. package/dist/client/assets/{gitGraph-4MIJSDKK-M7_hHVyH.js → gitGraph-4MIJSDKK-pvXQROBw.js} +1 -1
  47. package/dist/client/assets/{gitGraphDiagram-X574FWY7-BVm_sLT_.js → gitGraphDiagram-X574FWY7-pp7frUxm.js} +1 -1
  48. package/dist/client/assets/index-B10socvp.js +91 -0
  49. package/dist/client/assets/index-BUmM006M.css +1 -0
  50. package/dist/client/assets/{info-A6RAGUB7-DPBs3m_X.js → info-A6RAGUB7-DLCTmODc.js} +1 -1
  51. package/dist/client/assets/{infoDiagram-VRGFBTTK-DDb3KyOP.js → infoDiagram-VRGFBTTK-BGnYOvv2.js} +1 -1
  52. package/dist/client/assets/{ishikawaDiagram-OU5B5YK6-CPt4RDlr.js → ishikawaDiagram-OU5B5YK6-DYbwoJB-.js} +1 -1
  53. package/dist/client/assets/{journeyDiagram-ZHPQQLJL-ECQSHJ0N.js → journeyDiagram-ZHPQQLJL-DHav_LIH.js} +1 -1
  54. package/dist/client/assets/{kanban-definition-PNTS6WVX-tAmonxA8.js → kanban-definition-PNTS6WVX-Cj645S2T.js} +1 -1
  55. package/dist/client/assets/{line-x6vAh41a.js → line-Htxv9F4J.js} +1 -1
  56. package/dist/client/assets/{linear-BqczUNss.js → linear-e0hVUtYI.js} +1 -1
  57. package/dist/client/assets/{mermaid-parser.core-siQPZsry.js → mermaid-parser.core-DtRc-ypM.js} +3 -3
  58. package/dist/client/assets/{mermaid.core-CLHTQVF-.js → mermaid.core-CyG7EFf-.js} +4 -4
  59. package/dist/client/assets/{mindmap-definition-NLK3R4M7-C9fnEdyl.js → mindmap-definition-NLK3R4M7-501wUG6-.js} +1 -1
  60. package/dist/client/assets/{packet-AYTQ26CC-DAeK0Q4n.js → packet-AYTQ26CC-CBEtSauH.js} +1 -1
  61. package/dist/client/assets/{pegDiagram-GJSIUBJH-BrWBFYPO.js → pegDiagram-GJSIUBJH-958m_CS_.js} +1 -1
  62. package/dist/client/assets/{pie-WAS4IAKB-CnieihkO.js → pie-WAS4IAKB-CtMX8NyM.js} +1 -1
  63. package/dist/client/assets/{pieDiagram-5QR66LMP-Bp5f6Eal.js → pieDiagram-5QR66LMP-Ch_R04up.js} +1 -1
  64. package/dist/client/assets/{quadrantDiagram-O4NWA36T-ECuLA3RS.js → quadrantDiagram-O4NWA36T-WpRKg-an.js} +1 -1
  65. package/dist/client/assets/{radar-RG4KPBEZ-BJXkERy0.js → radar-RG4KPBEZ-C6cMrg-A.js} +1 -1
  66. package/dist/client/assets/{railroad-74A4TZTK-Di61fiV5.js → railroad-74A4TZTK-D5TKF4bs.js} +1 -1
  67. package/dist/client/assets/railroad-abnf-HS5TGJTU-DadVNrmb.js +1 -0
  68. package/dist/client/assets/railroad-ebnf-LZEXJU2U-Can6uT-b.js +1 -0
  69. package/dist/client/assets/railroad-peg-WCYAUIDC-BB7kTpaz.js +1 -0
  70. package/dist/client/assets/{railroadDiagram-XR7U4H2S-Dn2WPOQe.js → railroadDiagram-XR7U4H2S-CsGtkzal.js} +1 -1
  71. package/dist/client/assets/{requirementDiagram-PLB6GJNP-uuvtvHmq.js → requirementDiagram-PLB6GJNP-By5yShOx.js} +1 -1
  72. package/dist/client/assets/{sankeyDiagram-IPEJSGJF-BXk6X0af.js → sankeyDiagram-IPEJSGJF-D0iqRNhC.js} +1 -1
  73. package/dist/client/assets/{sequenceDiagram-PO4LG4MO-BsPoSXhg.js → sequenceDiagram-PO4LG4MO-BbN6AjiL.js} +1 -1
  74. package/dist/client/assets/{src-B4djUhOi.js → src-BPEEiDps.js} +1 -1
  75. package/dist/client/assets/{stateDiagram-v2-GCMORJYK-cCml5k6n.js → stateDiagram-v2-GCMORJYK-69H8hCN6.js} +1 -1
  76. package/dist/client/assets/{swimlanes-2SLR337P-Dh7v55ZA.js → swimlanes-2SLR337P-VMJm_C1R.js} +1 -1
  77. package/dist/client/assets/swimlanesDiagram-TC7HE7FX-C9C4mAsA.js +8 -0
  78. package/dist/client/assets/{timeline-definition-EJHVYXUP-LFjkFV14.js → timeline-definition-EJHVYXUP-DWTI0Vqo.js} +1 -1
  79. package/dist/client/assets/{treeView-Q6P3EWNA-RYZHSXeB.js → treeView-Q6P3EWNA-DoBvpaMV.js} +1 -1
  80. package/dist/client/assets/{treemap-WGGIJYW6-UVw_-EPz.js → treemap-WGGIJYW6-B43_cUvq.js} +1 -1
  81. package/dist/client/assets/{usecaseDiagram-POWQR4AR-DZfPogyb.js → usecaseDiagram-POWQR4AR-C9eMeNe5.js} +1 -1
  82. package/dist/client/assets/{vennDiagram-UO4OBE2U-CN7Ldg-2.js → vennDiagram-UO4OBE2U-pUMZhTOS.js} +1 -1
  83. package/dist/client/assets/{wardley-WFR3VGLG-CXPbbIy_.js → wardley-WFR3VGLG-CIzaJFvJ.js} +1 -1
  84. package/dist/client/assets/{wardleyDiagram-VNRHLVJA-5p0A7_g6.js → wardleyDiagram-VNRHLVJA-Cj_u7NlG.js} +1 -1
  85. package/dist/client/assets/{xychartDiagram-PMCCYNJV-gJ7xwZXO.js → xychartDiagram-PMCCYNJV-mGddxyW6.js} +1 -1
  86. package/dist/client/index.html +2 -2
  87. package/package.json +1 -1
  88. package/plugin.json +1 -1
  89. package/skills/diffo/SKILL.md +6 -5
  90. package/dist/client/assets/architecture-7GRP2DOG-BXYREMFQ.js +0 -1
  91. package/dist/client/assets/channel-CtvNwuQX.js +0 -1
  92. package/dist/client/assets/eventmodeling-NTZA5JFV-C7ouopD6.js +0 -1
  93. package/dist/client/assets/flowDiagram-KWPJA3E3-C2o4wCpi.js +0 -1
  94. package/dist/client/assets/index-BEG1ZxrX.css +0 -1
  95. package/dist/client/assets/index-BwDjlzOZ.js +0 -91
  96. package/dist/client/assets/railroad-abnf-HS5TGJTU-DCBYLLLl.js +0 -1
  97. package/dist/client/assets/railroad-ebnf-LZEXJU2U-VWOalqH1.js +0 -1
  98. package/dist/client/assets/railroad-peg-WCYAUIDC-BTTWaHra.js +0 -1
  99. package/dist/client/assets/swimlanesDiagram-TC7HE7FX-q8VF72XO.js +0 -8
package/dist/cli.mjs CHANGED
@@ -73,6 +73,11 @@ function detectSessionPid() {
73
73
  //#endregion
74
74
  //#region src/shared/review.ts
75
75
  const THREAD_INTENTS = ["fix", "question"];
76
+ function parseSuggestedReply(value) {
77
+ if (typeof value !== "string") return void 0;
78
+ const line = value.replace(/\s+/g, " ").trim();
79
+ return line ? line.slice(0, 120) : void 0;
80
+ }
76
81
  /** The thread was started by the agent (its opening message is the agent's).
77
82
  * Drives rendering — avatar, head label — and never changes. */
78
83
  function startedByAgent(thread) {
@@ -274,20 +279,36 @@ const ACK_NEXT_STEP = {
274
279
  /**
275
280
  * The guide doctrine — the one agent comment that orients a cold reader.
276
281
  * Stated once and interpolated into every surface that teaches it (the skill,
277
- * `help agent`, the open-time nudge below), the same way POLL_STANCE keeps the
278
- * poll rules aligned: the surfaces phrase it at different lengths, but these
279
- * invariants cannot drift apart.
282
+ * `help agent`, `help guide`, the open-time nudge below), the same way
283
+ * POLL_STANCE keeps the poll rules aligned: the surfaces phrase it at different
284
+ * lengths, but these invariants cannot drift apart.
285
+ *
286
+ * It is a map, not a tour. Every other tool infers a summary by reading the
287
+ * diff back; the session that wrote the change still holds what no diff shows
288
+ * — the invariant it had to respect, the seam it chose, the alternative it
289
+ * rejected, what it left alone on purpose — and that is what the reviewer
290
+ * cannot get anywhere else. Reading order is not on the list: layers own it.
280
291
  */
281
292
  const GUIDE = {
282
293
  /** When one is warranted — and that silence is a valid outcome. */
283
294
  when: "multi-file, structural, or subtle — skip when the diff explains itself",
284
- /** What it contains. */
285
- what: "one sentence on what the change does, plus a small ```mermaid diagram if a picture explains the shape better than words",
295
+ /** What it contains: ingredients, not sections — use the ones this change needs. */
296
+ what: "a map of the change, not a tour of it: what it does and why, in a sentence; how the changed pieces talk to each other, as a small ```mermaid diagram of the runtime flow (functions and modules, not a file list) when a picture beats words; what is worth checking as they read — an invariant the change must keep, a judgment call it made, a shortcoming it knows about — said in plain words, never behind a label of your own; and what is safe to skip",
286
297
  /** The line it must not cross. */
287
298
  stance: "Orient reading, never pre-review: no verdicts, nothing is \"fine\"",
299
+ /** What layers took over: the guide never orders the read. */
300
+ order: "no reading order and no file list — layers and the Files tab own those; a change that reads better in order gets a layers suggestion, not a numbered guide",
301
+ /** How much: one screen, and only the parts that apply. */
302
+ budget: "about a hundred words of prose plus the diagram — one screen; use only the parts this change needs, in whatever form fits",
303
+ /** The diagram convention: two tags, and a plain node means existing code. */
304
+ legend: "in the diagram tag new code `:::new` and changed code `:::changed`, declared by the two classDef lines below; a plain node is existing code the change now leans on",
288
305
  /** Staleness: the guide is a thread, so updates land under it. */
289
306
  update: "reply to your own guide thread with a short update"
290
307
  };
308
+ /** The two classDef lines the legend refers to, verbatim — pasted at the foot
309
+ * of the diagram. Strokes only, in hexes both renderers honour and both themes
310
+ * read; fills stay the renderer's own, so the diagram still follows the theme. */
311
+ const GUIDE_CLASSDEFS = ["classDef new stroke:#2e9e4f,stroke-width:2px", "classDef changed stroke:#d99a00,stroke-width:2px"];
291
312
  /**
292
313
  * The layers doctrine — the agent's reading plan for a changeset with an order
293
314
  * worth explaining. Same single-source rule as GUIDE: the skill, `help agent`,
@@ -329,7 +350,7 @@ const LAYERS = {
329
350
  */
330
351
  function guideNudge(hasGuide) {
331
352
  if (hasGuide) return null;
332
- return `share the URL above with the user right now, as a message line, before anything else. Then, while they open it, orient them if this changeset needs it (${GUIDE.when}): post a guide — one comment on the whole changeset: ${GUIDE.what}: \`${CLI_COMMANDS.guide}\` (no file, so it anchors to the changeset; it appears live at the top of their review). ${GUIDE.stance}.`;
353
+ return `share the URL above with the user right now, as a message line, before anything else. Then, while they open it, orient them if this changeset needs it (${GUIDE.when}): post a guide — one comment on the whole changeset: \`${CLI_COMMANDS.guide}\` (no file, so it anchors to the changeset; it appears live at the top of their review). It is ${GUIDE.what}. Not in it: ${GUIDE.order}. How much: ${GUIDE.budget}. ${GUIDE.stance}. \`diffo help guide\` has the diagram legend and one example.`;
333
354
  }
334
355
  /**
335
356
  * Printed by `diffo` (open) next to the guide nudge while the review has neither
@@ -630,7 +651,7 @@ function buildClearedPrompt(ctx) {
630
651
  `The reviewer cleared the review in \`${ctx.repo.name}\` (branch \`${ctx.repo.branch}\`): the previous round landed, and its threads and guide are gone. What the reviewer sees now is a fresh round.`,
631
652
  "",
632
653
  ...ctx.changeset ? [specLine(ctx.changeset), ""] : [],
633
- `There is no feedback to act on. But the fresh round has no guide — if this changeset needs one (${GUIDE.when}): post it — one comment on the whole changeset: ${GUIDE.what}: \`${CLI_COMMANDS.guide}\` (no file, so it anchors to the changeset). ${GUIDE.stance}.`,
654
+ `There is no feedback to act on. But the fresh round has no guide — if this changeset needs one (${GUIDE.when}): post it — one comment on the whole changeset: \`${CLI_COMMANDS.guide}\` (no file, so it anchors to the changeset). It is ${GUIDE.what}. Not in it: ${GUIDE.order}. How much: ${GUIDE.budget}. ${GUIDE.stance}. \`diffo help guide\` has the diagram legend and one example.`,
634
655
  "",
635
656
  `Then run \`${CLI_COMMANDS.poll}\` again to keep listening (${POLL_STANCE}).`,
636
657
  ""
@@ -849,6 +870,7 @@ For the agent (the AI that wrote the change):
849
870
  or --stdin posts the list, replacing the last one)
850
871
  end Detach from the review politely
851
872
  help agent The agent's whole protocol on one page
873
+ help guide The guide comment — the map of the change — with an example
852
874
 
853
875
  Options (for opening the review):
854
876
  --base <branch> Review everything since forking from <branch>
@@ -890,9 +912,12 @@ The loop:
890
912
  2. Guide — post one only when the changeset needs orientation:
891
913
  ${GUIDE.when}.
892
914
  Right after sharing the URL, while the reviewer opens the page, post ONE
893
- comment on the whole changeset (\`diffo comment -m "…"\`, no file),
894
- containing: ${GUIDE.what}.
915
+ comment on the whole changeset (\`diffo comment -m "…"\`, no file). It is
916
+ ${GUIDE.what}.
917
+ Not in it: ${GUIDE.order}.
918
+ How much: ${GUIDE.budget}.
895
919
  ${GUIDE.stance}.
920
+ Legend: ${GUIDE.legend} — \`diffo help guide\` has them, and one example.
896
921
  It lands live at the top of their review — never hold the URL back for it.
897
922
  If the changeset later shifts under the guide, ${GUIDE.update}.
898
923
  3. Layers — offer them when the changeset reads better in order:
@@ -922,6 +947,11 @@ The loop:
922
947
  plain reply before the next poll.
923
948
  7. Comment (sparingly): \`diffo comment [<file>] [--line <n>] -m "<text>"\`
924
949
  starts a thread in your voice — a concern, or context that helps the read.
950
+ When a reply or comment of yours ends in a decision that is the
951
+ reviewer's ("want me to extract this?"), add \`--suggest-reply "<one
952
+ line>"\` — it shows as ghost text in their reply box, taken with Tab.
953
+ Offer the answer you expect, not a menu; skip it on messages that only
954
+ report.
925
955
  8. Poll again only when the whole batch is handled — a new poll tells the
926
956
  reviewer you are done with the previous one.
927
957
  9. Detach: run \`diffo end\` when the review is over or the user moves on.
@@ -934,6 +964,54 @@ Rules:
934
964
  a poll says it took the review over, or returns status "superseded", say so
935
965
  to the user: their feedback moved with it.
936
966
  - Resolving a thread is the reviewer's call, never yours.`,
967
+ guide: `diffo help guide — the map an agent posts on the whole changeset
968
+
969
+ Posted with \`diffo comment -m "…"\` (no file, so it anchors to the changeset)
970
+ right after sharing the URL, while the reviewer opens the page — and only
971
+ when the changeset needs orientation: ${GUIDE.when}.
972
+
973
+ It is ${GUIDE.what}.
974
+ Not in it: ${GUIDE.order}.
975
+ How much: ${GUIDE.budget}.
976
+ ${GUIDE.stance}.
977
+ Legend: ${GUIDE.legend}:
978
+
979
+ ${GUIDE_CLASSDEFS[0]}
980
+ ${GUIDE_CLASSDEFS[1]}
981
+
982
+ A file named as \`path\` or \`path:line\` — in backticks, or in a diagram
983
+ node — becomes a jump into the review, so the map is navigation too.
984
+ If the changeset later shifts under the guide, ${GUIDE.update}.
985
+
986
+ Say each part in plain words a reader meets cold — "worth checking as you
987
+ read", "safe to skip" — never a label of your own like "Hold:" that they
988
+ would have to decode.
989
+
990
+ One shape that works — not THE shape: a rename needs no diagram, a one-file
991
+ change needs no checks, and headings are optional.
992
+
993
+ Caps oversized tool results at the model boundary and adds
994
+ \`read_tool_result\` so the model can page the rest — nothing is stored,
995
+ the text is recomputed on read.
996
+
997
+ \`\`\`mermaid
998
+ flowchart LR
999
+ E[tool.execute] --> W[withToolResultCap]:::new
1000
+ W -->|over budget: slice + notice| P[provider]
1001
+ M[read_tool_result]:::new --> R[resolveFullToolResult]:::new
1002
+ R --> S[SDK steps · raw output]
1003
+ T[island-chat-transport.ts · prepareStep]:::changed --> W
1004
+ ${GUIDE_CLASSDEFS[0]}
1005
+ ${GUIDE_CLASSDEFS[1]}
1006
+ \`\`\`
1007
+
1008
+ Worth checking as you read: the capper and the reader must agree, byte for
1009
+ byte, on one string — \`canonicalToolText\` is the only definition both use.
1010
+ And the reader re-runs each tool's own \`toModelOutput\`, which assumes every
1011
+ converter is pure.
1012
+
1013
+ Safe to skip: four \`tool-*\` display components moved only because a prop
1014
+ went dead.`,
937
1015
  poll: `diffo poll — wait for the reviewer's feedback
938
1016
 
939
1017
  Usage: diffo poll [--title "<what the change is>"]
@@ -957,7 +1035,7 @@ Examples:
957
1035
  diffo poll`,
958
1036
  reply: `diffo reply — post a reply to a review thread
959
1037
 
960
- Usage: diffo reply <threadId> --message "<text>"
1038
+ Usage: diffo reply <threadId> --message "<text>" [--suggest-reply "<one line>"]
961
1039
  … | diffo reply <threadId> (long replies: pipe on stdin)
962
1040
 
963
1041
  Thread ids arrive in poll payloads. Each run posts one message, so don't
@@ -966,6 +1044,11 @@ re-run a reply that succeeded.
966
1044
  reply on this thread is promised. The reviewer keeps seeing the thread as
967
1045
  "with the agent" until your next plain reply; going quiet instead marks it
968
1046
  unanswered.
1047
+ --suggest-reply offers the reviewer their answer: one line that appears as
1048
+ ghost text in their reply box, taken with Tab, edited or ignored at will.
1049
+ Use it when your message ends in a decision that is theirs to make
1050
+ ("want me to extract this?" → --suggest-reply "yes, extract it"); never
1051
+ on a message that only reports.
969
1052
  Messages render GitHub-flavored markdown; a \`\`\`mermaid fence renders as a
970
1053
  diagram in the review.
971
1054
 
@@ -975,7 +1058,7 @@ Example:
975
1058
  diffo reply t-3 --message "fixed — the guard now covers the empty case"`,
976
1059
  comment: `diffo comment — start a comment thread as the agent
977
1060
 
978
- Usage: diffo comment [<file>] [--line <n>] --message "<text>"
1061
+ Usage: diffo comment [<file>] [--line <n>] --message "<text>" [--suggest-reply "<one line>"]
979
1062
  … | diffo comment [<file>] [--line <n>] (long comments: pipe on stdin)
980
1063
 
981
1064
  Anchors to a line (--line), a file, or — with no file — the whole changeset.
@@ -983,13 +1066,18 @@ A potential issue, or context that helps the reviewer read: either way it is
983
1066
  one thread, labeled as yours, and it never counts as the reviewer's feedback
984
1067
  until they reply into it — then it is theirs to send — or they resolve it.
985
1068
  Spend these sparingly — an agent that annotates everything gets skimmed.
1069
+ --suggest-reply offers the reviewer their answer: one line that appears as
1070
+ ghost text in their reply box, taken with Tab, edited or ignored at will.
1071
+ Use it when the comment proposes something and the call is theirs; the
1072
+ reply they take hands the thread to you like any other.
986
1073
  Messages render GitHub-flavored markdown; a \`\`\`mermaid fence renders as a
987
1074
  diagram in the review.
988
1075
 
989
1076
  Output: {"ok":true,"threadId":"t-1","next_step":"…"}
990
1077
 
991
- Example:
992
- diffo comment src/auth.ts --line 42 --message "this branch is unreachable"`,
1078
+ Examples:
1079
+ diffo comment src/auth.ts --line 42 --message "this branch is unreachable"
1080
+ diffo comment src/auth.ts --line 42 -m "I can fold these two guards into one. Want that?" --suggest-reply "yes, fold them"`,
993
1081
  layers: `diffo layers — outline the changeset as steps to read in order
994
1082
 
995
1083
  Usage: diffo layers --suggest ["<why, in one line>"] at open: this read benefits from layers
@@ -1114,7 +1202,7 @@ function parseHelp(rest) {
1114
1202
  message: "help takes at most one command"
1115
1203
  };
1116
1204
  if (topic === void 0 || topic === "help") return { kind: "help" };
1117
- if (topic !== "agent" && !VERBS.has(topic)) return unknownCommand(topic);
1205
+ if (topic !== "agent" && topic !== "guide" && !VERBS.has(topic)) return unknownCommand(topic);
1118
1206
  return {
1119
1207
  kind: "help",
1120
1208
  topic
@@ -1301,6 +1389,7 @@ function parseVerb(verb, rest) {
1301
1389
  line: { type: "string" },
1302
1390
  title: { type: "string" },
1303
1391
  more: { type: "boolean" },
1392
+ "suggest-reply": { type: "string" },
1304
1393
  json: { type: "boolean" },
1305
1394
  help: {
1306
1395
  type: "boolean",
@@ -1313,6 +1402,7 @@ function parseVerb(verb, rest) {
1313
1402
  message: parsed.message
1314
1403
  };
1315
1404
  const { values, positionals } = parsed.value;
1405
+ const suggestReply = values["suggest-reply"];
1316
1406
  if (values.help) return {
1317
1407
  kind: "help",
1318
1408
  topic: verb
@@ -1325,6 +1415,20 @@ function parseVerb(verb, rest) {
1325
1415
  kind: "error",
1326
1416
  message: `'${verb}' takes no --more`
1327
1417
  };
1418
+ if (suggestReply !== void 0) {
1419
+ if (verb !== "reply" && verb !== "comment") return {
1420
+ kind: "error",
1421
+ message: `'${verb}' takes no --suggest-reply`
1422
+ };
1423
+ if (!suggestReply.trim()) return {
1424
+ kind: "error",
1425
+ message: "--suggest-reply needs the reply you are offering"
1426
+ };
1427
+ if (suggestReply.includes("\n")) return {
1428
+ kind: "error",
1429
+ message: "--suggest-reply is one line — the reviewer completes it"
1430
+ };
1431
+ }
1328
1432
  if (values.title !== void 0 && verb !== "poll") return {
1329
1433
  kind: "error",
1330
1434
  message: `'${verb}' takes no --title`
@@ -1373,7 +1477,8 @@ function parseVerb(verb, rest) {
1373
1477
  kind: "reply",
1374
1478
  threadId,
1375
1479
  message: values.message ?? null,
1376
- more: values.more === true
1480
+ more: values.more === true,
1481
+ suggestReply: suggestReply?.trim() ?? null
1377
1482
  };
1378
1483
  }
1379
1484
  const file = positionals[0] ?? null;
@@ -1397,7 +1502,8 @@ function parseVerb(verb, rest) {
1397
1502
  kind: "comment",
1398
1503
  file,
1399
1504
  line,
1400
- message: values.message ?? null
1505
+ message: values.message ?? null,
1506
+ suggestReply: suggestReply?.trim() ?? null
1401
1507
  };
1402
1508
  }
1403
1509
  //#endregion
@@ -2799,7 +2905,7 @@ var ReviewStore = class {
2799
2905
  this.listeners.add(listener);
2800
2906
  return () => this.listeners.delete(listener);
2801
2907
  }
2802
- createThread(anchor, text, capture, intent, author = "reviewer") {
2908
+ createThread(anchor, text, capture, intent, author = "reviewer", suggestedReply) {
2803
2909
  const now = (/* @__PURE__ */ new Date()).toISOString();
2804
2910
  return this.insert({
2805
2911
  id: randomUUID(),
@@ -2813,7 +2919,8 @@ var ReviewStore = class {
2813
2919
  id: randomUUID(),
2814
2920
  author,
2815
2921
  text,
2816
- at: now
2922
+ at: now,
2923
+ ...author === "agent" && suggestedReply ? { suggestedReply } : {}
2817
2924
  }],
2818
2925
  createdAt: now,
2819
2926
  updatedAt: now
@@ -2861,13 +2968,14 @@ var ReviewStore = class {
2861
2968
  * the reviewer raced in since — appended at the end, it would render as an
2862
2969
  * answer to a comment it never saw, and the raced comment would stop reading
2863
2970
  * as "waiting on the agent" even though it still is. */
2864
- addMessage(threadId, author, text, withheld = false, seenThroughMs, followUp = false) {
2971
+ addMessage(threadId, author, text, withheld = false, seenThroughMs, followUp = false, suggestedReply) {
2865
2972
  return this.update(threadId, ({ unanswered: _answered, ...thread }) => {
2866
2973
  const message = {
2867
2974
  id: randomUUID(),
2868
2975
  author,
2869
2976
  text,
2870
- at: (/* @__PURE__ */ new Date()).toISOString()
2977
+ at: (/* @__PURE__ */ new Date()).toISOString(),
2978
+ ...author === "agent" && suggestedReply ? { suggestedReply } : {}
2871
2979
  };
2872
2980
  const raced = author === "agent" && seenThroughMs !== void 0 ? thread.messages.findIndex((m) => m.author === "reviewer" && Date.parse(m.at) > seenThroughMs) : -1;
2873
2981
  const { awaitingFollowUp: _promised, ...settled } = thread;
@@ -3348,7 +3456,8 @@ function normalizeThread(value, now) {
3348
3456
  author: msg.author,
3349
3457
  text: msg.text,
3350
3458
  at: typeof msg.at === "string" ? msg.at : now,
3351
- ...typeof msg.durationMs === "number" ? { durationMs: msg.durationMs } : {}
3459
+ ...typeof msg.durationMs === "number" ? { durationMs: msg.durationMs } : {},
3460
+ ...msg.author === "agent" && typeof msg.suggestedReply === "string" && msg.suggestedReply ? { suggestedReply: msg.suggestedReply } : {}
3352
3461
  });
3353
3462
  }
3354
3463
  return {
@@ -3912,7 +4021,7 @@ function createApp(ctx, store, review, queue) {
3912
4021
  const line = typeof body?.line === "number" && Number.isInteger(body.line) && body.line >= 1 ? body.line : null;
3913
4022
  const anchor = agentAnchor(file, line);
3914
4023
  const capture = store ? captureAnchor(store.get(), anchor) : null;
3915
- return c.json(review.createThread(anchor, text, capture, void 0, "agent"));
4024
+ return c.json(review.createThread(anchor, text, capture, void 0, "agent", parseSuggestedReply(body?.suggestedReply)));
3916
4025
  }
3917
4026
  const anchor = parseAnchor(body?.anchor);
3918
4027
  if (!anchor) return c.json({ error: "need {anchor, text}" }, 400);
@@ -3957,7 +4066,7 @@ function createApp(ctx, store, review, queue) {
3957
4066
  const more = body?.more === true;
3958
4067
  const waitedMs = queue?.agentReplied(id, more) ?? null;
3959
4068
  const seenThroughMs = waitedMs === null ? void 0 : Date.now() - waitedMs;
3960
- const thread = review.addMessage(id, "agent", text, false, seenThroughMs, more);
4069
+ const thread = review.addMessage(id, "agent", text, false, seenThroughMs, more, parseSuggestedReply(body?.suggestedReply));
3961
4070
  if (!thread) return c.json({ error: "no such thread" }, 404);
3962
4071
  if (waitedMs !== null) review.annotateAgentReplies([thread.id], waitedMs);
3963
4072
  return c.json({
@@ -5344,7 +5453,8 @@ if (command.kind === "reply") {
5344
5453
  const { status, body } = await postJson(await requireServer(), `/api/review/threads/${encodeURIComponent(command.threadId)}/messages`, {
5345
5454
  author: "agent",
5346
5455
  text: message,
5347
- ...command.more ? { more: true } : {}
5456
+ ...command.more ? { more: true } : {},
5457
+ ...command.suggestReply ? { suggestedReply: command.suggestReply } : {}
5348
5458
  });
5349
5459
  if (status === 404) fail(`no thread with id '${command.threadId}'`);
5350
5460
  if (status !== 200) fail(`reply failed (${status})`);
@@ -5365,7 +5475,8 @@ if (command.kind === "comment") {
5365
5475
  author: "agent",
5366
5476
  file: command.file,
5367
5477
  line: command.line,
5368
- text: message
5478
+ text: message,
5479
+ ...command.suggestReply ? { suggestedReply: command.suggestReply } : {}
5369
5480
  });
5370
5481
  if (status !== 200) fail(`comment failed (${status})`);
5371
5482
  console.log(JSON.stringify({
@@ -1 +1 @@
1
- import{m as e,t}from"./mermaid-parser.core-siQPZsry.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-B4djUhOi.js";import"./chunk-O7XYJQB3-CyxnSfZ3.js";import{n as i,r as a,t as o}from"./chunk-GTNCS2PH-BodN5cRQ.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-CLHTQVF-.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
1
+ import{m as e,t}from"./mermaid-parser.core-DtRc-ypM.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-BPEEiDps.js";import"./chunk-O7XYJQB3-CYftULw7.js";import{n as i,r as a,t as o}from"./chunk-GTNCS2PH-DnfAIbaL.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-CyG7EFf-.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
@@ -1 +1 @@
1
- import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-BfTRyLGm.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
1
+ import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-DOT26anA.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
@@ -0,0 +1 @@
1
+ import"./chunk-FOHPRMQF-DzxwRta7.js";import{M as e}from"./mermaid-parser.core-DtRc-ypM.js";export{e as createArchitectureServices};