@bastani/atomic 0.9.26-alpha.1 → 0.9.26-alpha.3

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 (140) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/builtin/intercom/broker/spawn.ts +2 -0
  3. package/dist/builtin/intercom/index.bundle.mjs +1 -0
  4. package/dist/builtin/intercom/package.json +1 -1
  5. package/dist/builtin/mcp/native-client-licenses/NOTICE +2 -0
  6. package/dist/builtin/mcp/package.json +1 -1
  7. package/dist/builtin/subagents/package.json +1 -1
  8. package/dist/builtin/web-access/package.json +1 -1
  9. package/dist/builtin/workflows/package.json +1 -1
  10. package/dist/cli/args.d.ts.map +1 -1
  11. package/dist/cli/args.js +4 -1
  12. package/dist/cli/args.js.map +1 -1
  13. package/dist/core/extensions/api-types.d.ts +2 -1
  14. package/dist/core/extensions/api-types.d.ts.map +1 -1
  15. package/dist/core/extensions/api-types.js.map +1 -1
  16. package/dist/core/extensions/index.d.ts +1 -1
  17. package/dist/core/extensions/index.d.ts.map +1 -1
  18. package/dist/core/extensions/index.js.map +1 -1
  19. package/dist/core/extensions/loader-api.d.ts.map +1 -1
  20. package/dist/core/extensions/loader-api.js +7 -0
  21. package/dist/core/extensions/loader-api.js.map +1 -1
  22. package/dist/core/extensions/provider-types.d.ts +2 -0
  23. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  24. package/dist/core/extensions/provider-types.js.map +1 -1
  25. package/dist/core/keybindings.d.ts +5 -0
  26. package/dist/core/keybindings.d.ts.map +1 -1
  27. package/dist/core/keybindings.js +1 -0
  28. package/dist/core/keybindings.js.map +1 -1
  29. package/dist/core/model-runtime-streaming.d.ts +2 -1
  30. package/dist/core/model-runtime-streaming.d.ts.map +1 -1
  31. package/dist/core/model-runtime-streaming.js +4 -1
  32. package/dist/core/model-runtime-streaming.js.map +1 -1
  33. package/dist/core/model-runtime.d.ts +2 -0
  34. package/dist/core/model-runtime.d.ts.map +1 -1
  35. package/dist/core/model-runtime.js +69 -5
  36. package/dist/core/model-runtime.js.map +1 -1
  37. package/dist/core/oauth-provider-metadata.d.ts.map +1 -1
  38. package/dist/core/oauth-provider-metadata.js +4 -17
  39. package/dist/core/oauth-provider-metadata.js.map +1 -1
  40. package/dist/core/provider-alias.d.ts +8 -0
  41. package/dist/core/provider-alias.d.ts.map +1 -0
  42. package/dist/core/provider-alias.js +119 -0
  43. package/dist/core/provider-alias.js.map +1 -0
  44. package/dist/core/provider-composer-internal.d.ts +1 -0
  45. package/dist/core/provider-composer-internal.d.ts.map +1 -1
  46. package/dist/core/provider-composer-internal.js.map +1 -1
  47. package/dist/core/provider-composer.d.ts.map +1 -1
  48. package/dist/core/provider-composer.js +9 -0
  49. package/dist/core/provider-composer.js.map +1 -1
  50. package/dist/core/sdk.js +2 -1
  51. package/dist/core/sdk.js.map +1 -1
  52. package/dist/extensions/mcp/cli.d.ts.map +1 -1
  53. package/dist/extensions/mcp/cli.js +4 -1
  54. package/dist/extensions/mcp/cli.js.map +1 -1
  55. package/dist/extensions/mcp/client/oauth/callback.d.ts +4 -2
  56. package/dist/extensions/mcp/client/oauth/callback.d.ts.map +1 -1
  57. package/dist/extensions/mcp/client/oauth/callback.js +12 -7
  58. package/dist/extensions/mcp/client/oauth/callback.js.map +1 -1
  59. package/dist/extensions/mcp/client/oauth/flow.d.ts +7 -1
  60. package/dist/extensions/mcp/client/oauth/flow.d.ts.map +1 -1
  61. package/dist/extensions/mcp/client/oauth/flow.js +20 -21
  62. package/dist/extensions/mcp/client/oauth/flow.js.map +1 -1
  63. package/dist/extensions/mcp/client/oauth/index.d.ts +1 -1
  64. package/dist/extensions/mcp/client/oauth/index.d.ts.map +1 -1
  65. package/dist/extensions/mcp/client/oauth/index.js.map +1 -1
  66. package/dist/extensions/mcp/client/oauth/provider.d.ts +5 -2
  67. package/dist/extensions/mcp/client/oauth/provider.d.ts.map +1 -1
  68. package/dist/extensions/mcp/client/oauth/provider.js +2 -0
  69. package/dist/extensions/mcp/client/oauth/provider.js.map +1 -1
  70. package/dist/extensions/mcp/config.d.ts +16 -4
  71. package/dist/extensions/mcp/config.d.ts.map +1 -1
  72. package/dist/extensions/mcp/config.js +50 -11
  73. package/dist/extensions/mcp/config.js.map +1 -1
  74. package/dist/extensions/mcp/index.d.ts +4 -1
  75. package/dist/extensions/mcp/index.d.ts.map +1 -1
  76. package/dist/extensions/mcp/index.js +80 -46
  77. package/dist/extensions/mcp/index.js.map +1 -1
  78. package/dist/extensions/mcp/oauth.d.ts.map +1 -1
  79. package/dist/extensions/mcp/oauth.js +9 -5
  80. package/dist/extensions/mcp/oauth.js.map +1 -1
  81. package/dist/extensions/mcp/ui.d.ts.map +1 -1
  82. package/dist/extensions/mcp/ui.js +8 -4
  83. package/dist/extensions/mcp/ui.js.map +1 -1
  84. package/dist/index-extensions.d.ts +1 -1
  85. package/dist/index-extensions.d.ts.map +1 -1
  86. package/dist/index-extensions.js.map +1 -1
  87. package/dist/index.d.ts +1 -1
  88. package/dist/index.js.map +1 -1
  89. package/dist/modes/interactive/chat-input-actions.js.map +1 -1
  90. package/dist/modes/interactive/components/auth-url.d.ts +10 -0
  91. package/dist/modes/interactive/components/auth-url.d.ts.map +1 -0
  92. package/dist/modes/interactive/components/auth-url.js +37 -0
  93. package/dist/modes/interactive/components/auth-url.js.map +1 -0
  94. package/dist/modes/interactive/components/index.d.ts +0 -1
  95. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  96. package/dist/modes/interactive/components/index.js +0 -1
  97. package/dist/modes/interactive/components/index.js.map +1 -1
  98. package/dist/modes/interactive/components/login-dialog.d.ts +1 -0
  99. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  100. package/dist/modes/interactive/components/login-dialog.js +10 -5
  101. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  102. package/dist/modes/interactive/interactive-auth-login.js +0 -1
  103. package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
  104. package/dist/modes/interactive/interactive-hotkeys-debug.js +1 -11
  105. package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
  106. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  107. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -2
  108. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  109. package/dist/modes/interactive/interactive-mode-deps.js +0 -1
  110. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  111. package/dist/modes/interactive/interactive-mode-surface.d.ts +0 -5
  112. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  113. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  114. package/dist/modes/interactive/interactive-model-routing.js +0 -2
  115. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  116. package/dist/modes/interactive/interactive-tui.js.map +1 -1
  117. package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
  118. package/dist/modes/interactive-engine/engine-custom-ui.js +38 -2
  119. package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
  120. package/dist/modes/interactive-engine/protocol.d.ts +10 -0
  121. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
  122. package/dist/modes/interactive-engine/protocol.js +10 -0
  123. package/dist/modes/interactive-engine/protocol.js.map +1 -1
  124. package/dist/modes/interactive-engine/remote-component.d.ts +2 -1
  125. package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -1
  126. package/dist/modes/interactive-engine/remote-component.js +23 -1
  127. package/dist/modes/interactive-engine/remote-component.js.map +1 -1
  128. package/docs/custom-provider/oauth.md +2 -0
  129. package/docs/custom-provider/registration.md +32 -0
  130. package/docs/custom-provider.md +1 -0
  131. package/docs/keybindings.md +3 -0
  132. package/docs/mcp-servers.md +13 -1
  133. package/docs/providers.md +2 -0
  134. package/examples/extensions/provider-accounts.ts +11 -0
  135. package/npm-shrinkwrap.json +55 -33
  136. package/package.json +4 -3
  137. package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  138. package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
  139. package/dist/modes/interactive/components/daxnuts.js +0 -140
  140. package/dist/modes/interactive/components/daxnuts.js.map +0 -1
