@timurproko/a1 0.2.7-dev.1232 → 0.2.7-dev.1234

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 (103) hide show
  1. package/dist/composition/owned-ui.js +13 -79
  2. package/dist/composition/release-update-observation.d.ts +22 -0
  3. package/dist/composition/release-update-observation.js +91 -0
  4. package/dist/composition/resident-tab-bridge.d.ts +16 -0
  5. package/dist/composition/resident-tab-bridge.js +45 -16
  6. package/dist/composition/startup-route.d.ts +8 -0
  7. package/dist/composition/startup-route.js +20 -0
  8. package/dist/contracts/owned-ui/session-workflows.d.ts +3 -0
  9. package/dist/foundation/release/bootstrap.js +46 -36
  10. package/dist/foundation/release/progress-palette.generated.d.ts +1 -1
  11. package/dist/foundation/release/progress-palette.generated.js +1 -1
  12. package/dist/foundation/release/update-activation.js +8 -2
  13. package/dist/foundation/resident-tabs/bridge-client.d.ts +3 -0
  14. package/dist/foundation/resident-tabs/bridge-client.js +7 -1
  15. package/dist/foundation/resident-tabs/continuity.d.ts +12 -0
  16. package/dist/foundation/resident-tabs/continuity.js +55 -0
  17. package/dist/foundation/resident-tabs/index.d.ts +3 -0
  18. package/dist/foundation/resident-tabs/index.js +4 -0
  19. package/dist/foundation/resident-tabs/maintenance.d.ts +1 -1
  20. package/dist/foundation/resident-tabs/release-holds.js +11 -8
  21. package/dist/foundation/resident-tabs/runtime-control.d.ts +38 -0
  22. package/dist/foundation/resident-tabs/runtime-control.js +73 -0
  23. package/dist/foundation/startup/startup-descriptor.js +2 -2
  24. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  25. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  26. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  27. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  28. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  29. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  30. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  31. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +3 -3
  32. package/dist/integrations/pi/components/upstream/components/extension-editor.js +4 -1
  33. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  34. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  35. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  36. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  37. package/dist/integrations/pi/components/upstream/components/owned-editor.js +8 -1
  38. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  39. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +2 -1
  40. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +14 -3
  41. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  42. package/dist/integrations/pi/components/upstream/components/session-selector-search.d.ts +4 -0
  43. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +87 -23
  44. package/dist/integrations/pi/components/upstream/components/session-selector.d.ts +3 -2
  45. package/dist/integrations/pi/components/upstream/components/session-selector.js +18 -13
  46. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  47. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  48. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  49. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  50. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  51. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  52. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  53. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  54. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +6 -0
  55. package/dist/integrations/pi/components/upstream/components/tool-execution.js +14 -2
  56. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +2 -1
  57. package/dist/integrations/pi/components/upstream/components/tree-selector.js +5 -4
  58. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  59. package/dist/integrations/pi/components/upstream/external-editor.d.ts +1 -0
  60. package/dist/integrations/pi/components/upstream/external-editor.js +13 -6
  61. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +3 -1
  62. package/dist/integrations/pi/components/upstream/history/editor-core.js +9 -2
  63. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  64. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  65. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  66. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  67. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  68. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  69. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  70. package/dist/integrations/pi/components/upstream/model-search.d.ts +11 -1
  71. package/dist/integrations/pi/components/upstream/model-search.js +21 -0
  72. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  73. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  74. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  75. package/dist/integrations/pi/engine/adapter.js +6 -1
  76. package/dist/integrations/pi/engine/diagnostics-state.d.ts +9 -0
  77. package/dist/integrations/pi/engine/diagnostics-state.js +34 -0
  78. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  79. package/dist/integrations/pi/engine/view-state.d.ts +2 -1
  80. package/dist/integrations/pi/engine/view-state.js +4 -16
  81. package/dist/integrations/pi/startup-public.js +324 -309
  82. package/dist/integrations/pi/startup-public.manifest.json +1156 -846
  83. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  84. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  85. package/dist/native/darwin-arm64/manifest.json +1 -1
  86. package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
  87. package/dist/native/darwin-arm64/terminal-host.node +0 -0
  88. package/dist/native/darwin-x64/manifest.json +1 -1
  89. package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
  90. package/dist/native/darwin-x64/terminal-host.node +0 -0
  91. package/dist/native/linux-x64/manifest.json +1 -1
  92. package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
  93. package/dist/native/linux-x64/terminal-host.node +0 -0
  94. package/dist/native/win32-x64/manifest.json +2 -2
  95. package/dist/native/win32-x64/process-guardian.node +0 -0
  96. package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
  97. package/dist/native/win32-x64/terminal-host.node +0 -0
  98. package/dist/runtime-payload-inventory.json +8178 -5237
  99. package/dist/ui/settings/progress-palette.generated.d.ts +1 -1
  100. package/dist/ui/settings/progress-palette.generated.js +1 -1
  101. package/docs/architecture/native-fixture-isolation.md +23 -0
  102. package/docs/architecture/resident-tabs.md +23 -4
  103. package/package.json +10 -5
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/session-selector-search.ts.
4
4
  * Modifications: Source-synchronized session search port with only the public SessionInfo type import
