@timurproko/a1 0.2.4-dev.667 → 0.2.4

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 (95) hide show
  1. package/README.md +50 -39
  2. package/bin/pinned-pi-public.js +20 -2
  3. package/dist/app/session-shell/session-shell-root.d.ts +0 -1
  4. package/dist/app/session-shell/session-shell-root.js +2 -7
  5. package/dist/app/session-shell/session-shell.js +2 -12
  6. package/dist/features/owned-ui/resources/release-notes.json +4 -0
  7. package/dist/foundation/release/progress-palette.generated.d.ts +5 -0
  8. package/dist/foundation/release/progress-palette.generated.js +5 -0
  9. package/dist/foundation/release/update.js +4 -5
  10. package/dist/foundation/startup/startup-descriptor.js +2 -2
  11. package/dist/integrations/pi/components/index.d.ts +1 -1
  12. package/dist/integrations/pi/components/index.js +1 -1
  13. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +1 -1
  14. package/dist/integrations/pi/components/resources/builtin-themes.js +1 -1
  15. package/dist/integrations/pi/components/shell-presenters-transcript.js +10 -6
  16. package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +0 -1
  17. package/dist/integrations/pi/components/shell-selectors-dialogs.js +0 -5
  18. package/dist/integrations/pi/components/shell-shared-facade.d.ts +1 -1
  19. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  20. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  21. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  22. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  23. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  24. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  25. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  26. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  27. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  28. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  29. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  30. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  31. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  32. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  33. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  34. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  35. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  36. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  37. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  38. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  39. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  40. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  41. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  42. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  43. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  44. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +4 -3
  45. package/dist/integrations/pi/components/upstream/components/tool-execution.js +8 -7
  46. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  47. package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
  48. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  49. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  50. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
  51. package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
  52. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  53. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  54. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  55. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  56. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  57. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  58. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  59. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  60. package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +1 -1
  61. package/dist/integrations/pi/components/upstream/theme/system-theme.js +1 -1
  62. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  63. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  64. package/dist/integrations/pi/engine/adapter.d.ts +1 -1
  65. package/dist/integrations/pi/engine/adapter.js +8 -2
  66. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  67. package/dist/integrations/pi/startup-public.js +164 -166
  68. package/dist/integrations/pi/startup-public.manifest.json +3081 -3075
  69. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  70. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  71. package/dist/native/darwin-arm64/manifest.json +1 -1
  72. package/dist/native/linux-x64/manifest.json +1 -1
  73. package/dist/native/win32-x64/manifest.json +2 -2
  74. package/dist/native/win32-x64/process-guardian.exe +0 -0
  75. package/dist/runtime-payload-inventory.json +37842 -29757
  76. package/dist/ui/components/transcript-viewport.js +10 -7
  77. package/docs/architecture/project-structure.md +3 -1
  78. package/docs/assets/readme/gears-dark.svg +56 -0
  79. package/docs/assets/readme/gears.svg +0 -1
  80. package/docs/assets/readme/plugins-dark.svg +76 -0
  81. package/docs/assets/readme/plugins.svg +0 -1
  82. package/docs/assets/readme/rocket-dark.svg +66 -0
  83. package/docs/assets/readme/rocket.svg +0 -1
  84. package/docs/assets/readme/separator-dark.svg +13 -0
  85. package/docs/assets/readme/separator.svg +13 -0
  86. package/docs/assets/readme/terminal-dark.svg +76 -0
  87. package/docs/assets/readme/terminal.svg +0 -1
  88. package/docs/assets/readme/waves-dark.svg +142 -0
  89. package/docs/assets/readme/waves.svg +0 -1
  90. package/docs/local-worktree-cleanup.md +4 -2
  91. package/docs/openspec-archive-automation.md +14 -5
  92. package/docs/releases/0.2.4.md +22 -0
  93. package/package.json +3 -3
  94. package/dist/integrations/pi/components/upstream/components/daxnuts.d.ts +0 -29
  95. package/dist/integrations/pi/components/upstream/components/daxnuts.js +0 -146
@@ -2,7 +2,6 @@
2
2
  <style>
3
3
  text{font:500 9.8px 'JetBrains Mono',SFMono-Regular,Consolas,Menlo,monospace;fill:rgb(38,56,210);text-anchor:middle;dominant-baseline:central}
4
4
  .l0{fill-opacity:0.14}.l1{fill-opacity:0.247}.l2{fill-opacity:0.355}.l3{fill-opacity:0.463}.l4{fill-opacity:0.57}.l5{fill-opacity:0.677}.l6{fill-opacity:0.785}.l7{fill-opacity:0.892}.l8{fill-opacity:1}
