@timurproko/a1 0.1.8-dev.521 → 0.1.8-dev.527

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 (75) hide show
  1. package/README.md +8 -118
  2. package/dist/app/session-shell/session-shell-root.js +1 -1
  3. package/dist/app/session-shell/session-shell.d.ts +2 -2
  4. package/dist/app/session-shell/session-shell.js +9 -9
  5. package/dist/foundation/startup/startup-descriptor.js +2 -2
  6. package/dist/integrations/pi/components/shell-editor-autocomplete.js +2 -1
  7. package/dist/integrations/pi/components/shell-presenters-info.d.ts +19 -0
  8. package/dist/integrations/pi/components/shell-presenters-info.js +56 -2
  9. package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +6 -4
  10. package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -4
  11. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +2 -2
  12. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +2 -2
  13. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  14. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  15. package/dist/integrations/pi/components/upstream/components/daxnuts.d.ts +1 -1
  16. package/dist/integrations/pi/components/upstream/components/daxnuts.js +1 -1
  17. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  18. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +2 -1
  19. package/dist/integrations/pi/components/upstream/components/extension-editor.js +7 -2
  20. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  21. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  22. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  23. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  24. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  25. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  26. package/dist/integrations/pi/components/upstream/components/session-selector.d.ts +8 -6
  27. package/dist/integrations/pi/components/upstream/components/session-selector.js +75 -49
  28. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  29. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +18 -10
  30. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +3 -3
  31. package/dist/integrations/pi/components/upstream/components/status-indicator.js +8 -8
  32. package/dist/integrations/pi/components/upstream/components/tool-execution.js +1 -1
  33. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  34. package/dist/integrations/pi/components/upstream/components/tree-selector.js +3 -1
  35. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  36. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  37. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
  38. package/dist/integrations/pi/components/upstream/history/editor-core.js +8 -7
  39. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  40. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  41. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  42. package/dist/integrations/pi/components/upstream/history/text-helpers.d.ts +3 -0
  43. package/dist/integrations/pi/components/upstream/history/text-helpers.js +4 -1
  44. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  45. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  46. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  47. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  48. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  49. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  50. package/dist/integrations/pi/engine/index.d.ts +1 -1
  51. package/dist/integrations/pi/engine/index.js +1 -1
  52. package/dist/integrations/pi/engine/pi-settings-metadata.json +12 -0
  53. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  54. package/dist/integrations/pi/engine/settings-bridge.d.ts +1 -1
  55. package/dist/integrations/pi/engine/settings-bridge.js +2 -0
  56. package/dist/integrations/pi/engine/settings-port.js +11 -1
  57. package/dist/integrations/pi/engine/usage-view.js +1 -1
  58. package/dist/integrations/pi/engine/workflow-runner.js +4 -1
  59. package/dist/integrations/pi/engine/workflow-support.d.ts +6 -1
  60. package/dist/integrations/pi/engine/workflow-support.js +36 -2
  61. package/dist/integrations/pi/engine/workflows.d.ts +36 -3
  62. package/dist/integrations/pi/engine/workflows.js +8 -0
  63. package/dist/integrations/pi/startup-public.js +1001 -976
  64. package/dist/integrations/pi/startup-public.manifest.json +1846 -1672
  65. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  66. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +7 -1
  67. package/dist/native/darwin-arm64/manifest.json +1 -1
  68. package/dist/native/linux-x64/manifest.json +1 -1
  69. package/dist/native/win32-x64/manifest.json +2 -2
  70. package/dist/native/win32-x64/process-guardian.exe +0 -0
  71. package/dist/runtime-payload-inventory.json +41121 -34266
  72. package/docs/architecture/toolchain.md +2 -0
  73. package/docs/ci-release-runbook.md +1 -1
  74. package/docs/openspec-archive-automation.md +2 -2
  75. package/package.json +5 -4
package/README.md CHANGED
@@ -45,97 +45,6 @@ a1 pi # vanilla Pi oracle: ~/.pi/agent
45
45
  Unsupported commands exit quietly without launching anything. The removed
46
46
  `update:<preview>` forms are not aliases; use `update --develop`.
47
47
 