5
5
  * remapped.
@@ -9,8 +9,79 @@ import { fuzzyMatch } from "@earendil-works/pi-tui";
9
9
  function normalizeWhitespaceLower(text) {
10
10
  return text.toLowerCase().replace(/\s+/g, " ").trim();
11
11
  }
12
- function getSessionSearchText(session) {
13
- return `${session.id} ${session.name ?? ""} ${session.allMessagesText} ${session.cwd}`;
12
+ /**
13
+ * Match tiers, best first. Each token is scored by the best field it matches; tiers dominate
14
+ * fuzzy scores so an exact hit anywhere beats a scattered subsequence in a short field.
15
+ */
16
+ const TIER_NAME = 0; // query text appears in the session name
17
+ const TIER_TEXT = 1; // query text appears in the session id, messages, or cwd
18
+ const TIER_FUZZY = 2; // query characters appear scattered in the session name or cwd
19
+ const TIER_WEIGHT = 1_000_000;
20
+ /**
21
+ * Lowercased message text per session. allMessagesText holds every user/assistant message and
22
+ * can be megabytes, so lowercase it once instead of on every keystroke.
23
+ */
24
+ const messageTextCache = new WeakMap();
25
+ function getMessageText(session) {
26
+ let cached = messageTextCache.get(session);
27
+ if (!cached || cached.source !== session.allMessagesText) {
28
+ cached = { source: session.allMessagesText, lower: session.allMessagesText.toLowerCase() };
29
+ messageTextCache.set(session, cached);
30
+ }
31
+ return cached;
32
+ }
33
+ function getNormalizedMessageText(session) {
34
+ const cached = getMessageText(session);
35
+ cached.normalized ??= cached.lower.replace(/\s+/g, " ").trim();
36
+ return cached.normalized;
37
+ }
38
+ function tierScore(tier, score = 0) {
39
+ return tier * TIER_WEIGHT + score;
40
+ }
41
+ /** Exact (case-insensitive) text match. Messages and ids are only matched exactly: scattered matches in them are noise. */
42
+ function matchLiteralToken(session, value) {
43
+ const name = session.name?.toLowerCase() ?? "";
44
+ if (name.includes(value))
45
+ return tierScore(TIER_NAME, fuzzyMatch(value, name).score);
46
+ if (session.id.toLowerCase().includes(value))
47
+ return tierScore(TIER_TEXT);
48
+ if (getMessageText(session).lower.includes(value))
49
+ return tierScore(TIER_TEXT);
50
+ if (session.cwd.toLowerCase().includes(value))
51
+ return tierScore(TIER_TEXT);
52
+ return undefined;
53
+ }
54
+ function matchFuzzyToken(session, value) {
55
+ const literal = matchLiteralToken(session, value.toLowerCase());
56
+ if (literal !== undefined)
57
+ return literal;
58
+ let best;
59
+ for (const field of [session.name ?? "", session.cwd]) {
60
+ const m = fuzzyMatch(value, field);
61
+ if (m.matches && (best === undefined || m.score < best))
62
+ best = m.score;
63
+ }
64
+ return best === undefined ? undefined : tierScore(TIER_FUZZY, best);
65
+ }
66
+ function matchPhraseToken(session, phrase) {
67
+ const name = normalizeWhitespaceLower(session.name ?? "");
68
+ if (name.includes(phrase))
69
+ return tierScore(TIER_NAME, fuzzyMatch(phrase, name).score);
70
+ if (session.id.toLowerCase().includes(phrase))
71
+ return tierScore(TIER_TEXT);
72
+ if (getNormalizedMessageText(session).includes(phrase))
73
+ return tierScore(TIER_TEXT);
74
+ if (normalizeWhitespaceLower(session.cwd).includes(phrase))
75
+ return tierScore(TIER_TEXT);
76
+ return undefined;
77
+ }
78
+ function matchRegex(session, regex) {
79
+ if (session.name && regex.test(session.name))
80
+ return tierScore(TIER_NAME);
81
+ if (regex.test(session.id) || regex.test(session.allMessagesText) || regex.test(session.cwd)) {
82
+ return tierScore(TIER_TEXT);
83
+ }
84
+ return undefined;
14
85
  }
15
86
  export function hasSessionName(session) {
16
87
  return Boolean(session.name?.trim());
@@ -89,40 +160,33 @@ export function parseSearchQuery(query) {
89
160
  flush(inQuote ? "phrase" : "fuzzy");
90
161
  return { mode: "tokens", tokens, regex: null };
91
162
  }
163
+ /**
164
+ * Each field is matched separately, so a token never matches across field boundaries.
165
+ * Different tokens may match different fields.
166
+ */
92
167
  export function matchSession(session, parsed) {
93
- const text = getSessionSearchText(session);
94
168
  if (parsed.mode === "regex") {
95
169
  if (!parsed.regex) {
96
170
  return { matches: false, score: 0 };
97
171
  }
98
- const idx = text.search(parsed.regex);
99
- if (idx < 0)
100
- return { matches: false, score: 0 };
101
- return { matches: true, score: idx * 0.1 };
102
- }
103
- if (parsed.tokens.length === 0) {
104
- return { matches: true, score: 0 };
172
+ const score = matchRegex(session, parsed.regex);
173
+ return score === undefined ? { matches: false, score: 0 } : { matches: true, score };
105
174
  }
106
175
  let totalScore = 0;
107
- let normalizedText = null;
108
176
  for (const token of parsed.tokens) {
177
+ let score;
109
178
  if (token.kind === "phrase") {
110
- if (normalizedText === null) {
111
- normalizedText = normalizeWhitespaceLower(text);
112
- }
113
179
  const phrase = normalizeWhitespaceLower(token.value);
114
180
  if (!phrase)
115
181
  continue;
116
- const idx = normalizedText.indexOf(phrase);
117
- if (idx < 0)
118
- return { matches: false, score: 0 };
119
- totalScore += idx * 0.1;
120
- continue;
182
+ score = matchPhraseToken(session, phrase);
183
+ }
184
+ else {
185
+ score = matchFuzzyToken(session, token.value);
121
186
  }
122
- const m = fuzzyMatch(token.value, text);
123
- if (!m.matches)
187
+ if (score === undefined)
124
188
  return { matches: false, score: 0 };
125
- totalScore += m.score;
189
+ totalScore += score;
126
190
  }
127
191
  return { matches: true, score: totalScore };
128
192
  }
@@ -1,10 +1,10 @@
1
1
  import { type Component, Container, type Focusable } from "@earendil-works/pi-tui";
2
2
  import { KeybindingsManager } from "../adjacent/core/keybindings.js";
3
3
  import { type SessionInfo } from "@earendil-works/pi-coding-agent";
4
+ import { type NameFilter, type SortMode } from "./session-selector-search.js";
4
5
  type SessionListProgress = (loaded: number, total: number,
5
6
  /** Sessions loaded so far, sorted by activity. Present on periodic updates. */
6
7
  partialSessions?: readonly SessionInfo[]) => void;
7
- import { type NameFilter, type SortMode } from "./session-selector-search.js";
8
8
  /**
9
9
  * Custom session list component with multi-line items and search
10
10
  */
@@ -21,7 +21,7 @@ declare class SessionList implements Component, Focusable {
21
21
  private keybindings;
22
22
  private showPath;
23
23
  private confirmingDeletePath;
24
- private currentSessionCanonicalPath;
24
+ private currentSessionPathKey;
25
25
  onSelect?: (sessionPath: string) => void;
26
26
  onCancel?: () => void;
27
27
  onExit: () => void;
@@ -56,6 +56,7 @@ type SessionsLoader = (onProgress?: SessionListProgress, signal?: AbortSignal) =
56
56
  * Component that renders a session selector
57
57
  */
58
58
  export declare class SessionSelectorComponent extends Container implements Focusable {
59
+ get capturesViewportInput(): boolean;
59
60
  handleInput(data: string): void;
60
61
  private canRename;
61
62
  private sessionList;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/session-selector.ts.
4
4
  * Modifications: Source-synchronized session selector port: preserve threaded/current/all scope,
5
5
  * search, sort, named/path filters, rename, delete confirmation, active-session protection,
@@ -23,6 +23,7 @@ import { KeybindingsManager } from "../adjacent/core/keybindings.js";
23
23
  import { DynamicBorder } from "../../../startup-public.js";
24
24
  import { addPiModalHeader, adoptPiModalFrame, renderPiModalSearchInput } from "../../modal-frame.js";
25
25
  import { DIALOG_CLOSE_SHORTCUT_HINT, paintPiBorder, piTheme, renderPiModalShortcutHints } from "../../theme.js";
26
+ import { filterAndSortSessions, hasSessionName } from "./session-selector-search.js";
26
27
  const theme = new Proxy({}, {
27
28
  get(_target, property) {
28
29
  const active = piTheme();
@@ -46,15 +47,11 @@ function withCloseHint(content, width) {
46
47
  const body = truncateToWidth(content, bodyWidth, "…");
47
48
  return body.length === 0 ? close : `${body} ${close}`;
48
49
  }
49
- import { filterAndSortSessions, hasSessionName } from "./session-selector-search.js";
50
50
  function shortenPath(path) {
51
51
  const home = os.homedir();
52
52
  if (!path)
53
53
  return path;
54
- if (path.startsWith(home)) {
55
- return `~${path.slice(home.length)}`;
56
- }
57
- return path;
54
+ return path.startsWith(home) ? `~${path.slice(home.length)}` : path;
58
55
  }
59
56
  function formatSessionDate(date) {
60
57
  const now = new Date();
@@ -107,6 +104,11 @@ function canonicalizePath(path) {
107
104
  return path;
108
105
  }
109
106
  }
107
+ /** Comparison key for a session file path; follows symlinks and ignores case on Windows. */
108
+ function getSessionPathKey(path) {
109
+ const canonical = canonicalizePath(path) ?? path;
110
+ return process.platform === "win32" ? canonical.toLocaleLowerCase("en-US") : canonical;
111
+ }
110
112
  class SessionSelectorHeader {
111
113
  scope;
112
114
  sortMode;
@@ -219,14 +221,14 @@ class SessionSelectorFooter {
219
221
  function buildSessionTree(sessions) {
220
222
  const byPath = new Map();
221
223
  for (const session of sessions) {
222
- const sessionPath = canonicalizePath(session.path) ?? session.path;
224
+ const sessionPath = getSessionPathKey(session.path);
223
225
  byPath.set(sessionPath, { session, children: [], latestActivity: session.modified.getTime() });
224
226
  }
225
227
  const roots = [];
226
228
  for (const session of sessions) {
227
- const sessionPath = canonicalizePath(session.path) ?? session.path;
229
+ const sessionPath = getSessionPathKey(session.path);
228
230
  const node = byPath.get(sessionPath);
229
- const parentPath = canonicalizePath(session.parentSessionPath);
231
+ const parentPath = session.parentSessionPath ? getSessionPathKey(session.parentSessionPath) : undefined;
230
232
  if (parentPath && byPath.has(parentPath)) {
231
233
  byPath.get(parentPath).children.push(node);
232
234
  }
@@ -293,7 +295,7 @@ class SessionList {
293
295
  keybindings;
294
296
  showPath = false;
295
297
  confirmingDeletePath = null;
296
- currentSessionCanonicalPath;
298
+ currentSessionPathKey;
297
299
  onSelect;
298
300
  onCancel;
299
301
  onExit = () => { };
@@ -326,7 +328,7 @@ class SessionList {
326
328
  this.sortMode = sortMode;
327
329
  this.nameFilter = nameFilter;
328
330
  this.keybindings = keybindings;
329
- this.currentSessionCanonicalPath = canonicalizePath(currentSessionFilePath);
331
+ this.currentSessionPathKey = currentSessionFilePath ? getSessionPathKey(currentSessionFilePath) : undefined;
330
332
  this.filterSessions("");
331
333
  // Handle Enter in search input - select current item
332
334
  this.searchInput.onSubmit = () => {
@@ -396,9 +398,9 @@ class SessionList {
396
398
  this.setConfirmingDeletePath(selected.session.path);
397
399
  }
398
400
  isCurrentSessionPath(path) {
399
- if (!this.currentSessionCanonicalPath)
401
+ if (!this.currentSessionPathKey)
400
402
  return false;
401
- return (canonicalizePath(path) ?? path) === this.currentSessionCanonicalPath;
403
+ return getSessionPathKey(path) === this.currentSessionPathKey;
402
404
  }
403
405
  sessionPathText(session) {
404
406
  if (this.showPath)
@@ -644,6 +646,9 @@ async function deleteSessionFile(sessionPath) {
644
646
  * Component that renders a session selector
645
647
  */
646
648
  export class SessionSelectorComponent extends Container {
649
+ get capturesViewportInput() {
650
+ return this.mode !== "rename";
651
+ }
647
652
  handleInput(data) {
648
653
  if (this.mode === "rename") {
649
654
  const kb = getKeybindings();
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts.
4
4
  * Modifications: Mechanical port uses A1's public pi-tui instance, owned theme boundary, and
5
5
  * root-instance keybinding registry because the public coding-agent component closes over a second
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts.
4
4
  * Modifications: Mechanical port uses A1's public pi-tui instance, owned theme boundary, and
5
5
  * root-instance keybinding registry because the public coding-agent component closes over a second
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/status-indicator.ts.
4
4
  * Modifications: Mechanical source port with public package-root keybinding, Loader, and owned
5
5
  * theme/countdown imports plus ECMAScript private fields.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/status-indicator.ts.
4
4
  * Modifications: Mechanical source port with public package-root keybinding, Loader, and owned
5
5
  * theme/countdown imports plus ECMAScript private fields.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/themed-text.ts.
4
4
  * Modifications: Integrated invalidation-aware text into A1's owned startup header and notices;
5
5
  * repository formatting only.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/themed-text.ts.
4
4
  * Modifications: Integrated invalidation-aware text into A1's owned startup header and notices;
5
5
  * repository formatting only.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/thinking-selector.ts.
4
4
  * Modifications: Preserve the searchable thinking-level selector, current/default semantics,
5
5
  * selection, and focus while accepting the active bare-A1 cycle-key label from the shell, styling the
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/thinking-selector.ts.
4
4
  * Modifications: Preserve the searchable thinking-level selector, current/default semantics,
5
5
  * selection, and focus while accepting the active bare-A1 cycle-key label from the shell, styling the
@@ -38,6 +38,8 @@ export declare class ToolExecutionComponent extends Container {
38
38
  private cwd;
39
39
  private executionStarted;
40
40
  private argsComplete;
41
+ /** `updateArgs()` ran since the last display update; the next render applies it. */
42
+ private argsPending;
41
43
  private result;
42
44
  private hideComponent;
43
45
  constructor(toolName: string, toolCallId: string, args: any, options: ToolExecutionOptions | undefined, toolDefinition: ToolRenderers | ToolDefinition<any, any, any> | undefined, ui: TUI, cwd: string);
@@ -46,6 +48,10 @@ export declare class ToolExecutionComponent extends Container {
46
48
  private createCallFallback;
47
49
  private createResultFallback;
48
50
  private createResultRegion;
51
+ /**
52
+ * Show new partial arguments. Applied at the next render, so a call streaming many argument deltas between two
53
+ * frames runs its renderer once per frame, not once per delta (#9265).
54
+ */
49
55
  updateArgs(args: any): void;
50
56
  markExecutionStarted(): void;
51
57
  setArgsComplete(): void;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/tool-execution.ts.
4
4
  * Modifications: Retain pinned shell/public renderers. Own image conversion; replace private APIs with
5
5
  * public/local equivalents. Use bare-A1 secondary-accent read ranges and concise collapse shortcut
@@ -122,6 +122,8 @@ export class ToolExecutionComponent extends Container {
122
122
  cwd;
123
123
  executionStarted = false;
124
124
  argsComplete = false;
125
+ /** `updateArgs()` ran since the last display update; the next render applies it. */
126
+ argsPending = false;
125
127
  result;
126
128
  hideComponent = false;
127
129
  constructor(toolName, toolCallId, args, options = {}, toolDefinition, ui, cwd) {
@@ -179,6 +181,8 @@ export class ToolExecutionComponent extends Container {
179
181
  isError: this.result?.isError ?? false,
180
182
  durationMs: this.isPartial ? undefined : this.result?.durationMs,
181
183
  outputPad: this.outputPad,
184
+ keyText,
185
+ keyHint,
182
186
  };
183
187
  }
184
188
  createCallFallback() {
@@ -206,9 +210,14 @@ export class ToolExecutionComponent extends Container {
206
210
  return { handled: true };
207
211
  });
208
212
  }
213
+ /**
214
+ * Show new partial arguments. Applied at the next render, so a call streaming many argument deltas between two
215
+ * frames runs its renderer once per frame, not once per delta (#9265).
216
+ */
209
217
  updateArgs(args) {
210
218
  this.args = args;
211
- this.updateDisplay();
219
+ this.argsPending = true;
220
+ this.ui.requestRender();
212
221
  }
213
222
  markExecutionStarted() {
214
223
  this.executionStarted = true;
@@ -257,6 +266,8 @@ export class ToolExecutionComponent extends Container {
257
266
  this.updateDisplay();
258
267
  }
259
268
  render(width) {
269
+ if (this.argsPending)
270
+ this.updateDisplay();
260
271
  if (this.hideComponent) {
261
272
  return [];
262
273
  }
@@ -336,6 +347,7 @@ export class ToolExecutionComponent extends Container {
336
347
  }
337
348
  composeDisplay() {
338
349
  const theme = piTheme();
350
+ this.argsPending = false;
339
351
  const bgFn = enclosingToolBackground(theme, this.isPartial ? "toolPendingBg"
340
352
  : this.result?.isError ? "toolErrorBg" : "toolSuccessBg");
341
353
  let hasContent = false;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/tree-selector.ts.
4
4
  * Modifications: Port remaps public types/components plus owned keybindings/theme helpers while
5
5
  * preserving tree behavior; bare A1 uses compact modal chrome and label editing, four-mode
@@ -106,6 +106,7 @@ export declare class TreeSelectorComponent extends Container implements Focusabl
106
106
  private restoreTreeContent;
107
107
  private showLabelInput;
108
108
  private hideLabelInput;
109
+ get capturesViewportInput(): boolean;
109
110
  handleInput(keyData: string): void;
110
111
  getTreeList(): TreeList;
111
112
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/tree-selector.ts.
4
4
  * Modifications: Port remaps public types/components plus owned keybindings/theme helpers while
5
5
  * preserving tree behavior; bare A1 uses compact modal chrome and label editing, four-mode
@@ -807,9 +807,7 @@ class TreeList {
807
807
  formatToolCall(name, args) {
808
808
  const shortenPath = (p) => {
809
809
  const home = process.env.HOME || process.env.USERPROFILE || "";
810
- if (home && p.startsWith(home))
811
- return `~${p.slice(home.length)}`;
812
- return p;
810
+ return home && p.startsWith(home) ? `~${p.slice(home.length)}` : p;
813
811
  };
814
812
  switch (name) {
815
813
  case "read": {
@@ -1322,6 +1320,9 @@ export class TreeSelectorComponent extends Container {
1322
1320
  this.labelInputContainer.clear();
1323
1321
  this.restoreTreeContent();
1324
1322
  }
1323
+ get capturesViewportInput() {
1324
+ return this.labelInput === null;
1325
+ }
1325
1326
  handleInput(keyData) {
1326
1327
  if (this.labelInput) {
1327
1328
  this.labelInput.handleInput(keyData);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/components/trust-selector.ts.
4
4
  * Modifications: Mechanical source-synchronized trust selector port with injected public
5
5
  * ProjectTrustStore-derived options, remapped owned theme imports, the shared bare-A1 modal shortcut
@@ -6,4 +6,5 @@ export declare function editInExternalEditor(options: {
6
6
  readonly content: string;
7
7
  } | {
8
8
  readonly status: "failed";
9
+ readonly message: string;
9
10
  }>;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/external-editor.ts.
4
4
  * Modifications: Mechanical port: retain temporary prompt file, asynchronous inherited-stdio editor
5
5
  * process, completion readback, and best-effort cleanup behind the owned extension-editor component.
@@ -16,18 +16,25 @@ export async function editInExternalEditor(options) {
16
16
  writeFileSync(filePath, options.content, "utf-8");
17
17
  const [editor, ...editorArgs] = options.command.split(" ");
18
18
  if (!editor)
19
- return { status: "failed" };
19
+ return { status: "failed", message: "No external editor command is configured" };
20
20
  process.stdout.write(`Launching external editor: ${options.command}\nPi will resume when the editor exits.\n`);
21
- const exitCode = await new Promise(resolve => {
21
+ const exit = await new Promise(resolve => {
22
22
  const child = spawn(editor, [...editorArgs, filePath], {
23
23
  stdio: "inherit",
24
24
  shell: process.platform === "win32",
25
25
  });
26
26
  child.on("error", () => resolve(null));
27
- child.on("close", code => resolve(code));
27
+ child.on("close", (code, signal) => resolve(code ?? signal));
28
28
  });
29
- if (exitCode !== 0)
30
- return { status: "failed" };
29
+ if (exit === null) {
30
+ return { status: "failed", message: `Failed to launch external editor: ${options.command}` };
31
+ }
32
+ if (exit !== 0) {
33
+ return {
34
+ status: "failed",
35
+ message: `External editor exited with ${typeof exit === "number" ? `code ${exit}` : exit}; prompt unchanged`,
36
+ };
37
+ }
31
38
  // Rationale: upstream strips the BOM through a private util the package does not export; the check lives here.
32
39
  const edited = readFileSync(filePath, "utf-8");
33
40
  return { status: "complete", content: (edited.startsWith("") ? edited.slice(1) : edited).replace(/\n$/, "") };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-tui 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-tui 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/tui/src/components/editor.ts.
4
4
  * Modifications: Owned editor core or minimal editor-local helper subset; public imports, strict
5
5
  * types, typed persistent-history hooks, semantic border state with the user-approved numeric-only
@@ -48,6 +48,8 @@ export declare class HistoryEditorCore implements Component, Focusable {
48
48
  private state;
49
49
  /** Focusable interface - set by TUI when focus changes */
50
50
  focused: boolean;
51
+ /** The open autocomplete menu receives fullscreen viewport keys, such as PageUp/PageDown. */
52
+ get capturesViewportInput(): boolean;
51
53
  protected tui: TUI;
52
54
  private theme;
53
55
  private paddingX;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-tui 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-tui 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/tui/src/components/editor.ts.
4
4
  * Modifications: Owned editor core or minimal editor-local helper subset; public imports, strict
5
5
  * types, typed persistent-history hooks, semantic border state with the user-approved numeric-only
@@ -243,6 +243,10 @@ export class HistoryEditorCore {
243
243
  };
244
244
  /** Focusable interface - set by TUI when focus changes */
245
245
  focused = false;
246
+ /** The open autocomplete menu receives fullscreen viewport keys, such as PageUp/PageDown. */
247
+ get capturesViewportInput() {
248
+ return this.autocompleteState !== null;
249
+ }
246
250
  tui;
247
251
  theme;
248
252
  paddingX = 0;
@@ -734,7 +738,10 @@ export class HistoryEditorCore {
734
738
  this.cancelAutocomplete();
735
739
  return;
736
740
  }
737
- if (kb.matches(data, "tui.select.up") || kb.matches(data, "tui.select.down")) {
741
+ if (kb.matches(data, "tui.select.up") ||
742
+ kb.matches(data, "tui.select.down") ||
743
+ kb.matches(data, "tui.select.pageUp") ||
744
+ kb.matches(data, "tui.select.pageDown")) {
738
745
  this.autocompleteList.handleInput(data);
739
746
  return;
740
747
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-tui 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-tui 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/tui/src/kill-ring.ts.
4
4
  * Modifications: Owned editor core or minimal editor-local helper subset; public imports, strict
5
5
  * types, typed persistent-history hooks, and semantic border state. Public terminal runtime/exports
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-tui 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-tui 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/tui/src/kill-ring.ts.
4
4
  * Modifications: Owned editor core or minimal editor-local helper subset; public imports, strict
5
5
  * types, typed persistent-history hooks, and semantic border state. Public terminal runtime/exports
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-tui 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-tui 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/tui/src/keys.ts.
4
4
  * Modifications: Owned editor core or minimal editor-local helper subset; public imports, strict
5
5
  * types, typed persistent-history hooks, and semantic border state. Public terminal runtime/exports
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-tui 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-tui 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/tui/src/utils.ts.
4
4
  * Modifications: Owned editor core or minimal editor-local helper subset; public imports, strict
5
5
  * types, typed persistent-history hooks, and semantic border state. Public terminal runtime/exports
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-tui 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-tui 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/tui/src/undo-stack.ts.
4
4
  * Modifications: Owned editor core or minimal editor-local helper subset; public imports, strict
5
5
  * types, typed persistent-history hooks, and semantic border state. Public terminal runtime/exports
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-tui 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-tui 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/tui/src/undo-stack.ts.
4
4
  * Modifications: Owned editor core or minimal editor-local helper subset; public imports, strict
5
5
  * types, typed persistent-history hooks, and semantic border state. Public terminal runtime/exports
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-tui 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-tui 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/tui/src/word-navigation.ts.
4
4
  * Modifications: Owned editor core or minimal editor-local helper subset; public imports, strict
5
5
  * types, typed persistent-history hooks, and semantic border state. Public terminal runtime/exports
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.5.0 (MIT), commit f9a26365568127461c47a07a37dcb42c140a3ac5,
3
3
  * packages/coding-agent/src/modes/interactive/model-search.ts.
4
4
  * Modifications: Mechanical source-synchronized port preserving pinned model search terms for stateful
5
5
  * scoped-model filtering.
@@ -11,6 +11,16 @@ export interface ModelSearchItem {
11
11
  name?: string;
12
12
  }
13
13
  export declare function getModelSearchText(item: ModelSearchItem): string;
14
+ /**
15
+ * Returns the model name when it has words the ID does not, e.g. a renamed override like
16
+ * "MiniMax M3 [rasmus@openrouter, parasail]" for "minimax/minimax-m3". Names that only
17
+ * restate the ID with different casing, separators, or a dropped namespace/version suffix
18
+ * ("Claude Sonnet 4.5 (EU)" for "eu.anthropic.claude-sonnet-4-5-20250929-v1:0") return undefined.
19
+ */
20
+ export declare function getDistinctModelName(item: {
21
+ id: string;
22
+ name?: string;
23
+ }): string | undefined;
14
24
  /**
15
25
  * The /model selector search should rank exact provider-prefixed queries before proxy-provider IDs
16
26
  * like openrouter/openai/gpt-5, so keep the bare model ID out of the leading position.