pim-agent 0.14.1 → 0.15.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 (104) hide show
  1. package/package.json +3 -3
  2. package/packages/core/src/extensions/bash/MemoryCap.ts +10 -2
  3. package/packages/core/src/extensions/bash/run.ts +8 -2
  4. package/packages/core/src/session/SearchIndex.ts +4 -3
  5. package/packages/core/src/session/SessionDigest.ts +2 -2
  6. package/packages/core/src/session/UserPrompt.ts +34 -0
  7. package/packages/core/src/shared/Renderer.ts +5 -5
  8. package/packages/core/src/shared/Tools.ts +37 -1
  9. package/packages/protocol/src/ServerEvent.ts +8 -0
  10. package/packages/server/src/SessionProjection.ts +4 -1
  11. package/packages/server/src/SessionStream.ts +9 -0
  12. package/packages/telegram/src/Bot.ts +12 -2
  13. package/packages/tui/src/extensions/working-indicator/index.ts +3 -2
  14. package/packages/web/dist/client/assets/{abnfDiagram-O67JEVCF-w0u0UKcC.js → abnfDiagram-O67JEVCF-C4h_e8a0.js} +1 -1
  15. package/packages/web/dist/client/assets/{arc-C8AeY-3C.js → arc-DOFrJD2P.js} +1 -1
  16. package/packages/web/dist/client/assets/architecture-7GRP2DOG-IjTj0B7Q.js +1 -0
  17. package/packages/web/dist/client/assets/{architectureDiagram-NJMV4G6O-CLdCZfsP.js → architectureDiagram-NJMV4G6O-CMywPNO0.js} +1 -1
  18. package/packages/web/dist/client/assets/{blockDiagram-BEXU5L5S-BgAbOzdH.js → blockDiagram-BEXU5L5S-CilAxS33.js} +1 -1
  19. package/packages/web/dist/client/assets/{c4Diagram-YGBWAQC7-DGRXXzDl.js → c4Diagram-YGBWAQC7-B-dWG8Iz.js} +1 -1
  20. package/packages/web/dist/client/assets/channel-C4sZuBrb.js +1 -0
  21. package/packages/web/dist/client/assets/{chunk-3FUC2YCW-Dmz4_CY0.js → chunk-3FUC2YCW-Bsj57hpn.js} +1 -1
  22. package/packages/web/dist/client/assets/{chunk-5DYCD2WN-D6q0r_NW.js → chunk-5DYCD2WN-zGw1cRpq.js} +1 -1
  23. package/packages/web/dist/client/assets/{chunk-742MDFTN-biXvhzMn.js → chunk-742MDFTN-DywDPd1I.js} +1 -1
  24. package/packages/web/dist/client/assets/{chunk-7INBJB4K-CtfPEr8P.js → chunk-7INBJB4K-CVbwe-xT.js} +1 -1
  25. package/packages/web/dist/client/assets/{chunk-7M6MHVWA-CTixWKLk.js → chunk-7M6MHVWA-CHZ-gvHw.js} +1 -1
  26. package/packages/web/dist/client/assets/{chunk-7PRAP22T-DijOiKl2.js → chunk-7PRAP22T-WD7cf9gl.js} +1 -1
  27. package/packages/web/dist/client/assets/{chunk-GTNCS2PH-DLId7dTl.js → chunk-GTNCS2PH-BTulktWP.js} +1 -1
  28. package/packages/web/dist/client/assets/{chunk-GWA4HPMP-YUQxYmiu.js → chunk-GWA4HPMP-D3rtBoTv.js} +1 -1
  29. package/packages/web/dist/client/assets/{chunk-MBY4JIJT-VWR3HSRr.js → chunk-MBY4JIJT-B8O-Qwvz.js} +1 -1
  30. package/packages/web/dist/client/assets/{chunk-NETBCI7D-B8SeJoMY.js → chunk-NETBCI7D-DZlxcBK5.js} +1 -1
  31. package/packages/web/dist/client/assets/{chunk-O7XYJQB3-CeLpEz0Q.js → chunk-O7XYJQB3-4-W0jJea.js} +1 -1
  32. package/packages/web/dist/client/assets/{chunk-UA2S7LBM-cBGKkXV_.js → chunk-UA2S7LBM-D_rURue5.js} +1 -1
  33. package/packages/web/dist/client/assets/{chunk-WEXAMYUT-BesXAOy9.js → chunk-WEXAMYUT-CEL3e6t3.js} +1 -1
  34. package/packages/web/dist/client/assets/{chunk-XXDRQBXY-DiuGUc8m.js → chunk-XXDRQBXY-o4820CpE.js} +1 -1
  35. package/packages/web/dist/client/assets/{chunk-Z7XXMR3K-Dr2W5_t1.js → chunk-Z7XXMR3K-BohM0wWu.js} +1 -1
  36. package/packages/web/dist/client/assets/{chunk-ZIGJFQKS-CwoMYXLJ.js → chunk-ZIGJFQKS-BjwLZi8g.js} +1 -1
  37. package/packages/web/dist/client/assets/{classDiagram-v2-NBCMYWYE-Gc3jAsDf.js → classDiagram-v2-NBCMYWYE-D0ZfjRwg.js} +1 -1
  38. package/packages/web/dist/client/assets/{core-C27Q2ZSN.js → core-Dzrz3GvC.js} +1 -1
  39. package/packages/web/dist/client/assets/{cose-bilkent-JH36ORCC-ox5QohTH.js → cose-bilkent-JH36ORCC-CNlUwO2B.js} +1 -1
  40. package/packages/web/dist/client/assets/{cynefin-OW5HDTMX-CjQ-AjuJ.js → cynefin-OW5HDTMX-Bg2hWhJY.js} +1 -1
  41. package/packages/web/dist/client/assets/{cynefinDiagram-VND7K2PF-BVajmbbO.js → cynefinDiagram-VND7K2PF-Dt4WbdoO.js} +1 -1
  42. package/packages/web/dist/client/assets/{dagre-6A5THRUB-BtXhDxGN.js → dagre-6A5THRUB-D3J4e_FL.js} +1 -1
  43. package/packages/web/dist/client/assets/{diagram-22UHCM2B-DwjrV0H_.js → diagram-22UHCM2B-DcBAyGud.js} +1 -1
  44. package/packages/web/dist/client/assets/{diagram-3UASUU5V-DQ1E_6hO.js → diagram-3UASUU5V-knaPopyA.js} +1 -1
  45. package/packages/web/dist/client/assets/{diagram-ATOU4E4O-wVYWlHRV.js → diagram-ATOU4E4O-Cdt-UXR3.js} +1 -1
  46. package/packages/web/dist/client/assets/{diagram-CDSNMT55-CMlxHWMz.js → diagram-CDSNMT55-0Nc7NbM-.js} +1 -1
  47. package/packages/web/dist/client/assets/{diagram-MLGK6HIB-Cbiwo7t9.js → diagram-MLGK6HIB-obWj-j_j.js} +1 -1
  48. package/packages/web/dist/client/assets/{diagram-MPIPVDR6-Cv4zIyW1.js → diagram-MPIPVDR6-CNPimc-A.js} +1 -1
  49. package/packages/web/dist/client/assets/{dist-Dl4GbwtH.js → dist-CrAX-R0u.js} +1 -1
  50. package/packages/web/dist/client/assets/{ebnfDiagram-ZINNZB2B-Bd8xl8W2.js → ebnfDiagram-ZINNZB2B-CeIzXygs.js} +1 -1
  51. package/packages/web/dist/client/assets/{elk-276RUBZZ-DPRtUxgw.js → elk-276RUBZZ-DZpv0cFN.js} +1 -1
  52. package/packages/web/dist/client/assets/{erDiagram-OPXOYQCR-BNoG4SxS.js → erDiagram-OPXOYQCR-BA3y9LPc.js} +1 -1
  53. package/packages/web/dist/client/assets/eventmodeling-NTZA5JFV-CeuR-O65.js +1 -0
  54. package/packages/web/dist/client/assets/flowDiagram-KWPJA3E3-BMqk3vdL.js +1 -0
  55. package/packages/web/dist/client/assets/{ganttDiagram-FUAMR5RP-BtFYI7uw.js → ganttDiagram-FUAMR5RP-UaQqElIK.js} +1 -1
  56. package/packages/web/dist/client/assets/{gitGraph-4MIJSDKK-Di6RG5Kg.js → gitGraph-4MIJSDKK-cQmMFm4p.js} +1 -1
  57. package/packages/web/dist/client/assets/{gitGraphDiagram-X574FWY7-J4_JKGBH.js → gitGraphDiagram-X574FWY7-BmYgXYTo.js} +1 -1
  58. package/packages/web/dist/client/assets/{index-Cn66jcLF.js → index-BxPglwap.js} +6 -6
  59. package/packages/web/dist/client/assets/{index-BD7ptjuS.css → index-CmVu3w8s.css} +1 -1
  60. package/packages/web/dist/client/assets/{info-A6RAGUB7-wk6vNDP4.js → info-A6RAGUB7-TiduRcJ3.js} +1 -1
  61. package/packages/web/dist/client/assets/{infoDiagram-VRGFBTTK-Zl7Uhlcj.js → infoDiagram-VRGFBTTK-hFFOKGKl.js} +1 -1
  62. package/packages/web/dist/client/assets/{ishikawaDiagram-OU5B5YK6-I0VVed8w.js → ishikawaDiagram-OU5B5YK6-Bwocylgy.js} +1 -1
  63. package/packages/web/dist/client/assets/{journeyDiagram-ZHPQQLJL-CLGZAy0Q.js → journeyDiagram-ZHPQQLJL-vZ1hiG_4.js} +1 -1
  64. package/packages/web/dist/client/assets/{kanban-definition-PNTS6WVX-D3Zv63YL.js → kanban-definition-PNTS6WVX-BY_kNV28.js} +1 -1
  65. package/packages/web/dist/client/assets/{line-C4_qzTJY.js → line-D2gp374O.js} +1 -1
  66. package/packages/web/dist/client/assets/{linear-Dbp9FWGm.js → linear-EkWWd1l3.js} +1 -1
  67. package/packages/web/dist/client/assets/{mermaid-parser.core-Cbd2Flfk.js → mermaid-parser.core-CeboWX-k.js} +3 -3
  68. package/packages/web/dist/client/assets/{mermaid.core-CPXk02t0.js → mermaid.core-zdZDrs5K.js} +4 -4
  69. package/packages/web/dist/client/assets/{mindmap-definition-NLK3R4M7-hcjd2vg0.js → mindmap-definition-NLK3R4M7-gGYhS2WF.js} +1 -1
  70. package/packages/web/dist/client/assets/{packet-AYTQ26CC-CLiY7MdL.js → packet-AYTQ26CC-Dy4sLRUY.js} +1 -1
  71. package/packages/web/dist/client/assets/{pegDiagram-GJSIUBJH-Or6L-npJ.js → pegDiagram-GJSIUBJH-BzhQfVk9.js} +1 -1
  72. package/packages/web/dist/client/assets/{pie-WAS4IAKB-DTF5qxhB.js → pie-WAS4IAKB-DLnc8q-D.js} +1 -1
  73. package/packages/web/dist/client/assets/{pieDiagram-5QR66LMP-wDNyDsTs.js → pieDiagram-5QR66LMP-CFOryLv5.js} +1 -1
  74. package/packages/web/dist/client/assets/{quadrantDiagram-O4NWA36T-BL_0xWWi.js → quadrantDiagram-O4NWA36T-BJzJC3Pb.js} +1 -1
  75. package/packages/web/dist/client/assets/{radar-RG4KPBEZ-hK8uEd3E.js → radar-RG4KPBEZ-WzU2xFD1.js} +1 -1
  76. package/packages/web/dist/client/assets/{railroad-74A4TZTK-Cj1mtGfH.js → railroad-74A4TZTK-BxrFrtoZ.js} +1 -1
  77. package/packages/web/dist/client/assets/railroad-abnf-HS5TGJTU-WLTxQJbM.js +1 -0
  78. package/packages/web/dist/client/assets/railroad-ebnf-LZEXJU2U-Pr2MbT1G.js +1 -0
  79. package/packages/web/dist/client/assets/railroad-peg-WCYAUIDC-BnNqXJLR.js +1 -0
  80. package/packages/web/dist/client/assets/{railroadDiagram-XR7U4H2S-BUXe7pvJ.js → railroadDiagram-XR7U4H2S-CwCJ4qML.js} +1 -1
  81. package/packages/web/dist/client/assets/{requirementDiagram-PLB6GJNP-DBnKurFY.js → requirementDiagram-PLB6GJNP-N_e-xK1X.js} +1 -1
  82. package/packages/web/dist/client/assets/{sankeyDiagram-IPEJSGJF-BDlSxPY7.js → sankeyDiagram-IPEJSGJF-BxeoAN36.js} +1 -1
  83. package/packages/web/dist/client/assets/{sequenceDiagram-PO4LG4MO-BcKSq_cS.js → sequenceDiagram-PO4LG4MO-MSPwJ13c.js} +1 -1
  84. package/packages/web/dist/client/assets/{src-kcIgRrGC.js → src-D28B8eI9.js} +1 -1
  85. package/packages/web/dist/client/assets/{stateDiagram-v2-GCMORJYK-D-1tpyK1.js → stateDiagram-v2-GCMORJYK-D_aZ5Igh.js} +1 -1
  86. package/packages/web/dist/client/assets/{swimlanes-2SLR337P-edQaMeEJ.js → swimlanes-2SLR337P-DBPV-dq1.js} +1 -1
  87. package/packages/web/dist/client/assets/swimlanesDiagram-TC7HE7FX-HaI5QjO5.js +8 -0
  88. package/packages/web/dist/client/assets/{timeline-definition-EJHVYXUP-BHspcgaG.js → timeline-definition-EJHVYXUP-D_NN2X_H.js} +1 -1
  89. package/packages/web/dist/client/assets/{treeView-Q6P3EWNA-Bvc71ryx.js → treeView-Q6P3EWNA-D61xAbMJ.js} +1 -1
  90. package/packages/web/dist/client/assets/{treemap-WGGIJYW6-CoZvoF_t.js → treemap-WGGIJYW6-C4YKLl2j.js} +1 -1
  91. package/packages/web/dist/client/assets/{usecaseDiagram-POWQR4AR-B203AiCD.js → usecaseDiagram-POWQR4AR-02veKF4D.js} +1 -1
  92. package/packages/web/dist/client/assets/{vennDiagram-UO4OBE2U-Cia3spa9.js → vennDiagram-UO4OBE2U-DEgSBAmX.js} +1 -1
  93. package/packages/web/dist/client/assets/{wardley-WFR3VGLG-C7qHTXAu.js → wardley-WFR3VGLG-CZ6hgt6M.js} +1 -1
  94. package/packages/web/dist/client/assets/{wardleyDiagram-VNRHLVJA-CK2R_SgC.js → wardleyDiagram-VNRHLVJA-Bh1SCQA_.js} +1 -1
  95. package/packages/web/dist/client/assets/{xychartDiagram-PMCCYNJV-BBLqtYJ_.js → xychartDiagram-PMCCYNJV-C2v7l5nz.js} +1 -1
  96. package/packages/web/dist/client/index.html +2 -2
  97. package/packages/web/dist/client/assets/architecture-7GRP2DOG-D-GDy9ga.js +0 -1
  98. package/packages/web/dist/client/assets/channel-BJtpIKaC.js +0 -1
  99. package/packages/web/dist/client/assets/eventmodeling-NTZA5JFV-Dh9l6A3t.js +0 -1
  100. package/packages/web/dist/client/assets/flowDiagram-KWPJA3E3-DoJ97uSW.js +0 -1
  101. package/packages/web/dist/client/assets/railroad-abnf-HS5TGJTU-t8ibqa0P.js +0 -1
  102. package/packages/web/dist/client/assets/railroad-ebnf-LZEXJU2U-B4RYlcUM.js +0 -1
  103. package/packages/web/dist/client/assets/railroad-peg-WCYAUIDC-DFqfvrfB.js +0 -1
  104. package/packages/web/dist/client/assets/swimlanesDiagram-TC7HE7FX-vI6XtOyR.js +0 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pim-agent",
