pim-agent 0.14.2 → 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 (101) 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/shared/Renderer.ts +5 -5
  5. package/packages/core/src/shared/Tools.ts +37 -1
  6. package/packages/protocol/src/ServerEvent.ts +5 -0
  7. package/packages/server/src/SessionProjection.ts +1 -0
  8. package/packages/server/src/SessionStream.ts +9 -0
  9. package/packages/telegram/src/Bot.ts +12 -2
  10. package/packages/tui/src/extensions/working-indicator/index.ts +3 -2
  11. package/packages/web/dist/client/assets/{abnfDiagram-O67JEVCF-DDLsPl7M.js → abnfDiagram-O67JEVCF-C4h_e8a0.js} +1 -1
  12. package/packages/web/dist/client/assets/{arc-Bfm9LZ_0.js → arc-DOFrJD2P.js} +1 -1
  13. package/packages/web/dist/client/assets/architecture-7GRP2DOG-IjTj0B7Q.js +1 -0
  14. package/packages/web/dist/client/assets/{architectureDiagram-NJMV4G6O-CViHz0a3.js → architectureDiagram-NJMV4G6O-CMywPNO0.js} +1 -1
  15. package/packages/web/dist/client/assets/{blockDiagram-BEXU5L5S-CshoJ2jT.js → blockDiagram-BEXU5L5S-CilAxS33.js} +1 -1
  16. package/packages/web/dist/client/assets/{c4Diagram-YGBWAQC7-CGLODhJd.js → c4Diagram-YGBWAQC7-B-dWG8Iz.js} +1 -1
  17. package/packages/web/dist/client/assets/channel-C4sZuBrb.js +1 -0
  18. package/packages/web/dist/client/assets/{chunk-3FUC2YCW-BElZHdD7.js → chunk-3FUC2YCW-Bsj57hpn.js} +1 -1
  19. package/packages/web/dist/client/assets/{chunk-5DYCD2WN-xVF88TWx.js → chunk-5DYCD2WN-zGw1cRpq.js} +1 -1
  20. package/packages/web/dist/client/assets/{chunk-742MDFTN-1xoGm6_h.js → chunk-742MDFTN-DywDPd1I.js} +1 -1
  21. package/packages/web/dist/client/assets/{chunk-7INBJB4K-C8cub8Hz.js → chunk-7INBJB4K-CVbwe-xT.js} +1 -1
  22. package/packages/web/dist/client/assets/{chunk-7M6MHVWA-DFVau2oW.js → chunk-7M6MHVWA-CHZ-gvHw.js} +1 -1
  23. package/packages/web/dist/client/assets/{chunk-7PRAP22T-DB3rOKNz.js → chunk-7PRAP22T-WD7cf9gl.js} +1 -1
  24. package/packages/web/dist/client/assets/{chunk-GTNCS2PH-BpVHBDV7.js → chunk-GTNCS2PH-BTulktWP.js} +1 -1
  25. package/packages/web/dist/client/assets/{chunk-GWA4HPMP-BhLhdYL5.js → chunk-GWA4HPMP-D3rtBoTv.js} +1 -1
  26. package/packages/web/dist/client/assets/{chunk-MBY4JIJT-DvRGdfa-.js → chunk-MBY4JIJT-B8O-Qwvz.js} +1 -1
  27. package/packages/web/dist/client/assets/{chunk-NETBCI7D-CQNd8AmG.js → chunk-NETBCI7D-DZlxcBK5.js} +1 -1
  28. package/packages/web/dist/client/assets/{chunk-O7XYJQB3-DShLK-57.js → chunk-O7XYJQB3-4-W0jJea.js} +1 -1
  29. package/packages/web/dist/client/assets/{chunk-UA2S7LBM-DpQOqtjg.js → chunk-UA2S7LBM-D_rURue5.js} +1 -1
  30. package/packages/web/dist/client/assets/{chunk-WEXAMYUT-BduFhqwt.js → chunk-WEXAMYUT-CEL3e6t3.js} +1 -1
  31. package/packages/web/dist/client/assets/{chunk-XXDRQBXY-pli_xw5K.js → chunk-XXDRQBXY-o4820CpE.js} +1 -1
  32. package/packages/web/dist/client/assets/{chunk-Z7XXMR3K-x_3Xp2MR.js → chunk-Z7XXMR3K-BohM0wWu.js} +1 -1
  33. package/packages/web/dist/client/assets/{chunk-ZIGJFQKS-Cl42liG9.js → chunk-ZIGJFQKS-BjwLZi8g.js} +1 -1
  34. package/packages/web/dist/client/assets/{classDiagram-v2-NBCMYWYE-DEXTvNNQ.js → classDiagram-v2-NBCMYWYE-D0ZfjRwg.js} +1 -1
  35. package/packages/web/dist/client/assets/{core-Cc31wJLH.js → core-Dzrz3GvC.js} +1 -1
  36. package/packages/web/dist/client/assets/{cose-bilkent-JH36ORCC-DtFDmYNR.js → cose-bilkent-JH36ORCC-CNlUwO2B.js} +1 -1
  37. package/packages/web/dist/client/assets/{cynefin-OW5HDTMX-C1n5zA6z.js → cynefin-OW5HDTMX-Bg2hWhJY.js} +1 -1
  38. package/packages/web/dist/client/assets/{cynefinDiagram-VND7K2PF-BtkMmF6w.js → cynefinDiagram-VND7K2PF-Dt4WbdoO.js} +1 -1
  39. package/packages/web/dist/client/assets/{dagre-6A5THRUB-DSwGQnnB.js → dagre-6A5THRUB-D3J4e_FL.js} +1 -1
  40. package/packages/web/dist/client/assets/{diagram-22UHCM2B-B6kKp1l7.js → diagram-22UHCM2B-DcBAyGud.js} +1 -1
  41. package/packages/web/dist/client/assets/{diagram-3UASUU5V-BG5NVRSL.js → diagram-3UASUU5V-knaPopyA.js} +1 -1
  42. package/packages/web/dist/client/assets/{diagram-ATOU4E4O-wTfKyE4x.js → diagram-ATOU4E4O-Cdt-UXR3.js} +1 -1
  43. package/packages/web/dist/client/assets/{diagram-CDSNMT55-CgWazooW.js → diagram-CDSNMT55-0Nc7NbM-.js} +1 -1
  44. package/packages/web/dist/client/assets/{diagram-MLGK6HIB-C23kkY--.js → diagram-MLGK6HIB-obWj-j_j.js} +1 -1
  45. package/packages/web/dist/client/assets/{diagram-MPIPVDR6-0AIKkXyE.js → diagram-MPIPVDR6-CNPimc-A.js} +1 -1
  46. package/packages/web/dist/client/assets/{dist-D_jXzuJY.js → dist-CrAX-R0u.js} +1 -1
  47. package/packages/web/dist/client/assets/{ebnfDiagram-ZINNZB2B-SsipPvBE.js → ebnfDiagram-ZINNZB2B-CeIzXygs.js} +1 -1
  48. package/packages/web/dist/client/assets/{elk-276RUBZZ-UDHEztLV.js → elk-276RUBZZ-DZpv0cFN.js} +1 -1
  49. package/packages/web/dist/client/assets/{erDiagram-OPXOYQCR-ClTiR_Ec.js → erDiagram-OPXOYQCR-BA3y9LPc.js} +1 -1
  50. package/packages/web/dist/client/assets/eventmodeling-NTZA5JFV-CeuR-O65.js +1 -0
  51. package/packages/web/dist/client/assets/flowDiagram-KWPJA3E3-BMqk3vdL.js +1 -0
  52. package/packages/web/dist/client/assets/{ganttDiagram-FUAMR5RP-EQVlpLgF.js → ganttDiagram-FUAMR5RP-UaQqElIK.js} +1 -1
  53. package/packages/web/dist/client/assets/{gitGraph-4MIJSDKK-B1sicDxp.js → gitGraph-4MIJSDKK-cQmMFm4p.js} +1 -1
  54. package/packages/web/dist/client/assets/{gitGraphDiagram-X574FWY7-B7VGaCS6.js → gitGraphDiagram-X574FWY7-BmYgXYTo.js} +1 -1
  55. package/packages/web/dist/client/assets/{index-C5zfYYPp.js → index-BxPglwap.js} +6 -6
  56. package/packages/web/dist/client/assets/{index-DqdUWMRQ.css → index-CmVu3w8s.css} +1 -1
  57. package/packages/web/dist/client/assets/{info-A6RAGUB7-CIBaLxCu.js → info-A6RAGUB7-TiduRcJ3.js} +1 -1
  58. package/packages/web/dist/client/assets/{infoDiagram-VRGFBTTK-BTSwzxKa.js → infoDiagram-VRGFBTTK-hFFOKGKl.js} +1 -1
  59. package/packages/web/dist/client/assets/{ishikawaDiagram-OU5B5YK6-Bm6CSaCE.js → ishikawaDiagram-OU5B5YK6-Bwocylgy.js} +1 -1
  60. package/packages/web/dist/client/assets/{journeyDiagram-ZHPQQLJL-Boi1cndA.js → journeyDiagram-ZHPQQLJL-vZ1hiG_4.js} +1 -1
  61. package/packages/web/dist/client/assets/{kanban-definition-PNTS6WVX-kUvWgapI.js → kanban-definition-PNTS6WVX-BY_kNV28.js} +1 -1
  62. package/packages/web/dist/client/assets/{line-B_U2cP3K.js → line-D2gp374O.js} +1 -1
  63. package/packages/web/dist/client/assets/{linear-DeuHu4E-.js → linear-EkWWd1l3.js} +1 -1
  64. package/packages/web/dist/client/assets/{mermaid-parser.core-FXVUftR7.js → mermaid-parser.core-CeboWX-k.js} +3 -3
  65. package/packages/web/dist/client/assets/{mermaid.core-mmY-00PI.js → mermaid.core-zdZDrs5K.js} +4 -4
  66. package/packages/web/dist/client/assets/{mindmap-definition-NLK3R4M7-cojTX4MV.js → mindmap-definition-NLK3R4M7-gGYhS2WF.js} +1 -1
  67. package/packages/web/dist/client/assets/{packet-AYTQ26CC-Bd-cRuaI.js → packet-AYTQ26CC-Dy4sLRUY.js} +1 -1
  68. package/packages/web/dist/client/assets/{pegDiagram-GJSIUBJH-Cvwsk4js.js → pegDiagram-GJSIUBJH-BzhQfVk9.js} +1 -1
  69. package/packages/web/dist/client/assets/{pie-WAS4IAKB-BdI3q3bb.js → pie-WAS4IAKB-DLnc8q-D.js} +1 -1
  70. package/packages/web/dist/client/assets/{pieDiagram-5QR66LMP-CPB3b3IT.js → pieDiagram-5QR66LMP-CFOryLv5.js} +1 -1
  71. package/packages/web/dist/client/assets/{quadrantDiagram-O4NWA36T-BUd2eApo.js → quadrantDiagram-O4NWA36T-BJzJC3Pb.js} +1 -1
  72. package/packages/web/dist/client/assets/{radar-RG4KPBEZ-CxyJK7bg.js → radar-RG4KPBEZ-WzU2xFD1.js} +1 -1
  73. package/packages/web/dist/client/assets/{railroad-74A4TZTK-E5SCnFFE.js → railroad-74A4TZTK-BxrFrtoZ.js} +1 -1
  74. package/packages/web/dist/client/assets/railroad-abnf-HS5TGJTU-WLTxQJbM.js +1 -0
  75. package/packages/web/dist/client/assets/railroad-ebnf-LZEXJU2U-Pr2MbT1G.js +1 -0
  76. package/packages/web/dist/client/assets/railroad-peg-WCYAUIDC-BnNqXJLR.js +1 -0
  77. package/packages/web/dist/client/assets/{railroadDiagram-XR7U4H2S-C0F-VdME.js → railroadDiagram-XR7U4H2S-CwCJ4qML.js} +1 -1
  78. package/packages/web/dist/client/assets/{requirementDiagram-PLB6GJNP-B7MBOdoH.js → requirementDiagram-PLB6GJNP-N_e-xK1X.js} +1 -1
  79. package/packages/web/dist/client/assets/{sankeyDiagram-IPEJSGJF-FBKbBDfy.js → sankeyDiagram-IPEJSGJF-BxeoAN36.js} +1 -1
  80. package/packages/web/dist/client/assets/{sequenceDiagram-PO4LG4MO-CIf0Xk8r.js → sequenceDiagram-PO4LG4MO-MSPwJ13c.js} +1 -1
  81. package/packages/web/dist/client/assets/{src-Ng7mwp_r.js → src-D28B8eI9.js} +1 -1
  82. package/packages/web/dist/client/assets/{stateDiagram-v2-GCMORJYK-BTtnWQlx.js → stateDiagram-v2-GCMORJYK-D_aZ5Igh.js} +1 -1
  83. package/packages/web/dist/client/assets/{swimlanes-2SLR337P-C5gISPnD.js → swimlanes-2SLR337P-DBPV-dq1.js} +1 -1
  84. package/packages/web/dist/client/assets/swimlanesDiagram-TC7HE7FX-HaI5QjO5.js +8 -0
  85. package/packages/web/dist/client/assets/{timeline-definition-EJHVYXUP-o4Qx4_l5.js → timeline-definition-EJHVYXUP-D_NN2X_H.js} +1 -1
  86. package/packages/web/dist/client/assets/{treeView-Q6P3EWNA-C8Lg6iol.js → treeView-Q6P3EWNA-D61xAbMJ.js} +1 -1
  87. package/packages/web/dist/client/assets/{treemap-WGGIJYW6-DJwrsnbE.js → treemap-WGGIJYW6-C4YKLl2j.js} +1 -1
  88. package/packages/web/dist/client/assets/{usecaseDiagram-POWQR4AR-CUrjGCwM.js → usecaseDiagram-POWQR4AR-02veKF4D.js} +1 -1
  89. package/packages/web/dist/client/assets/{vennDiagram-UO4OBE2U-BjmRd40D.js → vennDiagram-UO4OBE2U-DEgSBAmX.js} +1 -1
  90. package/packages/web/dist/client/assets/{wardley-WFR3VGLG-CtolBbgf.js → wardley-WFR3VGLG-CZ6hgt6M.js} +1 -1
  91. package/packages/web/dist/client/assets/{wardleyDiagram-VNRHLVJA-CV53tO-B.js → wardleyDiagram-VNRHLVJA-Bh1SCQA_.js} +1 -1
  92. package/packages/web/dist/client/assets/{xychartDiagram-PMCCYNJV-36EYzFlh.js → xychartDiagram-PMCCYNJV-C2v7l5nz.js} +1 -1
  93. package/packages/web/dist/client/index.html +2 -2
  94. package/packages/web/dist/client/assets/architecture-7GRP2DOG-DpwRvkmV.js +0 -1
  95. package/packages/web/dist/client/assets/channel-DazHMyw-.js +0 -1
  96. package/packages/web/dist/client/assets/eventmodeling-NTZA5JFV-Ca0QGSHT.js +0 -1
  97. package/packages/web/dist/client/assets/flowDiagram-KWPJA3E3-BK9Yt33I.js +0 -1
  98. package/packages/web/dist/client/assets/railroad-abnf-HS5TGJTU-Cy4GbWLw.js +0 -1
  99. package/packages/web/dist/client/assets/railroad-ebnf-LZEXJU2U-C6CBSb9D.js +0 -1
  100. package/packages/web/dist/client/assets/railroad-peg-WCYAUIDC-DLEUBhTA.js +0 -1
  101. package/packages/web/dist/client/assets/swimlanesDiagram-TC7HE7FX-CfMzBcXH.js +0 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pim-agent",