@@ -31,6 +31,16 @@ Use `/mcp` to inspect connections and manage servers. After changing configurati
31
31
 
32
32
  Atomic reads user-level servers from `~/.atomic/agent/mcp.json` and project servers from `.atomic/mcp.json`. Project configuration is read only after [project trust](/security) is granted. A project entry replaces a user-level entry with the same name.
33
33
 
34
+ A project entry without `command`, `url`, or `type` overrides only `enabled`, `exposure`, and `toolExposure` of the user-level server with the same name and keeps the rest, including `env`, `headers`, and `auth`. For example, this turns off a user-level server in one project:
35
+
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "internal-tools": { "enabled": false }
40
+ }
41
+ }
42
+ ```
43
+
34
44
  Both files use a top-level `mcpServers` object. Keep personal servers and credentials in the user-level file. `ATOMIC_CODING_AGENT_DIR` relocates the Atomic agent directory.
35
45
 
36
46
  Stdio servers use `command`, `args`, `env`, and `cwd`. `command` is one executable, not a shell command string. Relative `cwd` values resolve against the session directory.
@@ -66,7 +76,7 @@ Server names may contain letters, digits, `_`, and `-`. Names that differ only i
66
76
 
67
77
  Installed [packages](/packages/authoring#mcp-servers) and extensions can contribute servers with the same configuration shape. File-configured servers take precedence over contributions with the same normalized name. Project packages load only after the project is trusted.
68
78
 
69
- `/mcp` shows each server's source. Enabled-state and exposure changes for file-configured servers are saved without replacing unrelated configuration. Changes to extension-contributed servers apply to the current session.
79
+ `/mcp` shows each server's source. Enabled-state and exposure changes for file-configured servers are saved without replacing unrelated configuration. In a trusted project, "Enable in this project" and "Disable in this project" add a project override for a user-level server; later changes to that server are saved to the override. `atomic mcp list` shows the override. Changes to extension-contributed servers apply to the current session.
70
80
 
71
81
  ## Manage servers
72
82
 
@@ -177,6 +187,8 @@ OAuth applies to HTTP servers without an `Authorization` header or provider-toke
177
187
 
178
188
  `clientSecret` is optional. `callbackPort` uses `http://127.0.0.1:<port>/callback`. For another registered redirect URI, set `callbackUrl`; it must use HTTP on `localhost`, `127.0.0.1`, or `[::1]`. Atomic sends it as written. If it has no port, Atomic adds `callbackPort` or a free port. The URI must match the client's registration.
179
189
 
190
+ When pasting a redirect URL, keep its scheme, host, port, and path unchanged. Atomic rejects a URL that does not match the redirect URI for the current sign-in, even if its authorization code and state are present.
191
+
180
192
  Use `oauth.clientName` when a server requires a known registration name. Sign out before signing in again to register with a changed name. Use `oauth.scope` for servers that do not advertise their required scopes; later scope requests are added to it.
181
193
 
182
194
  ### Override OAuth authorization server discovery
package/docs/providers.md CHANGED
@@ -521,6 +521,8 @@ atomic --provider cloudflare-workers-ai --model "@cf/moonshotai/kimi-k2.6"
521
521
 
522
522
  Atomic automatically sets `x-session-affinity` for [prefix caching](https://developers.cloudflare.com/workers-ai/features/prompt-caching/) discounts.
523
523
 
524
+ Workers AI also lists Cloudflare's Clef (`@cf/cloudflare/clef`) and Clef Flash (`@cf/cloudflare/clef-flash`) as classifiers. They use the same `CLOUDFLARE_API_KEY` and `CLOUDFLARE_ACCOUNT_ID`. Name the exact ID in `routerModel`, `structured_output`, or `generateStructuredOutput()`; like other classifiers they do not appear in `/model` or work with `--model`. See [Structured decisions](/sdk/structured-decisions).
525
+
524
526
  ### Google Vertex AI
525
527
 
526
528
  Uses Application Default Credentials:
@@ -0,0 +1,11 @@
1
+ import type { ExtensionAPI } from "@bastani/atomic";
2
+
3
+ export default function providerAccounts(pi: ExtensionAPI) {
4
+ for (let account = 1; account <= 7; account++) {
5
+ pi.registerProviderAlias({
6
+ id: `openai-${account}`,
7
+ name: `OpenAI account ${account}`,
8
+ provider: "openai",
9
+ });
10
+ }
11
+ }
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.26-alpha.1",
3
+ "version": "0.9.26-alpha.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bastani/atomic",
9
- "version": "0.9.26-alpha.1",
9
+ "version": "0.9.26-alpha.3",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@bastani/atomic-natives": "0.9.26-alpha.1",
13
- "@bastani/pi-ai": "0.9.26-alpha.1",
12
+ "@bastani/atomic-natives": "0.9.26-alpha.3",
13
+ "@bastani/pi-ai": "0.9.26-alpha.3",
14
14
  "@dbos-inc/dbos-sdk": "4.25.14",
15
15
  "@earendil-works/pi-agent-core": "1.0.0",
16
16
  "@earendil-works/pi-client": "1.0.0",
@@ -22,6 +22,7 @@
22
22
  "@mozilla/readability": "^0.6.0",
23
23
  "@silvia-odwyer/photon-node": "0.3.4",
24
24
  "@typesafe-ai/sdk": "0.6.0",
25
+ "brace-expansion": "5.0.12",
25
26
  "chalk": "6.0.0",
26
27
  "cross-spawn": "7.0.6",
27
28
  "diff": "8.0.4",
@@ -431,18 +432,18 @@
431
432
  }
432
433
  },
