@timurproko/a1 0.2.7-dev.1226 → 0.2.7-dev.1230

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 (27) hide show
  1. package/README.md +1 -1
  2. package/dist/app/session-shell/dock-chrome.d.ts +1 -0
  3. package/dist/app/session-shell/dock-chrome.js +9 -1
  4. package/dist/app/session-shell/shell-layout.d.ts +1 -1
  5. package/dist/app/session-shell/viewport-layout.js +6 -5
  6. package/dist/composition/owned-settings.js +9 -7
  7. package/dist/foundation/release/update.js +3 -1
  8. package/dist/integrations/pi/components/shell-footer-status.js +7 -8
  9. package/dist/integrations/pi/components/shell-shared-facade.d.ts +3 -0
  10. package/dist/integrations/pi/components/shell-shared-facade.js +9 -1
  11. package/dist/native/darwin-arm64/manifest.json +1 -1
  12. package/dist/native/darwin-arm64/terminal-host.manifest.json +2 -2
  13. package/dist/native/darwin-arm64/terminal-host.node +0 -0
  14. package/dist/native/darwin-x64/manifest.json +1 -1
  15. package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
  16. package/dist/native/darwin-x64/terminal-host.node +0 -0
  17. package/dist/native/linux-x64/manifest.json +1 -1
  18. package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
  19. package/dist/native/linux-x64/terminal-host.node +0 -0
  20. package/dist/native/win32-x64/manifest.json +2 -2
  21. package/dist/native/win32-x64/process-guardian.node +0 -0
  22. package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
  23. package/dist/native/win32-x64/terminal-host.node +0 -0
  24. package/dist/runtime-payload-inventory.json +1225 -1196
  25. package/dist/ui/components/selection-copy.js +1 -1
  26. package/docs/architecture/toolchain.md +1 -1
  27. package/package.json +4 -4
package/README.md CHANGED
@@ -149,7 +149,7 @@ npm x -y -- @timurproko/a1-install
149
149
 
150
150
  The **Update** setting controls release discovery:
151
151
 
152
- - **Auto** (default) checks the running release's stable or development channel at startup and every 15 minutes while open. It silently installs a verified update, then shows `Update installed · Restart to update`; existing sessions keep running until restarted.
152
+ - **Auto** (default) checks the running release's stable or development channel at startup and every 15 minutes while open. It silently installs a verified update, then shows `Update installed, restart to update` above the editor; existing sessions keep running until restarted.
153
153
  - **Notify** checks at startup (at most daily), keeps the `Update Available` notice, and leaves installation manual.
154
154
  - **No** performs no update check; updates remain available through the commands above.
155
155
 
@@ -29,6 +29,7 @@ export declare class DockChrome {
29
29
  showCopyAcknowledgement(message: string): void;
30
30
  clearCopyAcknowledgement(requestRender: boolean): void;
31
31
  renderCopyAcknowledgement(width: number): string | undefined;
32
+ renderPromptOverlay(diagnostics: OwnedUiSessionViewModel["diagnostics"], width: number): string | undefined;
32
33
  renderReleaseBanner(diagnostics: OwnedUiSessionViewModel["diagnostics"], width: number): PiShellReleaseUpdateBanner | undefined;
33
34
  locateReleaseClose(frame: TranscriptViewportFrame, banner: PiShellReleaseUpdateBanner | undefined, tailEnd: number, tailLength: number): void;
34
35
  }
@@ -1,7 +1,7 @@
1
1
  import { COPY_ACKNOWLEDGEMENT_DURATION_MS } from "../../ui/components/selection-copy.js";
2
2
  import { renderPiShellCommandMessage, renderPiShellReleaseUpdateBanner, renderPiShellStatusText, } from "../../integrations/pi/components/shell-presenters-info.js";