3
- "version": "0.14.1",
3
+ "version": "0.15.0",
4
4
  "description": "A batteries-included distro of Pi, accessible in your terminal, browser and Telegram.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -76,8 +76,8 @@
76
76
  "vite": "^8.2.2"
77
77
  },
78
78
  "dependencies": {
79
- "@earendil-works/pi-coding-agent": "1.0.4",
80
- "@earendil-works/pi-server": "1.0.4",
79
+ "@earendil-works/pi-coding-agent": "1.1.0",
80
+ "@earendil-works/pi-server": "1.1.0",
81
81
  "diff": "^9.0.0",
82
82
  "fzf": "^0.5.2",
83
83
  "grammy": "^1.46.0",
@@ -10,8 +10,16 @@ export type MemoryScope = {
10
10
  readonly unit: string;
11
11
  readonly limitBytes: number;
12
12
  readonly argv: readonly string[];
13
+ /** Shell run first inside the scope; makes the kernel's OOM kill take the whole command. */
14
+ readonly prelude: string;
13
15
  };
14
16
 
17
+ // The kernel kills the whole group on OOM, as OOMPolicy=kill would, but the unit never ends in
18
+ // Result=oom-kill, which desktops (Plasma's oom_notifier) report as "system low on memory".
19
+ // Only ever run inside our scope: anywhere else it would mark pim's own cgroup.
20
+ const OOM_GROUP_PRELUDE =
21
+ '{ read -r __pim_cg < /proc/self/cgroup; echo 1 > "/sys/fs/cgroup${__pim_cg#0::}/memory.oom.group"; unset __pim_cg; } 2>/dev/null; ';
22
+
15
23
  let supported: Promise<boolean> | null = null;
16
24
  let owner: Promise<string | null> | null = null;
17
25
 
@@ -93,6 +101,7 @@ async function scope(): Promise<MemoryScope | null> {
93
101
  return {
94
102
  unit,
95
103
  limitBytes: limit,
104
+ prelude: OOM_GROUP_PRELUDE,
96
105
  argv: [
97
106
  "systemd-run",
98
107
  "--user",
@@ -103,8 +112,7 @@ async function scope(): Promise<MemoryScope | null> {
103
112
  `--unit=${unit}`,
104
113
  `--property=MemoryMax=${limit}`,
105
114
  "--property=MemorySwapMax=0",
106
- "--property=OOMPolicy=kill",
107
- // The kernel's group kill races systemd's OOM stop; both must SIGKILL so run.ts can tell.
115
+ "--property=OOMPolicy=continue",
108
116
  "--property=KillSignal=SIGKILL",
109
117
  ...(bindTo
110
118
  ? [`--property=BindsTo=${bindTo}`, `--property=After=${bindTo}`]
@@ -100,7 +100,13 @@ export async function runBashCommand(
100
100
 
101
101
  // setsid: own process group (pgid == pid), so the whole tree can be signalled.
102
102
  const proc = Bun.spawn({
103
- cmd: [...(scope?.argv ?? []), "setsid", "bash", "-lc", RUNNER],
103
+ cmd: [
104
+ ...(scope?.argv ?? []),
105
+ "setsid",
106
+ "bash",
107
+ "-lc",
108
+ (scope?.prelude ?? "") + RUNNER,
109
+ ],
104
110
  cwd,
105
111
  stdout: "pipe",
106
112
  stderr: "pipe",
@@ -207,7 +213,7 @@ export async function runBashCommand(
207
213
  const stdout = stdoutCap.snapshot(sniffed !== null);
208
214
  const stderr = stderrCap.snapshot();
209
215
 
210
- // OOMPolicy=kill + KillSignal=SIGKILL: an OOM ends in SIGKILL whoever wins; systemd's Result is racy.
216
+ // The kernel's OOM group kill is a SIGKILL; systemd's Result never says oom-kill (see MemoryCap).
211
217
  const memoryLimitHit =
212
218
  scope !== null && signalCode === "SIGKILL" && !timedOut && !aborted
213
219
  ? scope.limitBytes
@@ -1,6 +1,5 @@
1
1
  import { parseSessionEntries } from "@earendil-works/pi-coding-agent";
2
2
 
3
- import { Attachments } from "../attachments/Attachments";
4
3
  import { Levenshtein } from "../shared/Levenshtein";
5
4
  import { Pool } from "../shared/Pool";
6
5
  import { MessageText } from "./MessageText";
@@ -12,6 +11,7 @@ import {
12
11
  type Durable,
13
12
  } from "./SessionDigest";
14
13
  import type { SessionSummary } from "./SessionRegistry";
14
+ import { UserPrompt } from "./UserPrompt";
15
15
 
16
16
  /** Half-open character offsets; non-overlapping and ascending. */
17
17
  export type SearchRange = readonly [start: number, end: number];
@@ -527,9 +527,10 @@ function turnOf(line: string, seq: number): Turn | undefined {
527
527
  if (message.role !== "user" && message.role !== "assistant") {
528
528
  return undefined;
529
529
  }
530
- const said = MessageText.textOf(message.content);
531
530
  const text = (
532
- message.role === "user" ? Attachments.parse(said).text : said
531
+ message.role === "user"
532
+ ? UserPrompt.of(message.content).text
533
+ : MessageText.textOf(message.content)
533
534
  ).trim();
534
535
  return text === "" ? undefined : { seq, role: message.role, text };
535
536
  }
@@ -1,7 +1,7 @@
1
1
  import { parseSessionEntries } from "@earendil-works/pi-coding-agent";
2
2
 
3
3
  import { Attachments } from "../attachments/Attachments";
4
- import { MessageText } from "./MessageText";
4
+ import { UserPrompt } from "./UserPrompt";
5
5
 
6
6
  /** Catalogue summary of a session file. */
7
7
  export type SessionDigest = {
@@ -138,7 +138,7 @@ function firstUserMessage(lines: readonly string[]): string | undefined {
138
138
  if (entry?.type !== "message" || entry.message.role !== "user") {
139
139
  continue;
140
140
  }
141
- const said = Attachments.parse(MessageText.textOf(entry.message.content));
141
+ const said = UserPrompt.of(entry.message.content);
142
142
  const text =
143
143
  said.text.trim() ||
144
144
  said.files.map((file) => Attachments.nameOf(file.path)).join(", ");
@@ -0,0 +1,34 @@
1
+ import type { UserMessage } from "@earendil-works/pi-ai";
2
+ import {
3
+ parseSkillBlock,
4
+ type ParsedSkillBlock,
5
+ } from "@earendil-works/pi-coding-agent";
6
+
7
+ import { Attachments, type PromptAttachment } from "../attachments/Attachments";
8
+ import { MessageText } from "./MessageText";
9
+
10
+ /** A skill pi expanded inline into the prompt. */
11
+ export type SkillUse = Pick<ParsedSkillBlock, "name" | "content">;
12
+
13
+ /** A stored user message as the user typed it, with what pi expanded into it set apart. */
14
+ export type UserPrompt = {
15
+ readonly text: string;
16
+ readonly files: readonly PromptAttachment[];
17
+ readonly skill?: SkillUse;
18
+ };
19
+
20
+ function of(content: UserMessage["content"]): UserPrompt {
21
+ const raw = MessageText.textOf(content);
22
+ const block = parseSkillBlock(raw);
23
+ if (block === null) {
24
+ return Attachments.parse(raw);
25
+ }
26
+ const said = Attachments.parse(block.userMessage ?? "");
27
+ return {
28
+ ...said,
29
+ text: [`/skill:${block.name}`, said.text].filter(Boolean).join(" "),
30
+ skill: { name: block.name, content: block.content },
31
+ };
32
+ }
33
+
34
+ export const UserPrompt = { of };
@@ -27,12 +27,12 @@ export type PrefixSpec = {
27
27
  };
28
28
 
29
29
  const GAPPED_PREFIX: PrefixSpec = {
30
- prefix: " │ ",
31
- width: 3,
30
+ prefix: "│ ",
31
+ width: 2,
32
32
  };
33
33
  const TIGHT_PREFIX: PrefixSpec = {
34
- prefix: " │",
35
- width: 2,
34
+ prefix: "│",
35
+ width: 1,
36
36
  };
37
37
 
38
38
  class ToolTitle implements Component {
@@ -213,7 +213,7 @@ function titleHead(args: {
213
213
  }): string {
214
214
  const { label, theme, markerColor, labelColor } = args;
215
215
  return (
216
- theme.fg(markerColor, " ▪") +
216
+ theme.fg(markerColor, "▪") +
217
217
  " " +
218
218
  theme.fg(labelColor ?? "toolTitle", theme.bold(label))
219
219
  );
@@ -3,6 +3,7 @@ import type {
3
3
  ExtensionAPI,
4
4
  ToolDefinition,
5
5
  } from "@earendil-works/pi-coding-agent";
6
+ import { Box, type Component } from "@earendil-works/pi-tui";
6
7
  import { validateToolArguments, type JsonObject } from "@earendil-works/pi-ai";
7
8
  import type { Static, TSchema } from "typebox";
8
9
  import { Levenshtein } from "./Levenshtein";
@@ -136,9 +137,23 @@ function wrap<TParams extends TSchema, TDetails = unknown, TState = unknown>(
136
137
  if (effect !== undefined) {
137
138
  effects.set(def.name, effect as ErasedToolEffect);
138
139
  }
140
+ const { renderCall, renderResult } =
141
+ toViewModel === undefined ? piDef : synthesizeRenderers(def, toViewModel);
142
+ const self = def.renderShell === "self";
139
143
  return {
140
144
  ...piDef,
141
- ...(toViewModel === undefined ? {} : synthesizeRenderers(def, toViewModel)),
145
+ renderCall:
146
+ self && renderCall
147
+ ? (args, theme, context) =>
148
+ padded(context, (inner) => renderCall(args, theme, inner))
149
+ : renderCall,
150
+ renderResult:
151
+ self && renderResult
152
+ ? (result, options, theme, context) =>
153
+ padded(context, (inner) =>
154
+ renderResult(result, options, theme, inner)
155
+ )
156
+ : renderResult,
142
157
  prepareArguments: (rawArgs: unknown): Static<TParams> => {
143
158
  const prepared = def.prepareArguments
144
159
  ? def.prepareArguments(rawArgs)
@@ -291,6 +306,27 @@ function synthesizeRenderers<TParams extends TSchema, TDetails, TState>(
291
306
  };
292
307
  }
293
308
 
309
+ type PadContext = {
310
+ readonly lastComponent: Component | undefined;
311
+ readonly outputPad: number;
312
+ };
313
+
314
+ /** pi leaves the `outputPad` margin to `renderShell: "self"` renderers. */
315
+ function padded<C extends PadContext>(
316
+ context: C,
317
+ draw: (context: C) => Component
318
+ ): Component {
319
+ const last = context.lastComponent;
320
+ const box = new Box(context.outputPad, 0);
321
+ box.addChild(
322
+ draw({
323
+ ...context,
324
+ lastComponent: last instanceof Box ? last.children[0] : last,
325
+ })
326
+ );
327
+ return box;
328
+ }
329
+
294
330
  function parseIssues(message: string): Issue[] {
295
331
  const issues: Issue[] = [];
296
332
  for (const line of message.split("\n")) {
@@ -4,6 +4,7 @@ import type { PickerItem } from "#core/picker/PickerItem";
4
4
  import type { ExtensionEntry } from "#core/shared/PiExtensions";
5
5
  import type { SearchRange, SearchSnippet } from "#core/session/SearchIndex";
6
6
  import type { LeaseFrontend } from "#core/session/SessionLease";
7
+ import type { SkillUse } from "#core/session/UserPrompt";
7
8
  import type { UpdateSkip } from "#core/shared/Updater";
8
9
  import type { NoticeSeverity, ToolView } from "#core/view/ViewBlock";
9
10
  import type { ChangeList, FileDiff, FileLines } from "./Diff";
@@ -44,6 +45,8 @@ export type DurableEvent =
44
45
  readonly thinking?: string;
45
46
  /** User messages only. */
46
47
  readonly attachments?: readonly AttachmentView[];
48
+ /** User messages only; `text` then holds the command as typed. */
49
+ readonly skill?: SkillUse;
47
50
  readonly toolCalls?: readonly ToolCallView[];
48
51
  /** Model call error; assistant messages only. */
49
52
  readonly error?: string;
@@ -55,6 +58,8 @@ export type DurableEvent =
55
58
  readonly name: string;
56
59
  readonly view: ToolView;
57
60
  readonly isError: boolean;
61
+ /** Absent when the tool did not run, or for results recorded before pi measured it. */
62
+ readonly durationMs?: number;
58
63
  }
59
64
  | {
60
65
  readonly seq: number;
@@ -140,6 +145,7 @@ export type EphemeralEvent =
140
145
  readonly callId: string;
141
146
  readonly view: ToolView;
142
147
  readonly isError: boolean;
148
+ readonly durationMs?: number;
143
149
  }
144
150
  /** Cached picker answers for this cwd are stale. */
145
151
  | {
@@ -231,6 +237,8 @@ export type EphemeralEvent =
231
237
  readonly tps?: number;
232
238
  /** Absent when idle. */
233
239
  readonly turnElapsedMs?: number;
240
+ /** The last turn was aborted rather than finished. */
241
+ readonly interrupted?: boolean;
234
242
  /** Context filled, 0–100. Absent until a turn has reported usage. */
235
243
  readonly contextPercent?: number;
236
244
  readonly contextWindow?: number;
@@ -7,6 +7,7 @@ import type { FileEntry } from "@earendil-works/pi-coding-agent";
7
7
  import { Attachments } from "#core/attachments/Attachments";
8
8
  import { EventLog, type LoggedEntry } from "#core/session/EventLog";
9
9
  import { MessageText } from "#core/session/MessageText";
10
+ import { UserPrompt } from "#core/session/UserPrompt";
10
11
  import { Tools } from "#core/shared/Tools";
11
12
  import type {
12
13
  AttachmentView,
@@ -83,7 +84,7 @@ export class SessionProjection {
83
84
  const timestamp = Date.parse(entry.timestamp);
84
85
  switch (message.role) {
85
86
  case "user": {
86
- const said = Attachments.parse(MessageText.textOf(message.content));
87
+ const said = UserPrompt.of(message.content);
87
88
  const attachments: readonly AttachmentView[] = said.files.map(
88
89
  (file) => ({
89
90
  name: Attachments.nameOf(file.path),
@@ -99,6 +100,7 @@ export class SessionProjection {
99
100
  text: said.text,
100
101
  timestamp,
101
102
  ...(attachments.length === 0 ? {} : { attachments }),
103
+ ...(said.skill === undefined ? {} : { skill: said.skill }),
102
104
  };
103
105
  }
104
106
  case "assistant": {
@@ -143,6 +145,7 @@ export class SessionProjection {
143
145
  callId: message.toolCallId,
144
146
  name: message.toolName,
145
147
  isError: message.isError,
148
+ durationMs: message.durationMs,
146
149
  view: Tools.viewOf({
147
150
  name: message.toolName,
148
151
  args: this.callArgs.get(message.toolCallId) ?? {},
@@ -40,6 +40,7 @@ type LiveTool = {
40
40
  view: ToolView;
41
41
  isError: boolean;
42
42
  done: boolean;
43
+ durationMs: number | undefined;
43
44
  };
44
45
 
45
46
  type LiveMessage = {
@@ -105,6 +106,7 @@ export class SessionStream implements SessionUi {
105
106
  private uiSeq = 0;
106
107
  private readonly dispatching: string[] = [];
107
108
  private turnStartedAt = 0;
109
+ private interrupted = false;
108
110
  private gitCwd: string | undefined;
109
111
  private gitStop: (() => void) | undefined;
110
112
  private gitBranch: string | null = null;
@@ -422,6 +424,7 @@ export class SessionStream implements SessionUi {
422
424
  callId: tool.callId,
423
425
  view: tool.view,
424
426
  isError: tool.isError,
427
+ durationMs: tool.durationMs,
425
428
  });
426
429
  }
427
430
  }
@@ -465,6 +468,7 @@ export class SessionStream implements SessionUi {
465
468
  ...(this.repoBusy?.() === true ? { repoBusy: true } : {}),
466
469
  ...(tps === undefined ? {} : { tps }),
467
470
  ...(turnElapsedMs === undefined ? {} : { turnElapsedMs }),
471
+ ...(this.interrupted ? { interrupted: true } : {}),
468
472
  ...(usage?.percent === null || usage === undefined
469
473
  ? {}
470
474
  : {
@@ -534,6 +538,7 @@ export class SessionStream implements SessionUi {
534
538
  switch (event.type) {
535
539
  case "agent_start":
536
540
  this.turnStartedAt = Date.now();
541
+ this.interrupted = false;
537
542
  this.liveTurn = [];
538
543
  this.emit(this.sessionState());
539
544
  return;
@@ -569,6 +574,7 @@ export class SessionStream implements SessionUi {
569
574
  view,
570
575
  isError: false,
571
576
  done: false,
577
+ durationMs: undefined,
572
578
  });
573
579
  this.emit({
574
580
  type: "tool_call",
@@ -609,12 +615,14 @@ export class SessionStream implements SessionUi {
609
615
  tool.view = view;
610
616
  tool.isError = event.isError;
611
617
  tool.done = true;
618
+ tool.durationMs = event.durationMs;
612
619
  }
613
620
  this.emit({
614
621
  type: "tool_end",
615
622
  callId: event.toolCallId,
616
623
  view,
617
624
  isError: event.isError,
625
+ durationMs: event.durationMs,
618
626
  });
619
627
  if (Tools.effectOf(event.toolName)?.kind !== "readOnly") {
620
628
  this.invalidatePickers("files");
@@ -652,6 +660,7 @@ export class SessionStream implements SessionUi {
652
660
  return;
653
661
  }
654
662
  case "agent_settled":
663
+ this.interrupted = event.aborted;
655
664
  void this.flushDurable().then(() => {
656
665
  // Clear only after the superseding durable events are sent.
657
666
  this.liveTurn = [];
@@ -182,7 +182,13 @@ export class Bot {
182
182
  prompt: Prompt
183
183
  ): Promise<void> {
184
184
  const renderer = new Renderer(session, this.grammy.api);
185
- const unsubscribe = agent.subscribe((event) => renderer.handleEvent(event));
185
+ let aborted = false;
186
+ const unsubscribe = agent.subscribe((event) => {
187
+ if (event.type === "agent_settled") {
188
+ aborted = event.aborted;
189
+ }
190
+ renderer.handleEvent(event);
191
+ });
186
192
  await renderer.start();
187
193
  try {
188
194
  await agent.prompt(prompt.text, {
@@ -190,7 +196,11 @@ export class Bot {
190
196
  source: "rpc",
191
197
  });
192
198
  const final = extractFinalResult(agent);
193
- await renderer.finish(final.text, final.state);
199
+ if (aborted && final.state === "ok") {
200
+ await renderer.finish("", "cancelled");
201
+ } else {
202
+ await renderer.finish(final.text, final.state);
203
+ }
194
204
  } catch (err) {
195
205
  const msg = (err as Error).message ?? String(err);
196
206
  console.error(`[bot] turn failed:`, err);
@@ -54,12 +54,13 @@ export default function (pi: ExtensionAPI): void {
54
54
  timer = setInterval(() => setWorkingMessage(ctx), 1000);
55
55
  });
56
56
 
57
- pi.on("agent_end", (_event, ctx) => {
57
+ pi.on("agent_settled", (event, ctx) => {
58
58
  stopTimer();
59
59
  if (!ctx.hasUI) {
60
60
  return;
61
61
  }
62
- const message = `⣿ Clanked for ${Format.formatElapsed(Date.now() - startedAt)}\n`;
62
+ const verb = event.aborted ? "Interrupted after" : "Clanked for";
63
+ const message = `⣿ ${verb} ${Format.formatElapsed(Date.now() - startedAt)}\n`;
63
64
  ctx.ui.setWidget(FINAL_WIDGET_ID, [ctx.ui.theme.fg("muted", message)]);
64
65
  });
65
66
 
@@ -1 +1 @@
1
- import{m as e,t}from"./mermaid-parser.core-Cbd2Flfk.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-kcIgRrGC.js";import"./chunk-O7XYJQB3-CeLpEz0Q.js";import{n as i,r as a,t as o}from"./chunk-GTNCS2PH-DLId7dTl.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-CPXk02t0.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-CeboWX-k.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-D28B8eI9.js";import"./chunk-O7XYJQB3-4-W0jJea.js";import{n as i,r as a,t as o}from"./chunk-GTNCS2PH-BTulktWP.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-zdZDrs5K.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-Dl4GbwtH.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-CrAX-R0u.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-CoA4358r.js";import{M as e}from"./mermaid-parser.core-CeboWX-k.js";export{e as createArchitectureServices};