@alexkroman1/aai-cli 5.1.1 → 5.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.
Files changed (99) hide show
  1. package/dist/_agent.d.ts +39 -0
  2. package/dist/_api-client.d.ts +37 -0
  3. package/dist/_bundler.d.ts +46 -0
  4. package/dist/_config.d.ts +57 -0
  5. package/dist/_default-html.d.ts +12 -0
  6. package/dist/_deploy.d.ts +28 -0
  7. package/dist/_dev-server.d.ts +74 -0
  8. package/dist/{_init-B-LEVTHx.mjs → _init-DU-sXH6S.mjs} +44 -65
  9. package/dist/_init.d.ts +7 -0
  10. package/dist/_mock-api.d.ts +22 -0
  11. package/dist/_mock-registry.d.ts +17 -0
  12. package/dist/_output.d.ts +50 -0
  13. package/dist/_server-common.d.ts +17 -0
  14. package/dist/_slug-api.d.ts +15 -0
  15. package/dist/_templates.d.ts +21 -0
  16. package/dist/_typecheck-gate.d.ts +7 -0
  17. package/dist/_ui.d.ts +22 -0
  18. package/dist/_utils.d.ts +48 -0
  19. package/dist/_vite-env.d.ts +8 -0
  20. package/dist/build.d.ts +16 -0
  21. package/dist/cli.d.ts +1 -0
  22. package/dist/cli.mjs +1 -1
  23. package/dist/client-bundler.d.ts +21 -0
  24. package/dist/delete.d.ts +18 -0
  25. package/dist/deploy.d.ts +15 -0
  26. package/dist/dev.d.ts +13 -0
  27. package/dist/{init-tc3Rbgrf.mjs → init-BjeK8crW.mjs} +1 -1
  28. package/dist/init.d.ts +24 -0
  29. package/dist/scaffold/.env.example +11 -0
  30. package/dist/scaffold/CLAUDE.md +919 -0
  31. package/dist/scaffold/global.d.ts +1 -0
  32. package/dist/scaffold/package.json +32 -0
  33. package/dist/scaffold/pnpm-workspace.yaml +13 -0
  34. package/dist/scaffold/tsconfig.json +19 -0
  35. package/dist/scaffold/vite.config.ts +14 -0
  36. package/dist/scaffold/vitest.config.ts +24 -0
  37. package/dist/secret.d.ts +25 -0
  38. package/dist/storage.d.ts +22 -0
  39. package/dist/templates/code-interpreter/agent.ts +11 -0
  40. package/dist/templates/code-interpreter/system-prompt.md +18 -0
  41. package/dist/templates/dispatch-center/agent.test.ts +153 -0
  42. package/dist/templates/dispatch-center/agent.ts +50 -0
  43. package/dist/templates/dispatch-center/client.tsx +378 -0
  44. package/dist/templates/dispatch-center/shared.ts +631 -0
  45. package/dist/templates/dispatch-center/system-prompt.md +39 -0
  46. package/dist/templates/dispatch-center/tools/incident_add_note.ts +27 -0
  47. package/dist/templates/dispatch-center/tools/incident_create.ts +79 -0
  48. package/dist/templates/dispatch-center/tools/incident_escalate.ts +88 -0
  49. package/dist/templates/dispatch-center/tools/incident_get.ts +36 -0
  50. package/dist/templates/dispatch-center/tools/incident_triage.ts +78 -0
  51. package/dist/templates/dispatch-center/tools/incident_update_status.ts +68 -0
  52. package/dist/templates/dispatch-center/tools/ops_dashboard.ts +52 -0
  53. package/dist/templates/dispatch-center/tools/ops_protocols.ts +27 -0
  54. package/dist/templates/dispatch-center/tools/ops_run_scenario.ts +149 -0
  55. package/dist/templates/dispatch-center/tools/resources_dispatch.ts +97 -0
  56. package/dist/templates/dispatch-center/tools/resources_get_available.ts +36 -0
  57. package/dist/templates/dispatch-center/tools/resources_update_status.ts +62 -0
  58. package/dist/templates/embedded-assets/agent.ts +55 -0
  59. package/dist/templates/embedded-assets/knowledge.json +20 -0
  60. package/dist/templates/health-assistant/agent.ts +174 -0
  61. package/dist/templates/health-assistant/system-prompt.md +17 -0
  62. package/dist/templates/infocom-adventure/agent.ts +119 -0
  63. package/dist/templates/infocom-adventure/client.tsx +279 -0
  64. package/dist/templates/infocom-adventure/shared.ts +38 -0
  65. package/dist/templates/infocom-adventure/system-prompt.md +43 -0
  66. package/dist/templates/math-buddy/agent.ts +16 -0
  67. package/dist/templates/math-buddy/system-prompt.md +12 -0
  68. package/dist/templates/night-owl/agent.ts +76 -0
  69. package/dist/templates/night-owl/client.tsx +130 -0
  70. package/dist/templates/night-owl/shared.ts +5 -0
  71. package/dist/templates/personal-finance/agent.ts +11 -0
  72. package/dist/templates/personal-finance/system-prompt.md +17 -0
  73. package/dist/templates/pipeline-simple/agent.test.ts +32 -0
  74. package/dist/templates/pipeline-simple/agent.ts +13 -0
  75. package/dist/templates/pizza-ordering/agent.test.ts +235 -0
  76. package/dist/templates/pizza-ordering/agent.ts +174 -0
  77. package/dist/templates/pizza-ordering/client.tsx +120 -0
  78. package/dist/templates/pizza-ordering/shared.ts +142 -0
  79. package/dist/templates/pizza-ordering/system-prompt.md +17 -0
  80. package/dist/templates/simple/agent.ts +5 -0
  81. package/dist/templates/solo-rpg/agent.test.ts +477 -0
  82. package/dist/templates/solo-rpg/agent.ts +37 -0
  83. package/dist/templates/solo-rpg/client.tsx +809 -0
  84. package/dist/templates/solo-rpg/shared.ts +747 -0
  85. package/dist/templates/solo-rpg/system-prompt.md +115 -0
  86. package/dist/templates/solo-rpg/tools/action_roll.ts +98 -0
  87. package/dist/templates/solo-rpg/tools/burn_momentum.ts +69 -0
  88. package/dist/templates/solo-rpg/tools/check_state.ts +11 -0
  89. package/dist/templates/solo-rpg/tools/load_game.ts +25 -0
  90. package/dist/templates/solo-rpg/tools/oracle.ts +248 -0
  91. package/dist/templates/solo-rpg/tools/save_game.ts +20 -0
  92. package/dist/templates/solo-rpg/tools/setup_character.ts +208 -0
  93. package/dist/templates/solo-rpg/tools/update_state.ts +170 -0
  94. package/dist/templates/web-researcher/agent.ts +11 -0
  95. package/dist/test.d.ts +39 -0
  96. package/dist/tsdown.config.d.ts +2 -0
  97. package/dist/typecheck.d.ts +26 -0
  98. package/dist/worker-bundler.d.ts +29 -0
  99. package/package.json +9 -6
