bit-office 1.2.3 → 1.2.5
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 +412 -396
- package/dist/index.js.map +1 -1
- package/dist/web/404.html +2 -2
- package/dist/web/_next/static/chunks/262.71aab99cc60a53d6.js +1 -0
- package/dist/web/_next/static/chunks/29.3f310d0e1e39b284.js +1 -0
- package/dist/web/_next/static/chunks/337.37c047a79777052d.js +1 -0
- package/dist/web/_next/static/chunks/{368.17f62d3909ec67e9.js → 368.3f346c171a638292.js} +1 -1
- package/dist/web/_next/static/chunks/606.4e73b23e56d12bdb.js +1 -0
- package/dist/web/_next/static/chunks/729.826ca49d46677d86.js +1 -0
- package/dist/web/_next/static/chunks/853.3ac80a6e5f45c12f.js +1 -0
- package/dist/web/_next/static/chunks/895.ba8d7f302ee0082f.js +1 -0
- package/dist/web/_next/static/chunks/999.bd3853e8dc65d694.js +1 -0
- package/dist/web/_next/static/chunks/app/office/page-6eabeff9ea24f0b8.js +1 -0
- package/dist/web/_next/static/chunks/app/pair/{page-67f86e4adcdf34ea.js → page-ec98149563ab8ea8.js} +1 -1
- package/dist/web/_next/static/chunks/{webpack-ecac0d5245a37138.js → webpack-1cd76fe3b13e8777.js} +1 -1
- package/dist/web/_next/static/css/620fea4ddbe8c89c.css +3 -0
- package/dist/web/index.html +2 -2
- package/dist/web/index.txt +2 -2
- package/dist/web/join.html +2 -2
- package/dist/web/join.txt +2 -2
- package/dist/web/office.html +3 -3
- package/dist/web/office.txt +3 -3
- package/dist/web/pair.html +2 -2
- package/dist/web/pair.txt +3 -3
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/dist/web/_next/static/chunks/262.c930af897fc1ae41.js +0 -1
- package/dist/web/_next/static/chunks/29.5e4e3e30b02d00ad.js +0 -1
- package/dist/web/_next/static/chunks/337.d02d761d8479a26b.js +0 -1
- package/dist/web/_next/static/chunks/606.64076fb5c9a76eb8.js +0 -1
- package/dist/web/_next/static/chunks/729.f8f9847d2d765724.js +0 -1
- package/dist/web/_next/static/chunks/853.1223037341c73df9.js +0 -1
- package/dist/web/_next/static/chunks/895.b20c839956b4d7fa.js +0 -1
- package/dist/web/_next/static/chunks/999.59e64ccb62c7e043.js +0 -1
- package/dist/web/_next/static/chunks/app/office/page-7e64f4657627f13b.js +0 -1
- package/dist/web/_next/static/css/7a1e811bf3f4909f.css +0 -3
- /package/dist/web/_next/static/{30c0_3N7JM7PsUvSPrOdD → 5vHCPBj0Ikhb0tVooPDGd}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{30c0_3N7JM7PsUvSPrOdD → 5vHCPBj0Ikhb0tVooPDGd}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -4154,6 +4154,7 @@ var CreateAgentCommand = external_exports.object({
|
|
|
4154
4154
|
palette: external_exports.number().optional(),
|
|
4155
4155
|
personality: external_exports.string().optional(),
|
|
4156
4156
|
backend: external_exports.string().optional(),
|
|
4157
|
+
model: external_exports.string().optional(),
|
|
4157
4158
|
teamId: external_exports.string().optional(),
|
|
4158
4159
|
workDir: external_exports.string().optional(),
|
|
4159
4160
|
skillFiles: external_exports.array(external_exports.string()).optional()
|
|
@@ -4261,9 +4262,6 @@ var LoadProjectCommand = external_exports.object({
|
|
|
4261
4262
|
type: external_exports.literal("LOAD_PROJECT"),
|
|
4262
4263
|
projectId: external_exports.string()
|
|
4263
4264
|
});
|
|
4264
|
-
var UpdateAgencyAgentsCommand = external_exports.object({
|
|
4265
|
-
type: external_exports.literal("UPDATE_AGENCY_AGENTS")
|
|
4266
|
-
});
|
|
4267
4265
|
var GetConfigCommand = external_exports.object({
|
|
4268
4266
|
type: external_exports.literal("GET_CONFIG")
|
|
4269
4267
|
});
|
|
@@ -4304,6 +4302,14 @@ var RequestReviewCommand = external_exports.object({
|
|
|
4304
4302
|
summary: external_exports.string().optional(),
|
|
4305
4303
|
backend: external_exports.string().optional()
|
|
4306
4304
|
});
|
|
4305
|
+
var SyncChatHistoryCommand = external_exports.object({
|
|
4306
|
+
type: external_exports.literal("SYNC_CHAT_HISTORY"),
|
|
4307
|
+
/** Serialized PersistedAgent[] — same format as localStorage office-chat-history */
|
|
4308
|
+
data: external_exports.string()
|
|
4309
|
+
});
|
|
4310
|
+
var LoadChatHistoryCommand = external_exports.object({
|
|
4311
|
+
type: external_exports.literal("LOAD_CHAT_HISTORY")
|
|
4312
|
+
});
|
|
4307
4313
|
var CommandSchema = external_exports.discriminatedUnion("type", [
|
|
4308
4314
|
RunTaskCommand,
|
|
4309
4315
|
ApprovalDecisionCommand,
|
|
@@ -4327,7 +4333,6 @@ var CommandSchema = external_exports.discriminatedUnion("type", [
|
|
|
4327
4333
|
RateProjectCommand,
|
|
4328
4334
|
ListProjectsCommand,
|
|
4329
4335
|
LoadProjectCommand,
|
|
4330
|
-
UpdateAgencyAgentsCommand,
|
|
4331
4336
|
RequestReviewCommand,
|
|
4332
4337
|
MergeWorktreeCommand,
|
|
4333
4338
|
UndoMergeCommand,
|
|
@@ -4337,7 +4342,9 @@ var CommandSchema = external_exports.discriminatedUnion("type", [
|
|
|
4337
4342
|
SaveConfigCommand,
|
|
4338
4343
|
ListSkillsCommand,
|
|
4339
4344
|
SaveSkillCommand,
|
|
4340
|
-
DeleteSkillCommand
|
|
4345
|
+
DeleteSkillCommand,
|
|
4346
|
+
SyncChatHistoryCommand,
|
|
4347
|
+
LoadChatHistoryCommand
|
|
4341
4348
|
]);
|
|
4342
4349
|
|
|
4343
4350
|
// ../../packages/shared/src/events.ts
|
|
@@ -4548,12 +4555,6 @@ var ImageUploadedEvent = external_exports.object({
|
|
|
4548
4555
|
requestId: external_exports.string(),
|
|
4549
4556
|
path: external_exports.string()
|
|
4550
4557
|
});
|
|
4551
|
-
var AgencyAgentsUpdatedEvent = external_exports.object({
|
|
4552
|
-
type: external_exports.literal("AGENCY_AGENTS_UPDATED"),
|
|
4553
|
-
success: external_exports.boolean(),
|
|
4554
|
-
message: external_exports.string(),
|
|
4555
|
-
count: external_exports.number().optional()
|
|
4556
|
-
});
|
|
4557
4558
|
var WorktreeReadyEvent = external_exports.object({
|
|
4558
4559
|
type: external_exports.literal("WORKTREE_READY"),
|
|
4559
4560
|
agentId: external_exports.string(),
|
|
@@ -4607,6 +4608,11 @@ var ConfigSavedEvent = external_exports.object({
|
|
|
4607
4608
|
telegramConnected: external_exports.boolean().optional(),
|
|
4608
4609
|
tunnelRunning: external_exports.boolean().optional()
|
|
4609
4610
|
});
|
|
4611
|
+
var ChatHistoryLoadedEvent = external_exports.object({
|
|
4612
|
+
type: external_exports.literal("CHAT_HISTORY_LOADED"),
|
|
4613
|
+
/** Serialized PersistedAgent[] — same format as localStorage */
|
|
4614
|
+
data: external_exports.string()
|
|
4615
|
+
});
|
|
4610
4616
|
var GatewayEventSchema = external_exports.discriminatedUnion("type", [
|
|
4611
4617
|
AgentsSyncEvent,
|
|
4612
4618
|
AgentStatusEvent,
|
|
@@ -4631,7 +4637,6 @@ var GatewayEventSchema = external_exports.discriminatedUnion("type", [
|
|
|
4631
4637
|
PreviewReadyEvent,
|
|
4632
4638
|
FolderPickedEvent,
|
|
4633
4639
|
ImageUploadedEvent,
|
|
4634
|
-
AgencyAgentsUpdatedEvent,
|
|
4635
4640
|
BackendsAvailableEvent,
|
|
4636
4641
|
ConfigLoadedEvent,
|
|
4637
4642
|
ConfigSavedEvent,
|
|
@@ -4639,29 +4644,35 @@ var GatewayEventSchema = external_exports.discriminatedUnion("type", [
|
|
|
4639
4644
|
WorktreeMergedEvent,
|
|
4640
4645
|
WorktreeRevertedEvent,
|
|
4641
4646
|
AutoMergeUpdatedEvent,
|
|
4642
|
-
SkillListEvent
|
|
4647
|
+
SkillListEvent,
|
|
4648
|
+
ChatHistoryLoadedEvent
|
|
4643
4649
|
]);
|
|
4644
4650
|
|
|
4645
4651
|
// ../../packages/shared/src/presets.ts
|
|
4646
4652
|
var AGENT_PRESETS = [
|
|
4647
|
-
{ palette:
|
|
4648
|
-
{ palette:
|
|
4649
|
-
{ palette:
|
|
4650
|
-
{ palette:
|
|
4651
|
-
{ palette: 4, name: "Nova", role: "
|
|
4653
|
+
{ palette: 3, name: "Rex", role: "Senior Developer", description: "General-purpose dev, any language/framework", personality: "" },
|
|
4654
|
+
{ palette: 0, name: "Alex", role: "Frontend Developer", description: "UI, React/Vue/Next.js, CSS, accessibility", personality: "" },
|
|
4655
|
+
{ palette: 1, name: "Mia", role: "Backend Architect", description: "APIs, databases, system design, cloud", personality: "" },
|
|
4656
|
+
{ palette: 2, name: "Leo", role: "Rapid Prototyper", description: "MVP, proof-of-concept, fast iteration", personality: "" },
|
|
4657
|
+
{ palette: 4, name: "Nova", role: "UI Designer", description: "Design systems, spacing, color, accessibility", personality: "" },
|
|
4658
|
+
{ palette: 6, name: "Luna", role: "Product Manager", description: "PRD, prioritization, user stories, outcomes", personality: "" },
|
|
4659
|
+
{ palette: 5, name: "Marcus", role: "Team Lead", description: "Creative direction, planning, delegation", personality: "", isLeader: true },
|
|
4660
|
+
{ palette: 7, name: "Sophie", role: "Code Reviewer", description: "Code review, bugs, security, quality", personality: "", isReviewer: true }
|
|
4652
4661
|
];
|
|
4653
4662
|
var LEADER_PRESET_INDEX = AGENT_PRESETS.findIndex((p) => p.isLeader);
|
|
4654
4663
|
|
|
4655
4664
|
// ../../packages/shared/src/agent-defs.ts
|
|
4656
4665
|
var DEFAULT_AGENT_DEFS = [
|
|
4657
|
-
//
|
|
4658
|
-
{ id: "rex", name: "Rex", role: "Developer", skills: "", personality: "", palette:
|
|
4659
|
-
|
|
4660
|
-
{ id: "
|
|
4661
|
-
{ id: "
|
|
4662
|
-
{ id: "
|
|
4663
|
-
{ id: "
|
|
4664
|
-
|
|
4666
|
+
// ── Hire list (6 presets) ──
|
|
4667
|
+
{ id: "rex", name: "Rex", role: "Senior Developer", skills: "General-purpose dev, any language/framework", personality: "", palette: 3, isBuiltin: true, teamRole: "dev" },
|
|
4668
|
+
{ id: "alex", name: "Alex", role: "Frontend Developer", skills: "UI, React/Vue/Next.js, CSS, accessibility", personality: "", palette: 0, isBuiltin: true, teamRole: "dev" },
|
|
4669
|
+
{ id: "mia", name: "Mia", role: "Backend Architect", skills: "APIs, databases, system design, cloud", personality: "", palette: 1, isBuiltin: true, teamRole: "dev" },
|
|
4670
|
+
{ id: "leo", name: "Leo", role: "Rapid Prototyper", skills: "MVP, proof-of-concept, fast iteration", personality: "", palette: 2, isBuiltin: true, teamRole: "dev" },
|
|
4671
|
+
{ id: "nova", name: "Nova", role: "UI Designer", skills: "Design systems, spacing, color, accessibility", personality: "", palette: 4, isBuiltin: true, teamRole: "dev" },
|
|
4672
|
+
{ id: "luna", name: "Luna", role: "Product Manager", skills: "PRD, prioritization, user stories, outcomes", personality: "", palette: 6, isBuiltin: true, teamRole: "dev" },
|
|
4673
|
+
// ── Hidden (auto-assigned, not in hire list) ──
|
|
4674
|
+
{ id: "marcus", name: "Marcus", role: "Team Lead", skills: "Creative direction, planning, delegation", personality: "", palette: 5, isBuiltin: true, teamRole: "leader" },
|
|
4675
|
+
{ id: "sophie", name: "Sophie", role: "Code Reviewer", skills: "Code review, bugs, security, quality", personality: "", palette: 7, isBuiltin: true, teamRole: "reviewer" }
|
|
4665
4676
|
];
|
|
4666
4677
|
|
|
4667
4678
|
// src/config.ts
|
|
@@ -4786,6 +4797,7 @@ function buildConfig() {
|
|
|
4786
4797
|
telegramAllowedUsers: process.env.TELEGRAM_ALLOWED_USERS ? process.env.TELEGRAM_ALLOWED_USERS.split(",").map((s) => s.trim()).filter(Boolean) : saved.telegramAllowedUsers ?? [],
|
|
4787
4798
|
detectedBackends: saved.detectedBackends ?? [],
|
|
4788
4799
|
defaultBackend: saved.defaultBackend ?? "claude",
|
|
4800
|
+
defaultModels: saved.defaultModels ?? { claude: "opus" },
|
|
4789
4801
|
sandboxMode: saved.sandboxMode ?? "full",
|
|
4790
4802
|
worktreeEnabled: saved.worktreeEnabled ?? true,
|
|
4791
4803
|
autoMergeEnabled: saved.autoMergeEnabled ?? true,
|
|
@@ -4968,6 +4980,40 @@ function parseAgentOutput(raw, fallbackText) {
|
|
|
4968
4980
|
const summary = extractFallbackSummary(text, changedFiles.length > 0, entryFile, projectDir);
|
|
4969
4981
|
return { summary, fullOutput, changedFiles, entryFile, projectDir, previewCmd, previewPort };
|
|
4970
4982
|
}
|
|
4983
|
+
function parseReviewerFeedback(raw) {
|
|
4984
|
+
const verdictMatch = raw.match(/\*{0,2}VERDICT:?\*{0,2}\s*(PASS|FAIL)/i);
|
|
4985
|
+
const verdict = verdictMatch ? verdictMatch[1].toUpperCase() : "UNKNOWN";
|
|
4986
|
+
const summaryMatch = raw.match(/\*{0,2}SUMMARY:?\*{0,2}\s*(.+)/i);
|
|
4987
|
+
const summary = summaryMatch?.[1]?.trim() ?? "";
|
|
4988
|
+
const issues = extractNumberedList(raw, "ISSUES");
|
|
4989
|
+
const suggestions2 = extractNumberedList(raw, "SUGGESTIONS");
|
|
4990
|
+
const parts = [`VERDICT: ${verdict}`];
|
|
4991
|
+
if (issues.length > 0) {
|
|
4992
|
+
parts.push("ISSUES:");
|
|
4993
|
+
issues.forEach((issue, i) => parts.push(`${i + 1}. ${issue}`));
|
|
4994
|
+
}
|
|
4995
|
+
if (suggestions2.length > 0) {
|
|
4996
|
+
parts.push("SUGGESTIONS:");
|
|
4997
|
+
suggestions2.forEach((s, i) => parts.push(`${i + 1}. ${s}`));
|
|
4998
|
+
}
|
|
4999
|
+
if (summary) parts.push(`SUMMARY: ${summary}`);
|
|
5000
|
+
return { verdict, issues, suggestions: suggestions2, summary, formatted: parts.join("\n") };
|
|
5001
|
+
}
|
|
5002
|
+
function extractNumberedList(raw, label) {
|
|
5003
|
+
const labelRe = new RegExp(`\\*{0,2}${label}:?\\*{0,2}\\s*(.*)`, "i");
|
|
5004
|
+
const labelMatch = raw.match(labelRe);
|
|
5005
|
+
if (!labelMatch) return [];
|
|
5006
|
+
const startIdx = raw.indexOf(labelMatch[0]) + labelMatch[0].length;
|
|
5007
|
+
const remainingSections = /\n\s*\*{0,2}(?:VERDICT|ISSUES|SUGGESTIONS|SUMMARY|STATUS|FILES_CHANGED|ENTRY_FILE):?\*{0,2}/i;
|
|
5008
|
+
const endMatch = raw.slice(startIdx).match(remainingSections);
|
|
5009
|
+
const block = labelMatch[1] + (endMatch ? raw.slice(startIdx, startIdx + endMatch.index) : raw.slice(startIdx));
|
|
5010
|
+
const items = [];
|
|
5011
|
+
for (const match of block.matchAll(/(?:^|\n)\s*(?:\d+[\.\)]\s*|[-*]\s+)(.+)/g)) {
|
|
5012
|
+
const item = match[1].trim();
|
|
5013
|
+
if (item) items.push(item);
|
|
5014
|
+
}
|
|
5015
|
+
return items;
|
|
5016
|
+
}
|
|
4971
5017
|
function extractFallbackSummary(raw, _hasFiles, _entryFile, _projectDir) {
|
|
4972
5018
|
const lines = raw.split("\n").filter((l) => l.trim());
|
|
4973
5019
|
const delegationRe = /^@(\w+):/;
|
|
@@ -6351,6 +6397,7 @@ var AgentSession = class {
|
|
|
6351
6397
|
timedOut = false;
|
|
6352
6398
|
_isTeamLead;
|
|
6353
6399
|
_memoryContext;
|
|
6400
|
+
_model;
|
|
6354
6401
|
/** Whether this leader has already been through execute phase at least once */
|
|
6355
6402
|
_hasExecuted = false;
|
|
6356
6403
|
_lastResult = null;
|
|
@@ -6420,6 +6467,10 @@ var AgentSession = class {
|
|
|
6420
6467
|
get backendId() {
|
|
6421
6468
|
return this.backend.id;
|
|
6422
6469
|
}
|
|
6470
|
+
/** Model override (e.g. "opus", "sonnet") */
|
|
6471
|
+
get model() {
|
|
6472
|
+
return this._model;
|
|
6473
|
+
}
|
|
6423
6474
|
teamId;
|
|
6424
6475
|
constructor(opts) {
|
|
6425
6476
|
this.agentId = opts.agentId;
|
|
@@ -6434,6 +6485,7 @@ var AgentSession = class {
|
|
|
6434
6485
|
this._isTeamLead = opts.isTeamLead ?? false;
|
|
6435
6486
|
this.teamId = opts.teamId;
|
|
6436
6487
|
this._memoryContext = opts.memoryContext ?? "";
|
|
6488
|
+
this._model = opts.model;
|
|
6437
6489
|
this.onEvent = opts.onEvent;
|
|
6438
6490
|
this._renderPrompt = opts.renderPrompt;
|
|
6439
6491
|
}
|
|
@@ -6522,14 +6574,7 @@ var AgentSession = class {
|
|
|
6522
6574
|
originalTask,
|
|
6523
6575
|
prompt,
|
|
6524
6576
|
memory: this._memoryContext || getMemoryContext(this.agentId),
|
|
6525
|
-
recoveryContext: recoveryContextStr
|
|
6526
|
-
soloHint: this.teamId ? "" : `- You are a SOLO developer. Do NOT delegate, assign tasks, or mention other team members. Do ALL the work yourself.
|
|
6527
|
-
- WORKSPACE: Your working directory is ${cwd}. ALL files must be created inside this directory. Do NOT create files in $HOME or any other directory.
|
|
6528
|
-
- PROJECT DIRECTORY: When creating files, first create a dedicated project directory (short kebab-case name, e.g. "snake-game") inside your workspace. 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.
|
|
6529
|
-
- Before destructive operations (rm -rf, git reset, chmod), ask for approval first.
|
|
6530
|
-
- OUTPUT DISCIPLINE: Return ONLY actionable results (code changes, file paths, findings, errors). No chain-of-thought, no step-by-step narration, no reasoning process. Maximum 5 sentences for summary. If the task produced code changes, return: files changed, what changed, any issues. Nothing else.
|
|
6531
|
-
- LANGUAGE: Always write SUMMARY in English, using conventional commit style (e.g. "feat: add login page with OAuth support"). Keep it under 72 characters.
|
|
6532
|
-
- If you have a plan, wrap it in [PLAN]...[/PLAN] tags and wait for approval before executing.`
|
|
6577
|
+
recoveryContext: recoveryContextStr
|
|
6533
6578
|
};
|
|
6534
6579
|
const isFirstExecute = this._isTeamLead && phaseOverride === "execute" && !this._hasExecuted;
|
|
6535
6580
|
let agentType;
|
|
@@ -6561,16 +6606,17 @@ var AgentSession = class {
|
|
|
6561
6606
|
} else {
|
|
6562
6607
|
workerInitial = "worker-initial";
|
|
6563
6608
|
}
|
|
6564
|
-
const canResume = this.hasHistory && !!this.sessionId;
|
|
6609
|
+
const canResume = !isReviewer && this.hasHistory && !!this.sessionId;
|
|
6565
6610
|
fullPrompt = this._renderPrompt(canResume ? "worker-continue" : workerInitial, templateVars);
|
|
6566
6611
|
}
|
|
6567
6612
|
const fullAccess = this.sandboxMode === "full";
|
|
6568
6613
|
const verbose = !!process.env.DEBUG;
|
|
6569
6614
|
const args = this.backend.buildArgs(fullPrompt, {
|
|
6570
6615
|
continue: false,
|
|
6571
|
-
resumeSessionId: this.sessionId ?? void 0,
|
|
6616
|
+
resumeSessionId: this.role.toLowerCase().includes("review") ? void 0 : this.sessionId ?? void 0,
|
|
6572
6617
|
fullAccess,
|
|
6573
6618
|
noTools: this._isTeamLead,
|
|
6619
|
+
model: this._model,
|
|
6574
6620
|
verbose,
|
|
6575
6621
|
agentType,
|
|
6576
6622
|
worktree: this.useNativeWorktree,
|
|
@@ -7179,8 +7225,8 @@ var AgentSession = class {
|
|
|
7179
7225
|
summary,
|
|
7180
7226
|
riskLevel
|
|
7181
7227
|
});
|
|
7182
|
-
return new Promise((
|
|
7183
|
-
this.pendingApprovals.set(approvalId, { approvalId, resolve:
|
|
7228
|
+
return new Promise((resolve5) => {
|
|
7229
|
+
this.pendingApprovals.set(approvalId, { approvalId, resolve: resolve5 });
|
|
7184
7230
|
});
|
|
7185
7231
|
}
|
|
7186
7232
|
setStatus(status) {
|
|
@@ -7507,7 +7553,8 @@ var DelegationRouter = class {
|
|
|
7507
7553
|
});
|
|
7508
7554
|
this.prepareWorktree?.(target.agentId, taskId, repoPath);
|
|
7509
7555
|
const workerTeamContext = this.buildWorkerTeamContext(target.agentId);
|
|
7510
|
-
|
|
7556
|
+
const effectiveRepoPath = targetRole.includes("review") ? this.resolveDevWorktreePath(repoPath) : repoPath;
|
|
7557
|
+
target.runTask(taskId, fullPrompt, effectiveRepoPath, workerTeamContext);
|
|
7511
7558
|
};
|
|
7512
7559
|
}
|
|
7513
7560
|
wireResultForwarding(session) {
|
|
@@ -7557,28 +7604,11 @@ var DelegationRouter = class {
|
|
|
7557
7604
|
this.tasks.set(reReviewTaskId, { origin: originAgentId, depth: 1 });
|
|
7558
7605
|
this.assignedTask.set(meta.reviewerAgentId, reReviewTaskId);
|
|
7559
7606
|
this.totalDelegations++;
|
|
7560
|
-
const
|
|
7561
|
-
|
|
7562
|
-
Your previous review (for reference):
|
|
7607
|
+
const issueChecklist = meta.reviewContext ? `
|
|
7608
|
+
Issues to verify (from your previous review):
|
|
7563
7609
|
${meta.reviewContext}` : "";
|
|
7564
|
-
const reReviewPrompt =
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
Dev's fix report:
|
|
7568
|
-
${summary.slice(0, CONFIG.limits.chatMessageChars)}${originalContext}
|
|
7569
|
-
|
|
7570
|
-
===== YOUR TASK =====
|
|
7571
|
-
1. Check if ALL previously reported ISSUES are resolved
|
|
7572
|
-
2. Verify the deliverable runs without crashes
|
|
7573
|
-
3. Verify core features work (compare against the original task requirements)
|
|
7574
|
-
|
|
7575
|
-
VERDICT: PASS | FAIL
|
|
7576
|
-
- PASS = code runs without crashes AND core features are implemented (even if rough)
|
|
7577
|
-
- FAIL = crashes/bugs that prevent usage OR core features are missing/broken
|
|
7578
|
-
ISSUES: (numbered list if FAIL \u2014 only real bugs or missing core features)
|
|
7579
|
-
SUMMARY: (one sentence overall assessment)`
|
|
7580
|
-
});
|
|
7581
|
-
const repoPath = this.teamProjectDir ?? void 0;
|
|
7610
|
+
const reReviewPrompt = `[Re-review after fix] ${fromName} reports fixing the issues. Read the code and verify each fix is correct.${issueChecklist}`;
|
|
7611
|
+
const repoPath = this.resolveDevWorktreePath(this.teamProjectDir ?? void 0);
|
|
7582
7612
|
console.log(`[DirectFix] Dev ${fromName} fix complete \u2192 auto re-review by ${reviewerSession.name}`);
|
|
7583
7613
|
this.emitEvent({
|
|
7584
7614
|
type: "task:delegated",
|
|
@@ -7646,34 +7676,36 @@ SUMMARY: (one sentence overall assessment)`
|
|
|
7646
7676
|
this.reviewCount++;
|
|
7647
7677
|
this.devFixAttempts.set(devAgentId, attempts + 1);
|
|
7648
7678
|
this.totalDelegations++;
|
|
7679
|
+
const feedback = parseReviewerFeedback(output);
|
|
7649
7680
|
const fixTaskId = nanoid2();
|
|
7650
7681
|
this.tasks.set(fixTaskId, {
|
|
7651
7682
|
origin: originAgentId,
|
|
7652
7683
|
depth: 1,
|
|
7653
7684
|
isDirectFix: true,
|
|
7654
7685
|
reviewerAgentId,
|
|
7655
|
-
reviewContext
|
|
7686
|
+
// Carry structured feedback as reviewContext for re-review resilience
|
|
7687
|
+
reviewContext: feedback.formatted
|
|
7656
7688
|
});
|
|
7657
7689
|
this.assignedTask.set(devAgentId, fixTaskId);
|
|
7658
7690
|
const reviewerName = reviewerSession?.name ?? "Code Reviewer";
|
|
7659
7691
|
const fixPrompt = this.promptEngine.render("worker-direct-fix", {
|
|
7660
7692
|
reviewerName,
|
|
7661
|
-
reviewFeedback:
|
|
7693
|
+
reviewFeedback: feedback.formatted
|
|
7662
7694
|
});
|
|
7663
7695
|
const repoPath = this.teamProjectDir ?? void 0;
|
|
7664
|
-
console.log(`[DirectFix] ${reviewerName} FAIL \u2192 ${devSession.name} (attempt ${attempts + 1}/${CONFIG.delegation.maxDirectFixes}, skipping leader)`);
|
|
7696
|
+
console.log(`[DirectFix] ${reviewerName} FAIL \u2192 ${devSession.name} (attempt ${attempts + 1}/${CONFIG.delegation.maxDirectFixes}, ${feedback.issues.length} issues, skipping leader)`);
|
|
7665
7697
|
this.emitEvent({
|
|
7666
7698
|
type: "task:delegated",
|
|
7667
7699
|
fromAgentId: reviewerAgentId,
|
|
7668
7700
|
toAgentId: devAgentId,
|
|
7669
7701
|
taskId: fixTaskId,
|
|
7670
|
-
prompt: `Fix issues from ${reviewerName}'s review`
|
|
7702
|
+
prompt: `Fix ${feedback.issues.length} issues from ${reviewerName}'s review`
|
|
7671
7703
|
});
|
|
7672
7704
|
this.emitEvent({
|
|
7673
7705
|
type: "team:chat",
|
|
7674
7706
|
fromAgentId: reviewerAgentId,
|
|
7675
7707
|
toAgentId: devAgentId,
|
|
7676
|
-
message: `Direct fix: ${
|
|
7708
|
+
message: `Direct fix: ${feedback.formatted.slice(0, CONFIG.limits.chatMessageChars)}`,
|
|
7677
7709
|
messageType: "delegation",
|
|
7678
7710
|
taskId: fixTaskId,
|
|
7679
7711
|
timestamp: Date.now()
|
|
@@ -7708,6 +7740,21 @@ SUMMARY: (one sentence overall assessment)`
|
|
|
7708
7740
|
Your teammates (for context \u2014 do NOT delegate or coordinate with them):
|
|
7709
7741
|
${lines.join("\n")}`;
|
|
7710
7742
|
}
|
|
7743
|
+
/**
|
|
7744
|
+
* Resolve the developer's worktree path for reviewer CWD.
|
|
7745
|
+
* Reviewers don't get their own worktree, but they need to run inside the
|
|
7746
|
+
* developer's worktree to see the actual code changes (git diff, file reads).
|
|
7747
|
+
* Falls back to the provided repoPath if no dev worktree is available.
|
|
7748
|
+
*/
|
|
7749
|
+
resolveDevWorktreePath(fallback) {
|
|
7750
|
+
if (this.lastDevAgentId) {
|
|
7751
|
+
const devSession = this.agentManager.get(this.lastDevAgentId);
|
|
7752
|
+
if (devSession?.worktreePath) {
|
|
7753
|
+
return devSession.worktreePath;
|
|
7754
|
+
}
|
|
7755
|
+
}
|
|
7756
|
+
return fallback;
|
|
7757
|
+
}
|
|
7711
7758
|
/**
|
|
7712
7759
|
* Queue a result for batched forwarding to the origin agent.
|
|
7713
7760
|
* Flush only when ALL delegated tasks from this origin have returned.
|
|
@@ -7815,35 +7862,26 @@ ${resultLines2}`,
|
|
|
7815
7862
|
// ../../packages/orchestrator/src/prompt-templates.ts
|
|
7816
7863
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync7 } from "fs";
|
|
7817
7864
|
import path7 from "path";
|
|
7818
|
-
var
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
"```",
|
|
7839
|
-
"STATUS: done | failed",
|
|
7840
|
-
"FILES_CHANGED: (list all files modified)",
|
|
7841
|
-
"ENTRY_FILE: (relative path, if applicable \u2014 NEVER absolute path)",
|
|
7842
|
-
"PREVIEW_CMD: (if applicable)",
|
|
7843
|
-
"PREVIEW_PORT: (if applicable)",
|
|
7844
|
-
"SUMMARY: (one sentence: what you fixed)",
|
|
7845
|
-
"```"
|
|
7846
|
-
].join("\n");
|
|
7865
|
+
var REPORT_FORMAT = `\`\`\`
|
|
7866
|
+
STATUS: done | failed
|
|
7867
|
+
FILES_CHANGED: (one per line)
|
|
7868
|
+
ENTRY_FILE: (relative path, e.g. index.html \u2014 NEVER absolute)
|
|
7869
|
+
PREVIEW_CMD: (for server/CLI apps)
|
|
7870
|
+
PREVIEW_PORT: (for web servers)
|
|
7871
|
+
SUMMARY: (one sentence, in English)
|
|
7872
|
+
\`\`\``;
|
|
7873
|
+
var DELIVERABLE_RULES = `**System constraints:**
|
|
7874
|
+
- NEVER run long-running commands (npm run dev, npm start, npx vite, etc). They hang forever. The system serves previews automatically.
|
|
7875
|
+
- Do NOT launch GUI apps or dev servers. You CANNOT see UI.
|
|
7876
|
+
- For web servers, your app MUST read port from the PORT env variable (e.g. process.env.PORT || 3000).
|
|
7877
|
+
|
|
7878
|
+
**Report format** (ONLY when you created or modified files \u2014 for plain conversation, reply normally):
|
|
7879
|
+
|
|
7880
|
+
${REPORT_FORMAT}`;
|
|
7881
|
+
var DELIVERABLE_RULES_FIX = `Report your result (ONLY if you modified files):
|
|
7882
|
+
|
|
7883
|
+
${REPORT_FORMAT}`;
|
|
7884
|
+
var DEFAULT_SOUL = `Solve correctly, verify before declaring done, surface failures explicitly.`;
|
|
7847
7885
|
var PROMPT_DEFAULTS = {
|
|
7848
7886
|
"leader-initial": `You are {{name}}, the Team Lead. {{personality}}
|
|
7849
7887
|
You CANNOT write code, run commands, or use any tools. You can ONLY delegate.
|
|
@@ -7851,32 +7889,13 @@ You CANNOT write code, run commands, or use any tools. You can ONLY delegate.
|
|
|
7851
7889
|
Team:
|
|
7852
7890
|
{{teamRoster}}
|
|
7853
7891
|
|
|
7854
|
-
Delegate using
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
The system has already created a dedicated project directory for this team. All agents will automatically work there \u2014 do NOT specify directory paths in delegations.
|
|
7858
|
-
|
|
7859
|
-
===== DELEGATION RULES =====
|
|
7860
|
-
|
|
7861
|
-
CRITICAL \u2014 How to assign work to developers:
|
|
7862
|
-
- Give each developer ONE complete, end-to-end task that produces a RUNNABLE deliverable.
|
|
7863
|
-
- The developer is responsible for EVERYTHING: project setup, dependencies, all source files, build configuration, and verification.
|
|
7864
|
-
- NEVER split a project into module-level sub-tasks (e.g. "create AudioManager.ts", "create GameScene.ts"). That produces disconnected files with no project skeleton.
|
|
7865
|
-
- CORRECT example: "@Leo: Build a complete arcade game with PixiJS. Set up the project (package.json, entry HTML, config), implement gameplay (player movement, enemies, scoring, game states), add audio (SFX + BGM with mute toggle), and build a working deliverable. Output ENTRY_FILE when done."
|
|
7866
|
-
- WRONG example: "@Leo: Create src/audio/AudioManager.ts" then "@Leo: Create src/game/GameScene.ts" \u2014 this produces isolated modules that can't run.
|
|
7867
|
-
- If you have multiple developers, split by FEATURE AREA (each producing a runnable piece), not by FILE.
|
|
7892
|
+
Delegate using: @AgentName: task description
|
|
7893
|
+
The project directory is managed by the system \u2014 do NOT specify paths.
|
|
7868
7894
|
|
|
7869
|
-
|
|
7895
|
+
Each developer gets ONE complete, end-to-end task that produces a RUNNABLE deliverable. Split by feature area, not by file.
|
|
7870
7896
|
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
3. FIX (if needed): If Reviewer reports VERDICT=FAIL, collect ISSUES and delegate a fix to the developer. Remind dev to rebuild/re-verify. After fix, assign Reviewer again. Up to 3 review cycles.
|
|
7874
|
-
4. REPORT: When Reviewer reports VERDICT=PASS (or after 3 cycles), output FINAL SUMMARY with preview info. Copy the developer's preview fields (ENTRY_FILE, PREVIEW_CMD, PREVIEW_PORT) exactly as reported \u2014 only include fields the dev actually provided.
|
|
7875
|
-
|
|
7876
|
-
Rules:
|
|
7877
|
-
- Never write code yourself. Only delegate.
|
|
7878
|
-
- Phase 1 (this round): Assign developers ONLY. Do NOT assign Code Reviewer yet \u2014 there is no code to review.
|
|
7879
|
-
- Skip review for trivial changes (config, typo, rename).
|
|
7897
|
+
Phases: BUILD (assign devs now) \u2192 REVIEW (assign reviewer after dev delivers) \u2192 FIX if needed (up to 3 cycles) \u2192 FINAL SUMMARY with preview fields.
|
|
7898
|
+
This round: assign developers ONLY. Skip review for trivial changes.
|
|
7880
7899
|
|
|
7881
7900
|
Approved plan:
|
|
7882
7901
|
{{originalTask}}
|
|
@@ -7892,11 +7911,7 @@ Team status:
|
|
|
7892
7911
|
|
|
7893
7912
|
Delegate using: @AgentName: task description
|
|
7894
7913
|
|
|
7895
|
-
|
|
7896
|
-
- ONE task at a time. Delegate to the developer FIRST. Wait for their result before assigning Code Reviewer.
|
|
7897
|
-
- Do NOT assign Code Reviewer and Developer simultaneously \u2014 there is nothing to review until the dev is done.
|
|
7898
|
-
- 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.
|
|
7899
|
-
- Do NOT redefine the reviewer's methodology or add new review requirements \u2014 just ask them to review the code.
|
|
7914
|
+
CRITICAL: Only ONE delegation per response. Delegate to developer FIRST. Do NOT assign reviewer until dev reports back. Never delegate to dev and reviewer in the same message.
|
|
7900
7915
|
|
|
7901
7916
|
{{prompt}}`,
|
|
7902
7917
|
"leader-result": `You are the Team Lead. You CANNOT write or fix code. You can ONLY delegate using @Name: <task>.
|
|
@@ -7911,52 +7926,31 @@ Team status:
|
|
|
7911
7926
|
New result from {{fromName}} ({{resultStatus}}):
|
|
7912
7927
|
{{resultSummary}}
|
|
7913
7928
|
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
\
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
\u2192 Exception: skip review for trivial changes (config, typo, rename) \u2014 go straight to FINAL SUMMARY.
|
|
7924
|
-
If STATUS=failed:
|
|
7925
|
-
\u2192 Delegate ONE targeted fix to the same developer. Be specific about what failed.
|
|
7926
|
-
|
|
7927
|
-
\u2500\u2500 RESULT FROM CODE REVIEWER \u2500\u2500
|
|
7928
|
-
Reviewer output format: VERDICT (PASS/FAIL), ISSUES (numbered list), SUGGESTIONS (optional).
|
|
7929
|
-
If VERDICT=PASS:
|
|
7930
|
-
\u2192 Output FINAL SUMMARY. Copy ENTRY_FILE/PREVIEW fields from the developer's last report. You are DONE.
|
|
7931
|
-
If VERDICT=FAIL:
|
|
7932
|
-
\u2192 Collect ALL issues into ONE fix delegation to the original developer.
|
|
7933
|
-
\u2192 Quote each issue verbatim. Remind dev: after fixing, rebuild and verify the deliverable works.
|
|
7934
|
-
\u2192 After dev returns with the fix, assign Code Reviewer again to re-check.
|
|
7935
|
-
|
|
7936
|
-
\u2500\u2500 SPECIAL CASES \u2500\u2500
|
|
7937
|
-
\u2022 If roundInfo says "REVIEW LIMIT REACHED" or "BUDGET REACHED" \u2192 Output FINAL SUMMARY immediately. Accept the work as-is.
|
|
7938
|
-
\u2022 Permanent blocker (auth error, missing API key, service down) \u2192 report to the user, do not retry.
|
|
7939
|
-
\u2022 Same error repeated twice \u2192 STOP and report to the user.
|
|
7929
|
+
CRITICAL: Only ONE delegation per response. Never delegate to multiple agents at once.
|
|
7930
|
+
|
|
7931
|
+
Next step (pick exactly ONE):
|
|
7932
|
+
- Dev done \u2192 assign reviewer ONLY (include ENTRY_FILE + key features)
|
|
7933
|
+
- Dev failed \u2192 delegate fix to same dev ONLY
|
|
7934
|
+
- Reviewer PASS \u2192 output FINAL SUMMARY (no delegation)
|
|
7935
|
+
- Reviewer FAIL \u2192 delegate fix to dev ONLY, reviewer will be assigned AFTER dev reports back
|
|
7936
|
+
- LIMIT/BUDGET REACHED \u2192 output FINAL SUMMARY
|
|
7937
|
+
- Permanent blocker or same error twice \u2192 report to user, stop
|
|
7940
7938
|
|
|
7941
7939
|
===== DEVELOPER'S LAST KNOWN PREVIEW FIELDS =====
|
|
7942
7940
|
{{devPreview}}
|
|
7943
7941
|
|
|
7944
7942
|
===== FINAL SUMMARY FORMAT =====
|
|
7945
|
-
(Copy
|
|
7946
|
-
|
|
7947
|
-
ENTRY_FILE: <
|
|
7948
|
-
PREVIEW_CMD: <
|
|
7949
|
-
PREVIEW_PORT: <
|
|
7950
|
-
SUMMARY: <2-3
|
|
7951
|
-
|
|
7952
|
-
|
|
7953
|
-
|
|
7954
|
-
- VERDICT=FAIL means real bugs \u2014 always delegate a fix before finalizing.
|
|
7955
|
-
- In every fix delegation, remind dev to rebuild and re-test before reporting.
|
|
7956
|
-
- You MUST include ENTRY_FILE or PREVIEW_CMD in your FINAL SUMMARY \u2014 the user needs this to preview.
|
|
7957
|
-
- Do NOT include PROJECT_DIR \u2014 the system manages project directories automatically.`,
|
|
7943
|
+
(Copy from developer's preview fields above. Do NOT invent values.)
|
|
7944
|
+
|
|
7945
|
+
ENTRY_FILE: <if available>
|
|
7946
|
+
PREVIEW_CMD: <if available \u2014 NEVER "npm run dev" or "npm start">
|
|
7947
|
+
PREVIEW_PORT: <if available>
|
|
7948
|
+
SUMMARY: <2-3 sentences>
|
|
7949
|
+
|
|
7950
|
+
VERDICT=PASS with SUGGESTIONS \u2192 done. SUGGESTIONS are non-blocking.
|
|
7951
|
+
You MUST include ENTRY_FILE or PREVIEW_CMD \u2014 the user needs this to preview.`,
|
|
7958
7952
|
"worker-initial": `Your name is {{name}}, your role is {{role}}. {{personality}}
|
|
7959
|
-
{{
|
|
7953
|
+
{{soul}}
|
|
7960
7954
|
{{memory}}
|
|
7961
7955
|
{{recoveryContext}}
|
|
7962
7956
|
{{teamRoster}}
|
|
@@ -7965,47 +7959,69 @@ ${DELIVERABLE_RULES}
|
|
|
7965
7959
|
|
|
7966
7960
|
{{prompt}}`,
|
|
7967
7961
|
"worker-reviewer-initial": `Your name is {{name}}, your role is {{role}}. {{personality}}
|
|
7962
|
+
{{soul}}
|
|
7968
7963
|
{{teamRoster}}
|
|
7969
7964
|
|
|
7970
|
-
|
|
7971
|
-
|
|
7965
|
+
NEVER run servers or dev commands. You CANNOT see UI.
|
|
7966
|
+
|
|
7967
|
+
Output your review in markdown. Use this exact structure:
|
|
7968
|
+
|
|
7969
|
+
**VERDICT:** PASS or FAIL
|
|
7972
7970
|
|
|
7973
|
-
|
|
7974
|
-
1.
|
|
7975
|
-
2.
|
|
7976
|
-
3. Check feature completeness against the task requirements.
|
|
7971
|
+
**ISSUES:**
|
|
7972
|
+
1. what is wrong \u2014 where (file/function)
|
|
7973
|
+
2. ...
|
|
7977
7974
|
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7975
|
+
**SUGGESTIONS:**
|
|
7976
|
+
1. optional improvement idea
|
|
7977
|
+
2. ...
|
|
7978
|
+
|
|
7979
|
+
**SUMMARY:** one sentence overall assessment
|
|
7980
|
+
|
|
7981
|
+
Rules:
|
|
7982
|
+
- PASS = runs without crashes AND core features work. FAIL = crashes/bugs or core features missing.
|
|
7983
|
+
- Max 5 issues, max 3 suggestions. Omit sections if empty.
|
|
7984
|
+
- ALWAYS use numbered list (1. 2. 3.) for issues and suggestions, even if there is only one item.
|
|
7985
|
+
- No source code. No fix instructions. Just state what is wrong and where.
|
|
7986
|
+
- Keep total output under 30 lines.
|
|
7985
7987
|
|
|
7986
7988
|
{{prompt}}`,
|
|
7987
7989
|
"worker-subagent-reviewer-initial": `Your name is {{name}}. {{personality}}
|
|
7990
|
+
{{soul}}
|
|
7988
7991
|
{{memory}}
|
|
7989
7992
|
{{teamRoster}}
|
|
7990
7993
|
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
ISSUES
|
|
7996
|
-
|
|
7997
|
-
|
|
7994
|
+
Output your review in markdown. Use this exact structure:
|
|
7995
|
+
|
|
7996
|
+
**VERDICT:** PASS or FAIL
|
|
7997
|
+
|
|
7998
|
+
**ISSUES:**
|
|
7999
|
+
1. what is wrong \u2014 where (file/function)
|
|
8000
|
+
2. ...
|
|
8001
|
+
|
|
8002
|
+
**SUGGESTIONS:**
|
|
8003
|
+
1. optional improvement idea
|
|
8004
|
+
2. ...
|
|
8005
|
+
|
|
8006
|
+
**SUMMARY:** one sentence overall assessment
|
|
8007
|
+
|
|
8008
|
+
Rules:
|
|
8009
|
+
- PASS = runs without crashes AND core features work. FAIL = crashes/bugs or core features missing.
|
|
8010
|
+
- Max 5 issues, max 3 suggestions. Omit sections if empty.
|
|
8011
|
+
- ALWAYS use numbered list (1. 2. 3.) for issues and suggestions, even if there is only one item.
|
|
8012
|
+
- No source code. No fix instructions. Just state what is wrong and where.
|
|
8013
|
+
- Keep total output under 30 lines.
|
|
7998
8014
|
|
|
7999
8015
|
{{prompt}}`,
|
|
8000
8016
|
"worker-subagent-initial": `Your name is {{name}}. {{personality}}
|
|
8001
|
-
{{
|
|
8017
|
+
{{soul}}
|
|
8002
8018
|
{{memory}}
|
|
8003
8019
|
{{teamRoster}}
|
|
8004
8020
|
{{recoveryContext}}
|
|
8005
8021
|
|
|
8006
8022
|
{{prompt}}`,
|
|
8007
8023
|
"worker-subagent-dev-initial": `Your name is {{name}}. {{personality}}
|
|
8008
|
-
{{
|
|
8024
|
+
{{soul}}
|
|
8009
8025
|
{{memory}}
|
|
8010
8026
|
{{teamRoster}}
|
|
8011
8027
|
{{recoveryContext}}
|
|
@@ -8014,7 +8030,7 @@ ${DELIVERABLE_RULES}
|
|
|
8014
8030
|
|
|
8015
8031
|
{{prompt}}`,
|
|
8016
8032
|
"worker-continue": `[Context reminder] You are {{name}} ({{role}}). {{personality}}
|
|
8017
|
-
{{
|
|
8033
|
+
{{soul}}
|
|
8018
8034
|
{{memory}}
|
|
8019
8035
|
{{recoveryContext}}
|
|
8020
8036
|
{{teamRoster}}
|
|
@@ -8035,99 +8051,68 @@ Do NOT introduce new features. Only fix the reported issues.`,
|
|
|
8035
8051
|
"delegation-prefix": `[Assigned by {{fromName}} ({{fromRole}})]
|
|
8036
8052
|
{{prompt}}`,
|
|
8037
8053
|
"delegation-hint": `To delegate a task to another agent, output on its own line: @AgentName: <task description>`,
|
|
8038
|
-
"leader-create": `You are {{name}}, the team's Creative Director
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
2. PRODUCT CONSULTANT \u2014 turn that vision into a clear, buildable plan
|
|
8054
|
+
"leader-create": `You are {{name}}, the team's Creative Director. {{personality}}
|
|
8055
|
+
|
|
8056
|
+
Your job: challenge the user's framing, find the real problem behind the request, then design a bold product vision. Don't just take orders \u2014 push back, reframe, and propose something better than what was asked for.
|
|
8042
8057
|
|
|
8043
8058
|
Rules:
|
|
8044
|
-
-
|
|
8045
|
-
- Ask at most 1-2
|
|
8046
|
-
- If the user gives a clear idea (even brief), that is ENOUGH \u2014 use your CREATIVITY to fill in the vision (theme, style, characters, mood, unique twist) and produce the plan immediately. Be bold and inventive: propose a surprising concept, an unexpected angle, or a distinctive theme that the user wouldn't think of on their own.
|
|
8059
|
+
- If the idea is clear enough, produce the plan immediately. Be bold \u2014 propose a surprising concept or unexpected angle.
|
|
8060
|
+
- Ask at most 1-2 questions, then produce a plan. Do NOT over-question.
|
|
8047
8061
|
- The goal is a WORKING PROTOTYPE, not a production system.
|
|
8048
|
-
-
|
|
8049
|
-
|
|
8050
|
-
===== PLAN FORMAT (strict \u2014 follow this structure) =====
|
|
8062
|
+
- Describe WHAT the product does and WHO it's for \u2014 NOT how to code it.
|
|
8063
|
+
- When ready, output the plan in [PLAN]...[/PLAN] tags.
|
|
8051
8064
|
|
|
8052
8065
|
[PLAN]
|
|
8053
|
-
CONCEPT: Short Name \u2014 one sentence
|
|
8066
|
+
CONCEPT: Short Name \u2014 one sentence (what it is + who it's for)
|
|
8054
8067
|
|
|
8055
8068
|
CREATIVE VISION:
|
|
8056
|
-
- Theme & setting
|
|
8057
|
-
- Visual style
|
|
8058
|
-
- Core experience \u2014 what
|
|
8069
|
+
- Theme & setting
|
|
8070
|
+
- Visual style
|
|
8071
|
+
- Core experience \u2014 what the user SEES and FEELS
|
|
8059
8072
|
|
|
8060
8073
|
FEATURES:
|
|
8061
|
-
- (3-5 bullet points
|
|
8062
|
-
- (focus on interactions, content, and behavior \u2014 NOT technical implementation)
|
|
8074
|
+
- (3-5 bullet points, user perspective, not technical)
|
|
8063
8075
|
|
|
8064
|
-
TECH: (one line
|
|
8076
|
+
TECH: (one line)
|
|
8065
8077
|
|
|
8066
8078
|
ASSIGNMENTS:
|
|
8067
|
-
- @DevName: (
|
|
8079
|
+
- @DevName: (what they build)
|
|
8068
8080
|
[/PLAN]
|
|
8069
8081
|
|
|
8070
|
-
===== ANTI-PATTERNS (never do these) =====
|
|
8071
|
-
- Do NOT write technical implementation steps (e.g. "implement game loop with requestAnimationFrame") \u2014 that is the developer's job.
|
|
8072
|
-
- Do NOT list generic engineering tasks (e.g. "add collision detection", "implement scoring system") \u2014 describe WHAT the product does, not HOW to code it.
|
|
8073
|
-
- Do NOT produce a checklist of modules or files. The plan is a PRODUCT DESCRIPTION, not a technical spec.
|
|
8074
|
-
- Do NOT include milestones, risk analysis, acceptance criteria, or deployment plans.
|
|
8075
|
-
- Do NOT delegate. Do NOT write code. Do NOT use @AgentName: syntax outside [PLAN] tags.
|
|
8076
|
-
|
|
8077
8082
|
If the user hasn't described their project yet, greet them and ask what they'd like to build.
|
|
8078
8083
|
{{memory}}
|
|
8079
8084
|
Team:
|
|
8080
8085
|
{{teamRoster}}
|
|
8081
8086
|
|
|
8082
8087
|
{{prompt}}`,
|
|
8083
|
-
"leader-create-continue": `You are {{name}}, the team's Creative Director
|
|
8084
|
-
Do NOT greet or re-introduce yourself
|
|
8088
|
+
"leader-create-continue": `You are {{name}}, the team's Creative Director. {{personality}}
|
|
8089
|
+
Do NOT greet or re-introduce yourself.
|
|
8085
8090
|
|
|
8086
8091
|
The user replied: {{prompt}}
|
|
8087
8092
|
|
|
8088
|
-
|
|
8093
|
+
If the user wants to move forward ("just do it", "you decide", "any is fine"), STOP asking and produce the plan in [PLAN]...[/PLAN] tags. Use your creativity to fill in the vision. Otherwise, ask at most ONE more question, then produce the plan.`,
|
|
8094
|
+
"leader-design": `You are {{name}}, refining the project vision. {{personality}}
|
|
8089
8095
|
|
|
8090
|
-
|
|
8091
|
-
"leader-design": `You are {{name}}, the team's Creative Director, refining the project vision with the user. {{personality}}
|
|
8092
|
-
The user has given feedback on your plan. Your job is to REVISE the existing plan, not start over.
|
|
8096
|
+
Apply the user's feedback to the existing plan. Only change what they mentioned \u2014 keep everything else intact.
|
|
8093
8097
|
|
|
8094
|
-
|
|
8095
|
-
- User feedback is usually a PARTIAL adjustment (e.g. "use PixiJS", "make it darker", "add multiplayer").
|
|
8096
|
-
- Apply the feedback to the EXISTING plan. Keep everything the user did NOT mention.
|
|
8097
|
-
- NEVER discard the original concept, story, characters, or gameplay just because the user asked for a tech or style change.
|
|
8098
|
-
- If the user says "use X engine" or "change to Y framework" \u2192 update ONLY the TECH line and any affected details. The product vision stays.
|
|
8099
|
-
- Think of it as editing a document, not writing a new one.
|
|
8100
|
-
|
|
8101
|
-
Rules:
|
|
8102
|
-
- Address the user's feedback directly and show what changed.
|
|
8103
|
-
- Always output the updated plan in [PLAN]...[/PLAN] tags using the standard format: CONCEPT, CREATIVE VISION, FEATURES, TECH, ASSIGNMENTS.
|
|
8104
|
-
- The plan describes the PRODUCT VISION \u2014 what users see, feel, and experience. NOT technical implementation steps.
|
|
8105
|
-
- Keep it prototype-focused. No milestones, risk analysis, or deployment plans.
|
|
8106
|
-
- Do NOT delegate. Do NOT write code. Do NOT use @AgentName: syntax outside [PLAN] tags.
|
|
8098
|
+
Output the revised plan in [PLAN]...[/PLAN] tags (CONCEPT, CREATIVE VISION, FEATURES, TECH, ASSIGNMENTS). Do NOT delegate or write code.
|
|
8107
8099
|
|
|
8108
8100
|
Team:
|
|
8109
8101
|
{{teamRoster}}
|
|
8110
8102
|
|
|
8111
|
-
Previous plan
|
|
8103
|
+
Previous plan: {{originalTask}}
|
|
8112
8104
|
|
|
8113
8105
|
User feedback: {{prompt}}`,
|
|
8114
|
-
"leader-design-continue": `You are {{name}},
|
|
8106
|
+
"leader-design-continue": `You are {{name}}, refining the project vision. {{personality}}
|
|
8115
8107
|
|
|
8116
|
-
|
|
8108
|
+
Current plan:
|
|
8117
8109
|
{{originalTask}}
|
|
8118
8110
|
|
|
8119
8111
|
The user replied: {{prompt}}
|
|
8120
8112
|
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
Output the revised plan in the standard format: CONCEPT, CREATIVE VISION, FEATURES, TECH, ASSIGNMENTS. Describe the product vision, NOT technical steps. Always output in [PLAN]...[/PLAN] tags. Do NOT delegate or write code.`,
|
|
8113
|
+
Incremental update \u2014 only change what the user mentioned. Output in [PLAN]...[/PLAN] tags. Do NOT delegate or write code.`,
|
|
8124
8114
|
"leader-complete": `You are {{name}}, presenting completed work to the user. {{personality}}
|
|
8125
|
-
The team has finished
|
|
8126
|
-
|
|
8127
|
-
Rules:
|
|
8128
|
-
- Be concise and highlight key outcomes.
|
|
8129
|
-
- If the user provides feedback, note it \u2014 the system will transition back to execute phase.
|
|
8130
|
-
- Do NOT delegate. Do NOT write code. Do NOT use @AgentName: syntax.
|
|
8115
|
+
The team has finished. Summarize what was accomplished and ask if the user wants changes.
|
|
8131
8116
|
|
|
8132
8117
|
Team:
|
|
8133
8118
|
{{teamRoster}}
|
|
@@ -8208,7 +8193,8 @@ var PromptEngine = class {
|
|
|
8208
8193
|
console.warn(`[Prompts] Unknown template: ${templateName}`);
|
|
8209
8194
|
return vars["prompt"] ?? "";
|
|
8210
8195
|
}
|
|
8211
|
-
|
|
8196
|
+
const mergedVars = { soul: DEFAULT_SOUL, ...vars };
|
|
8197
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => mergedVars[key] ?? "");
|
|
8212
8198
|
}
|
|
8213
8199
|
};
|
|
8214
8200
|
|
|
@@ -8606,6 +8592,7 @@ var Orchestrator = class extends EventEmitter {
|
|
|
8606
8592
|
workspace: opts.workDir ?? this.workspace,
|
|
8607
8593
|
resumeHistory: opts.resumeHistory,
|
|
8608
8594
|
backend,
|
|
8595
|
+
model: opts.model,
|
|
8609
8596
|
sandboxMode: this.sandboxMode,
|
|
8610
8597
|
isTeamLead: this.agentManager.isTeamLead(opts.agentId),
|
|
8611
8598
|
teamId: opts.teamId,
|
|
@@ -8905,6 +8892,7 @@ ${lines.join("\n")}`;
|
|
|
8905
8892
|
palette: s.palette,
|
|
8906
8893
|
personality: s.personality,
|
|
8907
8894
|
backend: s.backend.id,
|
|
8895
|
+
model: s.model,
|
|
8908
8896
|
pid: s.pid,
|
|
8909
8897
|
isTeamLead: this.agentManager.isTeamLead(s.agentId),
|
|
8910
8898
|
teamId: s.teamId,
|
|
@@ -9658,6 +9646,44 @@ var PreviewServer = class {
|
|
|
9658
9646
|
};
|
|
9659
9647
|
var previewServer = new PreviewServer();
|
|
9660
9648
|
|
|
9649
|
+
// ../../packages/orchestrator/src/agent-defs.ts
|
|
9650
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readdirSync as readdirSync2, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
9651
|
+
import { resolve as resolve2, dirname as dirname2 } from "path";
|
|
9652
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9653
|
+
import { homedir as homedir6 } from "os";
|
|
9654
|
+
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
9655
|
+
function getBundledAgentsDir() {
|
|
9656
|
+
const fromDist = resolve2(__dirname2, "../agents");
|
|
9657
|
+
if (existsSync10(fromDist)) return fromDist;
|
|
9658
|
+
const fromSrc = resolve2(__dirname2, "../agents");
|
|
9659
|
+
return fromSrc;
|
|
9660
|
+
}
|
|
9661
|
+
function syncAgentDefs() {
|
|
9662
|
+
const bundledDir = getBundledAgentsDir();
|
|
9663
|
+
if (!existsSync10(bundledDir)) {
|
|
9664
|
+
console.log(`[Agents] No bundled agents directory found at ${bundledDir}`);
|
|
9665
|
+
return;
|
|
9666
|
+
}
|
|
9667
|
+
const targetDir = resolve2(homedir6(), ".claude", "agents");
|
|
9668
|
+
if (!existsSync10(targetDir)) {
|
|
9669
|
+
mkdirSync7(targetDir, { recursive: true });
|
|
9670
|
+
}
|
|
9671
|
+
const files = readdirSync2(bundledDir).filter((f) => f.endsWith(".md"));
|
|
9672
|
+
let synced = 0;
|
|
9673
|
+
for (const file of files) {
|
|
9674
|
+
const src = resolve2(bundledDir, file);
|
|
9675
|
+
const dst = resolve2(targetDir, file);
|
|
9676
|
+
try {
|
|
9677
|
+
const content = readFileSync7(src, "utf-8");
|
|
9678
|
+
writeFileSync7(dst, content, "utf-8");
|
|
9679
|
+
synced++;
|
|
9680
|
+
} catch (e) {
|
|
9681
|
+
console.warn(`[Agents] Failed to sync ${file}: ${e}`);
|
|
9682
|
+
}
|
|
9683
|
+
}
|
|
9684
|
+
console.log(`[Agents] Synced ${synced} agent definitions to ${targetDir}`);
|
|
9685
|
+
}
|
|
9686
|
+
|
|
9661
9687
|
// ../../packages/orchestrator/src/index.ts
|
|
9662
9688
|
function createOrchestrator(options) {
|
|
9663
9689
|
return new Orchestrator(options);
|
|
@@ -9666,12 +9692,12 @@ function createOrchestrator(options) {
|
|
|
9666
9692
|
// src/ws-server.ts
|
|
9667
9693
|
import { networkInterfaces } from "os";
|
|
9668
9694
|
import { readFile, stat } from "fs/promises";
|
|
9669
|
-
import { readFileSync as
|
|
9670
|
-
import { join, extname, resolve as
|
|
9695
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync9, existsSync as existsSync12, mkdirSync as mkdirSync9 } from "fs";
|
|
9696
|
+
import { join, extname, resolve as resolve3 } from "path";
|
|
9671
9697
|
import * as Ably from "ably";
|
|
9672
9698
|
|
|
9673
9699
|
// src/runtime-state.ts
|
|
9674
|
-
import { existsSync as
|
|
9700
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readdirSync as readdirSync3, readFileSync as readFileSync8, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
9675
9701
|
import { execSync as execSync5 } from "child_process";
|
|
9676
9702
|
import path10 from "path";
|
|
9677
9703
|
var RUNTIME_FILE = path10.join(config.instanceDir, "runtime.json");
|
|
@@ -9685,9 +9711,9 @@ function portLockPath(port) {
|
|
|
9685
9711
|
}
|
|
9686
9712
|
function killPortLockHolder(port) {
|
|
9687
9713
|
const lockFile = portLockPath(port);
|
|
9688
|
-
if (!
|
|
9714
|
+
if (!existsSync11(lockFile)) return;
|
|
9689
9715
|
try {
|
|
9690
|
-
const pid = parseInt(
|
|
9716
|
+
const pid = parseInt(readFileSync8(lockFile, "utf-8").trim(), 10);
|
|
9691
9717
|
if (!pid || pid === process.pid) return;
|
|
9692
9718
|
try {
|
|
9693
9719
|
process.kill(pid, 0);
|
|
@@ -9713,9 +9739,9 @@ function killPortLockHolder(port) {
|
|
|
9713
9739
|
}
|
|
9714
9740
|
}
|
|
9715
9741
|
function writePortLock(port) {
|
|
9716
|
-
if (!
|
|
9742
|
+
if (!existsSync11(LOCKS_DIR)) mkdirSync8(LOCKS_DIR, { recursive: true });
|
|
9717
9743
|
const lockPath = portLockPath(port);
|
|
9718
|
-
|
|
9744
|
+
writeFileSync8(lockPath, String(process.pid), "utf-8");
|
|
9719
9745
|
portLockFile = lockPath;
|
|
9720
9746
|
console.log(`[Gateway] Port lock written: ${lockPath} (pid=${process.pid})`);
|
|
9721
9747
|
}
|
|
@@ -9730,9 +9756,9 @@ function clearPortLock() {
|
|
|
9730
9756
|
}
|
|
9731
9757
|
function writeRuntimeFile(state) {
|
|
9732
9758
|
const dir = path10.dirname(RUNTIME_FILE);
|
|
9733
|
-
if (!
|
|
9759
|
+
if (!existsSync11(dir)) mkdirSync8(dir, { recursive: true });
|
|
9734
9760
|
const tmp = `${RUNTIME_FILE}.tmp`;
|
|
9735
|
-
|
|
9761
|
+
writeFileSync8(tmp, JSON.stringify(state, null, 2), "utf-8");
|
|
9736
9762
|
renameSync2(tmp, RUNTIME_FILE);
|
|
9737
9763
|
}
|
|
9738
9764
|
function syncSleep(ms) {
|
|
@@ -9768,15 +9794,15 @@ function killPreviousInstances() {
|
|
|
9768
9794
|
const instancesDir = path10.dirname(config.instanceDir);
|
|
9769
9795
|
let dirs;
|
|
9770
9796
|
try {
|
|
9771
|
-
dirs =
|
|
9797
|
+
dirs = readdirSync3(instancesDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => path10.join(instancesDir, d.name));
|
|
9772
9798
|
} catch {
|
|
9773
9799
|
dirs = [config.instanceDir];
|
|
9774
9800
|
}
|
|
9775
9801
|
for (const dir of dirs) {
|
|
9776
9802
|
const runtimeFile = path10.join(dir, "runtime.json");
|
|
9777
|
-
if (!
|
|
9803
|
+
if (!existsSync11(runtimeFile)) continue;
|
|
9778
9804
|
try {
|
|
9779
|
-
const prev = JSON.parse(
|
|
9805
|
+
const prev = JSON.parse(readFileSync8(runtimeFile, "utf-8"));
|
|
9780
9806
|
if (prev.pid === process.pid) continue;
|
|
9781
9807
|
try {
|
|
9782
9808
|
process.kill(prev.pid, 0);
|
|
@@ -9859,13 +9885,13 @@ var pairCode = null;
|
|
|
9859
9885
|
var onCommand = null;
|
|
9860
9886
|
var shareTokens = /* @__PURE__ */ new Map();
|
|
9861
9887
|
function getSessionTokensFile() {
|
|
9862
|
-
return
|
|
9888
|
+
return resolve3(config.instanceDir, "session-tokens.json");
|
|
9863
9889
|
}
|
|
9864
9890
|
function loadSessionTokens() {
|
|
9865
9891
|
try {
|
|
9866
9892
|
const f = getSessionTokensFile();
|
|
9867
|
-
if (
|
|
9868
|
-
const data = JSON.parse(
|
|
9893
|
+
if (existsSync12(f)) {
|
|
9894
|
+
const data = JSON.parse(readFileSync9(f, "utf-8"));
|
|
9869
9895
|
return new Map(Object.entries(data));
|
|
9870
9896
|
}
|
|
9871
9897
|
} catch {
|
|
@@ -9873,9 +9899,9 @@ function loadSessionTokens() {
|
|
|
9873
9899
|
return /* @__PURE__ */ new Map();
|
|
9874
9900
|
}
|
|
9875
9901
|
function persistSessionTokens() {
|
|
9876
|
-
const dir =
|
|
9877
|
-
if (!
|
|
9878
|
-
|
|
9902
|
+
const dir = resolve3(config.instanceDir);
|
|
9903
|
+
if (!existsSync12(dir)) mkdirSync9(dir, { recursive: true });
|
|
9904
|
+
writeFileSync9(getSessionTokensFile(), JSON.stringify(Object.fromEntries(sessionTokens)), "utf-8");
|
|
9879
9905
|
}
|
|
9880
9906
|
var sessionTokens = loadSessionTokens();
|
|
9881
9907
|
function addSessionToken(token, role) {
|
|
@@ -10091,9 +10117,9 @@ var wsChannel = {
|
|
|
10091
10117
|
return;
|
|
10092
10118
|
}
|
|
10093
10119
|
const reqPath = decodeURIComponent((staticMatch[1] || "/").split("?")[0]);
|
|
10094
|
-
const filePath =
|
|
10095
|
-
const rootWithSep =
|
|
10096
|
-
if (filePath !==
|
|
10120
|
+
const filePath = resolve3(root, reqPath === "/" ? entry ?? "index.html" : reqPath.slice(1));
|
|
10121
|
+
const rootWithSep = resolve3(root) + "/";
|
|
10122
|
+
if (filePath !== resolve3(root) && !filePath.startsWith(rootWithSep)) {
|
|
10097
10123
|
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
10098
10124
|
res.end("Forbidden");
|
|
10099
10125
|
return;
|
|
@@ -10329,8 +10355,8 @@ async function serveStatic(req, res) {
|
|
|
10329
10355
|
} else {
|
|
10330
10356
|
filePath = join(config.webDir, url);
|
|
10331
10357
|
}
|
|
10332
|
-
const webRoot =
|
|
10333
|
-
const resolvedPath =
|
|
10358
|
+
const webRoot = resolve3(config.webDir);
|
|
10359
|
+
const resolvedPath = resolve3(filePath);
|
|
10334
10360
|
if (resolvedPath !== webRoot && !resolvedPath.startsWith(webRoot + "/")) {
|
|
10335
10361
|
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
10336
10362
|
res.end("Forbidden");
|
|
@@ -10734,13 +10760,13 @@ import { createInterface } from "readline";
|
|
|
10734
10760
|
|
|
10735
10761
|
// src/backends.ts
|
|
10736
10762
|
import { execSync as execSync6 } from "child_process";
|
|
10737
|
-
import { existsSync as
|
|
10738
|
-
import { homedir as
|
|
10763
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "fs";
|
|
10764
|
+
import { homedir as homedir8 } from "os";
|
|
10739
10765
|
import path11 from "path";
|
|
10740
10766
|
var isRoot = process.getuid?.() === 0;
|
|
10741
10767
|
function ensureClaudeSettingsForRoot() {
|
|
10742
10768
|
if (!isRoot) return;
|
|
10743
|
-
const claudeDir = path11.join(
|
|
10769
|
+
const claudeDir = path11.join(homedir8(), ".claude");
|
|
10744
10770
|
const settingsPath = path11.join(claudeDir, "settings.json");
|
|
10745
10771
|
const requiredAllow = [
|
|
10746
10772
|
"Bash",
|
|
@@ -10757,8 +10783,8 @@ function ensureClaudeSettingsForRoot() {
|
|
|
10757
10783
|
];
|
|
10758
10784
|
try {
|
|
10759
10785
|
let settings = {};
|
|
10760
|
-
if (
|
|
10761
|
-
settings = JSON.parse(
|
|
10786
|
+
if (existsSync13(settingsPath)) {
|
|
10787
|
+
settings = JSON.parse(readFileSync10(settingsPath, "utf-8"));
|
|
10762
10788
|
}
|
|
10763
10789
|
settings.defaultMode = "bypassPermissions";
|
|
10764
10790
|
const perms = settings.permissions ?? {};
|
|
@@ -10766,8 +10792,8 @@ function ensureClaudeSettingsForRoot() {
|
|
|
10766
10792
|
const merged = [.../* @__PURE__ */ new Set([...existing, ...requiredAllow])];
|
|
10767
10793
|
perms.allow = merged;
|
|
10768
10794
|
settings.permissions = perms;
|
|
10769
|
-
if (!
|
|
10770
|
-
|
|
10795
|
+
if (!existsSync13(claudeDir)) mkdirSync10(claudeDir, { recursive: true });
|
|
10796
|
+
writeFileSync10(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
10771
10797
|
console.log("[backends] Running as root \u2014 configured Claude Code settings.json to allow all permissions");
|
|
10772
10798
|
} catch (err) {
|
|
10773
10799
|
console.warn("[backends] Failed to configure Claude settings for root:", err);
|
|
@@ -10992,12 +11018,12 @@ function detectBackends() {
|
|
|
10992
11018
|
|
|
10993
11019
|
// src/setup.ts
|
|
10994
11020
|
function ask(rl, question) {
|
|
10995
|
-
return new Promise((
|
|
10996
|
-
const onClose = () =>
|
|
11021
|
+
return new Promise((resolve5) => {
|
|
11022
|
+
const onClose = () => resolve5("");
|
|
10997
11023
|
rl.once("close", onClose);
|
|
10998
11024
|
rl.question(question, (answer) => {
|
|
10999
11025
|
rl.removeListener("close", onClose);
|
|
11000
|
-
|
|
11026
|
+
resolve5(answer.trim());
|
|
11001
11027
|
});
|
|
11002
11028
|
});
|
|
11003
11029
|
}
|
|
@@ -11070,7 +11096,7 @@ async function runSetup() {
|
|
|
11070
11096
|
// src/index.ts
|
|
11071
11097
|
import { nanoid as nanoid6 } from "nanoid";
|
|
11072
11098
|
import { exec as exec2, execFile as execFile3, execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
11073
|
-
import { existsSync as
|
|
11099
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync13, readFileSync as readFileSync12, readdirSync as readdirSync6, writeFileSync as writeFileSync12, renameSync as renameSync5, unlinkSync as unlinkSync3, rmdirSync as rmdirSync2 } from "fs";
|
|
11074
11100
|
import path14 from "path";
|
|
11075
11101
|
|
|
11076
11102
|
// src/process-scanner.ts
|
|
@@ -11110,9 +11136,9 @@ function parseEtime(etime) {
|
|
|
11110
11136
|
return now - seconds * 1e3;
|
|
11111
11137
|
}
|
|
11112
11138
|
function exec(cmd, args) {
|
|
11113
|
-
return new Promise((
|
|
11139
|
+
return new Promise((resolve5) => {
|
|
11114
11140
|
execFile(cmd, args, { timeout: 5e3, maxBuffer: 1024 * 1024 * 2 }, (err, stdout) => {
|
|
11115
|
-
|
|
11141
|
+
resolve5(err ? "" : stdout);
|
|
11116
11142
|
});
|
|
11117
11143
|
});
|
|
11118
11144
|
}
|
|
@@ -11244,7 +11270,7 @@ var ProcessScanner = class _ProcessScanner {
|
|
|
11244
11270
|
};
|
|
11245
11271
|
|
|
11246
11272
|
// src/external-output-reader.ts
|
|
11247
|
-
import { watch, readdirSync as
|
|
11273
|
+
import { watch, readdirSync as readdirSync4, statSync, existsSync as existsSync14, openSync, readSync, closeSync } from "fs";
|
|
11248
11274
|
import { execFile as execFile2 } from "child_process";
|
|
11249
11275
|
import path12 from "path";
|
|
11250
11276
|
import os from "os";
|
|
@@ -11375,7 +11401,7 @@ var ExternalOutputReader = class {
|
|
|
11375
11401
|
};
|
|
11376
11402
|
const findAndWatch = () => {
|
|
11377
11403
|
if (stopped) return;
|
|
11378
|
-
if (!
|
|
11404
|
+
if (!existsSync14(projectDir)) {
|
|
11379
11405
|
retryCount++;
|
|
11380
11406
|
if (retryCount > MAX_RETRIES) {
|
|
11381
11407
|
console.log(`[OutputReader] Project dir not found after ${MAX_RETRIES} retries, giving up: ${projectDir}`);
|
|
@@ -11386,7 +11412,7 @@ var ExternalOutputReader = class {
|
|
|
11386
11412
|
return;
|
|
11387
11413
|
}
|
|
11388
11414
|
try {
|
|
11389
|
-
const files =
|
|
11415
|
+
const files = readdirSync4(projectDir).filter((f) => f.endsWith(".jsonl")).map((f) => ({
|
|
11390
11416
|
name: f,
|
|
11391
11417
|
mtime: statSync(path12.join(projectDir, f)).mtimeMs
|
|
11392
11418
|
})).sort((a, b) => b.mtime - a.mtime);
|
|
@@ -11408,7 +11434,7 @@ var ExternalOutputReader = class {
|
|
|
11408
11434
|
if (stopped) return;
|
|
11409
11435
|
if (filename && filename.endsWith(".jsonl")) {
|
|
11410
11436
|
const fullPath = path12.join(projectDir, filename);
|
|
11411
|
-
if (fullPath !== watchedFile &&
|
|
11437
|
+
if (fullPath !== watchedFile && existsSync14(fullPath)) {
|
|
11412
11438
|
try {
|
|
11413
11439
|
const newMtime = statSync(fullPath).mtimeMs;
|
|
11414
11440
|
const curMtime = watchedFile ? statSync(watchedFile).mtimeMs : 0;
|
|
@@ -11542,8 +11568,8 @@ var ExternalOutputReader = class {
|
|
|
11542
11568
|
};
|
|
11543
11569
|
|
|
11544
11570
|
// src/file-logger.ts
|
|
11545
|
-
import { createWriteStream, existsSync as
|
|
11546
|
-
import { resolve as
|
|
11571
|
+
import { createWriteStream, existsSync as existsSync15, mkdirSync as mkdirSync11, renameSync as renameSync3, statSync as statSync2 } from "fs";
|
|
11572
|
+
import { resolve as resolve4 } from "path";
|
|
11547
11573
|
var MAX_SIZE = 5 * 1024 * 1024;
|
|
11548
11574
|
var LOG_NAME = "gateway.log";
|
|
11549
11575
|
var BACKUP_NAME = "gateway.log.1";
|
|
@@ -11574,9 +11600,9 @@ function writeLine(level, args) {
|
|
|
11574
11600
|
if (bytesWritten > MAX_SIZE) rotate();
|
|
11575
11601
|
}
|
|
11576
11602
|
function installFileLogger(dir) {
|
|
11577
|
-
if (!
|
|
11578
|
-
logPath =
|
|
11579
|
-
backupPath =
|
|
11603
|
+
if (!existsSync15(dir)) mkdirSync11(dir, { recursive: true });
|
|
11604
|
+
logPath = resolve4(dir, LOG_NAME);
|
|
11605
|
+
backupPath = resolve4(dir, BACKUP_NAME);
|
|
11580
11606
|
try {
|
|
11581
11607
|
bytesWritten = statSync2(logPath).size;
|
|
11582
11608
|
} catch {
|
|
@@ -11673,7 +11699,7 @@ function isTunnelRunning() {
|
|
|
11673
11699
|
}
|
|
11674
11700
|
|
|
11675
11701
|
// src/team-state.ts
|
|
11676
|
-
import { existsSync as
|
|
11702
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync12, readFileSync as readFileSync11, writeFileSync as writeFileSync11, renameSync as renameSync4, appendFileSync, readdirSync as readdirSync5 } from "fs";
|
|
11677
11703
|
import path13 from "path";
|
|
11678
11704
|
var PROJECTS_DIR = path13.join(CONFIG_DIR, "data", "project-history");
|
|
11679
11705
|
function getStateFile() {
|
|
@@ -11685,8 +11711,8 @@ function getEventsFile() {
|
|
|
11685
11711
|
var EMPTY_STATE = { agents: [], team: null };
|
|
11686
11712
|
function loadTeamState() {
|
|
11687
11713
|
try {
|
|
11688
|
-
if (
|
|
11689
|
-
const raw = JSON.parse(
|
|
11714
|
+
if (existsSync16(getStateFile())) {
|
|
11715
|
+
const raw = JSON.parse(readFileSync11(getStateFile(), "utf-8"));
|
|
11690
11716
|
if (raw && Array.isArray(raw.agents)) {
|
|
11691
11717
|
return raw;
|
|
11692
11718
|
}
|
|
@@ -11699,9 +11725,9 @@ function saveTeamState(state) {
|
|
|
11699
11725
|
try {
|
|
11700
11726
|
const file = getStateFile();
|
|
11701
11727
|
const dir = path13.dirname(file);
|
|
11702
|
-
if (!
|
|
11728
|
+
if (!existsSync16(dir)) mkdirSync12(dir, { recursive: true });
|
|
11703
11729
|
const tmp = file + ".tmp";
|
|
11704
|
-
|
|
11730
|
+
writeFileSync11(tmp, JSON.stringify(state, null, 2), "utf-8");
|
|
11705
11731
|
renameSync4(tmp, file);
|
|
11706
11732
|
} catch (e) {
|
|
11707
11733
|
console.log(`[TeamState] Failed to save: ${e}`);
|
|
@@ -11722,14 +11748,14 @@ function resetProjectBuffer() {
|
|
|
11722
11748
|
projectStartedAt = Date.now();
|
|
11723
11749
|
projectName = "";
|
|
11724
11750
|
try {
|
|
11725
|
-
|
|
11751
|
+
writeFileSync11(getEventsFile(), "", "utf-8");
|
|
11726
11752
|
} catch {
|
|
11727
11753
|
}
|
|
11728
11754
|
}
|
|
11729
11755
|
function loadProjectBuffer() {
|
|
11730
11756
|
try {
|
|
11731
|
-
if (!
|
|
11732
|
-
const raw =
|
|
11757
|
+
if (!existsSync16(getEventsFile())) return;
|
|
11758
|
+
const raw = readFileSync11(getEventsFile(), "utf-8").trim();
|
|
11733
11759
|
if (!raw) return;
|
|
11734
11760
|
const lines = raw.split("\n");
|
|
11735
11761
|
for (const line of lines) {
|
|
@@ -11757,7 +11783,7 @@ function bufferEvent(event) {
|
|
|
11757
11783
|
projectEvents.push(stamped);
|
|
11758
11784
|
try {
|
|
11759
11785
|
const dir = path13.dirname(getEventsFile());
|
|
11760
|
-
if (!
|
|
11786
|
+
if (!existsSync16(dir)) mkdirSync12(dir, { recursive: true });
|
|
11761
11787
|
appendFileSync(getEventsFile(), JSON.stringify(stamped) + "\n", "utf-8");
|
|
11762
11788
|
} catch {
|
|
11763
11789
|
}
|
|
@@ -11765,10 +11791,10 @@ function bufferEvent(event) {
|
|
|
11765
11791
|
function rewriteEventsFile() {
|
|
11766
11792
|
try {
|
|
11767
11793
|
const dir = path13.dirname(getEventsFile());
|
|
11768
|
-
if (!
|
|
11794
|
+
if (!existsSync16(dir)) mkdirSync12(dir, { recursive: true });
|
|
11769
11795
|
const header = { _header: true, startedAt: projectStartedAt, projectName };
|
|
11770
11796
|
const lines = [JSON.stringify(header), ...projectEvents.map((e) => JSON.stringify(e))];
|
|
11771
|
-
|
|
11797
|
+
writeFileSync11(getEventsFile(), lines.join("\n") + "\n", "utf-8");
|
|
11772
11798
|
} catch {
|
|
11773
11799
|
}
|
|
11774
11800
|
}
|
|
@@ -11777,7 +11803,7 @@ function archiveProject(agents, team) {
|
|
|
11777
11803
|
(e) => e.type === "TASK_DONE" || e.type === "TEAM_CHAT" || e.type === "TASK_STARTED"
|
|
11778
11804
|
);
|
|
11779
11805
|
if (meaningful.length === 0) return null;
|
|
11780
|
-
if (!
|
|
11806
|
+
if (!existsSync16(PROJECTS_DIR)) mkdirSync12(PROJECTS_DIR, { recursive: true });
|
|
11781
11807
|
let preview;
|
|
11782
11808
|
for (let i = projectEvents.length - 1; i >= 0; i--) {
|
|
11783
11809
|
const e = projectEvents[i];
|
|
@@ -11807,8 +11833,8 @@ function archiveProject(agents, team) {
|
|
|
11807
11833
|
const filePath = path13.join(PROJECTS_DIR, `${id}.json`);
|
|
11808
11834
|
let existingRatings;
|
|
11809
11835
|
try {
|
|
11810
|
-
if (
|
|
11811
|
-
const existing = JSON.parse(
|
|
11836
|
+
if (existsSync16(filePath)) {
|
|
11837
|
+
const existing = JSON.parse(readFileSync11(filePath, "utf-8"));
|
|
11812
11838
|
existingRatings = existing.ratings;
|
|
11813
11839
|
}
|
|
11814
11840
|
} catch {
|
|
@@ -11826,7 +11852,7 @@ function archiveProject(agents, team) {
|
|
|
11826
11852
|
ratings: existingRatings
|
|
11827
11853
|
};
|
|
11828
11854
|
try {
|
|
11829
|
-
|
|
11855
|
+
writeFileSync11(filePath, JSON.stringify(archive), "utf-8");
|
|
11830
11856
|
console.log(`[TeamState] Archived project "${archive.name}" (${projectEvents.length} events) \u2192 ${filePath}`);
|
|
11831
11857
|
return id;
|
|
11832
11858
|
} catch (e) {
|
|
@@ -11836,13 +11862,13 @@ function archiveProject(agents, team) {
|
|
|
11836
11862
|
}
|
|
11837
11863
|
var MAX_LISTED_PROJECTS = 50;
|
|
11838
11864
|
function listProjects() {
|
|
11839
|
-
if (!
|
|
11865
|
+
if (!existsSync16(PROJECTS_DIR)) return [];
|
|
11840
11866
|
try {
|
|
11841
|
-
const files =
|
|
11867
|
+
const files = readdirSync5(PROJECTS_DIR).filter((f) => f.endsWith(".json")).sort().reverse().slice(0, MAX_LISTED_PROJECTS);
|
|
11842
11868
|
const summaries = [];
|
|
11843
11869
|
for (const file of files) {
|
|
11844
11870
|
try {
|
|
11845
|
-
const raw = JSON.parse(
|
|
11871
|
+
const raw = JSON.parse(readFileSync11(path13.join(PROJECTS_DIR, file), "utf-8"));
|
|
11846
11872
|
summaries.push({
|
|
11847
11873
|
id: raw.id,
|
|
11848
11874
|
name: raw.name,
|
|
@@ -11868,15 +11894,15 @@ function loadProject(id) {
|
|
|
11868
11894
|
const filePath = path13.join(PROJECTS_DIR, `${safeId}.json`);
|
|
11869
11895
|
if (!path13.resolve(filePath).startsWith(path13.resolve(PROJECTS_DIR))) return null;
|
|
11870
11896
|
try {
|
|
11871
|
-
if (
|
|
11872
|
-
return JSON.parse(
|
|
11897
|
+
if (existsSync16(filePath)) {
|
|
11898
|
+
return JSON.parse(readFileSync11(filePath, "utf-8"));
|
|
11873
11899
|
}
|
|
11874
11900
|
} catch {
|
|
11875
11901
|
}
|
|
11876
11902
|
return null;
|
|
11877
11903
|
}
|
|
11878
11904
|
function rateProject(ratings, projectId) {
|
|
11879
|
-
if (!
|
|
11905
|
+
if (!existsSync16(PROJECTS_DIR)) return false;
|
|
11880
11906
|
try {
|
|
11881
11907
|
let filePath;
|
|
11882
11908
|
if (projectId) {
|
|
@@ -11884,14 +11910,14 @@ function rateProject(ratings, projectId) {
|
|
|
11884
11910
|
filePath = path13.join(PROJECTS_DIR, `${safeId}.json`);
|
|
11885
11911
|
if (!path13.resolve(filePath).startsWith(path13.resolve(PROJECTS_DIR))) return false;
|
|
11886
11912
|
} else {
|
|
11887
|
-
const files =
|
|
11913
|
+
const files = readdirSync5(PROJECTS_DIR).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
11888
11914
|
if (files.length === 0) return false;
|
|
11889
11915
|
filePath = path13.join(PROJECTS_DIR, files[0]);
|
|
11890
11916
|
}
|
|
11891
|
-
if (!
|
|
11892
|
-
const archive = JSON.parse(
|
|
11917
|
+
if (!existsSync16(filePath)) return false;
|
|
11918
|
+
const archive = JSON.parse(readFileSync11(filePath, "utf-8"));
|
|
11893
11919
|
archive.ratings = ratings;
|
|
11894
|
-
|
|
11920
|
+
writeFileSync11(filePath, JSON.stringify(archive), "utf-8");
|
|
11895
11921
|
console.log(`[TeamState] Rated project "${archive.name}":`, ratings);
|
|
11896
11922
|
return true;
|
|
11897
11923
|
} catch (e) {
|
|
@@ -11916,6 +11942,7 @@ function persistTeamState() {
|
|
|
11916
11942
|
role: a.role,
|
|
11917
11943
|
personality: a.personality,
|
|
11918
11944
|
backend: a.backend,
|
|
11945
|
+
model: a.model,
|
|
11919
11946
|
palette: a.palette,
|
|
11920
11947
|
teamId: a.teamId,
|
|
11921
11948
|
isTeamLead: orc.isTeamLead(a.agentId),
|
|
@@ -11993,33 +12020,33 @@ function extractProjectName(planText) {
|
|
|
11993
12020
|
function createUniqueProjectDir(workspace, baseName) {
|
|
11994
12021
|
let dirName = baseName;
|
|
11995
12022
|
let counter = 1;
|
|
11996
|
-
while (
|
|
12023
|
+
while (existsSync17(path14.join(workspace, dirName))) {
|
|
11997
12024
|
counter++;
|
|
11998
12025
|
dirName = `${baseName}-${counter}`;
|
|
11999
12026
|
}
|
|
12000
12027
|
const fullPath = path14.join(workspace, dirName);
|
|
12001
|
-
|
|
12028
|
+
mkdirSync13(fullPath, { recursive: true });
|
|
12002
12029
|
console.log(`[Gateway] Created project directory: ${fullPath}`);
|
|
12003
12030
|
return fullPath;
|
|
12004
12031
|
}
|
|
12005
12032
|
var AGENTS_FILE = path14.join(CONFIG_DIR, "data", "agents.json");
|
|
12006
12033
|
var SKILLS_DIR = path14.join(CONFIG_DIR, "skills");
|
|
12007
12034
|
function listSkills() {
|
|
12008
|
-
if (!
|
|
12035
|
+
if (!existsSync17(SKILLS_DIR)) return [];
|
|
12009
12036
|
try {
|
|
12010
|
-
const entries =
|
|
12037
|
+
const entries = readdirSync6(SKILLS_DIR, { withFileTypes: true });
|
|
12011
12038
|
const skills = [];
|
|
12012
12039
|
for (const entry of entries) {
|
|
12013
12040
|
if (entry.isDirectory()) {
|
|
12014
12041
|
const entryPath = path14.join(SKILLS_DIR, entry.name, "skill.md");
|
|
12015
|
-
if (
|
|
12016
|
-
const content =
|
|
12042
|
+
if (existsSync17(entryPath)) {
|
|
12043
|
+
const content = readFileSync12(entryPath, "utf-8");
|
|
12017
12044
|
const titleMatch = content.match(/^#\s+(.+)/m);
|
|
12018
12045
|
skills.push({ name: entry.name, title: titleMatch?.[1] ?? entry.name, isFolder: true });
|
|
12019
12046
|
}
|
|
12020
12047
|
} else if (entry.name.endsWith(".md")) {
|
|
12021
12048
|
const name = entry.name.replace(/\.md$/, "");
|
|
12022
|
-
const content =
|
|
12049
|
+
const content = readFileSync12(path14.join(SKILLS_DIR, entry.name), "utf-8");
|
|
12023
12050
|
const titleMatch = content.match(/^#\s+(.+)/m);
|
|
12024
12051
|
skills.push({ name, title: titleMatch?.[1] ?? name, isFolder: false });
|
|
12025
12052
|
}
|
|
@@ -12033,14 +12060,14 @@ function listSkills() {
|
|
|
12033
12060
|
function getSkillEntryPath(skillName) {
|
|
12034
12061
|
const folderPath = path14.join(SKILLS_DIR, skillName, "skill.md");
|
|
12035
12062
|
const filePath = path14.join(SKILLS_DIR, `${skillName}.md`);
|
|
12036
|
-
if (
|
|
12037
|
-
if (
|
|
12063
|
+
if (existsSync17(folderPath)) return folderPath;
|
|
12064
|
+
if (existsSync17(filePath)) return filePath;
|
|
12038
12065
|
return null;
|
|
12039
12066
|
}
|
|
12040
12067
|
function loadAgentDefs() {
|
|
12041
12068
|
try {
|
|
12042
|
-
if (
|
|
12043
|
-
const raw = JSON.parse(
|
|
12069
|
+
if (existsSync17(AGENTS_FILE)) {
|
|
12070
|
+
const raw = JSON.parse(readFileSync12(AGENTS_FILE, "utf-8"));
|
|
12044
12071
|
if (Array.isArray(raw.agents)) {
|
|
12045
12072
|
const saved = raw.agents;
|
|
12046
12073
|
const custom2 = saved.filter((a) => !a.isBuiltin);
|
|
@@ -12058,8 +12085,8 @@ function loadAgentDefs() {
|
|
|
12058
12085
|
function saveAgentDefs(agents) {
|
|
12059
12086
|
try {
|
|
12060
12087
|
const dir = path14.dirname(AGENTS_FILE);
|
|
12061
|
-
if (!
|
|
12062
|
-
|
|
12088
|
+
if (!existsSync17(dir)) mkdirSync13(dir, { recursive: true });
|
|
12089
|
+
writeFileSync12(AGENTS_FILE, JSON.stringify({ agents }, null, 2), "utf-8");
|
|
12063
12090
|
console.log(`[Gateway] Saved ${agents.length} agent definitions to ${AGENTS_FILE}`);
|
|
12064
12091
|
} catch (e) {
|
|
12065
12092
|
console.log(`[Gateway] Failed to save agents.json: ${e}`);
|
|
@@ -12069,8 +12096,8 @@ var agentDefs = [];
|
|
|
12069
12096
|
function detectDevServer(projectDir) {
|
|
12070
12097
|
try {
|
|
12071
12098
|
const pkgPath = path14.join(projectDir, "package.json");
|
|
12072
|
-
if (!
|
|
12073
|
-
const pkg = JSON.parse(
|
|
12099
|
+
if (!existsSync17(pkgPath)) return null;
|
|
12100
|
+
const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
|
|
12074
12101
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
12075
12102
|
if (allDeps["vite"]) return { cmd: "npx vite", port: 5173 };
|
|
12076
12103
|
if (allDeps["webpack-dev-server"]) return { cmd: "npx webpack serve", port: 8080 };
|
|
@@ -12205,7 +12232,7 @@ function handleCommand(parsed, meta) {
|
|
|
12205
12232
|
const entryPath = getSkillEntryPath(skillName);
|
|
12206
12233
|
if (entryPath) {
|
|
12207
12234
|
try {
|
|
12208
|
-
const content =
|
|
12235
|
+
const content = readFileSync12(entryPath, "utf-8");
|
|
12209
12236
|
skillContents.push(content);
|
|
12210
12237
|
} catch (e) {
|
|
12211
12238
|
console.log(`[Gateway] Failed to read skill file ${skillName}: ${e}`);
|
|
@@ -12223,6 +12250,7 @@ function handleCommand(parsed, meta) {
|
|
|
12223
12250
|
role: parsed.role,
|
|
12224
12251
|
personality,
|
|
12225
12252
|
backend: backendId,
|
|
12253
|
+
model: parsed.model ?? config.defaultModels[backendId],
|
|
12226
12254
|
palette: parsed.palette,
|
|
12227
12255
|
teamId: parsed.teamId,
|
|
12228
12256
|
workDir
|
|
@@ -12312,10 +12340,10 @@ ${text}]`;
|
|
|
12312
12340
|
}
|
|
12313
12341
|
case "UPLOAD_IMAGE": {
|
|
12314
12342
|
const imgDir = path14.join(config.defaultWorkspace, ".images");
|
|
12315
|
-
if (!
|
|
12343
|
+
if (!existsSync17(imgDir)) mkdirSync13(imgDir, { recursive: true });
|
|
12316
12344
|
const imgPath = path14.join(imgDir, parsed.filename);
|
|
12317
12345
|
try {
|
|
12318
|
-
|
|
12346
|
+
writeFileSync12(imgPath, Buffer.from(parsed.data, "base64"));
|
|
12319
12347
|
console.log(`[Gateway] UPLOAD_IMAGE: saved ${parsed.filename} (${Math.round(parsed.data.length * 0.75 / 1024)}KB)`);
|
|
12320
12348
|
publishEvent({ type: "IMAGE_UPLOADED", requestId: parsed.requestId, path: imgPath });
|
|
12321
12349
|
} catch (err) {
|
|
@@ -12331,7 +12359,7 @@ ${text}]`;
|
|
|
12331
12359
|
console.error(`[Gateway] Blocked OPEN_FILE: path "${raw}" resolves outside workspace`);
|
|
12332
12360
|
break;
|
|
12333
12361
|
}
|
|
12334
|
-
if (!
|
|
12362
|
+
if (!existsSync17(normalized)) {
|
|
12335
12363
|
console.error(`[Gateway] OPEN_FILE: path does not exist: ${normalized}`);
|
|
12336
12364
|
break;
|
|
12337
12365
|
}
|
|
@@ -12355,6 +12383,8 @@ ${text}]`;
|
|
|
12355
12383
|
}
|
|
12356
12384
|
let leadAgentId = null;
|
|
12357
12385
|
const teamId = `team-${nanoid6(6)}`;
|
|
12386
|
+
const autoNames = ["Alex", "Mia", "Leo", "Nova", "Luna", "Rex", "Kai", "Zoe", "Jay", "Sam"];
|
|
12387
|
+
const usedNames = /* @__PURE__ */ new Set();
|
|
12358
12388
|
for (const defId of allIds) {
|
|
12359
12389
|
const def = agentDefs.find((a) => a.id === defId);
|
|
12360
12390
|
if (!def) {
|
|
@@ -12367,9 +12397,15 @@ ${text}]`;
|
|
|
12367
12397
|
leadAgentId = agentId;
|
|
12368
12398
|
orc.setTeamLead(agentId);
|
|
12369
12399
|
}
|
|
12400
|
+
let agentName = def.name;
|
|
12401
|
+
const isShortName = agentName.length <= 10 && !agentName.includes(" ");
|
|
12402
|
+
if (!isShortName || usedNames.has(agentName.toLowerCase())) {
|
|
12403
|
+
agentName = autoNames.find((n) => !usedNames.has(n.toLowerCase())) ?? `Agent${usedNames.size + 1}`;
|
|
12404
|
+
}
|
|
12405
|
+
usedNames.add(agentName.toLowerCase());
|
|
12370
12406
|
orc.createAgent({
|
|
12371
12407
|
agentId,
|
|
12372
|
-
name:
|
|
12408
|
+
name: agentName,
|
|
12373
12409
|
role: def.skills ? `${def.role} \u2014 ${def.skills}` : def.role,
|
|
12374
12410
|
personality: def.personality,
|
|
12375
12411
|
backend: backendId,
|
|
@@ -12531,6 +12567,7 @@ ${text}]`;
|
|
|
12531
12567
|
name: ext.name,
|
|
12532
12568
|
role: ext.cwd ? ext.cwd.split("/").pop() ?? ext.backendId : ext.backendId,
|
|
12533
12569
|
isExternal: true,
|
|
12570
|
+
palette: ext.pid % 6,
|
|
12534
12571
|
pid: ext.pid,
|
|
12535
12572
|
cwd: ext.cwd ?? void 0,
|
|
12536
12573
|
startedAt: ext.startedAt,
|
|
@@ -12587,8 +12624,8 @@ ${text}]`;
|
|
|
12587
12624
|
const skillName = parsed.name.replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
|
|
12588
12625
|
if (!skillName) break;
|
|
12589
12626
|
const skillDir = path14.join(SKILLS_DIR, skillName);
|
|
12590
|
-
if (!
|
|
12591
|
-
|
|
12627
|
+
if (!existsSync17(skillDir)) mkdirSync13(skillDir, { recursive: true });
|
|
12628
|
+
writeFileSync12(path14.join(skillDir, "skill.md"), parsed.content, "utf-8");
|
|
12592
12629
|
console.log(`[Gateway] Saved skill: ${skillName}`);
|
|
12593
12630
|
publishEvent({ type: "SKILL_LIST", skills: listSkills() });
|
|
12594
12631
|
break;
|
|
@@ -12598,12 +12635,12 @@ ${text}]`;
|
|
|
12598
12635
|
const folderPath = path14.join(SKILLS_DIR, skillName);
|
|
12599
12636
|
const filePath = path14.join(SKILLS_DIR, `${skillName}.md`);
|
|
12600
12637
|
try {
|
|
12601
|
-
if (
|
|
12602
|
-
} else if (
|
|
12603
|
-
const files =
|
|
12638
|
+
if (existsSync17(folderPath) && !existsSync17(path14.join(folderPath, "skill.md"))) {
|
|
12639
|
+
} else if (existsSync17(folderPath)) {
|
|
12640
|
+
const files = readdirSync6(folderPath);
|
|
12604
12641
|
for (const f of files) unlinkSync3(path14.join(folderPath, f));
|
|
12605
12642
|
rmdirSync2(folderPath);
|
|
12606
|
-
} else if (
|
|
12643
|
+
} else if (existsSync17(filePath)) {
|
|
12607
12644
|
unlinkSync3(filePath);
|
|
12608
12645
|
}
|
|
12609
12646
|
console.log(`[Gateway] Deleted skill: ${skillName}`);
|
|
@@ -12613,6 +12650,29 @@ ${text}]`;
|
|
|
12613
12650
|
publishEvent({ type: "SKILL_LIST", skills: listSkills() });
|
|
12614
12651
|
break;
|
|
12615
12652
|
}
|
|
12653
|
+
case "SYNC_CHAT_HISTORY": {
|
|
12654
|
+
try {
|
|
12655
|
+
const chatFile = path14.join(config.instanceDir, "chat-history.json");
|
|
12656
|
+
const tmpFile = chatFile + ".tmp";
|
|
12657
|
+
writeFileSync12(tmpFile, parsed.data, "utf-8");
|
|
12658
|
+
renameSync5(tmpFile, chatFile);
|
|
12659
|
+
} catch (e) {
|
|
12660
|
+
console.warn(`[Gateway] Failed to save chat history: ${e}`);
|
|
12661
|
+
}
|
|
12662
|
+
break;
|
|
12663
|
+
}
|
|
12664
|
+
case "LOAD_CHAT_HISTORY": {
|
|
12665
|
+
try {
|
|
12666
|
+
const chatFile = path14.join(config.instanceDir, "chat-history.json");
|
|
12667
|
+
if (existsSync17(chatFile)) {
|
|
12668
|
+
const data = readFileSync12(chatFile, "utf-8");
|
|
12669
|
+
publishEvent({ type: "CHAT_HISTORY_LOADED", data });
|
|
12670
|
+
}
|
|
12671
|
+
} catch (e) {
|
|
12672
|
+
console.warn(`[Gateway] Failed to load chat history: ${e}`);
|
|
12673
|
+
}
|
|
12674
|
+
break;
|
|
12675
|
+
}
|
|
12616
12676
|
case "SUGGEST": {
|
|
12617
12677
|
const lastSuggest = suggestRateLimit.get(meta.clientId) ?? 0;
|
|
12618
12678
|
if (Date.now() - lastSuggest < SUGGEST_COOLDOWN_MS) {
|
|
@@ -12658,40 +12718,6 @@ ${text}]`;
|
|
|
12658
12718
|
}
|
|
12659
12719
|
break;
|
|
12660
12720
|
}
|
|
12661
|
-
case "UPDATE_AGENCY_AGENTS": {
|
|
12662
|
-
console.log("[Gateway] Updating agency agents...");
|
|
12663
|
-
const scriptPath = path14.join(path14.dirname(new URL(import.meta.url).pathname), "..", "..", "..", "scripts", "install-agents.sh");
|
|
12664
|
-
if (!existsSync16(scriptPath)) {
|
|
12665
|
-
console.warn("[Gateway] install-agents.sh not found \u2014 only available in git checkout");
|
|
12666
|
-
publishEvent({
|
|
12667
|
-
type: "AGENCY_AGENTS_UPDATED",
|
|
12668
|
-
success: false,
|
|
12669
|
-
message: "Agency agents update is only available when running from the git checkout (not the npm package)."
|
|
12670
|
-
});
|
|
12671
|
-
break;
|
|
12672
|
-
}
|
|
12673
|
-
execFile3("bash", [scriptPath, "--update"], { timeout: 6e4 }, (err, stdout, stderr) => {
|
|
12674
|
-
if (err) {
|
|
12675
|
-
console.error("[Gateway] Agency agents update failed:", stderr || err.message);
|
|
12676
|
-
publishEvent({
|
|
12677
|
-
type: "AGENCY_AGENTS_UPDATED",
|
|
12678
|
-
success: false,
|
|
12679
|
-
message: stderr || err.message
|
|
12680
|
-
});
|
|
12681
|
-
} else {
|
|
12682
|
-
const countMatch = stdout.match(/(\d+) agents/);
|
|
12683
|
-
const count = countMatch ? parseInt(countMatch[1], 10) : void 0;
|
|
12684
|
-
console.log("[Gateway] Agency agents updated:", stdout.trim().split("\n").pop());
|
|
12685
|
-
publishEvent({
|
|
12686
|
-
type: "AGENCY_AGENTS_UPDATED",
|
|
12687
|
-
success: true,
|
|
12688
|
-
message: `Agency agents updated successfully`,
|
|
12689
|
-
count
|
|
12690
|
-
});
|
|
12691
|
-
}
|
|
12692
|
-
});
|
|
12693
|
-
break;
|
|
12694
|
-
}
|
|
12695
12721
|
case "GET_CONFIG": {
|
|
12696
12722
|
const tgConnected = isChannelActive(telegramChannel);
|
|
12697
12723
|
sendToClient(meta.clientId, {
|
|
@@ -12772,20 +12798,20 @@ ${text}]`;
|
|
|
12772
12798
|
const sourceAgent = orc.getAgent(sourceAgentId);
|
|
12773
12799
|
const agentWorkDir = agentWorkDirs.get(sourceAgentId);
|
|
12774
12800
|
let cwd;
|
|
12775
|
-
if (agentWorkDir &&
|
|
12801
|
+
if (agentWorkDir && existsSync17(agentWorkDir)) {
|
|
12776
12802
|
if (projectDir && !path14.isAbsolute(projectDir)) {
|
|
12777
12803
|
const joined = path14.join(agentWorkDir, projectDir);
|
|
12778
|
-
cwd =
|
|
12804
|
+
cwd = existsSync17(joined) ? joined : agentWorkDir;
|
|
12779
12805
|
} else {
|
|
12780
12806
|
cwd = agentWorkDir;
|
|
12781
12807
|
}
|
|
12782
12808
|
} else if (projectDir) {
|
|
12783
12809
|
const absProjectDir = path14.isAbsolute(projectDir) ? projectDir : path14.join(config.defaultWorkspace, projectDir);
|
|
12784
|
-
cwd =
|
|
12810
|
+
cwd = existsSync17(absProjectDir) ? absProjectDir : config.defaultWorkspace;
|
|
12785
12811
|
} else {
|
|
12786
12812
|
cwd = config.defaultWorkspace;
|
|
12787
12813
|
}
|
|
12788
|
-
if (!path14.isAbsolute(cwd) || !
|
|
12814
|
+
if (!path14.isAbsolute(cwd) || !existsSync17(cwd)) cwd = config.defaultWorkspace;
|
|
12789
12815
|
const reviewerBackendId = reviewBackend ?? sourceAgent?.backend ?? config.defaultBackend;
|
|
12790
12816
|
let diff = "";
|
|
12791
12817
|
try {
|
|
@@ -12802,7 +12828,7 @@ ${text}]`;
|
|
|
12802
12828
|
for (const f of untrackedFiles) {
|
|
12803
12829
|
try {
|
|
12804
12830
|
const absPath = path14.isAbsolute(f) ? f : path14.join(cwd, f);
|
|
12805
|
-
const content =
|
|
12831
|
+
const content = readFileSync12(absPath, "utf-8");
|
|
12806
12832
|
const lines = content.split("\n");
|
|
12807
12833
|
const truncated = lines.length > 80 ? lines.slice(0, 80).join("\n") + `
|
|
12808
12834
|
... (${lines.length - 80} more lines)` : content;
|
|
@@ -12835,28 +12861,15 @@ ${diff}`;
|
|
|
12835
12861
|
}
|
|
12836
12862
|
const fileList = changedFiles.map((f) => `- ${f}`).join("\n");
|
|
12837
12863
|
const reviewPrompt = [
|
|
12838
|
-
`Review the code changes below. Focus on the DIFF
|
|
12839
|
-
|
|
12840
|
-
`Severity classification:`,
|
|
12841
|
-
`- CRITICAL: Bugs, crashes, security vulnerabilities, logic errors \u2014 must fix`,
|
|
12842
|
-
`- SUGGESTION: Style, naming, refactoring \u2014 optional, non-blocking`,
|
|
12843
|
-
``,
|
|
12844
|
-
`Rules:`,
|
|
12845
|
-
`- Base your review primarily on the diff. Only Read files if you need surrounding context to understand the change.`,
|
|
12846
|
-
`- Do NOT suggest renaming, refactoring, or style changes unless they cause actual bugs.`,
|
|
12847
|
-
`- Be concise. For each issue: file, line, severity, what's wrong, how to fix.`,
|
|
12864
|
+
`Review the code changes below. Focus on the DIFF for what changed, Read files only if you need surrounding context.`,
|
|
12865
|
+
`Only flag real bugs, crashes, security issues, logic errors. Skip style/naming suggestions.`,
|
|
12848
12866
|
``,
|
|
12849
12867
|
`Project: ${cwd}`,
|
|
12850
12868
|
`Files changed:
|
|
12851
12869
|
${fileList}`,
|
|
12852
12870
|
entryFile ? `Entry: ${entryFile}` : "",
|
|
12853
12871
|
summary ? `Summary: ${summary}` : "",
|
|
12854
|
-
diffSection
|
|
12855
|
-
``,
|
|
12856
|
-
`Output format:`,
|
|
12857
|
-
`VERDICT: PASS | FAIL`,
|
|
12858
|
-
`ISSUES: (numbered list with severity, file:line, description)`,
|
|
12859
|
-
`SUMMARY: (one sentence)`
|
|
12872
|
+
diffSection
|
|
12860
12873
|
].filter(Boolean).join("\n");
|
|
12861
12874
|
orc.createAgent({
|
|
12862
12875
|
agentId: reviewerAgentId,
|
|
@@ -12931,6 +12944,7 @@ async function main() {
|
|
|
12931
12944
|
}
|
|
12932
12945
|
}
|
|
12933
12946
|
const backendsToUse = getAllBackends();
|
|
12947
|
+
syncAgentDefs();
|
|
12934
12948
|
setSessionDir(config.instanceDir);
|
|
12935
12949
|
setStorageRoot(path14.join(config.instanceDir, "memory"));
|
|
12936
12950
|
console.log(`[Gateway] Instance "${config.gatewayId}" \u2192 ${config.instanceDir}`);
|
|
@@ -12961,6 +12975,7 @@ async function main() {
|
|
|
12961
12975
|
role: agent.role,
|
|
12962
12976
|
personality: agent.personality,
|
|
12963
12977
|
backend: agent.backend ?? config.defaultBackend,
|
|
12978
|
+
model: agent.model ?? config.defaultModels[agent.backend ?? config.defaultBackend],
|
|
12964
12979
|
palette: agent.palette,
|
|
12965
12980
|
teamId: agent.teamId,
|
|
12966
12981
|
resumeHistory: true,
|
|
@@ -13000,7 +13015,7 @@ async function main() {
|
|
|
13000
13015
|
console.log(`[Gateway] Marked leader ${t.leadAgentId} as hasExecuted (was in ${t.phase} phase)`);
|
|
13001
13016
|
}
|
|
13002
13017
|
if (t.projectDir) {
|
|
13003
|
-
if (
|
|
13018
|
+
if (existsSync17(t.projectDir)) {
|
|
13004
13019
|
orc.setTeamProjectDir(t.projectDir);
|
|
13005
13020
|
} else {
|
|
13006
13021
|
console.warn(`[Gateway] Project dir does not exist: ${t.projectDir} \u2014 team will need a new project dir`);
|
|
@@ -13105,6 +13120,7 @@ async function main() {
|
|
|
13105
13120
|
name: displayName,
|
|
13106
13121
|
role: agent.cwd ? agent.cwd.split("/").pop() ?? agent.backendId : agent.backendId,
|
|
13107
13122
|
isExternal: true,
|
|
13123
|
+
palette: agent.pid % 6,
|
|
13108
13124
|
pid: agent.pid,
|
|
13109
13125
|
cwd: agent.cwd ?? void 0,
|
|
13110
13126
|
startedAt: agent.startedAt,
|
|
@@ -13164,7 +13180,7 @@ async function main() {
|
|
|
13164
13180
|
startTunnel();
|
|
13165
13181
|
console.log("[Gateway] Listening for commands...");
|
|
13166
13182
|
console.log("[Gateway] Press 'p' + Enter to generate a new pair code");
|
|
13167
|
-
if (process.env.NODE_ENV !== "development" && !process.env.NO_OPEN &&
|
|
13183
|
+
if (process.env.NODE_ENV !== "development" && !process.env.NO_OPEN && existsSync17(config.webDir)) {
|
|
13168
13184
|
const url = `http://localhost:${config.wsPort}`;
|
|
13169
13185
|
console.log(`[Gateway] Opening ${url}`);
|
|
13170
13186
|
execFile3("open", [url]);
|