@inbrowser/agent 0.0.0-placeholder → 0.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 (267) hide show
  1. package/AGENTS.md +270 -0
  2. package/LICENSE +21 -0
  3. package/README.md +117 -2
  4. package/bin/agent.ts +10 -0
  5. package/dist/cli/commands/describe.d.ts +14 -0
  6. package/dist/cli/commands/describe.d.ts.map +1 -0
  7. package/dist/cli/commands/describe.js +179 -0
  8. package/dist/cli/commands/describe.js.map +1 -0
  9. package/dist/cli/commands/events.d.ts +21 -0
  10. package/dist/cli/commands/events.d.ts.map +1 -0
  11. package/dist/cli/commands/events.js +59 -0
  12. package/dist/cli/commands/events.js.map +1 -0
  13. package/dist/cli/commands/fleet.d.ts +15 -0
  14. package/dist/cli/commands/fleet.d.ts.map +1 -0
  15. package/dist/cli/commands/fleet.js +149 -0
  16. package/dist/cli/commands/fleet.js.map +1 -0
  17. package/dist/cli/commands/help.d.ts +15 -0
  18. package/dist/cli/commands/help.d.ts.map +1 -0
  19. package/dist/cli/commands/help.js +93 -0
  20. package/dist/cli/commands/help.js.map +1 -0
  21. package/dist/cli/commands/migrate.d.ts +27 -0
  22. package/dist/cli/commands/migrate.d.ts.map +1 -0
  23. package/dist/cli/commands/migrate.js +109 -0
  24. package/dist/cli/commands/migrate.js.map +1 -0
  25. package/dist/cli/commands/run.d.ts +38 -0
  26. package/dist/cli/commands/run.d.ts.map +1 -0
  27. package/dist/cli/commands/run.js +535 -0
  28. package/dist/cli/commands/run.js.map +1 -0
  29. package/dist/cli/commands/schema.d.ts +8 -0
  30. package/dist/cli/commands/schema.d.ts.map +1 -0
  31. package/dist/cli/commands/schema.js +12 -0
  32. package/dist/cli/commands/schema.js.map +1 -0
  33. package/dist/cli/commands/serve.d.ts +39 -0
  34. package/dist/cli/commands/serve.d.ts.map +1 -0
  35. package/dist/cli/commands/serve.js +65 -0
  36. package/dist/cli/commands/serve.js.map +1 -0
  37. package/dist/cli/commands/undo.d.ts +36 -0
  38. package/dist/cli/commands/undo.d.ts.map +1 -0
  39. package/dist/cli/commands/undo.js +132 -0
  40. package/dist/cli/commands/undo.js.map +1 -0
  41. package/dist/cli/fixtures.d.ts +17 -0
  42. package/dist/cli/fixtures.d.ts.map +1 -0
  43. package/dist/cli/fixtures.js +107 -0
  44. package/dist/cli/fixtures.js.map +1 -0
  45. package/dist/cli/hardening.d.ts +39 -0
  46. package/dist/cli/hardening.d.ts.map +1 -0
  47. package/dist/cli/hardening.js +68 -0
  48. package/dist/cli/hardening.js.map +1 -0
  49. package/dist/cli/index.d.ts +28 -0
  50. package/dist/cli/index.d.ts.map +1 -0
  51. package/dist/cli/index.js +19 -0
  52. package/dist/cli/index.js.map +1 -0
  53. package/dist/cli/llm/openrouter.d.ts +33 -0
  54. package/dist/cli/llm/openrouter.d.ts.map +1 -0
  55. package/dist/cli/llm/openrouter.js +285 -0
  56. package/dist/cli/llm/openrouter.js.map +1 -0
  57. package/dist/cli/main.d.ts +32 -0
  58. package/dist/cli/main.d.ts.map +1 -0
  59. package/dist/cli/main.js +106 -0
  60. package/dist/cli/main.js.map +1 -0
  61. package/dist/cli/output.d.ts +36 -0
  62. package/dist/cli/output.d.ts.map +1 -0
  63. package/dist/cli/output.js +95 -0
  64. package/dist/cli/output.js.map +1 -0
  65. package/dist/cli/parse.d.ts +26 -0
  66. package/dist/cli/parse.d.ts.map +1 -0
  67. package/dist/cli/parse.js +160 -0
  68. package/dist/cli/parse.js.map +1 -0
  69. package/dist/cli/session-log.d.ts +34 -0
  70. package/dist/cli/session-log.d.ts.map +1 -0
  71. package/dist/cli/session-log.js +52 -0
  72. package/dist/cli/session-log.js.map +1 -0
  73. package/dist/cli/spec.d.ts +62 -0
  74. package/dist/cli/spec.d.ts.map +1 -0
  75. package/dist/cli/spec.js +510 -0
  76. package/dist/cli/spec.js.map +1 -0
  77. package/dist/cli/ui/RunView.d.ts +134 -0
  78. package/dist/cli/ui/RunView.d.ts.map +1 -0
  79. package/dist/cli/ui/RunView.js +341 -0
  80. package/dist/cli/ui/RunView.js.map +1 -0
  81. package/dist/diagnostics/index.d.ts +5 -0
  82. package/dist/diagnostics/index.d.ts.map +1 -0
  83. package/dist/diagnostics/index.js +3 -0
  84. package/dist/diagnostics/index.js.map +1 -0
  85. package/dist/diagnostics/timing.d.ts +48 -0
  86. package/dist/diagnostics/timing.d.ts.map +1 -0
  87. package/dist/diagnostics/timing.js +85 -0
  88. package/dist/diagnostics/timing.js.map +1 -0
  89. package/dist/diagnostics/truthfulness.d.ts +36 -0
  90. package/dist/diagnostics/truthfulness.d.ts.map +1 -0
  91. package/dist/diagnostics/truthfulness.js +180 -0
  92. package/dist/diagnostics/truthfulness.js.map +1 -0
  93. package/dist/dispatch-memoization.d.ts +84 -0
  94. package/dist/dispatch-memoization.d.ts.map +1 -0
  95. package/dist/dispatch-memoization.js +197 -0
  96. package/dist/dispatch-memoization.js.map +1 -0
  97. package/dist/eval/comparison-report.d.ts +164 -0
  98. package/dist/eval/comparison-report.d.ts.map +1 -0
  99. package/dist/eval/comparison-report.js +316 -0
  100. package/dist/eval/comparison-report.js.map +1 -0
  101. package/dist/eval/fixture.d.ts +74 -0
  102. package/dist/eval/fixture.d.ts.map +1 -0
  103. package/dist/eval/fixture.js +217 -0
  104. package/dist/eval/fixture.js.map +1 -0
  105. package/dist/eval/index.d.ts +13 -0
  106. package/dist/eval/index.d.ts.map +1 -0
  107. package/dist/eval/index.js +7 -0
  108. package/dist/eval/index.js.map +1 -0
  109. package/dist/eval/load-node.d.ts +16 -0
  110. package/dist/eval/load-node.d.ts.map +1 -0
  111. package/dist/eval/load-node.js +58 -0
  112. package/dist/eval/load-node.js.map +1 -0
  113. package/dist/eval/metric-collector.d.ts +209 -0
  114. package/dist/eval/metric-collector.d.ts.map +1 -0
  115. package/dist/eval/metric-collector.js +293 -0
  116. package/dist/eval/metric-collector.js.map +1 -0
  117. package/dist/eval/run-record.d.ts +76 -0
  118. package/dist/eval/run-record.d.ts.map +1 -0
  119. package/dist/eval/run-record.js +32 -0
  120. package/dist/eval/run-record.js.map +1 -0
  121. package/dist/eval/runner.d.ts +140 -0
  122. package/dist/eval/runner.d.ts.map +1 -0
  123. package/dist/eval/runner.js +310 -0
  124. package/dist/eval/runner.js.map +1 -0
  125. package/dist/eval/spec-framework.d.ts +113 -0
  126. package/dist/eval/spec-framework.d.ts.map +1 -0
  127. package/dist/eval/spec-framework.js +100 -0
  128. package/dist/eval/spec-framework.js.map +1 -0
  129. package/dist/eval/spec-helpers.d.ts +245 -0
  130. package/dist/eval/spec-helpers.d.ts.map +1 -0
  131. package/dist/eval/spec-helpers.js +605 -0
  132. package/dist/eval/spec-helpers.js.map +1 -0
  133. package/dist/events/codec.d.ts +79 -0
  134. package/dist/events/codec.d.ts.map +1 -0
  135. package/dist/events/codec.js +142 -0
  136. package/dist/events/codec.js.map +1 -0
  137. package/dist/events/log-core.d.ts +76 -0
  138. package/dist/events/log-core.d.ts.map +1 -0
  139. package/dist/events/log-core.js +73 -0
  140. package/dist/events/log-core.js.map +1 -0
  141. package/dist/events/log.d.ts +60 -0
  142. package/dist/events/log.d.ts.map +1 -0
  143. package/dist/events/log.js +193 -0
  144. package/dist/events/log.js.map +1 -0
  145. package/dist/events/replay.d.ts +106 -0
  146. package/dist/events/replay.d.ts.map +1 -0
  147. package/dist/events/replay.js +137 -0
  148. package/dist/events/replay.js.map +1 -0
  149. package/dist/events/wrap.d.ts +100 -0
  150. package/dist/events/wrap.d.ts.map +1 -0
  151. package/dist/events/wrap.js +141 -0
  152. package/dist/events/wrap.js.map +1 -0
  153. package/dist/index.d.ts +73 -0
  154. package/dist/index.d.ts.map +1 -0
  155. package/dist/index.js +47 -0
  156. package/dist/index.js.map +1 -0
  157. package/dist/llm-adapter.d.ts +96 -0
  158. package/dist/llm-adapter.d.ts.map +1 -0
  159. package/dist/llm-adapter.js +132 -0
  160. package/dist/llm-adapter.js.map +1 -0
  161. package/dist/mcp/serve.d.ts +70 -0
  162. package/dist/mcp/serve.d.ts.map +1 -0
  163. package/dist/mcp/serve.js +154 -0
  164. package/dist/mcp/serve.js.map +1 -0
  165. package/dist/metrics/runs.d.ts +58 -0
  166. package/dist/metrics/runs.d.ts.map +1 -0
  167. package/dist/metrics/runs.js +99 -0
  168. package/dist/metrics/runs.js.map +1 -0
  169. package/dist/metrics.d.ts +38 -0
  170. package/dist/metrics.d.ts.map +1 -0
  171. package/dist/metrics.js +123 -0
  172. package/dist/metrics.js.map +1 -0
  173. package/dist/node.d.ts +23 -0
  174. package/dist/node.d.ts.map +1 -0
  175. package/dist/node.js +23 -0
  176. package/dist/node.js.map +1 -0
  177. package/dist/planner-executor.d.ts +132 -0
  178. package/dist/planner-executor.d.ts.map +1 -0
  179. package/dist/planner-executor.js +274 -0
  180. package/dist/planner-executor.js.map +1 -0
  181. package/dist/session.d.ts +10 -0
  182. package/dist/session.d.ts.map +1 -0
  183. package/dist/session.js +179 -0
  184. package/dist/session.js.map +1 -0
  185. package/dist/skill-catalog.d.ts +81 -0
  186. package/dist/skill-catalog.d.ts.map +1 -0
  187. package/dist/skill-catalog.js +388 -0
  188. package/dist/skill-catalog.js.map +1 -0
  189. package/dist/skill-router.d.ts +95 -0
  190. package/dist/skill-router.d.ts.map +1 -0
  191. package/dist/skill-router.js +130 -0
  192. package/dist/skill-router.js.map +1 -0
  193. package/dist/storage.d.ts +14 -0
  194. package/dist/storage.d.ts.map +1 -0
  195. package/dist/storage.js +58 -0
  196. package/dist/storage.js.map +1 -0
  197. package/dist/strategy.d.ts +45 -0
  198. package/dist/strategy.d.ts.map +1 -0
  199. package/dist/strategy.js +520 -0
  200. package/dist/strategy.js.map +1 -0
  201. package/dist/tools.d.ts +40 -0
  202. package/dist/tools.d.ts.map +1 -0
  203. package/dist/tools.js +147 -0
  204. package/dist/tools.js.map +1 -0
  205. package/dist/types/agent.d.ts +94 -0
  206. package/dist/types/agent.d.ts.map +1 -0
  207. package/dist/types/agent.js +17 -0
  208. package/dist/types/agent.js.map +1 -0
  209. package/dist/types/capabilities.d.ts +17 -0
  210. package/dist/types/capabilities.d.ts.map +1 -0
  211. package/dist/types/capabilities.js +13 -0
  212. package/dist/types/capabilities.js.map +1 -0
  213. package/dist/types/chat.d.ts +74 -0
  214. package/dist/types/chat.d.ts.map +1 -0
  215. package/dist/types/chat.js +10 -0
  216. package/dist/types/chat.js.map +1 -0
  217. package/dist/types/events.d.ts +115 -0
  218. package/dist/types/events.d.ts.map +1 -0
  219. package/dist/types/events.js +30 -0
  220. package/dist/types/events.js.map +1 -0
  221. package/dist/types/llm.d.ts +89 -0
  222. package/dist/types/llm.d.ts.map +1 -0
  223. package/dist/types/llm.js +12 -0
  224. package/dist/types/llm.js.map +1 -0
  225. package/dist/types/metrics.d.ts +34 -0
  226. package/dist/types/metrics.d.ts.map +1 -0
  227. package/dist/types/metrics.js +10 -0
  228. package/dist/types/metrics.js.map +1 -0
  229. package/dist/types/observer.d.ts +41 -0
  230. package/dist/types/observer.d.ts.map +1 -0
  231. package/dist/types/observer.js +41 -0
  232. package/dist/types/observer.js.map +1 -0
  233. package/dist/types/project-context.d.ts +18 -0
  234. package/dist/types/project-context.d.ts.map +1 -0
  235. package/dist/types/project-context.js +11 -0
  236. package/dist/types/project-context.js.map +1 -0
  237. package/dist/types/runtime.d.ts +71 -0
  238. package/dist/types/runtime.d.ts.map +1 -0
  239. package/dist/types/runtime.js +21 -0
  240. package/dist/types/runtime.js.map +1 -0
  241. package/dist/types/session.d.ts +103 -0
  242. package/dist/types/session.d.ts.map +1 -0
  243. package/dist/types/session.js +11 -0
  244. package/dist/types/session.js.map +1 -0
  245. package/dist/types/storage.d.ts +20 -0
  246. package/dist/types/storage.d.ts.map +1 -0
  247. package/dist/types/storage.js +41 -0
  248. package/dist/types/storage.js.map +1 -0
  249. package/dist/types/strategy.d.ts +124 -0
  250. package/dist/types/strategy.d.ts.map +1 -0
  251. package/dist/types/strategy.js +10 -0
  252. package/dist/types/strategy.js.map +1 -0
  253. package/dist/types/tools.d.ts +154 -0
  254. package/dist/types/tools.d.ts.map +1 -0
  255. package/dist/types/tools.js +11 -0
  256. package/dist/types/tools.js.map +1 -0
  257. package/dist/types/trace.d.ts +175 -0
  258. package/dist/types/trace.d.ts.map +1 -0
  259. package/dist/types/trace.js +26 -0
  260. package/dist/types/trace.js.map +1 -0
  261. package/dist/types/workspace.d.ts +29 -0
  262. package/dist/types/workspace.d.ts.map +1 -0
  263. package/dist/types/workspace.js +18 -0
  264. package/dist/types/workspace.js.map +1 -0
  265. package/package.json +45 -14
  266. package/skills/agent-cli.md +218 -0
  267. package/index.js +0 -2
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `createAgentSession()` — the host-facing session container.
3
+ *
4
+ * Generic over the strategy. Translates a `StrategyEvent` stream
5
+ * into the typed `SessionEvent` stream the host consumes. Tracks
6
+ * workspace + runtime patches as tool results flow in.
7
+ */
8
+ import type { AgentSession, AgentSessionConfig } from './types/session.js';
9
+ export declare function createAgentSession(config: AgentSessionConfig): AgentSession;
10
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAgB,MAAM,oBAAoB,CAAC;AAOzF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CA+H3E"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * `createAgentSession()` — the host-facing session container.
3
+ *
4
+ * Generic over the strategy. Translates a `StrategyEvent` stream
5
+ * into the typed `SessionEvent` stream the host consumes. Tracks
6
+ * workspace + runtime patches as tool results flow in.
7
+ */
8
+ let sessionCounter = 0;
9
+ export function createAgentSession(config) {
10
+ const id = config.id ?? `session-${++sessionCounter}-${Date.now().toString(36)}`;
11
+ let workspace = freezeWorkspace(config.history.length > 0 ? extractInitialWorkspace(config) : initialWorkspace());
12
+ let runtime = initialRuntime();
13
+ let history = [...config.history];
14
+ let currentAbort = null;
15
+ const session = {
16
+ id,
17
+ get workspace() {
18
+ return workspace;
19
+ },
20
+ get runtime() {
21
+ return runtime;
22
+ },
23
+ submit(prompt, externalSignal) {
24
+ // Compose an internal controller that listens to both the
25
+ // external signal and our `cancel()` override.
26
+ const inner = new AbortController();
27
+ currentAbort = inner;
28
+ const linked = linkSignals(externalSignal, inner.signal);
29
+ return run(prompt, linked);
30
+ },
31
+ cancel() {
32
+ currentAbort?.abort();
33
+ },
34
+ };
35
+ function bumpWorkspace(patch) {
36
+ if (!patch)
37
+ return false;
38
+ workspace = freezeWorkspace({ ...workspace, ...patch });
39
+ return true;
40
+ }
41
+ function bumpRuntime(patch) {
42
+ if (!patch)
43
+ return false;
44
+ runtime = freezeRuntime({ ...runtime, ...patch });
45
+ return true;
46
+ }
47
+ async function* run(prompt, signal) {
48
+ const turnId = `t-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
49
+ yield { kind: 'turn_started', turnId };
50
+ // Capture the user message in history so the next turn sees it.
51
+ const userMsg = {
52
+ id: `u-${turnId}`,
53
+ role: 'user',
54
+ text: prompt,
55
+ timestamp: Date.now(),
56
+ };
57
+ history = [...history, userMsg];
58
+ const systemPrompt = config.systemPromptBuilder(workspace, runtime);
59
+ const strategyEvents = config.strategy.run({
60
+ prompt,
61
+ history,
62
+ workspace,
63
+ runtime,
64
+ llm: config.llm,
65
+ tools: config.tools,
66
+ toolList: config.toolList,
67
+ toolContext: config.toolContext,
68
+ systemPrompt,
69
+ ...(config.tracer ? { tracer: config.tracer } : {}),
70
+ turnId,
71
+ }, signal);
72
+ let assistantText = '';
73
+ const assistantId = `a-${turnId}`;
74
+ for await (const ev of strategyEvents) {
75
+ if (ev.kind === 'text') {
76
+ assistantText += ev.chunk;
77
+ yield { kind: 'text', turnId, chunk: ev.chunk };
78
+ }
79
+ else if (ev.kind === 'thinking') {
80
+ yield { kind: 'thinking', turnId, chunk: ev.chunk };
81
+ }
82
+ else if (ev.kind === 'tool_call') {
83
+ yield {
84
+ kind: 'tool_started',
85
+ turnId,
86
+ callId: ev.id,
87
+ name: ev.name,
88
+ args: ev.args,
89
+ ...(ev.signature ? { signature: ev.signature } : {}),
90
+ };
91
+ }
92
+ else if (ev.kind === 'tool_result') {
93
+ const wsBumped = bumpWorkspace(ev.result.workspacePatch);
94
+ const rtBumped = bumpRuntime(ev.result.runtimePatch);
95
+ yield { kind: 'tool_finished', turnId, callId: ev.id, result: ev.result };
96
+ if (wsBumped)
97
+ yield { kind: 'workspace_changed', workspace };
98
+ if (rtBumped)
99
+ yield { kind: 'runtime_changed', runtime };
100
+ }
101
+ else if (ev.kind === 'turn_complete') {
102
+ const metrics = config.metrics.recordTurn({
103
+ llmId: config.llm.id,
104
+ model: ev.details.requestedModel,
105
+ durationMs: 0,
106
+ rawUsage: ev.usage,
107
+ });
108
+ // Append assistant message to history.
109
+ const assistantMsg = {
110
+ id: assistantId,
111
+ role: 'assistant',
112
+ text: assistantText,
113
+ metrics,
114
+ details: ev.details,
115
+ timestamp: Date.now(),
116
+ };
117
+ history = [...history, assistantMsg];
118
+ yield { kind: 'turn_completed', turnId, metrics, details: ev.details };
119
+ }
120
+ else if (ev.kind === 'error') {
121
+ yield { kind: 'error', turnId, message: ev.message };
122
+ return;
123
+ }
124
+ else if (ev.kind === 'custom') {
125
+ yield { kind: 'strategy_event', name: ev.name, data: ev.data };
126
+ }
127
+ }
128
+ yield { kind: 'completed' };
129
+ }
130
+ return session;
131
+ }
132
+ function initialWorkspace() {
133
+ return freezeWorkspace({
134
+ presetId: '',
135
+ rules: '',
136
+ code: '',
137
+ appSource: '',
138
+ stitch: { projectId: null, latestScreenUrl: null, brief: null },
139
+ });
140
+ }
141
+ function extractInitialWorkspace(config) {
142
+ // History-only resume — workspace can be threaded in by the caller
143
+ // via a follow-up patch, but the session's initial workspace shape
144
+ // matches the empty defaults until then.
145
+ void config;
146
+ return initialWorkspace();
147
+ }
148
+ function initialRuntime() {
149
+ return freezeRuntime({
150
+ terminal: [],
151
+ runSummary: null,
152
+ deploy: null,
153
+ parseError: null,
154
+ uiErrors: [],
155
+ sandboxVersion: 0,
156
+ });
157
+ }
158
+ function freezeWorkspace(w) {
159
+ return Object.freeze({ ...w, stitch: Object.freeze({ ...w.stitch }) });
160
+ }
161
+ function freezeRuntime(r) {
162
+ return Object.freeze({
163
+ ...r,
164
+ terminal: Object.freeze([...r.terminal]),
165
+ uiErrors: Object.freeze([...r.uiErrors]),
166
+ });
167
+ }
168
+ /** Combine two abort signals into one that fires when either fires. */
169
+ function linkSignals(a, b) {
170
+ const controller = new AbortController();
171
+ if (a.aborted || b.aborted) {
172
+ controller.abort();
173
+ return controller.signal;
174
+ }
175
+ a.addEventListener('abort', () => controller.abort(), { once: true });
176
+ b.addEventListener('abort', () => controller.abort(), { once: true });
177
+ return controller.signal;
178
+ }
179
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Static catalog of skill workflows.
3
+ *
4
+ * Phase five of the implementation plan splits the planner-executor work
5
+ * into three branches: this catalog, the router that classifies a user
6
+ * prompt against the catalog, and the executor that walks a chosen
7
+ * skill's prescribed step sequence. This module is the data + types
8
+ * gate — no runtime logic. The router reads `triggerHints` to score
9
+ * candidate matches; the executor reads `steps` to materialize a plan.
10
+ *
11
+ * Each entry's `name` matches a value in the `SkillName` enum from
12
+ * `eval/fixture.ts` (re-exported here for convenience). Step
13
+ * descriptions are imperative, short, and model-agnostic. Per-step
14
+ * `verifier?` references existing starter / custom specs where one
15
+ * fits naturally; not every step has one. Leaf "compile / deploy /
16
+ * verify" steps tend to have a spec; intermediate read / draft steps
17
+ * usually don't.
18
+ *
19
+ * The catalog is hand-authored and intentionally `const`. The
20
+ * companion test in `test/skill-catalog.test.ts` asserts shape
21
+ * invariants: every `name` is in `SKILL_NAMES`, every entry has at
22
+ * least three trigger hints, every entry has between four and nine
23
+ * steps, every step id is unique and kebab-case within its plan, and
24
+ * every `verifier?.name` matches a spec registered by
25
+ * `registerAllSpecs(createSpecRegistry())`.
26
+ */
27
+ import type { SkillName, SuccessSpecReference } from './eval/fixture.js';
28
+ /**
29
+ * One ordered step in a skill's prescribed workflow.
30
+ *
31
+ * `id` is a stable kebab-case identifier, unique within the parent
32
+ * plan. The executor uses it as the scratch key for the step's
33
+ * bounded sub-loop. `description` is an imperative one-liner — what
34
+ * the step does, in the project's voice. `verifier?` is an optional
35
+ * `SuccessSpecReference` the executor can run after the step finishes
36
+ * to gate whether the plan advances; the same shape that fixtures
37
+ * use, so the executor can re-use `evaluateSpec` without translation.
38
+ */
39
+ export interface PlanStep {
40
+ /** Stable kebab-case id, unique within the plan. */
41
+ id: string;
42
+ /** Short imperative description of what the step does. */
43
+ description: string;
44
+ /** Optional reference to a success spec that verifies this step. */
45
+ verifier?: SuccessSpecReference;
46
+ }
47
+ /**
48
+ * One row in the skill catalog. Describes a single skill workflow as
49
+ * a triple of (router signals, plan, identity).
50
+ */
51
+ export interface SkillCatalogEntry {
52
+ /** Matches a value in `SKILL_NAMES` from `eval/fixture.ts`. */
53
+ name: SkillName;
54
+ /** One-line description used by the router and surfaced in the plan. */
55
+ description: string;
56
+ /**
57
+ * Lowercase keyword tokens the router scans the user prompt for.
58
+ * Order does not matter; at least one hit signals a candidate match.
59
+ */
60
+ triggerHints: readonly string[];
61
+ /** Prescribed workflow as an ordered sequence of steps. */
62
+ steps: readonly PlanStep[];
63
+ }
64
+ /** Read-only view over the catalog. */
65
+ export type SkillCatalog = readonly SkillCatalogEntry[];
66
+ export declare const SKILL_CATALOG: SkillCatalog;
67
+ /**
68
+ * Look up a catalog entry by skill name. Returns `undefined` when the
69
+ * name is not in the catalog. The router will use this to materialize
70
+ * an entry after picking a winner; the executor will use it to
71
+ * unwrap a router decision into a plan.
72
+ */
73
+ export declare function getSkillEntry(name: SkillName): SkillCatalogEntry | undefined;
74
+ /**
75
+ * List every skill name present in the catalog, in catalog order. The
76
+ * router uses this to iterate candidates when scoring a prompt; the
77
+ * test suite uses it to assert the catalog covers every value in
78
+ * `SKILL_NAMES`.
79
+ */
80
+ export declare function listSkillNames(): readonly SkillName[];
81
+ //# sourceMappingURL=skill-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-catalog.d.ts","sourceRoot":"","sources":["../src/skill-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAWzE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,QAAQ;IACvB,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,IAAI,EAAE,SAAS,CAAC;IAChB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,2DAA2D;IAC3D,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC5B;AAED,uCAAuC;AACvC,MAAM,MAAM,YAAY,GAAG,SAAS,iBAAiB,EAAE,CAAC;AAQxD,eAAO,MAAM,aAAa,EAAE,YA8V3B,CAAC;AAcF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAE5E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,SAAS,SAAS,EAAE,CAErD"}
@@ -0,0 +1,388 @@
1
+ /**
2
+ * Static catalog of skill workflows.
3
+ *
4
+ * Phase five of the implementation plan splits the planner-executor work
5
+ * into three branches: this catalog, the router that classifies a user
6
+ * prompt against the catalog, and the executor that walks a chosen
7
+ * skill's prescribed step sequence. This module is the data + types
8
+ * gate — no runtime logic. The router reads `triggerHints` to score
9
+ * candidate matches; the executor reads `steps` to materialize a plan.
10
+ *
11
+ * Each entry's `name` matches a value in the `SkillName` enum from
12
+ * `eval/fixture.ts` (re-exported here for convenience). Step
13
+ * descriptions are imperative, short, and model-agnostic. Per-step
14
+ * `verifier?` references existing starter / custom specs where one
15
+ * fits naturally; not every step has one. Leaf "compile / deploy /
16
+ * verify" steps tend to have a spec; intermediate read / draft steps
17
+ * usually don't.
18
+ *
19
+ * The catalog is hand-authored and intentionally `const`. The
20
+ * companion test in `test/skill-catalog.test.ts` asserts shape
21
+ * invariants: every `name` is in `SKILL_NAMES`, every entry has at
22
+ * least three trigger hints, every entry has between four and nine
23
+ * steps, every step id is unique and kebab-case within its plan, and
24
+ * every `verifier?.name` matches a spec registered by
25
+ * `registerAllSpecs(createSpecRegistry())`.
26
+ */
27
+ import { SPEC_FINAL_RULES_INCLUDES_LITERAL, SPEC_FINAL_RUNTIME_RUN_SUMMARY_OK, SPEC_GAME_RULES_SIMULATOR_ACCEPTS_POSITIVE_AND_REJECTS_CHEAT, SPEC_PYRIC_AGENTS_LINT_CLEAN_AND_RULE_REJECTS_CHEAT, SPEC_REPORT_MENTIONS_ALL_OF, SPEC_REPORT_MENTIONS_AT_LEAST_ONE_OF, SPEC_TRACE_CONTAINS_TOOL_CALL_BY_NAME, } from './eval/spec-helpers.js';
28
+ // ---------------------------------------------------------------------------
29
+ // The catalog. One entry per in-scope skill, in `SKILL_NAMES` order.
30
+ // Step content is derived from each skill's `SKILL.md` playbook in the
31
+ // downstream firebase-agent-sdk repo.
32
+ // ---------------------------------------------------------------------------
33
+ export const SKILL_CATALOG = [
34
+ {
35
+ name: 'firestore-rules-audit',
36
+ description: 'Audit Firestore security rules for vulnerabilities, semantic errors, and structural anti-patterns.',
37
+ triggerHints: ['firestore', 'audit', 'rules', 'security', 'vulnerability', 'review'],
38
+ steps: [
39
+ {
40
+ id: 'inspect-rules',
41
+ description: 'Fetch deployed Firestore rules, parse to AST, and run validator checks.',
42
+ },
43
+ {
44
+ id: 'triage-findings',
45
+ description: 'Group validator findings by severity: critical, high, medium, low.',
46
+ },
47
+ {
48
+ id: 'cross-reference',
49
+ description: 'Combine findings on the same path to surface compound vulnerabilities.',
50
+ },
51
+ {
52
+ id: 'apply-context',
53
+ description: 'Escalate or de-escalate findings based on path purpose and data sensitivity.',
54
+ },
55
+ {
56
+ id: 'compile-report',
57
+ description: 'Compile prioritized health report with score, findings, and remediation.',
58
+ verifier: {
59
+ name: SPEC_REPORT_MENTIONS_AT_LEAST_ONE_OF,
60
+ args: { tokens: ['critical', 'high', 'finding'] },
61
+ },
62
+ },
63
+ ],
64
+ },
65
+ {
66
+ name: 'firebase-project-audit',
67
+ description: 'Audit an unknown Firebase project for auth gaps, rule weaknesses, and structural issues across services.',
68
+ triggerHints: ['firebase', 'project', 'audit', 'inspect', 'health', 'unknown'],
69
+ steps: [
70
+ {
71
+ id: 'inspect-project',
72
+ description: 'Inspect auth, rules, and database structure in a single crawl.',
73
+ },
74
+ {
75
+ id: 'assess-auth',
76
+ description: 'Evaluate enabled providers and surface auth configuration gaps.',
77
+ },
78
+ {
79
+ id: 'assess-rules',
80
+ description: 'Walk the rule tree and flag open paths, broken expressions, and warnings.',
81
+ },
82
+ {
83
+ id: 'assess-structure',
84
+ description: 'Walk the data structure for deep nesting, god nodes, and array patterns.',
85
+ },
86
+ {
87
+ id: 'cross-reference-rules-data',
88
+ description: 'Compare rule paths against data paths to find unprotected data and orphan rules.',
89
+ },
90
+ {
91
+ id: 'compile-report',
92
+ description: 'Compile prioritized report with health score, findings, and recommended skills to load.',
93
+ verifier: {
94
+ name: SPEC_REPORT_MENTIONS_AT_LEAST_ONE_OF,
95
+ args: { tokens: ['health', 'finding', 'recommendation'] },
96
+ },
97
+ },
98
+ ],
99
+ },
100
+ {
101
+ name: 'rtdb-data-modeling',
102
+ description: 'Analyze and recommend Realtime Database structures with flat collections, fan-out writes, and index tables.',
103
+ triggerHints: [
104
+ 'rtdb',
105
+ 'realtime',
106
+ 'data',
107
+ 'model',
108
+ 'modeling',
109
+ 'denormalize',
110
+ 'structure',
111
+ 'schema',
112
+ ],
113
+ steps: [
114
+ {
115
+ id: 'crawl-structure',
116
+ description: 'Crawl database structure to inventory top-level keys, depth, and child counts.',
117
+ },
118
+ {
119
+ id: 'sample-data',
120
+ description: 'Read representative paths to compare stored shape against per-screen needs.',
121
+ },
122
+ {
123
+ id: 'check-god-nodes',
124
+ description: 'Identify unbounded lists and god nodes that grow without per-user scoping.',
125
+ },
126
+ {
127
+ id: 'evaluate-queries',
128
+ description: 'Map each app list to a single orderBy path and flag multi-field filter needs.',
129
+ },
130
+ {
131
+ id: 'propose-restructure',
132
+ description: 'Propose flat collections, index tables, and summary collections via fan-out writes.',
133
+ },
134
+ {
135
+ id: 'verify-restructure',
136
+ description: 'Validate the proposed shape with a multi-path write and a re-crawl of the structure.',
137
+ verifier: {
138
+ name: SPEC_TRACE_CONTAINS_TOOL_CALL_BY_NAME,
139
+ args: { tool: 'crawl_database_structure', minCount: 1 },
140
+ },
141
+ },
142
+ ],
143
+ },
144
+ {
145
+ name: 'firebase-security-rules',
146
+ description: 'Author, simulate, and deploy Realtime Database security rules with auth, validation, and immutability patterns.',
147
+ triggerHints: ['rtdb', 'realtime', 'rules', 'security', 'authz', 'access', 'validate'],
148
+ steps: [
149
+ {
150
+ id: 'inspect-current-rules',
151
+ description: 'Inspect deployed rules and read linter warnings on existing expressions.',
152
+ },
153
+ {
154
+ id: 'design-change',
155
+ description: 'Identify the rule changes required by the request or by prior audit findings.',
156
+ },
157
+ {
158
+ id: 'validate-expressions',
159
+ description: 'Build and validate each rule expression before assembling the ruleset IR.',
160
+ },
161
+ {
162
+ id: 'simulate-access',
163
+ description: 'Simulate positive, negative, cross-user, and validation scenarios against the draft rules.',
164
+ },
165
+ {
166
+ id: 'deploy-rules',
167
+ description: 'Deploy the full ruleset after every simulation passes.',
168
+ verifier: {
169
+ name: SPEC_FINAL_RULES_INCLUDES_LITERAL,
170
+ args: { literal: 'auth' },
171
+ },
172
+ },
173
+ {
174
+ id: 'verify-deployment',
175
+ description: 'Re-inspect the deployed rules to confirm they match the intended IR.',
176
+ },
177
+ ],
178
+ },
179
+ {
180
+ name: 'firebase-client-sdk',
181
+ description: 'Generate correct Firebase web client code for init, auth gating, listeners, fan-out writes, and queries.',
182
+ triggerHints: ['client', 'sdk', 'web', 'javascript', 'app', 'listener', 'init'],
183
+ steps: [
184
+ {
185
+ id: 'get-config',
186
+ description: 'Fetch the project client config for initializeApp.',
187
+ },
188
+ {
189
+ id: 'inspect-rules-for-auth',
190
+ description: 'Inspect deployed rules to determine the auth state the client must satisfy.',
191
+ },
192
+ {
193
+ id: 'check-indexes',
194
+ description: 'Verify indexOn declarations cover every planned orderByChild query.',
195
+ },
196
+ {
197
+ id: 'generate-init-and-auth',
198
+ description: 'Emit initialization, the auth gate, and the sign-in flow.',
199
+ },
200
+ {
201
+ id: 'generate-reads',
202
+ description: 'Emit entity listeners, fan-in patterns, or one-time reads as needed.',
203
+ },
204
+ {
205
+ id: 'generate-writes',
206
+ description: 'Emit set, update at path, and multi-location update writes per intent.',
207
+ },
208
+ {
209
+ id: 'add-cleanup-and-errors',
210
+ description: 'Add listener unsubscription and permission-denied error handling.',
211
+ },
212
+ {
213
+ id: 'verify-run',
214
+ description: 'Run the generated code once and confirm the run summary reports success.',
215
+ verifier: { name: SPEC_FINAL_RUNTIME_RUN_SUMMARY_OK },
216
+ },
217
+ ],
218
+ },
219
+ {
220
+ name: 'pyric-agents',
221
+ description: 'Author Firestore rules and seed data through the pyric MCP tools with lint gating and reversible commits.',
222
+ triggerHints: ['pyric', 'firestore', 'rules', 'seed', 'lint', 'mcp'],
223
+ steps: [
224
+ {
225
+ id: 'draft-rules',
226
+ description: 'Draft the Firestore rules source in conversation.',
227
+ },
228
+ {
229
+ id: 'lint-rules',
230
+ description: 'Lint the draft and iterate until errors are empty.',
231
+ },
232
+ {
233
+ id: 'write-rules',
234
+ description: 'Write the lint-clean rules through the gated write tool.',
235
+ },
236
+ {
237
+ id: 'draft-seed',
238
+ description: 'Compose seed data as collection-to-documents arrays.',
239
+ },
240
+ {
241
+ id: 'write-seed',
242
+ description: 'Write the shape-validated seed through the gated write tool.',
243
+ verifier: {
244
+ name: SPEC_PYRIC_AGENTS_LINT_CLEAN_AND_RULE_REJECTS_CHEAT,
245
+ },
246
+ },
247
+ {
248
+ id: 'surface-audit-log',
249
+ description: 'Point the user at the emitted plan and commit event ids.',
250
+ },
251
+ ],
252
+ },
253
+ {
254
+ name: 'playground-prompts',
255
+ description: 'Generate well-shaped 30-50 word playground prompts with a bounded domain and a rule-enforced security boundary.',
256
+ triggerHints: ['playground', 'prompt', 'prompts', 'demo', 'test', 'scenario'],
257
+ steps: [
258
+ {
259
+ id: 'pick-dimension',
260
+ description: 'Pick the capability dimension to exercise (rules, transactions, queries, listeners).',
261
+ },
262
+ {
263
+ id: 'pick-domain',
264
+ description: 'Pick a bounded familiar domain with two collections and a relationship.',
265
+ },
266
+ {
267
+ id: 'specify-security-boundary',
268
+ description: 'Specify a security boundary tedious to enforce in client code alone.',
269
+ },
270
+ {
271
+ id: 'draft-prompt',
272
+ description: 'Draft a 30-50 word prompt that fills in actors, data model, and constraint.',
273
+ },
274
+ {
275
+ id: 'tag-capabilities',
276
+ description: 'Tag what the prompt exercises so the consumer can pick by capability.',
277
+ verifier: {
278
+ name: SPEC_REPORT_MENTIONS_AT_LEAST_ONE_OF,
279
+ args: { tokens: ['exercises', 'capability', 'rules', 'state', 'membership'] },
280
+ },
281
+ },
282
+ ],
283
+ },
284
+ {
285
+ name: 'rtdb-game-rules',
286
+ description: 'Design and deploy Realtime Database security rules for turn-based games with turn guards and win checks.',
287
+ triggerHints: ['rtdb', 'realtime', 'game', 'turn', 'multiplayer', 'rules'],
288
+ steps: [
289
+ {
290
+ id: 'identify-players',
291
+ description: 'Identify players, their marks, and how they map to authenticated UIDs.',
292
+ },
293
+ {
294
+ id: 'design-turn-flow',
295
+ description: 'Design the turn marker, alternation order, and turn-guard write rule.',
296
+ },
297
+ {
298
+ id: 'design-board-and-moves',
299
+ description: 'Design the board layout, move protocol, and per-cell validation.',
300
+ },
301
+ {
302
+ id: 'design-win-and-end',
303
+ description: 'Design win helpers, terminal states, and the winner validation rule.',
304
+ },
305
+ {
306
+ id: 'compose-ruleset',
307
+ description: 'Compose the full ruleset from turnGuard, flip, winCheckHelper, and helpers.',
308
+ },
309
+ {
310
+ id: 'simulate-and-deploy',
311
+ description: 'Simulate positive and cheating moves, then deploy the ruleset.',
312
+ verifier: {
313
+ name: SPEC_GAME_RULES_SIMULATOR_ACCEPTS_POSITIVE_AND_REJECTS_CHEAT,
314
+ args: { database: 'rtdb' },
315
+ },
316
+ },
317
+ ],
318
+ },
319
+ {
320
+ name: 'firestore-game-rules',
321
+ description: 'Design and deploy Firestore security rules for turn-based games with split-allow rules and dynamic field keys.',
322
+ triggerHints: ['firestore', 'game', 'turn', 'multiplayer', 'rules', 'split-allow'],
323
+ steps: [
324
+ {
325
+ id: 'design-board',
326
+ description: 'Design a flat board map with statically named cell fields.',
327
+ },
328
+ {
329
+ id: 'design-turns',
330
+ description: 'Design turn enforcement with resource.data and a turn-flip validation.',
331
+ },
332
+ {
333
+ id: 'design-move-validity',
334
+ description: 'Design placement or movement validity with dynamic field keys or a config document.',
335
+ },
336
+ {
337
+ id: 'design-win-detection',
338
+ description: 'Enumerate winning lines or piece-counter wins as static expressions.',
339
+ },
340
+ {
341
+ id: 'split-allow-rules',
342
+ description: 'Split the update rule into normal-move, winning-move, and draw branches to stay under the complexity ceiling.',
343
+ },
344
+ {
345
+ id: 'generate-and-deploy',
346
+ description: 'Generate the rules via code, deploy them, and verify under the test API.',
347
+ verifier: {
348
+ name: SPEC_GAME_RULES_SIMULATOR_ACCEPTS_POSITIVE_AND_REJECTS_CHEAT,
349
+ args: { database: 'firestore' },
350
+ },
351
+ },
352
+ {
353
+ id: 'iterate-on-complexity',
354
+ description: 'If valid moves are denied, re-split the rules and move expensive checks into separate allow branches.',
355
+ verifier: {
356
+ name: SPEC_REPORT_MENTIONS_ALL_OF,
357
+ args: { tokens: ['allow', 'update'] },
358
+ },
359
+ },
360
+ ],
361
+ },
362
+ ];
363
+ // ---------------------------------------------------------------------------
364
+ // Helpers. The router and executor will read the catalog through these to
365
+ // keep their implementations narrow; the catalog itself is exported as a
366
+ // value so callers can iterate without going through them.
367
+ // ---------------------------------------------------------------------------
368
+ const ENTRY_BY_NAME = new Map(SKILL_CATALOG.map((entry) => [entry.name, entry]));
369
+ const NAMES = SKILL_CATALOG.map((entry) => entry.name);
370
+ /**
371
+ * Look up a catalog entry by skill name. Returns `undefined` when the
372
+ * name is not in the catalog. The router will use this to materialize
373
+ * an entry after picking a winner; the executor will use it to
374
+ * unwrap a router decision into a plan.
375
+ */
376
+ export function getSkillEntry(name) {
377
+ return ENTRY_BY_NAME.get(name);
378
+ }
379
+ /**
380
+ * List every skill name present in the catalog, in catalog order. The
381
+ * router uses this to iterate candidates when scoring a prompt; the
382
+ * test suite uses it to assert the catalog covers every value in
383
+ * `SKILL_NAMES`.
384
+ */
385
+ export function listSkillNames() {
386
+ return NAMES;
387
+ }
388
+ //# sourceMappingURL=skill-catalog.js.map