@inneranimalmedia/agentsam-sdk 2.4.1 → 2.5.0

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 (158) hide show
  1. package/README.md +7 -6
  2. package/docs/AGENTSAM_WORKBENCH.md +30 -0
  3. package/docs/AUTH_IDENTITY_CONTRACT.md +52 -0
  4. package/docs/CAPABILITIES.md +5 -3
  5. package/docs/CLI_SHELL.md +57 -80
  6. package/docs/CMS_STUDIO.md +101 -0
  7. package/docs/CONTEXT.md +170 -0
  8. package/docs/LOCAL_OLLAMA.md +58 -0
  9. package/docs/MERKLE.md +19 -19
  10. package/docs/PORTABLE_CONTEXT.md +4 -3
  11. package/docs/PROJECT_CONFIG.md +72 -0
  12. package/docs/RELEASES.md +26 -2
  13. package/docs/REPOSITORY_INTELLIGENCE.md +1 -1
  14. package/docs/REPOSITORY_KNOWLEDGE.md +114 -0
  15. package/docs/SDK_WORKER.md +86 -0
  16. package/docs/SECURITY.md +59 -22
  17. package/docs/client-cms-editor.md +15 -0
  18. package/docs/local-studio/WORKMODE_DONOR_NOTES.md +485 -0
  19. package/package.json +17 -4
  20. package/packages/identity/package.json +11 -2
  21. package/packages/identity/src/contracts/auth-config.js +98 -0
  22. package/packages/identity/src/index.js +1 -0
  23. package/packages/identity/src/oauth/README.md +2 -2
  24. package/packages/identity/src/oauth/credentials.js +11 -4
  25. package/packages/identity/src/oauth/iam-platform.js +3 -3
  26. package/packages/identity/src/providers/iam/index.js +7 -7
  27. package/packages/identity/src/providers/iam/oauth.js +6 -4
  28. package/packages/identity/src/providers/iam/profile.js +5 -5
  29. package/packages/identity/tests/auth-config.test.mjs +57 -0
  30. package/packages/identity/tests/oauth-credentials.test.mjs +13 -2
  31. package/protocol/FILEMETA_V1.md +95 -0
  32. package/protocol/INSPECT_VIEWS_V1.md +40 -0
  33. package/protocol/MERKLE_PERSISTENCE_V1.md +50 -0
  34. package/protocol/MERKLE_V1.md +3 -1
  35. package/protocol/capabilities/manifest.json +32 -3
  36. package/protocol/capabilities/repository-snapshot.schema.json +1 -0
  37. package/protocol/context/context-budget.schema.json +41 -0
  38. package/protocol/context/context-item.schema.json +20 -0
  39. package/protocol/context/resolved-context-pack.schema.json +42 -0
  40. package/protocol/context/result-policy.schema.json +17 -0
  41. package/protocol/knowledge/context-pack.schema.json +33 -0
  42. package/protocol/knowledge/retrieval-query.schema.json +68 -13
  43. package/python/README.md +15 -7
  44. package/python/agentsam_sdk/cli.py +0 -21
  45. package/python/agentsam_sdk/tui/README.md +17 -12
  46. package/python/agentsam_sdk/tui/bootstrap.py +2 -2
  47. package/python/agentsam_sdk/tui/demo.py +25 -10
  48. package/python/agentsam_sdk/tui/onboarding.py +208 -0
  49. package/python/tests/test_tui_cli.py +7 -6
  50. package/skills/README.md +21 -0
  51. package/skills/agentsam-app-fundamentals/SKILL.md +165 -0
  52. package/skills/agentsam-app-fundamentals/references/graphs-contracts-ast-merkle.md +89 -0
  53. package/skills/agentsam-app-fundamentals/references/trust-credentials-and-destinations.md +99 -0
  54. package/skills/agentsam-jr-dev/SKILL.md +232 -0
  55. package/skills/agentsam-jr-dev/references/real-application-logic.md +156 -0
  56. package/skills/agentsam-jr-dev/references/web-application-fundamentals.md +240 -0
  57. package/skills/agentsam-progression-guard/SKILL.md +197 -0
  58. package/skills/agentsam-progression-guard/references/checkpoint-chain.md +111 -0
  59. package/skills/agentsam-progression-guard/references/hooks-operational-io.md +96 -0
  60. package/skills/catalog.json +53 -0
  61. package/src/capabilities/index.js +7 -0
  62. package/src/capabilities/repository-snapshot-view.js +238 -0
  63. package/src/capabilities/repository-snapshot.js +28 -14
  64. package/src/cli.js +108 -56
  65. package/src/commands/context.js +14 -2
  66. package/src/commands/db.js +4 -7
  67. package/src/commands/deploy.js +17 -31
  68. package/src/commands/interactive.js +21 -0
  69. package/src/commands/knowledge.js +27 -4
  70. package/src/commands/merkle-persist.js +118 -0
  71. package/src/commands/merkle.js +32 -17
  72. package/src/commands/models.js +107 -0
  73. package/src/commands/ollama.js +259 -0
  74. package/src/commands/preferences.js +102 -0
  75. package/src/commands/product.js +86 -16
  76. package/src/commands/security.js +3 -3
  77. package/src/commands/shell.js +71 -27
  78. package/src/commands/skills.js +66 -0
  79. package/src/commands/start-local.js +1 -1
  80. package/src/commands/tunnel.js +5 -4
  81. package/src/context/budget.js +58 -0
  82. package/src/context/compact.js +28 -0
  83. package/src/context/index.js +5 -0
  84. package/src/context/resolve.js +84 -0
  85. package/src/context/result-policy.js +66 -0
  86. package/src/index.js +16 -0
  87. package/src/indexing/execution-boundary.js +144 -0
  88. package/src/indexing/index.js +8 -0
  89. package/src/indexing/provider.js +41 -0
  90. package/src/knowledge/config.js +2 -2
  91. package/src/knowledge/context-pack.js +12 -1
  92. package/src/knowledge/contracts.js +9 -4
  93. package/src/knowledge/engine.js +7 -3
  94. package/src/knowledge/service/server.js +1 -1
  95. package/src/lib/bridge-client.js +7 -5
  96. package/src/lib/cli-preferences.js +74 -0
  97. package/src/lib/core-client.js +8 -8
  98. package/src/lib/deploy-receipt/index.js +5 -2
  99. package/src/lib/detect-context.js +6 -5
  100. package/src/lib/identity-scaffold.js +1 -1
  101. package/src/lib/local-scaffold.js +35 -33
  102. package/src/lib/local-status.js +9 -17
  103. package/src/lib/merkle/cloudflare-persistence.js +321 -0
  104. package/src/lib/merkle/filemeta.js +43 -0
  105. package/src/lib/merkle/git-ignore.js +24 -0
  106. package/src/lib/merkle/hash.js +1 -0
  107. package/src/lib/merkle/index.js +22 -0
  108. package/src/lib/merkle/persistence.js +72 -0
  109. package/src/lib/merkle/semantic.js +359 -0
  110. package/src/lib/merkle/snapshot.js +9 -3
  111. package/src/lib/merkle/tree.js +11 -6
  112. package/src/lib/project-config.js +227 -0
  113. package/src/lib/project-rules.js +68 -0
  114. package/src/lib/save-sdk-token.js +1 -1
  115. package/src/lib/slash-commands.js +2 -1
  116. package/src/lib/tools.js +11 -5
  117. package/src/security/index.js +1 -0
  118. package/src/security/inventory.js +4 -1
  119. package/src/security/render.js +27 -5
  120. package/src/security/scan.js +24 -9
  121. package/src/security/trust-boundary.js +24 -0
  122. package/src/skills/index.js +64 -0
  123. package/src/tools/index.js +1 -0
  124. package/src/tools/search.js +70 -0
  125. package/src/ui/ansi.js +1 -1
  126. package/src/ui/boot.js +56 -0
  127. package/src/ui/merkle/render.js +1 -0
  128. package/src/ui/runtime-activity.js +192 -0
  129. package/src/ui/theme.js +19 -18
  130. package/test/app-building-skills.test.mjs +61 -0
  131. package/test/apps-scaffold-contract.test.mjs +56 -0
  132. package/test/capabilities.test.mjs +53 -4
  133. package/test/cli-preferences.test.mjs +25 -0
  134. package/test/context.test.mjs +95 -0
  135. package/test/indexing-provider.test.mjs +29 -0
  136. package/test/jr-dev-skill.test.mjs +26 -0
  137. package/test/knowledge-context-pack.test.mjs +19 -0
  138. package/test/knowledge.test.mjs +1 -1
  139. package/test/merkle-persistence.test.mjs +91 -0
  140. package/test/merkle.test.mjs +77 -3
  141. package/test/models.test.mjs +37 -0
  142. package/test/ollama.test.mjs +94 -0
  143. package/test/project-config.test.mjs +81 -0
  144. package/test/project-rules.test.mjs +44 -0
  145. package/test/release-hygiene.test.mjs +34 -0
  146. package/test/repository-snapshot-view.test.mjs +112 -0
  147. package/test/runtime-activity.test.mjs +98 -0
  148. package/test/sdk-worker-contract.test.mjs +68 -0
  149. package/test/security.test.mjs +46 -0
  150. package/test/shell.test.mjs +8 -1
  151. package/test/skills.test.mjs +22 -0
  152. package/test/smoke.mjs +2 -2
  153. package/test/theme-portability.test.mjs +14 -0
  154. package/test/tools-search.test.mjs +27 -0
  155. package/examples/agentsam-tui-ansi.mjs +0 -149
  156. package/src/commands/tui.js +0 -120
  157. package/src/ui/splash-xterm.js +0 -290
  158. package/src/ui/splash.js +0 -426
