agentic-dev 0.2.13 → 0.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -9
- package/dist/bin/agentic-dev.d.ts +3 -0
- package/dist/bin/agentic-dev.d.ts.map +1 -0
- package/dist/bin/agentic-dev.js +854 -0
- package/dist/bin/agentic-dev.js.map +1 -0
- package/dist/lib/github.d.ts +27 -0
- package/dist/lib/github.d.ts.map +1 -0
- package/dist/lib/github.js +217 -0
- package/dist/lib/github.js.map +1 -0
- package/dist/lib/orchestration-assets.d.ts +6 -0
- package/dist/lib/orchestration-assets.d.ts.map +1 -0
- package/dist/lib/orchestration-assets.js +673 -0
- package/dist/lib/orchestration-assets.js.map +1 -0
- package/dist/lib/scaffold.d.ts +23 -0
- package/dist/lib/scaffold.d.ts.map +1 -0
- package/dist/lib/scaffold.js +502 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/types.d.ts +106 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/types.js.map +1 -0
- package/package.json +13 -6
- package/bin/agentic-dev.mjs +0 -1014
- package/lib/github.mjs +0 -246
- package/lib/orchestration-assets.mjs +0 -249
- package/lib/scaffold.mjs +0 -609
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const SPECIALIZED_AGENTS = [
|
|
5
|
+
{ id: "architecture", description: "Drive boundaries, system shape, and migration decisions." },
|
|
6
|
+
{ id: "specs", description: "Translate SDD planning artifacts into actionable task structure." },
|
|
7
|
+
{ id: "runtime", description: "Own application/runtime implementation work." },
|
|
8
|
+
{ id: "ui", description: "Own screen and UI delivery tasks." },
|
|
9
|
+
{ id: "api", description: "Own contract and API work." },
|
|
10
|
+
{ id: "quality", description: "Run verification and regression closure." },
|
|
11
|
+
{ id: "gitops", description: "Own GitHub Projects, workflow automation, and delivery closure." },
|
|
12
|
+
];
|
|
13
|
+
function repoRootDir() {
|
|
14
|
+
return path.resolve(new URL("../../", import.meta.url).pathname);
|
|
15
|
+
}
|
|
16
|
+
function copyRecursive(sourceRoot, destinationRoot) {
|
|
17
|
+
fs.mkdirSync(destinationRoot, { recursive: true });
|
|
18
|
+
for (const entry of fs.readdirSync(sourceRoot, { withFileTypes: true })) {
|
|
19
|
+
const sourcePath = path.join(sourceRoot, entry.name);
|
|
20
|
+
const destinationPath = path.join(destinationRoot, entry.name);
|
|
21
|
+
if (entry.isDirectory()) {
|
|
22
|
+
copyRecursive(sourcePath, destinationPath);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
fs.copyFileSync(sourcePath, destinationPath);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function writeFile(filePath, content) {
|
|
30
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
31
|
+
fs.writeFileSync(filePath, content);
|
|
32
|
+
}
|
|
33
|
+
function workflowYaml() {
|
|
34
|
+
return `name: Agentic Orchestration
|
|
35
|
+
|
|
36
|
+
on:
|
|
37
|
+
push:
|
|
38
|
+
paths:
|
|
39
|
+
- "sdd/02_plan/**"
|
|
40
|
+
- ".agentic-dev/orchestration.json"
|
|
41
|
+
- ".agentic-dev/runtime/**"
|
|
42
|
+
workflow_dispatch:
|
|
43
|
+
|
|
44
|
+
jobs:
|
|
45
|
+
orchestrate:
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
permissions:
|
|
48
|
+
contents: read
|
|
49
|
+
issues: write
|
|
50
|
+
repository-projects: write
|
|
51
|
+
steps:
|
|
52
|
+
- name: Checkout
|
|
53
|
+
uses: actions/checkout@v4
|
|
54
|
+
|
|
55
|
+
- name: Setup Node
|
|
56
|
+
uses: actions/setup-node@v4
|
|
57
|
+
with:
|
|
58
|
+
node-version: "22"
|
|
59
|
+
|
|
60
|
+
- name: Start orchestration server
|
|
61
|
+
env:
|
|
62
|
+
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
63
|
+
run: |
|
|
64
|
+
npx --yes tsx .agentic-dev/runtime/server.ts > /tmp/agentic-orchestration.log 2>&1 &
|
|
65
|
+
echo $! > /tmp/agentic-orchestration.pid
|
|
66
|
+
for i in $(seq 1 30); do
|
|
67
|
+
if curl -fsS http://127.0.0.1:4310/health >/dev/null; then
|
|
68
|
+
exit 0
|
|
69
|
+
fi
|
|
70
|
+
sleep 1
|
|
71
|
+
done
|
|
72
|
+
cat /tmp/agentic-orchestration.log
|
|
73
|
+
exit 1
|
|
74
|
+
|
|
75
|
+
- name: Build task IR from SDD planning
|
|
76
|
+
run: curl -fsS -X POST http://127.0.0.1:4310/sync/ir
|
|
77
|
+
|
|
78
|
+
- name: Sync GitHub project tasks
|
|
79
|
+
env:
|
|
80
|
+
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
81
|
+
run: curl -fsS -X POST http://127.0.0.1:4310/sync/tasks
|
|
82
|
+
|
|
83
|
+
- name: Plan multi-agent queue
|
|
84
|
+
env:
|
|
85
|
+
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
86
|
+
run: curl -fsS -X POST http://127.0.0.1:4310/queue/plan
|
|
87
|
+
|
|
88
|
+
- name: Build dispatch plan
|
|
89
|
+
env:
|
|
90
|
+
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
91
|
+
run: curl -fsS -X POST http://127.0.0.1:4310/queue/dispatch
|
|
92
|
+
|
|
93
|
+
- name: Execute dispatch queue
|
|
94
|
+
env:
|
|
95
|
+
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
96
|
+
AGENTIC_AGENT_TIMEOUT_MS: "30000"
|
|
97
|
+
run: curl -fsS -X POST http://127.0.0.1:4310/queue/execute
|
|
98
|
+
|
|
99
|
+
- name: Close completed tasks
|
|
100
|
+
env:
|
|
101
|
+
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
102
|
+
run: curl -fsS -X POST http://127.0.0.1:4310/tasks/close
|
|
103
|
+
|
|
104
|
+
- name: Stop orchestration server
|
|
105
|
+
if: always()
|
|
106
|
+
run: |
|
|
107
|
+
if [ -f /tmp/agentic-orchestration.pid ]; then
|
|
108
|
+
kill $(cat /tmp/agentic-orchestration.pid) || true
|
|
109
|
+
fi
|
|
110
|
+
`;
|
|
111
|
+
}
|
|
112
|
+
function runtimeLibScript() {
|
|
113
|
+
return `#!/usr/bin/env node
|
|
114
|
+
import fs from "node:fs";
|
|
115
|
+
import path from "node:path";
|
|
116
|
+
import { execFileSync } from "node:child_process";
|
|
117
|
+
|
|
118
|
+
export function ensureDir(dir) {
|
|
119
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function readJson(filePath, fallback = null) {
|
|
123
|
+
if (!fs.existsSync(filePath)) return fallback;
|
|
124
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function writeJson(filePath, payload) {
|
|
128
|
+
ensureDir(path.dirname(filePath));
|
|
129
|
+
fs.writeFileSync(filePath, JSON.stringify(payload, null, 2) + "\\n");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function generatedDir() {
|
|
133
|
+
return path.resolve(".agentic-dev/generated");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function generatedPath(name) {
|
|
137
|
+
return path.join(generatedDir(), name);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function orchestrationConfig() {
|
|
141
|
+
return readJson(path.resolve(".agentic-dev/orchestration.json"), {});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function ghJson(args) {
|
|
145
|
+
return JSON.parse(execFileSync("gh", args, { encoding: "utf-8" }));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function gh(args) {
|
|
149
|
+
return execFileSync("gh", args, { encoding: "utf-8" }).trim();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function loadTaskIr() {
|
|
153
|
+
return readJson(generatedPath("task-ir.json"), { tasks: [] });
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function loadQueue() {
|
|
157
|
+
return readJson(generatedPath("agent-queue.json"), { queue: [] });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function loadTaskIndex() {
|
|
161
|
+
return readJson(generatedPath("task-index.json"), { tasks: [] });
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function loadDispatchPlan() {
|
|
165
|
+
return readJson(generatedPath("dispatch-plan.json"), { dispatch: [] });
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function loadExecutionJournal() {
|
|
169
|
+
return readJson(generatedPath("execution-journal.json"), { executions: [] });
|
|
170
|
+
}
|
|
171
|
+
`;
|
|
172
|
+
}
|
|
173
|
+
function sddToIrScript() {
|
|
174
|
+
return `#!/usr/bin/env node
|
|
175
|
+
import fs from "node:fs";
|
|
176
|
+
import path from "node:path";
|
|
177
|
+
import { generatedPath, writeJson } from "./runtime-lib.ts";
|
|
178
|
+
|
|
179
|
+
function walk(root) {
|
|
180
|
+
if (!fs.existsSync(root)) return [];
|
|
181
|
+
const files = [];
|
|
182
|
+
for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
|
|
183
|
+
const full = path.join(root, entry.name);
|
|
184
|
+
if (entry.isDirectory()) files.push(...walk(full));
|
|
185
|
+
else if (entry.name.endsWith(".md")) files.push(full);
|
|
186
|
+
}
|
|
187
|
+
return files;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function parseChecklist(markdown, source) {
|
|
191
|
+
const tasks = [];
|
|
192
|
+
const lines = markdown.split(/\\r?\\n/);
|
|
193
|
+
for (const [index, line] of lines.entries()) {
|
|
194
|
+
const match = line.match(/^- \\[( |x)\\] (.+)$/);
|
|
195
|
+
if (!match) continue;
|
|
196
|
+
const status = match[1] === "x" ? "closed" : "open";
|
|
197
|
+
const title = match[2].trim();
|
|
198
|
+
const id = \`\${path.basename(source, ".md")}:\${index + 1}\`;
|
|
199
|
+
tasks.push({ id, title, status, source });
|
|
200
|
+
}
|
|
201
|
+
return tasks;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const planRoot = path.resolve("sdd/02_plan");
|
|
205
|
+
const files = walk(planRoot);
|
|
206
|
+
const tasks = files.flatMap((file) =>
|
|
207
|
+
parseChecklist(fs.readFileSync(file, "utf-8"), path.relative(process.cwd(), file)),
|
|
208
|
+
);
|
|
209
|
+
const outputPath = generatedPath("task-ir.json");
|
|
210
|
+
writeJson(outputPath, { generated_at: new Date().toISOString(), tasks });
|
|
211
|
+
console.log(\`task_ir=\${outputPath}\`);
|
|
212
|
+
console.log(\`tasks=\${tasks.length}\`);
|
|
213
|
+
`;
|
|
214
|
+
}
|
|
215
|
+
function syncProjectTasksScript() {
|
|
216
|
+
return `#!/usr/bin/env node
|
|
217
|
+
import { gh, ghJson, loadTaskIr, orchestrationConfig, writeJson, generatedPath } from "./runtime-lib.ts";
|
|
218
|
+
|
|
219
|
+
const orchestration = orchestrationConfig();
|
|
220
|
+
const taskIr = loadTaskIr();
|
|
221
|
+
const existingIssues = ghJson([
|
|
222
|
+
"issue",
|
|
223
|
+
"list",
|
|
224
|
+
"--repo",
|
|
225
|
+
orchestration.github.repository.slug,
|
|
226
|
+
"--state",
|
|
227
|
+
"all",
|
|
228
|
+
"--limit",
|
|
229
|
+
"200",
|
|
230
|
+
"--json",
|
|
231
|
+
"number,title,state",
|
|
232
|
+
]);
|
|
233
|
+
const syncResult = { created: [], closed: [], tasks: [] };
|
|
234
|
+
|
|
235
|
+
for (const task of taskIr.tasks) {
|
|
236
|
+
const issueTitle = \`[agentic-task] \${task.id} \${task.title}\`;
|
|
237
|
+
const found = existingIssues.find((issue) =>
|
|
238
|
+
issue.title.startsWith(\`[agentic-task] \${task.id} \`),
|
|
239
|
+
);
|
|
240
|
+
if (!found && task.status === "open") {
|
|
241
|
+
const url = gh([
|
|
242
|
+
"issue",
|
|
243
|
+
"create",
|
|
244
|
+
"--repo",
|
|
245
|
+
orchestration.github.repository.slug,
|
|
246
|
+
"--title",
|
|
247
|
+
issueTitle,
|
|
248
|
+
"--body",
|
|
249
|
+
\`SDD source: \${task.source}\\n\\nManaged by agentic-dev orchestration.\`,
|
|
250
|
+
]);
|
|
251
|
+
syncResult.created.push({ id: task.id, title: task.title, issue_url: url });
|
|
252
|
+
}
|
|
253
|
+
if (found && task.status === "closed" && found.state !== "CLOSED") {
|
|
254
|
+
gh([
|
|
255
|
+
"issue",
|
|
256
|
+
"close",
|
|
257
|
+
String(found.number),
|
|
258
|
+
"--repo",
|
|
259
|
+
orchestration.github.repository.slug,
|
|
260
|
+
"--comment",
|
|
261
|
+
"Closed from SDD task IR.",
|
|
262
|
+
]);
|
|
263
|
+
syncResult.closed.push({ id: task.id, issue_number: found.number });
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
syncResult.tasks.push({
|
|
267
|
+
id: task.id,
|
|
268
|
+
title: task.title,
|
|
269
|
+
source: task.source,
|
|
270
|
+
status: task.status,
|
|
271
|
+
issue_number: found?.number ?? null,
|
|
272
|
+
issue_url: found
|
|
273
|
+
? \`https://github.com/\${orchestration.github.repository.slug}/issues/\${found.number}\`
|
|
274
|
+
: null,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
writeJson(generatedPath("task-sync.json"), syncResult);
|
|
279
|
+
writeJson(generatedPath("task-index.json"), { tasks: syncResult.tasks });
|
|
280
|
+
console.log(\`synced_tasks=\${taskIr.tasks.length}\`);
|
|
281
|
+
`;
|
|
282
|
+
}
|
|
283
|
+
function runQueueScript() {
|
|
284
|
+
return `#!/usr/bin/env node
|
|
285
|
+
import { generatedPath, loadTaskIr, orchestrationConfig, writeJson } from "./runtime-lib.ts";
|
|
286
|
+
|
|
287
|
+
const orchestration = orchestrationConfig();
|
|
288
|
+
const taskIr = loadTaskIr();
|
|
289
|
+
|
|
290
|
+
function classifyAgent(title) {
|
|
291
|
+
const lower = title.toLowerCase();
|
|
292
|
+
if (lower.includes("api") || lower.includes("contract")) return "api";
|
|
293
|
+
if (lower.includes("screen") || lower.includes("ui")) return "ui";
|
|
294
|
+
if (lower.includes("verify") || lower.includes("test") || lower.includes("proof")) return "quality";
|
|
295
|
+
if (lower.includes("workflow") || lower.includes("project") || lower.includes("github")) return "gitops";
|
|
296
|
+
if (lower.includes("arch") || lower.includes("boundary") || lower.includes("structure")) return "architecture";
|
|
297
|
+
if (lower.includes("plan") || lower.includes("spec")) return "specs";
|
|
298
|
+
return "runtime";
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function pickProvider(title) {
|
|
302
|
+
const providers = Array.isArray(orchestration.providers) ? orchestration.providers : [];
|
|
303
|
+
const lower = title.toLowerCase();
|
|
304
|
+
if (lower.includes("verify") || lower.includes("test")) {
|
|
305
|
+
return providers.find((provider) => provider.startsWith("claude")) || providers[0] || "claude-subscription";
|
|
306
|
+
}
|
|
307
|
+
if (lower.includes("api") || lower.includes("contract")) {
|
|
308
|
+
return providers.find((provider) => provider.includes("api")) || providers[0] || "openai-api";
|
|
309
|
+
}
|
|
310
|
+
return providers.find((provider) => provider.startsWith("codex")) || providers[0] || "codex-subscription";
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const openTasks = taskIr.tasks.filter((task) => task.status === "open");
|
|
314
|
+
const queue = openTasks.map((task) => ({
|
|
315
|
+
...task,
|
|
316
|
+
assigned_agent: classifyAgent(task.title),
|
|
317
|
+
preferred_provider: pickProvider(task.title),
|
|
318
|
+
}));
|
|
319
|
+
|
|
320
|
+
const outputPath = generatedPath("agent-queue.json");
|
|
321
|
+
writeJson(outputPath, { providers: orchestration.providers, queue });
|
|
322
|
+
console.log(\`agent_queue=\${outputPath}\`);
|
|
323
|
+
console.log(\`queued=\${queue.length}\`);
|
|
324
|
+
`;
|
|
325
|
+
}
|
|
326
|
+
function dispatchQueueScript() {
|
|
327
|
+
return `#!/usr/bin/env node
|
|
328
|
+
import { generatedPath, loadQueue, orchestrationConfig, writeJson } from "./runtime-lib.ts";
|
|
329
|
+
|
|
330
|
+
const orchestration = orchestrationConfig();
|
|
331
|
+
const queuePayload = loadQueue();
|
|
332
|
+
|
|
333
|
+
const dispatch = queuePayload.queue.map((task) => ({
|
|
334
|
+
task_id: task.id,
|
|
335
|
+
title: task.title,
|
|
336
|
+
source: task.source,
|
|
337
|
+
assigned_agent: task.assigned_agent,
|
|
338
|
+
provider: task.preferred_provider,
|
|
339
|
+
repository: orchestration.github.repository.slug,
|
|
340
|
+
project_title: orchestration.github.project.title,
|
|
341
|
+
execution_state: "planned",
|
|
342
|
+
}));
|
|
343
|
+
|
|
344
|
+
const outputPath = generatedPath("dispatch-plan.json");
|
|
345
|
+
writeJson(outputPath, {
|
|
346
|
+
generated_at: new Date().toISOString(),
|
|
347
|
+
dispatch,
|
|
348
|
+
});
|
|
349
|
+
console.log(\`dispatch_plan=\${outputPath}\`);
|
|
350
|
+
console.log(\`planned=\${dispatch.length}\`);
|
|
351
|
+
`;
|
|
352
|
+
}
|
|
353
|
+
function dispatchExecutorScript() {
|
|
354
|
+
return `#!/usr/bin/env node
|
|
355
|
+
import fs from "node:fs";
|
|
356
|
+
import path from "node:path";
|
|
357
|
+
import { spawnSync } from "node:child_process";
|
|
358
|
+
import { generatedPath, loadDispatchPlan, loadTaskIndex, orchestrationConfig, writeJson } from "./runtime-lib.ts";
|
|
359
|
+
|
|
360
|
+
const orchestration = orchestrationConfig();
|
|
361
|
+
const dispatchPlan = loadDispatchPlan();
|
|
362
|
+
const taskIndex = loadTaskIndex();
|
|
363
|
+
const executionDir = generatedPath("executions");
|
|
364
|
+
const commandTimeoutMs = Number(process.env.AGENTIC_AGENT_TIMEOUT_MS || 30000);
|
|
365
|
+
fs.mkdirSync(executionDir, { recursive: true });
|
|
366
|
+
|
|
367
|
+
function commandExists(command) {
|
|
368
|
+
const result = spawnSync("bash", ["-lc", \`command -v \${command}\`], { stdio: "ignore" });
|
|
369
|
+
return result.status === 0;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function commentOnIssue(issueNumber, body) {
|
|
373
|
+
return spawnSync(
|
|
374
|
+
"gh",
|
|
375
|
+
["issue", "comment", String(issueNumber), "--repo", orchestration.github.repository.slug, "--body", body],
|
|
376
|
+
{ encoding: "utf-8" },
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function buildPrompt(item, taskMeta) {
|
|
381
|
+
return [
|
|
382
|
+
\`You are the \${item.assigned_agent} agent working inside repository \${item.repository}.\`,
|
|
383
|
+
\`GitHub Project: \${item.project_title}\`,
|
|
384
|
+
\`Task id: \${item.task_id}\`,
|
|
385
|
+
\`Task title: \${item.title}\`,
|
|
386
|
+
taskMeta?.source ? \`SDD source: \${taskMeta.source}\` : "",
|
|
387
|
+
"Follow the repository SDD workflow.",
|
|
388
|
+
"Implement the task directly in the working tree when changes are required.",
|
|
389
|
+
"Run relevant verification for the task.",
|
|
390
|
+
"Return a concise summary of what changed, what was verified, and any blockers.",
|
|
391
|
+
]
|
|
392
|
+
.filter(Boolean)
|
|
393
|
+
.join("\\n");
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function runProvider(provider, prompt) {
|
|
397
|
+
if ((provider.startsWith("codex") || provider.startsWith("openai")) && commandExists("codex")) {
|
|
398
|
+
return {
|
|
399
|
+
adapter: "codex-cli",
|
|
400
|
+
result: spawnSync(
|
|
401
|
+
"codex",
|
|
402
|
+
[
|
|
403
|
+
"exec",
|
|
404
|
+
"--skip-git-repo-check",
|
|
405
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
406
|
+
"--cd",
|
|
407
|
+
process.cwd(),
|
|
408
|
+
prompt,
|
|
409
|
+
],
|
|
410
|
+
{ encoding: "utf-8", maxBuffer: 1024 * 1024 * 20, timeout: commandTimeoutMs },
|
|
411
|
+
),
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (provider.startsWith("claude") && commandExists("claude")) {
|
|
416
|
+
return {
|
|
417
|
+
adapter: "claude-cli",
|
|
418
|
+
result: spawnSync(
|
|
419
|
+
"claude",
|
|
420
|
+
[
|
|
421
|
+
"-p",
|
|
422
|
+
"--dangerously-skip-permissions",
|
|
423
|
+
"--output-format",
|
|
424
|
+
"text",
|
|
425
|
+
"--add-dir",
|
|
426
|
+
process.cwd(),
|
|
427
|
+
prompt,
|
|
428
|
+
],
|
|
429
|
+
{ encoding: "utf-8", maxBuffer: 1024 * 1024 * 20, timeout: commandTimeoutMs },
|
|
430
|
+
),
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (provider.startsWith("ollama") && commandExists("ollama")) {
|
|
435
|
+
return {
|
|
436
|
+
adapter: "ollama-cli",
|
|
437
|
+
result: spawnSync(
|
|
438
|
+
"ollama",
|
|
439
|
+
["run", process.env.AGENTIC_OLLAMA_MODEL || "qwen2.5-coder:7b", prompt],
|
|
440
|
+
{ encoding: "utf-8", maxBuffer: 1024 * 1024 * 20, timeout: commandTimeoutMs },
|
|
441
|
+
),
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return {
|
|
446
|
+
adapter: "unavailable",
|
|
447
|
+
result: {
|
|
448
|
+
status: 127,
|
|
449
|
+
stdout: "",
|
|
450
|
+
stderr: \`No live adapter available for provider \${provider}\`,
|
|
451
|
+
},
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const executions = [];
|
|
456
|
+
|
|
457
|
+
for (const item of dispatchPlan.dispatch) {
|
|
458
|
+
const taskMeta = taskIndex.tasks.find((task) => task.id === item.task_id) || {};
|
|
459
|
+
const executionPath = path.join(executionDir, \`\${item.task_id}.json\`);
|
|
460
|
+
const prompt = buildPrompt(item, taskMeta);
|
|
461
|
+
const startedAt = new Date().toISOString();
|
|
462
|
+
|
|
463
|
+
const record = {
|
|
464
|
+
...item,
|
|
465
|
+
issue_number: taskMeta.issue_number ?? null,
|
|
466
|
+
issue_url: taskMeta.issue_url ?? null,
|
|
467
|
+
started_at: startedAt,
|
|
468
|
+
completed_at: null,
|
|
469
|
+
prompt_path: path.relative(process.cwd(), executionPath.replace(/\\.json$/, ".prompt.txt")),
|
|
470
|
+
execution_artifact: path.relative(process.cwd(), executionPath),
|
|
471
|
+
adapter: "pending",
|
|
472
|
+
execution_state: "running",
|
|
473
|
+
exit_code: null,
|
|
474
|
+
stdout: "",
|
|
475
|
+
stderr: "",
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
fs.writeFileSync(executionPath.replace(/\\.json$/, ".prompt.txt"), prompt + "\\n");
|
|
479
|
+
const live = runProvider(String(item.provider || ""), prompt);
|
|
480
|
+
record.adapter = live.adapter;
|
|
481
|
+
record.exit_code = live.result.status ?? null;
|
|
482
|
+
record.stdout = String(live.result.stdout || "");
|
|
483
|
+
record.stderr = String(live.result.stderr || "");
|
|
484
|
+
record.execution_state = live.result.status === 0 ? "completed" : "failed";
|
|
485
|
+
record.completed_at = new Date().toISOString();
|
|
486
|
+
|
|
487
|
+
if (record.issue_number) {
|
|
488
|
+
const comment = [
|
|
489
|
+
"Agentic-dev dispatch execution result",
|
|
490
|
+
\`Task: \${record.task_id}\`,
|
|
491
|
+
\`Provider: \${record.provider}\`,
|
|
492
|
+
\`Adapter: \${record.adapter}\`,
|
|
493
|
+
\`State: \${record.execution_state}\`,
|
|
494
|
+
\`Execution artifact: \${record.execution_artifact}\`,
|
|
495
|
+
].join("\\n");
|
|
496
|
+
commentOnIssue(record.issue_number, comment);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
fs.writeFileSync(executionPath, JSON.stringify(record, null, 2) + "\\n");
|
|
500
|
+
executions.push(record);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
writeJson(generatedPath("execution-journal.json"), {
|
|
504
|
+
generated_at: new Date().toISOString(),
|
|
505
|
+
executions,
|
|
506
|
+
});
|
|
507
|
+
console.log(\`executed=\${executions.length}\`);
|
|
508
|
+
console.log(\`execution_journal=\${generatedPath("execution-journal.json")}\`);
|
|
509
|
+
`;
|
|
510
|
+
}
|
|
511
|
+
function closeTasksScript() {
|
|
512
|
+
return `#!/usr/bin/env node
|
|
513
|
+
import { gh, ghJson, generatedPath, loadExecutionJournal, orchestrationConfig, writeJson } from "./runtime-lib.ts";
|
|
514
|
+
|
|
515
|
+
const orchestration = orchestrationConfig();
|
|
516
|
+
const executionJournal = loadExecutionJournal();
|
|
517
|
+
const issues = ghJson([
|
|
518
|
+
"issue",
|
|
519
|
+
"list",
|
|
520
|
+
"--repo",
|
|
521
|
+
orchestration.github.repository.slug,
|
|
522
|
+
"--state",
|
|
523
|
+
"open",
|
|
524
|
+
"--limit",
|
|
525
|
+
"200",
|
|
526
|
+
"--json",
|
|
527
|
+
"number,title",
|
|
528
|
+
]);
|
|
529
|
+
const closed = [];
|
|
530
|
+
|
|
531
|
+
const successfulTaskIds = new Set(
|
|
532
|
+
executionJournal.executions
|
|
533
|
+
.filter((execution) => execution.execution_state === "completed")
|
|
534
|
+
.map((execution) => execution.task_id),
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
for (const issue of issues) {
|
|
538
|
+
const match = issue.title.match(/^\\[agentic-task\\] ([^ ]+) /);
|
|
539
|
+
if (!match) continue;
|
|
540
|
+
if (!successfulTaskIds.has(match[1])) continue;
|
|
541
|
+
gh([
|
|
542
|
+
"issue",
|
|
543
|
+
"close",
|
|
544
|
+
String(issue.number),
|
|
545
|
+
"--repo",
|
|
546
|
+
orchestration.github.repository.slug,
|
|
547
|
+
"--comment",
|
|
548
|
+
"Closed from SDD orchestration close pass.",
|
|
549
|
+
]);
|
|
550
|
+
closed.push({ id: match[1], issue_number: issue.number });
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
writeJson(generatedPath("closed-tasks.json"), { closed });
|
|
554
|
+
console.log(\`closed_candidates=\${successfulTaskIds.size}\`);
|
|
555
|
+
`;
|
|
556
|
+
}
|
|
557
|
+
function serverScript() {
|
|
558
|
+
return `#!/usr/bin/env node
|
|
559
|
+
import http from "node:http";
|
|
560
|
+
import { spawn } from "node:child_process";
|
|
561
|
+
|
|
562
|
+
const port = Number(process.env.AGENTIC_ORCHESTRATION_PORT || 4310);
|
|
563
|
+
|
|
564
|
+
function runNodeScript(script) {
|
|
565
|
+
return new Promise((resolve, reject) => {
|
|
566
|
+
const child = spawn("npx", ["--yes", "tsx", script], {
|
|
567
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
let stdout = "";
|
|
571
|
+
let stderr = "";
|
|
572
|
+
|
|
573
|
+
child.stdout.on("data", (chunk) => {
|
|
574
|
+
stdout += chunk.toString();
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
child.stderr.on("data", (chunk) => {
|
|
578
|
+
stderr += chunk.toString();
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
child.on("close", (code) => {
|
|
582
|
+
if (code !== 0) {
|
|
583
|
+
reject(new Error(stderr || stdout || \`Script failed: \${script}\`));
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
resolve({ stdout, stderr });
|
|
587
|
+
});
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const routes = {
|
|
592
|
+
"POST /sync/ir": ".agentic-dev/runtime/sdd_to_ir.ts",
|
|
593
|
+
"POST /sync/tasks": ".agentic-dev/runtime/sync_project_tasks.ts",
|
|
594
|
+
"POST /queue/plan": ".agentic-dev/runtime/run_multi_agent_queue.ts",
|
|
595
|
+
"POST /queue/dispatch": ".agentic-dev/runtime/dispatch_agents.ts",
|
|
596
|
+
"POST /queue/execute": ".agentic-dev/runtime/dispatch_execute.ts",
|
|
597
|
+
"POST /tasks/close": ".agentic-dev/runtime/close_completed_tasks.ts",
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
const server = http.createServer(async (req, res) => {
|
|
601
|
+
const routeKey = \`\${req.method} \${req.url}\`;
|
|
602
|
+
if (req.method === "GET" && req.url === "/health") {
|
|
603
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
604
|
+
res.end(JSON.stringify({ ok: true, port }));
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const script = routes[routeKey];
|
|
609
|
+
if (!script) {
|
|
610
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
611
|
+
res.end(JSON.stringify({ error: "not_found" }));
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
try {
|
|
616
|
+
const result = await runNodeScript(script);
|
|
617
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
618
|
+
res.end(JSON.stringify({ ok: true, stdout: result.stdout.trim() }));
|
|
619
|
+
} catch (error) {
|
|
620
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
621
|
+
res.end(JSON.stringify({ ok: false, error: String(error.message || error) }));
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
server.listen(port, "127.0.0.1", () => {
|
|
626
|
+
console.log(\`agentic_orchestration_server=http://127.0.0.1:\${port}\`);
|
|
627
|
+
});
|
|
628
|
+
`;
|
|
629
|
+
}
|
|
630
|
+
export function installSharedAgentAssets(destinationRoot) {
|
|
631
|
+
const root = repoRootDir();
|
|
632
|
+
copyRecursive(path.join(root, ".agent"), path.join(destinationRoot, ".agent"));
|
|
633
|
+
copyRecursive(path.join(root, ".claude"), path.join(destinationRoot, ".claude"));
|
|
634
|
+
copyRecursive(path.join(root, ".codex"), path.join(destinationRoot, ".codex"));
|
|
635
|
+
}
|
|
636
|
+
export function installOrchestrationAssets(destinationRoot) {
|
|
637
|
+
writeFile(path.join(destinationRoot, ".github/workflows/agentic-orchestration.yml"), workflowYaml());
|
|
638
|
+
writeFile(path.join(destinationRoot, ".agentic-dev/runtime/runtime-lib.ts"), runtimeLibScript());
|
|
639
|
+
writeFile(path.join(destinationRoot, ".agentic-dev/runtime/sdd_to_ir.ts"), sddToIrScript());
|
|
640
|
+
writeFile(path.join(destinationRoot, ".agentic-dev/runtime/sync_project_tasks.ts"), syncProjectTasksScript());
|
|
641
|
+
writeFile(path.join(destinationRoot, ".agentic-dev/runtime/run_multi_agent_queue.ts"), runQueueScript());
|
|
642
|
+
writeFile(path.join(destinationRoot, ".agentic-dev/runtime/dispatch_agents.ts"), dispatchQueueScript());
|
|
643
|
+
writeFile(path.join(destinationRoot, ".agentic-dev/runtime/dispatch_execute.ts"), dispatchExecutorScript());
|
|
644
|
+
writeFile(path.join(destinationRoot, ".agentic-dev/runtime/close_completed_tasks.ts"), closeTasksScript());
|
|
645
|
+
writeFile(path.join(destinationRoot, ".agentic-dev/runtime/server.ts"), serverScript());
|
|
646
|
+
}
|
|
647
|
+
export function buildOrchestrationConfig(setupSelections = {}) {
|
|
648
|
+
return {
|
|
649
|
+
project_name: setupSelections.projectName || "",
|
|
650
|
+
specialized_agents: SPECIALIZED_AGENTS,
|
|
651
|
+
providers: Array.isArray(setupSelections.providerProfiles) ? setupSelections.providerProfiles : [],
|
|
652
|
+
github: {
|
|
653
|
+
repository: setupSelections.githubRepository || {},
|
|
654
|
+
project: setupSelections.githubProject || {},
|
|
655
|
+
project_mode: setupSelections.githubProjectMode || "create-if-missing",
|
|
656
|
+
},
|
|
657
|
+
workflow: {
|
|
658
|
+
ir_output: ".agentic-dev/generated/task-ir.json",
|
|
659
|
+
queue_output: ".agentic-dev/generated/agent-queue.json",
|
|
660
|
+
dispatch_output: ".agentic-dev/generated/dispatch-plan.json",
|
|
661
|
+
execution_output: ".agentic-dev/generated/execution-journal.json",
|
|
662
|
+
workflow_file: ".github/workflows/agentic-orchestration.yml",
|
|
663
|
+
server_entry: ".agentic-dev/runtime/server.ts",
|
|
664
|
+
executor_entry: ".agentic-dev/runtime/dispatch_execute.ts",
|
|
665
|
+
server_port: 4310,
|
|
666
|
+
},
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
export function writeOrchestrationConfig(destinationRoot, setupSelections = {}) {
|
|
670
|
+
const config = buildOrchestrationConfig(setupSelections);
|
|
671
|
+
writeFile(path.join(destinationRoot, ".agentic-dev/orchestration.json"), `${JSON.stringify(config, null, 2)}\n`);
|
|
672
|
+
}
|
|
673
|
+
//# sourceMappingURL=orchestration-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestration-assets.js","sourceRoot":"","sources":["../../src/lib/orchestration-assets.ts"],"names":[],"mappings":"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"}
|