@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
|
@@ -28,24 +28,8 @@ function extractStatusField(statusRaw, label) {
|
|
|
28
28
|
const match = statusRaw.match(pattern);
|
|
29
29
|
return match?.[1] ? clip(oneLine(match[1])) : undefined;
|
|
30
30
|
}
|
|
31
|
-
function determineRole(
|
|
32
|
-
|
|
33
|
-
if (preferredRole && preferredRole !== "orchestrator") {
|
|
34
|
-
return preferredRole;
|
|
35
|
-
}
|
|
36
|
-
if (/\b(doc|docs|readme|changelog|guide)\b/.test(lowered))
|
|
37
|
-
return "docs";
|
|
38
|
-
if (/\b(test|qa|verify|regression|assert|review)\b/.test(lowered))
|
|
39
|
-
return "qa";
|
|
40
|
-
if (/\b(ui|design|layout|ux|css|frontend)\b/.test(lowered))
|
|
41
|
-
return "ui";
|
|
42
|
-
if (/\b(research|investigate|compare|audit|analyze|analysis)\b/.test(lowered))
|
|
43
|
-
return "research";
|
|
44
|
-
if (/\b(spec|schema|contract|interface)\b/.test(lowered))
|
|
45
|
-
return "spec";
|
|
46
|
-
if (/\b(build|implement|fix|patch|code|refactor|wire|edit)\b/.test(lowered))
|
|
47
|
-
return "coders";
|
|
48
|
-
return "orchestrator";
|
|
31
|
+
function determineRole(preferredRole) {
|
|
32
|
+
return preferredRole?.trim() || "orchestrator";
|
|
49
33
|
}
|
|
50
34
|
export function shouldSynthesizeShortPlan(task) {
|
|
51
35
|
const lowered = task.toLowerCase();
|
|
@@ -103,17 +87,15 @@ export function buildAcePreflightPacket(input) {
|
|
|
103
87
|
? "thin"
|
|
104
88
|
: "healthy";
|
|
105
89
|
const preflightState = blockers.length > 0 ? "blocked" : warnings.length > 0 || blockedByStatus ? "attention_required" : "ready";
|
|
106
|
-
const recommendedRole = determineRole(input.
|
|
90
|
+
const recommendedRole = determineRole(input.preferredRole);
|
|
107
91
|
const synthesize = shouldSynthesizeShortPlan(input.task);
|
|
108
92
|
const recommendedNextAction = preflightState === "blocked"
|
|
109
93
|
? "validate_framework"
|
|
110
94
|
: synthesize
|
|
111
95
|
? "run_orchestrator"
|
|
112
|
-
:
|
|
113
|
-
? "
|
|
114
|
-
:
|
|
115
|
-
? "route_task"
|
|
116
|
-
: "recall_context";
|
|
96
|
+
: recommendedRole === "orchestrator"
|
|
97
|
+
? "run_orchestrator"
|
|
98
|
+
: "recall_context";
|
|
117
99
|
return {
|
|
118
100
|
session_id: input.sessionId,
|
|
119
101
|
workspace_root: input.workspaceRoot,
|
|
@@ -154,7 +136,7 @@ export function buildStartupNudge(preflight, ledger) {
|
|
|
154
136
|
const text = action === "validate_framework"
|
|
155
137
|
? "ACE state is incomplete. Run validate_framework before free-form execution."
|
|
156
138
|
: action === "run_orchestrator"
|
|
157
|
-
? "
|
|
139
|
+
? "Start with run_orchestrator so ACE-Orchestrator can route the work."
|
|
158
140
|
: action === "route_task"
|
|
159
141
|
? "Role selection is still ambiguous. Route the task before deeper work."
|
|
160
142
|
: "Load ACE context first with recall_context before deeper work.";
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
*/
|
|
15
15
|
export declare const DEFAULT_OLLAMA_MODEL = "llama3.1:8b";
|
|
16
16
|
export declare const DEFAULT_LLAMA_CPP_MODEL = "local-model";
|
|
17
|
+
export declare const LOCAL_LLM_PROVIDERS: readonly ["ollama", "llama.cpp"];
|
|
18
|
+
export type LocalLlmProvider = (typeof LOCAL_LLM_PROVIDERS)[number];
|
|
17
19
|
export interface ProviderDiscoveryOptions {
|
|
18
20
|
workspaceRoot: string;
|
|
19
21
|
cliProvider?: string;
|
|
@@ -53,6 +55,10 @@ export declare function normalizeProvider(input: string | undefined): string | u
|
|
|
53
55
|
export declare function normalizeLocalBaseUrl(url: string | undefined): string | undefined;
|
|
54
56
|
export declare function buildOpenAiCompatibleBaseUrl(baseUrl: string): string;
|
|
55
57
|
export declare function inferProviderFromModel(model: string | undefined): string | undefined;
|
|
58
|
+
export declare function isLocalLlmProvider(providerInput: string | undefined): providerInput is LocalLlmProvider;
|
|
59
|
+
export declare function defaultModelForProvider(providerInput: string | undefined): string;
|
|
60
|
+
export declare function providerEnvPrefix(providerInput: string | undefined): string;
|
|
61
|
+
export declare function buildProviderDoctorCommands(providerInput: string | undefined, modelInput: string | undefined, baseUrlInput?: string): string[];
|
|
56
62
|
export declare function parseJsoncLoose(raw: string): unknown;
|
|
57
63
|
export declare function discoverProviderContext(options: ProviderDiscoveryOptions): ProviderDiscoveryResult;
|
|
58
64
|
export declare function scanLocalModelRuntimes(options?: LocalRuntimeScanOptions): Promise<LocalRuntimeScanResult>;
|
|
@@ -18,7 +18,14 @@ import { join, resolve } from "node:path";
|
|
|
18
18
|
import { readStoreJsonSync } from "../store/store-snapshot.js";
|
|
19
19
|
export const DEFAULT_OLLAMA_MODEL = "llama3.1:8b";
|
|
20
20
|
export const DEFAULT_LLAMA_CPP_MODEL = "local-model";
|
|
21
|
-
const
|
|
21
|
+
const DEFAULT_HOSTED_MODELS = {
|
|
22
|
+
codex: "gpt-5",
|
|
23
|
+
claude: "claude-3-7-sonnet",
|
|
24
|
+
gemini: "gemini-2.5-pro",
|
|
25
|
+
copilot: "copilot/gpt-5-mini",
|
|
26
|
+
};
|
|
27
|
+
export const LOCAL_LLM_PROVIDERS = ["ollama", "llama.cpp"];
|
|
28
|
+
const LOCAL_RUNTIME_PROVIDER_PREFERENCE = LOCAL_LLM_PROVIDERS;
|
|
22
29
|
const PROVIDER_PREFERENCE = [
|
|
23
30
|
...LOCAL_RUNTIME_PROVIDER_PREFERENCE,
|
|
24
31
|
"codex",
|
|
@@ -95,12 +102,69 @@ export function inferProviderFromModel(model) {
|
|
|
95
102
|
}
|
|
96
103
|
return undefined;
|
|
97
104
|
}
|
|
98
|
-
function
|
|
99
|
-
|
|
105
|
+
export function isLocalLlmProvider(providerInput) {
|
|
106
|
+
const provider = normalizeProvider(providerInput);
|
|
107
|
+
return provider === "ollama" || provider === "llama.cpp";
|
|
108
|
+
}
|
|
109
|
+
export function defaultModelForProvider(providerInput) {
|
|
110
|
+
const provider = normalizeProvider(providerInput);
|
|
111
|
+
if (provider === "ollama" || !provider)
|
|
100
112
|
return DEFAULT_OLLAMA_MODEL;
|
|
101
113
|
if (provider === "llama.cpp")
|
|
102
114
|
return DEFAULT_LLAMA_CPP_MODEL;
|
|
103
|
-
return
|
|
115
|
+
return DEFAULT_HOSTED_MODELS[provider] ?? DEFAULT_HOSTED_MODELS.codex;
|
|
116
|
+
}
|
|
117
|
+
export function providerEnvPrefix(providerInput) {
|
|
118
|
+
const provider = normalizeProvider(providerInput);
|
|
119
|
+
if (!provider)
|
|
120
|
+
return "LLM";
|
|
121
|
+
if (provider === "llama.cpp")
|
|
122
|
+
return "LLAMA_CPP";
|
|
123
|
+
return provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_");
|
|
124
|
+
}
|
|
125
|
+
export function buildProviderDoctorCommands(providerInput, modelInput, baseUrlInput) {
|
|
126
|
+
const provider = normalizeProvider(providerInput) ?? "ollama";
|
|
127
|
+
const model = modelInput?.trim() || defaultModelForProvider(provider);
|
|
128
|
+
const baseUrl = normalizeLocalBaseUrl(baseUrlInput);
|
|
129
|
+
if (provider === "ollama") {
|
|
130
|
+
return [
|
|
131
|
+
"ollama serve",
|
|
132
|
+
`ollama pull ${model}`,
|
|
133
|
+
...(baseUrl ? [`curl -s ${baseUrl}/api/tags`] : []),
|
|
134
|
+
baseUrl
|
|
135
|
+
? `ace doctor --llm ${provider} --model ${model} --base-url ${baseUrl}`
|
|
136
|
+
: `ace doctor --llm ${provider} --model ${model} --scan`,
|
|
137
|
+
];
|
|
138
|
+
}
|
|
139
|
+
if (provider === "llama.cpp") {
|
|
140
|
+
return [
|
|
141
|
+
"# Start llama-server separately, for example:",
|
|
142
|
+
"# llama-server -m /path/to/model.gguf --port 8080",
|
|
143
|
+
...(baseUrl ? [`curl -s ${buildOpenAiCompatibleBaseUrl(baseUrl)}/models`] : []),
|
|
144
|
+
baseUrl
|
|
145
|
+
? `ace doctor --llm ${provider} --model ${model} --base-url ${baseUrl}`
|
|
146
|
+
: `ace doctor --llm ${provider} --model ${model} --scan`,
|
|
147
|
+
];
|
|
148
|
+
}
|
|
149
|
+
if (provider === "codex") {
|
|
150
|
+
return [
|
|
151
|
+
"export OPENAI_API_KEY=<token>",
|
|
152
|
+
...(baseUrl ? [`export OPENAI_BASE_URL=${baseUrl}`] : []),
|
|
153
|
+
`ace doctor --llm ${provider} --model ${model}${baseUrl ? ` --base-url ${baseUrl}` : ""}`,
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
if (provider === "copilot") {
|
|
157
|
+
return [
|
|
158
|
+
"gh auth login # or export GITHUB_TOKEN=<token>",
|
|
159
|
+
`ace doctor --llm ${provider} --model ${model}`,
|
|
160
|
+
];
|
|
161
|
+
}
|
|
162
|
+
const prefix = providerEnvPrefix(provider);
|
|
163
|
+
return [
|
|
164
|
+
`export ${prefix}_BASE_URL=${baseUrl ?? "<openai-compatible-base-url>"}`,
|
|
165
|
+
`export ${prefix}_API_KEY=<token>`,
|
|
166
|
+
`ace doctor --llm ${provider} --model ${model}${baseUrl ? ` --base-url ${baseUrl}` : ""}`,
|
|
167
|
+
];
|
|
104
168
|
}
|
|
105
169
|
function looksLikeModel(value) {
|
|
106
170
|
const v = value.trim().toLowerCase();
|
|
@@ -326,6 +390,8 @@ export function discoverProviderContext(options) {
|
|
|
326
390
|
process.env.LLM_MODEL?.trim() ||
|
|
327
391
|
undefined;
|
|
328
392
|
const envGenericBaseUrl = normalizeLocalBaseUrl(process.env.ACE_TUI_BASE_URL ?? process.env.ACE_LLM_BASE_URL ?? process.env.LLM_BASE_URL);
|
|
393
|
+
const openAiBaseUrl = normalizeLocalBaseUrl(process.env.OPENAI_BASE_URL);
|
|
394
|
+
const genericBaseUrl = envGenericBaseUrl ?? openAiBaseUrl;
|
|
329
395
|
const cliProvider = normalizeProvider(options.cliProvider);
|
|
330
396
|
const cliModel = options.cliModel?.trim() || undefined;
|
|
331
397
|
const cliBaseUrl = normalizeLocalBaseUrl(options.cliBaseUrl ?? options.cliOllamaUrl);
|
|
@@ -355,9 +421,18 @@ export function discoverProviderContext(options) {
|
|
|
355
421
|
inferProviderFromModel(profileModel);
|
|
356
422
|
}
|
|
357
423
|
if (!provider) {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
424
|
+
const genericOpenAiSignals = Boolean(genericBaseUrl) ||
|
|
425
|
+
Boolean(process.env.OPENAI_API_KEY?.trim()) ||
|
|
426
|
+
Boolean(process.env.CODEX_API_KEY?.trim());
|
|
427
|
+
if (genericOpenAiSignals) {
|
|
428
|
+
provider = "codex";
|
|
429
|
+
notes.push("runtime_default=codex (generic OpenAI-compatible env detected)");
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
provider = "ollama";
|
|
433
|
+
if (settingHints.length > 0) {
|
|
434
|
+
notes.push("runtime_default=ollama (VS Code model hints are discovery-only)");
|
|
435
|
+
}
|
|
361
436
|
}
|
|
362
437
|
}
|
|
363
438
|
setProviderBaseUrl(providerBaseUrls, profileProvider, profileBaseUrl);
|
|
@@ -366,8 +441,8 @@ export function discoverProviderContext(options) {
|
|
|
366
441
|
if (!providerBaseUrls.has(provider) && cliBaseUrl) {
|
|
367
442
|
providerBaseUrls.set(provider, cliBaseUrl);
|
|
368
443
|
}
|
|
369
|
-
if (!providerBaseUrls.has(provider) &&
|
|
370
|
-
providerBaseUrls.set(provider,
|
|
444
|
+
if (!providerBaseUrls.has(provider) && genericBaseUrl) {
|
|
445
|
+
providerBaseUrls.set(provider, genericBaseUrl);
|
|
371
446
|
}
|
|
372
447
|
if (!providerBaseUrls.has(provider) && profileBaseUrl && profileProvider === provider) {
|
|
373
448
|
providerBaseUrls.set(provider, profileBaseUrl);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voybio/ace-swarm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "ACE Framework MCP server and CLI — single-file ACEPACK state, local-model serving, agent orchestration, and host compliance enforcement.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|