@voybio/ace-swarm 0.2.3 → 0.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/README.md +21 -11
- package/assets/.agents/ACE/ACE-Init/AGENTS.md +7 -1
- package/assets/.agents/ACE/orchestrator/AGENTS.md +4 -1
- package/assets/.agents/skills/eval-harness/SKILL.md +14 -0
- package/assets/.agents/skills/handoff-lint/SKILL.md +14 -0
- package/assets/.agents/skills/incident-commander/SKILL.md +14 -0
- package/assets/.agents/skills/memory-curator/SKILL.md +14 -0
- package/assets/.agents/skills/release-sentry/SKILL.md +14 -0
- package/assets/.agents/skills/risk-quant/SKILL.md +14 -0
- package/assets/.agents/skills/schema-forge/SKILL.md +14 -0
- package/assets/.agents/skills/state-auditor/SKILL.md +14 -0
- package/assets/agent-state/MODULES/gates/gate-correctness.json +1 -1
- package/dist/cli.js +128 -66
- package/dist/helpers.d.ts +3 -1
- package/dist/helpers.js +49 -31
- package/dist/local-model-runtime.js +6 -51
- package/dist/store/bootstrap-store.d.ts +1 -0
- package/dist/store/bootstrap-store.js +14 -27
- package/dist/store/cache-workspace.d.ts +22 -0
- package/dist/store/cache-workspace.js +143 -0
- package/dist/store/materializers/context-snapshot-materializer.js +1 -6
- package/dist/tools-agent.js +69 -58
- package/dist/tools-framework.js +121 -47
- package/dist/tui/index.js +3 -3
- package/dist/tui/local-model-contract.js +7 -25
- package/dist/tui/provider-discovery.d.ts +6 -0
- package/dist/tui/provider-discovery.js +84 -9
- package/package.json +1 -1
package/dist/tools-agent.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Agent, skill, kernel, and task-pack tool registrations.
|
|
3
3
|
*/
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import { ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, classifyPathSource, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, isSwarmRole, listAvailableSkills, readAgentInstructions, readAgentManifest, readKernelArtifact, readSkillInstructions, readTaskArtifact, resolveWritableTaskPath, safeWrite, } from "./helpers.js";
|
|
5
|
+
import { ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, classifyPathSource, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, isSwarmRole, listAvailableSkills, readAgentInstructions, readAgentManifest, readKernelArtifact, readSkillInstructions, readTaskArtifact, resolveWorkspaceRoot, resolveWritableTaskPath, safeWrite, } from "./helpers.js";
|
|
6
6
|
import { loadRuntimeProfile, readRuntimePromptTemplate, readRuntimeProfileState, validateRuntimeProfileContent, } from "./runtime-profile.js";
|
|
7
7
|
import { getUnattendedSession, listUnattendedSessions, startUnattendedSession, stopUnattendedSession, validateRuntimeExecutorSessionRegistryContent, waitForUnattendedSession, } from "./runtime-executor.js";
|
|
8
8
|
import { executeRuntimeTool, listRuntimeToolSpecs, loadRuntimeToolRegistry, validateRuntimeToolRegistryContent, } from "./runtime-tool-specs.js";
|
|
@@ -52,25 +52,6 @@ function extractToolTextContent(result) {
|
|
|
52
52
|
.filter(Boolean)
|
|
53
53
|
.join("\n");
|
|
54
54
|
}
|
|
55
|
-
function normalizeRoleCandidate(input) {
|
|
56
|
-
if (!input)
|
|
57
|
-
return undefined;
|
|
58
|
-
const normalized = input.trim().toLowerCase().replace(/^ace-/, "").replace(/[^a-z0-9]+/g, "");
|
|
59
|
-
const candidate = normalized === "coder" ? "coders" : normalized;
|
|
60
|
-
return ROLE_ENUM.options.includes(candidate)
|
|
61
|
-
? candidate
|
|
62
|
-
: undefined;
|
|
63
|
-
}
|
|
64
|
-
function parseRoleFromRoutingSummary(summary) {
|
|
65
|
-
const match = summary.match(/\*\*Primary Swarm Agent\(s\):\*\*\s*([^\n]+)/i);
|
|
66
|
-
if (!match?.[1])
|
|
67
|
-
return undefined;
|
|
68
|
-
const firstAgent = match[1]
|
|
69
|
-
.split(",")
|
|
70
|
-
.map((entry) => entry.trim())
|
|
71
|
-
.find(Boolean);
|
|
72
|
-
return normalizeRoleCandidate(firstAgent);
|
|
73
|
-
}
|
|
74
55
|
function mapRoleToTaskType(role) {
|
|
75
56
|
switch (role) {
|
|
76
57
|
case "vos":
|
|
@@ -91,15 +72,25 @@ function extractHandoffId(text) {
|
|
|
91
72
|
return lineMatch?.[1];
|
|
92
73
|
}
|
|
93
74
|
async function buildOrchestratorSteps(task, sessionId) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return [{ role: routedRole, task }];
|
|
75
|
+
void sessionId;
|
|
76
|
+
return [{ role: "orchestrator", task }];
|
|
97
77
|
}
|
|
98
78
|
function appendUniqueNote(target, note) {
|
|
99
79
|
if (!target.includes(note)) {
|
|
100
80
|
target.push(note);
|
|
101
81
|
}
|
|
102
82
|
}
|
|
83
|
+
function createToolOnlyBridgeResult(step, reason) {
|
|
84
|
+
return {
|
|
85
|
+
bridge_id: `tool-only-${step.step_id}-${Date.now()}`,
|
|
86
|
+
role: step.role,
|
|
87
|
+
status: "completed",
|
|
88
|
+
summary: `Tool-only orchestrator completion for ${step.step_id} (${step.role}): ${step.task}. ${reason}`,
|
|
89
|
+
turns: 0,
|
|
90
|
+
tool_calls: [],
|
|
91
|
+
child_results: [],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
103
94
|
function buildDefaultOrchestratorAmendment(input) {
|
|
104
95
|
if (input.result.status !== "completed" || input.step.role !== "coders") {
|
|
105
96
|
return undefined;
|
|
@@ -566,9 +557,9 @@ export function registerAgentTools(server) {
|
|
|
566
557
|
],
|
|
567
558
|
};
|
|
568
559
|
});
|
|
569
|
-
server.tool("run_local_model", "Offload a governed ACE subtask to
|
|
570
|
-
task: z.string().describe("Task to execute with the
|
|
571
|
-
role: ROLE_ENUM.optional().describe("Optional ACE role; defaults to
|
|
560
|
+
server.tool("run_local_model", "Offload a governed ACE subtask to the provider-backed ACE bridge and return the result", {
|
|
561
|
+
task: z.string().describe("Task to execute with the ACE model bridge"),
|
|
562
|
+
role: ROLE_ENUM.optional().describe("Optional ACE role; defaults to orchestrator"),
|
|
572
563
|
max_turns: z
|
|
573
564
|
.number()
|
|
574
565
|
.int()
|
|
@@ -582,15 +573,15 @@ export function registerAgentTools(server) {
|
|
|
582
573
|
provider: z
|
|
583
574
|
.string()
|
|
584
575
|
.optional()
|
|
585
|
-
.describe("Optional provider override; otherwise discovered from
|
|
576
|
+
.describe("Optional provider override; otherwise discovered from workspace/runtime context"),
|
|
586
577
|
model: z
|
|
587
578
|
.string()
|
|
588
579
|
.optional()
|
|
589
|
-
.describe("Optional model override; otherwise discovered from
|
|
580
|
+
.describe("Optional model override; otherwise discovered from workspace/runtime context"),
|
|
590
581
|
base_url: z
|
|
591
582
|
.string()
|
|
592
583
|
.optional()
|
|
593
|
-
.describe("Optional
|
|
584
|
+
.describe("Optional provider base URL override"),
|
|
594
585
|
ollama_url: z
|
|
595
586
|
.string()
|
|
596
587
|
.optional()
|
|
@@ -621,7 +612,7 @@ export function registerAgentTools(server) {
|
|
|
621
612
|
{
|
|
622
613
|
type: "text",
|
|
623
614
|
text: [
|
|
624
|
-
"##
|
|
615
|
+
"## Delegated Run",
|
|
625
616
|
`- role: ${delegated.role}`,
|
|
626
617
|
`- provider: ${delegated.runtime.provider}`,
|
|
627
618
|
`- model: ${delegated.runtime.model}`,
|
|
@@ -655,7 +646,7 @@ export function registerAgentTools(server) {
|
|
|
655
646
|
],
|
|
656
647
|
};
|
|
657
648
|
});
|
|
658
|
-
server.tool("run_orchestrator", "Execute a supervised plan via model bridge child runs; when steps are omitted,
|
|
649
|
+
server.tool("run_orchestrator", "Execute a supervised plan via model bridge child runs; when steps are omitted, the plan starts with ACE-Orchestrator", {
|
|
659
650
|
task: z.string().describe("The task to decompose and execute"),
|
|
660
651
|
steps: z
|
|
661
652
|
.array(z.object({
|
|
@@ -675,7 +666,7 @@ export function registerAgentTools(server) {
|
|
|
675
666
|
.describe("Optional ACE tool allowlist for the step"),
|
|
676
667
|
}))
|
|
677
668
|
.optional()
|
|
678
|
-
.describe("Pre-defined steps; if omitted, the orchestrator
|
|
669
|
+
.describe("Pre-defined steps; if omitted, the orchestrator starts with a single ACE-Orchestrator step"),
|
|
679
670
|
execution_mode: z
|
|
680
671
|
.enum(["sequential", "scheduled"])
|
|
681
672
|
.optional()
|
|
@@ -689,15 +680,15 @@ export function registerAgentTools(server) {
|
|
|
689
680
|
provider: z
|
|
690
681
|
.string()
|
|
691
682
|
.optional()
|
|
692
|
-
.describe("Optional provider override; otherwise discovered from
|
|
683
|
+
.describe("Optional provider override; otherwise discovered from workspace/runtime context"),
|
|
693
684
|
model: z
|
|
694
685
|
.string()
|
|
695
686
|
.optional()
|
|
696
|
-
.describe("Optional model override; otherwise discovered from
|
|
687
|
+
.describe("Optional model override; otherwise discovered from workspace/runtime context"),
|
|
697
688
|
base_url: z
|
|
698
689
|
.string()
|
|
699
690
|
.optional()
|
|
700
|
-
.describe("Optional
|
|
691
|
+
.describe("Optional provider base URL override"),
|
|
701
692
|
ollama_url: z
|
|
702
693
|
.string()
|
|
703
694
|
.optional()
|
|
@@ -707,15 +698,25 @@ export function registerAgentTools(server) {
|
|
|
707
698
|
.optional()
|
|
708
699
|
.describe("Optional workspace root override; defaults to the active workspace"),
|
|
709
700
|
}, async ({ task, steps, execution_mode, max_turns_per_step, provider, model, base_url, ollama_url, workspace_root }, extra) => {
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
701
|
+
let runtime;
|
|
702
|
+
const runtimeWarnings = [];
|
|
703
|
+
try {
|
|
704
|
+
runtime = resolveLocalModelRuntime({
|
|
705
|
+
workspaceRoot: workspace_root,
|
|
706
|
+
provider,
|
|
707
|
+
model,
|
|
708
|
+
baseUrl: base_url,
|
|
709
|
+
ollamaUrl: ollama_url,
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
catch (error) {
|
|
713
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
714
|
+
appendUniqueNote(runtimeWarnings, `Model bridge runtime unavailable; continuing in tool-only mode. ${message}`);
|
|
715
|
+
}
|
|
716
|
+
const effectiveWorkspaceRoot = runtime?.workspaceRoot ??
|
|
717
|
+
(workspace_root ? resolveRuntimeWorkspaceRoot(workspace_root) : resolveWorkspaceRoot());
|
|
717
718
|
const sessionId = typeof extra?.sessionId === "string" ? extra.sessionId : undefined;
|
|
718
|
-
const planSource = Array.isArray(steps) && steps.length > 0 ? "explicit_steps" : "
|
|
719
|
+
const planSource = Array.isArray(steps) && steps.length > 0 ? "explicit_steps" : "orchestrator_default_step";
|
|
719
720
|
const planSteps = Array.isArray(steps) && steps.length > 0
|
|
720
721
|
? steps
|
|
721
722
|
: await buildOrchestratorSteps(task, sessionId);
|
|
@@ -724,20 +725,27 @@ export function registerAgentTools(server) {
|
|
|
724
725
|
steps: planSteps,
|
|
725
726
|
execution_mode: execution_mode ?? "sequential",
|
|
726
727
|
});
|
|
727
|
-
const bridge =
|
|
728
|
+
const bridge = runtime
|
|
729
|
+
? new ModelBridge(createDefaultModelBridgeClients(runtime))
|
|
730
|
+
: undefined;
|
|
728
731
|
const fallbackHandoffPrefix = `LOCAL-${plan.plan_id}-`;
|
|
729
732
|
const vericifyWarnings = [];
|
|
730
733
|
const supervised = await superviseTaskPlan(plan, {
|
|
731
734
|
async spawnStep(step) {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
735
|
+
if (bridge && runtime) {
|
|
736
|
+
return bridge.spawn({
|
|
737
|
+
task: step.task,
|
|
738
|
+
role: step.role,
|
|
739
|
+
workspace: runtime.workspaceRoot,
|
|
740
|
+
maxTurns: max_turns_per_step ?? 6,
|
|
741
|
+
provider: runtime.provider,
|
|
742
|
+
model: runtime.model,
|
|
743
|
+
toolScope: step.tool_scope,
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
const reason = runtimeWarnings[0] ??
|
|
747
|
+
"No local model provider/runtime was resolved for model bridge execution.";
|
|
748
|
+
return createToolOnlyBridgeResult(step, reason);
|
|
741
749
|
},
|
|
742
750
|
async createHandoff({ step, plan: activePlan }) {
|
|
743
751
|
const created = await executeAceInternalTool("create_handoff", {
|
|
@@ -776,13 +784,13 @@ export function registerAgentTools(server) {
|
|
|
776
784
|
},
|
|
777
785
|
async getVericifyContext() {
|
|
778
786
|
return tryVericifyPacket(() => getVericifyContextPacket({
|
|
779
|
-
workspaceRoot:
|
|
787
|
+
workspaceRoot: effectiveWorkspaceRoot,
|
|
780
788
|
}), (message) => appendUniqueNote(vericifyWarnings, `Vericify context unavailable for ${plan.plan_id}: ${message}`));
|
|
781
789
|
},
|
|
782
790
|
async getVericifyDelta(since) {
|
|
783
791
|
return tryVericifyPacket(() => getVericifyDelta({
|
|
784
792
|
since,
|
|
785
|
-
workspaceRoot:
|
|
793
|
+
workspaceRoot: effectiveWorkspaceRoot,
|
|
786
794
|
}), (message) => appendUniqueNote(vericifyWarnings, `Vericify delta unavailable for ${plan.plan_id}: ${message}`));
|
|
787
795
|
},
|
|
788
796
|
async openCircuitBreaker(reason) {
|
|
@@ -838,10 +846,13 @@ export function registerAgentTools(server) {
|
|
|
838
846
|
{
|
|
839
847
|
type: "text",
|
|
840
848
|
text: JSON.stringify({
|
|
841
|
-
runtime,
|
|
849
|
+
runtime: runtime ?? null,
|
|
850
|
+
execution_backend: runtime ? "model_bridge" : "tool_only",
|
|
851
|
+
runtime_warnings: runtimeWarnings,
|
|
852
|
+
workspace_root: effectiveWorkspaceRoot,
|
|
842
853
|
plan_source: planSource,
|
|
843
|
-
planning_note: planSource === "
|
|
844
|
-
? "Auto-planning currently
|
|
854
|
+
planning_note: planSource === "orchestrator_default_step"
|
|
855
|
+
? "Auto-planning currently starts with ACE-Orchestrator. Pass explicit steps for multi-step orchestration."
|
|
845
856
|
: null,
|
|
846
857
|
plan: supervised.plan,
|
|
847
858
|
step_summaries,
|
package/dist/tools-framework.js
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { bootstrapStoreWorkspace } from "./store/bootstrap-store.js";
|
|
7
|
-
import { ACE_ROOT_REL, ACE_TASKS_ROOT_REL, ALL_MCP_CLIENTS, ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, WORKSPACE_ROOT, classifyPathSource, detectAssetDrift, getAllMcpServerConfigSnippets, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, getMcpClientInstallHint, getMcpServerConfigSnippet, getTaskArtifactPath, isSwarmRole, listAvailableSkills, normalizePathForValidation, safeRead, safeWrite, withFileLock, wsPath, } from "./helpers.js";
|
|
7
|
+
import { ACE_ROOT_REL, ACE_TASKS_ROOT_REL, ALL_MCP_CLIENTS, ALL_LLM_PROVIDERS, ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, WORKSPACE_ROOT, classifyPathSource, detectAssetDrift, getAllMcpServerConfigSnippets, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, getMcpClientInstallHint, getMcpServerConfigSnippet, getTaskArtifactPath, isSwarmRole, listAvailableSkills, normalizePathForValidation, resolveWorkspaceRoot, safeRead, safeWrite, withFileLock, wsPath, } from "./helpers.js";
|
|
8
8
|
import { getRoleTitle, MCP_CLIENT_ENUM, scoreDomains, } from "./shared.js";
|
|
9
|
-
import {
|
|
9
|
+
import { defaultModelForProvider, } from "./tui/provider-discovery.js";
|
|
10
10
|
import { refreshAstgrepIndex } from "./astgrep-index.js";
|
|
11
11
|
import { scanWorkspaceDelta } from "./index-store.js";
|
|
12
12
|
import { getOrRefreshKanbanSnapshot } from "./kanban.js";
|
|
@@ -20,6 +20,7 @@ import { auditPublicSurface } from "./public-surface.js";
|
|
|
20
20
|
import { auditStoreAuthority, writeStoreAuthorityAuditReport, } from "./store/store-authority-audit.js";
|
|
21
21
|
import { PROVENANCE_CRITICAL_EVENT_TYPES, validateArtifactManifestPayload, validateProvenanceLogContent, validateTealConfigContent, } from "./schemas.js";
|
|
22
22
|
import { readAceTaskContractAssessment } from "./ace-autonomy.js";
|
|
23
|
+
import { listStoreKeysSync, readStoreBlobSync } from "./store/store-snapshot.js";
|
|
23
24
|
function getArtifactManifestEntries(payload) {
|
|
24
25
|
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
25
26
|
return [];
|
|
@@ -38,15 +39,37 @@ function getArtifactManifestEntries(payload) {
|
|
|
38
39
|
}
|
|
39
40
|
return [];
|
|
40
41
|
}
|
|
42
|
+
function parseGateManifest(raw, sourceRef) {
|
|
43
|
+
try {
|
|
44
|
+
const gate = JSON.parse(raw);
|
|
45
|
+
const id = typeof gate.id === "string" ? gate.id.trim() : "";
|
|
46
|
+
if (!id)
|
|
47
|
+
return undefined;
|
|
48
|
+
const type = gate.type === "executable" || gate.type === "artifact_scan" || gate.type === "manual_review"
|
|
49
|
+
? gate.type
|
|
50
|
+
: "manual_review";
|
|
51
|
+
return {
|
|
52
|
+
id,
|
|
53
|
+
type,
|
|
54
|
+
invariant: typeof gate.invariant === "string" ? gate.invariant : "",
|
|
55
|
+
command: typeof gate.command === "string" ? gate.command : "",
|
|
56
|
+
evidence_requirement: typeof gate.evidence_requirement === "string" ? gate.evidence_requirement : "",
|
|
57
|
+
source_ref: sourceRef,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
41
64
|
function readGateManifests(gatesDir) {
|
|
42
65
|
const files = readdirSync(gatesDir).filter((f) => f.endsWith(".json"));
|
|
43
66
|
const allGates = [];
|
|
44
67
|
for (const file of files) {
|
|
45
68
|
try {
|
|
46
69
|
const raw = readFileSync(resolve(gatesDir, file), "utf-8");
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
allGates.push(
|
|
70
|
+
const parsed = parseGateManifest(raw, `agent-state/MODULES/gates/${file}`);
|
|
71
|
+
if (parsed)
|
|
72
|
+
allGates.push(parsed);
|
|
50
73
|
}
|
|
51
74
|
catch {
|
|
52
75
|
/* skip corrupt manifests */
|
|
@@ -54,6 +77,44 @@ function readGateManifests(gatesDir) {
|
|
|
54
77
|
}
|
|
55
78
|
return allGates;
|
|
56
79
|
}
|
|
80
|
+
function readStoreGateManifests(workspaceRoot) {
|
|
81
|
+
const gateKeys = listStoreKeysSync(workspaceRoot, "knowledge/gates/").filter((key) => key.endsWith(".json"));
|
|
82
|
+
const allGates = [];
|
|
83
|
+
for (const key of gateKeys) {
|
|
84
|
+
const raw = readStoreBlobSync(workspaceRoot, key);
|
|
85
|
+
if (typeof raw !== "string")
|
|
86
|
+
continue;
|
|
87
|
+
const parsed = parseGateManifest(raw, key);
|
|
88
|
+
if (parsed)
|
|
89
|
+
allGates.push(parsed);
|
|
90
|
+
}
|
|
91
|
+
return allGates;
|
|
92
|
+
}
|
|
93
|
+
function resolveGateManifests(gatesDir) {
|
|
94
|
+
if (existsSync(gatesDir)) {
|
|
95
|
+
const workspaceGates = readGateManifests(gatesDir);
|
|
96
|
+
if (workspaceGates.length > 0) {
|
|
97
|
+
return { gates: workspaceGates, source: "workspace" };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const storeGates = readStoreGateManifests(resolveWorkspaceRoot());
|
|
101
|
+
if (storeGates.length > 0) {
|
|
102
|
+
return { gates: storeGates, source: "store" };
|
|
103
|
+
}
|
|
104
|
+
return { gates: [], source: "none" };
|
|
105
|
+
}
|
|
106
|
+
function hasArtifactEvidence(reference) {
|
|
107
|
+
const normalized = reference.trim();
|
|
108
|
+
if (!normalized)
|
|
109
|
+
return false;
|
|
110
|
+
const candidates = [wsPath("agent-state", normalized), wsPath(normalized)];
|
|
111
|
+
if (candidates.some((candidate) => existsSync(candidate)))
|
|
112
|
+
return true;
|
|
113
|
+
return candidates.some((candidate) => {
|
|
114
|
+
const content = safeRead(candidate);
|
|
115
|
+
return !content.startsWith("[FILE NOT FOUND]") && !content.startsWith("[ACCESS DENIED]");
|
|
116
|
+
});
|
|
117
|
+
}
|
|
57
118
|
function evaluateGateTargets(targets) {
|
|
58
119
|
const results = [];
|
|
59
120
|
for (const gate of targets) {
|
|
@@ -97,7 +158,7 @@ function evaluateGateTargets(targets) {
|
|
|
97
158
|
}
|
|
98
159
|
else {
|
|
99
160
|
for (const artifact of relevantArtifacts) {
|
|
100
|
-
if (!
|
|
161
|
+
if (!hasArtifactEvidence(artifact)) {
|
|
101
162
|
missing.push(artifact);
|
|
102
163
|
}
|
|
103
164
|
}
|
|
@@ -109,11 +170,9 @@ function evaluateGateTargets(targets) {
|
|
|
109
170
|
.map((s) => s.trim())
|
|
110
171
|
.filter(Boolean);
|
|
111
172
|
for (const ref of evidenceFiles) {
|
|
112
|
-
|
|
113
|
-
const found = candidates.some((candidate) => existsSync(candidate));
|
|
114
|
-
if (!found) {
|
|
173
|
+
if (!hasArtifactEvidence(ref)) {
|
|
115
174
|
const asFile = ref.replace(/\s+/g, "_").replace(/[^a-zA-Z0-9_./-]/g, "");
|
|
116
|
-
const fileFound =
|
|
175
|
+
const fileFound = hasArtifactEvidence(asFile);
|
|
117
176
|
if (!fileFound)
|
|
118
177
|
missing.push(ref);
|
|
119
178
|
}
|
|
@@ -289,7 +348,7 @@ export function registerFrameworkTools(server) {
|
|
|
289
348
|
}
|
|
290
349
|
const routingMap = {
|
|
291
350
|
venture: {
|
|
292
|
-
swarm_agents: ["
|
|
351
|
+
swarm_agents: ["orchestrator"],
|
|
293
352
|
subagents: [
|
|
294
353
|
"astgrep",
|
|
295
354
|
"research",
|
|
@@ -298,11 +357,11 @@ export function registerFrameworkTools(server) {
|
|
|
298
357
|
"skeptic",
|
|
299
358
|
"ops",
|
|
300
359
|
],
|
|
301
|
-
pipeline: "
|
|
302
|
-
prompt: "ace-
|
|
360
|
+
pipeline: "Orchestrator -> VOS/UI/Coders as needed with composable Research/Spec/Skeptic/Ops support",
|
|
361
|
+
prompt: "ace-orchestrator",
|
|
303
362
|
},
|
|
304
363
|
ux: {
|
|
305
|
-
swarm_agents: ["
|
|
364
|
+
swarm_agents: ["orchestrator"],
|
|
306
365
|
subagents: [
|
|
307
366
|
"astgrep",
|
|
308
367
|
"research",
|
|
@@ -313,11 +372,11 @@ export function registerFrameworkTools(server) {
|
|
|
313
372
|
"skeptic",
|
|
314
373
|
"ops",
|
|
315
374
|
],
|
|
316
|
-
pipeline: "
|
|
317
|
-
prompt: "ace-
|
|
375
|
+
pipeline: "Orchestrator -> UI/Coders with composable Spec/Builder/QA and Skeptic/Ops sidecars",
|
|
376
|
+
prompt: "ace-orchestrator",
|
|
318
377
|
},
|
|
319
378
|
engineering: {
|
|
320
|
-
swarm_agents: ["
|
|
379
|
+
swarm_agents: ["orchestrator"],
|
|
321
380
|
subagents: [
|
|
322
381
|
"astgrep",
|
|
323
382
|
"spec",
|
|
@@ -331,8 +390,8 @@ export function registerFrameworkTools(server) {
|
|
|
331
390
|
"skeptic",
|
|
332
391
|
"ops",
|
|
333
392
|
],
|
|
334
|
-
pipeline: "Coders with composable Spec -> Builder -> QA -> Docs and Skeptic/Ops guards",
|
|
335
|
-
prompt: "ace-
|
|
393
|
+
pipeline: "Orchestrator -> Coders with composable Spec -> Builder -> QA -> Docs and Skeptic/Ops guards",
|
|
394
|
+
prompt: "ace-orchestrator",
|
|
336
395
|
},
|
|
337
396
|
mixed: {
|
|
338
397
|
swarm_agents: ["orchestrator"],
|
|
@@ -486,7 +545,8 @@ export function registerFrameworkTools(server) {
|
|
|
486
545
|
`**Primary Swarm Agent(s):** ${activeRoute.swarm_agents
|
|
487
546
|
.map((agent) => `ACE-${getRoleTitle(agent)}`)
|
|
488
547
|
.join(", ")}`,
|
|
489
|
-
"**
|
|
548
|
+
"**Default Entry Agent:** ACE-Orchestrator",
|
|
549
|
+
"**Hierarchy Rule:** Top-level work starts with ACE-Orchestrator. VOS, UI, and Coders are delegated specialists, not peer replacements.",
|
|
490
550
|
`**Preflight Owner:** ACE-Orchestrator`,
|
|
491
551
|
`**Task Contract:** ${taskContract.ok ? "aligned" : "attention required"}`,
|
|
492
552
|
`**Composable Subagents (Universal):** ${[...COMPOSABLE_AGENTS].join(", ")}`,
|
|
@@ -523,7 +583,7 @@ export function registerFrameworkTools(server) {
|
|
|
523
583
|
};
|
|
524
584
|
});
|
|
525
585
|
// ── Bootstrap ─────────────────────────────────────────────────────
|
|
526
|
-
server.tool("bootstrap_state", "Bootstrap ACE framework files (state, tasks, instructions, skills, scripts, MCP configs, optional
|
|
586
|
+
server.tool("bootstrap_state", "Bootstrap ACE framework files (state, tasks, instructions, skills, scripts, MCP configs, optional runtime profile)", {
|
|
527
587
|
project_name: z
|
|
528
588
|
.string()
|
|
529
589
|
.optional()
|
|
@@ -541,18 +601,28 @@ export function registerFrameworkTools(server) {
|
|
|
541
601
|
.optional()
|
|
542
602
|
.describe("Write minimal workspace host stubs (AGENTS.md, CLAUDE.md, .cursorrules, .github/copilot-instructions.md)"),
|
|
543
603
|
llm_provider: z
|
|
544
|
-
.enum(
|
|
604
|
+
.enum(ALL_LLM_PROVIDERS)
|
|
605
|
+
.optional()
|
|
606
|
+
.describe("Optional LLM runtime provider to scaffold"),
|
|
607
|
+
llm_model: z
|
|
608
|
+
.string()
|
|
609
|
+
.optional()
|
|
610
|
+
.describe("Model name for generated runtime profile"),
|
|
611
|
+
llm_base_url: z
|
|
612
|
+
.string()
|
|
545
613
|
.optional()
|
|
546
|
-
.describe("
|
|
614
|
+
.describe("Runtime base URL for generated provider profile"),
|
|
547
615
|
ollama_model: z
|
|
548
616
|
.string()
|
|
549
617
|
.optional()
|
|
550
|
-
.describe("
|
|
618
|
+
.describe("Legacy alias for llm_model"),
|
|
551
619
|
ollama_base_url: z
|
|
552
620
|
.string()
|
|
553
621
|
.optional()
|
|
554
|
-
.describe("
|
|
555
|
-
}, async ({ project_name, force, include_mcp_config, include_client_config_bundle, llm_provider, ollama_model, ollama_base_url, }) => {
|
|
622
|
+
.describe("Legacy alias for llm_base_url"),
|
|
623
|
+
}, async ({ project_name, force, include_mcp_config, include_client_config_bundle, llm_provider, llm_model, llm_base_url, ollama_model, ollama_base_url, }) => {
|
|
624
|
+
const resolvedLlmModel = llm_model ?? ollama_model;
|
|
625
|
+
const resolvedLlmBaseUrl = llm_base_url ?? ollama_base_url;
|
|
556
626
|
// Store-first bootstrap — initializes ace-state.ace, bakes host bundles into store,
|
|
557
627
|
// and optionally materializes minimal workspace stubs.
|
|
558
628
|
const storeResult = await bootstrapStoreWorkspace({
|
|
@@ -562,8 +632,8 @@ export function registerFrameworkTools(server) {
|
|
|
562
632
|
includeMcpConfig: include_mcp_config,
|
|
563
633
|
includeClientConfigBundle: include_client_config_bundle,
|
|
564
634
|
llm: llm_provider ?? undefined,
|
|
565
|
-
model:
|
|
566
|
-
|
|
635
|
+
model: resolvedLlmModel ?? undefined,
|
|
636
|
+
baseUrl: resolvedLlmBaseUrl ?? undefined,
|
|
567
637
|
});
|
|
568
638
|
const astIndex = refreshAstgrepIndex({
|
|
569
639
|
scope: ".",
|
|
@@ -601,8 +671,8 @@ export function registerFrameworkTools(server) {
|
|
|
601
671
|
materialized: storeResult.materialized.length,
|
|
602
672
|
force: Boolean(force),
|
|
603
673
|
llm_provider: llm_provider ?? null,
|
|
604
|
-
llm_model:
|
|
605
|
-
llm_base_url:
|
|
674
|
+
llm_model: resolvedLlmModel ?? null,
|
|
675
|
+
llm_base_url: resolvedLlmBaseUrl ?? null,
|
|
606
676
|
indexed_files: delta.snapshot.file_count,
|
|
607
677
|
index_truncated: delta.truncated,
|
|
608
678
|
ast_index_scope: astIndex.scope,
|
|
@@ -645,10 +715,13 @@ export function registerFrameworkTools(server) {
|
|
|
645
715
|
...(llm_provider
|
|
646
716
|
? [
|
|
647
717
|
"",
|
|
648
|
-
"##
|
|
718
|
+
"## LLM Runtime Profile",
|
|
649
719
|
`- provider: ${llm_provider}`,
|
|
650
|
-
`- model: ${
|
|
651
|
-
`- base_url: ${
|
|
720
|
+
`- model: ${resolvedLlmModel ?? defaultModelForProvider(llm_provider)}`,
|
|
721
|
+
`- base_url: ${resolvedLlmBaseUrl ??
|
|
722
|
+
(llm_provider === "ollama" || llm_provider === "llama.cpp"
|
|
723
|
+
? "discover via ace doctor --scan or set explicitly"
|
|
724
|
+
: "optional; use provider defaults or set explicitly")}`,
|
|
652
725
|
`- profile_path: ${storeResult.storePath}#state/runtime/llm_profile`,
|
|
653
726
|
`- doctor_path: ${storeResult.storePath}#state/runtime/doctor_checks.md`,
|
|
654
727
|
]
|
|
@@ -1335,31 +1408,27 @@ export function registerFrameworkTools(server) {
|
|
|
1335
1408
|
.describe("Optional short focus string persisted with skeptic adversarial review evidence."),
|
|
1336
1409
|
}, async ({ gate_ids, review_mode, review_focus }) => {
|
|
1337
1410
|
const gatesDir = wsPath("agent-state", "MODULES", "gates");
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
{
|
|
1342
|
-
type: "text",
|
|
1343
|
-
text: "❌ Gates directory not found: agent-state/MODULES/gates/",
|
|
1344
|
-
},
|
|
1345
|
-
],
|
|
1346
|
-
};
|
|
1347
|
-
}
|
|
1348
|
-
const allGates = readGateManifests(gatesDir);
|
|
1411
|
+
const resolved = resolveGateManifests(gatesDir);
|
|
1412
|
+
const allGates = resolved.gates;
|
|
1413
|
+
const gateEvidenceRef = resolved.source === "store" ? "knowledge/gates/*" : "agent-state/MODULES/gates/";
|
|
1349
1414
|
// Filter to requested gates (or run all)
|
|
1350
1415
|
const targets = gate_ids
|
|
1351
1416
|
? allGates.filter((g) => gate_ids.includes(g.id))
|
|
1352
1417
|
: allGates;
|
|
1353
1418
|
if (targets.length === 0) {
|
|
1419
|
+
const noGateMessage = allGates.length === 0
|
|
1420
|
+
? "❌ No gate manifests found in agent-state/MODULES/gates/ or ace-state.ace knowledge/gates/*."
|
|
1421
|
+
: `❌ No matching gates found. Available: ${allGates.map((g) => g.id).join(", ")}`;
|
|
1354
1422
|
return {
|
|
1355
1423
|
content: [
|
|
1356
1424
|
{
|
|
1357
1425
|
type: "text",
|
|
1358
|
-
text:
|
|
1426
|
+
text: noGateMessage,
|
|
1359
1427
|
},
|
|
1360
1428
|
],
|
|
1361
1429
|
};
|
|
1362
1430
|
}
|
|
1431
|
+
const gateArtifactRefs = targets.map((gate) => gate.source_ref ?? gateEvidenceRef);
|
|
1363
1432
|
const results = evaluateGateTargets(targets);
|
|
1364
1433
|
const passed = results.filter((r) => r.ok).length;
|
|
1365
1434
|
const failed = results.filter((r) => !r.ok).length;
|
|
@@ -1387,7 +1456,8 @@ export function registerFrameworkTools(server) {
|
|
|
1387
1456
|
})),
|
|
1388
1457
|
passed,
|
|
1389
1458
|
failed,
|
|
1390
|
-
evidence_ref: evidence?.evidenceRef ??
|
|
1459
|
+
evidence_ref: evidence?.evidenceRef ?? gateEvidenceRef,
|
|
1460
|
+
gate_manifest_source: resolved.source,
|
|
1391
1461
|
...(review
|
|
1392
1462
|
? {
|
|
1393
1463
|
review: {
|
|
@@ -1414,13 +1484,14 @@ export function registerFrameworkTools(server) {
|
|
|
1414
1484
|
? `Gate execution with skeptic review: ${review.summary.confirmed_count} confirmed findings`
|
|
1415
1485
|
: `Gate execution: ${passed}/${results.length} passed`,
|
|
1416
1486
|
artifacts: [
|
|
1417
|
-
...
|
|
1487
|
+
...gateArtifactRefs,
|
|
1418
1488
|
...(evidence ? ["agent-state/EVIDENCE_LOG.md"] : []),
|
|
1419
1489
|
],
|
|
1420
1490
|
metadata: {
|
|
1421
1491
|
passed,
|
|
1422
1492
|
failed,
|
|
1423
1493
|
gate_ids: results.map((r) => r.id),
|
|
1494
|
+
gate_manifest_source: resolved.source,
|
|
1424
1495
|
...(review
|
|
1425
1496
|
? {
|
|
1426
1497
|
review_mode: review.mode,
|
|
@@ -1446,6 +1517,9 @@ export function registerFrameworkTools(server) {
|
|
|
1446
1517
|
: allOk
|
|
1447
1518
|
? `✅ All gates passed: ${passed}/${results.length}`
|
|
1448
1519
|
: `❌ Gate failures: ${failed}/${results.length} failed`,
|
|
1520
|
+
`Gate manifest source: ${resolved.source === "store"
|
|
1521
|
+
? "ace-state.ace (knowledge/gates/*)"
|
|
1522
|
+
: "agent-state/MODULES/gates/"}`,
|
|
1449
1523
|
`Run ledger: ${ledger.path} (${ledger.entry.id})`,
|
|
1450
1524
|
...(evidence ? [`Evidence: ${evidence.path} (${evidence.evidenceRef})`] : []),
|
|
1451
1525
|
"",
|
package/dist/tui/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import { OpenAICompatibleClient, diagnoseChatRuntimeConfig, } from "./openai-com
|
|
|
17
17
|
import { detectColorLevel, write, cursor, screen, fg, style } from "./renderer.js";
|
|
18
18
|
import { ALL_AGENTS, WORKSPACE_ROOT } from "../helpers.js";
|
|
19
19
|
import { backfillHandoffsIntoScheduler } from "../tools-handoff.js";
|
|
20
|
-
import { DEFAULT_OLLAMA_MODEL, inferProviderFromModel, normalizeLocalBaseUrl, } from "./provider-discovery.js";
|
|
20
|
+
import { DEFAULT_OLLAMA_MODEL, defaultModelForProvider, inferProviderFromModel, normalizeLocalBaseUrl, } from "./provider-discovery.js";
|
|
21
21
|
import { resolveAceStateLayout } from "../ace-state-resolver.js";
|
|
22
22
|
import { withLocalModelRuntimeRepository, } from "../store/repositories/local-model-runtime-repository.js";
|
|
23
23
|
const DASHBOARD_CONTROLS = ["provider", "model", "chat", "logs", "refresh"];
|
|
@@ -56,7 +56,7 @@ export class AceTui {
|
|
|
56
56
|
const workspaceRoot = options.workspaceRoot ?? WORKSPACE_ROOT;
|
|
57
57
|
this.workspaceRoot = workspaceRoot;
|
|
58
58
|
this.provider = this.normalizeProvider(options.provider ?? inferProviderFromModel(options.model) ?? "ollama") ?? "ollama";
|
|
59
|
-
this.model = (options.model ??
|
|
59
|
+
this.model = (options.model ?? defaultModelForProvider(this.provider)).trim();
|
|
60
60
|
// Initialize modules
|
|
61
61
|
const colorLevel = detectColorLevel();
|
|
62
62
|
for (const [provider, baseUrl] of Object.entries(options.providerBaseUrls ?? {})) {
|
|
@@ -758,7 +758,7 @@ export class AceTui {
|
|
|
758
758
|
this.model = DEFAULT_OLLAMA_MODEL;
|
|
759
759
|
}
|
|
760
760
|
else {
|
|
761
|
-
this.model =
|
|
761
|
+
this.model = defaultModelForProvider(this.provider);
|
|
762
762
|
}
|
|
763
763
|
this.config.set("model", this.model);
|
|
764
764
|
this.telemetry.setModel(this.model);
|