5
- @media (prefers-color-scheme:dark){text{fill:rgb(166,181,255)}}
6
5
  .f{visibility:hidden}.s{display:none}
7
6
  @keyframes i{from,to{visibility:visible}}
8
7
  @keyframes l{0%{visibility:visible}0.794%,100%{visibility:hidden}}
@@ -2,7 +2,9 @@
2
2
 
3
3
  Local cleanup completes the delivery order in [the archive runbook](openspec-archive-automation.md). For version 3 that is one authorized manual implementation/acceptance/archive merge, read-only verification, remote topic-ref deletion, then safe local cleanup. Legacy versions still require their applicable acceptance-record and automatic archive merges. GitHub Actions never reaches into a developer machine. Local cleanup never publishes archives or merges PRs; `complete`, `retire-redundant`, preview, and queue/watch do not delete remote refs, while explicitly confirmed closed-unmerged `discard` owns only its exact expected-SHA topic-ref deletion.
4
4
 
5
- The implementation is repository tooling, not part of the installed A1 product. It requires Node, Git, and GitHub read access; the explicit closed-unmerged discard operation additionally requires authenticated permission to delete its exact remote topic ref. No product build, dependency installation, interactive UI, or OS-service provisioning is needed. It supports this repository's `origin` on github.com, via HTTPS or SSH.
5
+ The implementation is repository tooling, not part of the installed A1 product. It requires Node, Git, and GitHub read access; the explicit closed-unmerged discard operation additionally requires authenticated permission to delete its exact remote topic ref. No product build, dependency installation, interactive UI, or OS-service provisioning is needed. It supports this repository's `origin` on github.com, via HTTPS or SSH. The repository-local `remote.origin.url` must retain that canonical GitHub spelling; Git may still rewrite the effective transport through `url.*.insteadOf` to select an account-specific SSH host/key. A literal SSH alias remains unsupported because cleanup does not trust external SSH configuration as repository identity.
6
+
7
+ If the whole repository moves to another canonical path or Windows drive, a carried cleanup journal still names the old absolute paths. Read-only `status` and `preview` report `state-relocation-required` and never rewrite it. The next mutation-locked operation safely rebases the journal only when every recorded entry is completed terminal history, the repository and remote identities still match, and every historical path is beneath the old recorded worktree root. The migration is atomic and changes only repository/path fields; the requested current worktree is then captured afresh and must pass every ordinary cleanup gate. Any owned, released, partially deleting, malformed, escaped, or identity-mismatched entry blocks relocation without changing the journal or local resources.
6
8
 
7
9
  ## Hand-off and sweep: the ordinary agent path
8
10
 
@@ -60,7 +62,7 @@ node scripts/governance/local-worktree-cleanup.mjs complete \
60
62
 
61
63
  `complete` is explicit cleanup authorization for that exact candidate. It creates and releases an exact registration when needed, applies the repository-owned generated-path policy, verifies live merge/archive/CI/ref evidence, evaluates only that candidate, uses journaled non-force Git removal, deletes only the unchanged local topic ref, and leaves persistent watcher authority unchanged. Repeating it reports the completed candidate as already absent. Existing conflicting ownership, identity drift, unavailable evidence, or unknown content remains blocking.
62
64
 
63
- The central disposable policy is `node_modules`, `dist`, `.builds`, `.artifacts`, `native/process-guardian/target`, `native/terminal-host/target`, and the exact generated file `src/integrations/pi/engine/pi-settings-metadata.json`. The `.artifacts` root is the repository's ignored generated-artifact root (finalization and validation reports, packed candidates, agent-written logs and diffs); the two native roots contain repository-generated Cargo output; Vitest writes the metadata file for source-side settings tests and leaves it shared for overlapping test processes until worktree cleanup. Registrations that still name `.artifacts/openspec-archive` or `.artifacts/validation` stay valid and are widened to the current policy on the next `complete`.
65
+ The central disposable policy is `node_modules`, `dist`, `.builds`, `.artifacts`, `native/process-guardian/target`, `native/terminal-host/target`, and the exact generated file `src/integrations/pi/engine/pi-settings-metadata.json`. The `.artifacts` root is the repository's ignored generated-artifact root (finalization and validation reports, packed candidates, agent-written logs and diffs); the two native roots contain repository-generated Cargo output; Vitest writes the metadata file for source-side settings tests and leaves it shared for overlapping test processes until worktree cleanup. Agents select the owning worktree's `.artifacts/` root for their own transient delivery files rather than OS temp or another checkout, but its disposable status never makes scratch authoritative or permits secrets to be stored there. Registrations that still name `.artifacts/openspec-archive` or `.artifacts/validation` stay valid and are widened to the current policy on the next `complete`.
64
66
 