3
- "version": "0.14.2",
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
@@ -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")) {
@@ -58,6 +58,8 @@ export type DurableEvent =
58
58
  readonly name: string;
59
59
  readonly view: ToolView;
60
60
  readonly isError: boolean;
61
+ /** Absent when the tool did not run, or for results recorded before pi measured it. */
62
+ readonly durationMs?: number;
61
63
  }
62
64
  | {
63
65
  readonly seq: number;
@@ -143,6 +145,7 @@ export type EphemeralEvent =
143
145
  readonly callId: string;
144
146
  readonly view: ToolView;
145
147
  readonly isError: boolean;
148
+ readonly durationMs?: number;
146
149
  }
147
150
  /** Cached picker answers for this cwd are stale. */
148
151
  | {
@@ -234,6 +237,8 @@ export type EphemeralEvent =
234
237
  readonly tps?: number;
235
238
  /** Absent when idle. */
236
239
  readonly turnElapsedMs?: number;
240
+ /** The last turn was aborted rather than finished. */
241
+ readonly interrupted?: boolean;
237
242
  /** Context filled, 0–100. Absent until a turn has reported usage. */
238
243
  readonly contextPercent?: number;
239
244
  readonly contextWindow?: number;
@@ -145,6 +145,7 @@ export class SessionProjection {
145
145
  callId: message.toolCallId,
146
146
  name: message.toolName,
147
147
  isError: message.isError,
148
+ durationMs: message.durationMs,
148
149
  view: Tools.viewOf({
149
150
  name: message.toolName,
150
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-FXVUftR7.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-Ng7mwp_r.js";import"./chunk-O7XYJQB3-DShLK-57.js";import{n as i,r as a,t as o}from"./chunk-GTNCS2PH-BpVHBDV7.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-mmY-00PI.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-D_jXzuJY.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};