@jait/gateway 0.1.64 → 0.1.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +55 -0
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/schema.d.ts +392 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +31 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -1
- package/dist/routes/network.d.ts +3 -1
- package/dist/routes/network.d.ts.map +1 -1
- package/dist/routes/network.js +268 -13
- package/dist/routes/network.js.map +1 -1
- package/dist/routes/plans.d.ts +30 -0
- package/dist/routes/plans.d.ts.map +1 -0
- package/dist/routes/plans.js +328 -0
- package/dist/routes/plans.js.map +1 -0
- package/dist/routes/repositories.d.ts +2 -0
- package/dist/routes/repositories.d.ts.map +1 -1
- package/dist/routes/repositories.js +161 -1
- package/dist/routes/repositories.js.map +1 -1
- package/dist/routes/threads.d.ts.map +1 -1
- package/dist/routes/threads.js +10 -1
- package/dist/routes/threads.js.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +14 -1
- package/dist/server.js.map +1 -1
- package/dist/services/plans.d.ts +47 -0
- package/dist/services/plans.d.ts.map +1 -0
- package/dist/services/plans.js +108 -0
- package/dist/services/plans.js.map +1 -0
- package/dist/services/repositories.d.ts +1 -0
- package/dist/services/repositories.d.ts.map +1 -1
- package/dist/services/repositories.js.map +1 -1
- package/dist/tools/network-tools.d.ts +3 -0
- package/dist/tools/network-tools.d.ts.map +1 -1
- package/dist/tools/network-tools.js +99 -1
- package/dist/tools/network-tools.js.map +1 -1
- package/dist/ws.d.ts +2 -0
- package/dist/ws.d.ts.map +1 -1
- package/dist/ws.js +3 -0
- package/dist/ws.js.map +1 -1
- package/package.json +2 -2
- package/web-dist/assets/index-CD3glXmS.css +32 -0
- package/web-dist/assets/{index-BYcgrcMm.js → index-ZIbq9Hg7.js} +2 -2
- package/web-dist/assets/index-l2kzxway.js +799 -0
- package/web-dist/assets/{web-Dh9DfBu3.js → web-xVXcdViE.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/index-DkVzT5Nb.js +0 -734
- package/web-dist/assets/index-DxsTQ8KW.css +0 -32
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automation Plan REST routes.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/repos/:repoId/plans — list plans for a repo
|
|
5
|
+
* POST /api/repos/:repoId/plans — create a plan
|
|
6
|
+
* GET /api/plans/:id — get a plan
|
|
7
|
+
* PATCH /api/plans/:id — update plan
|
|
8
|
+
* DELETE /api/plans/:id — delete a plan
|
|
9
|
+
* POST /api/plans/:id/generate — AI-generate tasks
|
|
10
|
+
* POST /api/plans/:id/tasks/:taskId/start — start a single task
|
|
11
|
+
* POST /api/plans/:id/start — start all approved tasks
|
|
12
|
+
*/
|
|
13
|
+
import type { FastifyInstance } from "fastify";
|
|
14
|
+
import type { AppConfig } from "../config.js";
|
|
15
|
+
import type { PlanService } from "../services/plans.js";
|
|
16
|
+
import type { RepositoryService } from "../services/repositories.js";
|
|
17
|
+
import type { ThreadService } from "../services/threads.js";
|
|
18
|
+
import type { ProviderRegistry } from "../providers/registry.js";
|
|
19
|
+
import type { UserService } from "../services/users.js";
|
|
20
|
+
import type { WsControlPlane } from "../ws.js";
|
|
21
|
+
export interface PlanRouteDeps {
|
|
22
|
+
planService: PlanService;
|
|
23
|
+
repoService: RepositoryService;
|
|
24
|
+
threadService?: ThreadService;
|
|
25
|
+
providerRegistry?: ProviderRegistry;
|
|
26
|
+
userService?: UserService;
|
|
27
|
+
ws?: WsControlPlane;
|
|
28
|
+
}
|
|
29
|
+
export declare function registerPlanRoutes(app: FastifyInstance, config: AppConfig, deps: PlanRouteDeps): void;
|
|
30
|
+
//# sourceMappingURL=plans.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../../src/routes/plans.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,sBAAsB,CAAC;AAElE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAM/C,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,EAAE,CAAC,EAAE,cAAc,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,aAAa,GAClB,IAAI,CAmUN"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automation Plan REST routes.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/repos/:repoId/plans — list plans for a repo
|
|
5
|
+
* POST /api/repos/:repoId/plans — create a plan
|
|
6
|
+
* GET /api/plans/:id — get a plan
|
|
7
|
+
* PATCH /api/plans/:id — update plan
|
|
8
|
+
* DELETE /api/plans/:id — delete a plan
|
|
9
|
+
* POST /api/plans/:id/generate — AI-generate tasks
|
|
10
|
+
* POST /api/plans/:id/tasks/:taskId/start — start a single task
|
|
11
|
+
* POST /api/plans/:id/start — start all approved tasks
|
|
12
|
+
*/
|
|
13
|
+
import { newTaskId } from "../services/plans.js";
|
|
14
|
+
import { requireAuth } from "../security/http-auth.js";
|
|
15
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
export function registerPlanRoutes(app, config, deps) {
|
|
18
|
+
const { planService, repoService, userService, ws } = deps;
|
|
19
|
+
function broadcastPlanEvent(event, data) {
|
|
20
|
+
if (!ws)
|
|
21
|
+
return;
|
|
22
|
+
ws.broadcastAll({
|
|
23
|
+
type: `plan.${event}`,
|
|
24
|
+
sessionId: "",
|
|
25
|
+
timestamp: new Date().toISOString(),
|
|
26
|
+
payload: data,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// ── LIST plans for a repo ────────────────────────────────────────
|
|
30
|
+
app.get("/api/repos/:repoId/plans", async (request, reply) => {
|
|
31
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
32
|
+
if (!user)
|
|
33
|
+
return;
|
|
34
|
+
const plans = planService.listByRepo(request.params.repoId);
|
|
35
|
+
return { plans };
|
|
36
|
+
});
|
|
37
|
+
// ── CREATE plan ──────────────────────────────────────────────────
|
|
38
|
+
app.post("/api/repos/:repoId/plans", async (request, reply) => {
|
|
39
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
40
|
+
if (!user)
|
|
41
|
+
return;
|
|
42
|
+
const repo = repoService.getById(request.params.repoId);
|
|
43
|
+
if (!repo) {
|
|
44
|
+
return reply.status(404).send({ error: "Repository not found" });
|
|
45
|
+
}
|
|
46
|
+
const body = request.body;
|
|
47
|
+
const plan = planService.create({
|
|
48
|
+
repoId: request.params.repoId,
|
|
49
|
+
userId: user.id,
|
|
50
|
+
title: body.title ?? "New Plan",
|
|
51
|
+
tasks: body.tasks,
|
|
52
|
+
});
|
|
53
|
+
broadcastPlanEvent("created", { plan });
|
|
54
|
+
return reply.status(201).send({ plan });
|
|
55
|
+
});
|
|
56
|
+
// ── GET plan ─────────────────────────────────────────────────────
|
|
57
|
+
app.get("/api/plans/:id", async (request, reply) => {
|
|
58
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
59
|
+
if (!user)
|
|
60
|
+
return;
|
|
61
|
+
const plan = planService.getById(request.params.id);
|
|
62
|
+
if (!plan) {
|
|
63
|
+
return reply.status(404).send({ error: "Plan not found" });
|
|
64
|
+
}
|
|
65
|
+
return { plan };
|
|
66
|
+
});
|
|
67
|
+
// ── UPDATE plan ──────────────────────────────────────────────────
|
|
68
|
+
app.patch("/api/plans/:id", async (request, reply) => {
|
|
69
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
70
|
+
if (!user)
|
|
71
|
+
return;
|
|
72
|
+
const body = request.body;
|
|
73
|
+
const plan = planService.update(request.params.id, {
|
|
74
|
+
title: body.title,
|
|
75
|
+
status: body.status === "draft" || body.status === "active" || body.status === "completed" || body.status === "archived"
|
|
76
|
+
? body.status
|
|
77
|
+
: undefined,
|
|
78
|
+
tasks: body.tasks,
|
|
79
|
+
});
|
|
80
|
+
if (!plan) {
|
|
81
|
+
return reply.status(404).send({ error: "Plan not found" });
|
|
82
|
+
}
|
|
83
|
+
broadcastPlanEvent("updated", { plan });
|
|
84
|
+
return { plan };
|
|
85
|
+
});
|
|
86
|
+
// ── DELETE plan ──────────────────────────────────────────────────
|
|
87
|
+
app.delete("/api/plans/:id", async (request, reply) => {
|
|
88
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
89
|
+
if (!user)
|
|
90
|
+
return;
|
|
91
|
+
const existing = planService.getById(request.params.id);
|
|
92
|
+
if (!existing) {
|
|
93
|
+
return reply.status(404).send({ error: "Plan not found" });
|
|
94
|
+
}
|
|
95
|
+
planService.delete(request.params.id);
|
|
96
|
+
broadcastPlanEvent("deleted", { planId: request.params.id });
|
|
97
|
+
return { ok: true };
|
|
98
|
+
});
|
|
99
|
+
// ── GENERATE tasks via LLM ───────────────────────────────────────
|
|
100
|
+
app.post("/api/plans/:id/generate", async (request, reply) => {
|
|
101
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
102
|
+
if (!user)
|
|
103
|
+
return;
|
|
104
|
+
const plan = planService.getById(request.params.id);
|
|
105
|
+
if (!plan) {
|
|
106
|
+
return reply.status(404).send({ error: "Plan not found" });
|
|
107
|
+
}
|
|
108
|
+
const repo = repoService.getById(plan.repoId);
|
|
109
|
+
if (!repo) {
|
|
110
|
+
return reply.status(404).send({ error: "Repository not found" });
|
|
111
|
+
}
|
|
112
|
+
const body = request.body;
|
|
113
|
+
const userPromptHint = (body?.prompt ?? "").trim();
|
|
114
|
+
// Gather repo context
|
|
115
|
+
let repoContext = "";
|
|
116
|
+
if (existsSync(repo.localPath)) {
|
|
117
|
+
repoContext = gatherRepoContext(repo.localPath);
|
|
118
|
+
}
|
|
119
|
+
// Include strategy if available
|
|
120
|
+
const strategySection = repo.strategy?.trim()
|
|
121
|
+
? `\n\n### Repository Strategy\n${repo.strategy.trim()}`
|
|
122
|
+
: "";
|
|
123
|
+
const systemPrompt = [
|
|
124
|
+
"You are a senior engineering manager planning work for an AI coding agent.",
|
|
125
|
+
"Given a repository's context, generate a list of concrete, actionable tasks",
|
|
126
|
+
"that can each be executed as an independent agent thread.",
|
|
127
|
+
"Each task should be small enough to complete in one session (a few files at most).",
|
|
128
|
+
"Tasks can run in parallel unless they have explicit dependencies.",
|
|
129
|
+
"",
|
|
130
|
+
"Respond with a JSON array of task objects. Each object must have:",
|
|
131
|
+
' { "title": "short title", "description": "detailed instruction for the agent" }',
|
|
132
|
+
"",
|
|
133
|
+
"Output ONLY the JSON array, no markdown fences, no explanation.",
|
|
134
|
+
].join("\n");
|
|
135
|
+
const userContent = [
|
|
136
|
+
userPromptHint ? `The user wants: ${userPromptHint}\n` : "",
|
|
137
|
+
`Repository: ${repo.name}`,
|
|
138
|
+
strategySection,
|
|
139
|
+
repoContext ? `\n\nRepository files:\n${repoContext}` : "",
|
|
140
|
+
].join("\n");
|
|
141
|
+
// Resolve API keys
|
|
142
|
+
const apiKeys = userService?.getSettings(user.id).apiKeys ?? {};
|
|
143
|
+
const apiKey = apiKeys["OPENAI_API_KEY"]?.trim() || config.openaiApiKey;
|
|
144
|
+
const baseUrl = (apiKeys["OPENAI_BASE_URL"]?.trim() || config.openaiBaseUrl).replace(/\/+$/, "");
|
|
145
|
+
const model = apiKeys["OPENAI_MODEL"]?.trim() || config.openaiModel;
|
|
146
|
+
if (!apiKey && config.llmProvider === "openai") {
|
|
147
|
+
return reply.status(400).send({ error: "No API key configured." });
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
let rawJson;
|
|
151
|
+
if (apiKey || config.llmProvider === "openai") {
|
|
152
|
+
const response = await fetch(`${baseUrl}/chat/completions`, {
|
|
153
|
+
method: "POST",
|
|
154
|
+
headers: {
|
|
155
|
+
"Content-Type": "application/json",
|
|
156
|
+
Authorization: `Bearer ${apiKey}`,
|
|
157
|
+
},
|
|
158
|
+
body: JSON.stringify({
|
|
159
|
+
model,
|
|
160
|
+
temperature: 0.4,
|
|
161
|
+
max_tokens: 3000,
|
|
162
|
+
messages: [
|
|
163
|
+
{ role: "system", content: systemPrompt },
|
|
164
|
+
{ role: "user", content: userContent },
|
|
165
|
+
],
|
|
166
|
+
}),
|
|
167
|
+
});
|
|
168
|
+
if (!response.ok)
|
|
169
|
+
throw new Error(`LLM API returned ${response.status}`);
|
|
170
|
+
const data = await response.json();
|
|
171
|
+
rawJson = data.choices?.[0]?.message?.content?.trim() ?? "[]";
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
const response = await fetch(`${config.ollamaUrl.replace(/\/+$/, "")}/api/chat`, {
|
|
175
|
+
method: "POST",
|
|
176
|
+
headers: { "Content-Type": "application/json" },
|
|
177
|
+
body: JSON.stringify({
|
|
178
|
+
model: config.ollamaModel,
|
|
179
|
+
stream: false,
|
|
180
|
+
messages: [
|
|
181
|
+
{ role: "system", content: systemPrompt },
|
|
182
|
+
{ role: "user", content: userContent },
|
|
183
|
+
],
|
|
184
|
+
}),
|
|
185
|
+
});
|
|
186
|
+
if (!response.ok)
|
|
187
|
+
throw new Error(`Ollama API returned ${response.status}`);
|
|
188
|
+
const data = await response.json();
|
|
189
|
+
rawJson = data.message?.content?.trim() ?? "[]";
|
|
190
|
+
}
|
|
191
|
+
// Strip markdown fences if the model wrapped the output
|
|
192
|
+
rawJson = rawJson.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/i, "");
|
|
193
|
+
let generated;
|
|
194
|
+
try {
|
|
195
|
+
generated = JSON.parse(rawJson);
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return reply.status(500).send({ error: "LLM returned invalid JSON", raw: rawJson });
|
|
199
|
+
}
|
|
200
|
+
if (!Array.isArray(generated)) {
|
|
201
|
+
return reply.status(500).send({ error: "LLM did not return an array" });
|
|
202
|
+
}
|
|
203
|
+
const tasks = generated
|
|
204
|
+
.filter((t) => t.title)
|
|
205
|
+
.map((t) => ({
|
|
206
|
+
id: newTaskId(),
|
|
207
|
+
title: t.title ?? "Untitled task",
|
|
208
|
+
description: t.description ?? "",
|
|
209
|
+
status: "proposed",
|
|
210
|
+
}));
|
|
211
|
+
// Merge with existing tasks (append generated ones)
|
|
212
|
+
const allTasks = [...plan.tasks, ...tasks];
|
|
213
|
+
const updated = planService.update(plan.id, { tasks: allTasks });
|
|
214
|
+
if (updated)
|
|
215
|
+
broadcastPlanEvent("updated", { plan: updated });
|
|
216
|
+
return { plan: updated, generated: tasks.length };
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
220
|
+
return reply.status(500).send({ error: `Task generation failed: ${msg}` });
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
// ── START a single task ──────────────────────────────────────────
|
|
224
|
+
app.post("/api/plans/:id/tasks/:taskId/start", async (request, reply) => {
|
|
225
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
226
|
+
if (!user)
|
|
227
|
+
return;
|
|
228
|
+
const plan = planService.getById(request.params.id);
|
|
229
|
+
if (!plan)
|
|
230
|
+
return reply.status(404).send({ error: "Plan not found" });
|
|
231
|
+
const task = plan.tasks.find((t) => t.id === request.params.taskId);
|
|
232
|
+
if (!task)
|
|
233
|
+
return reply.status(404).send({ error: "Task not found in plan" });
|
|
234
|
+
if (task.threadId) {
|
|
235
|
+
return reply.status(409).send({ error: "Task already has a thread" });
|
|
236
|
+
}
|
|
237
|
+
const repo = repoService.getById(plan.repoId);
|
|
238
|
+
if (!repo)
|
|
239
|
+
return reply.status(404).send({ error: "Repository not found" });
|
|
240
|
+
// The actual thread creation and start is handled by the frontend
|
|
241
|
+
// the task info — the frontend will create the thread using the
|
|
242
|
+
// existing agentsApi.createThread + startThread flow, then PATCH
|
|
243
|
+
// the plan task with the threadId. This keeps the plan routes simple
|
|
244
|
+
// and avoids duplicating the complex thread start logic.
|
|
245
|
+
// Mark task as approved if still proposed
|
|
246
|
+
if (task.status === "proposed") {
|
|
247
|
+
planService.updateTask(plan.id, task.id, { status: "approved" });
|
|
248
|
+
}
|
|
249
|
+
const updatedPlan = planService.getById(plan.id);
|
|
250
|
+
if (updatedPlan)
|
|
251
|
+
broadcastPlanEvent("updated", { plan: updatedPlan });
|
|
252
|
+
return {
|
|
253
|
+
task,
|
|
254
|
+
repo: {
|
|
255
|
+
id: repo.id,
|
|
256
|
+
name: repo.name,
|
|
257
|
+
localPath: repo.localPath,
|
|
258
|
+
defaultBranch: repo.defaultBranch,
|
|
259
|
+
githubUrl: repo.githubUrl,
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
});
|
|
263
|
+
// ── START all approved tasks ─────────────────────────────────────
|
|
264
|
+
app.post("/api/plans/:id/start", async (request, reply) => {
|
|
265
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
266
|
+
if (!user)
|
|
267
|
+
return;
|
|
268
|
+
const plan = planService.getById(request.params.id);
|
|
269
|
+
if (!plan)
|
|
270
|
+
return reply.status(404).send({ error: "Plan not found" });
|
|
271
|
+
const approved = plan.tasks.filter((t) => t.status === "approved" && !t.threadId);
|
|
272
|
+
if (approved.length === 0) {
|
|
273
|
+
return reply.status(400).send({ error: "No approved tasks to start" });
|
|
274
|
+
}
|
|
275
|
+
// Mark plan as active
|
|
276
|
+
planService.update(plan.id, { status: "active" });
|
|
277
|
+
const repo = repoService.getById(plan.repoId);
|
|
278
|
+
if (!repo)
|
|
279
|
+
return reply.status(404).send({ error: "Repository not found" });
|
|
280
|
+
// Return the list of tasks to start — the frontend handles
|
|
281
|
+
// thread creation for each one (parallelizing as it sees fit).
|
|
282
|
+
const updatedPlan = planService.getById(plan.id);
|
|
283
|
+
if (updatedPlan)
|
|
284
|
+
broadcastPlanEvent("updated", { plan: updatedPlan });
|
|
285
|
+
return {
|
|
286
|
+
tasks: approved,
|
|
287
|
+
repo: {
|
|
288
|
+
id: repo.id,
|
|
289
|
+
name: repo.name,
|
|
290
|
+
localPath: repo.localPath,
|
|
291
|
+
defaultBranch: repo.defaultBranch,
|
|
292
|
+
githubUrl: repo.githubUrl,
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
298
|
+
function gatherRepoContext(repoPath) {
|
|
299
|
+
const sections = [];
|
|
300
|
+
const MAX_FILE_SIZE = 8000;
|
|
301
|
+
const keyFiles = [
|
|
302
|
+
"package.json", "README.md", "AGENTS.md", "CLAUDE.md",
|
|
303
|
+
".github/copilot-instructions.md",
|
|
304
|
+
"Cargo.toml", "pyproject.toml", "go.mod",
|
|
305
|
+
"Makefile", "Dockerfile", "docker-compose.yml",
|
|
306
|
+
"tsconfig.json",
|
|
307
|
+
];
|
|
308
|
+
for (const file of keyFiles) {
|
|
309
|
+
const fullPath = join(repoPath, file);
|
|
310
|
+
try {
|
|
311
|
+
if (existsSync(fullPath) && statSync(fullPath).isFile()) {
|
|
312
|
+
const content = readFileSync(fullPath, "utf-8").slice(0, MAX_FILE_SIZE);
|
|
313
|
+
sections.push(`### ${file}\n\`\`\`\n${content}\n\`\`\``);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch { /* skip */ }
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
const entries = readdirSync(repoPath, { withFileTypes: true })
|
|
320
|
+
.slice(0, 50)
|
|
321
|
+
.map((e) => `${e.isDirectory() ? "📁" : "📄"} ${e.name}`)
|
|
322
|
+
.join("\n");
|
|
323
|
+
sections.unshift(`### Directory listing\n\`\`\`\n${entries}\n\`\`\``);
|
|
324
|
+
}
|
|
325
|
+
catch { /* skip */ }
|
|
326
|
+
return sections.join("\n\n");
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=plans.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../../src/routes/plans.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
import type { FastifyInstance } from "fastify";
|
|
10
10
|
import type { AppConfig } from "../config.js";
|
|
11
11
|
import type { RepositoryService } from "../services/repositories.js";
|
|
12
|
+
import type { UserService } from "../services/users.js";
|
|
12
13
|
import type { WsControlPlane } from "../ws.js";
|
|
13
14
|
export interface RepoRouteDeps {
|
|
14
15
|
repoService: RepositoryService;
|
|
16
|
+
userService?: UserService;
|
|
15
17
|
ws?: WsControlPlane;
|
|
16
18
|
}
|
|
17
19
|
export declare function registerRepoRoutes(app: FastifyInstance, config: AppConfig, deps: RepoRouteDeps): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repositories.d.ts","sourceRoot":"","sources":["../../src/routes/repositories.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"repositories.d.ts","sourceRoot":"","sources":["../../src/routes/repositories.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAM/C,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,EAAE,CAAC,EAAE,cAAc,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,aAAa,GAClB,IAAI,CAkPN"}
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* DELETE /api/repos/:id — delete a repository
|
|
8
8
|
*/
|
|
9
9
|
import { requireAuth } from "../security/http-auth.js";
|
|
10
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
10
12
|
export function registerRepoRoutes(app, config, deps) {
|
|
11
|
-
const { repoService, ws } = deps;
|
|
13
|
+
const { repoService, userService, ws } = deps;
|
|
12
14
|
/** Broadcast a repo event over WS to all clients */
|
|
13
15
|
function broadcastRepoEvent(event, data) {
|
|
14
16
|
if (!ws)
|
|
@@ -74,6 +76,121 @@ export function registerRepoRoutes(app, config, deps) {
|
|
|
74
76
|
broadcastRepoEvent("updated", { repo });
|
|
75
77
|
return { repo };
|
|
76
78
|
});
|
|
79
|
+
// ── STRATEGY ─────────────────────────────────────────────────────
|
|
80
|
+
/** Get strategy markdown for a repo */
|
|
81
|
+
app.get("/api/repos/:id/strategy", async (request, reply) => {
|
|
82
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
83
|
+
if (!user)
|
|
84
|
+
return;
|
|
85
|
+
const repo = repoService.getById(request.params.id);
|
|
86
|
+
if (!repo) {
|
|
87
|
+
return reply.status(404).send({ error: "Repository not found" });
|
|
88
|
+
}
|
|
89
|
+
return { strategy: repo.strategy ?? "" };
|
|
90
|
+
});
|
|
91
|
+
/** Update strategy markdown for a repo */
|
|
92
|
+
app.put("/api/repos/:id/strategy", async (request, reply) => {
|
|
93
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
94
|
+
if (!user)
|
|
95
|
+
return;
|
|
96
|
+
const body = request.body;
|
|
97
|
+
if (typeof body.strategy !== "string") {
|
|
98
|
+
return reply.status(400).send({ error: "strategy must be a string" });
|
|
99
|
+
}
|
|
100
|
+
const repo = repoService.update(request.params.id, { strategy: body.strategy });
|
|
101
|
+
if (!repo) {
|
|
102
|
+
return reply.status(404).send({ error: "Repository not found" });
|
|
103
|
+
}
|
|
104
|
+
broadcastRepoEvent("updated", { repo });
|
|
105
|
+
return { strategy: repo.strategy ?? "" };
|
|
106
|
+
});
|
|
107
|
+
/** Generate a strategy by analyzing the repo with an LLM */
|
|
108
|
+
app.post("/api/repos/:id/strategy/generate", async (request, reply) => {
|
|
109
|
+
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
110
|
+
if (!user)
|
|
111
|
+
return;
|
|
112
|
+
const repo = repoService.getById(request.params.id);
|
|
113
|
+
if (!repo) {
|
|
114
|
+
return reply.status(404).send({ error: "Repository not found" });
|
|
115
|
+
}
|
|
116
|
+
// Gather context from the repo if locally accessible
|
|
117
|
+
let repoContext = "";
|
|
118
|
+
if (existsSync(repo.localPath)) {
|
|
119
|
+
repoContext = gatherRepoContext(repo.localPath);
|
|
120
|
+
}
|
|
121
|
+
// Build LLM prompt
|
|
122
|
+
const systemPrompt = [
|
|
123
|
+
"You are a senior developer writing a strategy document for an AI coding agent.",
|
|
124
|
+
"The strategy tells the agent how to work in this repository — build commands,",
|
|
125
|
+
"test commands, coding conventions, project structure, workflow guidelines, etc.",
|
|
126
|
+
"Output ONLY markdown, no wrapping code fences. Be concise and practical.",
|
|
127
|
+
].join(" ");
|
|
128
|
+
const userPrompt = repoContext
|
|
129
|
+
? `Generate a strategy document for the repository "${repo.name}".\n\nHere is context from the repo:\n\n${repoContext}`
|
|
130
|
+
: `Generate a strategy document for a repository named "${repo.name}". Since the repo isn't accessible locally, generate a sensible default template.`;
|
|
131
|
+
// Resolve API keys
|
|
132
|
+
const apiKeys = userService?.getSettings(user.id).apiKeys ?? {};
|
|
133
|
+
const apiKey = apiKeys["OPENAI_API_KEY"]?.trim() || config.openaiApiKey;
|
|
134
|
+
const baseUrl = (apiKeys["OPENAI_BASE_URL"]?.trim() || config.openaiBaseUrl).replace(/\/+$/, "");
|
|
135
|
+
const model = apiKeys["OPENAI_MODEL"]?.trim() || config.openaiModel;
|
|
136
|
+
if (!apiKey && config.llmProvider === "openai") {
|
|
137
|
+
return reply.status(400).send({ error: "No API key configured. Set an OpenAI API key in settings." });
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
let generated;
|
|
141
|
+
if (apiKey || config.llmProvider === "openai") {
|
|
142
|
+
const response = await fetch(`${baseUrl}/chat/completions`, {
|
|
143
|
+
method: "POST",
|
|
144
|
+
headers: {
|
|
145
|
+
"Content-Type": "application/json",
|
|
146
|
+
Authorization: `Bearer ${apiKey}`,
|
|
147
|
+
},
|
|
148
|
+
body: JSON.stringify({
|
|
149
|
+
model,
|
|
150
|
+
temperature: 0.3,
|
|
151
|
+
max_tokens: 2000,
|
|
152
|
+
messages: [
|
|
153
|
+
{ role: "system", content: systemPrompt },
|
|
154
|
+
{ role: "user", content: userPrompt },
|
|
155
|
+
],
|
|
156
|
+
}),
|
|
157
|
+
});
|
|
158
|
+
if (!response.ok) {
|
|
159
|
+
throw new Error(`LLM API returned ${response.status}`);
|
|
160
|
+
}
|
|
161
|
+
const data = await response.json();
|
|
162
|
+
generated = data.choices?.[0]?.message?.content?.trim() ?? "";
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// Ollama fallback
|
|
166
|
+
const response = await fetch(`${config.ollamaUrl.replace(/\/+$/, "")}/api/chat`, {
|
|
167
|
+
method: "POST",
|
|
168
|
+
headers: { "Content-Type": "application/json" },
|
|
169
|
+
body: JSON.stringify({
|
|
170
|
+
model: config.ollamaModel,
|
|
171
|
+
stream: false,
|
|
172
|
+
messages: [
|
|
173
|
+
{ role: "system", content: systemPrompt },
|
|
174
|
+
{ role: "user", content: userPrompt },
|
|
175
|
+
],
|
|
176
|
+
}),
|
|
177
|
+
});
|
|
178
|
+
if (!response.ok) {
|
|
179
|
+
throw new Error(`Ollama API returned ${response.status}`);
|
|
180
|
+
}
|
|
181
|
+
const data = await response.json();
|
|
182
|
+
generated = data.message?.content?.trim() ?? "";
|
|
183
|
+
}
|
|
184
|
+
if (!generated) {
|
|
185
|
+
return reply.status(500).send({ error: "LLM returned empty strategy" });
|
|
186
|
+
}
|
|
187
|
+
return { strategy: generated };
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
191
|
+
return reply.status(500).send({ error: `Strategy generation failed: ${msg}` });
|
|
192
|
+
}
|
|
193
|
+
});
|
|
77
194
|
// ── DELETE ───────────────────────────────────────────────────────
|
|
78
195
|
app.delete("/api/repos/:id", async (request, reply) => {
|
|
79
196
|
const user = await requireAuth(request, reply, config.jwtSecret);
|
|
@@ -88,4 +205,47 @@ export function registerRepoRoutes(app, config, deps) {
|
|
|
88
205
|
return { ok: true };
|
|
89
206
|
});
|
|
90
207
|
}
|
|
208
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
209
|
+
/** Read key files from a repo to build context for strategy generation. */
|
|
210
|
+
function gatherRepoContext(repoPath) {
|
|
211
|
+
const sections = [];
|
|
212
|
+
const MAX_FILE_SIZE = 8000; // bytes
|
|
213
|
+
// Key files to look for
|
|
214
|
+
const keyFiles = [
|
|
215
|
+
"package.json",
|
|
216
|
+
"README.md",
|
|
217
|
+
"AGENTS.md",
|
|
218
|
+
"CLAUDE.md",
|
|
219
|
+
".github/copilot-instructions.md",
|
|
220
|
+
"Cargo.toml",
|
|
221
|
+
"pyproject.toml",
|
|
222
|
+
"go.mod",
|
|
223
|
+
"Makefile",
|
|
224
|
+
"Dockerfile",
|
|
225
|
+
"docker-compose.yml",
|
|
226
|
+
"tsconfig.json",
|
|
227
|
+
".eslintrc.json",
|
|
228
|
+
"biome.json",
|
|
229
|
+
];
|
|
230
|
+
for (const file of keyFiles) {
|
|
231
|
+
const fullPath = join(repoPath, file);
|
|
232
|
+
try {
|
|
233
|
+
if (existsSync(fullPath) && statSync(fullPath).isFile()) {
|
|
234
|
+
const content = readFileSync(fullPath, "utf-8").slice(0, MAX_FILE_SIZE);
|
|
235
|
+
sections.push(`### ${file}\n\`\`\`\n${content}\n\`\`\``);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch { /* skip unreadable files */ }
|
|
239
|
+
}
|
|
240
|
+
// Add top-level directory listing
|
|
241
|
+
try {
|
|
242
|
+
const entries = readdirSync(repoPath, { withFileTypes: true })
|
|
243
|
+
.slice(0, 50)
|
|
244
|
+
.map((e) => `${e.isDirectory() ? "📁" : "📄"} ${e.name}`)
|
|
245
|
+
.join("\n");
|
|
246
|
+
sections.unshift(`### Directory listing\n\`\`\`\n${entries}\n\`\`\``);
|
|
247
|
+
}
|
|
248
|
+
catch { /* skip */ }
|
|
249
|
+
return sections.join("\n\n");
|
|
250
|
+
}
|
|
91
251
|
//# sourceMappingURL=repositories.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repositories.js","sourceRoot":"","sources":["../../src/routes/repositories.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"repositories.js","sourceRoot":"","sources":["../../src/routes/repositories.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,MAAM,UAAU,kBAAkB,CAChC,GAAoB,EACpB,MAAiB,EACjB,IAAmB;IAEnB,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAE9C,oDAAoD;IACpD,SAAS,kBAAkB,CAAC,KAAa,EAAE,IAAa;QACtD,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,EAAE,CAAC,YAAY,CAAC;YACd,IAAI,EAAE,QAAQ,KAAK,EAAiB;YACpC,SAAS,EAAE,EAAE;YACb,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,IAA+B;SACzC,CAAC,CAAC;IACL,CAAC;IAED,oEAAoE;IAEpE,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxC,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,oEAAoE;IAEpE,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC9C,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,IAAI,GAAG,OAAO,CAAC,IAMpB,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iCAAiC,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,uCAAuC;QACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACjE,IAAI,QAAQ,EAAE,CAAC;YACb,4DAA4D;YAC5D,IAAI,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACzD,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC7E,IAAI,OAAO,EAAE,CAAC;oBACZ,kBAAkB,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;oBACjD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;gBAC3B,CAAC;YACH,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC5B,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC;YAC9B,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,kBAAkB,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,OAAO,EAAE,IAAI,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,oEAAoE;IAEpE,GAAG,CAAC,KAAK,CAA6B,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC/E,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,IAAI,GAAG,OAAO,CAAC,IAOpB,CAAC;QAEF,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,kBAAkB,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,OAAO,EAAE,IAAI,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,oEAAoE;IAEpE,uCAAuC;IACvC,GAAG,CAAC,GAAG,CAA6B,yBAAyB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACtF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,0CAA0C;IAC1C,GAAG,CAAC,GAAG,CAA6B,yBAAyB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACtF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,IAAI,GAAG,OAAO,CAAC,IAA4B,CAAC;QAClD,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChF,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,kBAAkB,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,4DAA4D;IAC5D,GAAG,CAAC,IAAI,CAA6B,kCAAkC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAChG,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,qDAAqD;QACrD,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,CAAC;QAED,mBAAmB;QACnB,MAAM,YAAY,GAAG;YACnB,gFAAgF;YAChF,+EAA+E;YAC/E,iFAAiF;YACjF,0EAA0E;SAC3E,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEZ,MAAM,UAAU,GAAG,WAAW;YAC5B,CAAC,CAAC,oDAAoD,IAAI,CAAC,IAAI,2CAA2C,WAAW,EAAE;YACvH,CAAC,CAAC,wDAAwD,IAAI,CAAC,IAAI,mFAAmF,CAAC;QAEzJ,mBAAmB;QACnB,MAAM,OAAO,GAAG,WAAW,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;QAChE,MAAM,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,YAAY,CAAC;QACxE,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACjG,MAAM,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,WAAW,CAAC;QAEpE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YAC/C,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,2DAA2D,EAAE,CAAC,CAAC;QACxG,CAAC;QAED,IAAI,CAAC;YACH,IAAI,SAAiB,CAAC;YAEtB,IAAI,MAAM,IAAI,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;gBAC9C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,mBAAmB,EAAE;oBAC1D,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,aAAa,EAAE,UAAU,MAAM,EAAE;qBAClC;oBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,KAAK;wBACL,WAAW,EAAE,GAAG;wBAChB,UAAU,EAAE,IAAI;wBAChB,QAAQ,EAAE;4BACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;4BACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;yBACtC;qBACF,CAAC;iBACH,CAAC,CAAC;gBAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;gBACzD,CAAC;gBAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAE/B,CAAC;gBACF,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAChE,CAAC;iBAAM,CAAC;gBACN,kBAAkB;gBAClB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,EAAE;oBAC/E,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;oBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,KAAK,EAAE,MAAM,CAAC,WAAW;wBACzB,MAAM,EAAE,KAAK;wBACb,QAAQ,EAAE;4BACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;4BACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;yBACtC;qBACF,CAAC;iBACH,CAAC,CAAC;gBAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC5D,CAAC;gBAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAwC,CAAC;gBACzE,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAClD,CAAC;YAED,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC,CAAC;YAC1E,CAAC;YAED,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,+BAA+B,GAAG,EAAE,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,oEAAoE;IAEpE,GAAG,CAAC,MAAM,CAA6B,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAChF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtC,kBAAkB,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,wEAAwE;AAExE,2EAA2E;AAC3E,SAAS,iBAAiB,CAAC,QAAgB;IACzC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,QAAQ;IAEpC,wBAAwB;IACxB,MAAM,QAAQ,GAAG;QACf,cAAc;QACd,WAAW;QACX,WAAW;QACX,WAAW;QACX,iCAAiC;QACjC,YAAY;QACZ,gBAAgB;QAChB,QAAQ;QACR,UAAU;QACV,YAAY;QACZ,oBAAoB;QACpB,eAAe;QACf,gBAAgB;QAChB,YAAY;KACb,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;gBACxD,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;gBACxE,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,aAAa,OAAO,UAAU,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,2BAA2B,CAAC,CAAC;IACzC,CAAC;IAED,kCAAkC;IAClC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;aAC3D,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;aACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;aACxD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,QAAQ,CAAC,OAAO,CAAC,kCAAkC,OAAO,UAAU,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IAEtB,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../src/routes/threads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAI/C,OAAO,EAA0C,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AASrE,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,aAAa,CAAC;IAC7B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,UAAU,CAAC,EAAE;QACX,gBAAgB,CACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,gBAAgB,EACxB,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,OAAO,EACvB,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,CAAC;KAC3B,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,eAAe,GACpB,IAAI,
|
|
1
|
+
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../src/routes/threads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAI/C,OAAO,EAA0C,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AASrE,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,aAAa,CAAC;IAC7B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,UAAU,CAAC,EAAE;QACX,gBAAgB,CACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,gBAAgB,EACxB,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,OAAO,EACvB,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,CAAC;KAC3B,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,eAAe,GACpB,IAAI,CA2vBN"}
|
package/dist/routes/threads.js
CHANGED
|
@@ -385,9 +385,18 @@ export function registerThreadRoutes(app, config, deps) {
|
|
|
385
385
|
}
|
|
386
386
|
// ── Send the actual coding turn ────────────────────────
|
|
387
387
|
if (message) {
|
|
388
|
+
// Look up repository strategy to prepend as agent instructions
|
|
389
|
+
let fullMessage = message;
|
|
390
|
+
if (repoService && workingDirectory) {
|
|
391
|
+
const matchingRepo = repoService.list().find((r) => workingDirectory.startsWith(r.localPath) ||
|
|
392
|
+
workingDirectory.includes(r.name));
|
|
393
|
+
if (matchingRepo?.strategy?.trim()) {
|
|
394
|
+
fullMessage = `<repository-strategy>\n${matchingRepo.strategy.trim()}\n</repository-strategy>\n\n${message}`;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
388
397
|
const userActivity = threadService.addActivity(id, "message", message.slice(0, 500), { role: "user", content: message });
|
|
389
398
|
broadcastThreadEvent(id, "activity", { activity: userActivity });
|
|
390
|
-
await provider.sendTurn(session.id,
|
|
399
|
+
await provider.sendTurn(session.id, fullMessage);
|
|
391
400
|
}
|
|
392
401
|
}
|
|
393
402
|
catch (err) {
|