433
434
  "node_modules/@bastani/atomic-natives": {
434
- "version": "0.9.26-alpha.1",
435
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.26-alpha.1.tgz",
435
+ "version": "0.9.26-alpha.3",
436
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.26-alpha.3.tgz",
436
437
  "license": "MIT",
437
438
  "optionalDependencies": {
438
- "@bastani/atomic-natives-darwin-arm64": "0.9.26-alpha.1",
439
- "@bastani/atomic-natives-darwin-x64": "0.9.26-alpha.1",
440
- "@bastani/atomic-natives-linux-arm64-gnu": "0.9.26-alpha.1",
441
- "@bastani/atomic-natives-linux-arm64-musl": "0.9.26-alpha.1",
442
- "@bastani/atomic-natives-linux-x64-gnu": "0.9.26-alpha.1",
443
- "@bastani/atomic-natives-linux-x64-musl": "0.9.26-alpha.1",
444
- "@bastani/atomic-natives-win32-arm64-msvc": "0.9.26-alpha.1",
445
- "@bastani/atomic-natives-win32-x64-msvc": "0.9.26-alpha.1"
439
+ "@bastani/atomic-natives-darwin-arm64": "0.9.26-alpha.3",
440
+ "@bastani/atomic-natives-darwin-x64": "0.9.26-alpha.3",
441
+ "@bastani/atomic-natives-linux-arm64-gnu": "0.9.26-alpha.3",
442
+ "@bastani/atomic-natives-linux-arm64-musl": "0.9.26-alpha.3",
443
+ "@bastani/atomic-natives-linux-x64-gnu": "0.9.26-alpha.3",
444
+ "@bastani/atomic-natives-linux-x64-musl": "0.9.26-alpha.3",
445
+ "@bastani/atomic-natives-win32-arm64-msvc": "0.9.26-alpha.3",
446
+ "@bastani/atomic-natives-win32-x64-msvc": "0.9.26-alpha.3"
446
447
  },
447
448
  "engines": {
448
449
  "bun": ">=1.4.2",
@@ -450,8 +451,8 @@
450
451
  }
451
452
  },
