refactor: rombak arsitektur file ke modular clean-arch (vertikal per-feature)
Organisasi ulang layer-first (domain/application/infrastructure) menjadi vertikal per-feature, behavior tidak berubah: - src/shared/domain/ -> fondasi bersama (ex-domain/core): message, provider, tool_call, tool_result, store, error, usage, conversation - src/features/agent/ -> LLM turn loop: domain (TurnEvent, AgentTurnParams) + application (turn_service, ports) + infrastructure (llm LlmClient + tools) - src/features/cms/ -> settings/conversation/memory persistence: domain + application (services) + infrastructure (persistence repos) - src/features/subagent/ -> orchestration: domain (AccessTier) + infrastructure (engine runner, context, provider, delegate, spawn_tools) - src/features/workflow/ -> multi-phase + hive-mind: domain + infrastructure - src/interfaces/ -> cli + tui (outer ring) tetap Subagent-runner (engine.ts runAgent, division.ts toolsFor) dipindah ke features/subagent (bukan agent tools) utk memutus coupling agent<->subagent. Alias tsconfig: @zesdex/domain -> shared/domain, + @zesdex/agent, @zesdex/agent-infra, @zesdex/cms, @zesdex/subagent, @zesdex/workflow, @zesdex/shared. Bersihkan dead: application/ports PasswordService/TokenService/AuthService. compose.ts (composition root) & bootstrap repoint ke barrel feature. Gates: tsc --noEmit 0 error, bun test 70 pass/0 fail, bun build 147 modules, ./dist/zesdex --headless -> real turn OK.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Parallel delegation tool — splits a large task into sub-tasks that run
|
||||
* concurrently across multiple subagents. Mirrors `tools/parallel_delegate.rs`.
|
||||
*/
|
||||
import type { JsonValue } from "@zesdex/domain";
|
||||
import { type Tool, type ToolCtx } from "./mod.ts";
|
||||
import { argStr, optBool, optInt } from "./util.ts";
|
||||
|
||||
/** Delegate a large task to multiple subagents running in parallel. */
|
||||
export class ParallelDelegate implements Tool {
|
||||
name = "parallel_delegate";
|
||||
description = "Delegate a large task to multiple subagents running in parallel for 3x faster completion";
|
||||
|
||||
parameters = {
|
||||
type: "object",
|
||||
properties: {
|
||||
task: { type: "string", description: "The task to be split and delegated to parallel agents" },
|
||||
directives: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
directive: { type: "string" },
|
||||
access: { type: "string", enum: ["read", "write", "full"] },
|
||||
},
|
||||
required: ["directive"],
|
||||
},
|
||||
},
|
||||
synthesize: { type: "boolean", default: true },
|
||||
max_parallel: { type: "integer", default: 3, description: "Maximum number of parallel agents (default: 3, max: 8)" },
|
||||
},
|
||||
required: ["task"],
|
||||
};
|
||||
|
||||
async run(ctx: ToolCtx, args: JsonValue): Promise<string> {
|
||||
const task = argStr(args, "task");
|
||||
const synthesize = optBool(args, "synthesize", true);
|
||||
const maxParallel = Math.min(optInt(args, "max_parallel", 3), 8);
|
||||
|
||||
let directives: Array<{ directive: string; access: string }>;
|
||||
const explicit = args && typeof args === "object" && !Array.isArray(args)
|
||||
? (args as Record<string, JsonValue>).directives
|
||||
: undefined;
|
||||
if (Array.isArray(explicit)) {
|
||||
directives = explicit
|
||||
.filter((d): d is Record<string, JsonValue> => typeof d === "object" && d !== null)
|
||||
.map((d) => ({
|
||||
directive: typeof d.directive === "string" ? d.directive : "",
|
||||
access: typeof d.access === "string" ? d.access : "write",
|
||||
}))
|
||||
.filter((d) => d.directive !== "");
|
||||
} else {
|
||||
directives = fallbackSplit(task, maxParallel);
|
||||
}
|
||||
|
||||
if (directives.length === 0) {
|
||||
throw new Error("no directives could be derived for the task");
|
||||
}
|
||||
|
||||
// Delegate to subagent engine if available, else report the breakdown.
|
||||
try {
|
||||
const { runParallelDelegation } = await import("../../../subagent/infrastructure/delegate.ts");
|
||||
return await runParallelDelegation(task, directives, synthesize, ctx);
|
||||
} catch (e) {
|
||||
const msg = (e as Error).message;
|
||||
if (msg.includes("not yet") || msg.includes("Cannot find")) {
|
||||
let out = `## Parallel Delegation Complete\n\n**Task:** ${task}\n**Parallel agents:** ${directives.length}\n\n`;
|
||||
directives.forEach((d, i) => { out += `---\n### Agent ${i}: [${d.access}]\n\n${d.directive}\n`; });
|
||||
return out;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Fallback splitting when LLM is unavailable. */
|
||||
function fallbackSplit(task: string, maxParallel: number): Array<{ directive: string; access: string }> {
|
||||
const directives: Array<{ directive: string; access: string }> = [];
|
||||
if (task.includes("backend") || task.includes("api") || task.includes("server")) {
|
||||
directives.push({ directive: `Implement the backend/API components for: ${task}`, access: "write" });
|
||||
}
|
||||
if (task.includes("frontend") || task.includes("ui") || task.includes("client")) {
|
||||
directives.push({ directive: `Implement the frontend/UI components for: ${task}`, access: "write" });
|
||||
}
|
||||
if (task.includes("test") || task.includes("unit")) {
|
||||
directives.push({ directive: `Write unit tests for: ${task}`, access: "read" });
|
||||
}
|
||||
if (directives.length === 0) {
|
||||
for (let i = 0; i < maxParallel; i++) {
|
||||
directives.push({ directive: `Part ${i + 1} of parallel task: ${task}`, access: "write" });
|
||||
}
|
||||
}
|
||||
return directives.slice(0, maxParallel);
|
||||
}
|
||||
Reference in New Issue
Block a user