65
67
  Each root itself must be an ignored non-link regular file or directory inside the exact worktree. A descendant symbolic link or Windows junction is accepted only when its canonical target stays inside that same exact disposable root. Inspection records the link's path, filesystem identity, and target; purge revalidates them and removes the link entry without traversing it before removing the root. Root-level links, escapes, drift, unresolved/cyclic targets, special files, and nested repository boundaries remain blocking. Authority is component-exact: near matches such as `.artifacts-user`, `artifacts`, or `pi-settings-metadata-user.json`, arbitrary `target` directories, and sibling native projects remain blocking. Tracked/staged/unstaged/untracked content and every unknown ignored path still block. A tracked regular `.gitmodules` file alone is ordinary content; actual nested `.git` metadata, gitlinks, configured submodules, and submodule changes block. Ordinary content and these approved generated paths are traversed under separate finite entry allowances, so a normal dependency installation does not consume the ordinary source-tree allowance; both allowances retain the same deadline and content-boundary checks. Once those checks pass, cleanup deletes the declared disposable roots or files itself with a bounded retry for transient Windows sharing violations before handing the worktree to Git, so non-force Git removal only has to delete tracked content. A disposable path that stays locked after the retry budget reports `blocked` with `disposable-path-locked` and the path; the worktree, its `.git` pointer, and its journal are untouched, so stop the process holding the handle and rerun the same command.
66
68
 
@@ -77,6 +77,14 @@ Do not add a quoted phase line or a routine `Validation` section listing command
77
77
 
78
78
  Keep acceptance absent during proposal review so unfinished intent is not mistaken for final acceptance criteria. The finalization workflow rewrites only the implementation fence; keep the rest of the phase-free body unchanged through exact-head validation, maintainer review, and authorized manual merge. The same workflow run validates its finalized delivery record and applicable product/governance scopes before the stable protected aggregate succeeds. Do not add a lifecycle body edit or start a second validation run. After manual merge, trusted verification derives `Archived`; do not rewrite the accepted body.
79
79
 
80
+ ## Agent scratch files
81
+
82
+ When an agent chooses a path for a transient repository-delivery file—such as a PR/comment body, command payload, captured output, temporary patch/diff, or ad hoc log—it must use a purpose-specific descendant of the exact `.artifacts/` root in the worktree that owns the operation. A linked delivery uses its linked task worktree, not the primary checkout, another worktree, the operating-system temporary directory, home/desktop, or a sibling path. Address the worktree path explicitly because session linking does not change tool cwd.
83
+
84
+ Keep these files ignored, unstaged, uncommitted, disposable, non-authoritative, and free of credentials or other prohibited sensitive data. Required durable evidence belongs in its declared tracked OpenSpec location. This rule governs paths selected by the agent; it does not relocate temporary storage internally selected by Git, GitHub CLI, OpenSpec, language/package tooling, product runtime code, test frameworks, or hermetic fixtures.
85
+
86
+ For example, create `.artifacts/agent/pr-body.md` in the linked worktree before passing it to `gh pr create --body-file` or `gh pr edit --body-file`. The exact `.artifacts/` root remains subject to the existing guarded generated-content cleanup policy; this guidance does not authorize deletion outside that root or through unsafe filesystem boundaries.
87
+
80
88
  ## Version-3 implementation metadata
81
89
 
82
90
  The initial draft uses the existing metadata fence:
@@ -154,19 +162,20 @@ If an unassociated implementation has already integrated, do not edit its merged
154
162
 
155
163
  ## Finalization command
156
164
 
157
- The local command remains available for inspection or when a developer prefers to finalize before marking the PR ready; the workflow then verifies the head and pushes nothing. It has inspection mode by default and an explicit `--write` mode. It never commits, pushes, edits GitHub, marks a PR ready, or merges. Use a temporary body file so the operation can update exact version-3 paths without mutating remote PR state:
165
+ The local command remains available for inspection or when a developer prefers to finalize before marking the PR ready; the workflow then verifies the head and pushes nothing. It has inspection mode by default and an explicit `--write` mode. It never commits, pushes, edits GitHub, marks a PR ready, or merges. Run from the linked worktree and use an ignored artifact body file so the operation can update exact version-3 paths without mutating remote PR state:
158
166
 
