@inneranimalmedia/agentsam-sdk 1.1.1 → 1.2.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.
package/DEVELOPMENT.md CHANGED
@@ -51,5 +51,8 @@ npx agentsam init \
51
51
  ## Known gaps (roadmap)
52
52
 
53
53
  - `agentsam deploy`, `status`, `logs` — not implemented yet
54
- - CMS lane in READMECLI has 4 lanes today (Full Stack, Data, CRM, Creative)
54
+ - Gorilla Shell Phase 1PTY WebSocket bridge to ExecOS
55
+ - CMS lane in README — CLI has 5 lanes (Full Stack, CMS, Data, CRM, Creative)
55
56
  - Published API route may differ; stub mode works without `AGENTSAM_API_KEY`
57
+
58
+ See [docs/CLI_SHELL.md](./docs/CLI_SHELL.md) for the game-feel terminal UX path.
package/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Agent Sam is a full-stack autonomous agent SDK built on Cloudflare Workers, D1, Supabase, Durable Objects, and MCP — designed to converse, plan, and execute real work across your entire stack. CMS websites, full-stack applications, data pipelines, creative workflows, terminal execution, deployments, and multi-step agentic pipelines — all through one unified agent interface.
6
6
 
7
+ **Repo:** [github.com/SamPrimeaux/agentsam-sdk](https://github.com/SamPrimeaux/agentsam-sdk) · **npm:** `@inneranimalmedia/agentsam-sdk`
8
+
7
9
  ---
8
10
 
9
11
  ## What is Agent Sam?
@@ -22,32 +24,54 @@ It is not a wrapper around a chat API. It is a command fabric with a conversatio
22
24
 
23
25
  ## Quickstart
24
26
 
25
- \`\`\`bash
27
+ ```bash
26
28
  npx @inneranimalmedia/agentsam-sdk init
27
- \`\`\`
29
+ ```
28
30
 
29
31
  Non-interactive (CI / scripts):
30
32
 
31
- \`\`\`bash
32
- npx @inneranimalmedia/agentsam-sdk init \\
33
- --name my-agent \\
34
- --lane fullstack \\
35
- --provider cloudflare \\
36
- --agent orchestrator \\
33
+ ```bash
34
+ npx @inneranimalmedia/agentsam-sdk init \
35
+ --name my-agent \
36
+ --lane fullstack \
37
+ --provider cloudflare \
38
+ --agent orchestrator \
37
39
  --yes
38
- \`\`\`
40
+ ```
39
41
 
40
- Scaffolded workers expose \`GET /health\` and \`POST /chat\` immediately (stub mode without an API key).
42
+ Scaffolded workers expose `GET /health` and `POST /chat` immediately (stub mode without an API key).
41
43
 
42
44
  See [DEVELOPMENT.md](./DEVELOPMENT.md) for linking the SDK into Inner Animal Media locally.
43
45
 
44
46
  ---
45
47
 
48
+ ## CLI Shell Experience (Gorilla)
49
+
50
+ The SDK ships a **game-feel terminal UX** alongside the scaffold CLI — consolidated from the Gorilla Mode experiment:
51
+
52
+ ```bash
53
+ npx @inneranimalmedia/agentsam-sdk shell
54
+ ```
55
+
56
+ | Piece | Location |
57
+ |-------|----------|
58
+ | Slash command registry | `src/lib/slash-commands.js` |
59
+ | Phase 0 visual prototype | `examples/gorilla-shell/` |
60
+ | Architecture + phases | [docs/CLI_SHELL.md](./docs/CLI_SHELL.md) |
61
+
62
+ Run the prototype:
63
+
64
+ ```bash
65
+ cd examples/gorilla-shell && npm install && npm run dev
66
+ ```
67
+
68
+ ---
69
+
46
70
  ## Installation
47
71
 
48
- \`\`\`bash
72
+ ```bash
49
73
  npm install @inneranimalmedia/agentsam-sdk
50
- \`\`\`
74
+ ```
51
75
 
52
76
  ---
53
77
 
@@ -77,7 +101,7 @@ npm install @inneranimalmedia/agentsam-sdk
77
101
 
78
102
  ## How It Works
79
103
 
80
- \`\`\`
104
+ ```
81
105
  User Intent (chat or CLI)
82
106
 
83
107
  Agent Sam — intent classification + command match
@@ -87,7 +111,7 @@ User Intent (chat or CLI)
87
111
  Execution — terminal / D1 / Supabase / R2 / KV / DO / browser / deploy / MCP
88
112
 
89
113
  Telemetry — every action logged, measured, improvable
90
- \`\`\`
114
+ ```
91
115
 
92
116
  Capabilities are data-driven — new tools are added via D1, not Worker redeployments. The same tool catalog powers the dashboard, the CLI, and any MCP-connected client like Cursor or Claude Desktop.
93
117
 
@@ -125,35 +149,25 @@ Agent Sam routes work to the right environment automatically:
125
149
 
126
150
  ## What Gets Scaffolded
127
151
 
128
- Running \`agentsam init\` generates a production-ready project for your lane:
152
+ Running `agentsam init` generates a production-ready project for your lane:
129
153
 
130
154
  **All lanes include:**
131
- - \`agentsam.config.js\` — project config, lane, provider, agent
132
- - \`wrangler.toml\` — Worker, D1, R2, KV, Durable Object bindings
133
- - \`.env.example\` — all required secrets pre-listed
134
- - \`src/index.js\` — Worker entry point wired to your agent
135
- - \`README.md\` — setup and deploy instructions
136
-
137
- **CMS lane adds:**
138
- - Page, section, asset, and theme schema migrations
139
- - CMS worker with live edit, draft/publish, and R2 asset pipeline
140
-
141
- **Data lane adds:**
142
- - D1 + Supabase Hyperdrive connection config
143
- - Vector embedding pipeline scaffold
144
- - Migration templates for core data models
145
-
146
- **Full Stack adds:**
147
- - Durable Object session scaffold
148
- - Auth tables and session management
149
- - Full agent chat + tool loop worker
155
+ - `agentsam.config.js` — project config, lane, provider, agent
156
+ - `wrangler.toml` — Worker, D1, R2, KV, Durable Object bindings
157
+ - `.env.example` — all required secrets pre-listed
158
+ - `src/index.js` — Worker entry point wired to your agent
159
+ - `README.md` — setup and deploy instructions
160
+
161
+ **CMS lane adds:** page/section/asset schema migrations and CMS worker scaffold.
162
+
163
+ **Data lane adds:** D1 + Hyperdrive config and migration templates.
164
+
165
+ **Full Stack adds:** Durable Object session scaffold, auth tables, full agent chat loop.
150
166
 
151
167
  ---
152
168
 
153
169
  ## Multi-Tenant & Client Policy
154
170
 
155
- Agent Sam is built for isolation from the ground up:
156
-
157
171
  - Each user or client gets a scoped workspace
158
172
  - Terminal execution is path-isolated — no cross-tenant access
159
173
  - AI usage is policy-gated — BYOK, managed, or disabled per client
@@ -164,10 +178,12 @@ Agent Sam is built for isolation from the ground up:
164
178
 
165
179
  ## Roadmap
166
180
 
167
- - [ ] \`agentsam deploy\`push your project from CLI
168
- - [ ] \`agentsam status\` live agent and infrastructure health
169
- - [ ] \`agentsam logs\`tail tool call and command logs
170
- - [ ] \`agentsam kit\`install pre-built capability kits
181
+ - [x] `agentsam shell`shell UX info + slash command registry
182
+ - [x] Gorilla Shell Phase 0 prototype in `examples/gorilla-shell/`
183
+ - [ ] `agentsam deploy`push your project from CLI
184
+ - [ ] `agentsam status`live agent and infrastructure health
185
+ - [ ] `agentsam logs` — tail tool call and command logs
186
+ - [ ] PTY bridge (Phase 1) — ExecOS WebSocket in shell
171
187
  - [ ] Kit marketplace — CMS, ecommerce, nonprofit, SaaS starters
172
188
  - [ ] BYOK AI key support per project
173
189
 
@@ -175,7 +191,9 @@ Agent Sam is built for isolation from the ground up:
175
191
 
176
192
  ## Built By
177
193
 
178
- [Inner Animal Media](https://inneranimalmedia.com) — Agent Sam is the operator brain behind the Inner Animal Media platform. The SDK is how we share that infrastructure with other developers.
194
+ [Inner Animal Media](https://inneranimalmedia.com) — Agent Sam is the operator brain behind the platform. The SDK is how we productize that infrastructure for other developers.
195
+
196
+ **Legacy:** [InnerAnimal/gorilla-mode](https://github.com/InnerAnimal/gorilla-mode) → consolidated here.
179
197
 
180
198
  ---
181
199
 
@@ -0,0 +1,90 @@
1
+ # Agent Sam SDK — CLI Shell Experience
2
+
3
+ The SDK ships two complementary surfaces:
4
+
5
+ 1. **`agentsam init`** — scaffold Workers + D1 + agent loop (resell/scale path)
6
+ 2. **Gorilla Shell** (`examples/gorilla-shell/`) — game-feel terminal UX layer (unique install experience)
7
+
8
+ Gorilla Mode was consolidated from the standalone [InnerAnimal/gorilla-mode](https://github.com/InnerAnimal/gorilla-mode) experiment into this repo. **Do not start new work in gorilla-mode** — extend here.
9
+
10
+ ---
11
+
12
+ ## Why a game shell?
13
+
14
+ Developers installing `@inneranimalmedia/agentsam-sdk` get:
15
+
16
+ - Efficient tooling (`init`, future `deploy` / `status` / `logs`)
17
+ - A **memorable CLI identity** — pixel HUD, slash commands, themed moods, deploy reactions
18
+
19
+ The shell is not a toy terminal emulator. It is a **presentation layer** on real PTY + MCP + D1 tool execution — the same stack IAM runs in production.
20
+
21
+ ---
22
+
23
+ ## Architecture
24
+
25
+ ```
26
+ User
27
+ └─ agentsam shell (CLI) or embedded <AgentSamShell />
28
+ └─ Gorilla HUD (themes, sprite, quest log)
29
+ └─ xterm.js ↔ ExecOS / iam-pty WebSocket
30
+ └─ Slash commands → SDK router → MCP / wrangler / D1
31
+ ```
32
+
33
+ | Layer | Location in SDK |
34
+ |-------|-----------------|
35
+ | Slash command registry | `src/lib/slash-commands.js` |
36
+ | Phase 0 visual prototype | `examples/gorilla-shell/App.tsx` |
37
+ | Scaffold + Worker agent | `src/lib/scaffold.js`, `src/AgentSam.js` |
38
+ | Future PTY bridge | `src/lib/shell/` (Phase 1) |
39
+
40
+ ---
41
+
42
+ ## Phases
43
+
44
+ See `SHELL_PHASES` in `src/lib/slash-commands.js`. Current status:
45
+
46
+ | Phase | Status |
47
+ |-------|--------|
48
+ | 0 — Visual prototype | **Complete** (demo scenarios, themes, sprite) |
49
+ | 1 — Real PTY | **Next** — wire to ExecOS / `terminal.inneranimalmedia.com` |
50
+ | 2 — HUD (quest log, tool gate, XP) | Planned |
51
+ | 3 — Buddy (`/buddy`, MCP stream) | Planned |
52
+ | 4 — Dashboard embed | Planned |
53
+ | 5 — Standalone PWA as SDK default | Planned |
54
+
55
+ ---
56
+
57
+ ## Run the prototype
58
+
59
+ ```bash
60
+ cd examples/gorilla-shell
61
+ npm install
62
+ npm run dev
63
+ ```
64
+
65
+ Deploy preview (Cloudflare Pages):
66
+
67
+ ```bash
68
+ npm run build
69
+ npx wrangler pages deploy dist
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Platform linkage (IAM)
75
+
76
+ | Shell feature | IAM SSOT |
77
+ |---------------|----------|
78
+ | PTY sessions | `terminal_connections` + ExecOS |
79
+ | Tool execution | `agentsam_tools` → catalog executor |
80
+ | Buddy / MCP | `mcp.inneranimalmedia.com` |
81
+ | XP (future) | `gorilla_xp` D1 table |
82
+ | Themes (future) | user preferences / `cms_themes` pattern |
83
+
84
+ ---
85
+
86
+ ## Repo history
87
+
88
+ - **Before:** `InnerAnimal/gorilla-mode` (Phase 0 only, single-file React artifact)
89
+ - **Now:** `SamPrimeaux/agentsam-sdk/examples/gorilla-shell`
90
+ - **D1 project:** `proj_agentsam_sdk` (replaces `proj_gorilla_mode` on the IAM projects grid)
@@ -0,0 +1,540 @@
1
+ import { useState, useEffect, useRef, useMemo, useCallback } from "react";
2
+
3
+ const PS = 5;
4
+ const PAL = ['transparent','#060e1a','#0f2040','#1a3568','#6a6a90','#9898b8','#2a1006','#8a5830','#ff1a1a','#ffd88a','#0e0400','#ffffff','#ffd700','#ffaa00','#ff6600','#ff2200','#9B6E14','#6B4808','#3a2604','#c09030','#ffee44','#cc8800','#44ff88','#ff4444'];
5
+
6
+ const GORILLA = [
7
+ [0,0,0,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0],
8
+ [0,0,2,3,3,3,3,3,3,3,3,3,3,2,2,0,0,0],
9
+ [0,2,2,3,3,3,3,3,3,3,3,3,3,3,2,2,0,0],
10
+ [0,2,3,3,7,7,3,3,3,7,7,3,3,3,2,0,0,0],
11
+ [2,2,3,7,7,8,7,3,3,7,8,7,7,3,3,2,2,0],
12
+ [2,2,3,7,7,7,7,7,7,7,7,7,7,3,3,2,2,0],
13
+ [2,3,3,7,6,10,6,7,7,6,10,6,7,3,3,3,2,0],
14
+ [2,3,3,7,7,7,9,9,9,9,7,7,7,3,3,3,2,0],
15
+ [0,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,0],
16
+ [0,2,2,3,4,4,4,4,4,4,4,4,4,3,2,2,0,0],
17
+ [2,2,2,3,4,5,5,5,5,5,5,5,4,3,3,2,2,2],
18
+ [2,3,2,3,4,5,5,5,5,5,5,5,4,3,2,3,2,2],
19
+ [2,3,3,3,3,4,4,5,5,4,4,3,3,3,3,3,2,0],
20
+ [0,2,3,3,3,3,3,3,3,3,3,3,3,3,2,2,0,0],
21
+ [0,0,2,3,3,3,3,3,3,3,3,3,3,2,2,0,0,0],
22
+ [0,0,2,2,3,3,3,3,3,3,3,3,2,2,0,0,0,0],
23
+ [0,0,0,2,2,3,3,0,0,3,3,2,2,0,0,0,0,0],
24
+ [0,0,0,2,2,2,2,0,0,2,2,2,2,0,0,0,0,0],
25
+ [0,0,0,0,2,2,2,0,0,2,2,2,0,0,0,0,0,0],
26
+ [0,0,0,0,2,3,2,0,0,2,3,2,0,0,0,0,0,0],
27
+ ];
28
+ const GORILLA_PUMP = GORILLA.map((r,i) => {
29
+ if (i===8) return [2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,0];
30
+ if (i===9) return [2,2,3,4,5,5,5,5,5,5,5,5,5,4,3,2,2,0];
31
+ if (i===10) return [0,2,3,4,5,5,5,5,5,5,5,5,5,4,3,2,0,0];
32
+ if (i===11) return [0,2,3,3,4,5,5,5,5,5,5,5,4,3,3,2,0,0];
33
+ return r;
34
+ });
35
+
36
+ const COIN = [[0,12,12,12,12,12,0],[12,20,20,20,20,20,12],[12,20,12,20,12,20,12],[12,20,20,20,20,20,12],[0,12,12,12,12,12,0],[0,0,21,21,0,0,0]];
37
+ const FLAME_FRAMES = [
38
+ [[0,0,14,0,0],[0,14,15,14,0],[14,15,13,14,0],[14,13,20,14,0],[0,14,13,14,0],[0,13,14,13,0]],
39
+ [[0,14,0,14,0],[14,15,14,0,0],[14,13,15,14,0],[0,14,13,14,0],[0,13,14,0,0],[0,14,13,0,0]],
40
+ [[0,14,14,0,0],[0,14,15,14,0],[14,15,13,15,0],[14,13,14,13,0],[0,14,13,14,0],[0,0,14,13,0]],
41
+ ];
42
+
43
+ const THEMES = {
44
+ NIGHT: { bg:'#030a14', panel:'rgba(4,12,26,.97)', accent:'#00e5ff', dim:'#00e5ff22', glow:'0 0 14px #00e5ff55', border:'#00e5ff33' },
45
+ DAY: { bg:'#071a0a', panel:'rgba(6,20,10,.97)', accent:'#44ff88', dim:'#44ff8822', glow:'0 0 14px #44ff8855', border:'#44ff8833' },
46
+ LAVA: { bg:'#0e0003', panel:'rgba(18,2,4,.97)', accent:'#ff4400', dim:'#ff440022', glow:'0 0 14px #ff440055', border:'#ff440033' },
47
+ VOID: { bg:'#06001a', panel:'rgba(8,2,28,.97)', accent:'#aa44ff', dim:'#aa44ff22', glow:'0 0 14px #aa44ff55', border:'#aa44ff33' },
48
+ };
49
+ const TKEYS = Object.keys(THEMES);
50
+
51
+ // ── Line colors ───────────────────────────────────────────────────────────────
52
+ const LC = {
53
+ cmd: '#00e5ff',
54
+ success: '#44ff88',
55
+ error: '#ff4444',
56
+ warn: '#ffcc00',
57
+ info: '#88bbff',
58
+ muted: 'rgba(255,255,255,.45)',
59
+ dim: 'rgba(255,255,255,.18)',
60
+ white: 'rgba(255,255,255,.9)',
61
+ sam: '#cc88ff',
62
+ table: '#ffdd88',
63
+ pass: '#44ff88',
64
+ fail: '#ff4444',
65
+ accent: '#00e5ff',
66
+ };
67
+
68
+ // ── Scenario Builders ─────────────────────────────────────────────────────────
69
+ const BENCH_TESTS = [
70
+ ['health_check',13],['auth_superadmin',8],['auth_regular',9],['d1_query_basic',45],
71
+ ['d1_query_join',67],['d1_write_record',38],['mcp_tool_routing',23],['mcp_auth_bearer',11],
72
+ ['mcp_audit_log',19],['agent_context_load',88],['r2_upload_asset',54],['r2_fetch_asset',31],
73
+ ['kv_read_hit',7],['kv_write_ttl',14],['queue_publish',28],['worker_ai_t0',112],
74
+ ['gemini_flash_lite',189],['haiku_route',145],['sonnet_route',234],['budget_check',6],
75
+ ['cicd_sandbox_gate',17],['cicd_benchmark_gate',22],['deploy_record_insert',33],
76
+ ['workspace_switch',12],['terminal_session_resume',19],['rag_cosine_query',78],
77
+ ['tool_intent_match',15],['client_workflow_run',44],['project_context_load',29],
78
+ ['skill_lookup',11],['cicd_pipeline_e2e',156],
79
+ ];
80
+
81
+ function buildDeploy() {
82
+ let d = 0; const L = (text, color, gap=120) => { d+=gap; return {text,color,delay:d}; };
83
+ return [
84
+ L('gorilla@inneranimal ~ % /deploy sandbox','cmd',0),
85
+ L('','dim',60),
86
+ L(' ./scripts/with-cloudflare-env.sh npx wrangler deploy','muted',80),
87
+ L(' –config wrangler.sandbox.toml','muted',40),
88
+ L('','dim',80),
89
+ L(' Bundling worker…','muted',300),
90
+ L(' esbuild: scanning 847 modules…','muted',500),
91
+ L(' Tree-shaking complete: 284kb','muted',400),
92
+ L(' Build time: 1.24s','muted',200),
93
+ L('','dim',80),
94
+ L(' Uploading script…','muted',350),
95
+ L('','dim',60),
96
+ L(' Worker inneranimal-dashboard','info',200),
97
+ L(' Compat date 2026-04-08','info',60),
98
+ L(' D1 binding inneranimalmedia-business [cf87b717]','info',60),
99
+ L(' R2 binding agent-sam-sandbox-cicd','info',60),
100
+ L(' KV binding IAM_KV, RATE_LIMIT_KV','info',60),
101
+ L(' Queues DEPLOY_QUEUE, AGENT_QUEUE','info',60),
102
+ L('','dim',80),
103
+ L(' Routing table:','muted',200),
104
+ L(' dashboard.inneranimalmedia.com /* -> inneranimal-dashboard','dim',60),
105
+ L('','dim',80),
106
+ L(' [OK] Deployed successfully 3.41s','success',400),
107
+ L(' >> https://inneranimal-dashboard.samprimeaux.workers.dev','accent',80),
108
+ L('','dim',100),
109
+ L(' Next: run /benchmark to proceed to prod','warn',200),
110
+ ];
111
+ }
112
+
113
+ function buildBenchmark() {
114
+ let d = 0; const L = (text, color, gap=80) => { d+=gap; return {text,color,delay:d}; };
115
+ const lines = [
116
+ L('gorilla@inneranimal ~ % /benchmark','cmd',0),
117
+ L('','dim',60),
118
+ L(' Running 31 tests against inneranimal-dashboard…','muted',200),
119
+ L('','dim',60),
120
+ ];
121
+ BENCH_TESTS.forEach(([name, ms], i) => {
122
+ const num = String(i+1).padStart(2,'0');
123
+ const dots = '.'.repeat(Math.max(2, 36 - name.length));
124
+ lines.push(L(` [${num}/31] ${name} ${dots} PASS ${ms}ms`,'pass',75));
125
+ });
126
+ lines.push(L('','dim',100));
127
+ lines.push(L(' '+'-'.repeat(52),'dim',100));
128
+ lines.push(L(' RESULTS 31 / 31 PASSED avg 47ms total 1.46s','success',200));
129
+ lines.push(L(' '+'-'.repeat(52),'dim',60));
130
+ lines.push(L('','dim',80));
131
+ lines.push(L(' [GATE PASSED] Cleared for production promote','success',300));
132
+ return lines;
133
+ }
134
+
135
+ function buildD1() {
136
+ let d = 0; const L = (text, color, gap=100) => { d+=gap; return {text,color,delay:d}; };
137
+ const SEP = ' +—————————+———+———————+';
138
+ const rows = [
139
+ ['inneranimalmedia','success','2026-04-07 23:10:56'],
140
+ ['inneranimal-dashboard','success','2026-04-07 22:55:15'],
141
+ ['inneranimal-dashboard','success','2026-04-07 22:06:28'],
142
+ ['inneranimalmedia','success','2026-04-06 18:32:11'],
143
+ ['inneranimal-dashboard','error','2026-04-06 17:44:03'],
144
+ ];
145
+ return [
146
+ L('gorilla@inneranimal ~ % /d1 SELECT name, status, created_at FROM deployments ORDER BY created_at DESC LIMIT 5','cmd',0),
147
+ L('','dim',60),
148
+ L(' DB: inneranimalmedia-business','muted',150),
149
+ L(' ID: cf87b717-d4e2-4cf8-bab0-a81268e32d49','dim',60),
150
+ L('','dim',100),
151
+ L(SEP,'table',200),
152
+ L(' | name | status | created_at |','table',60),
153
+ L(SEP,'table',60),
154
+ …rows.map(([n,s,t]) => L(
155
+ ` | ${n.padEnd(25)} | ${s.padEnd(7)} | ${t} |`,
156
+ s==='error'?'error':'white', 90
157
+ )),
158
+ L(SEP,'table',90),
159
+ L(' 5 rows | 2ms','dim',100),
160
+ ];
161
+ }
162
+
163
+ function buildTail() {
164
+ let d = 0; const L = (text, color, gap=280) => { d+=gap; return {text,color,delay:d}; };
165
+ const reqs = [
166
+ ['GET ','/ ','200','14ms',''],
167
+ ['POST','/api/agent/chat ','200','234ms',''],
168
+ ['GET ','/api/workspace/status ','200','8ms',''],
169
+ ['POST','/mcp ','200','45ms','[MCP]'],
170
+ ['GET ','/api/deployments ','200','12ms',''],
171
+ ['POST','/api/agent/chat ','200','891ms','[LLM]'],
172
+ ['GET ','/health ','200','2ms',''],
173
+ ['POST','/api/d1/query ','200','34ms',''],
174
+ ['GET ','/api/workspace/list ','200','18ms',''],
175
+ ['POST','/api/agent/chat ','500','12ms','[ERR]'],
176
+ ];
177
+ const delays = [0,320,180,260,400,350,220,310,280,450];
178
+ return [
179
+ L('gorilla@inneranimal ~ % /tail inneranimalmedia','cmd',0),
180
+ L('','dim',60),
181
+ L(' npx wrangler tail inneranimalmedia –format pretty','muted',100),
182
+ L(' Streaming live logs… (CTRL+C to stop)','dim',300),
183
+ L('','dim',100),
184
+ …reqs.map(([m,p,s,t,tag],i) => L(
185
+ ` [10:23:${41+i}] ${m} ${p.padEnd(30)}${s} ${t.padEnd(8)}${tag}`,
186
+ s==='500'?'error': tag==='[LLM]'?'warn': tag==='[MCP]'?'info': 'muted',
187
+ delays[i] || 300
188
+ )),
189
+ L('','dim',200),
190
+ L(' 1 error detected – POST /api/agent/chat returned 500','error',200),
191
+ L(' Tip: run /samiam to diagnose','warn',200),
192
+ ];
193
+ }
194
+
195
+ function buildSamIAm() {
196
+ let d = 0; const L = (text, color, gap=80) => { d+=gap; return {text,color,delay:d}; };
197
+ return [
198
+ L('gorilla@inneranimal ~ % /samiam how is our terminal setup','cmd',0),
199
+ L('','dim',60),
200
+ L(' >> AGENT SAM ACTIVATED','sam',200),
201
+ L(' >> Workspace: ws_inneranimalmedia','sam',100),
202
+ L(' >> PTY context: injecting last 30 lines','sam',100),
203
+ L(' >> Routing: claude-sonnet-4-6 (T2)','sam',100),
204
+ L('','dim',200),
205
+ L(' [SAM] Terminal PTY is running clean. Your xterm.js','sam',400),
206
+ L(' bridge is connected to iam-pty via WebSocket.','sam',150),
207
+ L(' gorilla-mode shell is rendering on top of it.','sam',150),
208
+ L('','dim',80),
209
+ L(' [SAM] One issue flagging: 50 open errors in status','sam',300),
210
+ L(' bar – traced to mcp_services table having 30','sam',150),
211
+ L(' rows all pointing to same endpoint, NULL last_used.','sam',150),
212
+ L(' Table is never read by Worker – safe to truncate.','sam',150),
213
+ L('','dim',80),
214
+ L(' [SAM] Also: terminal_sessions user_id backfill is','sam',300),
215
+ L(' still needed in register INSERT (hardcoded sam).','sam',150),
216
+ L('','dim',80),
217
+ L(' [1] Show me the mcp_services cleanup query','white',300),
218
+ L(' [2] Run /d1 truncate mcp_services directly','white',80),
219
+ L(' [3] Open the terminal_sessions bug in Cursor','white',80),
220
+ L(' [esc] Skip for now','dim',80),
221
+ ];
222
+ }
223
+
224
+ function buildWrangler() {
225
+ let d = 0; const L = (text, color, gap=100) => { d+=gap; return {text,color,delay:d}; };
226
+ return [
227
+ L('gorilla@inneranimal ~ % /wrangler tail inneranimalmedia','cmd',0),
228
+ L('','dim',60),
229
+ L(' [GATE] About to run:','warn',150),
230
+ L(' ./scripts/with-cloudflare-env.sh npx wrangler tail inneranimalmedia','white',80),
231
+ L('','dim',80),
232
+ L(' PROCEED? [1] YES [esc] NO','warn',200),
233
+ L('','dim',100),
234
+ L(' >> 1','cmd',600),
235
+ L('','dim',60),
236
+ L(' Connecting to worker: inneranimalmedia','muted',200),
237
+ L(' Account: Inner Animal Media (6f2a…)','muted',80),
238
+ L(' Zone: inneranimalmedia.com','muted',80),
239
+ L('','dim',100),
240
+ L(' [STREAM] Listening for events…','success',300),
241
+ L('','dim',80),
242
+ L(' 10:31:04 GET / 200 11ms','dim',400),
243
+ L(' 10:31:06 POST /api/agent/chat 200 445ms','dim',350),
244
+ L(' 10:31:07 GET /api/status 200 6ms','dim',250),
245
+ L(' 10:31:09 POST /mcp 200 88ms [MCP]','info',380),
246
+ L(' 10:31:11 POST /api/agent/chat 200 1201ms [LLM]','warn',620),
247
+ L('','dim',200),
248
+ L(' LLM call latency spike: 1201ms – check Sonnet routing','warn',200),
249
+ ];
250
+ }
251
+
252
+ const SCENARIOS = [
253
+ { key:'deploy', label:'/deploy', fn:buildDeploy, status:'DEPLOYING', coins:6, pump:true, errAt:null },
254
+ { key:'benchmark', label:'/benchmark', fn:buildBenchmark, status:'BENCHMARKING',coins:12, pump:true, errAt:null },
255
+ { key:'d1', label:'/d1 query', fn:buildD1, status:'QUERYING D1',coins:3, pump:false, errAt:null },
256
+ { key:'tail', label:'/tail', fn:buildTail, status:'TAILING', coins:0, pump:false, errAt:9 },
257
+ { key:'samiam', label:'/samiam', fn:buildSamIAm, status:'SAM ACTIVE', coins:4, pump:true, errAt:null },
258
+ { key:'wrangler', label:'/wrangler', fn:buildWrangler, status:'CF GATE', coins:2, pump:false, errAt:null },
259
+ ];
260
+
261
+ // ── Sprite Renderer ───────────────────────────────────────────────────────────
262
+ function Sprite({ data, scale=1 }) {
263
+ const ps = PS * scale;
264
+ return (
265
+ <svg width={data[0].length*ps} height={data.length*ps} style={{imageRendering:'pixelated',display:'block'}}>
266
+ {data.flatMap((row,y) => row.map((c,x) =>
267
+ c ? <rect key={`${x},${y}`} x={x*ps} y={y*ps} width={ps} height={ps} fill={PAL[c]}/> : null
268
+ ))}
269
+ </svg>
270
+ );
271
+ }
272
+
273
+ // ── Bar ───────────────────────────────────────────────────────────────────────
274
+ function Bar({ pct, color, label, val }) {
275
+ return (
276
+ <div style={{marginBottom:10}}>
277
+ <div style={{display:'flex',justifyContent:'space-between',fontSize:9,letterSpacing:2,color:'rgba(255,255,255,.4)',marginBottom:3}}>
278
+ <span>{label}</span><span style={{color}}>{val}</span>
279
+ </div>
280
+ <div style={{height:6,background:'rgba(255,255,255,.07)',position:'relative'}}>
281
+ <div style={{position:'absolute',top:0,left:0,height:'100%',width:`${pct}%`,background:color,transition:'width .4s ease',boxShadow:`0 0 6px ${color}`}}/>
282
+ </div>
283
+ </div>
284
+ );
285
+ }
286
+
287
+ // ── Main ──────────────────────────────────────────────────────────────────────
288
+ export default function GorillaMode() {
289
+ const [themeIdx, setThemeIdx] = useState(0);
290
+ const [lines, setLines] = useState([{text:'gorilla@inneranimal ~ % ready. select a demo below.', color:'dim', delay:0}]);
291
+ const [running, setRunning] = useState(false);
292
+ const [status, setStatus] = useState('READY');
293
+ const [progress, setProgress] = useState(0);
294
+ const [pump, setPump] = useState(false);
295
+ const [errorFlash, setError] = useState(false);
296
+ const [coinCount, setCoinCount] = useState(0);
297
+ const [floatCoins, setFloat] = useState([]);
298
+ const [flameTick, setFlameTick] = useState(0);
299
+ const [booted, setBooted] = useState(false);
300
+ const [bootLine, setBootLine] = useState('');
301
+ const [activeScenario, setActive] = useState(null);
302
+ const termRef = useRef(null);
303
+ const timerRefs = useRef([]);
304
+
305
+ const T = THEMES[TKEYS[themeIdx]];
306
+
307
+ // Boot
308
+ useEffect(() => {
309
+ const BOOT = ['GORILLA MODE v0.1','>> D1: inneranimalmedia-business','>> MCP TOOLS: 98 LOADED','>> AGENT SAM: ONLINE','>> READY'];
310
+ let i = 0;
311
+ const t = setInterval(() => { if(i<BOOT.length){setBootLine(BOOT[i]);i++;}else{clearInterval(t);setTimeout(()=>setBooted(true),400);}}, 340);
312
+ return () => clearInterval(t);
313
+ }, []);
314
+
315
+ // Flame tick
316
+ useEffect(() => {
317
+ const t = setInterval(() => setFlameTick(n => (n+1)%3), 190);
318
+ return () => clearInterval(t);
319
+ }, []);
320
+
321
+ // Auto-scroll terminal
322
+ useEffect(() => {
323
+ if (termRef.current) termRef.current.scrollTop = termRef.current.scrollHeight;
324
+ }, [lines]);
325
+
326
+ const stars = useMemo(() =>
327
+ Array.from({length:40},(_,i) => ({id:i,x:Math.random()*100,y:Math.random()*45,s:Math.random()<.2?2:1,d:Math.random()*4}))
328
+ ,[]);
329
+
330
+ const spawnCoins = useCallback((n) => {
331
+ if (!n) return;
332
+ const batch = Array.from({length:n},(_,i) => ({id:Date.now()+i,x:15+Math.random()*30,y:40+Math.random()*15,dx:(Math.random()-.5)*50}));
333
+ setFloat(p=>[…p,…batch]);
334
+ setCoinCount(c=>c+n);
335
+ setTimeout(()=>setFloat(p=>p.filter(c=>!batch.find(b=>b.id===c.id))),1400);
336
+ },[]);
337
+
338
+ const runScenario = useCallback((s) => {
339
+ if (running) return;
340
+ timerRefs.current.forEach(clearTimeout);
341
+ timerRefs.current = [];
342
+ const scenario = SCENARIOS.find(x=>x.key===s);
343
+ if (!scenario) return;
344
+ const sceneLines = scenario.fn();
345
+ const maxDelay = Math.max(…sceneLines.map(l=>l.delay));
346
+ setLines([]);
347
+ setRunning(true);
348
+ setStatus(scenario.status);
349
+ setProgress(0);
350
+ setActive(s);
351
+
352
+ ```
353
+ sceneLines.forEach((line,i) => {
354
+ const t = setTimeout(() => {
355
+ setLines(p=>[...p,line]);
356
+ setProgress(Math.round(((i+1)/sceneLines.length)*100));
357
+ if (line.color==='error'||line.color==='fail') {
358
+ setError(true); setTimeout(()=>setError(false),600);
359
+ }
360
+ }, line.delay);
361
+ timerRefs.current.push(t);
362
+ });
363
+
364
+ const done = setTimeout(() => {
365
+ setRunning(false);
366
+ setStatus('READY');
367
+ setProgress(100);
368
+ if (scenario.pump) { setPump(true); setTimeout(()=>setPump(false),700); }
369
+ spawnCoins(scenario.coins);
370
+ }, maxDelay + 400);
371
+ timerRefs.current.push(done);
372
+ ```
373
+
374
+ }, [running, spawnCoins]);
375
+
376
+ const CSS = `@keyframes idle {0%,100%{transform:translateY(0)} 50%{transform:translateY(-4px)}} @keyframes pump {0%{transform:scale(1)} 30%{transform:scale(1.12) translateY(-7px)} 70%{transform:scale(.97)} 100%{transform:scale(1)}} @keyframes shake {0%,100%{transform:translateX(0)} 20%{transform:translateX(-4px)} 40%{transform:translateX(4px)} 60%{transform:translateX(-3px)} 80%{transform:translateX(3px)}} @keyframes rise {0%{transform:translateY(0) scale(1);opacity:1} 100%{transform:translateY(-80px) scale(.3);opacity:0}} @keyframes blink {0%,100%{opacity:1} 50%{opacity:0}} @keyframes twinkle {0%,100%{opacity:.7} 50%{opacity:.1}} @keyframes flicker {0%,100%{transform:scaleY(1)} 50%{transform:scaleY(1.12) scaleX(.9)}} @keyframes scan {0%{opacity:.02} 50%{opacity:.05} 100%{opacity:.02}} @keyframes fadein {from{opacity:0;transform:translateY(6px)} to{opacity:1;transform:none}} @keyframes errflash{0%,100%{box-shadow:none} 50%{box-shadow:0 0 30px #ff444488 inset}} .scen-btn{cursor:pointer;transition:all .12s;font-family:"Courier New",monospace;} .scen-btn:hover{transform:translateY(-1px);} .scen-btn:disabled{opacity:.35;cursor:not-allowed;transform:none;}`;
377
+
378
+ if (!booted) return (
379
+ <div style={{width:'100%',height:'100vh',background:'#030a14',display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',fontFamily:'"Courier New",monospace',color:'#00e5ff'}}>
380
+ <style>{CSS}</style>
381
+ <div style={{fontSize:10,letterSpacing:6,opacity:.35,marginBottom:14}}>INNERANIMAL MEDIA</div>
382
+ <div style={{fontSize:15,letterSpacing:2,textShadow:'0 0 10px #00e5ff'}}>
383
+ {bootLine}<span style={{animation:'blink .7s infinite'}}>_</span>
384
+ </div>
385
+ </div>
386
+ );
387
+
388
+ return (
389
+ <div style={{width:'100%',minHeight:'100vh',background:`linear-gradient(160deg,${T.bg} 0%,#030a14 100%)`,fontFamily:'"Courier New",monospace',position:'relative',overflow:'hidden'}}>
390
+ <style>{CSS}</style>
391
+
392
+ ```
393
+ {/* Scanlines */}
394
+ <div style={{position:'absolute',inset:0,pointerEvents:'none',zIndex:99,
395
+ backgroundImage:`repeating-linear-gradient(0deg,${T.dim.replace('22','06')} 0,${T.dim.replace('22','06')} 1px,transparent 1px,transparent 3px)`,
396
+ animation:'scan 5s infinite'}}/>
397
+
398
+ {/* Stars */}
399
+ {stars.map(s=>(
400
+ <div key={s.id} style={{position:'absolute',left:`${s.x}%`,top:`${s.y}%`,width:s.s,height:s.s,background:'#fff',
401
+ animation:`twinkle ${2+s.d}s infinite`,animationDelay:`${s.d}s`,pointerEvents:'none'}}/>
402
+ ))}
403
+
404
+ {/* Floating coins */}
405
+ {floatCoins.map(c=>(
406
+ <div key={c.id} style={{position:'absolute',left:`${c.x}%`,top:`${c.y}%`,
407
+ animation:'rise 1.3s ease-out forwards',transform:`translateX(${c.dx}px)`,pointerEvents:'none',zIndex:60}}>
408
+ <Sprite data={COIN} scale={.9}/>
409
+ </div>
410
+ ))}
411
+
412
+ {/* Top bar */}
413
+ <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',
414
+ padding:'10px 18px 8px',borderBottom:`1px solid ${T.border}`,background:T.panel}}>
415
+ <div>
416
+ <span style={{fontSize:9,letterSpacing:5,color:T.accent,opacity:.6}}>INNERANIMAL MEDIA // </span>
417
+ <span style={{fontSize:12,fontWeight:900,letterSpacing:4,color:'#fff',textShadow:T.glow}}>GORILLA MODE</span>
418
+ </div>
419
+ <div style={{display:'flex',alignItems:'center',gap:16}}>
420
+ <div style={{display:'flex',alignItems:'center',gap:6,background:'rgba(0,0,0,.5)',border:`1px solid ${T.accent}`,padding:'3px 10px'}}>
421
+ <Sprite data={COIN} scale={.45}/>
422
+ <span style={{color:T.accent,fontSize:11,letterSpacing:2}}>x {coinCount}</span>
423
+ </div>
424
+ <button className="scen-btn" onClick={()=>setThemeIdx(i=>(i+1)%TKEYS.length)}
425
+ style={{padding:'4px 10px',background:'transparent',border:`1px solid ${T.border}`,color:T.accent,fontSize:9,letterSpacing:2}}>
426
+ {TKEYS[themeIdx]}
427
+ </button>
428
+ </div>
429
+ </div>
430
+
431
+ {/* Main split */}
432
+ <div style={{display:'flex',height:'calc(100vh - 130px)',minHeight:400}}>
433
+
434
+ {/* LEFT: Gorilla + HUD */}
435
+ <div style={{width:200,minWidth:180,borderRight:`1px solid ${T.border}`,background:T.panel,
436
+ display:'flex',flexDirection:'column',alignItems:'center',padding:'16px 14px',gap:0,flexShrink:0}}>
437
+
438
+ {/* Gorilla */}
439
+ <div style={{
440
+ animation: errorFlash ? 'shake .5s ease' : pump ? 'pump .6s ease' : 'idle 2.8s ease-in-out infinite',
441
+ filter: errorFlash ? 'brightness(1.5) saturate(2) hue-rotate(-20deg)' : 'none',
442
+ marginBottom:8,
443
+ }}>
444
+ <Sprite data={pump ? GORILLA_PUMP : GORILLA} scale={1.05}/>
445
+ </div>
446
+
447
+ {/* Flames */}
448
+ <div style={{display:'flex',justifyContent:'center',gap:60,marginTop:-4}}>
449
+ {[0,1].map(i=>(
450
+ <div key={i} style={{animation:'flicker .45s infinite',animationDelay:`${i*.2}s`}}>
451
+ <Sprite data={FLAME_FRAMES[flameTick]} scale={.9}/>
452
+ </div>
453
+ ))}
454
+ </div>
455
+
456
+ {/* Status */}
457
+ <div style={{width:'100%',marginTop:14,paddingTop:12,borderTop:`1px solid ${T.border}`}}>
458
+ <div style={{fontSize:9,letterSpacing:3,color:T.accent,marginBottom:10,textAlign:'center',textShadow:T.glow}}>
459
+ {status}
460
+ {running && <span style={{animation:'blink .7s infinite',marginLeft:4}}>_</span>}
461
+ </div>
462
+
463
+ <Bar pct={progress} color={T.accent} label="PROGRESS" val={`${progress}%`}/>
464
+ <Bar pct={Math.max(0,100-progress)} color="#ff4444" label="ERRORS" val="50"/>
465
+ <Bar pct={running?65:100} color="#44ff88" label="AGENT" val={running?'BUSY':'READY'}/>
466
+
467
+ <div style={{marginTop:12,paddingTop:10,borderTop:`1px solid ${T.border}`,fontSize:9,color:'rgba(255,255,255,.3)',letterSpacing:1,lineHeight:1.8}}>
468
+ <div>ws_inneranimalmedia</div>
469
+ <div>branch: main {running&&<span style={{color:T.accent}}>*</span>}</div>
470
+ <div style={{color:activeScenario?T.accent:'inherit'}}>
471
+ {activeScenario ? `> ${activeScenario}` : '> idle'}
472
+ </div>
473
+ </div>
474
+ </div>
475
+ </div>
476
+
477
+ {/* RIGHT: Terminal */}
478
+ <div style={{flex:1,display:'flex',flexDirection:'column',overflow:'hidden'}}>
479
+
480
+ {/* Terminal header */}
481
+ <div style={{padding:'7px 16px',borderBottom:`1px solid ${T.border}`,background:'rgba(0,0,0,.4)',
482
+ display:'flex',alignItems:'center',gap:8}}>
483
+ <div style={{width:8,height:8,borderRadius:'50%',background:running?T.accent:'#ffffff22',boxShadow:running?T.glow:'none',transition:'all .3s'}}/>
484
+ <span style={{fontSize:9,letterSpacing:2,color:'rgba(255,255,255,.3)'}}>TERMINAL OUTPUT</span>
485
+ <span style={{marginLeft:'auto',fontSize:9,color:'rgba(255,255,255,.2)',letterSpacing:1}}>{lines.length} lines</span>
486
+ </div>
487
+
488
+ {/* Output */}
489
+ <div ref={termRef} style={{flex:1,overflowY:'auto',padding:'14px 18px',
490
+ animation: errorFlash ? 'errflash .5s ease' : 'none',
491
+ scrollbarWidth:'thin',scrollbarColor:`${T.accent}33 transparent`}}>
492
+ {lines.map((line, i) => (
493
+ <div key={i} style={{
494
+ fontFamily:'"Courier New",monospace',fontSize:12,lineHeight:1.65,
495
+ whiteSpace:'pre',color: LC[line.color] || LC.white,
496
+ animation: i===lines.length-1 ? 'fadein .15s ease' : 'none',
497
+ }}>
498
+ {line.text || '\u00A0'}
499
+ </div>
500
+ ))}
501
+ {running && (
502
+ <div style={{color:T.accent,fontSize:12,animation:'blink .7s infinite',marginTop:2}}>_</div>
503
+ )}
504
+ </div>
505
+
506
+ {/* Input line */}
507
+ <div style={{padding:'8px 16px',borderTop:`1px solid ${T.border}`,background:'rgba(0,0,0,.5)',
508
+ display:'flex',alignItems:'center',gap:8}}>
509
+ <span style={{color:T.accent,fontSize:12,whiteSpace:'nowrap'}}>gorilla@inneranimal ~ %</span>
510
+ <div style={{flex:1,fontSize:12,color:'rgba(255,255,255,.7)',letterSpacing:.5}}>
511
+ {running ? (
512
+ <span style={{color:'rgba(255,255,255,.3)'}}>running... <span style={{animation:'blink .5s infinite'}}>|</span></span>
513
+ ) : (
514
+ <span style={{color:'rgba(255,255,255,.3)'}}>type /help or select demo below<span style={{animation:'blink 1s infinite'}}>|</span></span>
515
+ )}
516
+ </div>
517
+ </div>
518
+ </div>
519
+ </div>
520
+
521
+ {/* Scenario buttons */}
522
+ <div style={{borderTop:`1px solid ${T.border}`,background:T.panel,
523
+ display:'flex',flexWrap:'wrap',gap:0}}>
524
+ {SCENARIOS.map(s=>(
525
+ <button key={s.key} className="scen-btn" disabled={running}
526
+ onClick={()=>runScenario(s.key)}
527
+ style={{flex:'1 1 0',padding:'10px 8px',minWidth:100,
528
+ background: activeScenario===s.key ? T.dim : 'transparent',
529
+ border:'none',borderRight:`1px solid ${T.border}`,
530
+ color: activeScenario===s.key ? T.accent : 'rgba(255,255,255,.5)',
531
+ fontSize:11,letterSpacing:1.5,textShadow: activeScenario===s.key ? T.glow : 'none'}}>
532
+ {s.label}
533
+ </button>
534
+ ))}
535
+ </div>
536
+ </div>
537
+ ```
538
+
539
+ );
540
+ }
@@ -0,0 +1,22 @@
1
+ # Gorilla Shell (Phase 0)
2
+
3
+ Game-feel terminal UI prototype — consolidated from [InnerAnimal/gorilla-mode](https://github.com/InnerAnimal/gorilla-mode) into **Agent Sam SDK**.
4
+
5
+ This is the **unique install experience** layer: pixel HUD, themed moods, slash-command demos, deploy/benchmark scenarios. Phase 1 connects real PTY via ExecOS.
6
+
7
+ ## Run locally
8
+
9
+ ```bash
10
+ cd examples/gorilla-shell
11
+ npm install
12
+ npm run dev
13
+ ```
14
+
15
+ ## What you see
16
+
17
+ - Gorilla launch screen + sprite reactions
18
+ - Themes: NIGHT, DAY, LAVA, VOID
19
+ - Six demo scenarios (deploy, benchmark, D1, tail, samiam, wrangler)
20
+ - Slash command registry lives in `../../src/lib/slash-commands.js`
21
+
22
+ Full architecture: [docs/CLI_SHELL.md](../../docs/CLI_SHELL.md)
@@ -0,0 +1,15 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Agent Sam Shell — Gorilla Mode</title>
7
+ <style>
8
+ html, body, #root { margin: 0; height: 100%; background: #030a14; }
9
+ </style>
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ <script type="module" src="/main.jsx"></script>
14
+ </body>
15
+ </html>
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import App from './App.tsx';
4
+
5
+ createRoot(document.getElementById('root')).render(
6
+ <React.StrictMode>
7
+ <App />
8
+ </React.StrictMode>,
9
+ );
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@inneranimalmedia/agentsam-shell-example",
3
+ "private": true,
4
+ "type": "module",
5
+ "description": "Phase 0 Gorilla Shell — game-feel CLI UX prototype for Agent Sam SDK",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "react": "^19.1.0",
13
+ "react-dom": "^19.1.0"
14
+ },
15
+ "devDependencies": {
16
+ "@vitejs/plugin-react": "^4.5.2",
17
+ "vite": "^6.3.5"
18
+ }
19
+ }
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ build: {
7
+ outDir: 'dist',
8
+ emptyOutDir: true,
9
+ },
10
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-sdk",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Agent Sam is a full-stack AI agent SDK for autonomous task execution — covering data management, creative workflows, design commands, and multi-step agentic pipelines.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -9,10 +9,12 @@
9
9
  "./package.json": "./package.json"
10
10
  },
11
11
  "bin": {
12
- "agentsam": "./src/cli.js"
12
+ "agentsam": "src/cli.js"
13
13
  },
14
14
  "files": [
15
15
  "src",
16
+ "docs",
17
+ "examples",
16
18
  "test",
17
19
  "README.md",
18
20
  "LICENSE",
package/src/cli.js CHANGED
@@ -3,6 +3,7 @@
3
3
  import readline from 'readline';
4
4
  import pkg from '../package.json' with { type: 'json' };
5
5
  import { scaffoldProject } from './lib/scaffold.js';
6
+ import { SLASH_COMMANDS, SHELL_PHASES } from './lib/slash-commands.js';
6
7
 
7
8
  const VERSION = pkg.version;
8
9
 
@@ -61,6 +62,7 @@ function printHelp() {
61
62
 
62
63
  Usage:
63
64
  agentsam init [options] Scaffold a new Agent Sam project
65
+ agentsam shell CLI shell UX info + slash commands (Gorilla Shell)
64
66
  agentsam --version Print version
65
67
  agentsam --help Show this help
66
68
 
@@ -244,6 +246,30 @@ async function initFromArgs(argv) {
244
246
  });
245
247
  }
246
248
 
249
+ async function runShellInfo() {
250
+ const next = SHELL_PHASES.find((p) => p.status === 'next');
251
+ console.log(`
252
+ ╔═══════════════════════════════════╗
253
+ ║ Agent Sam Shell (Gorilla) ║
254
+ ╚═══════════════════════════════════╝
255
+
256
+ Game-feel terminal UX for SDK installs — HUD, themes, slash commands, PTY bridge.
257
+
258
+ Phase 0 prototype: examples/gorilla-shell/
259
+ Docs: docs/CLI_SHELL.md
260
+ Next milestone: ${next?.label ?? 'PTY connection'}
261
+
262
+ Slash commands (${SLASH_COMMANDS.length} registered):
263
+ `);
264
+ for (const row of SLASH_COMMANDS) {
265
+ console.log(` ${row.cmd.padEnd(14)} ${row.description}`);
266
+ }
267
+ console.log(`
268
+ Run the visual prototype:
269
+ cd examples/gorilla-shell && npm install && npm run dev
270
+ `);
271
+ }
272
+
247
273
  const command = process.argv[2];
248
274
  const rest = process.argv.slice(3);
249
275
 
@@ -251,6 +277,8 @@ if (command === '--version' || command === '-v') {
251
277
  console.log(VERSION);
252
278
  } else if (command === '--help' || command === '-h' || !command) {
253
279
  printHelp();
280
+ } else if (command === 'shell') {
281
+ await runShellInfo();
254
282
  } else if (command === 'init') {
255
283
  const hasFlags = rest.some((a) => a.startsWith('--'));
256
284
  if (hasFlags) {
package/src/index.js CHANGED
@@ -6,6 +6,12 @@ export { AgentSam } from './AgentSam.js';
6
6
  export { routeIntent } from './lib/router.js';
7
7
  export { getToolCatalog } from './lib/tools.js';
8
8
  export { scaffoldProject } from './lib/scaffold.js';
9
+ export {
10
+ SLASH_COMMANDS,
11
+ SHELL_THEMES,
12
+ SHELL_PHASES,
13
+ listSlashCommands,
14
+ } from './lib/slash-commands.js';
9
15
 
10
16
  export const version = pkg.version;
11
17
  export const name = pkg.name;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Canonical slash-command surface for Agent Sam SDK CLI / shell UX.
3
+ * Consumed by the gorilla-shell example and future `agentsam shell` PTY bridge.
4
+ */
5
+
6
+ export const SHELL_THEMES = ['NIGHT', 'DAY', 'LAVA', 'VOID'];
7
+
8
+ /** @type {Array<{ cmd: string, description: string, lane?: string }>} */
9
+ export const SLASH_COMMANDS = [
10
+ { cmd: '/cd', description: 'Change working directory', lane: 'terminal' },
11
+ { cmd: '/pwd', description: 'Print working directory', lane: 'terminal' },
12
+ { cmd: '/gh', description: 'GitHub operations (status, PR, issue)', lane: 'git' },
13
+ { cmd: '/wrangler', description: 'Wrangler deploy and bindings', lane: 'deploy' },
14
+ { cmd: '/workspace', description: 'Switch or show active workspace', lane: 'platform' },
15
+ { cmd: '/samiam', description: 'Agent Sam quick invoke', lane: 'agent' },
16
+ { cmd: '/claude', description: 'Route prompt to Claude arm', lane: 'agent' },
17
+ { cmd: '/codex', description: 'Route prompt to Codex arm', lane: 'agent' },
18
+ { cmd: '/tail', description: 'Tail worker logs', lane: 'observability' },
19
+ { cmd: '/d1', description: 'D1 query helper', lane: 'data' },
20
+ { cmd: '/deploy', description: 'Deploy worker (sandbox or prod gate)', lane: 'deploy' },
21
+ { cmd: '/buddy', description: 'Open Agent Sam buddy panel (MCP)', lane: 'agent' },
22
+ { cmd: '/status', description: 'Platform + project health', lane: 'platform' },
23
+ { cmd: '/diagnostics', description: 'Run diagnostic scenario', lane: 'platform' },
24
+ ];
25
+
26
+ /** Shell UX rollout phases (gorilla-shell → SDK default CLI experience). */
27
+ export const SHELL_PHASES = [
28
+ { id: '0-prototype', label: 'Visual prototype + demo scenarios', status: 'complete' },
29
+ { id: 'pty-connection', label: 'ExecOS / iam-pty WebSocket bridge', status: 'next' },
30
+ { id: 'hud-layer', label: 'Quest log, tool gate, XP HUD', status: 'planned' },
31
+ { id: 'buddy-system', label: 'In-shell Agent Sam via MCP', status: 'planned' },
32
+ { id: 'dashboard-embed', label: 'Embeddable shell for IAM dashboard', status: 'planned' },
33
+ { id: 'standalone-pwa', label: 'Installable PWA / SDK default shell', status: 'planned' },
34
+ ];
35
+
36
+ export function listSlashCommands(opts = {}) {
37
+ const lane = opts.lane ? String(opts.lane).trim().toLowerCase() : '';
38
+ if (!lane) return [...SLASH_COMMANDS];
39
+ return SLASH_COMMANDS.filter((row) => !row.lane || row.lane === lane);
40
+ }
package/test/smoke.mjs CHANGED
@@ -35,4 +35,8 @@ assert.ok(fs.existsSync(path.join(dir, 'src/index.js')));
35
35
  assert.ok(fs.readFileSync(path.join(dir, 'migrations/0001_agentsam_core.sql'), 'utf8').includes('cms_pages'));
36
36
  assert.ok(fs.readFileSync(path.join(dir, 'package.json'), 'utf8').includes('wrangler'));
37
37
 
38
+ import { SLASH_COMMANDS, listSlashCommands } from '../src/lib/slash-commands.js';
39
+ assert.ok(SLASH_COMMANDS.some((c) => c.cmd === '/deploy'));
40
+ assert.equal(listSlashCommands({ lane: 'deploy' }).length, 2);
41
+
38
42
  console.log('SDK smoke tests passed');