48
- ## Agent input
49
-
50
- The agent prompt and Settings search share one input component: neutral white
51
- bars and an undimmed arrow matching submitted prompts. Thinking-level color is
52
- shown on the level name in the status bar, not on the input bars.
53
-
54
- In bare A1, **Ctrl+L cycles the thinking level**. **Shift+Tab is unassigned** and
55
- performs no agent-input action, including while a suggestion is visible. Model
56
- selection has **no default shortcut**; use `/models`. Explicit keybinding overrides
57
- remain configurable, and `/hotkeys` shows the resolved bindings. The `a1 pi`
58
- comparison profile keeps its original presentation and shortcuts.
59
-
60
- ## Models
61
-
62
- Bare A1 has one model command, `/models`, which replaces the pinned `/model` and
63
- `/scoped-models` pair (those remain in the `a1 pi` comparison profile). The dialog
64
- lists every authenticated model with `all` and `scoped` filters (Tab), a search box,
65
- a scope marker before each model id, and the active checkmark after `[provider]`.
66
- Enter switches to the highlighted model and persists it as the default; Space adds or
67
- removes it from the Ctrl+P cycling scope for this session only; Ctrl+S saves that scope
68
- to settings. While the scope or its order differs from the last save, the title reads
69
- `Models (unsaved)`; Escape closes without saving and keeps the session-only scope.
70
- `/models <text>` seeds the search instead of switching. The bulk, provider, and reorder
71
- scope actions keep their existing bindings and appear under `/hotkeys`.
72
-
73
- ## Reference screens
74
-
75
- In bare A1, `/changelog` and `/hotkeys` open a full-screen read-only reference
76
- screen over the session instead of appending a long document to the
77
- conversation: `What's New` shows the complete pinned changelog and
78
- `Keyboard Shortcuts` shows the bare-A1 keybinding tables, including extension
79
- shortcuts as bound when the screen opens. Scroll with ↑/↓, PageUp/PageDown,
80
- Home/End, the mouse wheel, or the scrollbar rail, which follows the
81
- `/settings` → Scroll appearance, style, and speed; press `Esc` to close. The
82
- screen is framed between two border-coloured rules with the hint below, as the
83
- v2 extension drew it. After
84
- an upgrade, the release notes newer than the last acknowledged version open the
85
- same `What's New` screen once at startup while the feed keeps only the
86
- `Run /changelog to view the full release notes.` hint. If another dialog is up
87
- at that moment, the screen is not opened for that launch. The `a1 pi`
88
- comparison profile keeps Pi's in-feed changelog and hotkeys documents.
89
-
90
- ## Prompt suggestions
91
-
92
- Bare A1's `/settings` → Agent → Prompt suggestions controls faint next-prompt
93
- predictions. It is enabled by default and uses one additional background request
94
- with the selected model for eligible turns. Disabling it takes effect immediately.
95
- Tab accepts a suggestion as editable text; Enter submits it afterward. The setting
96
- remains stored in A1's profile, and `a1 pi` is unchanged.
97
-
98
- Suggestions use the selected model's lowest supported reasoning effort without
99
- changing your main thinking level. Clear next actions such as `archive it` are
100
- preferred when consistent with your intent; genuinely unclear cases can remain
101
- empty. [Private diagnostic capture](docs/architecture/prompt-suggestions.md)
102
- explains how to distinguish skipped, empty, rejected, and timed-out suggestions.
103
-
104
- ## Skills
105
-
106
- Bare A1's `/settings` → Agent → Skills chooses how discovered skills appear in the
107
- slash-command menu. `collapse` (the default) replaces the per-skill `/skill:<name>`
108
- entries with one `/skills` command: bare `/skills` opens a searchable Skills dialog,
109
- `/skills <name> [args]` applies a skill directly (an unknown name reports
110
- `Unknown skill: <name>`), and typing `/skills:` lists every skill inline so
111
- `/skills:<name> args` runs as `/skill:<name> args`. With the `skills` row selected in
112
- the menu, typing `:` completes to `/skills:`. `expand` lists every `/skill:<name>`
113
- command as before. Both take effect immediately; a typed `/skill:<name>` always
114
- works, and the engine's own Skill commands toggle still governs whether skills are
115
- offered at all. The `a1 pi` comparison profile is unchanged.
116
-
117
- ## Quitting
118
-
119
- `/quit`, `Ctrl+C` twice, and `Ctrl+D` on an empty prompt end a bare A1 session.
120
- The last screen dissolves on the alternate screen, the terminal is restored once,
121
- and only the dim `To resume this session:` hint is printed; the conversation is
122
- not echoed into your scrollback. `/settings` → Quit chooses the effect (`fall`,
123
- `dissolve`, `starburst`, `waves`, or `off`) and its duration (300–2000 ms). The
124
- `a1 pi` comparison profile keeps Pi's `fullscreenExitOutput` behavior.
125
-
126
- ## Prompt history
127
-
128
- Bare A1 recalls recent unique prompts across sessions with Up/Down. History is
129
- stored in a separate profile-local SQLite database at
130
- `~/.a1/data/history/<profile-id>.sqlite3`, or under `<A1_DATA_DIR>/history` when
131
- explicitly overridden. Other application data stays in its existing location.
132
- `/settings` → History controls persistence and the 10-100-entry limit (default
133
- 100), effective on next start. The new default starts fresh: old platform history
134
- is neither imported nor automatically deleted. Ordinary upgrades and npm
135
- uninstall/reinstall preserve saved history. History is unencrypted user text;
136
- images are not reattached. See
137
- [prompt history](docs/features/prompt-history.md) for privacy, storage, and removal.
138
-
139
48
  ## Extensions
140
49
 
141
50
  Pi extension packages install into A1's own profile (`~/.a1/agent`), so bare `a1`
@@ -160,7 +69,15 @@ project), never `~/.pi/agent`. Configure MCP with `/mcp setup` inside bare `a1`.
160
69
 
161
70
  ## Develop
162
71
 
