@voybio/ace-swarm 0.2.5 → 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 +19 -1
- package/README.md +21 -13
- package/assets/.agents/ACE/agent-qa/instructions.md +11 -0
- package/assets/agent-state/EVIDENCE_LOG.md +1 -1
- package/assets/agent-state/MODULES/roles/capability-framework.json +41 -0
- package/assets/agent-state/MODULES/roles/capability-git.json +33 -0
- package/assets/agent-state/MODULES/roles/capability-safety.json +37 -0
- package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +21 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +43 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json +43 -0
- package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +11 -0
- package/assets/agent-state/STATUS.md +2 -2
- 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/assets/scripts/ace-hook-dispatch.mjs +70 -6
- package/assets/scripts/render-mcp-configs.sh +19 -5
- package/dist/ace-context.js +91 -11
- package/dist/ace-internal-tools.d.ts +3 -1
- package/dist/ace-internal-tools.js +10 -2
- package/dist/ace-server-instructions.js +3 -3
- package/dist/ace-state-resolver.js +5 -3
- 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 +57 -1
- package/dist/astgrep-index.js +140 -4
- package/dist/cli.js +232 -35
- package/dist/discovery-runtime-wrappers.d.ts +108 -0
- package/dist/discovery-runtime-wrappers.js +615 -0
- package/dist/handoff-registry.js +5 -5
- package/dist/helpers/artifacts.d.ts +19 -0
- package/dist/helpers/artifacts.js +152 -0
- package/dist/helpers/bootstrap.d.ts +24 -0
- package/dist/helpers/bootstrap.js +894 -0
- package/dist/helpers/constants.d.ts +53 -0
- package/dist/helpers/constants.js +295 -0
- package/dist/helpers/drift.d.ts +13 -0
- package/dist/helpers/drift.js +45 -0
- package/dist/helpers/path-utils.d.ts +24 -0
- package/dist/helpers/path-utils.js +123 -0
- package/dist/helpers/store-resolution.d.ts +19 -0
- package/dist/helpers/store-resolution.js +305 -0
- package/dist/helpers/workspace-root.d.ts +3 -0
- package/dist/helpers/workspace-root.js +80 -0
- package/dist/helpers.d.ts +8 -125
- package/dist/helpers.js +8 -1768
- package/dist/job-scheduler.js +33 -7
- 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 +33 -21
- package/dist/model-bridge.d.ts +13 -1
- package/dist/model-bridge.js +410 -23
- package/dist/orchestrator-supervisor.d.ts +56 -0
- package/dist/orchestrator-supervisor.js +179 -1
- package/dist/plan-proposal.d.ts +115 -0
- package/dist/plan-proposal.js +1073 -0
- package/dist/run-ledger.js +3 -3
- package/dist/runtime-command.d.ts +8 -0
- package/dist/runtime-command.js +38 -6
- package/dist/runtime-executor.d.ts +20 -1
- package/dist/runtime-executor.js +737 -172
- package/dist/runtime-profile.d.ts +32 -0
- package/dist/runtime-profile.js +89 -13
- package/dist/runtime-tool-specs.d.ts +39 -0
- package/dist/runtime-tool-specs.js +144 -28
- package/dist/safe-edit.d.ts +7 -0
- package/dist/safe-edit.js +163 -37
- package/dist/schemas.js +48 -1
- package/dist/server.js +51 -0
- package/dist/shared.d.ts +3 -2
- package/dist/shared.js +2 -0
- package/dist/status-events.js +9 -6
- package/dist/store/ace-packed-store.d.ts +3 -2
- package/dist/store/ace-packed-store.js +188 -110
- package/dist/store/bootstrap-store.d.ts +2 -1
- package/dist/store/bootstrap-store.js +102 -83
- package/dist/store/cache-workspace.js +11 -5
- package/dist/store/materializers/context-snapshot-materializer.js +6 -2
- package/dist/store/materializers/hook-context-materializer.d.ts +6 -9
- package/dist/store/materializers/hook-context-materializer.js +11 -21
- package/dist/store/materializers/host-file-materializer.js +6 -0
- package/dist/store/materializers/projection-manager.d.ts +0 -1
- package/dist/store/materializers/projection-manager.js +5 -13
- package/dist/store/materializers/scheduler-projection-materializer.js +1 -1
- package/dist/store/materializers/vericify-projector.d.ts +7 -7
- package/dist/store/materializers/vericify-projector.js +11 -11
- package/dist/store/repositories/local-model-runtime-repository.d.ts +120 -3
- package/dist/store/repositories/local-model-runtime-repository.js +242 -6
- package/dist/store/repositories/vericify-repository.d.ts +1 -1
- package/dist/store/skills-install.d.ts +4 -0
- package/dist/store/skills-install.js +21 -12
- package/dist/store/state-reader.d.ts +2 -0
- package/dist/store/state-reader.js +20 -0
- package/dist/store/store-artifacts.d.ts +7 -0
- package/dist/store/store-artifacts.js +27 -1
- package/dist/store/store-authority-audit.d.ts +18 -1
- package/dist/store/store-authority-audit.js +115 -5
- package/dist/store/store-snapshot.d.ts +3 -0
- package/dist/store/store-snapshot.js +22 -2
- package/dist/store/workspace-store-paths.d.ts +39 -0
- package/dist/store/workspace-store-paths.js +94 -0
- package/dist/store/write-coordinator.d.ts +65 -0
- package/dist/store/write-coordinator.js +386 -0
- package/dist/todo-state.js +5 -5
- package/dist/tools-agent.d.ts +20 -0
- package/dist/tools-agent.js +789 -25
- package/dist/tools-discovery.js +136 -1
- package/dist/tools-files.d.ts +7 -0
- package/dist/tools-files.js +1002 -11
- package/dist/tools-framework.js +105 -66
- package/dist/tools-handoff.js +2 -2
- package/dist/tools-lifecycle.js +4 -4
- package/dist/tools-memory.js +6 -6
- package/dist/tools-todo.js +2 -2
- package/dist/tracker-adapters.d.ts +1 -1
- package/dist/tracker-adapters.js +13 -18
- package/dist/tracker-sync.js +5 -3
- package/dist/tui/agent-runner.js +3 -1
- package/dist/tui/chat.js +103 -7
- package/dist/tui/dashboard.d.ts +1 -0
- package/dist/tui/dashboard.js +43 -0
- package/dist/tui/index.js +10 -1
- package/dist/tui/layout.d.ts +20 -0
- package/dist/tui/layout.js +31 -1
- package/dist/tui/local-model-contract.d.ts +6 -2
- package/dist/tui/local-model-contract.js +16 -3
- 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 +6 -1
- package/dist/vericify-bridge.js +27 -3
- package/dist/workspace-manager.d.ts +30 -3
- package/dist/workspace-manager.js +257 -27
- package/package.json +1 -2
- package/dist/internal-tool-runtime.d.ts +0 -21
- package/dist/internal-tool-runtime.js +0 -136
- package/dist/store/workspace-snapshot.d.ts +0 -26
- package/dist/store/workspace-snapshot.js +0 -107
|
@@ -8,6 +8,31 @@ export declare const DEFAULT_RUNTIME_TOOL_REGISTRY_REL_PATH = "agent-state/runti
|
|
|
8
8
|
export declare const DEFAULT_EXECUTOR_MAX_TURNS = 6;
|
|
9
9
|
export declare const DEFAULT_EXECUTOR_TURN_TIMEOUT_MS = 300000;
|
|
10
10
|
export declare const DEFAULT_VERICIFY_BRIDGE_REL_PATH = "agent-state/vericify/ace-bridge.json";
|
|
11
|
+
export type RuntimeModelClass = "frontier" | "mid" | "small_local";
|
|
12
|
+
export declare const DEFAULT_STALL_WINDOW_MS = 300000;
|
|
13
|
+
export declare const DEFAULT_TURN_BUDGET_MS = 1800000;
|
|
14
|
+
export declare const DEFAULT_MAX_STALL_RESTARTS = 3;
|
|
15
|
+
export declare const DEFAULT_INITIAL_BACKOFF_MS = 5000;
|
|
16
|
+
export declare const DEFAULT_MAX_RETRY_BACKOFF_MS = 300000;
|
|
17
|
+
export interface ModelClassLivenessDefaults {
|
|
18
|
+
turn_budget_ms: number;
|
|
19
|
+
stall_window_ms: number;
|
|
20
|
+
max_stall_restarts: number;
|
|
21
|
+
initial_backoff_ms: number;
|
|
22
|
+
max_retry_backoff_ms: number;
|
|
23
|
+
}
|
|
24
|
+
export interface SurgicalReadBudgets {
|
|
25
|
+
small_local: number;
|
|
26
|
+
mid: number;
|
|
27
|
+
frontier: number | null;
|
|
28
|
+
}
|
|
29
|
+
export interface ResolvedSurgicalReadBudget {
|
|
30
|
+
model_class: RuntimeModelClass;
|
|
31
|
+
read_file_lines_max_lines: number | null;
|
|
32
|
+
}
|
|
33
|
+
export declare const DEFAULT_SURGICAL_READ_BUDGETS: SurgicalReadBudgets;
|
|
34
|
+
export declare function getLivenessDefaults(modelClass?: RuntimeModelClass): ModelClassLivenessDefaults;
|
|
35
|
+
export declare function resolveEffectiveSurgicalReadBudget(profile: RuntimeProfile | undefined, modelClass?: RuntimeModelClass): ResolvedSurgicalReadBudget;
|
|
11
36
|
export declare const DEFAULT_VERICIFY_PROCESS_POST_LOG_REL_PATH = "agent-state/vericify/process-posts.json";
|
|
12
37
|
declare const runtimeProfileSchema: z.ZodObject<{
|
|
13
38
|
ace_runtime_version: z.ZodLiteral<"1.0.0">;
|
|
@@ -41,6 +66,11 @@ declare const runtimeProfileSchema: z.ZodObject<{
|
|
|
41
66
|
}, z.core.$strict>;
|
|
42
67
|
tools: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
43
68
|
registry_path: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
69
|
+
surgical_read_budgets: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
70
|
+
small_local: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
71
|
+
mid: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
72
|
+
frontier: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodNumber>>>;
|
|
73
|
+
}, z.core.$strict>>>;
|
|
44
74
|
}, z.core.$strict>>>;
|
|
45
75
|
autonomy: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
46
76
|
orchestrator_preflight: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -110,7 +140,9 @@ export declare function readRuntimeProfile(): RuntimeProfile;
|
|
|
110
140
|
export declare function readRuntimePromptTemplate(): string;
|
|
111
141
|
export declare function readRuntimeProfileState(): RuntimeProfileSnapshot;
|
|
112
142
|
export declare function renderRuntimePrompt(templateContext: Record<string, unknown>): string;
|
|
143
|
+
export declare function renderRuntimePromptFromSnapshot(snapshot: RuntimeProfileSnapshot, templateContext: Record<string, unknown>): string;
|
|
113
144
|
export declare function getRuntimeProfilePath(): string;
|
|
114
145
|
export declare function getRuntimeProfileSchemaPath(): string;
|
|
146
|
+
export declare function getSurgicalReadBudget(modelClass: "frontier" | "mid" | "small_local" | undefined, profile?: RuntimeProfile): number | null;
|
|
115
147
|
export {};
|
|
116
148
|
//# sourceMappingURL=runtime-profile.d.ts.map
|
package/dist/runtime-profile.js
CHANGED
|
@@ -4,7 +4,7 @@ import { resolve } from "node:path";
|
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { DEFAULTS_ROOT, resolveWorkspaceArtifactPath, resolveWorkspaceRoot, } from "./helpers.js";
|
|
6
6
|
import { getStoreStatSync, getWorkspaceStorePath, parseVirtualStorePath, readStoreBlobSync, readStoreBlobByPathSync, toVirtualStorePath, } from "./store/store-snapshot.js";
|
|
7
|
-
import {
|
|
7
|
+
import { appendStatusEventSafe } from "./status-events.js";
|
|
8
8
|
import { DEFAULT_AUTONOMY_POLICY, DEFAULT_CONTINUITY_POLICY, } from "./ace-autonomy.js";
|
|
9
9
|
export const RUNTIME_PROFILE_REL_PATH = "agent-state/ACE_WORKFLOW.md";
|
|
10
10
|
export const RUNTIME_PROFILE_SCHEMA_REL_PATH = "agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json";
|
|
@@ -13,6 +13,57 @@ export const DEFAULT_RUNTIME_TOOL_REGISTRY_REL_PATH = "agent-state/runtime-tool-
|
|
|
13
13
|
export const DEFAULT_EXECUTOR_MAX_TURNS = 6;
|
|
14
14
|
export const DEFAULT_EXECUTOR_TURN_TIMEOUT_MS = 300_000;
|
|
15
15
|
export const DEFAULT_VERICIFY_BRIDGE_REL_PATH = "agent-state/vericify/ace-bridge.json";
|
|
16
|
+
// Liveness defaults per model class
|
|
17
|
+
export const DEFAULT_STALL_WINDOW_MS = 300_000; // 5 min — inter-progress cap
|
|
18
|
+
export const DEFAULT_TURN_BUDGET_MS = 1_800_000; // 30 min — per-turn soft cap
|
|
19
|
+
export const DEFAULT_MAX_STALL_RESTARTS = 3;
|
|
20
|
+
export const DEFAULT_INITIAL_BACKOFF_MS = 5_000;
|
|
21
|
+
export const DEFAULT_MAX_RETRY_BACKOFF_MS = 300_000;
|
|
22
|
+
export const DEFAULT_SURGICAL_READ_BUDGETS = {
|
|
23
|
+
small_local: 200,
|
|
24
|
+
mid: 800,
|
|
25
|
+
frontier: null,
|
|
26
|
+
};
|
|
27
|
+
export function getLivenessDefaults(modelClass) {
|
|
28
|
+
switch (modelClass) {
|
|
29
|
+
case "small_local":
|
|
30
|
+
return {
|
|
31
|
+
turn_budget_ms: 3_600_000, // 60 min — slow models need generous cap
|
|
32
|
+
stall_window_ms: 180_000, // 3 min stall window
|
|
33
|
+
max_stall_restarts: 3,
|
|
34
|
+
initial_backoff_ms: 10_000,
|
|
35
|
+
max_retry_backoff_ms: 300_000,
|
|
36
|
+
};
|
|
37
|
+
case "mid":
|
|
38
|
+
return {
|
|
39
|
+
turn_budget_ms: 1_800_000, // 30 min
|
|
40
|
+
stall_window_ms: 300_000, // 5 min
|
|
41
|
+
max_stall_restarts: 3,
|
|
42
|
+
initial_backoff_ms: 5_000,
|
|
43
|
+
max_retry_backoff_ms: 180_000,
|
|
44
|
+
};
|
|
45
|
+
case "frontier":
|
|
46
|
+
default:
|
|
47
|
+
return {
|
|
48
|
+
turn_budget_ms: DEFAULT_TURN_BUDGET_MS,
|
|
49
|
+
stall_window_ms: DEFAULT_STALL_WINDOW_MS,
|
|
50
|
+
max_stall_restarts: DEFAULT_MAX_STALL_RESTARTS,
|
|
51
|
+
initial_backoff_ms: DEFAULT_INITIAL_BACKOFF_MS,
|
|
52
|
+
max_retry_backoff_ms: DEFAULT_MAX_RETRY_BACKOFF_MS,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function resolveSurgicalReadBudgetValue(budgets, modelClass) {
|
|
57
|
+
const resolved = budgets ?? DEFAULT_SURGICAL_READ_BUDGETS;
|
|
58
|
+
return resolved[modelClass] ?? null;
|
|
59
|
+
}
|
|
60
|
+
export function resolveEffectiveSurgicalReadBudget(profile, modelClass) {
|
|
61
|
+
const effectiveModelClass = modelClass ?? "frontier";
|
|
62
|
+
return {
|
|
63
|
+
model_class: effectiveModelClass,
|
|
64
|
+
read_file_lines_max_lines: resolveSurgicalReadBudgetValue(profile?.tools?.surgical_read_budgets, effectiveModelClass),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
16
67
|
export const DEFAULT_VERICIFY_PROCESS_POST_LOG_REL_PATH = "agent-state/vericify/process-posts.json";
|
|
17
68
|
const DEFAULT_RUNTIME_PROFILE_PATH = resolve(DEFAULTS_ROOT, RUNTIME_PROFILE_REL_PATH);
|
|
18
69
|
const DEFAULT_RUNTIME_PROFILE_SCHEMA_PATH = resolve(DEFAULTS_ROOT, RUNTIME_PROFILE_SCHEMA_REL_PATH);
|
|
@@ -63,10 +114,22 @@ const runtimeProfileSchema = z
|
|
|
63
114
|
.min(1)
|
|
64
115
|
.optional()
|
|
65
116
|
.default(DEFAULT_RUNTIME_TOOL_REGISTRY_REL_PATH),
|
|
117
|
+
surgical_read_budgets: z
|
|
118
|
+
.object({
|
|
119
|
+
small_local: z.number().int().positive().optional().default(DEFAULT_SURGICAL_READ_BUDGETS.small_local),
|
|
120
|
+
mid: z.number().int().positive().optional().default(DEFAULT_SURGICAL_READ_BUDGETS.mid),
|
|
121
|
+
frontier: z.number().int().positive().nullable().optional().default(DEFAULT_SURGICAL_READ_BUDGETS.frontier),
|
|
122
|
+
})
|
|
123
|
+
.strict()
|
|
124
|
+
.optional()
|
|
125
|
+
.default(DEFAULT_SURGICAL_READ_BUDGETS),
|
|
66
126
|
})
|
|
67
127
|
.strict()
|
|
68
128
|
.optional()
|
|
69
|
-
.default({
|
|
129
|
+
.default({
|
|
130
|
+
registry_path: DEFAULT_RUNTIME_TOOL_REGISTRY_REL_PATH,
|
|
131
|
+
surgical_read_budgets: DEFAULT_SURGICAL_READ_BUDGETS,
|
|
132
|
+
}),
|
|
70
133
|
autonomy: z
|
|
71
134
|
.object({
|
|
72
135
|
orchestrator_preflight: z.boolean().optional().default(true),
|
|
@@ -336,7 +399,7 @@ function parseRuntimeProfileContent(raw) {
|
|
|
336
399
|
}
|
|
337
400
|
function emitRuntimeProfileEvent(eventType, input) {
|
|
338
401
|
try {
|
|
339
|
-
|
|
402
|
+
void appendStatusEventSafe({
|
|
340
403
|
source_module: "capability-framework",
|
|
341
404
|
event_type: eventType,
|
|
342
405
|
status: eventType === "RUNTIME_PROFILE_INVALID" ? "fail" : "pass",
|
|
@@ -349,6 +412,8 @@ function emitRuntimeProfileEvent(eventType, input) {
|
|
|
349
412
|
signature: input.signature,
|
|
350
413
|
errors: input.errors,
|
|
351
414
|
},
|
|
415
|
+
}).catch(() => {
|
|
416
|
+
// Runtime profile reads must not fail due to observability side effects.
|
|
352
417
|
});
|
|
353
418
|
}
|
|
354
419
|
catch {
|
|
@@ -357,13 +422,16 @@ function emitRuntimeProfileEvent(eventType, input) {
|
|
|
357
422
|
}
|
|
358
423
|
function ensureLastGoodSnapshot() {
|
|
359
424
|
const current = loadRuntimeProfile();
|
|
360
|
-
if (current.ok
|
|
361
|
-
return
|
|
362
|
-
if (lastGoodSnapshot
|
|
425
|
+
if (current.ok)
|
|
426
|
+
return current;
|
|
427
|
+
if (lastGoodSnapshot &&
|
|
428
|
+
lastGoodSnapshot.path === current.path &&
|
|
429
|
+
lastGoodSnapshot.source === current.source) {
|
|
363
430
|
return lastGoodSnapshot;
|
|
431
|
+
}
|
|
364
432
|
const packaged = loadRuntimeProfile(DEFAULT_RUNTIME_PROFILE_PATH);
|
|
365
|
-
if (packaged.ok
|
|
366
|
-
return
|
|
433
|
+
if (packaged.ok)
|
|
434
|
+
return packaged;
|
|
367
435
|
throw new Error(`Packaged ACE runtime profile is invalid: ${(packaged.ok ? [] : packaged.errors).join("; ")}`);
|
|
368
436
|
}
|
|
369
437
|
function resolveTemplatePath(context, path) {
|
|
@@ -511,14 +579,17 @@ export function readRuntimeProfileState() {
|
|
|
511
579
|
}
|
|
512
580
|
export function renderRuntimePrompt(templateContext) {
|
|
513
581
|
const active = ensureLastGoodSnapshot();
|
|
582
|
+
return renderRuntimePromptFromSnapshot(active, templateContext);
|
|
583
|
+
}
|
|
584
|
+
export function renderRuntimePromptFromSnapshot(snapshot, templateContext) {
|
|
514
585
|
const renderContext = {
|
|
515
|
-
...
|
|
516
|
-
runtime_profile_path:
|
|
517
|
-
runtime_profile_source:
|
|
518
|
-
prompt_template:
|
|
586
|
+
...snapshot.profile,
|
|
587
|
+
runtime_profile_path: snapshot.path,
|
|
588
|
+
runtime_profile_source: snapshot.source,
|
|
589
|
+
prompt_template: snapshot.prompt_template,
|
|
519
590
|
...templateContext,
|
|
520
591
|
};
|
|
521
|
-
return
|
|
592
|
+
return snapshot.prompt_template.replace(/{{\s*([A-Za-z0-9_.-]+)\s*}}/g, (match, token) => {
|
|
522
593
|
const value = resolveTemplatePath(renderContext, token);
|
|
523
594
|
return value === undefined ? match : stringifyTemplateValue(value);
|
|
524
595
|
});
|
|
@@ -529,4 +600,9 @@ export function getRuntimeProfilePath() {
|
|
|
529
600
|
export function getRuntimeProfileSchemaPath() {
|
|
530
601
|
return DEFAULT_RUNTIME_PROFILE_SCHEMA_PATH;
|
|
531
602
|
}
|
|
603
|
+
export function getSurgicalReadBudget(modelClass, profile) {
|
|
604
|
+
const effectiveProfile = profile ?? readRuntimeProfile();
|
|
605
|
+
const budgets = effectiveProfile.tools?.surgical_read_budgets ?? DEFAULT_SURGICAL_READ_BUDGETS;
|
|
606
|
+
return budgets[modelClass ?? "frontier"] ?? null;
|
|
607
|
+
}
|
|
532
608
|
//# sourceMappingURL=runtime-profile.js.map
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { ToolCostClass } from "./store/repositories/local-model-runtime-repository.js";
|
|
1
2
|
import { type ArtifactSource } from "./helpers.js";
|
|
3
|
+
import { type RuntimeModelClass } from "./runtime-profile.js";
|
|
2
4
|
import { type ValidationResult } from "./schemas.js";
|
|
3
5
|
export declare const RUNTIME_TOOL_SPEC_REGISTRY_REL_PATH = "agent-state/runtime-tool-specs.json";
|
|
4
6
|
export declare const RUNTIME_TOOL_SPEC_SCHEMA_REL_PATH = "agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json";
|
|
@@ -20,6 +22,14 @@ export interface RuntimeToolExecutorConfig {
|
|
|
20
22
|
timeout_ms?: number;
|
|
21
23
|
env?: Record<string, string>;
|
|
22
24
|
}
|
|
25
|
+
export interface RuntimeToolMcpServerConfig {
|
|
26
|
+
transport: "stdio" | "http";
|
|
27
|
+
command?: string;
|
|
28
|
+
args?: string[];
|
|
29
|
+
url?: string;
|
|
30
|
+
env?: Record<string, string>;
|
|
31
|
+
tool_allowlist?: string[];
|
|
32
|
+
}
|
|
23
33
|
export interface RuntimeToolSpec {
|
|
24
34
|
name: string;
|
|
25
35
|
description: string;
|
|
@@ -27,6 +37,7 @@ export interface RuntimeToolSpec {
|
|
|
27
37
|
success_schema?: RuntimeToolSchema;
|
|
28
38
|
failure_schema?: RuntimeToolSchema;
|
|
29
39
|
executor: RuntimeToolExecutorConfig;
|
|
40
|
+
mcp_server?: RuntimeToolMcpServerConfig;
|
|
30
41
|
}
|
|
31
42
|
export interface RuntimeToolSpecRegistry {
|
|
32
43
|
version: 1;
|
|
@@ -58,11 +69,39 @@ export interface RuntimeToolExecutionResult {
|
|
|
58
69
|
error?: unknown;
|
|
59
70
|
validation_errors?: string[];
|
|
60
71
|
}
|
|
72
|
+
export declare function buildRuntimeToolEnvironment(input: {
|
|
73
|
+
base_env?: NodeJS.ProcessEnv;
|
|
74
|
+
spec_env?: Record<string, string>;
|
|
75
|
+
injected_env: Record<string, string>;
|
|
76
|
+
}): NodeJS.ProcessEnv;
|
|
77
|
+
export declare function persistRuntimeToolInvocationArtifacts(callId: string, requestContent: string, responseContent: string): Promise<{
|
|
78
|
+
requestPath: string;
|
|
79
|
+
responsePath: string;
|
|
80
|
+
}>;
|
|
61
81
|
export declare function validateRuntimeToolRegistryContent(raw: string): ValidationResult;
|
|
62
82
|
export declare function loadRuntimeToolRegistry(explicitPath?: string): RuntimeToolSpecRegistryResult;
|
|
63
83
|
export declare function readRuntimeToolRegistry(): RuntimeToolSpecRegistry;
|
|
64
84
|
export declare function listRuntimeToolSpecs(): RuntimeToolSpec[];
|
|
65
85
|
export declare function getRuntimeToolRegistryPath(): string;
|
|
66
86
|
export declare function executeRuntimeTool(name: string, input: unknown, context?: RuntimeToolExecutionContext): Promise<RuntimeToolExecutionResult>;
|
|
87
|
+
export type ModelClass = RuntimeModelClass;
|
|
88
|
+
export declare const SMALL_LOCAL_PRIORITY_TOOL_NAMES: readonly ["outline_file", "astgrep_query", "astgrep_locate", "read_file_lines", "compile_structural_edit", "preview_structural_edit", "list_workspace", "recall_context", "validate_framework", "run_orchestrator"];
|
|
89
|
+
export interface FilteredToolCatalogEntry {
|
|
90
|
+
name: string;
|
|
91
|
+
description: string;
|
|
92
|
+
input_schema: RuntimeToolSchema;
|
|
93
|
+
cost_class: ToolCostClass;
|
|
94
|
+
}
|
|
95
|
+
export interface FilteredToolCatalog {
|
|
96
|
+
entries: FilteredToolCatalogEntry[];
|
|
97
|
+
model_class: ModelClass;
|
|
98
|
+
unavailable_tools: {
|
|
99
|
+
name: string;
|
|
100
|
+
reason: string;
|
|
101
|
+
reason_code: string;
|
|
102
|
+
}[];
|
|
103
|
+
tool_cost_class: Record<string, ToolCostClass>;
|
|
104
|
+
}
|
|
105
|
+
export declare function buildFilteredToolCatalog(modelClass: ModelClass | undefined, allowedTools?: string[]): FilteredToolCatalog;
|
|
67
106
|
export {};
|
|
68
107
|
//# sourceMappingURL=runtime-tool-specs.d.ts.map
|
|
@@ -12,7 +12,8 @@ import { appendStatusEventSafe } from "./status-events.js";
|
|
|
12
12
|
import { openStore } from "./store/ace-packed-store.js";
|
|
13
13
|
import { getWorkspaceStorePath, readStoreBlobSync, storeExistsSync, toVirtualStorePath, } from "./store/store-snapshot.js";
|
|
14
14
|
import { operationalArtifactKey, } from "./store/store-artifacts.js";
|
|
15
|
-
import {
|
|
15
|
+
import { withStoreWriteCoordinator } from "./store/write-coordinator.js";
|
|
16
|
+
import { parseJsonLikeText } from "./json-sanitizer.js";
|
|
16
17
|
export const RUNTIME_TOOL_SPEC_REGISTRY_REL_PATH = "agent-state/runtime-tool-specs.json";
|
|
17
18
|
export const RUNTIME_TOOL_SPEC_SCHEMA_REL_PATH = "agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json";
|
|
18
19
|
export const RUNTIME_TOOL_SPEC_SCHEMA_NAME = "runtime-tool-spec-registry@1.0.0";
|
|
@@ -96,13 +97,46 @@ function buildTempToolPaths(callId) {
|
|
|
96
97
|
responsePath: join(tempDir, "response.json"),
|
|
97
98
|
};
|
|
98
99
|
}
|
|
100
|
+
const SAFE_RUNTIME_ENV_KEYS = new Set([
|
|
101
|
+
"PATH",
|
|
102
|
+
"HOME",
|
|
103
|
+
"TMPDIR",
|
|
104
|
+
"TEMP",
|
|
105
|
+
"TMP",
|
|
106
|
+
"USER",
|
|
107
|
+
"LANG",
|
|
108
|
+
"LC_ALL",
|
|
109
|
+
"SHELL",
|
|
110
|
+
"NODE_PATH",
|
|
111
|
+
]);
|
|
112
|
+
function isSecretEnvKey(key) {
|
|
113
|
+
return /(SECRET|TOKEN|KEY|PASSWORD|PASS|CREDENTIAL|AUTH|COOKIE|SESSION)/i.test(key);
|
|
114
|
+
}
|
|
115
|
+
export function buildRuntimeToolEnvironment(input) {
|
|
116
|
+
const base = input.base_env ?? process.env;
|
|
117
|
+
const env = {};
|
|
118
|
+
for (const key of SAFE_RUNTIME_ENV_KEYS) {
|
|
119
|
+
const value = base[key];
|
|
120
|
+
if (typeof value === "string")
|
|
121
|
+
env[key] = value;
|
|
122
|
+
}
|
|
123
|
+
for (const [key, value] of Object.entries(input.spec_env ?? {})) {
|
|
124
|
+
if (isSecretEnvKey(key))
|
|
125
|
+
continue;
|
|
126
|
+
env[key] = value;
|
|
127
|
+
}
|
|
128
|
+
for (const [key, value] of Object.entries(input.injected_env)) {
|
|
129
|
+
env[key] = value;
|
|
130
|
+
}
|
|
131
|
+
return env;
|
|
132
|
+
}
|
|
99
133
|
function runtimeToolArtifactKey(callId, kind) {
|
|
100
134
|
return `state/runtime/tools/invocations/${callId}/${kind}.json`;
|
|
101
135
|
}
|
|
102
136
|
function runtimeToolArtifactVirtualPath(callId, kind) {
|
|
103
137
|
return toVirtualStorePath(getWorkspaceStorePath(resolveWorkspaceRoot()), runtimeToolArtifactKey(callId, kind));
|
|
104
138
|
}
|
|
105
|
-
async function
|
|
139
|
+
export async function persistRuntimeToolInvocationArtifacts(callId, requestContent, responseContent) {
|
|
106
140
|
const workspaceRoot = resolveWorkspaceRoot();
|
|
107
141
|
if (!storeExistsSync(workspaceRoot)) {
|
|
108
142
|
const requestPath = resolveWorkspaceArtifactPath(`.ace-runtime/tools/${callId}.request.json`);
|
|
@@ -113,7 +147,7 @@ async function persistToolInvocationArtifacts(callId, requestContent, responseCo
|
|
|
113
147
|
return { requestPath, responsePath };
|
|
114
148
|
}
|
|
115
149
|
const storePath = getWorkspaceStorePath(workspaceRoot);
|
|
116
|
-
await
|
|
150
|
+
await withStoreWriteCoordinator(storePath, async () => {
|
|
117
151
|
const store = await openStore(storePath);
|
|
118
152
|
try {
|
|
119
153
|
await store.setBlob(runtimeToolArtifactKey(callId, "request"), requestContent);
|
|
@@ -123,25 +157,25 @@ async function persistToolInvocationArtifacts(callId, requestContent, responseCo
|
|
|
123
157
|
finally {
|
|
124
158
|
await store.close();
|
|
125
159
|
}
|
|
126
|
-
});
|
|
160
|
+
}, { operation_label: "persistToolInvocationArtifacts" });
|
|
127
161
|
return {
|
|
128
162
|
requestPath: runtimeToolArtifactVirtualPath(callId, "request"),
|
|
129
163
|
responsePath: runtimeToolArtifactVirtualPath(callId, "response"),
|
|
130
164
|
};
|
|
131
165
|
}
|
|
132
166
|
function parseRuntimeToolRegistry(raw) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
167
|
+
const parsed = parseJsonLikeText(raw);
|
|
168
|
+
if (!parsed.ok) {
|
|
169
|
+
throw new Error(`Runtime tool registry contains invalid JSON: ${parsed.error}`);
|
|
136
170
|
}
|
|
137
|
-
|
|
138
|
-
throw new Error(`Runtime tool registry contains
|
|
171
|
+
if (parsed.sanitized.removed_control_bytes > 0) {
|
|
172
|
+
throw new Error(`Runtime tool registry contains control-byte corruption: control_bytes_removed=${parsed.sanitized.removed_control_bytes}`);
|
|
139
173
|
}
|
|
140
|
-
const validation = validateRuntimeToolSpecRegistryPayload(parsed);
|
|
174
|
+
const validation = validateRuntimeToolSpecRegistryPayload(parsed.value);
|
|
141
175
|
if (!validation.ok) {
|
|
142
176
|
throw new Error(`Runtime tool registry failed validation (${validation.schema}): ${validation.errors.join("; ")}`);
|
|
143
177
|
}
|
|
144
|
-
return parsed;
|
|
178
|
+
return parsed.value;
|
|
145
179
|
}
|
|
146
180
|
function ensureToolSpec(spec, name) {
|
|
147
181
|
if (spec)
|
|
@@ -258,17 +292,20 @@ export function loadRuntimeToolRegistry(explicitPath) {
|
|
|
258
292
|
};
|
|
259
293
|
}
|
|
260
294
|
catch (error) {
|
|
295
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
296
|
+
const controlBytesRemoved = Number(errorMessage.match(/control_bytes_removed=(\d+)/)?.[1] ?? 0);
|
|
261
297
|
void emitRuntimeToolEvent("RUNTIME_TOOL_REGISTRY_INVALID", `Runtime tool registry validation failed for ${target.path}`, {
|
|
262
298
|
path: target.path,
|
|
263
299
|
source: target.source,
|
|
264
|
-
|
|
300
|
+
...(controlBytesRemoved > 0 ? { control_bytes_removed: controlBytesRemoved } : {}),
|
|
301
|
+
errors: [errorMessage],
|
|
265
302
|
});
|
|
266
303
|
return {
|
|
267
304
|
ok: false,
|
|
268
305
|
schema: RUNTIME_TOOL_SPEC_SCHEMA_NAME,
|
|
269
306
|
path: target.path,
|
|
270
307
|
source: target.source,
|
|
271
|
-
errors: [
|
|
308
|
+
errors: [errorMessage],
|
|
272
309
|
};
|
|
273
310
|
}
|
|
274
311
|
}
|
|
@@ -317,7 +354,7 @@ export async function executeRuntimeTool(name, input, context = {}) {
|
|
|
317
354
|
},
|
|
318
355
|
validation_errors: inputErrors,
|
|
319
356
|
}, null, 2);
|
|
320
|
-
({ requestPath, responsePath } = await
|
|
357
|
+
({ requestPath, responsePath } = await persistRuntimeToolInvocationArtifacts(callId, validationRequest, validationResponse));
|
|
321
358
|
rmSync(tempPaths.tempDir, { recursive: true, force: true });
|
|
322
359
|
const result = {
|
|
323
360
|
ok: false,
|
|
@@ -368,16 +405,17 @@ export async function executeRuntimeTool(name, input, context = {}) {
|
|
|
368
405
|
: workspacePath;
|
|
369
406
|
const shellResult = await runShellCommand(spec.executor.command, {
|
|
370
407
|
cwd: cwdBase,
|
|
371
|
-
env: {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
408
|
+
env: buildRuntimeToolEnvironment({
|
|
409
|
+
spec_env: spec.executor.env,
|
|
410
|
+
injected_env: {
|
|
411
|
+
ACE_RUNTIME_TOOL_NAME: spec.name,
|
|
412
|
+
ACE_RUNTIME_TOOL_REQUEST_FILE: tempPaths.requestPath,
|
|
413
|
+
ACE_RUNTIME_TOOL_RESPONSE_FILE: tempPaths.responsePath,
|
|
414
|
+
ACE_RUNTIME_SESSION_ID: context.session_id ?? "",
|
|
415
|
+
ACE_RUNTIME_TURN: context.turn_number ? String(context.turn_number) : "",
|
|
416
|
+
ACE_RUNTIME_WORKSPACE_PATH: workspacePath,
|
|
417
|
+
},
|
|
418
|
+
}),
|
|
381
419
|
timeout_ms: spec.executor.timeout_ms ?? 60_000,
|
|
382
420
|
});
|
|
383
421
|
let responseRaw;
|
|
@@ -386,7 +424,7 @@ export async function executeRuntimeTool(name, input, context = {}) {
|
|
|
386
424
|
}
|
|
387
425
|
if (!responseRaw) {
|
|
388
426
|
const summary = `Runtime tool '${name}' did not produce a response payload`;
|
|
389
|
-
({ requestPath, responsePath } = await
|
|
427
|
+
({ requestPath, responsePath } = await persistRuntimeToolInvocationArtifacts(callId, requestRaw, JSON.stringify({
|
|
390
428
|
ok: false,
|
|
391
429
|
summary,
|
|
392
430
|
error: {
|
|
@@ -436,7 +474,7 @@ export async function executeRuntimeTool(name, input, context = {}) {
|
|
|
436
474
|
}
|
|
437
475
|
catch (error) {
|
|
438
476
|
const summary = `Runtime tool '${name}' returned invalid JSON`;
|
|
439
|
-
({ requestPath, responsePath } = await
|
|
477
|
+
({ requestPath, responsePath } = await persistRuntimeToolInvocationArtifacts(callId, requestRaw, responseRaw));
|
|
440
478
|
await emitRuntimeToolEvent("RUNTIME_TOOL_FAILED", summary, {
|
|
441
479
|
tool_name: name,
|
|
442
480
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -458,7 +496,7 @@ export async function executeRuntimeTool(name, input, context = {}) {
|
|
|
458
496
|
const envelope = runtimeToolResponseSchema.safeParse(parsed);
|
|
459
497
|
if (!envelope.success) {
|
|
460
498
|
const summary = `Runtime tool '${name}' returned an invalid response envelope`;
|
|
461
|
-
({ requestPath, responsePath } = await
|
|
499
|
+
({ requestPath, responsePath } = await persistRuntimeToolInvocationArtifacts(callId, requestRaw, responseRaw));
|
|
462
500
|
rmSync(tempPaths.tempDir, { recursive: true, force: true });
|
|
463
501
|
return {
|
|
464
502
|
ok: false,
|
|
@@ -483,7 +521,7 @@ export async function executeRuntimeTool(name, input, context = {}) {
|
|
|
483
521
|
const success = envelope.data.ok && validationErrors.length === 0;
|
|
484
522
|
const summary = envelope.data.summary ??
|
|
485
523
|
(success ? `Runtime tool '${name}' executed successfully` : `Runtime tool '${name}' failed`);
|
|
486
|
-
({ requestPath, responsePath } = await
|
|
524
|
+
({ requestPath, responsePath } = await persistRuntimeToolInvocationArtifacts(callId, requestRaw, responseRaw));
|
|
487
525
|
rmSync(tempPaths.tempDir, { recursive: true, force: true });
|
|
488
526
|
const result = {
|
|
489
527
|
ok: success,
|
|
@@ -524,4 +562,82 @@ export async function executeRuntimeTool(name, input, context = {}) {
|
|
|
524
562
|
});
|
|
525
563
|
return result;
|
|
526
564
|
}
|
|
565
|
+
export const SMALL_LOCAL_PRIORITY_TOOL_NAMES = [
|
|
566
|
+
"outline_file",
|
|
567
|
+
"astgrep_query",
|
|
568
|
+
"astgrep_locate",
|
|
569
|
+
"read_file_lines",
|
|
570
|
+
"compile_structural_edit",
|
|
571
|
+
"preview_structural_edit",
|
|
572
|
+
"list_workspace",
|
|
573
|
+
"recall_context",
|
|
574
|
+
"validate_framework",
|
|
575
|
+
"run_orchestrator",
|
|
576
|
+
];
|
|
577
|
+
const HEAVY_TOOL_NAMES = new Set([
|
|
578
|
+
"read_workspace_file",
|
|
579
|
+
"write_workspace_file",
|
|
580
|
+
"safe_edit_file",
|
|
581
|
+
"astgrep_rewrite",
|
|
582
|
+
]);
|
|
583
|
+
function extractCostClass(tool) {
|
|
584
|
+
const desc = (tool.description ?? "").toLowerCase();
|
|
585
|
+
if (desc.includes("cost: cheap"))
|
|
586
|
+
return "cheap";
|
|
587
|
+
if (desc.includes("cost: moderate"))
|
|
588
|
+
return "moderate";
|
|
589
|
+
if (desc.includes("cost: heavy"))
|
|
590
|
+
return "heavy";
|
|
591
|
+
if (HEAVY_TOOL_NAMES.has(tool.name))
|
|
592
|
+
return "heavy";
|
|
593
|
+
if (["read_file_lines", "apply_patch", "diff_files"].includes(tool.name))
|
|
594
|
+
return "moderate";
|
|
595
|
+
return "cheap";
|
|
596
|
+
}
|
|
597
|
+
export function buildFilteredToolCatalog(modelClass, allowedTools) {
|
|
598
|
+
const allTools = listRuntimeToolSpecs();
|
|
599
|
+
const effectiveModelClass = modelClass ?? "frontier";
|
|
600
|
+
const allowed = allowedTools ? new Set(allowedTools) : null;
|
|
601
|
+
const unavailable = [];
|
|
602
|
+
let entries = [];
|
|
603
|
+
for (const tool of allTools) {
|
|
604
|
+
if (allowed !== null && !allowed.has(tool.name)) {
|
|
605
|
+
unavailable.push({
|
|
606
|
+
name: tool.name,
|
|
607
|
+
reason: "Not in allowed_tools for this session",
|
|
608
|
+
reason_code: "workspace_disabled",
|
|
609
|
+
});
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
const costClass = extractCostClass(tool);
|
|
613
|
+
let description = tool.description;
|
|
614
|
+
if (effectiveModelClass === "small_local" && costClass === "heavy") {
|
|
615
|
+
description = `[cost: heavy — prefer surgical alternatives] ${description}`;
|
|
616
|
+
}
|
|
617
|
+
entries.push({
|
|
618
|
+
name: tool.name,
|
|
619
|
+
description,
|
|
620
|
+
input_schema: tool.input_schema,
|
|
621
|
+
cost_class: costClass,
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
if (effectiveModelClass === "small_local" || effectiveModelClass === "mid") {
|
|
625
|
+
const priority = new Map(SMALL_LOCAL_PRIORITY_TOOL_NAMES.map((name, idx) => [name, idx]));
|
|
626
|
+
entries.sort((a, b) => {
|
|
627
|
+
const pa = priority.get(a.name) ?? 999;
|
|
628
|
+
const pb = priority.get(b.name) ?? 999;
|
|
629
|
+
return pa - pb;
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
const toolCostClass = {};
|
|
633
|
+
for (const e of entries) {
|
|
634
|
+
toolCostClass[e.name] = e.cost_class;
|
|
635
|
+
}
|
|
636
|
+
return {
|
|
637
|
+
entries,
|
|
638
|
+
model_class: effectiveModelClass,
|
|
639
|
+
unavailable_tools: unavailable,
|
|
640
|
+
tool_cost_class: toolCostClass,
|
|
641
|
+
};
|
|
642
|
+
}
|
|
527
643
|
//# sourceMappingURL=runtime-tool-specs.js.map
|
package/dist/safe-edit.d.ts
CHANGED
|
@@ -49,4 +49,11 @@ export declare function diffContents(original: string, updated: string): DiffRes
|
|
|
49
49
|
export declare function diffFiles(pathA: string, pathB: string): DiffResult & {
|
|
50
50
|
error?: string;
|
|
51
51
|
};
|
|
52
|
+
export interface ApplyPatchInput {
|
|
53
|
+
path: string;
|
|
54
|
+
patch: string;
|
|
55
|
+
validation_command?: string;
|
|
56
|
+
test_command?: string;
|
|
57
|
+
}
|
|
58
|
+
export declare function applyPatch(input: ApplyPatchInput): SafeEditResult;
|
|
52
59
|
//# sourceMappingURL=safe-edit.d.ts.map
|