@voybio/ace-swarm 2.4.0 → 2.4.1
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/CHANGELOG.md +8 -0
- package/README.md +1 -0
- package/assets/.agents/ACE/agent-qa/instructions.md +11 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json +43 -0
- package/assets/agent-state/runtime-tool-specs.json +70 -2
- package/assets/instructions/ACE_Coder.instructions.md +13 -0
- package/assets/instructions/ACE_UI.instructions.md +11 -0
- package/dist/ace-context.js +70 -11
- package/dist/ace-internal-tools.d.ts +3 -1
- package/dist/ace-internal-tools.js +10 -2
- package/dist/agent-runtime/role-adapters.d.ts +18 -1
- package/dist/agent-runtime/role-adapters.js +49 -5
- package/dist/astgrep-index.d.ts +48 -0
- package/dist/astgrep-index.js +126 -1
- package/dist/cli.js +205 -15
- package/dist/discovery-runtime-wrappers.d.ts +108 -0
- package/dist/discovery-runtime-wrappers.js +615 -0
- package/dist/helpers/bootstrap.js +1 -1
- package/dist/helpers/constants.d.ts +2 -2
- package/dist/helpers/constants.js +7 -0
- package/dist/helpers/path-utils.d.ts +8 -1
- package/dist/helpers/path-utils.js +27 -8
- package/dist/helpers/store-resolution.js +7 -3
- package/dist/job-scheduler.js +30 -4
- package/dist/json-sanitizer.d.ts +16 -0
- package/dist/json-sanitizer.js +26 -0
- package/dist/local-model-policy.d.ts +27 -0
- package/dist/local-model-policy.js +84 -0
- package/dist/local-model-runtime.d.ts +6 -0
- package/dist/local-model-runtime.js +21 -20
- package/dist/model-bridge.d.ts +6 -1
- package/dist/model-bridge.js +338 -21
- package/dist/orchestrator-supervisor.d.ts +42 -0
- package/dist/orchestrator-supervisor.js +110 -3
- package/dist/plan-proposal.d.ts +115 -0
- package/dist/plan-proposal.js +1073 -0
- package/dist/runtime-executor.d.ts +6 -1
- package/dist/runtime-executor.js +72 -5
- package/dist/runtime-tool-specs.d.ts +19 -1
- package/dist/runtime-tool-specs.js +67 -26
- package/dist/schemas.js +29 -1
- package/dist/server.js +51 -0
- package/dist/shared.d.ts +1 -0
- package/dist/shared.js +2 -0
- package/dist/store/bootstrap-store.d.ts +1 -0
- package/dist/store/bootstrap-store.js +8 -2
- package/dist/store/repositories/local-model-runtime-repository.d.ts +1 -1
- package/dist/store/repositories/local-model-runtime-repository.js +1 -1
- package/dist/store/repositories/vericify-repository.d.ts +1 -1
- package/dist/tools-agent.d.ts +20 -0
- package/dist/tools-agent.js +538 -28
- package/dist/tools-discovery.js +135 -0
- package/dist/tools-files.js +768 -66
- package/dist/tools-framework.js +80 -61
- package/dist/tui/index.js +10 -1
- package/dist/tui/ollama.d.ts +8 -1
- package/dist/tui/ollama.js +53 -12
- package/dist/tui/openai-compatible.d.ts +13 -0
- package/dist/tui/openai-compatible.js +305 -5
- package/dist/tui/provider-discovery.d.ts +1 -0
- package/dist/tui/provider-discovery.js +35 -11
- package/dist/vericify-bridge.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.4.0] - 2026-05-02
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Added `ace connect` so users can register an explicit local or hosted runtime profile without ACE inventing a local model preset.
|
|
8
|
+
- Updated local runtime bootstrap and doctor guidance to avoid hardcoded `llama.cpp` model defaults when the user has not supplied one.
|
|
9
|
+
- Added a Copilot CLI `.mcp.json` projection to `ace preconfig` while preserving the existing `.vscode/mcp.json` bridge.
|
|
10
|
+
|
|
3
11
|
## [2.3.0] - 2026-03-28
|
|
4
12
|
|
|
5
13
|
### Added
|
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ Modern coding agents can already read files, write code, run commands, and call
|
|
|
20
20
|
ACE provides model providers with the context they cannot infer on their own: task state, tool surfaces, status events, evidence trails, and the next move in the loop.
|
|
21
21
|
|
|
22
22
|
- `ace init --llm <provider>` records the selected runtime profile in the store.
|
|
23
|
+
- `ace connect` records an explicit runtime profile from a user-chosen local runtime endpoint or hosted provider without inventing a local model preset.
|
|
23
24
|
- `ace doctor` validates local or hosted runtime wiring, checks the selected model when the provider exposes listings, and keeps the runtime honest.
|
|
24
25
|
- `ace doctor --scan` probes common Ollama and llama.cpp endpoints and writes the selected profile back into the store.
|
|
25
26
|
- `ace tui` is provider-aware for `ollama`, `llama.cpp`, `codex`, `claude`, `gemini`, and `copilot` when credentials or base URLs are configured.
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
applyTo: 'agent-qa'
|
|
3
3
|
---
|
|
4
|
+
<!-- ACE Bridge Contract — high salience: this block takes precedence over all directives below -->
|
|
5
|
+
## ACE Bridge Contract (Non-Negotiable)
|
|
6
|
+
|
|
7
|
+
**Short structured verdict:** Your completion summary must be a concise structured verdict — pass/fail counts, gate status, and failure classification. Do NOT reproduce file content, rewrite artifacts, or include large code blocks.
|
|
8
|
+
|
|
9
|
+
**Read-only enforcement:** Do not modify, rewrite, or improve the artifacts you inspect. If an artifact has a bug, classify it and route it — do not fix it inline.
|
|
10
|
+
|
|
11
|
+
**No artifact drift:** If you find yourself generating large code blocks or reproducing the full content of an inspected file, stop immediately and restate as a short verdict summary instead.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
4
15
|
# agent-qa Execution Instructions
|
|
5
16
|
|
|
6
17
|
## Operating Objective
|
|
@@ -108,6 +108,46 @@
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
|
+
"mcp_server": {
|
|
112
|
+
"type": "object",
|
|
113
|
+
"additionalProperties": false,
|
|
114
|
+
"required": [
|
|
115
|
+
"transport"
|
|
116
|
+
],
|
|
117
|
+
"properties": {
|
|
118
|
+
"transport": {
|
|
119
|
+
"type": "string",
|
|
120
|
+
"enum": [
|
|
121
|
+
"stdio",
|
|
122
|
+
"http"
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
"command": {
|
|
126
|
+
"type": "string"
|
|
127
|
+
},
|
|
128
|
+
"args": {
|
|
129
|
+
"type": "array",
|
|
130
|
+
"items": {
|
|
131
|
+
"type": "string"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"url": {
|
|
135
|
+
"type": "string"
|
|
136
|
+
},
|
|
137
|
+
"env": {
|
|
138
|
+
"type": "object",
|
|
139
|
+
"additionalProperties": {
|
|
140
|
+
"type": "string"
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"tool_allowlist": {
|
|
144
|
+
"type": "array",
|
|
145
|
+
"items": {
|
|
146
|
+
"type": "string"
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
111
151
|
"tool_spec": {
|
|
112
152
|
"type": "object",
|
|
113
153
|
"additionalProperties": false,
|
|
@@ -137,6 +177,9 @@
|
|
|
137
177
|
},
|
|
138
178
|
"executor": {
|
|
139
179
|
"$ref": "#/$defs/executor"
|
|
180
|
+
},
|
|
181
|
+
"mcp_server": {
|
|
182
|
+
"$ref": "#/$defs/mcp_server"
|
|
140
183
|
}
|
|
141
184
|
}
|
|
142
185
|
}
|
|
@@ -1,5 +1,73 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"updated_at": "
|
|
4
|
-
"tools": [
|
|
3
|
+
"updated_at": "2026-05-06T00:00:00.000Z",
|
|
4
|
+
"tools": [
|
|
5
|
+
{
|
|
6
|
+
"name": "duckduckgo_search_fetch_mcp_example",
|
|
7
|
+
"description": "Example configurable DuckDuckGo-style search/fetch MCP server class. Cost: moderate. This is a registry template; provider command/env must be supplied by workspace policy before use.",
|
|
8
|
+
"input_schema": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"required": [
|
|
11
|
+
"query"
|
|
12
|
+
],
|
|
13
|
+
"additionalProperties": false,
|
|
14
|
+
"properties": {
|
|
15
|
+
"query": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Search query"
|
|
18
|
+
},
|
|
19
|
+
"fetch_urls": {
|
|
20
|
+
"type": "array",
|
|
21
|
+
"items": {
|
|
22
|
+
"type": "string"
|
|
23
|
+
},
|
|
24
|
+
"description": "Optional URLs to fetch after search"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"success_schema": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"additionalProperties": true,
|
|
31
|
+
"properties": {
|
|
32
|
+
"citations": {
|
|
33
|
+
"type": "array",
|
|
34
|
+
"items": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"additionalProperties": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"fetches": {
|
|
40
|
+
"type": "array",
|
|
41
|
+
"items": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"additionalProperties": true
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"failure_schema": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": true
|
|
51
|
+
},
|
|
52
|
+
"executor": {
|
|
53
|
+
"command": "node -e \"const fs=require('node:fs'); fs.writeFileSync(process.env.ACE_RUNTIME_TOOL_RESPONSE_FILE, JSON.stringify({ok:false, summary:'DuckDuckGo MCP example is not configured in this workspace.', error:{reason_code:'provider_unconfigured'}}));\"",
|
|
54
|
+
"timeout_ms": 30000,
|
|
55
|
+
"env": {
|
|
56
|
+
"ACE_RUNTIME_TOOL_PROVIDER": "duckduckgo-mcp-example"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"mcp_server": {
|
|
60
|
+
"transport": "stdio",
|
|
61
|
+
"command": "duckduckgo-mcp-server",
|
|
62
|
+
"args": [],
|
|
63
|
+
"env": {
|
|
64
|
+
"ACE_MCP_PROVIDER": "duckduckgo"
|
|
65
|
+
},
|
|
66
|
+
"tool_allowlist": [
|
|
67
|
+
"search",
|
|
68
|
+
"fetch"
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
]
|
|
5
73
|
}
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
applyTo: 'ACE_coders'
|
|
3
3
|
---
|
|
4
|
+
<!-- ACE Bridge Contract — high salience: this block takes precedence over all directives below -->
|
|
5
|
+
## ACE Bridge Contract (Non-Negotiable)
|
|
6
|
+
|
|
7
|
+
**Output envelope:** Every response MUST be a valid JSON object with a `"status"` key. Do NOT wrap your JSON in markdown code fences. Do NOT add prose before or after it.
|
|
8
|
+
|
|
9
|
+
**One envelope per response:** Emit exactly one top-level JSON object per turn. No preamble, no narration, no code fence wrappers around the envelope itself.
|
|
10
|
+
|
|
11
|
+
**Tool-first discipline:** If the task requires writing, modifying, or creating files, call the appropriate write tool inside `tool_calls`. Do not narrate the change — execute it via a tool call.
|
|
12
|
+
|
|
13
|
+
**No echo drift:** Do not reproduce the task description, the expected spec shape, or test output as your completion summary. State what you accomplished concisely.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
4
17
|
# ACE Coders v7.1
|
|
5
18
|
|
|
6
19
|
## The Engineering Swarm — High-Performance TDD Execution Unit
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
applyTo: 'ACE-UI'
|
|
3
3
|
---
|
|
4
|
+
<!-- ACE Bridge Contract — high salience: this block takes precedence over all directives below -->
|
|
5
|
+
## ACE Bridge Contract (Non-Negotiable)
|
|
6
|
+
|
|
7
|
+
**Output format:** Your primary deliverable is **prose**. You may include brief HTML or JSON snippets inline as illustrations. Never produce a full HTML document, a large standalone JSON structure, or a raw data file as your main response.
|
|
8
|
+
|
|
9
|
+
**Stay on scope:** When given a specific outline or a section list, follow it exactly. Do not invent new sections or expand the scope beyond what was requested.
|
|
10
|
+
|
|
11
|
+
**No semantic drift:** If the task requests a CRISPR-style outline, produce only that outline. Do not layer in brand strategy, personas, or strategic narrative unless the operator explicitly requested those.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
4
15
|
# CX-OS Framework v1.2 (Mercer-Integrated)
|
|
5
16
|
|
|
6
17
|
## Content Experience Operating System — Strategic Brand, UX & Visual Orchestration
|
package/dist/ace-context.js
CHANGED
|
@@ -22,9 +22,15 @@ const ROLE_TOOL_DEFAULTS = {
|
|
|
22
22
|
"emit_status_event",
|
|
23
23
|
],
|
|
24
24
|
coders: [
|
|
25
|
-
"
|
|
26
|
-
"
|
|
25
|
+
"outline_file",
|
|
26
|
+
"astgrep_query",
|
|
27
|
+
"astgrep_locate",
|
|
28
|
+
"read_file_lines",
|
|
29
|
+
"compile_structural_edit",
|
|
30
|
+
"preview_structural_edit",
|
|
31
|
+
"astgrep_rewrite",
|
|
27
32
|
"safe_edit_file",
|
|
33
|
+
"write_workspace_file",
|
|
28
34
|
"run_tests",
|
|
29
35
|
"git_diff",
|
|
30
36
|
"git_status",
|
|
@@ -91,8 +97,13 @@ export function renderAceContinuityPromptBlock(packet) {
|
|
|
91
97
|
return packet ? formatAceContinuityPacketMarkdown(packet) : "";
|
|
92
98
|
}
|
|
93
99
|
function keywordScore(task, tool) {
|
|
94
|
-
const
|
|
95
|
-
|
|
100
|
+
const name = typeof tool?.name === "string" ? tool.name : String(tool?.name ?? "");
|
|
101
|
+
const desc = typeof tool?.description === "string" ? tool.description : String(tool?.description ?? "");
|
|
102
|
+
const inputs = Array.isArray(tool?.input_keys) ? tool.input_keys.join(" ") : "";
|
|
103
|
+
const haystack = `${name} ${desc} ${inputs}`.toLowerCase();
|
|
104
|
+
if (!task)
|
|
105
|
+
return 0;
|
|
106
|
+
return String(task)
|
|
96
107
|
.toLowerCase()
|
|
97
108
|
.split(/[^a-z0-9_]+/)
|
|
98
109
|
.filter((token) => token.length > 2)
|
|
@@ -107,17 +118,26 @@ function selectToolCount(tier) {
|
|
|
107
118
|
}
|
|
108
119
|
function scopeTools(role, task, tier, explicitTools) {
|
|
109
120
|
const catalog = listAceInternalToolCatalog();
|
|
110
|
-
if (explicitTools
|
|
121
|
+
if (Array.isArray(explicitTools)) {
|
|
122
|
+
if (explicitTools.length === 0) {
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
111
125
|
const explicitSet = new Set(explicitTools);
|
|
112
126
|
return catalog.filter((tool) => explicitSet.has(tool.name));
|
|
113
127
|
}
|
|
114
|
-
const
|
|
128
|
+
const defaultTools = ROLE_TOOL_DEFAULTS[role.trim().toLowerCase()] ?? [];
|
|
129
|
+
const roleDefaults = new Set(defaultTools);
|
|
130
|
+
const rolePriority = new Map(defaultTools.map((name, index) => [name, index]));
|
|
115
131
|
const ranked = catalog
|
|
116
132
|
.map((tool) => ({
|
|
117
133
|
tool,
|
|
118
134
|
score: (roleDefaults.has(tool.name) ? 5 : 0) + keywordScore(task, tool),
|
|
119
135
|
}))
|
|
120
|
-
.sort((left, right) =>
|
|
136
|
+
.sort((left, right) => (roleDefaults.has(left.tool.name) && roleDefaults.has(right.tool.name)
|
|
137
|
+
? (rolePriority.get(left.tool.name) ?? 999) - (rolePriority.get(right.tool.name) ?? 999)
|
|
138
|
+
: right.score - left.score) ||
|
|
139
|
+
right.score - left.score ||
|
|
140
|
+
left.tool.name.localeCompare(right.tool.name))
|
|
121
141
|
.slice(0, selectToolCount(tier))
|
|
122
142
|
.map((entry) => entry.tool);
|
|
123
143
|
if (ranked.length > 0 && ranked.some((tool) => roleDefaults.has(tool.name))) {
|
|
@@ -130,7 +150,7 @@ function renderToolCatalogMarkdown(tools, tier) {
|
|
|
130
150
|
return tools
|
|
131
151
|
.map((tool) => {
|
|
132
152
|
const parts = [`- \`${tool.name}\` — ${tool.description || "ACE MCP tool"}`];
|
|
133
|
-
if (includeInputs && tool.input_keys.length > 0) {
|
|
153
|
+
if (includeInputs && Array.isArray(tool.input_keys) && tool.input_keys.length > 0) {
|
|
134
154
|
parts.push(` - input keys: ${tool.input_keys.join(", ")}`);
|
|
135
155
|
}
|
|
136
156
|
return parts.join("\n");
|
|
@@ -157,7 +177,7 @@ function buildPlanningCatalog(role, task, tier) {
|
|
|
157
177
|
.map((entry) => entry.tool);
|
|
158
178
|
}
|
|
159
179
|
function inferRelevantSkills(task) {
|
|
160
|
-
const lowered = task.toLowerCase();
|
|
180
|
+
const lowered = String(task ?? "").toLowerCase();
|
|
161
181
|
const skillSignals = [
|
|
162
182
|
{ name: "state-auditor", pattern: /\b(state|drift|authority|audit)\b/ },
|
|
163
183
|
{ name: "handoff-lint", pattern: /\b(handoff|transition|payload)\b/ },
|
|
@@ -175,7 +195,8 @@ function inferRelevantSkills(task) {
|
|
|
175
195
|
}
|
|
176
196
|
export function buildToolPlan(options) {
|
|
177
197
|
const tier = options.tier ?? "compressed";
|
|
178
|
-
const
|
|
198
|
+
const explicitToolsProvided = Array.isArray(options.tools);
|
|
199
|
+
const catalog = explicitToolsProvided
|
|
179
200
|
? listAceInternalToolCatalog().filter((tool) => options.tools?.includes(tool.name))
|
|
180
201
|
: buildPlanningCatalog(options.role, options.task, tier);
|
|
181
202
|
const recommended = scopeTools(options.role, options.task, tier, options.tools).map((tool) => tool.name);
|
|
@@ -202,6 +223,42 @@ export function buildToolPlan(options) {
|
|
|
202
223
|
selection_limit: selectionLimit,
|
|
203
224
|
};
|
|
204
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Per-role negative output-shape guardrails injected into the system prompt.
|
|
228
|
+
* These complement the shared "## Output Contract" block with role-specific drift constraints.
|
|
229
|
+
*
|
|
230
|
+
* - coders/builder: bridge response must be a JSON envelope; they CAN write HTML/code via tools.
|
|
231
|
+
* - vos/ui: primary output is prose; snippets are fine inline but full HTML docs are not their job.
|
|
232
|
+
*/
|
|
233
|
+
const ROLE_OUTPUT_SHAPE_GUARDRAILS = {
|
|
234
|
+
coders: [
|
|
235
|
+
"- Your bridge response MUST be a JSON envelope (status: tool, complete, etc.) — do not send raw prose as your top-level reply.",
|
|
236
|
+
"- For code mutation, default to astgrep_locate -> compile_structural_edit -> preview_structural_edit -> astgrep_rewrite(plan_id).",
|
|
237
|
+
"- Use write_workspace_file for new files, generated non-code artifacts, or explicit structural_edit_waiver cases only.",
|
|
238
|
+
"- If you bypass the structural lane for code, state the waiver reason and provide evidence_refs.",
|
|
239
|
+
"- Do NOT echo the task description or expected artifact shape as your response without executing via tool calls.",
|
|
240
|
+
"- If you are writing files, call the write tool first, then close with status:complete and evidence_refs.",
|
|
241
|
+
],
|
|
242
|
+
builder: [
|
|
243
|
+
"- Your bridge response MUST be a JSON envelope — raw prose as the top-level reply is a contract violation.",
|
|
244
|
+
"- For code mutation, default to astgrep_locate -> compile_structural_edit -> preview_structural_edit -> astgrep_rewrite(plan_id).",
|
|
245
|
+
"- Use write_workspace_file for new files, generated non-code artifacts, or explicit structural_edit_waiver cases only.",
|
|
246
|
+
"- If you bypass the structural lane for code, state the waiver reason and provide evidence_refs.",
|
|
247
|
+
"- Do NOT echo the artifact shape without executing the build step via tool calls.",
|
|
248
|
+
"- File content (code, HTML, configs) belongs inside tool calls, not in raw text output.",
|
|
249
|
+
"- If you are writing files, close with status:complete and evidence_refs after the write tool succeeds.",
|
|
250
|
+
],
|
|
251
|
+
vos: [
|
|
252
|
+
"- Your primary output is prose. Inline code snippets or JSON examples are acceptable when illustrating a point.",
|
|
253
|
+
"- Do NOT produce a full HTML document or a raw JSON structure as your main deliverable.",
|
|
254
|
+
"- You are a planning and narrative role; do not attempt to write files or persist artifacts directly.",
|
|
255
|
+
],
|
|
256
|
+
ui: [
|
|
257
|
+
"- Your primary output is prose. You may reference or sketch HTML snippets inline as examples.",
|
|
258
|
+
"- Do NOT produce a full HTML document as your response — HTML authoring is the coders role's job.",
|
|
259
|
+
"- Do not emit large raw JSON blobs as your main output; summarize or reference them instead.",
|
|
260
|
+
],
|
|
261
|
+
};
|
|
205
262
|
export function renderAceContext(options) {
|
|
206
263
|
const tier = options.tier ?? "compressed";
|
|
207
264
|
const active = readRuntimeProfileState();
|
|
@@ -248,13 +305,15 @@ export function renderAceContext(options) {
|
|
|
248
305
|
"- Stop if you are about to claim tested, verified, or passed without evidence.",
|
|
249
306
|
"- If ACE state is thin or contradictory, call recall_context or validate_framework before improvising.",
|
|
250
307
|
"- For obviously multi-step work, prefer run_orchestrator over a single free-form answer.",
|
|
308
|
+
"- When you mutate workspace, use the smallest safe mutation lane: structural edit for existing code, write_workspace_file for new/generated artifacts; never assert file creation in prose alone.",
|
|
251
309
|
"- Do not declare completion while approval, retry, or blocker state remains active.",
|
|
310
|
+
...(ROLE_OUTPUT_SHAPE_GUARDRAILS[options.role.trim().toLowerCase()] ?? []),
|
|
252
311
|
"",
|
|
253
312
|
"## Output Contract",
|
|
254
313
|
'Respond in JSON only with one of these shapes:',
|
|
255
314
|
'- `{"status":"tool","thinking":"...","tool_calls":[{"tool":"name","input":{}}]}`',
|
|
256
315
|
'- `{"status":"message","thinking":"...","message":"..."}`',
|
|
257
|
-
'- `{"status":"complete","thinking":"...","summary":"..."}`',
|
|
316
|
+
'- `{"status":"complete","thinking":"...","summary":"...","evidence_refs":["agent-state/..."]}`',
|
|
258
317
|
'- `{"status":"need_input","thinking":"...","message":"..."}`',
|
|
259
318
|
].join("\n");
|
|
260
319
|
return {
|
|
@@ -4,5 +4,7 @@ export interface AceInternalToolCatalogEntry {
|
|
|
4
4
|
input_keys: string[];
|
|
5
5
|
}
|
|
6
6
|
export declare function listAceInternalToolCatalog(): AceInternalToolCatalogEntry[];
|
|
7
|
-
export declare function executeAceInternalTool(name: string, input: Record<string, unknown> | undefined, sessionId?: string
|
|
7
|
+
export declare function executeAceInternalTool(name: string, input: Record<string, unknown> | undefined, sessionId?: string, options?: {
|
|
8
|
+
workspace_path?: string;
|
|
9
|
+
}): Promise<any>;
|
|
8
10
|
//# sourceMappingURL=ace-internal-tools.d.ts.map
|
|
@@ -42,7 +42,7 @@ export function listAceInternalToolCatalog() {
|
|
|
42
42
|
}))
|
|
43
43
|
.sort((left, right) => left.name.localeCompare(right.name));
|
|
44
44
|
}
|
|
45
|
-
export async function executeAceInternalTool(name, input, sessionId) {
|
|
45
|
+
export async function executeAceInternalTool(name, input, sessionId, options = {}) {
|
|
46
46
|
const tool = getRegistry()[name];
|
|
47
47
|
if (!tool || !tool.enabled) {
|
|
48
48
|
return {
|
|
@@ -50,8 +50,16 @@ export async function executeAceInternalTool(name, input, sessionId) {
|
|
|
50
50
|
isError: true,
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
+
const inputWithContext = options.workspace_path && name === "write_workspace_file"
|
|
54
|
+
? {
|
|
55
|
+
...(input ?? {}),
|
|
56
|
+
workspace_path: typeof input?.workspace_path === "string" && input.workspace_path.trim()
|
|
57
|
+
? input.workspace_path
|
|
58
|
+
: options.workspace_path,
|
|
59
|
+
}
|
|
60
|
+
: input;
|
|
53
61
|
const parsedInput = tool.inputSchema
|
|
54
|
-
? tool.inputSchema.safeParse(
|
|
62
|
+
? tool.inputSchema.safeParse(inputWithContext ?? {})
|
|
55
63
|
: { success: true, data: undefined };
|
|
56
64
|
if (!parsedInput.success) {
|
|
57
65
|
const errorText = parsedInput.error.issues
|
|
@@ -21,9 +21,26 @@ export interface AdapterDecision {
|
|
|
21
21
|
domain: AdapterDomain;
|
|
22
22
|
confidence: number;
|
|
23
23
|
confidenceLevel: "low" | "medium" | "high";
|
|
24
|
+
preflight?: AcePreflightPacket;
|
|
25
|
+
}
|
|
26
|
+
export interface AcePreflightPacket {
|
|
27
|
+
required: boolean;
|
|
28
|
+
status: "passed" | "attention_required" | "blocked";
|
|
29
|
+
summary: string;
|
|
30
|
+
evidence_refs: string[];
|
|
31
|
+
model_visible_tools: ToolIntent[];
|
|
24
32
|
}
|
|
25
33
|
export declare function inferDomain(input: string): AdapterDomain;
|
|
26
34
|
export declare function parseManualHandoffCommand(input: string): HandoffIntent | undefined;
|
|
27
35
|
export declare function parseManualToolCommand(input: string): ToolIntent | undefined;
|
|
28
|
-
export declare function
|
|
36
|
+
export declare function buildAcePreflightPacket(input: {
|
|
37
|
+
role: string;
|
|
38
|
+
model_class?: "frontier" | "mid" | "small_local";
|
|
39
|
+
text: string;
|
|
40
|
+
domain: AdapterDomain;
|
|
41
|
+
preflight_required: boolean;
|
|
42
|
+
}): AcePreflightPacket;
|
|
43
|
+
export declare function planRoleExecution(roleValue: string, input: string, options?: {
|
|
44
|
+
model_class?: "frontier" | "mid" | "small_local";
|
|
45
|
+
}): AdapterDecision;
|
|
29
46
|
//# sourceMappingURL=role-adapters.d.ts.map
|
|
@@ -273,7 +273,31 @@ function buildCreateHandoffIntent(fromRole, toRole, input) {
|
|
|
273
273
|
},
|
|
274
274
|
};
|
|
275
275
|
}
|
|
276
|
-
export function
|
|
276
|
+
export function buildAcePreflightPacket(input) {
|
|
277
|
+
const routeIntent = { tool: "route_task", args: { description: input.text, domain: input.domain } };
|
|
278
|
+
const smallLocalOrchestrator = input.role === "orchestrator" && input.model_class === "small_local";
|
|
279
|
+
return {
|
|
280
|
+
required: input.preflight_required,
|
|
281
|
+
status: input.preflight_required ? "attention_required" : "passed",
|
|
282
|
+
summary: smallLocalOrchestrator
|
|
283
|
+
? "ACE-owned preflight covers recall_context, validate_framework, and get_framework_status before model dispatch."
|
|
284
|
+
: "Adapter preflight remains model-visible for this caller.",
|
|
285
|
+
evidence_refs: [
|
|
286
|
+
"agent-state/TASK.md",
|
|
287
|
+
"agent-state/STATUS.md",
|
|
288
|
+
"agent-state/QUALITY_GATES.md",
|
|
289
|
+
],
|
|
290
|
+
model_visible_tools: smallLocalOrchestrator
|
|
291
|
+
? [routeIntent]
|
|
292
|
+
: [
|
|
293
|
+
{ tool: "recall_context", args: {} },
|
|
294
|
+
{ tool: "validate_framework", args: {} },
|
|
295
|
+
{ tool: "get_framework_status", args: {} },
|
|
296
|
+
routeIntent,
|
|
297
|
+
],
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
export function planRoleExecution(roleValue, input, options = {}) {
|
|
277
301
|
const normalizedRole = canonicalizeRole(roleValue);
|
|
278
302
|
const text = input.toLowerCase();
|
|
279
303
|
const domainScore = scoreDomain(input);
|
|
@@ -316,10 +340,17 @@ export function planRoleExecution(roleValue, input) {
|
|
|
316
340
|
domainScore.confidenceLevel === "low" ||
|
|
317
341
|
contradictoryStateRequested ||
|
|
318
342
|
aceStateRequested;
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
343
|
+
const preflight = buildAcePreflightPacket({
|
|
344
|
+
role: normalizedRole,
|
|
345
|
+
model_class: options.model_class,
|
|
346
|
+
text: input,
|
|
347
|
+
domain,
|
|
348
|
+
preflight_required: preflightRequired,
|
|
349
|
+
});
|
|
350
|
+
toolCalls.push(...preflight.model_visible_tools);
|
|
351
|
+
if (options.model_class === "small_local") {
|
|
352
|
+
notes.push(preflight.summary);
|
|
353
|
+
}
|
|
323
354
|
if (preflightRequired) {
|
|
324
355
|
toolCalls.push({ tool: "execute_gates", args: {} });
|
|
325
356
|
notes.push("Orchestrator preflight required before dispatch.");
|
|
@@ -568,6 +599,19 @@ export function planRoleExecution(roleValue, input) {
|
|
|
568
599
|
domain,
|
|
569
600
|
confidence: domainScore.confidence,
|
|
570
601
|
confidenceLevel: domainScore.confidenceLevel,
|
|
602
|
+
preflight: normalizedRole === "orchestrator"
|
|
603
|
+
? buildAcePreflightPacket({
|
|
604
|
+
role: normalizedRole,
|
|
605
|
+
model_class: options.model_class,
|
|
606
|
+
text: input,
|
|
607
|
+
domain,
|
|
608
|
+
preflight_required: dispatchRequested ||
|
|
609
|
+
domainScore.ambiguous ||
|
|
610
|
+
domainScore.confidenceLevel === "low" ||
|
|
611
|
+
contradictoryStateRequested ||
|
|
612
|
+
aceStateRequested,
|
|
613
|
+
})
|
|
614
|
+
: undefined,
|
|
571
615
|
};
|
|
572
616
|
}
|
|
573
617
|
//# sourceMappingURL=role-adapters.js.map
|
package/dist/astgrep-index.d.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
interface AstGrepMatch {
|
|
2
|
+
file?: string;
|
|
3
|
+
text?: string;
|
|
4
|
+
range?: {
|
|
5
|
+
start?: {
|
|
6
|
+
line?: number;
|
|
7
|
+
column?: number;
|
|
8
|
+
};
|
|
9
|
+
end?: {
|
|
10
|
+
line?: number;
|
|
11
|
+
column?: number;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
metaVariables?: Record<string, unknown>;
|
|
15
|
+
kind?: string;
|
|
16
|
+
nodeKind?: string;
|
|
17
|
+
}
|
|
1
18
|
export interface AstgrepMatch {
|
|
2
19
|
file: string;
|
|
3
20
|
line: number;
|
|
@@ -5,7 +22,36 @@ export interface AstgrepMatch {
|
|
|
5
22
|
text: string;
|
|
6
23
|
context_lines?: string[];
|
|
7
24
|
}
|
|
25
|
+
export interface AstgrepLocateInput {
|
|
26
|
+
pattern: string;
|
|
27
|
+
lang: string;
|
|
28
|
+
scope?: string;
|
|
29
|
+
symbol_hint?: string;
|
|
30
|
+
max_results?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface AstgrepLocatedMatch {
|
|
33
|
+
match_id: string;
|
|
34
|
+
file: string;
|
|
35
|
+
range: NonNullable<AstGrepMatch["range"]>;
|
|
36
|
+
text_preview: string;
|
|
37
|
+
matched_text: string;
|
|
38
|
+
captures?: Record<string, string>;
|
|
39
|
+
node_kind?: string;
|
|
40
|
+
file_hash: string;
|
|
41
|
+
}
|
|
42
|
+
export interface AstgrepLocateResult {
|
|
43
|
+
ok: boolean;
|
|
44
|
+
pattern: string;
|
|
45
|
+
lang: string;
|
|
46
|
+
scope: string;
|
|
47
|
+
symbol_hint?: string;
|
|
48
|
+
astgrep_command: string | null;
|
|
49
|
+
total_matches: number;
|
|
50
|
+
matches: AstgrepLocatedMatch[];
|
|
51
|
+
error?: string;
|
|
52
|
+
}
|
|
8
53
|
export declare function runAstgrepQuery(pattern: string, lang: string, roots: string[], _contextLines?: number): AstgrepMatch[];
|
|
54
|
+
export declare function locateAstgrepMatches(input: AstgrepLocateInput): AstgrepLocateResult;
|
|
9
55
|
export interface RefreshAstgrepIndexInput {
|
|
10
56
|
scope?: string;
|
|
11
57
|
append_evidence?: boolean;
|
|
@@ -28,5 +74,7 @@ export interface RefreshAstgrepIndexResult {
|
|
|
28
74
|
todo_signals: number;
|
|
29
75
|
};
|
|
30
76
|
}
|
|
77
|
+
export declare function detectAstgrepCommand(): string | null;
|
|
31
78
|
export declare function refreshAstgrepIndex(input?: RefreshAstgrepIndexInput): Promise<RefreshAstgrepIndexResult>;
|
|
79
|
+
export {};
|
|
32
80
|
//# sourceMappingURL=astgrep-index.d.ts.map
|