72
+ A source build needs Node.js `>=22.19.0 <25`, npm 11, git, and Rust/Cargo 1.85 or
73
+ newer—the build compiles the `native/process-guardian` crate. Publishing a release
74
+ or a pull request additionally needs an authenticated [GitHub CLI](https://cli.github.com).
75
+ `npm run doctor` reports every prerequisite with the exact command that installs
76
+ whatever is missing, and `npm run build` runs the same check first so a fresh clone
77
+ fails by name instead of inside a resolver or Cargo.
78
+
163
79
  ```sh
80
+ npm run doctor # report Node, npm, git, Rust, and dependency readiness
164
81
  npm ci # install exact locked dependencies
165
82
  npm run build # compile TypeScript and the process guardian into dist
166
83
  npm start # build and launch a development `a1`
@@ -174,33 +91,6 @@ Create every task worktree at `{working-dir}/.worktrees/<task-id>`, where
174
91
  `D:/Git/a1`, use `D:/Git/a1/.worktrees/<task-id>`—never a sibling such as
175
92
  `D:/Git/a1-<task-id>`. The primary worktree remains on `develop` for integration only.
176
93
 
177
- ## Pull request integration
178
-
179
- Pull requests whose complete diff is only under `openspec/**`, under `docs/**`,
180
- exactly the root `README.md`, or a combination of those paths are automatically
181
- squash-merged after `Development validation required` succeeds. The automation
182
- reads the complete GitHub changed-file list, including both sides of renames, and
183
- runs only for trusted branches in this repository.
184
-
185
- Any other path makes the pull request code/operational. That includes source, tests,
186
- scripts, workflows, configuration, generated baselines, arbitrary root Markdown,
187
- and a mixed documentation-plus-code change. Those pull requests remain open after
188
- CI for local maintainer validation and explicit manual merge; automation disables
189
- auto-merge if it was armed. Documentation remains exempt from product builds and
190
- tests, but docs-sensitive generated governance and strict OpenSpec consistency are
191
- checked before integration.
192
-
193
- After any same-repository pull request into `develop` merges, trusted automation
194
- reconciles its remote topic branch. Human merges use the close-event workflow;
195
- documentation merges authored by `GITHUB_TOKEN` use a synchronous fallback because
196
- GitHub suppresses recursive workflow events. Both delete only an unprotected live
197
- ref that still equals the pull request's exact merged head SHA. Fork, advanced,
198
- reserved, protected, malformed, and unmerged refs are preserved and reported.
199
-
200
- Specification approval and implementation remain separate pull requests. An
201
- implementation starts from updated `origin/develop` only after its specification
202
- has merged and implementation was explicitly requested.
203
-
204
94
  ## Release
205
95
 
206
96
  Two channels, both published by CI from the exact bytes it validated — never from
@@ -849,7 +849,7 @@ export class OwnedUiSessionShellRoot {
849
849
  this.#appendAnchoredWorkflowComponent(width => ["", ...announcement.render(width)], () => announcement.dispose?.());
850
850
  return;
851
851
  }
852
- // Rationale: pinned 0.85.1 links both share URLs; the workflow result carries the plain URLs.
852
+ // Rationale: the pinned engine links both share URLs; the workflow result carries the plain URLs.
853
853
  const message = result.command === "share" && result.detail
854
854
  ? `${linkShareUrl(result.message)}\nGist: ${piShellHyperlink(result.detail)}`
855
855
  : result.message;
@@ -43,10 +43,10 @@ export declare class OwnedUiSessionShell {
43
43
  showForkSelector(): void;
44
44
  showLogoutSelector(): Promise<void>;
45
45
  showLoginMethodSelector(providerReference: string): void;
46
- showTreeSelector(initialSelectedId?: string): void;
46
+ showTreeSelector(initialSelectedId?: string): Promise<void>;
47
47
  showLoginAuthTypeSelector(): void;
48
48
  showLoginProviderSelector(authType?: "oauth" | "api_key", initialSearchInput?: string): void;
49
- showSessionSelector(): void;
49
+ showSessionSelector(): Promise<void>;
50
50
  showSettingsSelector(): void;
51
51
  shutdown(): Promise<AdapterCommandResult>;
52
52
  runWorkflow(request: PiWorkflowRequest): Promise<AdapterCommandResult>;
@@ -717,7 +717,7 @@ export class OwnedUiSessionShell {
717
717
  if (now - this.#lastEscapeTime < 500) {
718
718
  this.#lastEscapeTime = 0;
719
719
  if (action === "tree")
720
- this.showTreeSelector();
720
+ await this.showTreeSelector();
721
721
  else
722
722
  this.showForkSelector();
723
723
  return { outcome: "completed", diagnostic: null };
@@ -972,7 +972,7 @@ export class OwnedUiSessionShell {
972
972
  this.root.setInputSurface(component);
973
973
  this.runtime.requestRender();
974
974
  }
975
- showTreeSelector(initialSelectedId) {
975
+ async showTreeSelector(initialSelectedId) {
976
976
  const context = this.backend.pinnedTreeSelectorContext();
977
977
  if (context.tree.length === 0) {
978
978
  this.root.appendWorkflowStatus("No entries in session");
@@ -983,7 +983,7 @@ export class OwnedUiSessionShell {
983
983
  this.root.setInputSurface(null);
984
984
  this.runtime.requestRender();
985
985
  };
986
- const component = createPiShellTreeSelector({
986
+ const component = await createPiShellTreeSelector({
987
987
  tree: context.tree,
988
988
  currentLeafId: context.currentLeafId,
989
989
  terminalHeight: this.runtime.viewport().rows,
@@ -1058,13 +1058,13 @@ export class OwnedUiSessionShell {
1058
1058
  this.root.setInputSurface(component);
1059
1059
  this.runtime.requestRender();
1060
1060
  }
1061
- showSessionSelector() {
1061
+ async showSessionSelector() {
1062
1062
  const context = this.backend.pinnedSessionSelectorContext();
1063
1063
  const close = () => {
1064
1064
  this.root.setInputSurface(null);
1065
1065
  this.runtime.requestRender();
1066
1066
  };
1067
- const component = createPiShellSessionSelector({
1067
+ const component = await createPiShellSessionSelector({
1068
1068
  currentSessionsLoader: context.loadCurrentSessions,
1069
1069
  allSessionsLoader: context.loadAllSessions,
1070
1070
  currentSessionFilePath: context.currentSessionFilePath,
@@ -1200,7 +1200,7 @@ export class OwnedUiSessionShell {
1200
1200
  return { outcome: "completed", diagnostic: null };
1201
1201
  }
1202
1202
  if (request.command === "resume" && request.selection === undefined && request.confirmed === undefined && request.argument.trim().length === 0) {
1203
- this.showSessionSelector();
1203
+ await this.showSessionSelector();
1204
1204
  return { outcome: "completed", diagnostic: null };
1205
1205
  }
1206
1206
  if (request.command === "login" && request.selection === undefined && request.confirmed === undefined) {
@@ -1215,7 +1215,7 @@ export class OwnedUiSessionShell {
1215
1215
  return { outcome: "completed", diagnostic: null };
1216
1216
  }
1217
1217
  if (request.command === "tree" && request.selection === undefined && request.confirmed === undefined && request.argument.trim().length === 0) {
1218
- this.showTreeSelector();
1218
+ await this.showTreeSelector();
1219
1219
  return { outcome: "completed", diagnostic: null };
1220
1220
  }
1221
1221
  if (request.command === "reload") {
@@ -1913,7 +1913,7 @@ export class OwnedUiSessionShell {
1913
1913
  "Summarize with custom prompt",
1914
1914
  ]);
1915
1915
  if (choice === undefined) {
1916
- this.showTreeSelector(entryId);
1916
+ await this.showTreeSelector(entryId);
1917
1917
  return;
1918
1918
  }
1919
1919
  summarize = choice !== "No summary";
@@ -1935,7 +1935,7 @@ export class OwnedUiSessionShell {
1935
1935
  },
1936
1936
  });
1937
1937
  if (result.diagnostic === "Branch summarization cancelled")
1938
- this.showTreeSelector(entryId);
1938
+ await this.showTreeSelector(entryId);
1939
1939
  }
1940
1940
  #startWorkflowLogin(request) {
1941
1941
  this.#finishWorkflowLogin();
@@ -10,7 +10,7 @@ export const STARTUP_DESCRIPTOR = Object.freeze({
10
10
  ],
11
11
  "generatedArtifact": {
12
12
  "path": "dist/integrations/pi/startup-public.js",
13
- "sha256": "8782a192051008e2d99edaa7abc2eb47bd37a8b8ebda1b7fbd62a74f990e6d48"
13
+ "sha256": "540d60a56c6f2934d243f81dce09bc91e191371bed154b7620d15d22a855697d"
14
14
  },
15
15
  "dependencyLayerIdentity": {
16
16
  "source": "A1_RELEASE_LAYERS",
@@ -19,7 +19,7 @@ export const STARTUP_DESCRIPTOR = Object.freeze({
19
19
  "compileCacheNamespace": {
20
20
  "strategy": "node-abi-version-and-ordered-layer-sha256-v1"
21
21
  },
22
- "identity": "24b9db93df1ea18ef3fc7f669a9f45587750eb50c6de2ed7f57541c26c42ff0e"
22
+ "identity": "a14fa5abdb33493d6a8d11fb1f2e62eff1ddbce083e997187d88531927ca1c24"
23
23
  });
24
24
 
25
25
  export function loadDeclaredStartupGraph() {
@@ -12,6 +12,8 @@ const SELECTED_TUNNEL_ROW = /^(→ skills:\S+)(\s{2,}.*)$/u;
12
12
  export const PINNED_PI_BUILTIN_SLASH_COMMANDS = [
13
13
  { name: "settings", description: "Open settings menu" },
14
14
  { name: "model", description: "Select model (opens selector UI)", argumentHint: "<provider/model>" },
15
+ { name: "tree", description: "Navigate session tree (switch branches)" },
16
+ { name: "thinking", description: "Set thinking level", argumentHint: "<level>" },
15
17
  { name: "scoped-models", description: "Enable/disable models for Ctrl+P cycling" },
16
18
  { name: "export", description: "Export session (HTML default, or specify path: .html/.jsonl)" },
17
19
  { name: "import", description: "Import and resume a session from a JSONL file" },
@@ -23,7 +25,6 @@ export const PINNED_PI_BUILTIN_SLASH_COMMANDS = [
23
25
  { name: "hotkeys", description: "Show all keyboard shortcuts" },
24
26
  { name: "fork", description: "Create a new fork from a previous user message" },
25
27
  { name: "clone", description: "Duplicate the current session at the current position" },
26
- { name: "tree", description: "Navigate session tree (switch branches)" },
27
28
  { name: "trust", description: "Save project trust decision for future sessions" },
28
29
  { name: "login", description: "Configure provider authentication", argumentHint: "<provider>" },
29
30
  { name: "logout", description: "Remove provider authentication" },
@@ -29,6 +29,25 @@ export interface PiShellSessionInfoPresentation {
29
29
  readonly cost: number;
30
30
  readonly tokens: number;
31
31
  }[];
32
+ readonly cacheWarming: PiShellCacheWarmingPresentation;
33
+ }
34
+ export interface PiShellCacheWarmingPresentation {
35
+ readonly mode: string;
36
+ readonly status?: {
37
+ readonly state: "inactive" | "scheduled" | "refreshing";
38
+ readonly reason?: string;
39
+ readonly nextWarmAt?: number;
40
+ readonly extensionOverride?: boolean;
41
+ readonly decision?: {
42
+ readonly phase: "streaming" | "idle";
43
+ readonly action: string;
44
+ readonly warmCost: number;
45
+ readonly missCost: number;
46
+ readonly continuationProbability: number;
47
+ readonly expectedSavings: number;
48
+ readonly economicsAvailable: boolean;
49
+ };
50
+ };
32
51
  }
33
52
  export declare function renderPiShellStatusText(message: string, width: number, outputPad?: 0 | 1): readonly string[];
34
53
  export interface PiShellCommandMessagePresentation {
@@ -23,9 +23,55 @@ export function renderPiShellCommandMessage(presentation, width, outputPad = PIN
23
23
  ...text.render(width),
24
24
  ];
25
25
  }
26
+ const CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS = 0.05;
27
+ function formatWarmingDollars(value) {
28
+ return value < 0 ? `-${Math.abs(value).toFixed(3)}` : `${value.toFixed(3)}`;
29
+ }
30
+ function formatWarmingEconomics(decision) {
31
+ if (!decision.economicsAvailable)
32
+ return "cache economics unavailable";
33
+ const probability = Math.round(decision.continuationProbability * 100);
34
+ const probabilityText = decision.phase === "streaming"
35
+ ? `${probability}% continuation probability while agent is running`
36
+ : `${probability}% continuation probability`;
37
+ const comparison = decision.action === "warm" ? ">=" : "<";
38
+ return `${probabilityText}, expected savings ${formatWarmingDollars(decision.expectedSavings)} ${comparison} ${CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS.toFixed(3)}`;
39
+ }
40
+ function formatWarmingDecisionTime(nextWarmAt, now) {
41
+ if (nextWarmAt === undefined || nextWarmAt <= now)
42
+ return "Decision now";
43
+ let remainingSeconds = Math.ceil((nextWarmAt - now) / 1000);
44
+ const hours = Math.floor(remainingSeconds / 3600);
45
+ remainingSeconds %= 3600;
46
+ const minutes = Math.floor(remainingSeconds / 60);
47
+ const seconds = remainingSeconds % 60;
48
+ const parts = [];
49
+ if (hours > 0)
50
+ parts.push(`${hours}h`);
51
+ if (minutes > 0)
52
+ parts.push(`${minutes}m`);
53
+ if (seconds > 0 || parts.length === 0)
54
+ parts.push(`${seconds}s`);
55
+ return `Decision in ${parts.join(" ")}`;
56
+ }
57
+ /** The one-line warming status the pinned session report shows; a decision is attached once warming acted. */
58
+ function formatCacheWarmingStatus(status, now = Date.now()) {
59
+ const decision = status.decision;
60
+ if (!decision || (status.state === "inactive" && !decision.economicsAvailable && !status.extensionOverride)) {
61
+ return `Inactive (${status.reason ?? "unknown reason"})`;
62
+ }
63
+ const details = status.extensionOverride
64
+ ? `extension override, ${formatWarmingEconomics(decision)}`
65
+ : `${formatWarmingEconomics(decision)} -> ${decision.action}`;
66
+ if (status.state === "inactive")
67
+ return `Stopped (${details})`;
68
+ if (status.state === "refreshing")
69
+ return `Warming cache (${details})`;
70
+ return `${formatWarmingDecisionTime(status.nextWarmAt, now)} (${details})`;
71
+ }
26
72
  export function createPiShellSessionInfo(presentation) {
27
73
  ensureTheme();
28
- const { stats, sessionName, cacheWaste, usageBreakdown } = presentation;
74
+ const { stats, sessionName, cacheWaste, usageBreakdown, cacheWarming } = presentation;
29
75
  let info = `${piTheme().bold("Session Info")}\n\n`;
30
76
  if (sessionName)
31
77
  info += `${piTheme().fg("dim", "Name:")} ${sessionName}\n`;
@@ -42,6 +88,14 @@ export function createPiShellSessionInfo(presentation) {
42
88
  info += ` ${piTheme().fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
43
89
  }
44
90
  info += `${piTheme().fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n${piTheme().fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
91
+ const warmingStatus = cacheWarming.status;
92
+ info += `\n${piTheme().bold("Cache Warming")}\n${piTheme().fg("dim", "Mode:")} ${cacheWarming.mode}\n`;
93
+ info += `${piTheme().fg("dim", "Status:")} ${warmingStatus ? formatCacheWarmingStatus(warmingStatus) : "Inactive (cache warming unavailable)"}\n`;
94
+ const warmingDecision = warmingStatus?.decision;
95
+ if (warmingDecision?.economicsAvailable) {
96
+ info += `${piTheme().fg("dim", "Cache miss penalty:")} $${warmingDecision.missCost.toFixed(3)}\n`;
97
+ info += `${piTheme().fg("dim", "Refresh cost:")} $${warmingDecision.warmCost.toFixed(3)}\n`;
98
+ }
45
99
  if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
46
100
  info += `\n${piTheme().bold("Cost")}\n${piTheme().fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
47
101
  if (usageBreakdown.length > 1)
@@ -124,7 +178,7 @@ function hotkeysMarkdown(bindings, getShortcuts, profile) {
124
178
  ? action === "app.model.select" ? "Unbound (`/models`)" : "Unbound"
125
179
  : `\`${label}\``;
126
180
  }).join(" / ")} | ${description} |`;
127
- let markdown = ["**Navigation**", "| Key | Action |", "|-----|--------|", row(["tui.editor.cursorUp", "tui.editor.cursorDown", "tui.editor.cursorLeft", "tui.editor.cursorRight"], "Move cursor / browse history"), row(["tui.editor.cursorWordLeft", "tui.editor.cursorWordRight"], "Move by word"), row(["tui.editor.cursorLineStart"], profile === "a1" ? "Start of prompt line" : "Start of line"), row(["tui.editor.cursorLineEnd"], profile === "a1" ? "End of prompt line" : "End of line"), ...(profile === "a1" ? ["| `Ctrl+Home` | Start of content |", "| `Ctrl+End` | End of content / follow output |"] : []), row(["tui.editor.jumpForward"], "Jump forward to character"), row(["tui.editor.jumpBackward"], "Jump backward to character"), row(["tui.editor.pageUp", "tui.editor.pageDown"], "Scroll by page"), "", "**Editing**", "| Key | Action |", "|-----|--------|", row(["tui.input.submit"], "Send message"), row(["tui.input.newLine"], `New line${process.platform === "win32" ? " (Ctrl+Enter on Windows Terminal)" : ""}`), row(["tui.editor.deleteWordBackward"], "Delete word backwards"), row(["tui.editor.deleteWordForward"], "Delete word forwards"), row(["tui.editor.deleteToLineStart"], "Delete to start of line"), row(["tui.editor.deleteToLineEnd"], "Delete to end of line"), row(["tui.editor.yank"], "Paste the most-recently-deleted text"), row(["tui.editor.yankPop"], "Cycle through the deleted text after pasting"), row(["tui.editor.undo"], "Undo"), "", "**Other**", "| Key | Action |", "|-----|--------|", row(["tui.input.tab"], "Path completion / accept autocomplete"), row(["app.interrupt"], "Cancel autocomplete / abort streaming"), row(["app.clear"], "Clear editor (first) / exit (second)"), row(["app.exit"], "Exit (when editor is empty)"), row(["app.suspend"], "Suspend to background"), row(["app.thinking.cycle"], "Cycle thinking level"), row(["app.model.cycleForward", "app.model.cycleBackward"], "Cycle models"), row(["app.model.select"], profile === "a1" ? "Open the Models dialog" : "Open model selector"), row(["app.tools.expand"], "Toggle tool output expansion"), row(["app.thinking.toggle"], "Toggle thinking block visibility"), row(["app.editor.external"], "Edit message in external editor"), row(["app.message.copy"], "Copy last assistant message"), row(["app.message.followUp"], "Queue follow-up message"), row(["app.message.dequeue"], "Restore queued messages"), row(["app.clipboard.pasteImage"], "Paste image or text from clipboard"), "| `/` | Slash commands |", "| `!` | Run bash command |", "| `!!` | Run bash command (excluded from context) |", ...(profile === "a1" ? ["", "**Models dialog**", "| Key | Action |", "|-----|--------|", "| `Space` | Toggle the selected model in the cycling scope |", "| `Tab` | Switch the all/scoped filter |", row(["app.models.save"], "Save the scope to settings"), row(["app.models.enableAll"], "Scope every listed model"), row(["app.models.clearAll"], "Clear the listed models from the scope"), row(["app.models.toggleProvider"], "Toggle the selected model's provider"), row(["app.models.reorderUp", "app.models.reorderDown"], "Reorder the cycling scope")] : [])].join("\n");
181
+ let markdown = ["**Navigation**", "| Key | Action |", "|-----|--------|", row(["tui.editor.cursorUp", "tui.editor.cursorDown", "tui.editor.cursorLeft", "tui.editor.cursorRight"], "Move cursor / browse history"), row(["tui.editor.cursorWordLeft", "tui.editor.cursorWordRight"], "Move by word"), row(["tui.editor.cursorLineStart"], profile === "a1" ? "Start of prompt line" : "Start of line"), row(["tui.editor.cursorLineEnd"], profile === "a1" ? "End of prompt line" : "End of line"), ...(profile === "a1" ? ["| `Ctrl+Home` | Start of content |", "| `Ctrl+End` | End of content / follow output |"] : []), row(["tui.editor.jumpForward"], "Jump forward to character"), row(["tui.editor.jumpBackward"], "Jump backward to character"), row(["tui.editor.pageUp", "tui.editor.pageDown"], "Scroll by page"), "", "**Editing**", "| Key | Action |", "|-----|--------|", row(["tui.input.submit"], "Send message"), row(["tui.input.newLine"], `New line${process.platform === "win32" ? " (Ctrl+Enter on Windows Terminal)" : ""}`), row(["tui.editor.deleteWordBackward"], "Delete word backwards"), row(["tui.editor.deleteWordForward"], "Delete word forwards"), row(["tui.editor.deleteToLineStart"], "Delete to start of line"), row(["tui.editor.deleteToLineEnd"], "Delete to end of line"), row(["tui.editor.yank"], "Paste the most-recently-deleted text"), row(["tui.editor.yankPop"], "Cycle through the deleted text after pasting"), row(["tui.editor.undo"], "Undo"), "", "**Other**", "| Key | Action |", "|-----|--------|", row(["tui.input.tab"], "Path completion / accept autocomplete"), row(["app.interrupt"], "Cancel autocomplete / abort streaming"), row(["app.clear"], "Clear editor (first) / exit (second)"), row(["app.exit"], "Exit (when editor is empty)"), row(["app.suspend"], "Suspend to background"), row(["app.thinking.cycle"], "Cycle thinking level"), row(["app.model.cycleForward", "app.model.cycleBackward"], "Cycle models"), row(["app.model.select"], profile === "a1" ? "Open the Models dialog" : "Open model selector"), row(["app.tools.expand"], "Toggle tool output expansion"), row(["app.thinking.toggle"], "Toggle thinking block visibility"), row(["app.editor.external"], "Edit message in external editor"), row(["app.message.copy"], "Copy selection or last assistant message"), row(["app.message.followUp"], "Queue follow-up message"), row(["app.message.dequeue"], "Restore queued messages"), row(["app.clipboard.pasteImage"], "Paste image or text from clipboard"), "| `/` | Slash commands |", "| `!` | Run bash command |", "| `!!` | Run bash command (excluded from context) |", ...(profile === "a1" ? ["", "**Models dialog**", "| Key | Action |", "|-----|--------|", "| `Space` | Toggle the selected model in the cycling scope |", "| `Tab` | Switch the all/scoped filter |", row(["app.models.save"], "Save the scope to settings"), row(["app.models.enableAll"], "Scope every listed model"), row(["app.models.clearAll"], "Clear the listed models from the scope"), row(["app.models.toggleProvider"], "Toggle the selected model's provider"), row(["app.models.reorderUp", "app.models.reorderDown"], "Reorder the cycling scope")] : [])].join("\n");
128
182
  const shortcuts = getShortcuts(bindings ?? keys.getEffectiveConfig());
129
183
  if (shortcuts.length > 0) {
130
184
  markdown += "\n\n**Extensions**\n| Key | Action |\n|-----|--------|\n";
@@ -67,16 +67,18 @@ export declare function createPiShellTrustSelector(options: {
67
67
  }) => void;
68
68
  readonly onCancel: () => void;
69
69
  }): PiShellComponentPort;
70
+ /** Mirrors the pinned session manager's progress callback, including its partial results. */
71
+ type SessionListProgress = (loaded: number, total: number, partialSessions?: readonly SessionInfo[]) => void;
70
72
  export declare function createPiShellSessionSelector(options: {
71
- readonly currentSessionsLoader: (onProgress?: (loaded: number, total: number) => void) => Promise<SessionInfo[]>;
72
- readonly allSessionsLoader: (onProgress?: (loaded: number, total: number) => void) => Promise<SessionInfo[]>;
73
+ readonly currentSessionsLoader: (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;
74
+ readonly allSessionsLoader: (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;
73
75
  readonly onSelect: (path: string) => void;
74
76
  readonly onCancel: () => void;
75
77
  readonly onExit: () => void;
76
78
  readonly requestRender: () => void;
77
79
  readonly renameSession: (sessionFilePath: string, nextName: string | undefined) => Promise<void>;
78
80
  readonly currentSessionFilePath: string | undefined;
79
- }): PiShellComponentPort;
81
+ }): Promise<PiShellComponentPort>;
80
82
  export declare function createPiShellTreeSelector(options: {
81
83
  readonly tree: readonly unknown[];
82
84
  readonly currentLeafId: string | null;
@@ -87,7 +89,7 @@ export declare function createPiShellTreeSelector(options: {
87
89
  readonly onCopy?: (text: string | undefined) => void;
88
90
  readonly initialSelectedId?: string;
89
91
  readonly initialFilterMode?: "default" | "no-tools" | "user-only" | "labeled-only" | "all";
90
- }): PiShellComponentPort;
92
+ }): Promise<PiShellComponentPort>;
91
93
  export declare function createPiShellUserMessageSelector(messages: readonly PiShellSelectorOption[], onSelect: (id: string) => void, onCancel: () => void, initialSelectedId?: string): PiShellComponentPort;
92
94
  export interface PiShellLoginDialogPort extends PiShellComponentPort {
93
95
  showAuth(url: string, instructions?: string): void;
@@ -1,8 +1,6 @@
1
1
  import { ArminComponent, BorderedLoader, DynamicBorder, ExtensionSelectorComponent, getSelectListTheme, LoginDialogComponent, ModelSelectorComponent, OAuthSelectorComponent, SettingsSelectorComponent, ShowImagesSelectorComponent, ThemeSelectorComponent, ThinkingSelectorComponent, UserMessageSelectorComponent, } from "../startup-public.js";
2
2
  import { DaxnutsComponent, } from "./upstream/components/daxnuts.js";
3
3
  import { EarendilAnnouncementComponent, } from "./upstream/components/earendil-announcement.js";
4
- import { SessionSelectorComponent, } from "./upstream/components/session-selector.js";
5
- import { TreeSelectorComponent, } from "./upstream/components/tree-selector.js";
6
4
  import { Box, Container, SelectList, Spacer, Text, } from "@earendil-works/pi-tui";
7
5
  import { ScopedModelsSelectorComponent, } from "./upstream/components/scoped-models-selector.js";
8
6
  import { ModelsDialogComponent, } from "./models-dialog.js";
@@ -40,6 +38,7 @@ export function createPiShellSettingsSelector(options) {
40
38
  onFollowUpModeChange: change("onFollowUpModeChange"),
41
39
  onTransportChange: change("onTransportChange"),
42
40
  onHttpIdleTimeoutMsChange: change("onHttpIdleTimeoutMsChange"),
41
+ onCacheWarmingModeChange: change("onCacheWarmingModeChange"),
43
42
  onModelThinkingLevelChange: change("onModelThinkingLevelChange"),
44
43
  onModelThinkingLevelRemove: change("onModelThinkingLevelRemove"),
45
44
  onThemeChange: change("onThemeChange"),
@@ -120,13 +119,15 @@ export function createPiShellTrustSelector(options) {
120
119
  ensureTheme();
121
120
  return componentPort(new TrustSelectorComponent(options));
122
121
  }
123
- export function createPiShellSessionSelector(options) {
122
+ export async function createPiShellSessionSelector(options) {
124
123
  ensureTheme();
124
+ const { SessionSelectorComponent } = await import("./upstream/components/session-selector.js");
125
125
  const selector = new SessionSelectorComponent(options.currentSessionsLoader, options.allSessionsLoader, options.onSelect, options.onCancel, options.onExit, options.requestRender, { renameSession: options.renameSession, showRenameHint: true }, options.currentSessionFilePath);
126
126
  return componentPort(selector);
127
127
  }
128
- export function createPiShellTreeSelector(options) {
128
+ export async function createPiShellTreeSelector(options) {
129
129
  ensureTheme();
130
+ const { TreeSelectorComponent } = await import("./upstream/components/tree-selector.js");
130
131
  const selector = new TreeSelectorComponent([...options.tree], options.currentLeafId, options.terminalHeight, options.onSelect, options.onCancel, options.onLabelChange, options.initialSelectedId, options.initialFilterMode);
131
132
  if (options.onCopy)
132
133
  selector.onCopy = options.onCopy;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/core/keybindings.ts.
4
4
  * Modifications: Mechanical source port with Node import prefixes, public package-root agent-directory
5
5
  * resolution, and an opt-in bare-A1 input profile including Ctrl+L level cycling and unbound model
@@ -136,7 +136,7 @@ export declare const KEYBINDINGS: {
136
136
  };
137
137
  readonly "app.message.copy": {
138
138
  readonly defaultKeys: "ctrl+x";
139
- readonly description: "Copy message to clipboard";
139
+ readonly description: "Copy selection or last assistant message";
140
140
  };
141
141
  readonly "app.message.followUp": {
142
142
  readonly defaultKeys: "ctrl+q" | "alt+enter";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/core/keybindings.ts.
4
4
  * Modifications: Mechanical source port with Node import prefixes, public package-root agent-directory
5
5
  * resolution, and an opt-in bare-A1 input profile including Ctrl+L level cycling and unbound model
@@ -72,7 +72,7 @@ export const KEYBINDINGS = {
72
72
  },
73
73
  "app.message.copy": {
74
74
  defaultKeys: "ctrl+x",
75
- description: "Copy message to clipboard",
75
+ description: "Copy selection or last assistant message",
76
76
  },
77
77
  "app.message.followUp": {
78
78
  defaultKeys: windowsKeybindings ? "ctrl+q" : "alt+enter",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "sourcePackage": "@earendil-works/pi-coding-agent",
3
- "sourceVersion": "0.85.1",
3
+ "sourceVersion": "0.86.1",
4
4
  "upstreamRepository": "https://github.com/earendil-works/pi.git",
5
- "upstreamCommit": "d981de1229ef899957bbe968bc8dcda02a21f477",
5
+ "upstreamCommit": "13cbf77df2396303013a41646bcfa77b4271ae56",
6
6
  "sourcePath": "dist/modes/interactive/assets/clankolas.png",
7
7
  "sourceSha256": "169acd0dfe6fbb8d8742ed24a3fc654fd0b2e2d4223c733249c5493723f1b72d",
8
8
  "license": "MIT",
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/modes/interactive/components/countdown-timer.ts.
4
4
  * Modifications: Mechanical source port with ECMAScript private fields; imports remain on the public
5
5
  * Pi TUI package root.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/modes/interactive/components/daxnuts.ts.
4
4
  * Modifications: Mechanical pinned source port with private imports remapped to public package-root
5
5
  * types/APIs and A1-owned theme boundaries; behavior remains acceptance-tested.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/modes/interactive/components/daxnuts.ts.
4
4
  * Modifications: Mechanical pinned source port with private imports remapped to public package-root
5
5
  * types/APIs and A1-owned theme boundaries; behavior remains acceptance-tested.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/modes/interactive/components/earendil-announcement.ts.
4
4
  * Modifications: Mechanical pinned source port with private imports remapped to public package-root
5
5
  * types/APIs and A1-owned theme boundaries. The unchanged image is loaded lazily from its attributed,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/modes/interactive/components/extension-editor.ts.
4
4
  * Modifications: Mechanical port: remap pi-tui to the root public singleton, use owned
5
5
  * keybindings/theme and external-editor seams, preserve editor layout, hints, focus, submission,
@@ -15,6 +15,7 @@ export declare class ExtensionEditorComponent extends Container {
15
15
  constructor(tui: TUI, keybindings: KeybindingsManager, title: string, prefill: string | undefined, onSubmit: (value: string) => void, onCancel: () => void, options?: {
16
16
  readonly paddingX?: number;
17
17
  readonly autocompleteMaxVisible?: number;
18
+ readonly description?: string;
18
19
  }, externalEditorCommand?: string);
19
20
  handleInput(data: string): void;
20
21
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/modes/interactive/components/extension-editor.ts.
4
4
  * Modifications: Mechanical port: remap pi-tui to the root public singleton, use owned
5
5
  * keybindings/theme and external-editor seams, preserve editor layout, hints, focus, submission,
@@ -36,14 +36,19 @@ export class ExtensionEditorComponent extends Container {
36
36
  || process.env.VISUAL
37
37
  || process.env.EDITOR
38
38
  || (process.platform === "win32" ? "notepad" : "nano");
39
+ const { description, ...editorOptions } = options ?? {};
39
40
  this.addChild(new DynamicBorder());
40
41
  this.addChild(new Spacer(1));
41
42
  this.addChild(new Text(piTheme().fg("accent", title), 1, 0));
43
+ if (description) {
44
+ this.addChild(new Spacer(1));
45
+ this.addChild(new Text(piTheme().fg("text", description), 1, 0));
46
+ }
42
47
  this.addChild(new Spacer(1));
43
48
  this.#editor = new Editor(tui, {
44
49
  borderColor: text => piTheme().fg("borderMuted", text),
45
50
  selectList: getSelectListTheme(),
46
- }, options);
51
+ }, editorOptions);
47
52
  if (prefill)
48
53
  this.#editor.setText(prefill);
49
54
  this.#editor.onSubmit = onSubmit;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/modes/interactive/components/mermaid.ts.
4
4
  * Modifications: Mechanical pinned source port with private imports remapped to public package-root
5
5
  * types/APIs and A1-owned theme boundaries; behavior remains acceptance-tested.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/modes/interactive/components/custom-editor.ts.
4
4
  * Modifications: A1-owned class name and synchronized A1 keybinding contract replace the nominal
5
5
  * private upstream keybinding constructor dependency; bare A1 injects the shared Settings/agent input
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 0.85.1 (MIT), commit d981de1229ef899957bbe968bc8dcda02a21f477,
2
+ * Provenance: @earendil-works/pi-coding-agent 0.86.1 (MIT), commit 13cbf77df2396303013a41646bcfa77b4271ae56,
3
3
  * packages/coding-agent/src/modes/interactive/components/custom-editor.ts.
4
4
  * Modifications: A1-owned class name and synchronized A1 keybinding contract replace the nominal
5
5
  * private upstream keybinding constructor dependency; bare A1 injects the shared Settings/agent input