@inneranimalmedia/agentsam-sdk 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEVELOPMENT.md +58 -0
- package/LICENSE +21 -0
- package/README.md +202 -0
- package/docs/CLI_SHELL.md +90 -0
- package/examples/gorilla-shell/App.tsx +540 -0
- package/examples/gorilla-shell/README.md +22 -0
- package/examples/gorilla-shell/index.html +15 -0
- package/examples/gorilla-shell/main.jsx +9 -0
- package/examples/gorilla-shell/package.json +19 -0
- package/examples/gorilla-shell/vite.config.js +10 -0
- package/package.json +24 -3
- package/src/AgentSam.js +67 -0
- package/src/cli.js +232 -56
- package/src/index.js +16 -4
- package/src/lib/responses.js +21 -0
- package/src/lib/router.js +51 -0
- package/src/lib/scaffold.js +208 -110
- package/src/lib/sessions.js +53 -0
- package/src/lib/slash-commands.js +40 -0
- package/src/lib/tools.js +38 -0
- package/src/schemas/config.js +2 -0
- package/test/smoke.mjs +42 -0
package/src/AgentSam.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { json, notFound, readJson } from './lib/responses.js';
|
|
2
|
+
import { createSession, getSession } from './lib/sessions.js';
|
|
3
|
+
import { routeIntent } from './lib/router.js';
|
|
4
|
+
import { getToolCatalog } from './lib/tools.js';
|
|
5
|
+
|
|
6
|
+
export class AgentSam {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.env = options.env ?? {};
|
|
9
|
+
this.agent = options.agent ?? 'orchestrator';
|
|
10
|
+
this.lane = options.lane ?? 'fullstack';
|
|
11
|
+
this.project = options.project ?? 'agentsam-project';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async handle(request) {
|
|
15
|
+
const url = new URL(request.url);
|
|
16
|
+
const path = url.pathname.replace(/\/$/, '') || '/';
|
|
17
|
+
|
|
18
|
+
if (request.method === 'GET' && path === '/api/health') {
|
|
19
|
+
return json({ ok: true, service: 'AgentSam', agent: this.agent, lane: this.lane, status: 'online' });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (request.method === 'GET' && path === '/api/agentsam/info') {
|
|
23
|
+
return json({
|
|
24
|
+
ok: true,
|
|
25
|
+
name: 'AgentSam SDK',
|
|
26
|
+
project: this.project,
|
|
27
|
+
agent: this.agent,
|
|
28
|
+
lane: this.lane,
|
|
29
|
+
capabilities: getToolCatalog(this.lane).map((tool) => tool.name),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (request.method === 'POST' && path === '/api/agentsam/session') {
|
|
34
|
+
const body = await readJson(request);
|
|
35
|
+
const session = await createSession({ env: this.env, agent: this.agent, lane: this.lane, goal: body.goal });
|
|
36
|
+
return json({ ok: true, session });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (request.method === 'GET' && path.startsWith('/api/agentsam/session/')) {
|
|
40
|
+
const sessionId = path.split('/').pop();
|
|
41
|
+
const session = await getSession({ env: this.env, sessionId });
|
|
42
|
+
if (!session) return json({ ok: false, error: 'session_not_found' }, 404);
|
|
43
|
+
return json({ ok: true, session });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (request.method === 'POST' && path === '/api/agentsam/message') {
|
|
47
|
+
const body = await readJson(request);
|
|
48
|
+
const result = routeIntent({
|
|
49
|
+
message: body.message ?? body.goal ?? '',
|
|
50
|
+
agent: body.agent ?? this.agent,
|
|
51
|
+
lane: body.lane ?? this.lane,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return json({
|
|
55
|
+
ok: true,
|
|
56
|
+
session_id: body.session_id ?? null,
|
|
57
|
+
agent: result.agent,
|
|
58
|
+
lane: result.lane,
|
|
59
|
+
intent: result.intent,
|
|
60
|
+
next_steps: result.next_steps,
|
|
61
|
+
requires_approval: result.requires_approval,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return notFound();
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/cli.js
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import readline from 'readline';
|
|
4
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
4
5
|
import { scaffoldProject } from './lib/scaffold.js';
|
|
6
|
+
import { SLASH_COMMANDS, SHELL_PHASES } from './lib/slash-commands.js';
|
|
5
7
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
+
const VERSION = pkg.version;
|
|
9
|
+
|
|
10
|
+
function createPrompt() {
|
|
11
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
12
|
+
return {
|
|
13
|
+
ask: (q) => new Promise((resolve) => rl.question(q, resolve)),
|
|
14
|
+
close: () => rl.close(),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
8
17
|
|
|
9
18
|
const LANES = {
|
|
10
19
|
'1': 'Full Stack',
|
|
11
|
-
'2': '
|
|
12
|
-
'3': '
|
|
13
|
-
'4': '
|
|
20
|
+
'2': 'CMS',
|
|
21
|
+
'3': 'Data Solutions',
|
|
22
|
+
'4': 'Customer Management',
|
|
23
|
+
'5': 'Creative & Design',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const LANE_BY_SLUG = {
|
|
27
|
+
fullstack: 'Full Stack',
|
|
28
|
+
cms: 'CMS',
|
|
29
|
+
data: 'Data Solutions',
|
|
30
|
+
crm: 'Customer Management',
|
|
31
|
+
creative: 'Creative & Design',
|
|
14
32
|
};
|
|
15
33
|
|
|
16
34
|
const PROVIDERS = {
|
|
@@ -19,61 +37,89 @@ const PROVIDERS = {
|
|
|
19
37
|
'3': 'Local / Self-hosted',
|
|
20
38
|
};
|
|
21
39
|
|
|
40
|
+
const PROVIDER_BY_SLUG = {
|
|
41
|
+
cloudflare: 'Cloudflare Workers',
|
|
42
|
+
github: 'GitHub + Cloudflare',
|
|
43
|
+
local: 'Local / Self-hosted',
|
|
44
|
+
};
|
|
45
|
+
|
|
22
46
|
const AGENTS = {
|
|
23
47
|
'1': 'orchestrator',
|
|
24
|
-
'2': '
|
|
25
|
-
'3': '
|
|
26
|
-
'4': '
|
|
48
|
+
'2': 'cms',
|
|
49
|
+
'3': 'data',
|
|
50
|
+
'4': 'crm',
|
|
51
|
+
'5': 'creative',
|
|
27
52
|
};
|
|
28
53
|
|
|
29
|
-
|
|
54
|
+
function laneKeyFromLabel(label) {
|
|
55
|
+
const entry = Object.entries(LANES).find(([, v]) => v === label);
|
|
56
|
+
return entry?.[0] ?? '1';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function printHelp() {
|
|
30
60
|
console.log(`
|
|
31
|
-
|
|
32
|
-
║ Agent Sam SDK — Init ║
|
|
33
|
-
╚═══════════════════════════════════╝
|
|
34
|
-
`);
|
|
61
|
+
Agent Sam SDK — CLI v${VERSION}
|
|
35
62
|
|
|
36
|
-
|
|
63
|
+
Usage:
|
|
64
|
+
agentsam init [options] Scaffold a new Agent Sam project
|
|
65
|
+
agentsam shell CLI shell UX info + slash commands (Gorilla Shell)
|
|
66
|
+
agentsam --version Print version
|
|
67
|
+
agentsam --help Show this help
|
|
37
68
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
69
|
+
Init options (non-interactive):
|
|
70
|
+
--name <name> Project directory name
|
|
71
|
+
--lane <fullstack|cms|data|crm|creative>
|
|
72
|
+
--provider <cloudflare|github|local>
|
|
73
|
+
--agent <orchestrator|cms|data|crm|creative>
|
|
74
|
+
--cf-account <id> Cloudflare account ID
|
|
75
|
+
--yes Skip confirmation prompt
|
|
44
76
|
`);
|
|
45
|
-
|
|
46
|
-
const lane = LANES[laneKey] ?? 'Full Stack';
|
|
77
|
+
}
|
|
47
78
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
79
|
+
function parseInitArgs(argv) {
|
|
80
|
+
const opts = {
|
|
81
|
+
projectName: '',
|
|
82
|
+
lane: '',
|
|
83
|
+
provider: '',
|
|
84
|
+
agent: '',
|
|
85
|
+
cfAccountId: '',
|
|
86
|
+
yes: false,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
90
|
+
const arg = argv[i];
|
|
91
|
+
if (arg === '--yes' || arg === '-y') opts.yes = true;
|
|
92
|
+
else if (arg === '--name') opts.projectName = argv[++i] || '';
|
|
93
|
+
else if (arg === '--lane') {
|
|
94
|
+
const slug = argv[++i] || '';
|
|
95
|
+
opts.lane = LANE_BY_SLUG[slug] || slug;
|
|
96
|
+
} else if (arg === '--provider') {
|
|
97
|
+
const slug = argv[++i] || '';
|
|
98
|
+
opts.provider = PROVIDER_BY_SLUG[slug] || slug;
|
|
99
|
+
} else if (arg === '--agent') opts.agent = argv[++i] || '';
|
|
100
|
+
else if (arg === '--cf-account') opts.cfAccountId = argv[++i] || '';
|
|
58
101
|
}
|
|
59
102
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
1) Orchestrator — general purpose, routes to all lanes
|
|
63
|
-
2) Data Agent — database ops, migrations, queries
|
|
64
|
-
3) CRM Agent — customer management, contacts, billing
|
|
65
|
-
4) Creative Agent — design, 3D, media, content
|
|
66
|
-
`);
|
|
67
|
-
const agentKey = await ask(' Agent [1-4]: ');
|
|
68
|
-
const agent = AGENTS[agentKey] ?? 'orchestrator';
|
|
103
|
+
return opts;
|
|
104
|
+
}
|
|
69
105
|
|
|
70
|
-
|
|
106
|
+
async function runInit(config) {
|
|
107
|
+
const {
|
|
108
|
+
projectName,
|
|
109
|
+
lane,
|
|
110
|
+
provider,
|
|
111
|
+
agent,
|
|
112
|
+
cfAccountId = '',
|
|
113
|
+
yes = false,
|
|
114
|
+
prompt = null,
|
|
115
|
+
} = config;
|
|
71
116
|
|
|
117
|
+
const safeDir = projectName.trim();
|
|
72
118
|
console.log(`
|
|
73
119
|
┌─────────────────────────────────────┐
|
|
74
120
|
│ Agent Sam Project Config │
|
|
75
121
|
├─────────────────────────────────────┤
|
|
76
|
-
│ Project: ${
|
|
122
|
+
│ Project: ${safeDir.padEnd(25)}│
|
|
77
123
|
│ Lane: ${lane.padEnd(25)}│
|
|
78
124
|
│ Provider: ${provider.padEnd(25)}│
|
|
79
125
|
│ Agent: ${agent.padEnd(25)}│
|
|
@@ -81,37 +127,167 @@ async function init() {
|
|
|
81
127
|
└─────────────────────────────────────┘
|
|
82
128
|
`);
|
|
83
129
|
|
|
84
|
-
|
|
130
|
+
let confirm = 'y';
|
|
131
|
+
if (!yes && prompt) {
|
|
132
|
+
confirm = await prompt.ask(' Scaffold project? (y/n): ');
|
|
133
|
+
}
|
|
85
134
|
|
|
86
135
|
if (confirm.toLowerCase() === 'y') {
|
|
87
|
-
|
|
88
|
-
|
|
136
|
+
try {
|
|
137
|
+
const dir = scaffoldProject({
|
|
138
|
+
projectName: safeDir,
|
|
139
|
+
lane,
|
|
140
|
+
provider,
|
|
141
|
+
agent,
|
|
142
|
+
cfAccountId,
|
|
143
|
+
sdkVersion: VERSION,
|
|
144
|
+
});
|
|
145
|
+
console.log(`
|
|
89
146
|
✓ Project created at ${dir}
|
|
90
147
|
|
|
91
148
|
Next steps:
|
|
92
|
-
cd ${
|
|
149
|
+
cd ${dir.split('/').pop()}
|
|
93
150
|
cp .env.example .env
|
|
94
151
|
npm install
|
|
152
|
+
npm run smoke
|
|
95
153
|
npm run dev
|
|
96
154
|
`);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error(`\n ✗ ${error.message}\n`);
|
|
157
|
+
process.exitCode = 1;
|
|
158
|
+
}
|
|
97
159
|
} else {
|
|
98
160
|
console.log('\n Cancelled.\n');
|
|
99
161
|
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function initInteractive(partial = {}) {
|
|
165
|
+
const prompt = createPrompt();
|
|
166
|
+
|
|
167
|
+
console.log(`
|
|
168
|
+
╔═══════════════════════════════════╗
|
|
169
|
+
║ Agent Sam SDK — Init ║
|
|
170
|
+
╚═══════════════════════════════════╝
|
|
171
|
+
`);
|
|
172
|
+
|
|
173
|
+
const projectName = partial.projectName || (await prompt.ask(' Project name: '));
|
|
174
|
+
|
|
175
|
+
if (!partial.lane) {
|
|
176
|
+
console.log(`
|
|
177
|
+
Select a lane:
|
|
178
|
+
1) Full Stack
|
|
179
|
+
2) CMS
|
|
180
|
+
3) Data Solutions
|
|
181
|
+
4) Customer Management
|
|
182
|
+
5) Creative & Design
|
|
183
|
+
`);
|
|
184
|
+
}
|
|
185
|
+
const laneKey = partial.lane ? laneKeyFromLabel(partial.lane) : await prompt.ask(' Lane [1-5]: ');
|
|
186
|
+
const lane = partial.lane || LANES[laneKey] || 'Full Stack';
|
|
187
|
+
|
|
188
|
+
console.log(`
|
|
189
|
+
Select a provider:
|
|
190
|
+
1) Cloudflare Workers
|
|
191
|
+
2) GitHub + Cloudflare
|
|
192
|
+
3) Local / Self-hosted
|
|
193
|
+
`);
|
|
194
|
+
const providerKey = partial.provider
|
|
195
|
+
? Object.entries(PROVIDERS).find(([, v]) => v === partial.provider)?.[0] || '1'
|
|
196
|
+
: await prompt.ask(' Provider [1-3]: ');
|
|
197
|
+
const provider = partial.provider || PROVIDERS[providerKey] || 'Cloudflare Workers';
|
|
198
|
+
|
|
199
|
+
if (!partial.agent) {
|
|
200
|
+
console.log(`
|
|
201
|
+
Select your default Agent Sam:
|
|
202
|
+
1) Orchestrator — general purpose, routes to all lanes
|
|
203
|
+
2) CMS Agent — pages, sections, assets, publishing workflows
|
|
204
|
+
3) Data Agent — database ops, migrations, queries
|
|
205
|
+
4) CRM Agent — customer management, contacts, billing
|
|
206
|
+
5) Creative Agent — design, 3D, media, content
|
|
207
|
+
`);
|
|
208
|
+
}
|
|
209
|
+
const agentKey = partial.agent
|
|
210
|
+
? Object.entries(AGENTS).find(([, v]) => v === partial.agent)?.[0] || '1'
|
|
211
|
+
: await prompt.ask(' Agent [1-5]: ');
|
|
212
|
+
const agent = partial.agent || AGENTS[agentKey] || 'orchestrator';
|
|
100
213
|
|
|
101
|
-
|
|
214
|
+
const cfAccountId =
|
|
215
|
+
partial.cfAccountId !== undefined && partial.cfAccountId !== ''
|
|
216
|
+
? partial.cfAccountId
|
|
217
|
+
: await prompt.ask(' Cloudflare Account ID (enter to skip): ');
|
|
218
|
+
|
|
219
|
+
await runInit({
|
|
220
|
+
projectName,
|
|
221
|
+
lane,
|
|
222
|
+
provider,
|
|
223
|
+
agent,
|
|
224
|
+
cfAccountId,
|
|
225
|
+
yes: partial.yes,
|
|
226
|
+
prompt,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
prompt.close();
|
|
102
230
|
}
|
|
103
231
|
|
|
104
|
-
|
|
232
|
+
async function initFromArgs(argv) {
|
|
233
|
+
const opts = parseInitArgs(argv);
|
|
234
|
+
if (!opts.projectName) {
|
|
235
|
+
console.error('\n ✗ --name is required for non-interactive init.\n');
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
await runInit({
|
|
239
|
+
projectName: opts.projectName,
|
|
240
|
+
lane: opts.lane || 'Full Stack',
|
|
241
|
+
provider: opts.provider || 'Cloudflare Workers',
|
|
242
|
+
agent: opts.agent || 'orchestrator',
|
|
243
|
+
cfAccountId: opts.cfAccountId,
|
|
244
|
+
yes: true,
|
|
245
|
+
prompt: null,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
105
248
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
} else {
|
|
249
|
+
async function runShellInfo() {
|
|
250
|
+
const next = SHELL_PHASES.find((p) => p.status === 'next');
|
|
109
251
|
console.log(`
|
|
110
|
-
|
|
252
|
+
╔═══════════════════════════════════╗
|
|
253
|
+
║ Agent Sam Shell (Gorilla) ║
|
|
254
|
+
╚═══════════════════════════════════╝
|
|
111
255
|
|
|
112
|
-
|
|
113
|
-
|
|
256
|
+
Game-feel terminal UX for SDK installs — HUD, themes, slash commands, PTY bridge.
|
|
257
|
+
|
|
258
|
+
Phase 0 prototype: examples/gorilla-shell/
|
|
259
|
+
Docs: docs/CLI_SHELL.md
|
|
260
|
+
Next milestone: ${next?.label ?? 'PTY connection'}
|
|
114
261
|
|
|
115
|
-
|
|
262
|
+
Slash commands (${SLASH_COMMANDS.length} registered):
|
|
263
|
+
`);
|
|
264
|
+
for (const row of SLASH_COMMANDS) {
|
|
265
|
+
console.log(` ${row.cmd.padEnd(14)} ${row.description}`);
|
|
266
|
+
}
|
|
267
|
+
console.log(`
|
|
268
|
+
Run the visual prototype:
|
|
269
|
+
cd examples/gorilla-shell && npm install && npm run dev
|
|
116
270
|
`);
|
|
117
271
|
}
|
|
272
|
+
|
|
273
|
+
const command = process.argv[2];
|
|
274
|
+
const rest = process.argv.slice(3);
|
|
275
|
+
|
|
276
|
+
if (command === '--version' || command === '-v') {
|
|
277
|
+
console.log(VERSION);
|
|
278
|
+
} else if (command === '--help' || command === '-h' || !command) {
|
|
279
|
+
printHelp();
|
|
280
|
+
} else if (command === 'shell') {
|
|
281
|
+
await runShellInfo();
|
|
282
|
+
} else if (command === 'init') {
|
|
283
|
+
const hasFlags = rest.some((a) => a.startsWith('--'));
|
|
284
|
+
if (hasFlags) {
|
|
285
|
+
await initFromArgs(rest);
|
|
286
|
+
} else {
|
|
287
|
+
await initInteractive({});
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
console.error(`\n Unknown command: ${command}\n`);
|
|
291
|
+
printHelp();
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
// @inneranimalmedia/agentsam-sdk
|
|
2
|
-
// Agent Sam SDK — entry point
|
|
1
|
+
// @inneranimalmedia/agentsam-sdk — public API
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
4
|
+
|
|
5
|
+
export { AgentSam } from './AgentSam.js';
|
|
6
|
+
export { routeIntent } from './lib/router.js';
|
|
7
|
+
export { getToolCatalog } from './lib/tools.js';
|
|
8
|
+
export { scaffoldProject } from './lib/scaffold.js';
|
|
9
|
+
export {
|
|
10
|
+
SLASH_COMMANDS,
|
|
11
|
+
SHELL_THEMES,
|
|
12
|
+
SHELL_PHASES,
|
|
13
|
+
listSlashCommands,
|
|
14
|
+
} from './lib/slash-commands.js';
|
|
15
|
+
|
|
16
|
+
export const version = pkg.version;
|
|
17
|
+
export const name = pkg.name;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function json(data, status = 200, headers = {}) {
|
|
2
|
+
return new Response(JSON.stringify(data, null, 2), {
|
|
3
|
+
status,
|
|
4
|
+
headers: {
|
|
5
|
+
'content-type': 'application/json; charset=utf-8',
|
|
6
|
+
...headers,
|
|
7
|
+
},
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function notFound() {
|
|
12
|
+
return json({ ok: false, error: 'not_found' }, 404);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function readJson(request) {
|
|
16
|
+
try {
|
|
17
|
+
return await request.json();
|
|
18
|
+
} catch {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export function routeIntent({ message = '', agent = 'orchestrator', lane = 'fullstack' }) {
|
|
2
|
+
const text = String(message).toLowerCase();
|
|
3
|
+
|
|
4
|
+
if (/delete|drop table|destroy|wipe|purge|production/.test(text)) {
|
|
5
|
+
return {
|
|
6
|
+
agent,
|
|
7
|
+
lane,
|
|
8
|
+
intent: 'high_risk_action',
|
|
9
|
+
requires_approval: true,
|
|
10
|
+
next_steps: ['Summarize intended change', 'Request explicit approval', 'Run only after approval'],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (/page|cms|publish|section|hero|content/.test(text)) {
|
|
15
|
+
return {
|
|
16
|
+
agent: 'cms',
|
|
17
|
+
lane: 'cms',
|
|
18
|
+
intent: 'cms_build',
|
|
19
|
+
requires_approval: false,
|
|
20
|
+
next_steps: ['Create page outline', 'Attach visual assets', 'Prepare draft for preview'],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (/database|sql|query|migration|schema|supabase|d1/.test(text)) {
|
|
25
|
+
return {
|
|
26
|
+
agent: 'data',
|
|
27
|
+
lane: 'data',
|
|
28
|
+
intent: 'data_task',
|
|
29
|
+
requires_approval: false,
|
|
30
|
+
next_steps: ['Inspect schema', 'Draft safe query or migration', 'Return reviewable plan'],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (/design|3d|cad|media|video|image|creative/.test(text)) {
|
|
35
|
+
return {
|
|
36
|
+
agent: 'creative',
|
|
37
|
+
lane: 'creative',
|
|
38
|
+
intent: 'creative_task',
|
|
39
|
+
requires_approval: false,
|
|
40
|
+
next_steps: ['Create production brief', 'Identify assets needed', 'Prepare generation or build steps'],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
agent,
|
|
46
|
+
lane,
|
|
47
|
+
intent: 'general_build',
|
|
48
|
+
requires_approval: false,
|
|
49
|
+
next_steps: ['Understand goal', 'Plan the work', 'Route to the right specialist'],
|
|
50
|
+
};
|
|
51
|
+
}
|