@@ -0,0 +1,378 @@
1
+ import "@alexkroman1/aai-ui/styles.css";
2
+ import type { ChatMessage } from "@alexkroman1/aai-ui";
3
+ import { client, useAgentState, useSession } from "@alexkroman1/aai-ui";
4
+ import { useEffect, useRef } from "react";
5
+ import type { DashboardView, DispatchState, IncidentSummary, Severity, Status } from "./shared.ts";
6
+ import { dashboardView } from "./shared.ts";
7
+
8
+ const CSS = `
9
+ @keyframes dc-pulse {
10
+ 0%, 100% { opacity: 1; }
11
+ 50% { opacity: 0.5; }
12
+ }
13
+ @keyframes dc-slide-in {
14
+ from { transform: translateY(10px); opacity: 0; }
15
+ to { transform: translateY(0); opacity: 1; }
16
+ }
17
+ .dc-messages::-webkit-scrollbar { width: 6px; }
18
+ .dc-messages::-webkit-scrollbar-track { background: transparent; }
19
+ .dc-messages::-webkit-scrollbar-thumb { background: #334155; border-radius: 3px; }
20
+ .dc-sidebar::-webkit-scrollbar { width: 6px; }
21
+ .dc-sidebar::-webkit-scrollbar-track { background: transparent; }
22
+ .dc-sidebar::-webkit-scrollbar-thumb { background: #334155; border-radius: 3px; }
23
+ @media (max-width: 900px) {
24
+ .dc-main { grid-template-columns: 1fr !important; grid-template-rows: auto 1fr !important; }
25
+ }
26
+ `;
27
+
28
+ // Each color map is `satisfies`-pinned to the shared union it renders, so a
29
+ // renamed or added level/severity/status is a compile error here instead of
30
+ // a silently gray badge.
31
+ const alertColors: Record<string, string> = {
32
+ green: "#22c55e",
33
+ yellow: "#eab308",
34
+ orange: "#f97316",
35
+ red: "#ef4444",
36
+ } satisfies Record<DispatchState["alertLevel"], string>;
37
+
38
+ const severityColors: Record<string, string> = {
39
+ critical: "#ef4444",
40
+ urgent: "#f97316",
41
+ moderate: "#eab308",
42
+ minor: "#22c55e",
43
+ } satisfies Record<Severity, string>;
44
+
45
+ const statusColors: Record<string, string> = {
46
+ incoming: "#818cf8",
47
+ triaged: "#a78bfa",
48
+ dispatched: "#f59e0b",
49
+ en_route: "#3b82f6",
50
+ on_scene: "#22c55e",
51
+ resolved: "#6b7280",
52
+ escalated: "#ef4444",
53
+ } satisfies Record<Status, string>;
54
+
55
+ // The board before the first tool call — derived from the projection so a
56
+ // new DashboardView field can't silently miss the pre-first-tool-call render.
57
+ const EMPTY_DASH = dashboardView({});
58
+
59
+ function stateColor(state: string): string {
60
+ return state === "listening"
61
+ ? "#22c55e"
62
+ : state === "thinking"
63
+ ? "#eab308"
64
+ : state === "speaking"
65
+ ? "#3b82f6"
66
+ : state === "ready"
67
+ ? "#22c55e"
68
+ : "#6b7280";
69
+ }
70
+
71
+ function Panel({ title, children }: { title: string; children: React.ReactNode }) {
72
+ return (
73
+ <div className="rounded-lg p-3" style={{ background: "#1a1a2e", border: "1px solid #1e293b" }}>
74
+ <div
75
+ className="text-[10px] font-bold uppercase tracking-[1.5px] mb-2.5"
76
+ style={{ color: "#64748b" }}
77
+ >
78
+ {title}
79
+ </div>
80
+ {children}
81
+ </div>
82
+ );
83
+ }
84
+
85
+ function StatRow({ label, value, color }: { label: string; value: number; color?: string }) {
86
+ return (
87
+ <div className="flex justify-between items-center py-1 text-xs">
88
+ <span style={{ color: "#94a3b8" }}>{label}</span>
89
+ <span className="font-bold" style={{ color: color ?? "#e2e8f0" }}>
90
+ {value}
91
+ </span>
92
+ </div>
93
+ );
94
+ }
95
+
96
+ function IncidentCard({ inc }: { inc: IncidentSummary }) {
97
+ const sevColor = severityColors[inc.severity] || "#334155";
98
+ return (
99
+ <div
100
+ className="rounded-md p-2.5 mb-2"
101
+ style={{
102
+ background: "#0f172a",
103
+ animation: "dc-slide-in 0.3s ease-out",
104
+ border: `1px solid ${sevColor}40`,
105
+ borderLeft: `3px solid ${sevColor}`,
106
+ }}
107
+ >
108
+ <div className="flex justify-between items-center mb-1">
109
+ <span className="text-xs font-bold" style={{ color: "#f1f5f9" }}>
110
+ {inc.id}
111
+ </span>
112
+ <span
113
+ className="text-[9px] px-1.5 py-0.5 rounded font-bold uppercase"
114
+ style={{ background: `${sevColor}30`, color: sevColor }}
115
+ >
116
+ {inc.severity}
117
+ </span>
118
+ </div>
119
+ {inc.location && (
120
+ <div className="text-[11px] mb-0.5" style={{ color: "#94a3b8" }}>
121
+ {inc.location}
122
+ </div>
123
+ )}
124
+ <div
125
+ className="text-[10px] uppercase tracking-wider"
126
+ style={{ color: statusColors[inc.status] || "#6b7280" }}
127
+ >
128
+ {inc.status.replace("_", " ")}
129
+ </div>
130
+ </div>
131
+ );
132
+ }
133
+
134
+ function App() {
135
+ const session = useSession();
136
+ const messagesEndRef = useRef<HTMLDivElement>(null);
137
+ // The agent's own board, projected by `syncState`. This replaced a
138
+ // useState mirror that merged incident deltas out of tool events — the
139
+ // projection is already the complete list, so there is nothing to merge.
140
+ const dash = useAgentState<DashboardView>() ?? EMPTY_DASH;
141
+
142
+ useEffect(() => {
143
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
144
+ }, [session.messages]);
145
+
146
+ const incidentList = [...dash.incidents].reverse();
147
+ const activeIncidents = incidentList.filter((i) => i.status !== "resolved");
148
+ const resolvedCount = incidentList.filter((i) => i.status === "resolved").length;
149
+
150
+ const alertLevel = dash.systemAlertLevel;
151
+ const alertBg = alertColors[alertLevel] || "#6b7280";
152
+ const alertTextColor = alertLevel === "yellow" ? "#000" : "#fff";
153
+
154
+ return (
155
+ <>
156
+ <style>{CSS}</style>
157
+ <div
158
+ className="flex flex-col min-h-screen m-0 p-0 font-mono"
159
+ style={{ background: "#0a0a0f", color: "#e2e8f0" }}
160
+ >
161
+ {/* Header */}
162
+ <div
163
+ className="flex items-center justify-between px-6 py-4 gap-4 flex-wrap shrink-0"
164
+ style={{
165
+ background: "linear-gradient(135deg, #1a1a2e, #16213e)",
166
+ borderBottom: "1px solid #1e293b",
167
+ }}
168
+ >
169
+ <div
170
+ className="flex items-center gap-2.5 text-lg font-bold uppercase tracking-wider"
171
+ style={{ color: "#f1f5f9" }}
172
+ >
173
+ <span style={{ color: "#3b82f6" }}>&#9670;</span>
174
+ Dispatch Command Center
175
+ <span
176
+ className="w-2.5 h-2.5 rounded-full inline-block"
177
+ style={{
178
+ background: stateColor(session.state),
179
+ animation:
180
+ session.state === "listening"
181
+ ? "dc-pulse 1.5s ease-in-out infinite"
182
+ : session.state === "thinking"
183
+ ? "dc-pulse 0.8s ease-in-out infinite"
184
+ : "none",
185
+ }}
186
+ title={session.state}
187
+ />
188
+ <span className="text-[11px] font-normal normal-case" style={{ color: "#64748b" }}>
189
+ {session.state === "listening"
190
+ ? "LISTENING"
191
+ : session.state === "thinking"
192
+ ? "PROCESSING"
193
+ : session.state === "speaking"
194
+ ? "TRANSMITTING"
195
+ : session.state.toUpperCase()}
196
+ </span>
197
+ </div>
198
+ <div className="flex gap-2 items-center">
199
+ <span className="text-[10px] tracking-wider" style={{ color: "#64748b" }}>
200
+ SYSTEM ALERT:
201
+ </span>
202
+ <span
203
+ className="px-3 py-1 rounded text-[11px] font-bold uppercase tracking-wider"
204
+ style={{
205
+ background: alertBg,
206
+ color: alertTextColor,
207
+ animation: alertLevel === "red" ? "dc-pulse 1s ease-in-out infinite" : "none",
208
+ }}
209
+ >
210
+ {alertLevel.toUpperCase()}
211
+ </span>
212
+ </div>
213
+ </div>
214
+
215
+ {/* Main content */}
216
+ <div
217
+ className="dc-main flex-1 grid overflow-hidden"
218
+ style={{ gridTemplateColumns: "1fr 320px" }}
219
+ >
220
+ {/* Left: conversation feed */}
221
+ <div
222
+ className="flex flex-col overflow-hidden"
223
+ style={{ borderRight: "1px solid #1e293b" }}
224
+ >
225
+ <div className="dc-messages flex-1 overflow-y-auto p-4 flex flex-col gap-2">
226
+ {session.messages.length === 0 && (
227
+ <div className="text-center p-10 text-[13px]" style={{ color: "#475569" }}>
228
+ Dispatch Command Center standing by. Click START to begin operations.
229
+ </div>
230
+ )}
231
+ {session.messages.map((m: ChatMessage, i: number) => (
232
+ <div
233
+ key={i}
234
+ className="rounded-lg text-[13px] max-w-[85%] px-3.5 py-2.5"
235
+ style={{
236
+ lineHeight: 1.6,
237
+ alignSelf: m.role === "assistant" ? "flex-start" : "flex-end",
238
+ background: m.role === "assistant" ? "#1e293b" : "#172554",
239
+ animation: "dc-slide-in 0.2s ease-out",
240
+ borderLeft: m.role === "assistant" ? "3px solid #3b82f6" : "none",
241
+ borderRight: m.role !== "assistant" ? "3px solid #22d3ee" : "none",
242
+ }}
243
+ >
244
+ <div
245
+ className="text-[10px] uppercase tracking-wider mb-1"
246
+ style={{ color: "#64748b" }}
247
+ >
248
+ {m.role === "assistant" ? "DISPATCH" : "OPERATOR"}
249
+ </div>
250
+ {m.content}
251
+ </div>
252
+ ))}
253
+ <div ref={messagesEndRef} />
254
+ </div>
255
+
256
+ {session.userTranscript !== null && (
257
+ <div
258
+ className="flex items-center px-4 py-2 text-xs italic min-h-8"
259
+ style={{ background: "#111827", borderTop: "1px solid #1e293b", color: "#64748b" }}
260
+ >
261
+ <span
262
+ className="w-2.5 h-2.5 rounded-full inline-block mr-2"
263
+ style={{ background: "#22c55e", animation: "dc-pulse 1.5s ease-in-out infinite" }}
264
+ />
265
+ {session.userTranscript === "" ? "..." : session.userTranscript}
266
+ </div>
267
+ )}
268
+ {session.error && (
269
+ <div
270
+ className="px-4 py-2 text-xs"
271
+ style={{ background: "#450a0a", color: "#fca5a5", borderTop: "1px solid #991b1b" }}
272
+ >
273
+ ERROR: {session.error.message} ({session.error.code})
274
+ </div>
275
+ )}
276
+
277
+ <div
278
+ className="flex items-center gap-2.5 px-4 py-3"
279
+ style={{ background: "#111827", borderTop: "1px solid #1e293b" }}
280
+ >
281
+ {!session.started ? (
282
+ <button
283
+ type="button"
284
+ className="px-4 py-2 border-none rounded-md font-mono text-xs font-semibold uppercase tracking-wider cursor-pointer text-white"
285
+ style={{ background: "#2563eb" }}
286
+ onClick={() => session.start()}
287
+ >
288
+ Start Dispatch
289
+ </button>
290
+ ) : (
291
+ <>
292
+ <button
293
+ type="button"
294
+ className="px-4 py-2 border-none rounded-md font-mono text-xs font-semibold uppercase tracking-wider cursor-pointer"
295
+ style={{
296
+ background: session.running ? "#334155" : "#2563eb",
297
+ color: session.running ? "#e2e8f0" : "white",
298
+ }}
299
+ onClick={() => session.toggle()}
300
+ >
301
+ {session.running ? "Pause" : "Resume"}
302
+ </button>
303
+ <button
304
+ type="button"
305
+ className="px-4 py-2 border-none rounded-md font-mono text-xs font-semibold uppercase tracking-wider cursor-pointer text-white"
306
+ style={{ background: "#dc2626" }}
307
+ onClick={() => session.reset()}
308
+ >
309
+ Reset
310
+ </button>
311
+ </>
312
+ )}
313
+ <div className="flex-1" />
314
+ <span className="text-[10px]" style={{ color: "#475569" }}>
315
+ {incidentList.length} incident{incidentList.length !== 1 ? "s" : ""} logged
316
+ </span>
317
+ </div>
318
+ </div>
319
+
320
+ {/* Right: sidebar dashboard */}
321
+ <div
322
+ className="dc-sidebar overflow-y-auto p-4 flex flex-col gap-4"
323
+ style={{ background: "#111827" }}
324
+ >
325
+ <Panel title="Operations Summary">
326
+ <StatRow
327
+ label="Active Incidents"
328
+ value={activeIncidents.length}
329
+ color={activeIncidents.length > 3 ? "#ef4444" : "#e2e8f0"}
330
+ />
331
+ <StatRow label="Resolved" value={resolvedCount} color="#22c55e" />
332
+ <StatRow label="Total Logged" value={incidentList.length} />
333
+ </Panel>
334
+
335
+ <Panel title="Active Incidents">
336
+ {activeIncidents.length === 0 ? (
337
+ <div className="text-xs text-center py-2" style={{ color: "#475569" }}>
338
+ No active incidents
339
+ </div>
340
+ ) : (
341
+ activeIncidents.map((inc) => <IncidentCard key={inc.id} inc={inc} />)
342
+ )}
343
+ </Panel>
344
+
345
+ <Panel title="Severity Legend">
346
+ {Object.entries(severityColors).map(([sev, color]) => (
347
+ <div key={sev} className="flex items-center gap-2 py-0.5">
348
+ <span className="w-2.5 h-2.5 rounded-sm" style={{ background: color }} />
349
+ <span className="text-[11px] capitalize" style={{ color: "#94a3b8" }}>
350
+ {sev}
351
+ </span>
352
+ </div>
353
+ ))}
354
+ </Panel>
355
+
356
+ <Panel title="Training Scenarios">
357
+ <div className="text-[11px] leading-relaxed" style={{ color: "#64748b" }}>
358
+ Say "run mass casualty scenario" or "simulate active shooter" to test dispatch
359
+ operations with complex multi-incident drills.
360
+ </div>
361
+ </Panel>
362
+ </div>
363
+ </div>
364
+ </div>
365
+ </>
366
+ );
367
+ }
368
+
369
+ client({
370
+ component: App,
371
+ theme: {
372
+ bg: "#0a0a0f",
373
+ primary: "#3b82f6",
374
+ text: "#e2e8f0",
375
+ surface: "#1a1a2e",
376
+ border: "#1e293b",
377
+ },
378
+ });