452
453
  "node_modules/@bastani/atomic-natives-darwin-arm64": {
453
- "version": "0.9.26-alpha.1",
454
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.26-alpha.1.tgz",
454
+ "version": "0.9.26-alpha.3",
455
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.26-alpha.3.tgz",
455
456
  "license": "MIT",
456
457
  "os": [
457
458
  "darwin"
@@ -462,8 +463,8 @@
462
463
  "optional": true
463
464
  },
464
465
  "node_modules/@bastani/atomic-natives-darwin-x64": {
465
- "version": "0.9.26-alpha.1",
466
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.26-alpha.1.tgz",
466
+ "version": "0.9.26-alpha.3",
467
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.26-alpha.3.tgz",
467
468
  "license": "MIT",
468
469
  "os": [
469
470
  "darwin"
@@ -474,8 +475,8 @@
474
475
  "optional": true
475
476
  },
476
477
  "node_modules/@bastani/atomic-natives-linux-arm64-gnu": {
477
- "version": "0.9.26-alpha.1",
478
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.26-alpha.1.tgz",
478
+ "version": "0.9.26-alpha.3",
479
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.26-alpha.3.tgz",
479
480
  "license": "MIT",
480
481
  "os": [
481
482
  "linux"
@@ -489,8 +490,8 @@
489
490
  "optional": true
490
491
  },
491
492
  "node_modules/@bastani/atomic-natives-linux-arm64-musl": {
492
- "version": "0.9.26-alpha.1",
493
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.26-alpha.1.tgz",
493
+ "version": "0.9.26-alpha.3",
494
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.26-alpha.3.tgz",
494
495
  "license": "MIT",
495
496
  "os": [
496
497
  "linux"
@@ -504,8 +505,8 @@
504
505
  "optional": true
505
506
  },
506
507
  "node_modules/@bastani/atomic-natives-linux-x64-gnu": {
507
- "version": "0.9.26-alpha.1",
508
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.26-alpha.1.tgz",
508
+ "version": "0.9.26-alpha.3",
509
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.26-alpha.3.tgz",
509
510
  "license": "MIT",
510
511
  "os": [
511
512
  "linux"
@@ -519,8 +520,8 @@
519
520
  "optional": true
520
521
  },
521
522
  "node_modules/@bastani/atomic-natives-linux-x64-musl": {
522
- "version": "0.9.26-alpha.1",
523
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.26-alpha.1.tgz",
523
+ "version": "0.9.26-alpha.3",
524
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.26-alpha.3.tgz",
524
525
  "license": "MIT",
525
526
  "os": [
526
527
  "linux"
@@ -534,8 +535,8 @@
534
535
  "optional": true
535
536
  },
536
537
  "node_modules/@bastani/atomic-natives-win32-arm64-msvc": {
537
- "version": "0.9.26-alpha.1",
538
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.26-alpha.1.tgz",
538
+ "version": "0.9.26-alpha.3",
539
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.26-alpha.3.tgz",
539
540
  "license": "MIT",
540
541
  "os": [
541
542
  "win32"
@@ -546,8 +547,8 @@
546
547
  "optional": true
547
548
  },
548
549
  "node_modules/@bastani/atomic-natives-win32-x64-msvc": {
549
- "version": "0.9.26-alpha.1",
550
- "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.26-alpha.1.tgz",
550
+ "version": "0.9.26-alpha.3",
551
+ "resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.26-alpha.3.tgz",
551
552
  "license": "MIT",
552
553
  "os": [
553
554
  "win32"
@@ -558,11 +559,11 @@
558
559
  "optional": true
559
560
  },
560
561
  "node_modules/@bastani/pi-ai": {
561
- "version": "0.9.26-alpha.1",
562
- "resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.26-alpha.1.tgz",
562
+ "version": "0.9.26-alpha.3",
563
+ "resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.26-alpha.3.tgz",
563
564
  "license": "MIT",
564
565
  "dependencies": {
565
- "@anthropic-ai/sdk": "0.124.0",
566
+ "@anthropic-ai/sdk": "0.129.0",
566
567
  "@aws-sdk/client-bedrock-runtime": "3.1127.0",
567
568
  "@earendil-works/pi-telemetry": "1.0.0",
568
569
  "@google/genai": "2.21.0",
@@ -580,6 +581,27 @@
580
581
  "node": ">=22.19.0"
581
582
  }
582
583
  },
584
+ "node_modules/@bastani/pi-ai/node_modules/@anthropic-ai/sdk": {
585
+ "version": "0.129.0",
586
+ "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.129.0.tgz",
587
+ "integrity": "sha512-MH7LB20kNpGLUpPTe2OG5XvL/KhX8HUO9XyBaFjgFk6TLS4Xjt0VPIuMKywe7POKKPslX+QxSlVok9e+8kG5Nw==",
588
+ "license": "MIT",
589
+ "dependencies": {
590
+ "json-schema-to-ts": "^3.1.1",
591
+ "standardwebhooks": "^1.0.0"
592
+ },
593
+ "peerDependencies": {
594
+ "zod": "^3.25.0 || ^4.0.0"
595
+ },
596
+ "peerDependenciesMeta": {
597
+ "zod": {
598
+ "optional": true
599
+ }
600
+ },
601
+ "bin": {
602
+ "anthropic-ai-sdk": "bin/cli"
603
+ }
604
+ },
583
605
  "node_modules/@bastani/pi-ai/node_modules/agent-base": {
584
606
  "version": "9.0.0",
585
607
  "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.9.26-alpha.1",
3
+ "version": "0.9.26-alpha.3",
4
4
  "description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "atomicConfig": {
@@ -80,8 +80,8 @@
80
80
  "prepublishOnly": "bun run clean && bun run build && bun run shrinkwrap"
81
81
  },
82
82
  "dependencies": {
83
- "@bastani/atomic-natives": "0.9.26-alpha.1",
84
- "@bastani/pi-ai": "0.9.26-alpha.1",
83
+ "@bastani/atomic-natives": "0.9.26-alpha.3",
84
+ "@bastani/pi-ai": "0.9.26-alpha.3",
85
85
  "@dbos-inc/dbos-sdk": "4.25.14",
86
86
  "@earendil-works/pi-agent-core": "1.0.0",
87
87
  "@earendil-works/pi-client": "1.0.0",
@@ -93,6 +93,7 @@
93
93
  "@mozilla/readability": "^0.6.0",
94
94
  "@silvia-odwyer/photon-node": "0.3.4",
95
95
  "@typesafe-ai/sdk": "0.6.0",
96
+ "brace-expansion": "5.0.12",
96
97
  "chalk": "6.0.0",
97
98
  "cross-spawn": "7.0.6",
98
99
  "diff": "8.0.4",
@@ -1,23 +0,0 @@
1
- /**
2
- * POWERED BY DAXNUTS - Easter egg for OpenCode + Kimi K2.5
3
- *
4
- * A heartfelt tribute to dax (@thdxr) for providing free Kimi K2.5 access via OpenCode.
5
- */
6
- import type { Component, TUI } from "@earendil-works/pi-tui";
7
- export declare class DaxnutsComponent implements Component {
8
- private ui;
9
- private image;
10
- private interval;
11
- private tick;
12
- private maxTicks;
13
- private cachedLines;
14
- private cachedWidth;
15
- private cachedTick;
16
- constructor(ui: TUI);
17
- invalidate(): void;
18
- private startAnimation;
19
- private stopAnimation;
20
- render(width: number): string[];
21
- dispose(): void;
22
- }
23
- //# sourceMappingURL=daxnuts.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"daxnuts.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/daxnuts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAkD7D,qBAAa,gBAAiB,YAAW,SAAS;IACjD,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAM;IAExB,YAAY,EAAE,EAAE,GAAG,EAIlB;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,aAAa;IAOrB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAgE9B;IAED,OAAO,IAAI,IAAI,CAEd;CACD"}
@@ -1,140 +0,0 @@
1
- /**
2
- * POWERED BY DAXNUTS - Easter egg for OpenCode + Kimi K2.5
3
- *
4
- * A heartfelt tribute to dax (@thdxr) for providing free Kimi K2.5 access via OpenCode.
5
- */
6
- import { theme } from "../theme/theme.js";
7
- // 32x32 RGB image of dax, hex encoded (3 bytes per pixel)
8
- const DAX_HEX = "bbbab8b9b9b6b9b8b5bcbbb8b8b7b4b7b5b2b6b5b2b8b7b4b7b6b3b6b4b1bdbcb8bab8b6bbb8b5b8b5b1bbb8b4c2bebbc1bebac0bdbabfbcb9c1bebabfbebbc0bfbcc0bdbabbb8b5c1bfbcbfbcb8bbb9b6bfbcb8c2bfbcc1bfbcbfbbb8bdb9b6b8b7b5b9b8b5b8b8b5b5b5b2b6b5b2b8b7b4b9b8b5b9b8b5b6b5b3bab8b5bcbab7bbb9b6bbb8b5bfb9b5bdb2abbcb0a8beb2aabeb5afbfbab6bebab7c0bfbcbebdbabebbb8c0bdbabfbebbc2bebbbdbab7c3c0bdc3c0bdc1bebbc2bebabfbcb8bab9b6b7b6b3b2b1aeb6b5b2b5b4b1b5b4b2b6b5b2b7b6b4b9b8b6b7b6b3bbbab7b2afaba5988fb49e90b09481b79a88b39683b09583b7a395bfb6b0c0bdbabdbbb8bebcb9c1bfbcc0bebbbdbab7bebbb8c2bfbcc0bdbac0bcb9bdb9b6c0bcb8b5b4b2b4b3b0bab9b6b9b9b6b5b4b1b5b4b1b6b5b3b9b8b5b9b8b6b9b8b6b2aeaa968174a6836eaa856eab846eaf8973ac8973b08f79b18f7ab39786b7a89dbbb3aebfbab6c2c0bdbebcb9bfbdbac3c1bdc2bebbc0bcb9bdb9b6c1bdbabfbbb8b4b3b0b9b8b5b8b7b5b4b3b1b5b4b1b8b7b4b8b7b5bab9b6bbbab7b1afad8c7a719d735ca47860a87d65a98069ae8972ae8c75af8d77aa826ba98067aa8974b39e90b6a79dbbb2adc0bdbac1bfbdbfbbb8c1bdb9bebab6c0bdb9bfbbb8c1bdbab4b2b0b7b6b4b7b6b3b4b2b0bab9b7b6b5b2b6b5b2bab9b6bab9b6958c87977663aa836bac8772b08f7aad8c77b2917db0917db0907cac8971a77d64a87f67ac8972b29887b8a89dbfbab5bfbdbac1bebac0bcb9c0bcb9c0bcb9c1bebabebab7b8b7b4b7b6b4b5b4b1b5b4b2b7b6b3b5b4b2bab9b7bab9b6b4b1ada88f7fad8973ae8d78b19684b19685b29786b69a89b29582b1917daa856ea87e66a97e66ad866ea9826baf9280b8ada6bdbbb8bebab7bfbbb8c1bdbabfbbb8bcb8b4bcb8b5b6b4b2b7b5b3b6b5b2b8b7b4b3b2afb8b7b4b6b5b2b3b2b0b3a59aab856fad8d78b0917eb19886b49b8bb49a89b39785b0917eaf8f7cab866fa77d65a77a61a87d64a9816ab08f79b5a296c1bcb8c3bfbcc2bebbbebab7bfbbb7bdbab6c2bebab8b7b4b7b6b4b6b5b3b7b6b3b6b5b2b9b8b6b4b3b1b6b1acac8f7ca9826bae8f7aaf9583b49c8cb49c8bb79d8cb59987b19380ad8e79ae8c77af8e78ac8771a3775faa826bae8972b39888bbb6b2bebbb8bfbbb8bfbbb8c0bdb9bebbb7c0bdb9b6b5b2b9b8b5b4b3b1b8b7b5b4b3b0b7b6b4b6b5b3b1a7a0aa8772a77d65a88570b49887b19b8d9c887c907a6d987f71aa907faf917daf8e7aad8c78ac8b77a8836ca9836cac8770b49b8abdb6b2c0bcb9c0bdb9bfbbb8bebab7bfbcb9bebab7b9b8b6b5b4b2b9b8b5b8b7b5b8b7b4b7b6b4b5b4b2b3a9a2ad8973a1755da9856fb398858c776a65544b776358725d526e594d9c7f6eb1907ba68672ad8e7aab8771ac856db18f79b3a092beb9b5c1bdbabdb9b5bebab7bfbbb7bebab7bcb9b6b7b6b4b6b6b3b8b7b4b5b4b2b8b6b4b7b6b3b4b3b0b4aba4a6826ba3775fb08e79b19584a88e7daa8e7db29481ad8f7c997e6da38674ac8d79ac8e7aae917f9a7c6a896a599a7c6ab3a398c1bdbabdb9b6bcb8b5bebab6bebab7bdb9b5bdb9b6b5b4b1b7b5b3b5b4b2b7b6b3b7b6b4b3b3b0b3b2b0b4aca5a7846fa97f68ae8f7bae9383b59c8bb2937fae8e79ac8b76af927eaf927eb29683b39885b2988891786a72594c6e594d978d86bdbab7bab7b3c0bcb9c0bcb9bebab7bebbb7bdb9b6b3b2b0b4b3b0b5b4b2b4b4b1b4b3b1b4b3b1b4b3b0b6ada5aa8670a57a62ad8e7ab29b8cb69d8dab856fa9826aa88069ab8771af907db49987b19684b29886b59987b39480b09787b5a9a1bcb8b5bebab7bdb9b5bebab7bfbbb8bfbbb7bbb7b4b3b2afb8b7b5b8b7b5b3b2b0b5b4b2b6b5b3b6b4b1afa299a98975a9826baf907cb39988b49a89af8e7aac8973aa856eaf8c74b1917dae907dac907db39988b29785b49785b7a090b9aca3bfbab7bcb8b5bdb9b6bcb8b4bcb8b5bdb9b5bcb8b4b5b4b2b6b5b3b4b3b0b4b3b0b9b8b5b8b6b4908b88887467aa8f7ea78976ad8973b08b74b59885b69e8eb29888b1917cb1917db1937fae907cb19686b39a8ab29886b59b8ab8a192b6aaa3b7b2afbcb8b4bcb8b5bbb7b4c0bcb9bebab7c0bcb9b6b5b2b6b5b3b4b3b0bab9b7b7b6b4b1b0ae7b716ba083709b806f716158967764b08870b29481b69b8ab69f8fb39a89b69f90b49d8db39a89b29988b49c8cb6a090b8a496baa49593867f8f8986bfbbb7bdb9b5bcb7b4bab6b3b9b5b2bab6b2b4b3b1b3b3b0b6b5b3b8b7b5b4b2b0a7a5a38f837dae917ea084725a504c63544da28370b39784b59e8db2a093a698909b918b998e8790857e95877dad998bb39c8cb5a091b9a2938d827c95908dbebab6bbb7b3bdbab7bbb7b4bdb9b6bbb7b4b4b3b0b5b4b1b8b7b5b6b5b3b8b8b5b4b2af968f8ab29a8bab9485544b483a323073655d96887f70655f61595547403e453e3c453f3d57504f655e5b90847db39c8db7a090b6a09189807aaba6a3bdb9b6c0bcb9bebab7bcb7b4bebab7bbb7b4b3b2b0b6b5b3b2b1afb7b6b4b8b7b4b5b4b1aeaba8b5a89fac998d4d44412d25244d46444e4744322b293a3230423937433a37352d2a59504c534b48524a48988a81b59f8fb19c8d827974b2afacbdb9b5bcb8b4bdb9b5bcb8b5bdb9b6bab6b2b8b7b5b5b4b2b6b6b3b9b8b5b7b6b3b6b5b2b8b6b3b9b4b1b2a9a26c64612d25242d2625312a28352d2c453d3a78675c8d7a6ea09792aea6a0615854332b29524a479f8e82b09d90a49b96c1bdb9bebab7bfbbb8bbb8b4b9b5b1b8b4b0b9b4b0b7b6b4b8b7b5b8b7b4b6b5b3b8b6b3bab9b6b9b8b5b4b3b0b7b5b2a5a29f453d3b261e1d261f1e2e2625413936857268977865b19482b5a69caca5a07c7572453d3b746963a0948cc5bfbbc0bbb8beb9b6bbb7b3bbb6b3b7b3afb8b4b0b9b5b1b7b6b3b6b5b3b5b4b2b5b4b2b7b6b3b7b6b3b8b6b3b4b2afb7b6b3b3b1ae6d6765251f1e1e18172a22212d2523443b3971625ab19888b09482a89182877e792c25243e3634766d6abeb9b5bfbbb7bebab6bcb7b3bbb6b3b9b5b1b7b3afb8b4b0b4b3b0b5b4b1b5b4b1b4b3b1b5b4b2b8b6b4b5b3b0b9b6b4b5b4b1b6b4b27f79762a2322221c1b2d2524221b1a443e3c47413f6f676281766f867971675e5a3e37352a222166605dbab7b3bdb9b5beb9b5bcb7b3bcb7b3b9b4b0bab6b2bab6b2b5b3b0b6b4b2b3b2afb7b6b3b4b4b1b4b3b0b6b4b1b5b4b1b4b3b0b9b6b29a8c8252474230292828201f181212322c2c231e1d1c16162c26252923222d26252d2523332b2a8e8885bcb8b5bcb7b3bbb6b2bcb7b3b9b4b1b9b5b1b7b2afb7b2ae7a838e9b9b9caeadacb3b2b0b3b2afb7b7b4b6b5b3b6b6b3b7b6b3b9ada4a991808e7b6f50453f2b24231a14142923221f19181d17161f18182620201d17162a22215d5654b7b3b0bbb7b3bbb6b2b8b4b0bab5b1bbb6b2bab5b1b8b4b0bab6b22c496b4c5d735f68766e727a828285929090adaba8b7b2aeb6a59ab39682a28470a387748e76674e403a1a14141d1716181211221c1c1f1918221c1b2f2827342d2c8d8884bab6b3b9b5b2bab5b1bab5b1b9b4b0bab6b2b8b4b0b9b4b0b7b2ae325e8b365f8a3a5d833f5b7a545f70646469706b6aa08f84b08e78b18e769f7e689e7f6b9e816d907766584940362d2a1c1615201b1a1a1413201a1a251e1d393331a39e9bbab5b1bcb7b3bab6b2b8b3afb8b4b0b9b4b0b9b4b1bab5b2b5b0ac3d6c9843729d44719c426e98415f805a64716f6a699d8677b1927eb3947faa89749d7a649f7f6ba487749e837186716454463f2c25231e181837302e3a33317a7471beb9b6bcb8b4bbb6b2b6b2aebab5b1b9b5b1b8b3afbab6b2b6b1adb5aeaa4877a14c7aa44e7ba345719a3a5d80586b7f767475927b6eb1927faf8e79b08e78a78169a07861a17f6aa58570a688749b83738270666f66618a8480a49e99b7b2aebab6b2bcb8b4b9b5b1b7b2aebab5b1b9b4b0b6b1aeb6b1adb2aca8b2aca84876a04a78a2517fa74771973a5d80405c7a6161677c695fac8a75b08d77b4917aaf8971ad876fa5816aa6846ea78670a98a76ac9484ab9f96b2aca8bdb8b4bcb7b3bcb8b4bcb8b4b8b3afb7b2aeb9b4b0b8b3afb8b2aeb6afabb3aeaab2aeaa4878a14b7aa34c7ba44a759b3d63873b5f825b67766f5f569c7e6caf8c77b18f79b28f78b5927caf8e78a98872aa8a76a98a76ac917fada199b7b0acb9b3afbfb9b5c1bab6bdb6b2b8b3afbab5b1b9b4b0b6afabb7b1adb3ada9b3aeaab0aba8";
9
- const WIDTH = 32;
10
- const HEIGHT = 32;
11
- function parseImage() {
12
- const pixels = [];
13
- for (let y = 0; y < HEIGHT; y++) {
14
- const row = [];
15
- for (let x = 0; x < WIDTH; x++) {
16
- const idx = (y * WIDTH + x) * 6;
17
- const r = parseInt(DAX_HEX.slice(idx, idx + 2), 16);
18
- const g = parseInt(DAX_HEX.slice(idx + 2, idx + 4), 16);
19
- const b = parseInt(DAX_HEX.slice(idx + 4, idx + 6), 16);
20
- row.push([r, g, b]);
21
- }
22
- pixels.push(row);
23
- }
24
- return pixels;
25
- }
26
- function rgb(r, g, b, bg = false) {
27
- return `\x1b[${bg ? 48 : 38};2;${r};${g};${b}m`;
28
- }
29
- const RESET = "\x1b[0m";
30
- function buildImage() {
31
- const pixels = parseImage();
32
- const lines = [];
33
- // Use half-block chars: ▄ with bg=top pixel, fg=bottom pixel
34
- for (let row = 0; row < HEIGHT; row += 2) {
35
- let line = "";
36
- for (let x = 0; x < WIDTH; x++) {
37
- const top = pixels[row][x];
38
- const bottom = pixels[row + 1]?.[x] ?? top;
39
- line += `${rgb(bottom[0], bottom[1], bottom[2])}${rgb(top[0], top[1], top[2], true)}▄`;
40
- }
41
- line += RESET;
42
- lines.push(line);
43
- }
44
- return lines;
45
- }
46
- export class DaxnutsComponent {
47
- ui;
48
- image;
49
- interval = null;
50
- tick = 0;
51
- maxTicks = 25; // ~2 seconds at 80ms
52
- cachedLines = [];
53
- cachedWidth = 0;
54
- cachedTick = -1;
55
- constructor(ui) {
56
- this.ui = ui;
57
- this.image = buildImage();
58
- this.startAnimation();
59
- }
60
- invalidate() {
61
- this.cachedWidth = 0;
62
- }
63
- startAnimation() {
64
- this.interval = setInterval(() => {
65
- this.tick++;
66
- if (this.tick >= this.maxTicks) {
67
- this.stopAnimation();
68
- }
69
- this.cachedWidth = 0;
70
- this.ui.requestRender();
71
- }, 80);
72
- }
73
- stopAnimation() {
74
- if (this.interval) {
75
- clearInterval(this.interval);
76
- this.interval = null;
77
- }
78
- }
79
- render(width) {
80
- if (width === this.cachedWidth && this.cachedTick === this.tick) {
81
- return this.cachedLines;
82
- }
83
- const t = theme;
84
- const lines = [];
85
- const center = (s) => {
86
- const visible = s.replace(/\x1b\[[0-9;]*m/g, "").length;
87
- const left = Math.max(0, Math.floor((width - visible) / 2));
88
- return " ".repeat(left) + s;
89
- };
90
- lines.push("");
91
- // Scanline reveal effect: show rows progressively
92
- const revealedRows = Math.min(this.image.length, Math.floor((this.tick / this.maxTicks) * (this.image.length + 3)));
93
- for (let i = 0; i < this.image.length; i++) {
94
- if (i < revealedRows) {
95
- lines.push(center(this.image[i]));
96
- }
97
- else {
98
- // Show scan line
99
- if (i === revealedRows) {
100
- const scanline = "▓".repeat(WIDTH);
101
- lines.push(center(rgb(100, 200, 255) + scanline + RESET));
102
- }
103
- else {
104
- lines.push(center(" ".repeat(WIDTH)));
105
- }
106
- }
107
- }
108
- lines.push("");
109
- // Fade in text after image is revealed
110
- const textPhase = Math.max(0, this.tick - this.maxTicks * 0.6);
111
- if (textPhase > 0 || this.tick >= this.maxTicks) {
112
- lines.push(center(t.fg("accent", "Free Kimi K2.5 via OpenCode Zen")));
113
- lines.push(center(t.fg("success", '"Powered by daxnuts"')));
114
- lines.push(center(t.fg("muted", "— @thdxr")));
115
- }
116
- else {
117
- lines.push("");
118
- lines.push("");
119
- lines.push("");
120
- }
121
- lines.push("");
122
- if (textPhase > 2 || this.tick >= this.maxTicks) {
123
- lines.push(center(t.fg("dim", "Try OpenCode")));
124
- lines.push(center(t.fg("mdLink", "https://mistral.ai/news/mistral-vibe-2-0")));
125
- }
126
- else {
127
- lines.push("");
128
- lines.push("");
129
- }
130
- lines.push("");
131
- this.cachedLines = lines;
132
- this.cachedWidth = width;
133
- this.cachedTick = this.tick;
134
- return lines;
135
- }
136
- dispose() {
137
- this.stopAnimation();
138
- }
139
- }
140
- //# sourceMappingURL=daxnuts.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"daxnuts.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/daxnuts.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * POWERED BY DAXNUTS - Easter egg for OpenCode + Kimi K2.5\n *\n * A heartfelt tribute to dax (@thdxr) for providing free Kimi K2.5 access via OpenCode.\n */\n\nimport type { Component, TUI } from \"@earendil-works/pi-tui\";\nimport { theme } from \"../theme/theme.js\";\n\n// 32x32 RGB image of dax, hex encoded (3 bytes per pixel)\nconst DAX_HEX =\n\t\"bbbab8b9b9b6b9b8b5bcbbb8b8b7b4b7b5b2b6b5b2b8b7b4b7b6b3b6b4b1bdbcb8bab8b6bbb8b5b8b5b1bbb8b4c2bebbc1bebac0bdbabfbcb9c1bebabfbebbc0bfbcc0bdbabbb8b5c1bfbcbfbcb8bbb9b6bfbcb8c2bfbcc1bfbcbfbbb8bdb9b6b8b7b5b9b8b5b8b8b5b5b5b2b6b5b2b8b7b4b9b8b5b9b8b5b6b5b3bab8b5bcbab7bbb9b6bbb8b5bfb9b5bdb2abbcb0a8beb2aabeb5afbfbab6bebab7c0bfbcbebdbabebbb8c0bdbabfbebbc2bebbbdbab7c3c0bdc3c0bdc1bebbc2bebabfbcb8bab9b6b7b6b3b2b1aeb6b5b2b5b4b1b5b4b2b6b5b2b7b6b4b9b8b6b7b6b3bbbab7b2afaba5988fb49e90b09481b79a88b39683b09583b7a395bfb6b0c0bdbabdbbb8bebcb9c1bfbcc0bebbbdbab7bebbb8c2bfbcc0bdbac0bcb9bdb9b6c0bcb8b5b4b2b4b3b0bab9b6b9b9b6b5b4b1b5b4b1b6b5b3b9b8b5b9b8b6b9b8b6b2aeaa968174a6836eaa856eab846eaf8973ac8973b08f79b18f7ab39786b7a89dbbb3aebfbab6c2c0bdbebcb9bfbdbac3c1bdc2bebbc0bcb9bdb9b6c1bdbabfbbb8b4b3b0b9b8b5b8b7b5b4b3b1b5b4b1b8b7b4b8b7b5bab9b6bbbab7b1afad8c7a719d735ca47860a87d65a98069ae8972ae8c75af8d77aa826ba98067aa8974b39e90b6a79dbbb2adc0bdbac1bfbdbfbbb8c1bdb9bebab6c0bdb9bfbbb8c1bdbab4b2b0b7b6b4b7b6b3b4b2b0bab9b7b6b5b2b6b5b2bab9b6bab9b6958c87977663aa836bac8772b08f7aad8c77b2917db0917db0907cac8971a77d64a87f67ac8972b29887b8a89dbfbab5bfbdbac1bebac0bcb9c0bcb9c0bcb9c1bebabebab7b8b7b4b7b6b4b5b4b1b5b4b2b7b6b3b5b4b2bab9b7bab9b6b4b1ada88f7fad8973ae8d78b19684b19685b29786b69a89b29582b1917daa856ea87e66a97e66ad866ea9826baf9280b8ada6bdbbb8bebab7bfbbb8c1bdbabfbbb8bcb8b4bcb8b5b6b4b2b7b5b3b6b5b2b8b7b4b3b2afb8b7b4b6b5b2b3b2b0b3a59aab856fad8d78b0917eb19886b49b8bb49a89b39785b0917eaf8f7cab866fa77d65a77a61a87d64a9816ab08f79b5a296c1bcb8c3bfbcc2bebbbebab7bfbbb7bdbab6c2bebab8b7b4b7b6b4b6b5b3b7b6b3b6b5b2b9b8b6b4b3b1b6b1acac8f7ca9826bae8f7aaf9583b49c8cb49c8bb79d8cb59987b19380ad8e79ae8c77af8e78ac8771a3775faa826bae8972b39888bbb6b2bebbb8bfbbb8bfbbb8c0bdb9bebbb7c0bdb9b6b5b2b9b8b5b4b3b1b8b7b5b4b3b0b7b6b4b6b5b3b1a7a0aa8772a77d65a88570b49887b19b8d9c887c907a6d987f71aa907faf917daf8e7aad8c78ac8b77a8836ca9836cac8770b49b8abdb6b2c0bcb9c0bdb9bfbbb8bebab7bfbcb9bebab7b9b8b6b5b4b2b9b8b5b8b7b5b8b7b4b7b6b4b5b4b2b3a9a2ad8973a1755da9856fb398858c776a65544b776358725d526e594d9c7f6eb1907ba68672ad8e7aab8771ac856db18f79b3a092beb9b5c1bdbabdb9b5bebab7bfbbb7bebab7bcb9b6b7b6b4b6b6b3b8b7b4b5b4b2b8b6b4b7b6b3b4b3b0b4aba4a6826ba3775fb08e79b19584a88e7daa8e7db29481ad8f7c997e6da38674ac8d79ac8e7aae917f9a7c6a896a599a7c6ab3a398c1bdbabdb9b6bcb8b5bebab6bebab7bdb9b5bdb9b6b5b4b1b7b5b3b5b4b2b7b6b3b7b6b4b3b3b0b3b2b0b4aca5a7846fa97f68ae8f7bae9383b59c8bb2937fae8e79ac8b76af927eaf927eb29683b39885b2988891786a72594c6e594d978d86bdbab7bab7b3c0bcb9c0bcb9bebab7bebbb7bdb9b6b3b2b0b4b3b0b5b4b2b4b4b1b4b3b1b4b3b1b4b3b0b6ada5aa8670a57a62ad8e7ab29b8cb69d8dab856fa9826aa88069ab8771af907db49987b19684b29886b59987b39480b09787b5a9a1bcb8b5bebab7bdb9b5bebab7bfbbb8bfbbb7bbb7b4b3b2afb8b7b5b8b7b5b3b2b0b5b4b2b6b5b3b6b4b1afa299a98975a9826baf907cb39988b49a89af8e7aac8973aa856eaf8c74b1917dae907dac907db39988b29785b49785b7a090b9aca3bfbab7bcb8b5bdb9b6bcb8b4bcb8b5bdb9b5bcb8b4b5b4b2b6b5b3b4b3b0b4b3b0b9b8b5b8b6b4908b88887467aa8f7ea78976ad8973b08b74b59885b69e8eb29888b1917cb1917db1937fae907cb19686b39a8ab29886b59b8ab8a192b6aaa3b7b2afbcb8b4bcb8b5bbb7b4c0bcb9bebab7c0bcb9b6b5b2b6b5b3b4b3b0bab9b7b7b6b4b1b0ae7b716ba083709b806f716158967764b08870b29481b69b8ab69f8fb39a89b69f90b49d8db39a89b29988b49c8cb6a090b8a496baa49593867f8f8986bfbbb7bdb9b5bcb7b4bab6b3b9b5b2bab6b2b4b3b1b3b3b0b6b5b3b8b7b5b4b2b0a7a5a38f837dae917ea084725a504c63544da28370b39784b59e8db2a093a698909b918b998e8790857e95877dad998bb39c8cb5a091b9a2938d827c95908dbebab6bbb7b3bdbab7bbb7b4bdb9b6bbb7b4b4b3b0b5b4b1b8b7b5b6b5b3b8b8b5b4b2af968f8ab29a8bab9485544b483a323073655d96887f70655f61595547403e453e3c453f3d57504f655e5b90847db39c8db7a090b6a09189807aaba6a3bdb9b6c0bcb9bebab7bcb7b4bebab7bbb7b4b3b2b0b6b5b3b2b1afb7b6b4b8b7b4b5b4b1aeaba8b5a89fac998d4d44412d25244d46444e4744322b293a3230423937433a37352d2a59504c534b48524a48988a81b59f8fb19c8d827974b2afacbdb9b5bcb8b4bdb9b5bcb8b5bdb9b6bab6b2b8b7b5b5b4b2b6b6b3b9b8b5b7b6b3b6b5b2b8b6b3b9b4b1b2a9a26c64612d25242d2625312a28352d2c453d3a78675c8d7a6ea09792aea6a0615854332b29524a479f8e82b09d90a49b96c1bdb9bebab7bfbbb8bbb8b4b9b5b1b8b4b0b9b4b0b7b6b4b8b7b5b8b7b4b6b5b3b8b6b3bab9b6b9b8b5b4b3b0b7b5b2a5a29f453d3b261e1d261f1e2e2625413936857268977865b19482b5a69caca5a07c7572453d3b746963a0948cc5bfbbc0bbb8beb9b6bbb7b3bbb6b3b7b3afb8b4b0b9b5b1b7b6b3b6b5b3b5b4b2b5b4b2b7b6b3b7b6b3b8b6b3b4b2afb7b6b3b3b1ae6d6765251f1e1e18172a22212d2523443b3971625ab19888b09482a89182877e792c25243e3634766d6abeb9b5bfbbb7bebab6bcb7b3bbb6b3b9b5b1b7b3afb8b4b0b4b3b0b5b4b1b5b4b1b4b3b1b5b4b2b8b6b4b5b3b0b9b6b4b5b4b1b6b4b27f79762a2322221c1b2d2524221b1a443e3c47413f6f676281766f867971675e5a3e37352a222166605dbab7b3bdb9b5beb9b5bcb7b3bcb7b3b9b4b0bab6b2bab6b2b5b3b0b6b4b2b3b2afb7b6b3b4b4b1b4b3b0b6b4b1b5b4b1b4b3b0b9b6b29a8c8252474230292828201f181212322c2c231e1d1c16162c26252923222d26252d2523332b2a8e8885bcb8b5bcb7b3bbb6b2bcb7b3b9b4b1b9b5b1b7b2afb7b2ae7a838e9b9b9caeadacb3b2b0b3b2afb7b7b4b6b5b3b6b6b3b7b6b3b9ada4a991808e7b6f50453f2b24231a14142923221f19181d17161f18182620201d17162a22215d5654b7b3b0bbb7b3bbb6b2b8b4b0bab5b1bbb6b2bab5b1b8b4b0bab6b22c496b4c5d735f68766e727a828285929090adaba8b7b2aeb6a59ab39682a28470a387748e76674e403a1a14141d1716181211221c1c1f1918221c1b2f2827342d2c8d8884bab6b3b9b5b2bab5b1bab5b1b9b4b0bab6b2b8b4b0b9b4b0b7b2ae325e8b365f8a3a5d833f5b7a545f70646469706b6aa08f84b08e78b18e769f7e689e7f6b9e816d907766584940362d2a1c1615201b1a1a1413201a1a251e1d393331a39e9bbab5b1bcb7b3bab6b2b8b3afb8b4b0b9b4b0b9b4b1bab5b2b5b0ac3d6c9843729d44719c426e98415f805a64716f6a699d8677b1927eb3947faa89749d7a649f7f6ba487749e837186716454463f2c25231e181837302e3a33317a7471beb9b6bcb8b4bbb6b2b6b2aebab5b1b9b5b1b8b3afbab6b2b6b1adb5aeaa4877a14c7aa44e7ba345719a3a5d80586b7f767475927b6eb1927faf8e79b08e78a78169a07861a17f6aa58570a688749b83738270666f66618a8480a49e99b7b2aebab6b2bcb8b4b9b5b1b7b2aebab5b1b9b4b0b6b1aeb6b1adb2aca8b2aca84876a04a78a2517fa74771973a5d80405c7a6161677c695fac8a75b08d77b4917aaf8971ad876fa5816aa6846ea78670a98a76ac9484ab9f96b2aca8bdb8b4bcb7b3bcb8b4bcb8b4b8b3afb7b2aeb9b4b0b8b3afb8b2aeb6afabb3aeaab2aeaa4878a14b7aa34c7ba44a759b3d63873b5f825b67766f5f569c7e6caf8c77b18f79b28f78b5927caf8e78a98872aa8a76a98a76ac917fada199b7b0acb9b3afbfb9b5c1bab6bdb6b2b8b3afbab5b1b9b4b0b6afabb7b1adb3ada9b3aeaab0aba8\";\n\nconst WIDTH = 32;\nconst HEIGHT = 32;\n\nfunction parseImage(): number[][][] {\n\tconst pixels: number[][][] = [];\n\tfor (let y = 0; y < HEIGHT; y++) {\n\t\tconst row: number[][] = [];\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tconst idx = (y * WIDTH + x) * 6;\n\t\t\tconst r = parseInt(DAX_HEX.slice(idx, idx + 2), 16);\n\t\t\tconst g = parseInt(DAX_HEX.slice(idx + 2, idx + 4), 16);\n\t\t\tconst b = parseInt(DAX_HEX.slice(idx + 4, idx + 6), 16);\n\t\t\trow.push([r, g, b]);\n\t\t}\n\t\tpixels.push(row);\n\t}\n\treturn pixels;\n}\n\nfunction rgb(r: number, g: number, b: number, bg = false): string {\n\treturn `\\x1b[${bg ? 48 : 38};2;${r};${g};${b}m`;\n}\n\nconst RESET = \"\\x1b[0m\";\n\nfunction buildImage(): string[] {\n\tconst pixels = parseImage();\n\tconst lines: string[] = [];\n\n\t// Use half-block chars: ▄ with bg=top pixel, fg=bottom pixel\n\tfor (let row = 0; row < HEIGHT; row += 2) {\n\t\tlet line = \"\";\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tconst top = pixels[row][x];\n\t\t\tconst bottom = pixels[row + 1]?.[x] ?? top;\n\t\t\tline += `${rgb(bottom[0], bottom[1], bottom[2])}${rgb(top[0], top[1], top[2], true)}▄`;\n\t\t}\n\t\tline += RESET;\n\t\tlines.push(line);\n\t}\n\treturn lines;\n}\n\nexport class DaxnutsComponent implements Component {\n\tprivate ui: TUI;\n\tprivate image: string[];\n\tprivate interval: ReturnType<typeof setInterval> | null = null;\n\tprivate tick = 0;\n\tprivate maxTicks = 25; // ~2 seconds at 80ms\n\tprivate cachedLines: string[] = [];\n\tprivate cachedWidth = 0;\n\tprivate cachedTick = -1;\n\n\tconstructor(ui: TUI) {\n\t\tthis.ui = ui;\n\t\tthis.image = buildImage();\n\t\tthis.startAnimation();\n\t}\n\n\tinvalidate(): void {\n\t\tthis.cachedWidth = 0;\n\t}\n\n\tprivate startAnimation(): void {\n\t\tthis.interval = setInterval(() => {\n\t\t\tthis.tick++;\n\t\t\tif (this.tick >= this.maxTicks) {\n\t\t\t\tthis.stopAnimation();\n\t\t\t}\n\t\t\tthis.cachedWidth = 0;\n\t\t\tthis.ui.requestRender();\n\t\t}, 80);\n\t}\n\n\tprivate stopAnimation(): void {\n\t\tif (this.interval) {\n\t\t\tclearInterval(this.interval);\n\t\t\tthis.interval = null;\n\t\t}\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width === this.cachedWidth && this.cachedTick === this.tick) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\tconst t = theme;\n\t\tconst lines: string[] = [];\n\n\t\tconst center = (s: string) => {\n\t\t\tconst visible = s.replace(/\\x1b\\[[0-9;]*m/g, \"\").length;\n\t\t\tconst left = Math.max(0, Math.floor((width - visible) / 2));\n\t\t\treturn \" \".repeat(left) + s;\n\t\t};\n\n\t\tlines.push(\"\");\n\n\t\t// Scanline reveal effect: show rows progressively\n\t\tconst revealedRows = Math.min(\n\t\t\tthis.image.length,\n\t\t\tMath.floor((this.tick / this.maxTicks) * (this.image.length + 3)),\n\t\t);\n\n\t\tfor (let i = 0; i < this.image.length; i++) {\n\t\t\tif (i < revealedRows) {\n\t\t\t\tlines.push(center(this.image[i]));\n\t\t\t} else {\n\t\t\t\t// Show scan line\n\t\t\t\tif (i === revealedRows) {\n\t\t\t\t\tconst scanline = \"▓\".repeat(WIDTH);\n\t\t\t\t\tlines.push(center(rgb(100, 200, 255) + scanline + RESET));\n\t\t\t\t} else {\n\t\t\t\t\tlines.push(center(\" \".repeat(WIDTH)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlines.push(\"\");\n\n\t\t// Fade in text after image is revealed\n\t\tconst textPhase = Math.max(0, this.tick - this.maxTicks * 0.6);\n\t\tif (textPhase > 0 || this.tick >= this.maxTicks) {\n\t\t\tlines.push(center(t.fg(\"accent\", \"Free Kimi K2.5 via OpenCode Zen\")));\n\t\t\tlines.push(center(t.fg(\"success\", '\"Powered by daxnuts\"')));\n\t\t\tlines.push(center(t.fg(\"muted\", \"— @thdxr\")));\n\t\t} else {\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\"\");\n\t\t}\n\n\t\tlines.push(\"\");\n\t\tif (textPhase > 2 || this.tick >= this.maxTicks) {\n\t\t\tlines.push(center(t.fg(\"dim\", \"Try OpenCode\")));\n\t\t\tlines.push(center(t.fg(\"mdLink\", \"https://mistral.ai/news/mistral-vibe-2-0\")));\n\t\t} else {\n\t\t\tlines.push(\"\");\n\t\t\tlines.push(\"\");\n\t\t}\n\t\tlines.push(\"\");\n\n\t\tthis.cachedLines = lines;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedTick = this.tick;\n\t\treturn lines;\n\t}\n\n\tdispose(): void {\n\t\tthis.stopAnimation();\n\t}\n}\n"]}