package/src/ui/splash.js DELETED
@@ -1,426 +0,0 @@
1
- /**
2
- * @file src/ui/splash.js
3
- * @description Cinematic intro sequence for `agentsam shell` and `agentsam init`.
4
- *
5
- * Choreography (cold start, ~1.25s total):
6
- * 0ms — black void
7
- * 60ms — cd ~/inneranimalmedia flashes then erases (verb, not description)
8
- * 200ms — gorilla renders row by row (28ms/row)
9
- * 600ms — title border + INNERANIMAL MEDIA letter by letter
10
- * 750ms — stone ledge draws L→R
11
- * 820ms — ladder rungs appear
12
- * 900ms — "Start ▸" in amber
13
- * 950ms — HUD bar appears (all 4 items: checking...)
14
- * 950ms — probes fire in parallel
15
- * 1250ms — HUD updates in-place with real status
16
- * 1300ms — prompt cursor appears
17
- *
18
- * Usage:
19
- * import { runSplash } from './ui/splash.js';
20
- * const status = await runSplash({ apiBase, workspaceId, authToken, lane });
21
- * // returns { workspace, runtime, tunnel, agent }
22
- */
23
-
24
- import { PALETTE, getLaneTheme } from './theme.js';
25
-
26
- // ─────────────────────────────────────────────────────────────────────────────
27
- // ANSI primitives
28
- // ─────────────────────────────────────────────────────────────────────────────
29
-
30
- const ESC = '\x1b';
31
- const CSI = `${ESC}[`;
32
-
33
- const A = {
34
- reset: `${CSI}0m`,
35
- bold: `${CSI}1m`,
36
- dim: `${CSI}2m`,
37
- hide: `${CSI}?25l`,
38
- show: `${CSI}?25h`,
39
- clear: `${CSI}2J${CSI}H`,
40
- clearLine: `${CSI}2K\r`,
41
- up: (n = 1) => `${CSI}${n}A`,
42
- fg: (hex) => {
43
- const h = hex.replace('#', '');
44
- const r = parseInt(h.slice(0, 2), 16);
45
- const g = parseInt(h.slice(2, 4), 16);
46
- const b = parseInt(h.slice(4, 6), 16);
47
- return `${CSI}38;2;${r};${g};${b}m`;
48
- },
49
- };
50
-
51
- const w = (s) => process.stdout.write(s);
52
- const wln = (s = '') => process.stdout.write(s + '\n');
53
- const sleep = (ms) => new Promise(r => setTimeout(r, ms));
54
-
55
- // ─────────────────────────────────────────────────────────────────────────────
56
- // COLOR SHORTCUTS
57
- // ─────────────────────────────────────────────────────────────────────────────
58
-
59
- const TEAL = A.fg(PALETTE.teal300);
60
- const AMBER = A.fg(PALETTE.amber300);
61
- const AMBER2 = A.fg(PALETTE.amber200);
62
- const STONE = A.fg('#3a3530');
63
- const STONE2 = A.fg('#2a2520');
64
- const VINE = A.fg('#1a4a2a');
65
- const VINE2 = A.fg('#0f6b3a');
66
- const FIRE1 = A.fg('#f97316');
67
- const FIRE2 = A.fg('#ef4444');
68
- const FIREY = A.fg('#fef08a');
69
- const GRILL = A.fg('#1e2830');
70
- const GRILL2 = A.fg('#2d3d4a');
71
- const PELT = A.fg('#8b6f5a');
72
- const DIM = A.fg('#444444');
73
- const GHOST = A.fg('#888888');
74
- const WHT = A.fg('#e2e8f0');
75
- const R = A.reset;
76
- const B = A.bold;
77
-
78
- // ─────────────────────────────────────────────────────────────────────────────
79
- // GORILLA ART — 12 rows, pre-colored
80
- // ─────────────────────────────────────────────────────────────────────────────
81
-
82
- const GORILLA_ROWS = [
83
- ` ${DIM}░░▒${R}${GRILL2}▓▓▓▓▓▓▓▓${R}${DIM}▒░░${R}`,
84
- ` ${DIM}░${R}${GRILL2}▒▓▓${R}${GRILL}█████████████${R}${GRILL2}▓▓▒${R}${DIM}░${R}`,
85
- ` ${GRILL2}▒▓${R}${GRILL}███${R}${GRILL2}▒▒${R}${GRILL}████████${R}${GRILL2}▒▒${R}${GRILL}███${R}${GRILL2}▓▒${R}`,
86
- ` ${GRILL2}▓${R}${GRILL}████${R} ${DIM}▒▒▒▒▒▒▒▒${R} ${GRILL}████${R}${GRILL2}▓${R}`,
87
- ` ${GRILL}▓███${R}${GRILL2}▒${R} ${PELT}██${R}${DIM}▒${R}${PELT}████${R}${DIM}▒${R}${PELT}██${R} ${GRILL2}▒${R}${GRILL}███▓${R}`,
88
- ` ${GRILL}████${R} ${PELT}███${R}${DIM}▒▒▒▒${R}${PELT}███${R} ${GRILL}████${R}`,
89
- ` ${GRILL}████${R}${GRILL2}▒${R} ${PELT}██████████${R} ${GRILL2}▒${R}${GRILL}████${R}`,
90
- ` ${GRILL}████${R} ${DIM}▒▒▒▒▒▒▒▒▒▒${R} ${GRILL}████${R}`,
91
- ` ${GRILL2}▒${R}${GRILL}████${R}${GRILL2}▓▓▓${R}${GRILL}████████████${R}${GRILL2}▓▓▓${R}${GRILL}████${R}${GRILL2}▒${R}`,
92
- ` ${GRILL}██████████████████████████${R}`,
93
- ` ${DIM}▒▒${R}${GRILL}████████${R}${GRILL2}▒▒▒▒▒▒▒▒▒▒▒▒${R}${GRILL}████████${R}${DIM}▒▒${R}`,
94
- ` ${PELT}▓${R}${GRILL}██████████${R}${DIM}░░░░░░░░░░░░░░${R}${GRILL}██████████${R}${PELT}▓${R}`,
95
- ];
96
-
97
- // ─────────────────────────────────────────────────────────────────────────────
98
- // TITLE BOX
99
- // ─────────────────────────────────────────────────────────────────────────────
100
-
101
- function titleBoxLines() {
102
- const wide = 26;
103
- const h = `${TEAL}═${R}`;
104
- return [
105
- `${TEAL}╔${R}${h.repeat(wide)}${TEAL}╗${R}`,
106
- `${TEAL}║${R} ${B}${AMBER}INNERANIMAL MEDIA${R} ${TEAL}║${R}`,
107
- `${TEAL}║${R} ${TEAL}inneranimalmedia.com${R} ${TEAL}║${R}`,
108
- `${TEAL}╚${R}${h.repeat(wide)}${TEAL}╝${R}`,
109
- ];
110
- }
111
-
112
- const LADDER_ROWS = [
113
- ` ${TEAL}║${R} ${TEAL}║${R}`,
114
- ` ${TEAL}╠═══╣${R}`,
115
- ` ${TEAL}║${R} ${TEAL}║${R}`,
116
- ` ${TEAL}╠═══╣${R}`,
117
- ` ${TEAL}║${R} ${TEAL}║${R}`,
118
- ` ${TEAL}╠═══╣${R}`,
119
- ` ${TEAL}║${R} ${TEAL}║${R}`,
120
- ];
121
-
122
- // ─────────────────────────────────────────────────────────────────────────────
123
- // HUD RENDER
124
- // ─────────────────────────────────────────────────────────────────────────────
125
-
126
- const HUD_ITEMS = [
127
- { key: 'workspace', icon: '⊞', label: 'Workspace' },
128
- { key: 'runtime', icon: '▣', label: 'Runtime' },
129
- { key: 'tunnel', icon: '⟁', label: 'Tunnel' },
130
- { key: 'agent', icon: '⬡', label: 'Agent' },
131
- ];
132
-
133
- const READY_LABELS = {
134
- workspace: 'active',
135
- runtime: 'ready',
136
- tunnel: 'connected',
137
- agent: 'online',
138
- };
139
-
140
- export function renderHUDLine(states) {
141
- return HUD_ITEMS.map((item, i) => {
142
- const state = states[item.key] || 'checking';
143
- let stateStr;
144
- if (state === 'ready') {
145
- stateStr = `${TEAL}● ${READY_LABELS[item.key]}${R}`;
146
- } else if (state === 'checking') {
147
- stateStr = `${GHOST}◌ checking...${R}`;
148
- } else if (state === 'error') {
149
- stateStr = `${A.fg('#ef4444')}✗ error${R}`;
150
- } else {
151
- stateStr = `${A.fg('#666666')}○ offline${R}`;
152
- }
153
- const div = i < HUD_ITEMS.length - 1 ? ` ${DIM}│${R} ` : '';
154
- return `${GHOST}${item.icon}${R} ${B}${WHT}${item.label}${R} ${stateStr}${div}`;
155
- }).join('');
156
- }
157
-
158
- // ─────────────────────────────────────────────────────────────────────────────
159
- // STATUS PROBES
160
- // Fire in parallel — each returns 'ready' | 'error' | 'offline'
161
- // ─────────────────────────────────────────────────────────────────────────────
162
-
163
- export async function probeAll({ apiBase = '', workspaceId = '', authToken = '' } = {}) {
164
- const headers = {
165
- 'Content-Type': 'application/json',
166
- ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),
167
- ...(workspaceId ? { 'x-iam-workspace-id': workspaceId } : {}),
168
- };
169
-
170
- const timeout = (ms) => new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), ms));
171
- const safe = async (fn) => { try { return await Promise.race([fn(), timeout(2500)]); } catch { return 'offline'; } };
172
-
173
- const [workspace, runtime, tunnel, agent] = await Promise.all([
174
- safe(async () => {
175
- const r = await fetch(`${apiBase}/api/agent/session`, { headers });
176
- return r.ok ? 'ready' : 'error';
177
- }),
178
- safe(async () => {
179
- const r = await fetch(`${apiBase}/api/terminal/connections/targets`, { headers });
180
- if (!r.ok) return 'offline';
181
- const data = await r.json();
182
- const cloud = data.targets?.find(t => t.target_type === 'platform_vm');
183
- return cloud?.healthy ? 'ready' : 'offline';
184
- }),
185
- safe(async () => {
186
- const r = await fetch(`${apiBase}/api/terminal/connections/targets`, { headers });
187
- if (!r.ok) return 'offline';
188
- const data = await r.json();
189
- const local = data.targets?.find(t => t.target_type === 'user_hosted_tunnel');
190
- return local?.healthy ? 'ready' : 'offline';
191
- }),
192
- safe(async () => {
193
- const r = await fetch(`${apiBase}/api/agent/terminal/config-status`, { headers });
194
- if (!r.ok) return 'offline';
195
- const data = await r.json();
196
- return data.can_run_pty ? 'ready' : 'offline';
197
- }),
198
- ]);
199
-
200
- return { workspace, runtime, tunnel, agent };
201
- }
202
-
203
- // ─────────────────────────────────────────────────────────────────────────────
204
- // SPINNER
205
- // ─────────────────────────────────────────────────────────────────────────────
206
-
207
- const SPINNER_FRAMES = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];
208
-
209
- export function createSpinner(initialLabel = '', lane = 'cloud') {
210
- const laneTheme = getLaneTheme(
211
- lane === 'local' ? 'user_hosted_tunnel' :
212
- lane === 'sandbox' ? 'sandbox' : 'platform_vm'
213
- );
214
- const PRIMARY = A.fg(laneTheme.colors.primary);
215
- let label = initialLabel;
216
- let tick = 0;
217
- let running = true;
218
- w(A.hide);
219
- const interval = setInterval(() => {
220
- if (!running) return;
221
- const frame = SPINNER_FRAMES[tick % SPINNER_FRAMES.length];
222
- w(`\r ${PRIMARY}${frame}${R} ${GHOST}${label}${R}${A.clearLine.slice(1)}`);
223
- tick++;
224
- }, 80);
225
- return {
226
- update: (l) => { label = l; },
227
- succeed: (l = label) => {
228
- running = false; clearInterval(interval);
229
- wln(`\r ${TEAL}✓${R} ${WHT}${l}${R}${A.clearLine.slice(1)}`);
230
- w(A.show);
231
- },
232
- fail: (l = label) => {
233
- running = false; clearInterval(interval);
234
- wln(`\r ${A.fg('#ef4444')}✗${R} ${WHT}${l}${R}${A.clearLine.slice(1)}`);
235
- w(A.show);
236
- },
237
- stop: () => {
238
- running = false; clearInterval(interval);
239
- w(`\r${A.clearLine}`); w(A.show);
240
- },
241
- };
242
- }
243
-
244
- // ─────────────────────────────────────────────────────────────────────────────
245
- // SLASH REGISTRY PRINT
246
- // ─────────────────────────────────────────────────────────────────────────────
247
-
248
- export function printSlashRegistry(commands, lane = 'cloud') {
249
- const laneTheme = getLaneTheme(
250
- lane === 'local' ? 'user_hosted_tunnel' :
251
- lane === 'sandbox' ? 'sandbox' : 'platform_vm'
252
- );
253
- const PRIMARY = A.fg(laneTheme.colors.primary);
254
- const W = process.stdout.columns || 80;
255
- wln();
256
- wln(` ${DIM}${'─'.repeat(W - 4)}${R}`);
257
- wln(` ${GHOST}Slash commands${R}`);
258
- wln();
259
- for (const { cmd, description } of commands) {
260
- wln(` ${B}${PRIMARY}${cmd.padEnd(18)}${R}${GHOST}${description}${R}`);
261
- }
262
- wln();
263
- wln(` ${DIM}${'─'.repeat(W - 4)}${R}`);
264
- wln();
265
- }
266
-
267
- // ─────────────────────────────────────────────────────────────────────────────
268
- // MAIN SPLASH
269
- // ─────────────────────────────────────────────────────────────────────────────
270
-
271
- /**
272
- * Run the full cinematic splash.
273
- * @param {object} opts
274
- * @param {string} opts.apiBase
275
- * @param {string} opts.workspaceId
276
- * @param {string} opts.authToken
277
- * @param {boolean} opts.skipArt — skip gorilla on repeat sessions
278
- * @param {string} opts.lane — 'cloud'|'local'|'sandbox'
279
- * @param {number} opts.cols
280
- * @returns {Promise<{workspace, runtime, tunnel, agent}>}
281
- */
282
- export async function runSplash({
283
- apiBase = '',
284
- workspaceId = '',
285
- authToken = '',
286
- skipArt = false,
287
- lane = 'cloud',
288
- cols,
289
- } = {}) {
290
-
291
- const W = cols || process.stdout.columns || 80;
292
- const laneTheme = getLaneTheme(
293
- lane === 'local' ? 'user_hosted_tunnel' :
294
- lane === 'sandbox' ? 'sandbox' : 'platform_vm'
295
- );
296
- const PRIMARY = A.fg(laneTheme.colors.primary);
297
-
298
- w(A.hide);
299
-
300
- try {
301
- w(A.clear);
302
- await sleep(60);
303
-
304
- // cd verb flash — shows the command, then erases it
305
- w(` ${GHOST}$ ${R}${AMBER}cd ~/inneranimalmedia${R}`);
306
- await sleep(340);
307
- w(`\r${A.clearLine}`);
308
- await sleep(60);
309
-
310
- if (!skipArt) {
311
- wln();
312
-
313
- const title = titleBoxLines();
314
- const TITLE_START = 3;
315
-
316
- for (let i = 0; i < GORILLA_ROWS.length; i++) {
317
- const titleIdx = i - TITLE_START;
318
- const titlePart = (titleIdx >= 0 && titleIdx < title.length)
319
- ? ' ' + title[titleIdx]
320
- : '';
321
- wln(` ${GORILLA_ROWS[i]}${titlePart}`);
322
- await sleep(26);
323
- }
324
-
325
- wln();
326
-
327
- // Torches
328
- w(` ${FIRE1} ▓▓▓${R}`);
329
- await sleep(90);
330
- wln(`${' '.repeat(Math.max(0, W - 14))}${FIRE2}▓▓▓${R}`);
331
- await sleep(30);
332
-
333
- // Ledge L→R
334
- w(' ');
335
- for (let i = 0; i < W - 4; i++) {
336
- w((i % 2 === 0) ? `${STONE}█${R}` : `${STONE2}▓${R}`);
337
- await sleep(4);
338
- }
339
- wln();
340
- wln(` ${DIM}${'╌'.repeat(W - 4)}${R}`);
341
- await sleep(50);
342
-
343
- // Ladder
344
- for (const rung of LADDER_ROWS) {
345
- wln(rung);
346
- await sleep(32);
347
- }
348
- }
349
-
350
- wln();
351
-
352
- // Start prompt
353
- await sleep(skipArt ? 0 : 70);
354
- wln(` ${B}${AMBER}Start ${PRIMARY}▸${R}`);
355
- await sleep(40);
356
- wln(` ${GHOST}Type a command to begin.${R}`);
357
- await sleep(skipArt ? 0 : 70);
358
- wln();
359
-
360
- // HUD — fire probes in parallel
361
- const probePromise = probeAll({ apiBase, workspaceId, authToken });
362
- const initStates = { workspace: 'checking', runtime: 'checking', tunnel: 'checking', agent: 'checking' };
363
-
364
- wln(` ${DIM}${'─'.repeat(W - 4)}${R}`);
365
- wln();
366
- w(` ${renderHUDLine(initStates)}`);
367
- wln(); wln();
368
- wln(` ${DIM}${'─'.repeat(W - 4)}${R}`);
369
- wln();
370
-
371
- // Update HUD when probes resolve
372
- const LINES_BELOW = 4;
373
- const resolvedStates = await probePromise;
374
- w(A.up(LINES_BELOW));
375
- w(`\r${A.clearLine}`);
376
- w(` ${renderHUDLine(resolvedStates)}`);
377
- w('\n'.repeat(LINES_BELOW));
378
-
379
- await sleep(80);
380
- w(` ${PRIMARY}>${R} `);
381
- w(A.show);
382
-
383
- return resolvedStates;
384
-
385
- } catch (err) {
386
- w(A.show);
387
- throw err;
388
- }
389
- }
390
-
391
- // ─────────────────────────────────────────────────────────────────────────────
392
- // COMPACT HEADER (repeat sessions)
393
- // ─────────────────────────────────────────────────────────────────────────────
394
-
395
- export async function runCompactHeader({ apiBase, workspaceId, authToken, lane = 'cloud' } = {}) {
396
- const laneTheme = getLaneTheme(
397
- lane === 'local' ? 'user_hosted_tunnel' :
398
- lane === 'sandbox' ? 'sandbox' : 'platform_vm'
399
- );
400
- const PRIMARY = A.fg(laneTheme.colors.primary);
401
- const W = process.stdout.columns || 80;
402
-
403
- w(A.hide);
404
- w(A.clear);
405
-
406
- wln(` ${B}${PRIMARY}${laneTheme.meta.icon} Agent Sam${R} ${GHOST}${laneTheme.meta.label.toUpperCase()}${R} ${DIM}${laneTheme.meta.tunnelHint}${R}`);
407
- wln(` ${DIM}${'─'.repeat(W - 4)}${R}`);
408
- wln();
409
-
410
- const probePromise = probeAll({ apiBase, workspaceId, authToken });
411
- const init = { workspace: 'checking', runtime: 'checking', tunnel: 'checking', agent: 'checking' };
412
- w(` ${renderHUDLine(init)}`);
413
- wln(); wln();
414
-
415
- const resolved = await probePromise;
416
- w(A.up(2));
417
- w(`\r${A.clearLine}`);
418
- w(` ${renderHUDLine(resolved)}`);
419
- w('\n'.repeat(2));
420
-
421
- w(A.show);
422
- w(` ${PRIMARY}>${R} `);
423
- return resolved;
424
- }
425
-
426
- export default { runSplash, runCompactHeader, printSlashRegistry, createSpinner, probeAll, renderHUDLine };