3
3
  import { PINNED_PI_LAYOUT, piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
4
- import { piShellTruncateToWidth } from "../../integrations/pi/components/shell-shared-facade.js";
4
+ import { piShellTruncateToWidth, renderPiShellInstalledUpdateStatus } from "../../integrations/pi/components/shell-shared-facade.js";
5
5
  import { parseReleaseUpdateDiagnostic } from "./transcript-document.js";
6
6
  /**
7
7
  * The transient chrome around bare A1's dock: the one command notice above the editor, the release
@@ -80,6 +80,14 @@ export class DockChrome {
80
80
  return undefined;
81
81
  return piTheme().fg("accent", piShellTruncateToWidth(this.#copyAcknowledgement, width));
82
82
  }
83
+ renderPromptOverlay(diagnostics, width) {
84
+ const acknowledgement = this.renderCopyAcknowledgement(width);
85
+ if (acknowledgement !== undefined)
86
+ return acknowledgement;
87
+ if (!diagnostics.some(diagnostic => diagnostic.code === "release-update-installed"))
88
+ return undefined;
89
+ return renderPiShellInstalledUpdateStatus(width) || undefined;
90
+ }
83
91
  renderReleaseBanner(diagnostics, width) {
84
92
  if (this.#releaseDismissed)
85
93
  return undefined;
@@ -22,7 +22,7 @@ export interface ShellLayoutPorts {
22
22
  readonly input: InputSurfaceSwitch;
23
23
  readonly editor: Pick<PiShellEditorPort, "getText">;
24
24
  readonly promptChips: Pick<PromptChipStore, "atomicRanges">;
25
- readonly dockChrome: Pick<DockChrome, "renderCopyAcknowledgement" | "renderReleaseBanner" | "locateReleaseClose">;
25
+ readonly dockChrome: Pick<DockChrome, "renderPromptOverlay" | "renderReleaseBanner" | "locateReleaseClose">;
26
26
  readonly theme: TranscriptViewportTheme;
27
27
  readonly onFrame?: (frame: TranscriptViewportFrame) => void;
28
28
  rows(): number;
@@ -24,7 +24,8 @@ export class ViewportLayout {
24
24
  const { viewport, input, dockChrome } = this.#ports;
25
25
  const height = Math.max(0, this.#ports.rows());
26
26
  const dock = this.#ports.dock(width);
27
- const copyAcknowledgement = dockChrome.renderCopyAcknowledgement(width);
27
+ const diagnostics = this.#ports.diagnostics();
28
+ const promptOverlay = dockChrome.renderPromptOverlay(diagnostics, width);
28
29
  // Invariant: auto/always own one stable final-column gutter. Every scrollable
29
30
  // surface ends before it; the dock remains full-width and hidden mode returns it.
30
31
  const documentWidth = viewport.config.scrollbarAppearance === "hidden"
@@ -32,7 +33,7 @@ export class ViewportLayout {
32
33
  : Math.max(1, width - 1);
33
34
  const document = this.#ports.document(documentWidth);
34
35
  const steeringRows = this.#ports.queued(documentWidth);
35
- const releaseBanner = dockChrome.renderReleaseBanner(this.#ports.diagnostics(), documentWidth);
36
+ const releaseBanner = dockChrome.renderReleaseBanner(diagnostics, documentWidth);
36
37
  // Rationale: the release notice rides the bottom-aligned tail directly above Working, so it
37
38
  // never displaces transcript content and scrolls away with the live status.
38
39
  // Invariant: when idle the banner's last row sits on the line Working would occupy.
@@ -41,7 +42,7 @@ export class ViewportLayout {
41
42
  const snapshot = this.#snapshot;
42
43
  // Invariant: paint-only feedback may cover either viewport or dock cells, so
43
44
  // ordinary dock-only reuse cannot safely omit its overlay composition.
44
- const dockInputCandidate = input.dockInputCandidate && copyAcknowledgement === undefined;
45
+ const dockInputCandidate = input.dockInputCandidate && promptOverlay === undefined;
45
46
  // Concurrency: input may change after a keyboard receipt but before its paint.
46
47
  // Capture only the live inputs this composition will actually represent.
47
48
  const inputSurface = input.surface;
@@ -87,10 +88,10 @@ export class ViewportLayout {
87
88
  // Invariant: the control belongs immediately above the complete dock and
88
89
  // floats over transient viewport content rather than consuming a dock row.
89
90
  bottomControlRow: Math.max(0, height - Math.min(height, dockRows.length) - 1),
90
- ...(copyAcknowledgement === undefined || height <= 0 ? {} : {
91
+ ...(promptOverlay === undefined || height <= 0 ? {} : {
91
92
  frameOverlay: {
92
93
  row: Math.max(1, Math.min(height, dockStartRow + dock.inputOffset - 1)),
93
- text: copyAcknowledgement,
94
+ text: promptOverlay,
94
95
  },
95
96
  }),
96
97
  theme: this.#ports.theme,
@@ -1,4 +1,4 @@
1
- import { unwatchFile, watchFile } from "node:fs";
1
+ import { statSync } from "node:fs";
2
2
  import { resolveLaunchProfilePaths } from "../features/launch/profile-paths.js";
3
3
  import { resolveProductPaths } from "../foundation/lifecycle/paths.js";
4
4
  import { PRODUCT_IDENTITY } from "../product-identity.js";
@@ -19,18 +19,20 @@ export function createOwnedSettingsManager(options) {
19
19
  agentSettingLabelOverrides: { fullscreenCopyOnSelect: "Copy on select" },
20
20
  });
21
21
  }
22
- const SHARED_SETTINGS_POLL_MS = 250;
23
22
  /** Rereads the shared settings document whenever its stat changes; returns the stop. */
24
23
  export function watchSharedSettings(settings) {
25
- const file = settings.file;
26
- const listener = () => {
24
+ let last = "";
25
+ const poll = () => {
27
26
  try {
28
- settings.refresh();
27
+ const s = statSync(settings.file);
28
+ if (last !== (last = `${s.ino}:${s.mtimeMs}`))
29
+ settings.refresh();
29
30
  }
30
31
  catch {
31
32
  // Compatibility: an unreadable peer write resolves on the next stat change.
32
33
  }
33
34
  };
34
- watchFile(file, { interval: SHARED_SETTINGS_POLL_MS, persistent: false }, listener);
35
- return () => unwatchFile(file, listener);
35
+ poll();
36
+ const timer = setInterval(poll, 250).unref();
37
+ return () => clearInterval(timer);
36
38
  }
@@ -67,7 +67,9 @@ export function createNpmProcessRunner(platform = process.platform) {
67
67
  // Invariant: no child of the updater shares the terminal. The progress bar is the only
68
68
  // live output; a child's own text is kept, bounded, and shown with a failure or not at all.
69
69
  const stdio = ["ignore", request.captureStdout ? "pipe" : "ignore", "pipe"];
70
- const child = platform === "win32" ? crossSpawn(command, [...arguments_], { stdio }) : spawn(command, [...arguments_], { stdio });
70
+ const child = platform === "win32"
71
+ ? crossSpawn(command, [...arguments_], { stdio, windowsHide: true })
72
+ : spawn(command, [...arguments_], { stdio });
71
73
  const stdout = [];
72
74
  let stderr = "";
73
75
  child.stdout?.on("data", chunk => stdout.push(Buffer.from(chunk)));
@@ -7,7 +7,7 @@ import { KeybindingsManager } from "./upstream/adjacent/core/keybindings.js";
7
7
  import { StatusIndicator, WorkingStatusIndicator } from "./upstream/components/status-indicator.js";
8
8
  import { protectPiPromptChipPresentation } from "./prompt-chip-presentation.js";
9
9
  import { PINNED_PI_LAYOUT, piTheme, } from "./theme.js";
10
- import { createTuiFacade, ensureTheme, piShellTruncateToWidth, piShellVisibleWidth, } from "./shell-shared-facade.js";
10
+ import { createTuiFacade, ensureTheme, renderPiShellInstalledUpdateStatus, piShellVisibleWidth, } from "./shell-shared-facade.js";
11
11
  export function createPiShellHeader(options = {}) {
12
12
  ensureTheme();
13
13
  let expanded = options.expanded ?? false;
@@ -107,9 +107,9 @@ export function createPiShellStatus(view, progressStatus, runtime) {
107
107
  component = statusComponent(view, statusUi, outputPad, liveStatusText, placement, progressPresentation, progressStatus);
108
108
  };
109
109
  return {
110
- render: width => appendInstalledUpdateStatus(component?.render(width) ?? [], width, view),
110
+ render: width => appendInstalledUpdateStatus(component?.render(width) ?? [], width, view, progressPresentation),
111
111
  renderDock: width => placement === "dock" ? component?.render(width) ?? [] : [],
112
- renderLive: width => appendInstalledUpdateStatus(placement === "live" ? component?.render(width) ?? [] : [], width, view),
112
+ renderLive: width => appendInstalledUpdateStatus(placement === "live" ? component?.render(width) ?? [] : [], width, view, progressPresentation),
113
113
  placement: () => placement,
114
114
  invalidate: () => component?.invalidate(),
115
115
  update(next) {
@@ -228,12 +228,11 @@ function statusSignature(view, workingOverride, outputPad, placement, progressPr
228
228
  const message = withMessage ? `${workingOverride ?? ""}\u0000${view.status.workingMessage ?? ""}\u0000${view.status.workingProgress ?? ""}` : "";
229
229
  return `${placement}\u0000${outputPad}\u0000${view.lifecycle}\u0000${progressPresentation}\u0000${message}\u0000${view.status.diagnostics.at(-1) ?? ""}`;
230
230
  }
231
- function appendInstalledUpdateStatus(rows, width, view) {
232
- if (width <= 0 || !view.diagnostics.some(diagnostic => diagnostic.code === "release-update-installed"))
231
+ function appendInstalledUpdateStatus(rows, width, view, progressPresentation) {
232
+ if (progressPresentation === "custom-viewport" || width <= 0
233
+ || !view.diagnostics.some(diagnostic => diagnostic.code === "release-update-installed"))
233
234
  return rows;
234
- const theme = piTheme();
235
- const full = `${theme.fg("success", "Update installed")} ${theme.fg("muted", "·")} ${theme.fg("accent", "Restart to update")}`;
236
- const status = piShellTruncateToWidth(full, width);
235
+ const status = renderPiShellInstalledUpdateStatus(width);
237
236
  const statusWidth = piShellVisibleWidth(status);
238
237
  const target = rows.findLastIndex(row => piShellVisibleWidth(row.trimEnd()) > 0);
239
238
  if (target < 0)
@@ -8,6 +8,9 @@ import { KeybindingsManager } from "./upstream/adjacent/core/keybindings.js";
8
8
  /** Terminal-cell width authority used by Pi-rendered component rows. */
9
9
  export declare const piShellVisibleWidth: typeof visibleWidth;
10
10
  export declare const piShellTruncateToWidth: (text: string, width: number) => string;
11
+ export declare const INSTALLED_UPDATE_STATUS_TEXT = "Update installed, restart to update";
12
+ /** Shared green restart notice for the pinned status and bare-A1 prompt overlay. */
13
+ export declare function renderPiShellInstalledUpdateStatus(width: number): string;
11
14
  /** A clickable URL in pinned Pi's grammar: an OSC 8 link where the terminal supports one, the plain URL otherwise. */
12
15
  export declare const piShellHyperlink: (url: string, text?: string) => string;
13
16
  export interface PiShellComponentPort extends PresentationComponentPort {
@@ -1,9 +1,17 @@
1
1
  import { getKeybindings, hyperlink, matchesKey, setKeybindings, visibleWidth, truncateToWidth, } from "@earendil-works/pi-tui";
2
2
  import { KeybindingsManager, } from "./upstream/adjacent/core/keybindings.js";
3
- import { ensurePiTheme, } from "./theme.js";
3
+ import { ensurePiTheme, piTheme, } from "./theme.js";
4
4
  /** Terminal-cell width authority used by Pi-rendered component rows. */
5
5
  export const piShellVisibleWidth = visibleWidth;
6
6
  export const piShellTruncateToWidth = (text, width) => truncateToWidth(text, width, "");
7
+ export const INSTALLED_UPDATE_STATUS_TEXT = "Update installed, restart to update";
8
+ /** Shared green restart notice for the pinned status and bare-A1 prompt overlay. */
9
+ export function renderPiShellInstalledUpdateStatus(width) {
10
+ if (width <= 0)
11
+ return "";
12
+ ensurePiTheme();
13
+ return piShellTruncateToWidth(piTheme().fg("success", INSTALLED_UPDATE_STATUS_TEXT), width);
14
+ }
7
15
  /** A clickable URL in pinned Pi's grammar: an OSC 8 link where the terminal supports one, the plain URL otherwise. */
8
16
  export const piShellHyperlink = (url, text = url) => hyperlink(url, text);
9
17
  // Provenance: pinned from packages/coding-agent/src/core/slash-commands.ts at 914cf14.
@@ -7,7 +7,7 @@
7
7
  "platform": "darwin",
8
8
  "architecture": "arm64",
9
9
  "capability": "supported",
10
- "builtAt": "2026-10-29T18:55:24.681Z",
10
+ "builtAt": "2026-10-31T17:04:19.753Z",
11
11
  "artifact": {
12
12
  "filename": "process-guardian.node",
13
13
  "sha256": "a87eaaffcd986b624c8b044b756446cc1bdaf4334a1775b97820542fe34f9fb7",
@@ -9,10 +9,10 @@
9
9
  "architecture": "arm64",
10
10
  "target": "aarch64-apple-darwin",
11
11
  "capability": "supported",
12
- "builtAt": "2026-10-29T18:58:27.392Z",
12
+ "builtAt": "2026-10-31T17:06:07.880Z",
13
13
  "artifact": {
14
14
  "filename": "terminal-host.node",
15
- "sha256": "4c5b6471dd48f1f571c226022b01038dbba09798880ead564bd174617e60fc00",
15
+ "sha256": "4e35835f3af4c0d9ae9582886f3a1f66d8a8bd306014d24af29e979ca504aed6",
16
16
  "size": 6019520
17
17
  },
18
18
  "entry": {
@@ -7,7 +7,7 @@
7
7
  "platform": "darwin",
8
8
  "architecture": "x64",
9
9
  "capability": "supported",
10
- "builtAt": "2026-10-29T18:55:32.496Z",
10
+ "builtAt": "2026-10-31T17:04:33.467Z",
11
11
  "artifact": {
12
12
  "filename": "process-guardian.node",
13
13
  "sha256": "783a65f0de287a1c02cd5429dbe97bc8633f4cc8a7b92e3e961180b9bdcff814",
@@ -9,11 +9,11 @@
9
9
  "architecture": "x64",
10
10
  "target": "x86_64-apple-darwin",
11
11
  "capability": "supported",
12
- "builtAt": "2026-10-29T19:00:47.347Z",
12
+ "builtAt": "2026-10-31T17:07:58.103Z",
13
13
  "artifact": {
14
14
  "filename": "terminal-host.node",
15
- "sha256": "c9b2b998c06bb582db4b90639b8dbacdc698ef6c4b0361a2a0d19fbe9adfadbf",
16
- "size": 6562328
15
+ "sha256": "7161d3bde5cf9d1caf2978fe623b6d26dbdc257093a48b2870d510804563a1b3",
16
+ "size": 6566416
17
17
  },
18
18
  "entry": {
19
19
  "filename": "dist/foundation/resident-tabs/host-entry.js",
@@ -7,7 +7,7 @@
7
7
  "platform": "linux",
8
8
  "architecture": "x64",
9
9
  "capability": "supported",
10
- "builtAt": "2026-10-29T18:55:03.862Z",
10
+ "builtAt": "2026-10-31T17:03:56.410Z",
11
11
  "artifact": {
12
12
  "filename": "process-guardian.node",
13
13
  "sha256": "118e5954e3864672bd8482ab7edf419cb27dcdf2533720316979b7f5cc5a53a5",
@@ -9,11 +9,11 @@
9
9
  "architecture": "x64",
10
10
  "target": "x86_64-unknown-linux-gnu",
11
11
  "capability": "supported",
12
- "builtAt": "2026-10-29T18:58:26.007Z",
12
+ "builtAt": "2026-10-31T17:06:59.851Z",
13
13
  "artifact": {
14
14
  "filename": "terminal-host.node",
15
- "sha256": "5ab7264cbbd505e2455b05d11b2ca2a8378d007f20e0730e25cb84a6e98096cf",
16
- "size": 7302056
15
+ "sha256": "41212856c811ddef6e918e96b49dc957b2d49946d7ef5494962db8d70937d760",
16
+ "size": 7306168
17
17
  },
18
18
  "entry": {
19
19
  "filename": "dist/foundation/resident-tabs/host-entry.js",
@@ -7,10 +7,10 @@
7
7
  "platform": "win32",
8
8
  "architecture": "x64",
9
9
  "capability": "supported",
10
- "builtAt": "2026-10-29T18:55:37.021Z",
10
+ "builtAt": "2026-10-31T17:04:36.928Z",
11
11
  "artifact": {
12
12
  "filename": "process-guardian.node",
13
- "sha256": "b11440d8ba81b69e18061dd2e73934ce4723ef3250c19a47a1563378d045268a",
13
+ "sha256": "a032ca679b335c66cef97c80b084e457e9bf3adb0f4fc93f338ace98ad955b23",
14
14
  "size": 402432
15
15
  },
16
16
  "provenance": {
@@ -9,11 +9,11 @@
9
9
  "architecture": "x64",
10
10
  "target": "x86_64-pc-windows-msvc",
11
11
  "capability": "supported",
12
- "builtAt": "2026-10-29T18:59:32.923Z",
12
+ "builtAt": "2026-10-31T17:07:00.170Z",
13
13
  "artifact": {
14
14
  "filename": "terminal-host.node",
15
- "sha256": "f6e448a810795d4d7db437d591e43fbf998e05b63f6cac37f56d3270e422c861",
16
- "size": 6393344
15
+ "sha256": "f352de0bb4dc23588d870e500e9e593f1928b1d0291a7b60f92425706b3c7015",
16
+ "size": 6397440
17
17
  },
18
18
  "entry": {
19
19
  "filename": "dist/foundation/resident-tabs/host-entry.js",