159
167
  ```bash
160
168
  git fetch origin develop
161
169
  git rebase origin/develop
162
- gh pr view <pr> --json body --jq .body > "$TMPDIR/openspec-pr-body.md"
170
+ mkdir -p .artifacts/agent
171
+ gh pr view <pr> --json body --jq .body > .artifacts/agent/openspec-pr-body.md
163
172
  node scripts/governance/finalize-openspec-delivery.mjs \
164
173
  --change example-change \
165
174
  --repository owner/repo \
166
175
  --pr <pr> \
167
176
  --date YYYY-MM-DD \
168
177
  --target "$(git rev-parse origin/develop)" \
169
- --body-file "$TMPDIR/openspec-pr-body.md"
178
+ --body-file .artifacts/agent/openspec-pr-body.md
170
179
  ```
171
180
 
172
181
  Inspect the reported paths. Then rerun with `--write` and update the existing PR body from the emitted file:
@@ -178,9 +187,9 @@ node scripts/governance/finalize-openspec-delivery.mjs \
178
187
  --pr <pr> \
179
188
  --date YYYY-MM-DD \
180
189
  --target "$(git rev-parse origin/develop)" \
181
- --body-file "$TMPDIR/openspec-pr-body.md" \
190
+ --body-file .artifacts/agent/openspec-pr-body.md \
182
191
  --write
