bit-office 1.2.1 → 1.2.2
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/index.js +322 -178
- package/dist/index.js.map +1 -1
- package/dist/web/404.html +2 -2
- package/dist/web/_next/static/chunks/336.033a979c6c5fe642.js +1 -0
- package/dist/web/_next/static/chunks/app/office/page-358079be75bf327f.js +1 -0
- package/dist/web/_next/static/chunks/{webpack-c82364bd627eb710.js → webpack-1c3347ded5c6a52b.js} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/index.txt +1 -1
- package/dist/web/join.html +2 -2
- package/dist/web/join.txt +1 -1
- package/dist/web/office.html +3 -3
- package/dist/web/office.txt +2 -2
- package/dist/web/pair.html +2 -2
- package/dist/web/pair.txt +1 -1
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/dist/web/_next/static/chunks/336.9c9378c53a6fb44e.js +0 -1
- package/dist/web/_next/static/chunks/app/office/page-c4d6d4b7bf6b906f.js +0 -1
- /package/dist/web/_next/static/{8cfKslBAKuXQUC3ILpBvL → 0Clbb0V7-cqhwpr3pjKk1}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{8cfKslBAKuXQUC3ILpBvL → 0Clbb0V7-cqhwpr3pjKk1}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -4201,6 +4201,11 @@ var SuggestCommand = external_exports.object({
|
|
|
4201
4201
|
text: external_exports.string().max(500),
|
|
4202
4202
|
author: external_exports.string().max(30).optional()
|
|
4203
4203
|
});
|
|
4204
|
+
var RateProjectCommand = external_exports.object({
|
|
4205
|
+
type: external_exports.literal("RATE_PROJECT"),
|
|
4206
|
+
projectId: external_exports.string().optional(),
|
|
4207
|
+
ratings: external_exports.record(external_exports.string(), external_exports.number().min(1).max(5))
|
|
4208
|
+
});
|
|
4204
4209
|
var ListProjectsCommand = external_exports.object({
|
|
4205
4210
|
type: external_exports.literal("LIST_PROJECTS")
|
|
4206
4211
|
});
|
|
@@ -4226,6 +4231,7 @@ var CommandSchema = external_exports.discriminatedUnion("type", [
|
|
|
4226
4231
|
SaveAgentDefCommand,
|
|
4227
4232
|
DeleteAgentDefCommand,
|
|
4228
4233
|
SuggestCommand,
|
|
4234
|
+
RateProjectCommand,
|
|
4229
4235
|
ListProjectsCommand,
|
|
4230
4236
|
LoadProjectCommand
|
|
4231
4237
|
]);
|
|
@@ -4392,7 +4398,8 @@ var ProjectListEvent = external_exports.object({
|
|
|
4392
4398
|
agentNames: external_exports.array(external_exports.string()),
|
|
4393
4399
|
eventCount: external_exports.number(),
|
|
4394
4400
|
preview: ProjectPreviewSchema,
|
|
4395
|
-
tokenUsage: external_exports.object({ inputTokens: external_exports.number(), outputTokens: external_exports.number() }).optional()
|
|
4401
|
+
tokenUsage: external_exports.object({ inputTokens: external_exports.number(), outputTokens: external_exports.number() }).optional(),
|
|
4402
|
+
ratings: external_exports.record(external_exports.string(), external_exports.number()).optional()
|
|
4396
4403
|
}))
|
|
4397
4404
|
});
|
|
4398
4405
|
var ProjectDataEvent = external_exports.object({
|
|
@@ -4403,6 +4410,10 @@ var ProjectDataEvent = external_exports.object({
|
|
|
4403
4410
|
endedAt: external_exports.number(),
|
|
4404
4411
|
events: external_exports.array(external_exports.any())
|
|
4405
4412
|
});
|
|
4413
|
+
var PreviewReadyEvent = external_exports.object({
|
|
4414
|
+
type: external_exports.literal("PREVIEW_READY"),
|
|
4415
|
+
url: external_exports.string()
|
|
4416
|
+
});
|
|
4406
4417
|
var GatewayEventSchema = external_exports.discriminatedUnion("type", [
|
|
4407
4418
|
AgentsSyncEvent,
|
|
4408
4419
|
AgentStatusEvent,
|
|
@@ -4422,7 +4433,8 @@ var GatewayEventSchema = external_exports.discriminatedUnion("type", [
|
|
|
4422
4433
|
AgentDefsEvent,
|
|
4423
4434
|
SuggestionEvent,
|
|
4424
4435
|
ProjectListEvent,
|
|
4425
|
-
ProjectDataEvent
|
|
4436
|
+
ProjectDataEvent,
|
|
4437
|
+
PreviewReadyEvent
|
|
4426
4438
|
]);
|
|
4427
4439
|
|
|
4428
4440
|
// ../../packages/shared/src/presets.ts
|
|
@@ -5337,9 +5349,9 @@ var CONFIG = {
|
|
|
5337
5349
|
|
|
5338
5350
|
// ../../packages/orchestrator/src/agent-session.ts
|
|
5339
5351
|
import { spawn, execSync as execSync2 } from "child_process";
|
|
5340
|
-
import
|
|
5341
|
-
import { readFileSync as
|
|
5342
|
-
import { homedir as
|
|
5352
|
+
import path5 from "path";
|
|
5353
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync7 } from "fs";
|
|
5354
|
+
import { homedir as homedir5 } from "os";
|
|
5343
5355
|
|
|
5344
5356
|
// ../../packages/orchestrator/src/preview-resolver.ts
|
|
5345
5357
|
import { existsSync as existsSync5 } from "fs";
|
|
@@ -5413,19 +5425,23 @@ function parseAgentOutput(raw, fallbackText) {
|
|
|
5413
5425
|
const entryFileMatch = text.match(/ENTRY_FILE:\s*(.+)/i);
|
|
5414
5426
|
const projectDirMatch = text.match(/PROJECT_DIR:\s*(.+)/i);
|
|
5415
5427
|
const previewCmdMatch = text.match(/PREVIEW_CMD:\s*(.+)/i);
|
|
5416
|
-
const previewPortMatch = text.match(/PREVIEW_PORT:\s*(\d+)/i);
|
|
5428
|
+
const previewPortMatch = text.match(/PREVIEW_PORT:\s*[*`_]*(\d+)/i);
|
|
5429
|
+
const stripMarkdown = (v) => v.replace(/\*\*/g, "").replace(/`/g, "").replace(/^_+|_+$/g, "").trim();
|
|
5417
5430
|
const changedFiles = [];
|
|
5418
5431
|
if (filesMatch) {
|
|
5419
5432
|
const fileList = filesMatch[1].trim();
|
|
5420
5433
|
for (const f of fileList.split(/[,\n]+/)) {
|
|
5421
|
-
const cleaned = f.trim().replace(/^[-*]\s*/, "");
|
|
5434
|
+
const cleaned = stripMarkdown(f.trim().replace(/^[-*]\s*/, ""));
|
|
5422
5435
|
if (cleaned) changedFiles.push(cleaned);
|
|
5423
5436
|
}
|
|
5424
5437
|
}
|
|
5425
5438
|
const isPlaceholder = (v) => !v || /^[\[(].*not provided.*[\])]$/i.test(v) || /^[\[(].*n\/?a.*[\])]$/i.test(v) || /^none$/i.test(v);
|
|
5426
|
-
const
|
|
5427
|
-
const
|
|
5428
|
-
const
|
|
5439
|
+
const rawEntry = entryFileMatch?.[1]?.trim();
|
|
5440
|
+
const rawDir = projectDirMatch?.[1]?.trim();
|
|
5441
|
+
const rawCmd = previewCmdMatch?.[1]?.trim();
|
|
5442
|
+
const entryFile = isPlaceholder(rawEntry) ? void 0 : stripMarkdown(rawEntry);
|
|
5443
|
+
const projectDir = isPlaceholder(rawDir) ? void 0 : stripMarkdown(rawDir);
|
|
5444
|
+
const previewCmd = isPlaceholder(rawCmd) ? void 0 : stripMarkdown(rawCmd);
|
|
5429
5445
|
const previewPort = previewPortMatch ? parseInt(previewPortMatch[1], 10) : void 0;
|
|
5430
5446
|
if (summaryMatch) {
|
|
5431
5447
|
return { summary: summaryMatch[1].trim(), fullOutput, changedFiles, entryFile, projectDir, previewCmd, previewPort };
|
|
@@ -5465,10 +5481,139 @@ function extractFallbackSummary(raw, _hasFiles, _entryFile, _projectDir) {
|
|
|
5465
5481
|
|
|
5466
5482
|
// ../../packages/orchestrator/src/agent-session.ts
|
|
5467
5483
|
import { nanoid as nanoid3 } from "nanoid";
|
|
5468
|
-
|
|
5484
|
+
|
|
5485
|
+
// ../../packages/orchestrator/src/memory.ts
|
|
5486
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync6 } from "fs";
|
|
5487
|
+
import path4 from "path";
|
|
5488
|
+
import { homedir as homedir4 } from "os";
|
|
5489
|
+
var MEMORY_DIR = path4.join(homedir4(), ".bit-office", "memory");
|
|
5490
|
+
function ensureDir() {
|
|
5491
|
+
if (!existsSync6(MEMORY_DIR)) {
|
|
5492
|
+
mkdirSync4(MEMORY_DIR, { recursive: true });
|
|
5493
|
+
}
|
|
5494
|
+
}
|
|
5495
|
+
function loadStore() {
|
|
5496
|
+
const filePath = path4.join(MEMORY_DIR, "memory.json");
|
|
5497
|
+
try {
|
|
5498
|
+
if (existsSync6(filePath)) {
|
|
5499
|
+
return JSON.parse(readFileSync4(filePath, "utf-8"));
|
|
5500
|
+
}
|
|
5501
|
+
} catch {
|
|
5502
|
+
}
|
|
5503
|
+
return { reviewPatterns: [], techPreferences: [], projectHistory: [] };
|
|
5504
|
+
}
|
|
5505
|
+
function saveStore(store) {
|
|
5506
|
+
ensureDir();
|
|
5507
|
+
const filePath = path4.join(MEMORY_DIR, "memory.json");
|
|
5508
|
+
writeFileSync4(filePath, JSON.stringify(store, null, 2), "utf-8");
|
|
5509
|
+
}
|
|
5510
|
+
function recordReviewFeedback(reviewOutput) {
|
|
5511
|
+
const verdictMatch = reviewOutput.match(/VERDICT[:\s]*(\w+)/i);
|
|
5512
|
+
if (!verdictMatch || verdictMatch[1].toUpperCase() !== "FAIL") return;
|
|
5513
|
+
const issueLines = [];
|
|
5514
|
+
const issueRe = /^\s*\d+[.)]\s*(.+)/gm;
|
|
5515
|
+
let match;
|
|
5516
|
+
while ((match = issueRe.exec(reviewOutput)) !== null) {
|
|
5517
|
+
const issue = match[1].trim();
|
|
5518
|
+
if (issue.length > 10 && issue.length < 200) {
|
|
5519
|
+
issueLines.push(issue);
|
|
5520
|
+
}
|
|
5521
|
+
}
|
|
5522
|
+
if (issueLines.length === 0) return;
|
|
5523
|
+
const store = loadStore();
|
|
5524
|
+
const now = Date.now();
|
|
5525
|
+
for (const issue of issueLines) {
|
|
5526
|
+
const normalized = normalizeIssue(issue);
|
|
5527
|
+
const existing = store.reviewPatterns.find((p) => normalizeIssue(p.pattern) === normalized);
|
|
5528
|
+
if (existing) {
|
|
5529
|
+
existing.count++;
|
|
5530
|
+
existing.lastSeen = now;
|
|
5531
|
+
} else {
|
|
5532
|
+
store.reviewPatterns.push({ pattern: issue, count: 1, lastSeen: now });
|
|
5533
|
+
}
|
|
5534
|
+
}
|
|
5535
|
+
store.reviewPatterns.sort((a, b) => b.count - a.count);
|
|
5536
|
+
store.reviewPatterns = store.reviewPatterns.slice(0, 20);
|
|
5537
|
+
saveStore(store);
|
|
5538
|
+
console.log(`[Memory] Recorded ${issueLines.length} review pattern(s), total=${store.reviewPatterns.length}`);
|
|
5539
|
+
}
|
|
5540
|
+
function recordProjectCompletion(summary, tech, reviewPassed) {
|
|
5541
|
+
const store = loadStore();
|
|
5542
|
+
store.projectHistory.push({
|
|
5543
|
+
summary: summary.slice(0, 300),
|
|
5544
|
+
tech: tech.slice(0, 100),
|
|
5545
|
+
completedAt: Date.now(),
|
|
5546
|
+
reviewPassed
|
|
5547
|
+
});
|
|
5548
|
+
if (store.projectHistory.length > 50) {
|
|
5549
|
+
store.projectHistory = store.projectHistory.slice(-50);
|
|
5550
|
+
}
|
|
5551
|
+
saveStore(store);
|
|
5552
|
+
console.log(`[Memory] Recorded project completion: ${summary.slice(0, 80)}`);
|
|
5553
|
+
}
|
|
5554
|
+
function recordTechPreference(tech) {
|
|
5555
|
+
const store = loadStore();
|
|
5556
|
+
const normalized = tech.trim().toLowerCase();
|
|
5557
|
+
if (!store.techPreferences.some((t) => t.toLowerCase() === normalized)) {
|
|
5558
|
+
store.techPreferences.push(tech.trim());
|
|
5559
|
+
if (store.techPreferences.length > 10) {
|
|
5560
|
+
store.techPreferences = store.techPreferences.slice(-10);
|
|
5561
|
+
}
|
|
5562
|
+
saveStore(store);
|
|
5563
|
+
console.log(`[Memory] Recorded tech preference: ${tech}`);
|
|
5564
|
+
}
|
|
5565
|
+
}
|
|
5566
|
+
function recordProjectRatings(ratings) {
|
|
5567
|
+
const store = loadStore();
|
|
5568
|
+
if (store.projectHistory.length === 0) return;
|
|
5569
|
+
store.projectHistory[store.projectHistory.length - 1].ratings = ratings;
|
|
5570
|
+
saveStore(store);
|
|
5571
|
+
const avg = Object.values(ratings);
|
|
5572
|
+
const mean = avg.length > 0 ? (avg.reduce((a, b) => a + b, 0) / avg.length).toFixed(1) : "?";
|
|
5573
|
+
console.log(`[Memory] Updated latest project ratings (avg ${mean}/5)`);
|
|
5574
|
+
}
|
|
5575
|
+
function getMemoryContext() {
|
|
5576
|
+
const store = loadStore();
|
|
5577
|
+
const sections = [];
|
|
5578
|
+
const recurring = store.reviewPatterns.filter((p) => p.count >= 2);
|
|
5579
|
+
if (recurring.length > 0) {
|
|
5580
|
+
const lines = recurring.slice(0, 5).map((p) => `- ${p.pattern} (flagged ${p.count}x)`);
|
|
5581
|
+
sections.push(`COMMON REVIEW ISSUES (avoid these):
|
|
5582
|
+
${lines.join("\n")}`);
|
|
5583
|
+
}
|
|
5584
|
+
if (store.techPreferences.length > 0) {
|
|
5585
|
+
const recent = store.techPreferences.slice(-3);
|
|
5586
|
+
sections.push(`USER'S PREFERRED TECH: ${recent.join(", ")}`);
|
|
5587
|
+
}
|
|
5588
|
+
const rated = store.projectHistory.filter((p) => p.ratings && Object.keys(p.ratings).length > 0).slice(-3);
|
|
5589
|
+
if (rated.length > 0) {
|
|
5590
|
+
const lines = rated.map((p) => {
|
|
5591
|
+
const r = p.ratings;
|
|
5592
|
+
const scores = Object.entries(r).map(([k, v]) => `${k}:${v}/5`).join(", ");
|
|
5593
|
+
const avg = Object.values(r).reduce((a, b) => a + b, 0) / Object.values(r).length;
|
|
5594
|
+
const weak = Object.entries(r).filter(([, v]) => v <= 2).map(([k]) => k);
|
|
5595
|
+
let line = `- "${p.summary.slice(0, 60)}" [${scores}] avg=${avg.toFixed(1)}`;
|
|
5596
|
+
if (weak.length > 0) line += ` \u2192 improve: ${weak.join(", ")}`;
|
|
5597
|
+
return line;
|
|
5598
|
+
});
|
|
5599
|
+
sections.push(`PAST PROJECT RATINGS (learn from user feedback):
|
|
5600
|
+
${lines.join("\n")}`);
|
|
5601
|
+
}
|
|
5602
|
+
if (sections.length === 0) return "";
|
|
5603
|
+
return `
|
|
5604
|
+
===== LEARNED FROM PREVIOUS PROJECTS =====
|
|
5605
|
+
${sections.join("\n\n")}
|
|
5606
|
+
`;
|
|
5607
|
+
}
|
|
5608
|
+
function normalizeIssue(issue) {
|
|
5609
|
+
return issue.toLowerCase().replace(/[^a-z0-9\s]/g, "").replace(/\s+/g, " ").trim();
|
|
5610
|
+
}
|
|
5611
|
+
|
|
5612
|
+
// ../../packages/orchestrator/src/agent-session.ts
|
|
5613
|
+
var SESSION_FILE = path5.join(homedir5(), ".bit-office", "agent-sessions.json");
|
|
5469
5614
|
function loadSessionMap() {
|
|
5470
5615
|
try {
|
|
5471
|
-
if (
|
|
5616
|
+
if (existsSync7(SESSION_FILE)) return JSON.parse(readFileSync5(SESSION_FILE, "utf-8"));
|
|
5472
5617
|
} catch {
|
|
5473
5618
|
}
|
|
5474
5619
|
return {};
|
|
@@ -5477,15 +5622,15 @@ function clearSessionId(agentId) {
|
|
|
5477
5622
|
saveSessionId(agentId, null);
|
|
5478
5623
|
}
|
|
5479
5624
|
function saveSessionId(agentId, sessionId) {
|
|
5480
|
-
const dir =
|
|
5481
|
-
if (!
|
|
5625
|
+
const dir = path5.dirname(SESSION_FILE);
|
|
5626
|
+
if (!existsSync7(dir)) mkdirSync5(dir, { recursive: true });
|
|
5482
5627
|
const map = loadSessionMap();
|
|
5483
5628
|
if (sessionId) {
|
|
5484
5629
|
map[agentId] = sessionId;
|
|
5485
5630
|
} else {
|
|
5486
5631
|
delete map[agentId];
|
|
5487
5632
|
}
|
|
5488
|
-
|
|
5633
|
+
writeFileSync5(SESSION_FILE, JSON.stringify(map), "utf-8");
|
|
5489
5634
|
}
|
|
5490
5635
|
var AgentSession = class {
|
|
5491
5636
|
agentId;
|
|
@@ -5639,7 +5784,7 @@ var AgentSession = class {
|
|
|
5639
5784
|
teamRoster: teamContext ?? "",
|
|
5640
5785
|
originalTask,
|
|
5641
5786
|
prompt,
|
|
5642
|
-
memory: this._memoryContext,
|
|
5787
|
+
memory: this._memoryContext || getMemoryContext(),
|
|
5643
5788
|
soloHint: this.teamId ? "" : `- You are a SOLO developer. Do NOT delegate, assign tasks, or mention other team members. Do ALL the work yourself.
|
|
5644
5789
|
- PROJECT DIRECTORY: When creating files, first create a dedicated project directory (short kebab-case name, e.g. "snake-game"). Do ALL work inside it. Report it as PROJECT_DIR: <directory-name> in your output. If the user is just chatting (no code needed), skip this.`
|
|
5645
5790
|
};
|
|
@@ -5969,7 +6114,7 @@ var AgentSession = class {
|
|
|
5969
6114
|
detectPreview() {
|
|
5970
6115
|
const result = this.extractResult();
|
|
5971
6116
|
const baseCwd = this.currentCwd ?? this.workspace;
|
|
5972
|
-
const cwd = result.projectDir ?
|
|
6117
|
+
const cwd = result.projectDir ? path5.isAbsolute(result.projectDir) ? result.projectDir : path5.join(baseCwd, result.projectDir) : baseCwd;
|
|
5973
6118
|
return resolvePreview({
|
|
5974
6119
|
entryFile: result.entryFile,
|
|
5975
6120
|
previewCmd: result.previewCmd,
|
|
@@ -6184,7 +6329,7 @@ var AgentManager = class {
|
|
|
6184
6329
|
|
|
6185
6330
|
// ../../packages/orchestrator/src/delegation.ts
|
|
6186
6331
|
import { nanoid as nanoid4 } from "nanoid";
|
|
6187
|
-
import
|
|
6332
|
+
import path6 from "path";
|
|
6188
6333
|
var DelegationRouter = class {
|
|
6189
6334
|
/** All per-task delegation metadata, keyed by taskId */
|
|
6190
6335
|
tasks = /* @__PURE__ */ new Map();
|
|
@@ -6206,6 +6351,8 @@ var DelegationRouter = class {
|
|
|
6206
6351
|
devFixAttempts = /* @__PURE__ */ new Map();
|
|
6207
6352
|
/** Tracks which dev agent was last assigned to work (for reviewer → dev routing) */
|
|
6208
6353
|
lastDevAgentId = null;
|
|
6354
|
+
/** Last known preview fields from developer output (survives across rounds for leader context) */
|
|
6355
|
+
lastDevPreview = "";
|
|
6209
6356
|
agentManager;
|
|
6210
6357
|
promptEngine;
|
|
6211
6358
|
emitEvent;
|
|
@@ -6309,6 +6456,7 @@ var DelegationRouter = class {
|
|
|
6309
6456
|
this.teamProjectDir = null;
|
|
6310
6457
|
this.devFixAttempts.clear();
|
|
6311
6458
|
this.lastDevAgentId = null;
|
|
6459
|
+
this.lastDevPreview = "";
|
|
6312
6460
|
for (const pending of this.pendingResults.values()) {
|
|
6313
6461
|
clearTimeout(pending.timer);
|
|
6314
6462
|
}
|
|
@@ -6371,7 +6519,7 @@ var DelegationRouter = class {
|
|
|
6371
6519
|
const dirPart = dirMatch[1].replace(/\/$/, "");
|
|
6372
6520
|
const leaderSession = this.agentManager.get(fromAgentId);
|
|
6373
6521
|
if (leaderSession) {
|
|
6374
|
-
repoPath =
|
|
6522
|
+
repoPath = path6.resolve(leaderSession.workspaceDir, dirPart);
|
|
6375
6523
|
}
|
|
6376
6524
|
}
|
|
6377
6525
|
}
|
|
@@ -6487,6 +6635,17 @@ SUMMARY: (one sentence overall assessment)`
|
|
|
6487
6635
|
if (this.tryDirectFix(agentId, fromSession, fullOutput ?? summary, originAgentId)) {
|
|
6488
6636
|
return;
|
|
6489
6637
|
}
|
|
6638
|
+
const fromRole = fromSession?.role?.toLowerCase() ?? "";
|
|
6639
|
+
if (!fromRole.includes("review") && fullOutput) {
|
|
6640
|
+
const lines = [];
|
|
6641
|
+
const em = fullOutput.match(/ENTRY_FILE:\s*(.+)/i);
|
|
6642
|
+
const cm = fullOutput.match(/PREVIEW_CMD:\s*(.+)/i);
|
|
6643
|
+
const pm = fullOutput.match(/PREVIEW_PORT:\s*[*`_]*(\d+)/i);
|
|
6644
|
+
if (em) lines.push(`ENTRY_FILE: ${em[1].trim()}`);
|
|
6645
|
+
if (cm) lines.push(`PREVIEW_CMD: ${cm[1].trim()}`);
|
|
6646
|
+
if (pm) lines.push(`PREVIEW_PORT: ${pm[1]}`);
|
|
6647
|
+
if (lines.length > 0) this.lastDevPreview = lines.join("\n");
|
|
6648
|
+
}
|
|
6490
6649
|
this.enqueueResult(originAgentId, { fromName, statusWord, summary: summary.slice(0, 400) });
|
|
6491
6650
|
};
|
|
6492
6651
|
}
|
|
@@ -6650,7 +6809,8 @@ ${resultLines2}`,
|
|
|
6650
6809
|
resultStatus: pending.results.every((r) => r.statusWord.includes("success")) ? "completed successfully" : "mixed results",
|
|
6651
6810
|
resultSummary: resultLines,
|
|
6652
6811
|
originalTask: originSession.originalTask ?? "",
|
|
6653
|
-
roundInfo
|
|
6812
|
+
roundInfo,
|
|
6813
|
+
devPreview: this.lastDevPreview
|
|
6654
6814
|
});
|
|
6655
6815
|
console.log(`[ResultBatch] Flushing ${pending.results.length} result(s) to ${originAgentId} (round ${this.leaderRounds}, budget=${CONFIG.delegation.budgetRounds}, ceiling=${CONFIG.delegation.hardCeilingRounds})`);
|
|
6656
6816
|
originSession.runTask(followUpTaskId, batchPrompt, void 0, teamContext);
|
|
@@ -6658,8 +6818,8 @@ ${resultLines2}`,
|
|
|
6658
6818
|
};
|
|
6659
6819
|
|
|
6660
6820
|
// ../../packages/orchestrator/src/prompt-templates.ts
|
|
6661
|
-
import { readFileSync as
|
|
6662
|
-
import
|
|
6821
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, existsSync as existsSync8 } from "fs";
|
|
6822
|
+
import path7 from "path";
|
|
6663
6823
|
var PROMPT_DEFAULTS = {
|
|
6664
6824
|
"leader-initial": `You are {{name}}, the Team Lead. {{personality}}
|
|
6665
6825
|
You CANNOT write code, run commands, or use any tools. You can ONLY delegate.
|
|
@@ -6708,6 +6868,12 @@ Team status:
|
|
|
6708
6868
|
|
|
6709
6869
|
Delegate using: @AgentName: task description
|
|
6710
6870
|
|
|
6871
|
+
===== RULES =====
|
|
6872
|
+
- ONE task at a time. Delegate to the developer FIRST. Wait for their result before assigning Code Reviewer.
|
|
6873
|
+
- Do NOT assign Code Reviewer and Developer simultaneously \u2014 there is nothing to review until the dev is done.
|
|
6874
|
+
- Keep fixes MINIMAL. If the user reports a bug, fix THAT bug only. Do NOT add new features, tests, or process changes in the same round.
|
|
6875
|
+
- Do NOT redefine the reviewer's methodology or add new review requirements \u2014 just ask them to review the code.
|
|
6876
|
+
|
|
6711
6877
|
{{prompt}}`,
|
|
6712
6878
|
"leader-result": `You are the Team Lead. You CANNOT write or fix code. You can ONLY delegate using @Name: <task>.
|
|
6713
6879
|
|
|
@@ -6748,12 +6914,15 @@ Check WHO sent this result, then follow the matching branch:
|
|
|
6748
6914
|
\u2022 Permanent blocker (auth error, missing API key, service down) \u2192 report to the user, do not retry.
|
|
6749
6915
|
\u2022 Same error repeated twice \u2192 STOP and report to the user.
|
|
6750
6916
|
|
|
6917
|
+
===== DEVELOPER'S LAST KNOWN PREVIEW FIELDS =====
|
|
6918
|
+
{{devPreview}}
|
|
6919
|
+
|
|
6751
6920
|
===== FINAL SUMMARY FORMAT =====
|
|
6752
|
-
(Copy preview fields
|
|
6921
|
+
(Copy preview fields from DEVELOPER'S LAST KNOWN PREVIEW FIELDS above. Do NOT invent values.)
|
|
6753
6922
|
|
|
6754
|
-
ENTRY_FILE: <from
|
|
6755
|
-
PREVIEW_CMD: <from
|
|
6756
|
-
PREVIEW_PORT: <from
|
|
6923
|
+
ENTRY_FILE: <copy from above if available, otherwise OMIT>
|
|
6924
|
+
PREVIEW_CMD: <copy from above if available, otherwise OMIT. NEVER use "npm run dev" or "npm start"!>
|
|
6925
|
+
PREVIEW_PORT: <copy from above if available, otherwise OMIT>
|
|
6757
6926
|
SUMMARY: <2-3 sentence description of what was built>
|
|
6758
6927
|
|
|
6759
6928
|
RULES:
|
|
@@ -6792,6 +6961,12 @@ A) STATIC WEB \u2192 ENTRY_FILE: index.html
|
|
|
6792
6961
|
B) WEB SERVER (only if backend needed) \u2192 PREVIEW_CMD + PREVIEW_PORT
|
|
6793
6962
|
C) DESKTOP/CLI \u2192 PREVIEW_CMD only
|
|
6794
6963
|
|
|
6964
|
+
PORT RULES FOR WEB SERVERS (type B):
|
|
6965
|
+
- The system overrides your port. Your app MUST read port from the PORT environment variable.
|
|
6966
|
+
- Python: use int(os.environ.get("PORT", 5000)) \u2014 NOT a hardcoded port.
|
|
6967
|
+
- Node/JS: use process.env.PORT || 3000
|
|
6968
|
+
- Always output PREVIEW_CMD even for Vite/webpack/bundler projects (e.g. PREVIEW_CMD: npx vite).
|
|
6969
|
+
|
|
6795
6970
|
RESULT FORMAT:
|
|
6796
6971
|
STATUS: done | failed
|
|
6797
6972
|
FILES_CHANGED: (one per line)
|
|
@@ -6889,7 +7064,7 @@ ASSIGNMENTS:
|
|
|
6889
7064
|
- Do NOT delegate. Do NOT write code. Do NOT use @AgentName: syntax outside [PLAN] tags.
|
|
6890
7065
|
|
|
6891
7066
|
If the user hasn't described their project yet, greet them and ask what they'd like to build.
|
|
6892
|
-
|
|
7067
|
+
{{memory}}
|
|
6893
7068
|
Team:
|
|
6894
7069
|
{{teamRoster}}
|
|
6895
7070
|
|
|
@@ -6973,13 +7148,13 @@ var PromptEngine = class {
|
|
|
6973
7148
|
console.log(`[Prompts] No promptsDir configured, using ${Object.keys(PROMPT_DEFAULTS).length} default templates`);
|
|
6974
7149
|
return;
|
|
6975
7150
|
}
|
|
6976
|
-
if (!
|
|
6977
|
-
|
|
7151
|
+
if (!existsSync8(this.promptsDir)) {
|
|
7152
|
+
mkdirSync6(this.promptsDir, { recursive: true });
|
|
6978
7153
|
}
|
|
6979
7154
|
let written = 0;
|
|
6980
7155
|
for (const [name, content] of Object.entries(PROMPT_DEFAULTS)) {
|
|
6981
|
-
const filePath =
|
|
6982
|
-
|
|
7156
|
+
const filePath = path7.join(this.promptsDir, `${name}.md`);
|
|
7157
|
+
writeFileSync6(filePath, content, "utf-8");
|
|
6983
7158
|
written++;
|
|
6984
7159
|
}
|
|
6985
7160
|
console.log(`[Prompts] Synced ${written} default templates to ${this.promptsDir}`);
|
|
@@ -6994,10 +7169,10 @@ var PromptEngine = class {
|
|
|
6994
7169
|
let defaulted = 0;
|
|
6995
7170
|
if (this.promptsDir) {
|
|
6996
7171
|
for (const name of Object.keys(PROMPT_DEFAULTS)) {
|
|
6997
|
-
const filePath =
|
|
6998
|
-
if (
|
|
7172
|
+
const filePath = path7.join(this.promptsDir, `${name}.md`);
|
|
7173
|
+
if (existsSync8(filePath)) {
|
|
6999
7174
|
try {
|
|
7000
|
-
merged[name] =
|
|
7175
|
+
merged[name] = readFileSync6(filePath, "utf-8");
|
|
7001
7176
|
loaded++;
|
|
7002
7177
|
} catch {
|
|
7003
7178
|
defaulted++;
|
|
@@ -7258,7 +7433,7 @@ var PhaseMachine = class {
|
|
|
7258
7433
|
};
|
|
7259
7434
|
|
|
7260
7435
|
// ../../packages/orchestrator/src/result-finalizer.ts
|
|
7261
|
-
import
|
|
7436
|
+
import path8 from "path";
|
|
7262
7437
|
function finalizeTeamResult(ctx) {
|
|
7263
7438
|
const { result, teamPreview, teamChangedFiles, projectDir, workspace } = ctx;
|
|
7264
7439
|
if (teamChangedFiles.size > 0) {
|
|
@@ -7288,12 +7463,12 @@ function validateEntryFile(result, projectDir, workspace) {
|
|
|
7288
7463
|
if (!result.entryFile) return;
|
|
7289
7464
|
const resolved = resolveAgentPath(result.entryFile, projectDir, workspace);
|
|
7290
7465
|
if (resolved) {
|
|
7291
|
-
result.entryFile =
|
|
7466
|
+
result.entryFile = path8.relative(projectDir, resolved);
|
|
7292
7467
|
return;
|
|
7293
7468
|
}
|
|
7294
7469
|
const allFiles = result.changedFiles ?? [];
|
|
7295
|
-
const ext =
|
|
7296
|
-
const candidate = allFiles.map((f) =>
|
|
7470
|
+
const ext = path8.extname(result.entryFile).toLowerCase();
|
|
7471
|
+
const candidate = allFiles.map((f) => path8.basename(f)).find((f) => path8.extname(f).toLowerCase() === ext);
|
|
7297
7472
|
if (candidate) {
|
|
7298
7473
|
console.log(`[ResultFinalizer] entryFile "${result.entryFile}" not found, using "${candidate}" from changedFiles`);
|
|
7299
7474
|
result.entryFile = candidate;
|
|
@@ -7304,7 +7479,7 @@ function validateEntryFile(result, projectDir, workspace) {
|
|
|
7304
7479
|
}
|
|
7305
7480
|
function autoConstructPreviewCmd(result) {
|
|
7306
7481
|
if (!result.entryFile || result.previewCmd || /\.html?$/i.test(result.entryFile)) return;
|
|
7307
|
-
const ext =
|
|
7482
|
+
const ext = path8.extname(result.entryFile).toLowerCase();
|
|
7308
7483
|
const runner = CONFIG.preview.runners[ext];
|
|
7309
7484
|
if (runner) {
|
|
7310
7485
|
result.previewCmd = `${runner} ${result.entryFile}`;
|
|
@@ -7335,7 +7510,7 @@ function resolvePreviewUrlFromTeam(result, ctx) {
|
|
|
7335
7510
|
|
|
7336
7511
|
// ../../packages/orchestrator/src/worktree.ts
|
|
7337
7512
|
import { execSync as execSync3 } from "child_process";
|
|
7338
|
-
import
|
|
7513
|
+
import path9 from "path";
|
|
7339
7514
|
var TIMEOUT = 5e3;
|
|
7340
7515
|
function isGitRepo(cwd) {
|
|
7341
7516
|
try {
|
|
@@ -7347,9 +7522,9 @@ function isGitRepo(cwd) {
|
|
|
7347
7522
|
}
|
|
7348
7523
|
function createWorktree(workspace, agentId, taskId, agentName) {
|
|
7349
7524
|
if (!isGitRepo(workspace)) return null;
|
|
7350
|
-
const worktreeDir =
|
|
7525
|
+
const worktreeDir = path9.join(workspace, ".worktrees");
|
|
7351
7526
|
const worktreeName = `${agentId}-${taskId}`;
|
|
7352
|
-
const worktreePath =
|
|
7527
|
+
const worktreePath = path9.join(worktreeDir, worktreeName);
|
|
7353
7528
|
const branch = `agent/${agentName.toLowerCase().replace(/\s+/g, "-")}/${taskId}`;
|
|
7354
7529
|
try {
|
|
7355
7530
|
execSync3(`git worktree add "${worktreePath}" -b "${branch}"`, {
|
|
@@ -7395,7 +7570,7 @@ function mergeWorktree(workspace, worktreePath, branch) {
|
|
|
7395
7570
|
}
|
|
7396
7571
|
}
|
|
7397
7572
|
function removeWorktree(worktreePath, branch, workspace) {
|
|
7398
|
-
const cwd = workspace ??
|
|
7573
|
+
const cwd = workspace ?? path9.dirname(path9.dirname(worktreePath));
|
|
7399
7574
|
try {
|
|
7400
7575
|
execSync3(`git worktree remove --force "${worktreePath}"`, { cwd, stdio: "pipe", timeout: TIMEOUT });
|
|
7401
7576
|
} catch {
|
|
@@ -7406,110 +7581,6 @@ function removeWorktree(worktreePath, branch, workspace) {
|
|
|
7406
7581
|
}
|
|
7407
7582
|
}
|
|
7408
7583
|
|
|
7409
|
-
// ../../packages/orchestrator/src/memory.ts
|
|
7410
|
-
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, existsSync as existsSync8 } from "fs";
|
|
7411
|
-
import path9 from "path";
|
|
7412
|
-
import { homedir as homedir5 } from "os";
|
|
7413
|
-
var MEMORY_DIR = path9.join(homedir5(), ".bit-office", "memory");
|
|
7414
|
-
function ensureDir() {
|
|
7415
|
-
if (!existsSync8(MEMORY_DIR)) {
|
|
7416
|
-
mkdirSync6(MEMORY_DIR, { recursive: true });
|
|
7417
|
-
}
|
|
7418
|
-
}
|
|
7419
|
-
function loadStore() {
|
|
7420
|
-
const filePath = path9.join(MEMORY_DIR, "memory.json");
|
|
7421
|
-
try {
|
|
7422
|
-
if (existsSync8(filePath)) {
|
|
7423
|
-
return JSON.parse(readFileSync6(filePath, "utf-8"));
|
|
7424
|
-
}
|
|
7425
|
-
} catch {
|
|
7426
|
-
}
|
|
7427
|
-
return { reviewPatterns: [], techPreferences: [], projectHistory: [] };
|
|
7428
|
-
}
|
|
7429
|
-
function saveStore(store) {
|
|
7430
|
-
ensureDir();
|
|
7431
|
-
const filePath = path9.join(MEMORY_DIR, "memory.json");
|
|
7432
|
-
writeFileSync6(filePath, JSON.stringify(store, null, 2), "utf-8");
|
|
7433
|
-
}
|
|
7434
|
-
function recordReviewFeedback(reviewOutput) {
|
|
7435
|
-
const verdictMatch = reviewOutput.match(/VERDICT[:\s]*(\w+)/i);
|
|
7436
|
-
if (!verdictMatch || verdictMatch[1].toUpperCase() !== "FAIL") return;
|
|
7437
|
-
const issueLines = [];
|
|
7438
|
-
const issueRe = /^\s*\d+[.)]\s*(.+)/gm;
|
|
7439
|
-
let match;
|
|
7440
|
-
while ((match = issueRe.exec(reviewOutput)) !== null) {
|
|
7441
|
-
const issue = match[1].trim();
|
|
7442
|
-
if (issue.length > 10 && issue.length < 200) {
|
|
7443
|
-
issueLines.push(issue);
|
|
7444
|
-
}
|
|
7445
|
-
}
|
|
7446
|
-
if (issueLines.length === 0) return;
|
|
7447
|
-
const store = loadStore();
|
|
7448
|
-
const now = Date.now();
|
|
7449
|
-
for (const issue of issueLines) {
|
|
7450
|
-
const normalized = normalizeIssue(issue);
|
|
7451
|
-
const existing = store.reviewPatterns.find((p) => normalizeIssue(p.pattern) === normalized);
|
|
7452
|
-
if (existing) {
|
|
7453
|
-
existing.count++;
|
|
7454
|
-
existing.lastSeen = now;
|
|
7455
|
-
} else {
|
|
7456
|
-
store.reviewPatterns.push({ pattern: issue, count: 1, lastSeen: now });
|
|
7457
|
-
}
|
|
7458
|
-
}
|
|
7459
|
-
store.reviewPatterns.sort((a, b) => b.count - a.count);
|
|
7460
|
-
store.reviewPatterns = store.reviewPatterns.slice(0, 20);
|
|
7461
|
-
saveStore(store);
|
|
7462
|
-
console.log(`[Memory] Recorded ${issueLines.length} review pattern(s), total=${store.reviewPatterns.length}`);
|
|
7463
|
-
}
|
|
7464
|
-
function recordProjectCompletion(summary, tech, reviewPassed) {
|
|
7465
|
-
const store = loadStore();
|
|
7466
|
-
store.projectHistory.push({
|
|
7467
|
-
summary: summary.slice(0, 300),
|
|
7468
|
-
tech: tech.slice(0, 100),
|
|
7469
|
-
completedAt: Date.now(),
|
|
7470
|
-
reviewPassed
|
|
7471
|
-
});
|
|
7472
|
-
if (store.projectHistory.length > 50) {
|
|
7473
|
-
store.projectHistory = store.projectHistory.slice(-50);
|
|
7474
|
-
}
|
|
7475
|
-
saveStore(store);
|
|
7476
|
-
console.log(`[Memory] Recorded project completion: ${summary.slice(0, 80)}`);
|
|
7477
|
-
}
|
|
7478
|
-
function recordTechPreference(tech) {
|
|
7479
|
-
const store = loadStore();
|
|
7480
|
-
const normalized = tech.trim().toLowerCase();
|
|
7481
|
-
if (!store.techPreferences.some((t) => t.toLowerCase() === normalized)) {
|
|
7482
|
-
store.techPreferences.push(tech.trim());
|
|
7483
|
-
if (store.techPreferences.length > 10) {
|
|
7484
|
-
store.techPreferences = store.techPreferences.slice(-10);
|
|
7485
|
-
}
|
|
7486
|
-
saveStore(store);
|
|
7487
|
-
console.log(`[Memory] Recorded tech preference: ${tech}`);
|
|
7488
|
-
}
|
|
7489
|
-
}
|
|
7490
|
-
function getMemoryContext() {
|
|
7491
|
-
const store = loadStore();
|
|
7492
|
-
const sections = [];
|
|
7493
|
-
const recurring = store.reviewPatterns.filter((p) => p.count >= 2);
|
|
7494
|
-
if (recurring.length > 0) {
|
|
7495
|
-
const lines = recurring.slice(0, 5).map((p) => `- ${p.pattern} (flagged ${p.count}x)`);
|
|
7496
|
-
sections.push(`COMMON REVIEW ISSUES (avoid these):
|
|
7497
|
-
${lines.join("\n")}`);
|
|
7498
|
-
}
|
|
7499
|
-
if (store.techPreferences.length > 0) {
|
|
7500
|
-
const recent = store.techPreferences.slice(-3);
|
|
7501
|
-
sections.push(`USER'S PREFERRED TECH: ${recent.join(", ")}`);
|
|
7502
|
-
}
|
|
7503
|
-
if (sections.length === 0) return "";
|
|
7504
|
-
return `
|
|
7505
|
-
===== LEARNED FROM PREVIOUS PROJECTS =====
|
|
7506
|
-
${sections.join("\n\n")}
|
|
7507
|
-
`;
|
|
7508
|
-
}
|
|
7509
|
-
function normalizeIssue(issue) {
|
|
7510
|
-
return issue.toLowerCase().replace(/[^a-z0-9\s]/g, "").replace(/\s+/g, " ").trim();
|
|
7511
|
-
}
|
|
7512
|
-
|
|
7513
7584
|
// ../../packages/orchestrator/src/orchestrator.ts
|
|
7514
7585
|
var Orchestrator = class extends EventEmitter {
|
|
7515
7586
|
agentManager = new AgentManager();
|
|
@@ -7564,8 +7635,8 @@ var Orchestrator = class extends EventEmitter {
|
|
|
7564
7635
|
createAgent(opts) {
|
|
7565
7636
|
const backend = this.backends.get(opts.backend ?? this.defaultBackendId) ?? this.backends.get(this.defaultBackendId);
|
|
7566
7637
|
const roleLower = opts.role.toLowerCase();
|
|
7567
|
-
const
|
|
7568
|
-
const memoryContext =
|
|
7638
|
+
const isReviewer = roleLower.includes("review");
|
|
7639
|
+
const memoryContext = !isReviewer ? getMemoryContext() : "";
|
|
7569
7640
|
const session = new AgentSession({
|
|
7570
7641
|
agentId: opts.agentId,
|
|
7571
7642
|
name: opts.name,
|
|
@@ -8118,7 +8189,10 @@ var PreviewServer = class {
|
|
|
8118
8189
|
const port = COMMAND_PORT;
|
|
8119
8190
|
cmd = cmd.replace(/\s+(?:--port|-p)\s+\d+/gi, "");
|
|
8120
8191
|
if (agentPort) cmd = cmd.replace(new RegExp(`\\b${agentPort}\\b`, "g"), String(port));
|
|
8121
|
-
|
|
8192
|
+
const isPython = /^python\b|^python3\b/i.test(cmd.trim());
|
|
8193
|
+
if (!isPython) {
|
|
8194
|
+
cmd = `${cmd} --port ${port}`;
|
|
8195
|
+
}
|
|
8122
8196
|
console.log(`[PreviewServer] Command: "${cmd}" (forced port ${port})`);
|
|
8123
8197
|
this.killPortHolder(port);
|
|
8124
8198
|
try {
|
|
@@ -8811,6 +8885,15 @@ function archiveProject(agents, team) {
|
|
|
8811
8885
|
}
|
|
8812
8886
|
const tokenUsage = totalInputTokens > 0 || totalOutputTokens > 0 ? { inputTokens: totalInputTokens, outputTokens: totalOutputTokens } : void 0;
|
|
8813
8887
|
const id = `${projectStartedAt}-${projectName || "project"}`;
|
|
8888
|
+
const filePath = path12.join(PROJECTS_DIR, `${id}.json`);
|
|
8889
|
+
let existingRatings;
|
|
8890
|
+
try {
|
|
8891
|
+
if (existsSync11(filePath)) {
|
|
8892
|
+
const existing = JSON.parse(readFileSync7(filePath, "utf-8"));
|
|
8893
|
+
existingRatings = existing.ratings;
|
|
8894
|
+
}
|
|
8895
|
+
} catch {
|
|
8896
|
+
}
|
|
8814
8897
|
const archive = {
|
|
8815
8898
|
id,
|
|
8816
8899
|
name: projectName || "Untitled Project",
|
|
@@ -8820,10 +8903,10 @@ function archiveProject(agents, team) {
|
|
|
8820
8903
|
team,
|
|
8821
8904
|
events: projectEvents,
|
|
8822
8905
|
preview,
|
|
8823
|
-
tokenUsage
|
|
8906
|
+
tokenUsage,
|
|
8907
|
+
ratings: existingRatings
|
|
8824
8908
|
};
|
|
8825
8909
|
try {
|
|
8826
|
-
const filePath = path12.join(PROJECTS_DIR, `${id}.json`);
|
|
8827
8910
|
writeFileSync7(filePath, JSON.stringify(archive), "utf-8");
|
|
8828
8911
|
console.log(`[TeamState] Archived project "${archive.name}" (${projectEvents.length} events) \u2192 ${filePath}`);
|
|
8829
8912
|
return id;
|
|
@@ -8849,7 +8932,8 @@ function listProjects() {
|
|
|
8849
8932
|
agentNames: raw.agents.map((a) => a.name),
|
|
8850
8933
|
eventCount: raw.events.length,
|
|
8851
8934
|
preview: raw.preview,
|
|
8852
|
-
tokenUsage: raw.tokenUsage
|
|
8935
|
+
tokenUsage: raw.tokenUsage,
|
|
8936
|
+
ratings: raw.ratings
|
|
8853
8937
|
});
|
|
8854
8938
|
} catch {
|
|
8855
8939
|
}
|
|
@@ -8872,6 +8956,30 @@ function loadProject(id) {
|
|
|
8872
8956
|
}
|
|
8873
8957
|
return null;
|
|
8874
8958
|
}
|
|
8959
|
+
function rateProject(ratings, projectId) {
|
|
8960
|
+
if (!existsSync11(PROJECTS_DIR)) return false;
|
|
8961
|
+
try {
|
|
8962
|
+
let filePath;
|
|
8963
|
+
if (projectId) {
|
|
8964
|
+
const safeId = projectId.replace(/[/\\]/g, "");
|
|
8965
|
+
filePath = path12.join(PROJECTS_DIR, `${safeId}.json`);
|
|
8966
|
+
if (!path12.resolve(filePath).startsWith(path12.resolve(PROJECTS_DIR))) return false;
|
|
8967
|
+
} else {
|
|
8968
|
+
const files = readdirSync2(PROJECTS_DIR).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
8969
|
+
if (files.length === 0) return false;
|
|
8970
|
+
filePath = path12.join(PROJECTS_DIR, files[0]);
|
|
8971
|
+
}
|
|
8972
|
+
if (!existsSync11(filePath)) return false;
|
|
8973
|
+
const archive = JSON.parse(readFileSync7(filePath, "utf-8"));
|
|
8974
|
+
archive.ratings = ratings;
|
|
8975
|
+
writeFileSync7(filePath, JSON.stringify(archive), "utf-8");
|
|
8976
|
+
console.log(`[TeamState] Rated project "${archive.name}":`, ratings);
|
|
8977
|
+
return true;
|
|
8978
|
+
} catch (e) {
|
|
8979
|
+
console.log(`[TeamState] Failed to rate project: ${e}`);
|
|
8980
|
+
return false;
|
|
8981
|
+
}
|
|
8982
|
+
}
|
|
8875
8983
|
|
|
8876
8984
|
// src/index.ts
|
|
8877
8985
|
registerChannel(wsChannel);
|
|
@@ -8994,6 +9102,40 @@ function saveAgentDefs(agents) {
|
|
|
8994
9102
|
}
|
|
8995
9103
|
}
|
|
8996
9104
|
var agentDefs = [];
|
|
9105
|
+
function detectDevServer(projectDir) {
|
|
9106
|
+
try {
|
|
9107
|
+
const pkgPath = path13.join(projectDir, "package.json");
|
|
9108
|
+
if (!existsSync12(pkgPath)) return null;
|
|
9109
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
9110
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
9111
|
+
if (allDeps["vite"]) return { cmd: "npx vite", port: 5173 };
|
|
9112
|
+
if (allDeps["webpack-dev-server"]) return { cmd: "npx webpack serve", port: 8080 };
|
|
9113
|
+
if (allDeps["parcel"]) return { cmd: "npx parcel index.html", port: 1234 };
|
|
9114
|
+
if (allDeps["next"]) return { cmd: "npx next dev", port: 3e3 };
|
|
9115
|
+
if (allDeps["react-scripts"]) return { cmd: "npx react-scripts start", port: 3e3 };
|
|
9116
|
+
return null;
|
|
9117
|
+
} catch {
|
|
9118
|
+
return null;
|
|
9119
|
+
}
|
|
9120
|
+
}
|
|
9121
|
+
function buildArchiveAgents() {
|
|
9122
|
+
return orc.getAllAgents().map((a) => ({
|
|
9123
|
+
agentId: a.agentId,
|
|
9124
|
+
name: a.name,
|
|
9125
|
+
role: a.role,
|
|
9126
|
+
personality: a.personality,
|
|
9127
|
+
backend: a.backend,
|
|
9128
|
+
palette: a.palette,
|
|
9129
|
+
teamId: a.teamId,
|
|
9130
|
+
isTeamLead: orc.isTeamLead(a.agentId)
|
|
9131
|
+
}));
|
|
9132
|
+
}
|
|
9133
|
+
function buildArchiveTeam() {
|
|
9134
|
+
const phases = orc.getAllTeamPhases();
|
|
9135
|
+
if (phases.length === 0) return null;
|
|
9136
|
+
const tp = phases[0];
|
|
9137
|
+
return { teamId: tp.teamId, leadAgentId: tp.leadAgentId, phase: tp.phase, projectDir: orc.getTeamProjectDir() };
|
|
9138
|
+
}
|
|
8997
9139
|
function mapOrchestratorEvent(e) {
|
|
8998
9140
|
switch (e.type) {
|
|
8999
9141
|
case "task:started":
|
|
@@ -9026,6 +9168,9 @@ function mapOrchestratorEvent(e) {
|
|
|
9026
9168
|
bufferEvent(phaseEvt);
|
|
9027
9169
|
publishEvent(phaseEvt);
|
|
9028
9170
|
persistTeamState();
|
|
9171
|
+
if (e.phase === "complete") {
|
|
9172
|
+
archiveProject(buildArchiveAgents(), buildArchiveTeam());
|
|
9173
|
+
}
|
|
9029
9174
|
return null;
|
|
9030
9175
|
}
|
|
9031
9176
|
case "token:update":
|
|
@@ -9140,18 +9285,28 @@ ${text}]`;
|
|
|
9140
9285
|
break;
|
|
9141
9286
|
}
|
|
9142
9287
|
case "SERVE_PREVIEW": {
|
|
9143
|
-
const
|
|
9288
|
+
const cleanCmd = parsed.previewCmd?.replace(/\*\*/g, "").replace(/`/g, "").replace(/^_+|_+$/g, "").trim();
|
|
9289
|
+
const cleanPath = parsed.filePath?.replace(/\*\*/g, "").replace(/`/g, "").replace(/^_+|_+$/g, "").trim();
|
|
9290
|
+
const cmdLooksValid = cleanCmd && !/^[\[(].*[\])]$/.test(cleanCmd) && !/^none$/i.test(cleanCmd);
|
|
9144
9291
|
if (cmdLooksValid && parsed.previewPort) {
|
|
9145
9292
|
const cwd = parsed.cwd ?? config.defaultWorkspace;
|
|
9146
|
-
console.log(`[Gateway] SERVE_PREVIEW (cmd): "${
|
|
9147
|
-
previewServer.runCommand(
|
|
9293
|
+
console.log(`[Gateway] SERVE_PREVIEW (cmd): "${cleanCmd}" port=${parsed.previewPort} cwd=${cwd}`);
|
|
9294
|
+
previewServer.runCommand(cleanCmd, cwd, parsed.previewPort);
|
|
9148
9295
|
} else if (cmdLooksValid) {
|
|
9149
9296
|
const cwd = parsed.cwd ?? config.defaultWorkspace;
|
|
9150
|
-
console.log(`[Gateway] SERVE_PREVIEW (launch): "${
|
|
9151
|
-
previewServer.launchProcess(
|
|
9152
|
-
} else if (
|
|
9153
|
-
|
|
9154
|
-
|
|
9297
|
+
console.log(`[Gateway] SERVE_PREVIEW (launch): "${cleanCmd}" cwd=${cwd}`);
|
|
9298
|
+
previewServer.launchProcess(cleanCmd, cwd);
|
|
9299
|
+
} else if (cleanPath) {
|
|
9300
|
+
const projectDir = parsed.cwd ?? (cleanPath.includes("/") ? path13.dirname(cleanPath) : config.defaultWorkspace);
|
|
9301
|
+
const detected = detectDevServer(projectDir);
|
|
9302
|
+
if (detected) {
|
|
9303
|
+
console.log(`[Gateway] SERVE_PREVIEW (auto-detected ${detected.cmd}): cwd=${projectDir}`);
|
|
9304
|
+
previewServer.runCommand(detected.cmd, projectDir, detected.port);
|
|
9305
|
+
publishEvent({ type: "PREVIEW_READY", url: "http://localhost:9101" });
|
|
9306
|
+
} else {
|
|
9307
|
+
console.log(`[Gateway] SERVE_PREVIEW (static): ${cleanPath}`);
|
|
9308
|
+
previewServer.serve(cleanPath);
|
|
9309
|
+
}
|
|
9155
9310
|
}
|
|
9156
9311
|
break;
|
|
9157
9312
|
}
|
|
@@ -9276,23 +9431,7 @@ ${text}]`;
|
|
|
9276
9431
|
case "END_PROJECT": {
|
|
9277
9432
|
const agentId = parsed.agentId;
|
|
9278
9433
|
console.log(`[Gateway] END_PROJECT: agent=${agentId}`);
|
|
9279
|
-
|
|
9280
|
-
agentId: a.agentId,
|
|
9281
|
-
name: a.name,
|
|
9282
|
-
role: a.role,
|
|
9283
|
-
personality: a.personality,
|
|
9284
|
-
backend: a.backend,
|
|
9285
|
-
palette: a.palette,
|
|
9286
|
-
teamId: a.teamId,
|
|
9287
|
-
isTeamLead: orc.isTeamLead(a.agentId)
|
|
9288
|
-
}));
|
|
9289
|
-
let archiveTeam = null;
|
|
9290
|
-
const archivePhases = orc.getAllTeamPhases();
|
|
9291
|
-
if (archivePhases.length > 0) {
|
|
9292
|
-
const tp = archivePhases[0];
|
|
9293
|
-
archiveTeam = { teamId: tp.teamId, leadAgentId: tp.leadAgentId, phase: tp.phase, projectDir: orc.getTeamProjectDir() };
|
|
9294
|
-
}
|
|
9295
|
-
archiveProject(archiveAgents, archiveTeam);
|
|
9434
|
+
archiveProject(buildArchiveAgents(), buildArchiveTeam());
|
|
9296
9435
|
resetProjectBuffer();
|
|
9297
9436
|
orc.clearLeaderHistory(agentId);
|
|
9298
9437
|
if (!orc.getAgent(agentId) && parsed.name) {
|
|
@@ -9426,6 +9565,11 @@ ${text}]`;
|
|
|
9426
9565
|
});
|
|
9427
9566
|
break;
|
|
9428
9567
|
}
|
|
9568
|
+
case "RATE_PROJECT": {
|
|
9569
|
+
rateProject(parsed.ratings, parsed.projectId);
|
|
9570
|
+
recordProjectRatings(parsed.ratings);
|
|
9571
|
+
break;
|
|
9572
|
+
}
|
|
9429
9573
|
case "LIST_PROJECTS": {
|
|
9430
9574
|
const projects = listProjects();
|
|
9431
9575
|
publishEvent({ type: "PROJECT_LIST", projects });
|