@inneranimalmedia/agentsam-sdk 1.5.0 → 1.6.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/README.md +2 -0
- package/package.json +2 -1
- package/src/cli.js +20 -3
- package/src/commands/http-server.js +97 -0
- package/src/commands/tunnel.js +232 -0
- package/src/lib/gorilla-template.js +54 -0
- package/src/lib/local-scaffold.js +32 -8
- package/src/ui/splash-xterm.js +290 -0
- package/src/ui/splash.js +426 -0
- package/src/ui/terminal-lanes.css +162 -0
- package/src/ui/theme.js +315 -0
- package/templates/gorilla-shell/App.tsx +639 -0
- package/templates/gorilla-shell/README.md +22 -0
- package/templates/gorilla-shell/index.html +15 -0
- package/templates/gorilla-shell/main.jsx +9 -0
- package/templates/gorilla-shell/package.json +19 -0
- package/templates/gorilla-shell/vite.config.js +21 -0
- package/test/smoke.mjs +16 -0
package/src/ui/theme.js
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file src/ui/theme.js
|
|
3
|
+
* @description IAM Terminal Theme System — single source of truth for
|
|
4
|
+
* per-lane color identity. Used by:
|
|
5
|
+
* - xterm.js panels in XTermShell.tsx (pass theme object to Terminal constructor)
|
|
6
|
+
* - CLI ANSI output in agentsam-sdk (import ANSI constants)
|
|
7
|
+
* - Splash/HUD renders in both contexts
|
|
8
|
+
*
|
|
9
|
+
* Lane identity:
|
|
10
|
+
* LOCAL → amber (samsmac tunnel, darwin)
|
|
11
|
+
* CLOUD → teal (GCP platform_vm, iam-pty)
|
|
12
|
+
* SANDBOX → purple (CF container, isolated exec)
|
|
13
|
+
*
|
|
14
|
+
* No dependencies. ESM + CJS compatible (conditional exports in package.json).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
// RAW COLOR PALETTE
|
|
19
|
+
// All hex values live here. Nothing else in the codebase hardcodes colors.
|
|
20
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
export const PALETTE = {
|
|
23
|
+
// Shared blacks / neutrals (terminal voids)
|
|
24
|
+
void: '#080808',
|
|
25
|
+
void2: '#0d0d0d',
|
|
26
|
+
void3: '#121212',
|
|
27
|
+
surface: '#1a1a1a',
|
|
28
|
+
muted: '#3d3d3d',
|
|
29
|
+
dim: '#666666',
|
|
30
|
+
subtle: '#888888',
|
|
31
|
+
ghost: '#aaaaaa',
|
|
32
|
+
white: '#e8e8e8',
|
|
33
|
+
|
|
34
|
+
// LOCAL lane — amber/gold (samsmac, darwin_arm64)
|
|
35
|
+
amber900: '#0d0900',
|
|
36
|
+
amber800: '#1a1200',
|
|
37
|
+
amber700: '#2d1f00',
|
|
38
|
+
amber600: '#78450a',
|
|
39
|
+
amber500: '#b56a0f',
|
|
40
|
+
amber400: '#d4820f',
|
|
41
|
+
amber300: '#f59e0b', // PRIMARY amber
|
|
42
|
+
amber200: '#fbbf24',
|
|
43
|
+
amber100: '#fde68a',
|
|
44
|
+
amber050: '#fef3c7',
|
|
45
|
+
|
|
46
|
+
// CLOUD lane — teal/cyan (GCP, iam-pty, platform_vm)
|
|
47
|
+
teal900: '#000d0b',
|
|
48
|
+
teal800: '#001a17',
|
|
49
|
+
teal700: '#002e28',
|
|
50
|
+
teal600: '#065f52',
|
|
51
|
+
teal500: '#0d9488',
|
|
52
|
+
teal400: '#14b8a6',
|
|
53
|
+
teal300: '#22d3c8', // PRIMARY teal
|
|
54
|
+
teal200: '#5eead4',
|
|
55
|
+
teal100: '#99f6e4',
|
|
56
|
+
teal050: '#ccfbf1',
|
|
57
|
+
|
|
58
|
+
// SANDBOX lane — purple (CF container, isolated build exec)
|
|
59
|
+
purple900: '#06020d',
|
|
60
|
+
purple800: '#0d0520',
|
|
61
|
+
purple700: '#1e0a3d',
|
|
62
|
+
purple600: '#4c1d95',
|
|
63
|
+
purple500: '#6d28d9',
|
|
64
|
+
purple400: '#7c3aed',
|
|
65
|
+
purple300: '#a78bfa', // PRIMARY purple
|
|
66
|
+
purple200: '#c4b5fd',
|
|
67
|
+
purple100: '#ddd6fe',
|
|
68
|
+
purple050: '#ede9fe',
|
|
69
|
+
|
|
70
|
+
// Semantic
|
|
71
|
+
success: '#22c55e',
|
|
72
|
+
warning: '#f59e0b',
|
|
73
|
+
error: '#ef4444',
|
|
74
|
+
info: '#38bdf8',
|
|
75
|
+
connecting: '#fb923c',
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
79
|
+
// LANE THEME OBJECTS
|
|
80
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
const makeLane = ({ bg, bgSubtle, primary, secondary, dim, accent, name, label, icon, tunnelHint }) => ({
|
|
83
|
+
meta: { name, label, icon, tunnelHint },
|
|
84
|
+
|
|
85
|
+
xterm: {
|
|
86
|
+
background: bg,
|
|
87
|
+
foreground: '#e8e8e8',
|
|
88
|
+
cursor: primary,
|
|
89
|
+
cursorAccent: bg,
|
|
90
|
+
selectionBackground: primary + '44',
|
|
91
|
+
selectionForeground: '#e8e8e8',
|
|
92
|
+
black: '#080808',
|
|
93
|
+
brightBlack: '#3d3d3d',
|
|
94
|
+
red: '#ef4444',
|
|
95
|
+
brightRed: '#ff6b6b',
|
|
96
|
+
green: '#22c55e',
|
|
97
|
+
brightGreen: '#4ade80',
|
|
98
|
+
yellow: '#f59e0b',
|
|
99
|
+
brightYellow: '#fbbf24',
|
|
100
|
+
blue: '#38bdf8',
|
|
101
|
+
brightBlue: '#7dd3fc',
|
|
102
|
+
magenta: '#a78bfa',
|
|
103
|
+
brightMagenta: '#c4b5fd',
|
|
104
|
+
cyan: '#22d3c8',
|
|
105
|
+
brightCyan: '#5eead4',
|
|
106
|
+
white: '#aaaaaa',
|
|
107
|
+
brightWhite: '#e8e8e8',
|
|
108
|
+
minimumContrastRatio: 4.5,
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
ansi: {
|
|
112
|
+
reset: '\x1b[0m',
|
|
113
|
+
bold: '\x1b[1m',
|
|
114
|
+
dim: '\x1b[2m',
|
|
115
|
+
italic: '\x1b[3m',
|
|
116
|
+
underline: '\x1b[4m',
|
|
117
|
+
primary: `\x1b[38;2;${hexToRgb(primary)}m`,
|
|
118
|
+
secondary: `\x1b[38;2;${hexToRgb(secondary)}m`,
|
|
119
|
+
dimColor: `\x1b[38;2;${hexToRgb(dim)}m`,
|
|
120
|
+
accent: `\x1b[38;2;${hexToRgb(accent)}m`,
|
|
121
|
+
white: `\x1b[38;2;232;232;232m`,
|
|
122
|
+
ghost: `\x1b[38;2;136;136;136m`,
|
|
123
|
+
success: `\x1b[38;2;34;197;94m`,
|
|
124
|
+
warning: `\x1b[38;2;245;158;11m`,
|
|
125
|
+
error: `\x1b[38;2;239;68;68m`,
|
|
126
|
+
info: `\x1b[38;2;56;189;248m`,
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
colors: { bg, bgSubtle, primary, secondary, dim, accent },
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
133
|
+
// THE THREE LANES
|
|
134
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
export const LOCAL = makeLane({
|
|
137
|
+
name: 'local', label: 'Local', icon: '◈',
|
|
138
|
+
tunnelHint: 'samsmac → localpty.inneranimalmedia.com',
|
|
139
|
+
bg: '#0d0900', bgSubtle: '#1a1200',
|
|
140
|
+
primary: '#f59e0b', secondary: '#fbbf24', dim: '#78450a', accent: '#22d3c8',
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
export const CLOUD = makeLane({
|
|
144
|
+
name: 'cloud', label: 'Cloud', icon: '●',
|
|
145
|
+
tunnelHint: 'inneranimalmedia → terminal.inneranimalmedia.com (GCP iam-tunnel)',
|
|
146
|
+
bg: '#000d0b', bgSubtle: '#001a17',
|
|
147
|
+
primary: '#22d3c8', secondary: '#5eead4', dim: '#065f52', accent: '#f59e0b',
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export const SANDBOX = makeLane({
|
|
151
|
+
name: 'sandbox', label: 'Sandbox', icon: '◌',
|
|
152
|
+
tunnelHint: 'CF Container → MY_CONTAINER DO (inneranimalmedia)',
|
|
153
|
+
bg: '#06020d', bgSubtle: '#0d0520',
|
|
154
|
+
primary: '#a78bfa', secondary: '#c4b5fd', dim: '#4c1d95', accent: '#22d3c8',
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
158
|
+
// LOOKUP HELPERS
|
|
159
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get lane theme by D1 target_type string.
|
|
163
|
+
* @param {'user_hosted_tunnel'|'platform_vm'|'sandbox'|string} targetType
|
|
164
|
+
*/
|
|
165
|
+
export function getLaneTheme(targetType) {
|
|
166
|
+
switch (targetType) {
|
|
167
|
+
case 'user_hosted_tunnel': return LOCAL;
|
|
168
|
+
case 'platform_vm': return CLOUD;
|
|
169
|
+
case 'sandbox': return SANDBOX;
|
|
170
|
+
default: return CLOUD;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get lane theme by name string (for SDK CLI use).
|
|
176
|
+
* @param {'local'|'cloud'|'sandbox'|string} name
|
|
177
|
+
*/
|
|
178
|
+
export function getLaneThemeByName(name) {
|
|
179
|
+
switch (name?.toLowerCase()) {
|
|
180
|
+
case 'local': return LOCAL;
|
|
181
|
+
case 'cloud': return CLOUD;
|
|
182
|
+
case 'sandbox': return SANDBOX;
|
|
183
|
+
default: return CLOUD;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** All lanes as ordered array */
|
|
188
|
+
export const LANES = [LOCAL, CLOUD, SANDBOX];
|
|
189
|
+
|
|
190
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
191
|
+
// STATUS SYMBOLS
|
|
192
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
export const STATUS = {
|
|
195
|
+
ready: '●',
|
|
196
|
+
connecting: '◐',
|
|
197
|
+
pending: '◌',
|
|
198
|
+
active: '◈',
|
|
199
|
+
error: '✗',
|
|
200
|
+
disabled: '○',
|
|
201
|
+
arrow: '▸',
|
|
202
|
+
check: '✓',
|
|
203
|
+
spinner: ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'],
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
207
|
+
// CLI RENDER HELPERS
|
|
208
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
209
|
+
|
|
210
|
+
export function renderDivider(lane, width = 72) {
|
|
211
|
+
const { primary, reset } = lane.ansi;
|
|
212
|
+
return `${primary}${'─'.repeat(width)}${reset}`;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function renderBanner(lane, title, width = 72) {
|
|
216
|
+
const { primary, accent, reset, bold } = lane.ansi;
|
|
217
|
+
const padded = ` ${title} `;
|
|
218
|
+
const sideLen = Math.max(0, Math.floor((width - padded.length) / 2));
|
|
219
|
+
const side = '─'.repeat(sideLen);
|
|
220
|
+
return `${primary}${side}${reset}${accent}${bold}${padded}${reset}${primary}${side}${reset}\n`;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function renderLaneRow(lane, status, description, isActive = false) {
|
|
224
|
+
const { primary, ghost, reset, bold } = lane.ansi;
|
|
225
|
+
const sym = STATUS[status] || STATUS.pending;
|
|
226
|
+
const arrow = isActive ? `${primary}${STATUS.arrow}${reset} ` : ' ';
|
|
227
|
+
let symColor;
|
|
228
|
+
switch (status) {
|
|
229
|
+
case 'ready': symColor = `\x1b[38;2;34;197;94m`; break;
|
|
230
|
+
case 'connecting': symColor = `\x1b[38;2;251;146;60m`; break;
|
|
231
|
+
case 'error': symColor = `\x1b[38;2;239;68;68m`; break;
|
|
232
|
+
default: symColor = `\x1b[38;2;102;102;102m`; break;
|
|
233
|
+
}
|
|
234
|
+
return [
|
|
235
|
+
`${arrow}${symColor}${sym}${reset} `,
|
|
236
|
+
`${bold}${primary}${lane.meta.label.padEnd(10)}${reset}`,
|
|
237
|
+
`${ghost}${description}${reset}`,
|
|
238
|
+
].join('');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function renderSlashCmd(lane, cmd, description) {
|
|
242
|
+
const { primary, ghost, reset, bold } = lane.ansi;
|
|
243
|
+
return ` ${bold}${primary}${cmd.padEnd(16)}${reset}${ghost}${description}${reset}`;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function renderSpinner(lane, label, tick) {
|
|
247
|
+
const { primary, ghost, reset } = lane.ansi;
|
|
248
|
+
const frame = STATUS.spinner[tick % STATUS.spinner.length];
|
|
249
|
+
return `${primary}${frame}${reset} ${ghost}${label}${reset}`;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function renderKV(lane, key, value) {
|
|
253
|
+
const { ghost, white, reset } = lane.ansi;
|
|
254
|
+
return ` ${ghost}${key.padEnd(14)}${reset}${white}${value}${reset}`;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
258
|
+
// XTERM.JS INTEGRATION
|
|
259
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Get complete xterm.js Terminal options for a given lane.
|
|
263
|
+
* @param {'user_hosted_tunnel'|'platform_vm'|'sandbox'} targetType
|
|
264
|
+
*/
|
|
265
|
+
export function getXtermOptions(targetType) {
|
|
266
|
+
const lane = getLaneTheme(targetType);
|
|
267
|
+
return {
|
|
268
|
+
theme: lane.xterm,
|
|
269
|
+
fontFamily: '"Cascadia Code", "JetBrains Mono", "Fira Code", monospace',
|
|
270
|
+
fontSize: 13,
|
|
271
|
+
lineHeight: 1.4,
|
|
272
|
+
letterSpacing: 0.3,
|
|
273
|
+
cursorBlink: true,
|
|
274
|
+
cursorStyle: 'block',
|
|
275
|
+
scrollback: 5000,
|
|
276
|
+
allowProposedApi: true,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Get CSS custom property string for a lane — inject on terminal panel wrapper.
|
|
282
|
+
* @param {'user_hosted_tunnel'|'platform_vm'|'sandbox'} targetType
|
|
283
|
+
*/
|
|
284
|
+
export function getLaneCSSVars(targetType) {
|
|
285
|
+
const lane = getLaneTheme(targetType);
|
|
286
|
+
const { primary, secondary, bg, bgSubtle, dim, accent } = lane.colors;
|
|
287
|
+
return [
|
|
288
|
+
`--lane-primary: ${primary};`,
|
|
289
|
+
`--lane-secondary: ${secondary};`,
|
|
290
|
+
`--lane-bg: ${bg};`,
|
|
291
|
+
`--lane-bg-subtle: ${bgSubtle};`,
|
|
292
|
+
`--lane-dim: ${dim};`,
|
|
293
|
+
`--lane-accent: ${accent};`,
|
|
294
|
+
`--lane-name: "${lane.meta.name}";`,
|
|
295
|
+
].join(' ');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
299
|
+
// INTERNAL
|
|
300
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
301
|
+
|
|
302
|
+
function hexToRgb(hex) {
|
|
303
|
+
const h = hex.replace('#', '');
|
|
304
|
+
const r = parseInt(h.substring(0, 2), 16);
|
|
305
|
+
const g = parseInt(h.substring(2, 4), 16);
|
|
306
|
+
const b = parseInt(h.substring(4, 6), 16);
|
|
307
|
+
return `${r};${g};${b}`;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export default {
|
|
311
|
+
PALETTE, STATUS, LOCAL, CLOUD, SANDBOX, LANES,
|
|
312
|
+
getLaneTheme, getLaneThemeByName, getXtermOptions, getLaneCSSVars,
|
|
313
|
+
renderDivider, renderBanner, renderLaneRow, renderSlashCmd,
|
|
314
|
+
renderSpinner, renderKV,
|
|
315
|
+
};
|