183
- gh pr edit <pr> --body-file "$TMPDIR/openspec-pr-body.md"
192
+ gh pr edit <pr> --body-file .artifacts/agent/openspec-pr-body.md
184
193
  ```
185
194
 
186
195
  Use repeated `--known-gap "exact disposition"` only for an actually reviewed explicit gap. Gaps remain visible in the committed manifest and do not become test results. Missing or ambiguous disposition blocks finalization.
@@ -0,0 +1,22 @@
1
+ ## [0.2.4] - 2026-10-05
2
+
3
+ ### New Features
4
+
5
+ - add README section navigation ([#678](https://github.com/timurproko/a1/pull/678))
6
+
7
+ ### Changed
8
+
9
+ - upgrade pinned Pi to 1.0.0 ([#658](https://github.com/timurproko/a1/pull/658))
10
+ - add animated mark, section art, and browser preview ([#665](https://github.com/timurproko/a1/pull/665))
11
+ - keep the hero mark still and link only it to the site ([#666](https://github.com/timurproko/a1/pull/666))
12
+ - pick dark-mode art via picture sources ([#668](https://github.com/timurproko/a1/pull/668))
13
+ - upgrade pinned Pi to 1.0.2 ([#669](https://github.com/timurproko/a1/pull/669))
14
+
15
+ ### Fixed
16
+
17
+ - make self-update upgrades reliable ([#664](https://github.com/timurproko/a1/pull/664))
18
+ - restore the terminal and print a resume hint when a1 is killed ([#667](https://github.com/timurproko/a1/pull/667))
19
+ - align progress with Pi accent ([#671](https://github.com/timurproko/a1/pull/671))
20
+ - support Git URL rewrites ([#673](https://github.com/timurproko/a1/pull/673))
21
+ - support repository relocation ([#675](https://github.com/timurproko/a1/pull/675))
22
+ - prevent bottom control gutter bleed ([#677](https://github.com/timurproko/a1/pull/677))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timurproko/a1",
3
- "version": "0.2.4-dev.667",
3
+ "version": "0.2.4",
4
4
  "description": "Standalone terminal workspace for supervised native and managed agents",
5
5
  "type": "module",
6
6
  "privateLaunchContract": "neutral-launch-v1",
@@ -65,8 +65,8 @@
65
65
  "typecheck:bin": "tsgo -p tsconfig.bin.json"
66
66
  },
67
67
  "dependencies": {
68
- "@earendil-works/pi-coding-agent": "1.0.0",
69
- "@earendil-works/pi-tui": "1.0.0",
68
+ "@earendil-works/pi-coding-agent": "1.0.2",
69
+ "@earendil-works/pi-tui": "1.0.2",
70
70
  "@silvia-odwyer/photon-node": "0.3.4",
71
71
  "chalk": "5.6.2",
72
72
  "cross-spawn": "7.0.6",
@@ -1,29 +0,0 @@
1
- /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.0.0 (MIT), commit a13d35a742c6ef8462812a28fbe1d8c8b7431c32,
3
- * packages/coding-agent/src/modes/interactive/components/daxnuts.ts.
4
- * Modifications: Mechanical pinned source port with private imports remapped to public package-root
5
- * types/APIs and A1-owned theme boundaries; behavior remains acceptance-tested.
6
- * Deviations: none.
7
- */
8
- /**
9
- * POWERED BY DAXNUTS - Easter egg for OpenCode + Kimi K2.5
10
- *
11
- * A heartfelt tribute to dax (@thdxr) for providing free Kimi K2.5 access via OpenCode.
12
- */
13
- import type { Component, TUI } from "@earendil-works/pi-tui";
14
- export declare class DaxnutsComponent implements Component {
15
- private ui;
16
- private image;
17
- private interval;
18
- private tick;
19
- private maxTicks;
20
- private cachedLines;
21
- private cachedWidth;
22
- private cachedTick;
23
- constructor(ui: TUI);
24
- invalidate(): void;
25
- private startAnimation;
26
- private stopAnimation;
27
- render(width: number): string[];
28
- dispose(): void;
29
- }
@@ -1,146 +0,0 @@
1
- /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.0.0 (MIT), commit a13d35a742c6ef8462812a28fbe1d8c8b7431c32,
3
- * packages/coding-agent/src/modes/interactive/components/daxnuts.ts.
4
- * Modifications: Mechanical pinned source port with private imports remapped to public package-root
5
- * types/APIs and A1-owned theme boundaries; behavior remains acceptance-tested.
6
- * Deviations: none.
7
- */
8
- /**
9
- * POWERED BY DAXNUTS - Easter egg for OpenCode + Kimi K2.5
10
- *
11
- * A heartfelt tribute to dax (@thdxr) for providing free Kimi K2.5 access via OpenCode.
12
- */
13
- import { piTheme } from "../theme/theme.js";
14
- // 32x32 RGB image of dax, hex encoded (3 bytes per pixel)
15
- const DAX_HEX = "bbbab8b9b9b6b9b8b5bcbbb8b8b7b4b7b5b2b6b5b2b8b7b4b7b6b3b6b4b1bdbcb8bab8b6bbb8b5b8b5b1bbb8b4c2bebbc1bebac0bdbabfbcb9c1bebabfbebbc0bfbcc0bdbabbb8b5c1bfbcbfbcb8bbb9b6bfbcb8c2bfbcc1bfbcbfbbb8bdb9b6b8b7b5b9b8b5b8b8b5b5b5b2b6b5b2b8b7b4b9b8b5b9b8b5b6b5b3bab8b5bcbab7bbb9b6bbb8b5bfb9b5bdb2abbcb0a8beb2aabeb5afbfbab6bebab7c0bfbcbebdbabebbb8c0bdbabfbebbc2bebbbdbab7c3c0bdc3c0bdc1bebbc2bebabfbcb8bab9b6b7b6b3b2b1aeb6b5b2b5b4b1b5b4b2b6b5b2b7b6b4b9b8b6b7b6b3bbbab7b2afaba5988fb49e90b09481b79a88b39683b09583b7a395bfb6b0c0bdbabdbbb8bebcb9c1bfbcc0bebbbdbab7bebbb8c2bfbcc0bdbac0bcb9bdb9b6c0bcb8b5b4b2b4b3b0bab9b6b9b9b6b5b4b1b5b4b1b6b5b3b9b8b5b9b8b6b9b8b6b2aeaa968174a6836eaa856eab846eaf8973ac8973b08f79b18f7ab39786b7a89dbbb3aebfbab6c2c0bdbebcb9bfbdbac3c1bdc2bebbc0bcb9bdb9b6c1bdbabfbbb8b4b3b0b9b8b5b8b7b5b4b3b1b5b4b1b8b7b4b8b7b5bab9b6bbbab7b1afad8c7a719d735ca47860a87d65a98069ae8972ae8c75af8d77aa826ba98067aa8974b39e90b6a79dbbb2adc0bdbac1bfbdbfbbb8c1bdb9bebab6c0bdb9bfbbb8c1bdbab4b2b0b7b6b4b7b6b3b4b2b0bab9b7b6b5b2b6b5b2bab9b6bab9b6958c87977663aa836bac8772b08f7aad8c77b2917db0917db0907cac8971a77d64a87f67ac8972b29887b8a89dbfbab5bfbdbac1bebac0bcb9c0bcb9c0bcb9c1bebabebab7b8b7b4b7b6b4b5b4b1b5b4b2b7b6b3b5b4b2bab9b7bab9b6b4b1ada88f7fad8973ae8d78b19684b19685b29786b69a89b29582b1917daa856ea87e66a97e66ad866ea9826baf9280b8ada6bdbbb8bebab7bfbbb8c1bdbabfbbb8bcb8b4bcb8b5b6b4b2b7b5b3b6b5b2b8b7b4b3b2afb8b7b4b6b5b2b3b2b0b3a59aab856fad8d78b0917eb19886b49b8bb49a89b39785b0917eaf8f7cab866fa77d65a77a61a87d64a9816ab08f79b5a296c1bcb8c3bfbcc2bebbbebab7bfbbb7bdbab6c2bebab8b7b4b7b6b4b6b5b3b7b6b3b6b5b2b9b8b6b4b3b1b6b1acac8f7ca9826bae8f7aaf9583b49c8cb49c8bb79d8cb59987b19380ad8e79ae8c77af8e78ac8771a3775faa826bae8972b39888bbb6b2bebbb8bfbbb8bfbbb8c0bdb9bebbb7c0bdb9b6b5b2b9b8b5b4b3b1b8b7b5b4b3b0b7b6b4b6b5b3b1a7a0aa8772a77d65a88570b49887b19b8d9c887c907a6d987f71aa907faf917daf8e7aad8c78ac8b77a8836ca9836cac8770b49b8abdb6b2c0bcb9c0bdb9bfbbb8bebab7bfbcb9bebab7b9b8b6b5b4b2b9b8b5b8b7b5b8b7b4b7b6b4b5b4b2b3a9a2ad8973a1755da9856fb398858c776a65544b776358725d526e594d9c7f6eb1907ba68672ad8e7aab8771ac856db18f79b3a092beb9b5c1bdbabdb9b5bebab7bfbbb7bebab7bcb9b6b7b6b4b6b6b3b8b7b4b5b4b2b8b6b4b7b6b3b4b3b0b4aba4a6826ba3775fb08e79b19584a88e7daa8e7db29481ad8f7c997e6da38674ac8d79ac8e7aae917f9a7c6a896a599a7c6ab3a398c1bdbabdb9b6bcb8b5bebab6bebab7bdb9b5bdb9b6b5b4b1b7b5b3b5b4b2b7b6b3b7b6b4b3b3b0b3b2b0b4aca5a7846fa97f68ae8f7bae9383b59c8bb2937fae8e79ac8b76af927eaf927eb29683b39885b2988891786a72594c6e594d978d86bdbab7bab7b3c0bcb9c0bcb9bebab7bebbb7bdb9b6b3b2b0b4b3b0b5b4b2b4b4b1b4b3b1b4b3b1b4b3b0b6ada5aa8670a57a62ad8e7ab29b8cb69d8dab856fa9826aa88069ab8771af907db49987b19684b29886b59987b39480b09787b5a9a1bcb8b5bebab7bdb9b5bebab7bfbbb8bfbbb7bbb7b4b3b2afb8b7b5b8b7b5b3b2b0b5b4b2b6b5b3b6b4b1afa299a98975a9826baf907cb39988b49a89af8e7aac8973aa856eaf8c74b1917dae907dac907db39988b29785b49785b7a090b9aca3bfbab7bcb8b5bdb9b6bcb8b4bcb8b5bdb9b5bcb8b4b5b4b2b6b5b3b4b3b0b4b3b0b9b8b5b8b6b4908b88887467aa8f7ea78976ad8973b08b74b59885b69e8eb29888b1917cb1917db1937fae907cb19686b39a8ab29886b59b8ab8a192b6aaa3b7b2afbcb8b4bcb8b5bbb7b4c0bcb9bebab7c0bcb9b6b5b2b6b5b3b4b3b0bab9b7b7b6b4b1b0ae7b716ba083709b806f716158967764b08870b29481b69b8ab69f8fb39a89b69f90b49d8db39a89b29988b49c8cb6a090b8a496baa49593867f8f8986bfbbb7bdb9b5bcb7b4bab6b3b9b5b2bab6b2b4b3b1b3b3b0b6b5b3b8b7b5b4b2b0a7a5a38f837dae917ea084725a504c63544da28370b39784b59e8db2a093a698909b918b998e8790857e95877dad998bb39c8cb5a091b9a2938d827c95908dbebab6bbb7b3bdbab7bbb7b4bdb9b6bbb7b4b4b3b0b5b4b1b8b7b5b6b5b3b8b8b5b4b2af968f8ab29a8bab9485544b483a323073655d96887f70655f61595547403e453e3c453f3d57504f655e5b90847db39c8db7a090b6a09189807aaba6a3bdb9b6c0bcb9bebab7bcb7b4bebab7bbb7b4b3b2b0b6b5b3b2b1afb7b6b4b8b7b4b5b4b1aeaba8b5a89fac998d4d44412d25244d46444e4744322b293a3230423937433a37352d2a59504c534b48524a48988a81b59f8fb19c8d827974b2afacbdb9b5bcb8b4bdb9b5bcb8b5bdb9b6bab6b2b8b7b5b5b4b2b6b6b3b9b8b5b7b6b3b6b5b2b8b6b3b9b4b1b2a9a26c64612d25242d2625312a28352d2c453d3a78675c8d7a6ea09792aea6a0615854332b29524a479f8e82b09d90a49b96c1bdb9bebab7bfbbb8bbb8b4b9b5b1b8b4b0b9b4b0b7b6b4b8b7b5b8b7b4b6b5b3b8b6b3bab9b6b9b8b5b4b3b0b7b5b2a5a29f453d3b261e1d261f1e2e2625413936857268977865b19482b5a69caca5a07c7572453d3b746963a0948cc5bfbbc0bbb8beb9b6bbb7b3bbb6b3b7b3afb8b4b0b9b5b1b7b6b3b6b5b3b5b4b2b5b4b2b7b6b3b7b6b3b8b6b3b4b2afb7b6b3b3b1ae6d6765251f1e1e18172a22212d2523443b3971625ab19888b09482a89182877e792c25243e3634766d6abeb9b5bfbbb7bebab6bcb7b3bbb6b3b9b5b1b7b3afb8b4b0b4b3b0b5b4b1b5b4b1b4b3b1b5b4b2b8b6b4b5b3b0b9b6b4b5b4b1b6b4b27f79762a2322221c1b2d2524221b1a443e3c47413f6f676281766f867971675e5a3e37352a222166605dbab7b3bdb9b5beb9b5bcb7b3bcb7b3b9b4b0bab6b2bab6b2b5b3b0b6b4b2b3b2afb7b6b3b4b4b1b4b3b0b6b4b1b5b4b1b4b3b0b9b6b29a8c8252474230292828201f181212322c2c231e1d1c16162c26252923222d26252d2523332b2a8e8885bcb8b5bcb7b3bbb6b2bcb7b3b9b4b1b9b5b1b7b2afb7b2ae7a838e9b9b9caeadacb3b2b0b3b2afb7b7b4b6b5b3b6b6b3b7b6b3b9ada4a991808e7b6f50453f2b24231a14142923221f19181d17161f18182620201d17162a22215d5654b7b3b0bbb7b3bbb6b2b8b4b0bab5b1bbb6b2bab5b1b8b4b0bab6b22c496b4c5d735f68766e727a828285929090adaba8b7b2aeb6a59ab39682a28470a387748e76674e403a1a14141d1716181211221c1c1f1918221c1b2f2827342d2c8d8884bab6b3b9b5b2bab5b1bab5b1b9b4b0bab6b2b8b4b0b9b4b0b7b2ae325e8b365f8a3a5d833f5b7a545f70646469706b6aa08f84b08e78b18e769f7e689e7f6b9e816d907766584940362d2a1c1615201b1a1a1413201a1a251e1d393331a39e9bbab5b1bcb7b3bab6b2b8b3afb8b4b0b9b4b0b9b4b1bab5b2b5b0ac3d6c9843729d44719c426e98415f805a64716f6a699d8677b1927eb3947faa89749d7a649f7f6ba487749e837186716454463f2c25231e181837302e3a33317a7471beb9b6bcb8b4bbb6b2b6b2aebab5b1b9b5b1b8b3afbab6b2b6b1adb5aeaa4877a14c7aa44e7ba345719a3a5d80586b7f767475927b6eb1927faf8e79b08e78a78169a07861a17f6aa58570a688749b83738270666f66618a8480a49e99b7b2aebab6b2bcb8b4b9b5b1b7b2aebab5b1b9b4b0b6b1aeb6b1adb2aca8b2aca84876a04a78a2517fa74771973a5d80405c7a6161677c695fac8a75b08d77b4917aaf8971ad876fa5816aa6846ea78670a98a76ac9484ab9f96b2aca8bdb8b4bcb7b3bcb8b4bcb8b4b8b3afb7b2aeb9b4b0b8b3afb8b2aeb6afabb3aeaab2aeaa4878a14b7aa34c7ba44a759b3d63873b5f825b67766f5f569c7e6caf8c77b18f79b28f78b5927caf8e78a98872aa8a76a98a76ac917fada199b7b0acb9b3afbfb9b5c1bab6bdb6b2b8b3afbab5b1b9b4b0b6afabb7b1adb3ada9b3aeaab0aba8";
16
- const WIDTH = 32;
17
- const HEIGHT = 32;
18
- function parseImage() {
19
- const pixels = [];
20
- for (let y = 0; y < HEIGHT; y++) {
21
- const row = [];
22
- for (let x = 0; x < WIDTH; x++) {
23
- const idx = (y * WIDTH + x) * 6;
24
- const r = parseInt(DAX_HEX.slice(idx, idx + 2), 16);
25
- const g = parseInt(DAX_HEX.slice(idx + 2, idx + 4), 16);
26
- const b = parseInt(DAX_HEX.slice(idx + 4, idx + 6), 16);
27
- row.push([r, g, b]);
28
- }
29
- pixels.push(row);
30
- }
31
- return pixels;
32
- }
33
- function rgb(r, g, b, bg = false) {
34
- return `\x1b[${bg ? 48 : 38};2;${r};${g};${b}m`;
35
- }
36
- const RESET = "\x1b[0m";
37
- function buildImage() {
38
- const pixels = parseImage();
39
- const lines = [];
40
- // Use half-block chars: ▄ with bg=top pixel, fg=bottom pixel
41
- for (let row = 0; row < HEIGHT; row += 2) {
42
- let line = "";
43
- for (let x = 0; x < WIDTH; x++) {
44
- const top = pixels[row]?.[x] ?? [0, 0, 0];
45
- const bottom = pixels[row + 1]?.[x] ?? top;
46
- line += `${rgb(bottom[0] ?? 0, bottom[1] ?? 0, bottom[2] ?? 0)}${rgb(top[0] ?? 0, top[1] ?? 0, top[2] ?? 0, true)}▄`;
47
- }
48
- line += RESET;
49
- lines.push(line);
50
- }
51
- return lines;
52
- }
53
- export class DaxnutsComponent {
54
- ui;
55
- image;
56
- interval = null;
57
- tick = 0;
58
- maxTicks = 25; // ~2 seconds at 80ms
59
- cachedLines = [];
60
- cachedWidth = 0;
61
- cachedTick = -1;
62
- constructor(ui) {
63
- this.ui = ui;
64
- this.image = buildImage();
65
- this.startAnimation();
66
- }
67
- invalidate() {
68
- this.cachedWidth = 0;
69
- }
70
- startAnimation() {
71
- this.interval = setInterval(() => {
72
- this.tick++;
73
- if (this.tick >= this.maxTicks) {
74
- this.stopAnimation();
75
- }
76
- this.cachedWidth = 0;
77
- this.ui.requestRender();
78
- }, 80);
79
- }
80
- stopAnimation() {
81
- if (this.interval) {
82
- clearInterval(this.interval);
83
- this.interval = null;
84
- }
85
- }
86
- render(width) {
87
- if (width === this.cachedWidth && this.cachedTick === this.tick) {
88
- return this.cachedLines;
89
- }
90
- const t = piTheme();
91
- const lines = [];
92
- const center = (s) => {
93
- const visible = s.replace(/\x1b\[[0-9;]*m/g, "").length;
94
- const left = Math.max(0, Math.floor((width - visible) / 2));
95
- return " ".repeat(left) + s;
96
- };
97
- lines.push("");
98
- // Scanline reveal effect: show rows progressively
99
- const revealedRows = Math.min(this.image.length, Math.floor((this.tick / this.maxTicks) * (this.image.length + 3)));
100
- for (let i = 0; i < this.image.length; i++) {
101
- if (i < revealedRows) {
102
- lines.push(center(this.image[i] ?? ""));
103
- }
104
- else {
105
- // Show scan line
106
- if (i === revealedRows) {
107
- const scanline = "▓".repeat(WIDTH);
108
- lines.push(center(rgb(100, 200, 255) + scanline + RESET));
109
- }
110
- else {
111
- lines.push(center(" ".repeat(WIDTH)));
112
- }
113
- }
114
- }
115
- lines.push("");
116
- // Fade in text after image is revealed
117
- const textPhase = Math.max(0, this.tick - this.maxTicks * 0.6);
118
- if (textPhase > 0 || this.tick >= this.maxTicks) {
119
- lines.push(center(t.fg("accent", "Free Kimi K2.5 via OpenCode Zen")));
120
- lines.push(center(t.fg("success", '"Powered by daxnuts"')));
121
- lines.push(center(t.fg("muted", "— @thdxr")));
122
- }
123
- else {
124
- lines.push("");
125
- lines.push("");
126
- lines.push("");
127
- }
128
- lines.push("");
129
- if (textPhase > 2 || this.tick >= this.maxTicks) {
130
- lines.push(center(t.fg("dim", "Try OpenCode")));
131
- lines.push(center(t.fg("mdLink", "https://mistral.ai/news/mistral-vibe-2-0")));
132
- }
133
- else {
134
- lines.push("");
135
- lines.push("");
136
- }
137
- lines.push("");
138
- this.cachedLines = lines;
139
- this.cachedWidth = width;
140
- this.cachedTick = this.tick;
141
- return lines;
142
- }
143
- dispose() {
144
- this.stopAnimation();
145
- }
146
- }