@castari/cli 0.0.7 → 0.0.9
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/dist/commands/init.js +304 -112
- package/dist/commands/start.js +4 -1
- package/package.json +2 -2
package/dist/commands/init.js
CHANGED
|
@@ -26,7 +26,7 @@ export async function init(options = {}) {
|
|
|
26
26
|
},
|
|
27
27
|
dependencies: {
|
|
28
28
|
'@castari/sdk': '^0.0.6',
|
|
29
|
-
'@anthropic-ai/claude-agent-sdk': '^0.1.
|
|
29
|
+
'@anthropic-ai/claude-agent-sdk': '^0.1.50',
|
|
30
30
|
},
|
|
31
31
|
castari: {
|
|
32
32
|
volume: 'default-data',
|
|
@@ -41,8 +41,7 @@ export async function init(options = {}) {
|
|
|
41
41
|
skipLibCheck: true,
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
|
-
const agentTs = `import { serve } from '@castari/sdk
|
|
45
|
-
import { tool } from '@castari/sdk'
|
|
44
|
+
const agentTs = `import { serve, tool } from '@castari/sdk'
|
|
46
45
|
|
|
47
46
|
// Define your agent tools and logic here
|
|
48
47
|
const myTool = tool({
|
|
@@ -65,7 +64,7 @@ serve({
|
|
|
65
64
|
systemPrompt: 'You are a helpful Castari agent.',
|
|
66
65
|
})
|
|
67
66
|
`;
|
|
68
|
-
const envExample = `ANTHROPIC_API_KEY=sk-ant-...\nCASTARI_CLIENT_ID=your-client-id\n# CASTARI_PLATFORM_URL=https://api.castari.com\n`;
|
|
67
|
+
const envExample = `ANTHROPIC_API_KEY=sk-ant-...\nCASTARI_CLIENT_ID=your-client-id\nCASTARI_API_KEY=castari_your-api-key\n# CASTARI_PLATFORM_URL=https://api.castari.com\n`;
|
|
69
68
|
await writeFile('package.json', JSON.stringify(packageJson, null, 2));
|
|
70
69
|
await writeFile('tsconfig.json', JSON.stringify(tsConfig, null, 2));
|
|
71
70
|
await writeFile('.env.example', envExample);
|
|
@@ -111,7 +110,7 @@ async function initDemo() {
|
|
|
111
110
|
},
|
|
112
111
|
include: ['src'],
|
|
113
112
|
});
|
|
114
|
-
await writeFile(join(agentDir, '.env.example'), 'ANTHROPIC_API_KEY=sk-ant-...\nCASTARI_CLIENT_ID=your-client-id\n# CASTARI_PLATFORM_URL=http://localhost:3000\n');
|
|
113
|
+
await writeFile(join(agentDir, '.env.example'), 'ANTHROPIC_API_KEY=sk-ant-...\nCASTARI_CLIENT_ID=your-client-id\nCASTARI_API_KEY=castari_your-api-key\n# CASTARI_PLATFORM_URL=http://localhost:3000\n');
|
|
115
114
|
await writeFile(join(agentDir, 'src', 'agent.ts'), `import { serve } from '@castari/sdk'
|
|
116
115
|
|
|
117
116
|
serve({
|
|
@@ -126,6 +125,7 @@ serve({
|
|
|
126
125
|
// Web scaffold
|
|
127
126
|
await mkdir(join(webDir, 'app', 'api', 'chat'), { recursive: true });
|
|
128
127
|
await mkdir(join(webDir, 'lib'), { recursive: true });
|
|
128
|
+
await mkdir(join(webDir, 'public'), { recursive: true });
|
|
129
129
|
await writeJson(join(webDir, 'package.json'), {
|
|
130
130
|
name: 'castari-demo-web',
|
|
131
131
|
version: '0.1.0',
|
|
@@ -187,11 +187,16 @@ const nextConfig = {
|
|
|
187
187
|
|
|
188
188
|
export default nextConfig
|
|
189
189
|
`);
|
|
190
|
-
await writeFile(join(webDir, '.env.example'), 'ANTHROPIC_API_KEY=sk-ant-...\nCASTARI_CLIENT_ID=your-client-id\n# CASTARI_PLATFORM_URL=http://localhost:3000\n# CASTARI_DEBUG=false\n');
|
|
190
|
+
await writeFile(join(webDir, '.env.example'), 'ANTHROPIC_API_KEY=sk-ant-...\nCASTARI_CLIENT_ID=your-client-id\nCASTARI_API_KEY=castari_your-api-key\n# CASTARI_PLATFORM_URL=http://localhost:3000\n# CASTARI_DEBUG=false\n');
|
|
191
191
|
await writeFile(join(webDir, 'app', 'globals.css'), `:root {
|
|
192
|
-
color-scheme:
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
color-scheme: dark;
|
|
193
|
+
--bg: #131418;
|
|
194
|
+
--panel: #1c1d24;
|
|
195
|
+
--border: #2a2b36;
|
|
196
|
+
--muted: #888888;
|
|
197
|
+
--text: #ffffff;
|
|
198
|
+
--accent: #ffffff;
|
|
199
|
+
font-family: var(--font-inter), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
195
200
|
}
|
|
196
201
|
|
|
197
202
|
* {
|
|
@@ -200,9 +205,10 @@ export default nextConfig
|
|
|
200
205
|
|
|
201
206
|
body {
|
|
202
207
|
margin: 0;
|
|
203
|
-
background:
|
|
204
|
-
color:
|
|
208
|
+
background-color: var(--bg);
|
|
209
|
+
color: var(--text);
|
|
205
210
|
min-height: 100vh;
|
|
211
|
+
font-weight: 300;
|
|
206
212
|
}
|
|
207
213
|
|
|
208
214
|
a {
|
|
@@ -210,139 +216,261 @@ a {
|
|
|
210
216
|
text-decoration: none;
|
|
211
217
|
}
|
|
212
218
|
|
|
213
|
-
.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
219
|
+
.page-shell {
|
|
220
|
+
position: relative;
|
|
221
|
+
min-height: 100vh;
|
|
222
|
+
overflow: hidden;
|
|
223
|
+
display: flex;
|
|
224
|
+
justify-content: center;
|
|
225
|
+
padding: 36px 20px 72px;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.content {
|
|
229
|
+
position: relative;
|
|
230
|
+
width: min(1180px, 100%);
|
|
217
231
|
display: flex;
|
|
218
232
|
flex-direction: column;
|
|
219
|
-
gap:
|
|
233
|
+
gap: 28px;
|
|
234
|
+
z-index: 1;
|
|
220
235
|
}
|
|
221
236
|
|
|
222
|
-
.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
padding:
|
|
237
|
+
.topbar {
|
|
238
|
+
display: flex;
|
|
239
|
+
align-items: center;
|
|
240
|
+
justify-content: space-between;
|
|
241
|
+
gap: 12px;
|
|
242
|
+
flex-wrap: wrap;
|
|
243
|
+
padding-bottom: 12px;
|
|
244
|
+
border-bottom: 1px solid var(--border);
|
|
229
245
|
}
|
|
230
246
|
|
|
231
|
-
.
|
|
247
|
+
.brand {
|
|
232
248
|
display: flex;
|
|
233
249
|
align-items: center;
|
|
250
|
+
gap: 14px;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.brand-logo {
|
|
254
|
+
width: 32px;
|
|
255
|
+
height: auto;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.brand-name {
|
|
259
|
+
font-family: var(--font-orbitron), 'Orbitron', sans-serif;
|
|
260
|
+
letter-spacing: 0.06em;
|
|
261
|
+
text-transform: uppercase;
|
|
262
|
+
font-size: 18px;
|
|
263
|
+
color: var(--text);
|
|
264
|
+
font-weight: 600;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.top-pills {
|
|
268
|
+
display: flex;
|
|
269
|
+
gap: 8px;
|
|
270
|
+
flex-wrap: wrap;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.hero {
|
|
274
|
+
display: flex;
|
|
275
|
+
flex-direction: column;
|
|
234
276
|
gap: 12px;
|
|
235
|
-
|
|
236
|
-
|
|
277
|
+
padding: 40px 0 20px;
|
|
278
|
+
align-items: center;
|
|
279
|
+
text-align: center;
|
|
237
280
|
}
|
|
238
281
|
|
|
239
|
-
.
|
|
240
|
-
font-
|
|
282
|
+
.hero-title {
|
|
283
|
+
font-family: var(--font-orbitron), 'Orbitron', sans-serif;
|
|
284
|
+
font-size: clamp(30px, 4vw, 44px);
|
|
285
|
+
margin: 0;
|
|
286
|
+
letter-spacing: 0.02em;
|
|
241
287
|
font-weight: 600;
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.hero-copy {
|
|
291
|
+
color: var(--muted);
|
|
292
|
+
font-size: 18px;
|
|
293
|
+
line-height: 1.6;
|
|
294
|
+
max-width: 600px;
|
|
295
|
+
margin: 0;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.card {
|
|
299
|
+
position: relative;
|
|
300
|
+
background: var(--panel);
|
|
301
|
+
border: 1px solid var(--border);
|
|
302
|
+
border-radius: 20px;
|
|
303
|
+
padding: 22px;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.panel {
|
|
307
|
+
overflow: hidden;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.panel-header {
|
|
311
|
+
display: flex;
|
|
312
|
+
align-items: center;
|
|
313
|
+
justify-content: space-between;
|
|
314
|
+
gap: 14px;
|
|
315
|
+
flex-wrap: wrap;
|
|
316
|
+
margin-bottom: 20px;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.panel-title {
|
|
320
|
+
font-size: 18px;
|
|
321
|
+
font-weight: 500;
|
|
322
|
+
margin: 0;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.panel-copy {
|
|
326
|
+
color: var(--muted);
|
|
327
|
+
font-size: 14px;
|
|
328
|
+
margin: 4px 0 0;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.pill-row {
|
|
332
|
+
display: flex;
|
|
333
|
+
gap: 8px;
|
|
334
|
+
flex-wrap: wrap;
|
|
335
|
+
margin-bottom: 12px;
|
|
247
336
|
}
|
|
248
337
|
|
|
249
338
|
.messages {
|
|
250
339
|
display: flex;
|
|
251
340
|
flex-direction: column;
|
|
252
341
|
gap: 12px;
|
|
342
|
+
background: #16171d;
|
|
343
|
+
border: 1px solid var(--border);
|
|
344
|
+
border-radius: 16px;
|
|
345
|
+
padding: 14px;
|
|
346
|
+
min-height: 300px;
|
|
253
347
|
}
|
|
254
348
|
|
|
255
349
|
.bubble {
|
|
256
350
|
padding: 14px 16px;
|
|
257
351
|
border-radius: 14px;
|
|
258
|
-
max-width: 90%;
|
|
259
352
|
line-height: 1.5;
|
|
260
353
|
font-size: 15px;
|
|
354
|
+
max-width: 85%;
|
|
261
355
|
}
|
|
262
356
|
|
|
263
357
|
.bubble.assistant {
|
|
264
|
-
background: #
|
|
265
|
-
color:
|
|
358
|
+
background: #1c1d24;
|
|
359
|
+
color: var(--text);
|
|
266
360
|
align-self: flex-start;
|
|
267
|
-
border
|
|
361
|
+
border: 1px solid var(--border);
|
|
268
362
|
}
|
|
269
363
|
|
|
270
364
|
.bubble.user {
|
|
271
|
-
background:
|
|
272
|
-
color: #
|
|
273
|
-
border: 1px solid rgba(15, 23, 42, 0.06);
|
|
365
|
+
background: #ffffff;
|
|
366
|
+
color: #000000;
|
|
274
367
|
align-self: flex-end;
|
|
275
|
-
border-bottom-right-radius: 4px;
|
|
276
368
|
}
|
|
277
369
|
|
|
278
370
|
.form {
|
|
279
371
|
display: flex;
|
|
280
372
|
gap: 12px;
|
|
281
|
-
|
|
373
|
+
align-items: center;
|
|
374
|
+
margin-top: 16px;
|
|
375
|
+
background: #16171d;
|
|
376
|
+
border: 1px solid var(--border);
|
|
377
|
+
border-radius: 14px;
|
|
378
|
+
padding: 10px;
|
|
282
379
|
}
|
|
283
380
|
|
|
284
381
|
.input {
|
|
285
382
|
flex: 1;
|
|
286
|
-
padding: 14px
|
|
383
|
+
padding: 12px 14px;
|
|
287
384
|
border-radius: 12px;
|
|
288
|
-
border: 1px solid
|
|
385
|
+
border: 1px solid transparent;
|
|
289
386
|
font-size: 15px;
|
|
290
387
|
outline: none;
|
|
291
|
-
|
|
388
|
+
background: transparent;
|
|
389
|
+
color: var(--text);
|
|
292
390
|
}
|
|
293
391
|
|
|
294
|
-
.input
|
|
295
|
-
|
|
296
|
-
box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.12);
|
|
392
|
+
.input::placeholder {
|
|
393
|
+
color: #666666;
|
|
297
394
|
}
|
|
298
395
|
|
|
299
396
|
.button {
|
|
300
|
-
background:
|
|
301
|
-
color:
|
|
397
|
+
background: #ffffff;
|
|
398
|
+
color: #000000;
|
|
302
399
|
border: none;
|
|
303
400
|
border-radius: 12px;
|
|
304
|
-
padding: 12px
|
|
305
|
-
font-weight:
|
|
401
|
+
padding: 12px 24px;
|
|
402
|
+
font-weight: 600;
|
|
306
403
|
cursor: pointer;
|
|
307
|
-
|
|
308
|
-
min-width: 110px;
|
|
309
|
-
transition: transform 0.12s ease, box-shadow 0.12s ease, opacity 0.12s ease;
|
|
404
|
+
transition: opacity 0.2s;
|
|
310
405
|
}
|
|
311
406
|
|
|
312
407
|
.button:disabled {
|
|
313
|
-
opacity: 0.
|
|
408
|
+
opacity: 0.5;
|
|
314
409
|
cursor: not-allowed;
|
|
315
|
-
box-shadow: none;
|
|
316
410
|
}
|
|
317
411
|
|
|
318
|
-
.button:not(:disabled)
|
|
319
|
-
|
|
320
|
-
box-shadow: 0 16px 30px rgba(99, 102, 241, 0.45);
|
|
412
|
+
.button:hover:not(:disabled) {
|
|
413
|
+
opacity: 0.9;
|
|
321
414
|
}
|
|
322
415
|
|
|
323
416
|
.status {
|
|
324
417
|
font-size: 13px;
|
|
325
|
-
color:
|
|
326
|
-
margin-top:
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
.pill-row {
|
|
330
|
-
display: flex;
|
|
331
|
-
gap: 8px;
|
|
332
|
-
flex-wrap: wrap;
|
|
418
|
+
color: var(--muted);
|
|
419
|
+
margin-top: 10px;
|
|
420
|
+
text-align: center;
|
|
333
421
|
}
|
|
334
422
|
|
|
335
423
|
.pill {
|
|
336
|
-
|
|
424
|
+
display: inline-flex;
|
|
425
|
+
align-items: center;
|
|
426
|
+
gap: 8px;
|
|
427
|
+
padding: 6px 12px;
|
|
337
428
|
border-radius: 999px;
|
|
338
|
-
|
|
429
|
+
border: 1px solid var(--border);
|
|
430
|
+
background: transparent;
|
|
431
|
+
color: var(--muted);
|
|
339
432
|
font-size: 12px;
|
|
340
|
-
|
|
341
|
-
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.pill-accent {
|
|
436
|
+
color: var(--text);
|
|
437
|
+
border-color: var(--text);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.pill-ghost {
|
|
441
|
+
border-color: var(--border);
|
|
442
|
+
color: var(--muted);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
@media (max-width: 720px) {
|
|
446
|
+
.page-shell {
|
|
447
|
+
padding: 28px 16px 56px;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.form {
|
|
451
|
+
flex-direction: column;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.button {
|
|
455
|
+
width: 100%;
|
|
456
|
+
}
|
|
342
457
|
}
|
|
343
458
|
`);
|
|
344
459
|
await writeFile(join(webDir, 'app', 'layout.tsx'), `import './globals.css'
|
|
345
460
|
import { ReactNode } from 'react'
|
|
461
|
+
import { Inter, Orbitron } from 'next/font/google'
|
|
462
|
+
|
|
463
|
+
const inter = Inter({
|
|
464
|
+
subsets: ['latin'],
|
|
465
|
+
weight: ['300', '500', '700'],
|
|
466
|
+
variable: '--font-inter',
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
const orbitron = Orbitron({
|
|
470
|
+
subsets: ['latin'],
|
|
471
|
+
weight: ['600'],
|
|
472
|
+
variable: '--font-orbitron',
|
|
473
|
+
})
|
|
346
474
|
|
|
347
475
|
export default function RootLayout({ children }: { children: ReactNode }) {
|
|
348
476
|
return (
|
|
@@ -350,7 +478,7 @@ export default function RootLayout({ children }: { children: ReactNode }) {
|
|
|
350
478
|
<head>
|
|
351
479
|
<title>Castari Demo Chat</title>
|
|
352
480
|
</head>
|
|
353
|
-
<body>{children}</body>
|
|
481
|
+
<body className={\`\${inter.variable} \${orbitron.variable}\`}>{children}</body>
|
|
354
482
|
</html>
|
|
355
483
|
)
|
|
356
484
|
}
|
|
@@ -358,6 +486,7 @@ export default function RootLayout({ children }: { children: ReactNode }) {
|
|
|
358
486
|
await writeFile(join(webDir, 'app', 'page.tsx'), `"use client"
|
|
359
487
|
|
|
360
488
|
import { FormEvent, useState } from 'react'
|
|
489
|
+
import Image from 'next/image'
|
|
361
490
|
|
|
362
491
|
type ChatMessage = {
|
|
363
492
|
role: 'assistant' | 'user'
|
|
@@ -437,43 +566,68 @@ export default function Home() {
|
|
|
437
566
|
}
|
|
438
567
|
|
|
439
568
|
return (
|
|
440
|
-
<main className="
|
|
441
|
-
<div className="
|
|
442
|
-
<
|
|
443
|
-
<
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
<span className="pill">Volume: castari-demo-workspace</span>
|
|
454
|
-
<span className="pill">Labels: app=castari-demo, env=local</span>
|
|
455
|
-
</div>
|
|
456
|
-
|
|
457
|
-
<div className="messages">
|
|
458
|
-
{messages.map((m, idx) => (
|
|
459
|
-
<div key={idx} className={\`bubble \${m.role}\`}>
|
|
460
|
-
{m.content}
|
|
569
|
+
<main className="page-shell">
|
|
570
|
+
<div className="content">
|
|
571
|
+
<header className="topbar">
|
|
572
|
+
<div className="brand">
|
|
573
|
+
<Image
|
|
574
|
+
src="/logo.svg"
|
|
575
|
+
alt="Castari Logo"
|
|
576
|
+
width={32}
|
|
577
|
+
height={32}
|
|
578
|
+
className="brand-logo"
|
|
579
|
+
/>
|
|
580
|
+
<div>
|
|
581
|
+
<div className="brand-name">Castari</div>
|
|
461
582
|
</div>
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
583
|
+
</div>
|
|
584
|
+
|
|
585
|
+
<div className="top-pills">
|
|
586
|
+
<span className="pill pill-ghost">Demo sandbox</span>
|
|
587
|
+
</div>
|
|
588
|
+
</header>
|
|
589
|
+
|
|
590
|
+
<section className="hero">
|
|
591
|
+
<h1 className="hero-title">Production-Ready Agents</h1>
|
|
592
|
+
<p className="hero-copy">
|
|
593
|
+
Secure, sandboxed AI agents for your infrastructure.
|
|
594
|
+
</p>
|
|
595
|
+
</section>
|
|
596
|
+
|
|
597
|
+
<section className="card panel">
|
|
598
|
+
<div className="panel-header">
|
|
599
|
+
<div>
|
|
600
|
+
<div className="panel-title">Chat with Castari</div>
|
|
601
|
+
</div>
|
|
602
|
+
<span className="pill pill-accent">Live</span>
|
|
603
|
+
</div>
|
|
604
|
+
|
|
605
|
+
<div className="pill-row">
|
|
606
|
+
<span className="pill">Snapshot: castari-demo-agent</span>
|
|
607
|
+
<span className="pill">Volume: castari-demo-workspace</span>
|
|
608
|
+
</div>
|
|
609
|
+
|
|
610
|
+
<div className="messages">
|
|
611
|
+
{messages.map((m, idx) => (
|
|
612
|
+
<div key={idx} className={\`bubble \${m.role}\`}>
|
|
613
|
+
{m.content}
|
|
614
|
+
</div>
|
|
615
|
+
))}
|
|
616
|
+
</div>
|
|
617
|
+
|
|
618
|
+
<form className="form" onSubmit={sendMessage}>
|
|
619
|
+
<input
|
|
620
|
+
className="input"
|
|
621
|
+
placeholder="Ask the Castari agent anything..."
|
|
622
|
+
value={input}
|
|
623
|
+
onChange={e => setInput(e.target.value)}
|
|
624
|
+
/>
|
|
625
|
+
<button className="button" type="submit" disabled={sending}>
|
|
626
|
+
{sending ? 'Talking…' : 'Send'}
|
|
627
|
+
</button>
|
|
628
|
+
</form>
|
|
629
|
+
{status && <div className="status">{status}</div>}
|
|
630
|
+
</section>
|
|
477
631
|
</div>
|
|
478
632
|
</main>
|
|
479
633
|
)
|
|
@@ -495,10 +649,11 @@ async function createClient() {
|
|
|
495
649
|
|
|
496
650
|
const client = new CastariClient({
|
|
497
651
|
snapshot: SNAPSHOT,
|
|
498
|
-
volume: VOLUME,
|
|
652
|
+
// volume: VOLUME, // opt-in; omit to run ephemeral unless provided
|
|
499
653
|
labels: LABELS,
|
|
500
654
|
platformUrl: process.env.CASTARI_PLATFORM_URL,
|
|
501
655
|
clientId: process.env.CASTARI_CLIENT_ID,
|
|
656
|
+
platformApiKey: process.env.CASTARI_API_KEY,
|
|
502
657
|
anthropicApiKey,
|
|
503
658
|
debug: process.env.CASTARI_DEBUG === 'true',
|
|
504
659
|
})
|
|
@@ -652,6 +807,35 @@ export async function POST(request: Request) {
|
|
|
652
807
|
},
|
|
653
808
|
})
|
|
654
809
|
}
|
|
810
|
+
`);
|
|
811
|
+
// Logo SVG
|
|
812
|
+
await writeFile(join(webDir, 'public', 'logo.svg'), `<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
813
|
+
<path d="M0 32L31.619 0L63.2381 32L31.619 64L0 32Z" fill="#A44A0C"/>
|
|
814
|
+
<path d="M31.527 31.8743H6.87042L24.3595 24.3417L31.527 7.24737V31.8743Z" fill="white"/>
|
|
815
|
+
<path d="M31.527 31.8743H6.87042L24.3595 24.3417L31.527 31.8743Z" fill="url(#paint0_linear_173_2089)"/>
|
|
816
|
+
<path d="M31.5268 31.872L31.5192 6.91829L24.0817 24.6204L31.5268 31.872Z" fill="url(#paint1_linear_173_2089)"/>
|
|
817
|
+
<path d="M31.7116 32.128L31.7192 57.0817L38.9973 39.3796L31.7116 32.128Z" fill="url(#paint2_linear_173_2089)"/>
|
|
818
|
+
<path d="M31.7117 32.1258H56.3683L38.8792 39.6584L31.7117 56.7527V32.1258Z" fill="white"/>
|
|
819
|
+
<path d="M31.7117 32.1258H56.3683L38.8792 39.6584L31.7117 32.1258Z" fill="url(#paint3_linear_173_2089)"/>
|
|
820
|
+
<defs>
|
|
821
|
+
<linearGradient id="paint0_linear_173_2089" x1="53.6475" y1="32.6825" x2="36.7362" y2="37.9872" gradientUnits="userSpaceOnUse">
|
|
822
|
+
<stop stop-color="#F8F8F8"/>
|
|
823
|
+
<stop offset="1" stop-color="#EACAB4"/>
|
|
824
|
+
</linearGradient>
|
|
825
|
+
<linearGradient id="paint1_linear_173_2089" x1="6.97479" y1="59.2675" x2="54.1923" y2="54.7965" gradientUnits="userSpaceOnUse">
|
|
826
|
+
<stop stop-color="white"/>
|
|
827
|
+
<stop offset="1" stop-color="#EDEDED"/>
|
|
828
|
+
</linearGradient>
|
|
829
|
+
<linearGradient id="paint2_linear_173_2089" x1="6.97479" y1="59.2675" x2="54.1923" y2="54.7965" gradientUnits="userSpaceOnUse">
|
|
830
|
+
<stop stop-color="white"/>
|
|
831
|
+
<stop offset="1" stop-color="#EDEDED"/>
|
|
832
|
+
</linearGradient>
|
|
833
|
+
<linearGradient id="paint3_linear_173_2089" x1="53.6475" y1="32.6825" x2="36.7362" y2="37.9872" gradientUnits="userSpaceOnUse">
|
|
834
|
+
<stop stop-color="#F8F8F8"/>
|
|
835
|
+
<stop offset="1" stop-color="#EACAB4"/>
|
|
836
|
+
</linearGradient>
|
|
837
|
+
</defs>
|
|
838
|
+
</svg>
|
|
655
839
|
`);
|
|
656
840
|
// Demo README
|
|
657
841
|
await writeFile(join(demoRoot, 'README.md'), `# Castari Demo (Web + Agent)
|
|
@@ -666,12 +850,20 @@ Structure:
|
|
|
666
850
|
- Bun (for the Castari CLI and scripts)
|
|
667
851
|
- Node 18+ (for the Next.js app)
|
|
668
852
|
- \`ANTHROPIC_API_KEY\`
|
|
853
|
+
- Castari credentials (\`CASTARI_CLIENT_ID\` and \`CASTARI_API_KEY\`)
|
|
669
854
|
- Castari Platform running locally or reachable via \`CASTARI_PLATFORM_URL\`
|
|
670
855
|
|
|
856
|
+
## Getting Castari Credentials
|
|
857
|
+
Generate your clientId and apiKey by running:
|
|
858
|
+
\`\`\`bash
|
|
859
|
+
castari generate-client-id
|
|
860
|
+
\`\`\`
|
|
861
|
+
Or via the Castari Platform Console if available.
|
|
862
|
+
|
|
671
863
|
## 1) Prepare and deploy the agent
|
|
672
864
|
\`\`\`bash
|
|
673
865
|
cd castari_demo/agent
|
|
674
|
-
cp .env.example .env # add ANTHROPIC_API_KEY
|
|
866
|
+
cp .env.example .env # add ANTHROPIC_API_KEY, CASTARI_CLIENT_ID, CASTARI_API_KEY
|
|
675
867
|
bun install # pulls @castari/sdk from npm
|
|
676
868
|
castari deploy # builds snapshot castari-demo-agent (CLI must be installed)
|
|
677
869
|
# Optional: bun run src/agent.ts # run locally without the CLI
|
|
@@ -680,7 +872,7 @@ castari deploy # builds snapshot castari-demo-agent (CLI must be installe
|
|
|
680
872
|
## 2) Run the web app
|
|
681
873
|
\`\`\`bash
|
|
682
874
|
cd ../web
|
|
683
|
-
cp .env.example .env # add ANTHROPIC_API_KEY
|
|
875
|
+
cp .env.example .env # add ANTHROPIC_API_KEY, CASTARI_CLIENT_ID, CASTARI_API_KEY
|
|
684
876
|
npm install # or bun install
|
|
685
877
|
npm run dev # opens http://localhost:3000
|
|
686
878
|
\`\`\`
|
package/dist/commands/start.js
CHANGED
|
@@ -28,10 +28,13 @@ export async function start(options) {
|
|
|
28
28
|
if (volumeName) {
|
|
29
29
|
console.log(chalk.blue(`📦 Using volume: ${volumeName}`));
|
|
30
30
|
}
|
|
31
|
+
else {
|
|
32
|
+
console.log(chalk.blue(`📦 No volume specified (sandbox will be ephemeral)`));
|
|
33
|
+
}
|
|
31
34
|
const platformUrl = process.env.CASTARI_PLATFORM_URL;
|
|
32
35
|
const clientOptions = {
|
|
33
36
|
snapshot: snapshotName,
|
|
34
|
-
volume: volumeName,
|
|
37
|
+
...(volumeName ? { volume: volumeName } : {}),
|
|
35
38
|
platformUrl,
|
|
36
39
|
debug: true, // Enable debug logs for CLI
|
|
37
40
|
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@castari/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"castari": "./dist/index.js"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@anthropic-ai/claude-agent-sdk": "^0.1.44",
|
|
21
|
-
"@castari/sdk": "^0.0.
|
|
21
|
+
"@castari/sdk": "^0.0.7",
|
|
22
22
|
"adm-zip": "^0.5.16",
|
|
23
23
|
"cac": "^6.7.14",
|
|
24
24
|
"chalk": "^5.3.0",
|