@voybio/ace-swarm 2.4.1 → 2.4.2

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.
@@ -0,0 +1,187 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { dirname, resolve } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { spawn } from "node:child_process";
7
+ import { HERMES_BRIDGE_PROTOCOL_VERSION, HermesBridgeFrameDecoder, } from "./bridge-protocol.js";
8
+ import { resolveHermesLaunchProfile, } from "./launch-profile.js";
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+ const DIST_ROOT = resolve(__dirname, "..");
12
+ const PACKAGE_ROOT = resolve(DIST_ROOT, "..");
13
+ const MIN_HERMES_LOCAL_CONTEXT_LENGTH = 65536;
14
+ function summarizeToolResult(value) {
15
+ if (typeof value === "string")
16
+ return value.slice(0, 500);
17
+ try {
18
+ return JSON.stringify(value).slice(0, 500);
19
+ }
20
+ catch {
21
+ return String(value).slice(0, 500);
22
+ }
23
+ }
24
+ function eventText(event) {
25
+ const value = event.text ?? event.message;
26
+ return typeof value === "string" ? value : "";
27
+ }
28
+ function hermesBaseUrl(provider, baseUrl) {
29
+ const normalized = String(baseUrl ?? "").replace(/\/+$/, "");
30
+ if (provider === "ollama" && normalized && !normalized.endsWith("/v1")) {
31
+ return `${normalized}/v1`;
32
+ }
33
+ return normalized;
34
+ }
35
+ export class HermesSubprocessExecutor {
36
+ options;
37
+ constructor(options = {}) {
38
+ this.options = options;
39
+ }
40
+ async runTurn(options) {
41
+ const sessionId = `hermes-${randomUUID()}`;
42
+ const shadowId = `shadow-${randomUUID()}`;
43
+ const hermesHome = mkdtempSync(resolve(tmpdir(), "ace-hermes-home-"));
44
+ mkdirSync(hermesHome, { recursive: true });
45
+ const toolScope = options.toolScope ?? [];
46
+ const cliPath = resolve(DIST_ROOT, "cli.js");
47
+ const baseUrl = hermesBaseUrl(options.runtime.provider, options.runtime.baseUrl ?? options.runtime.ollamaUrl);
48
+ writeFileSync(resolve(hermesHome, "config.yaml"), [
49
+ "model:",
50
+ ` default: ${JSON.stringify(options.runtime.model)}`,
51
+ " provider: custom",
52
+ ` base_url: ${JSON.stringify(baseUrl)}`,
53
+ " api_key: no-key-required",
54
+ ` context_length: ${MIN_HERMES_LOCAL_CONTEXT_LENGTH}`,
55
+ "",
56
+ "auxiliary:",
57
+ " compression:",
58
+ ` model: ${JSON.stringify(options.runtime.model)}`,
59
+ " provider: custom",
60
+ ` base_url: ${JSON.stringify(baseUrl)}`,
61
+ " api_key: no-key-required",
62
+ ` context_length: ${MIN_HERMES_LOCAL_CONTEXT_LENGTH}`,
63
+ "",
64
+ "mcp_servers:",
65
+ " ace_shadow:",
66
+ ` command: ${JSON.stringify(process.execPath)}`,
67
+ " args:",
68
+ ` - ${JSON.stringify(cliPath)}`,
69
+ " - mcp-shadow",
70
+ ` - ${JSON.stringify("--tools")}`,
71
+ ` - ${JSON.stringify(toolScope.join(","))}`,
72
+ " timeout: 30",
73
+ "",
74
+ ].join("\n"), "utf-8");
75
+ const launchProfile = this.options.launchProfile ??
76
+ resolveHermesLaunchProfile({
77
+ workspaceRoot: options.runtime.workspaceRoot,
78
+ cliHermesRoot: this.options.hermesRoot,
79
+ cliHermesPython: this.options.pythonCommand,
80
+ });
81
+ const workerPath = this.options.workerPath ?? launchProfile.worker_path;
82
+ const hermesRoot = this.options.hermesRoot ?? launchProfile.hermes_root;
83
+ const command = this.options.command ?? launchProfile.command;
84
+ const [bin, ...args] = command;
85
+ if (!bin) {
86
+ throw new Error("Hermes launch command must contain at least one executable argument.");
87
+ }
88
+ const child = spawn(bin, [...args, workerPath], {
89
+ cwd: PACKAGE_ROOT,
90
+ env: {
91
+ ...process.env,
92
+ HERMES_HOME: hermesHome,
93
+ ACE_WORKSPACE_ROOT: options.runtime.workspaceRoot,
94
+ },
95
+ stdio: ["pipe", "pipe", "pipe"],
96
+ });
97
+ const decoder = new HermesBridgeFrameDecoder();
98
+ const events = [];
99
+ const malformed = [];
100
+ const stderr = [];
101
+ let finalText = "";
102
+ let turns = 0;
103
+ let sawError = "";
104
+ child.stdout.on("data", (chunk) => {
105
+ for (const frame of decoder.push(chunk)) {
106
+ if (frame.ok) {
107
+ events.push(frame.event);
108
+ if (frame.event.type === "final") {
109
+ finalText = eventText(frame.event);
110
+ const rawTurns = frame.event.turns;
111
+ turns = typeof rawTurns === "number" ? rawTurns : turns;
112
+ }
113
+ if (frame.event.type === "error") {
114
+ sawError = eventText(frame.event) || "Hermes bridge error";
115
+ }
116
+ }
117
+ else {
118
+ malformed.push(frame.reason);
119
+ }
120
+ }
121
+ });
122
+ child.stderr.on("data", (chunk) => {
123
+ stderr.push(chunk.toString("utf8"));
124
+ });
125
+ const request = {
126
+ session_id: sessionId,
127
+ turn_id: randomUUID(),
128
+ hermes_root: hermesRoot ?? "",
129
+ task: options.task,
130
+ role: options.role,
131
+ provider: options.runtime.provider,
132
+ model: options.runtime.model,
133
+ base_url: options.runtime.baseUrl ?? options.runtime.ollamaUrl,
134
+ max_turns: options.maxTurns,
135
+ system_prompt: "You are running inside ACE Hermes-local mode. Use only the imported ACE MCP toolset for tool calls. Do not use plain text as executable authority.",
136
+ };
137
+ child.stdin.end(`${JSON.stringify(request)}\n`);
138
+ const exitCode = await new Promise((resolvePromise, reject) => {
139
+ child.on("error", reject);
140
+ child.on("close", resolvePromise);
141
+ });
142
+ for (const frame of decoder.push(new Uint8Array(), true)) {
143
+ if (frame.ok)
144
+ events.push(frame.event);
145
+ else
146
+ malformed.push(frame.reason);
147
+ }
148
+ if (!this.options.keepTemp) {
149
+ rmSync(hermesHome, { recursive: true, force: true });
150
+ }
151
+ const toolCalls = events
152
+ .filter((event) => event.type === "tool_complete")
153
+ .map((event) => ({
154
+ tool: String(event.tool ?? "unknown"),
155
+ ok: !event.is_error,
156
+ summary: summarizeToolResult(event.result ?? eventText(event)),
157
+ isError: Boolean(event.is_error),
158
+ }));
159
+ const status = sawError || malformed.length > 0 || exitCode !== 0 ? "failed" : "completed";
160
+ const summary = status === "failed"
161
+ ? sawError ||
162
+ `Hermes bridge failed${malformed.length ? `; malformed_frames=${malformed.join(",")}` : ""}${stderr.length ? `; stderr=${stderr.join("").slice(0, 500)}` : ""}`
163
+ : finalText || "Hermes-local turn completed.";
164
+ return {
165
+ result: {
166
+ bridge_id: sessionId,
167
+ role: options.role,
168
+ status,
169
+ summary,
170
+ turns,
171
+ tool_calls: toolCalls,
172
+ child_results: [],
173
+ evidence_refs: toolCalls.map((tool) => `tool:${tool.tool}`),
174
+ },
175
+ metadata: {
176
+ bridge_protocol_version: HERMES_BRIDGE_PROTOCOL_VERSION,
177
+ hermes_session_id: sessionId,
178
+ shadow_mcp_session_id: shadowId,
179
+ execution_engine: "hermes_local",
180
+ provider: options.runtime.provider,
181
+ model: options.runtime.model,
182
+ events,
183
+ },
184
+ };
185
+ }
186
+ }
187
+ //# sourceMappingURL=session-manager.js.map
@@ -1,9 +1,13 @@
1
+ import { type ExecutionEngine } from "./helpers/constants.js";
1
2
  import { type BridgeResult, type ModelBridgeClients } from "./model-bridge.js";
2
3
  import type { AceContextTier } from "./ace-context.js";
3
4
  import { type LocalModelExecutionPolicy } from "./local-model-policy.js";
4
5
  import type { RuntimeModelClass } from "./runtime-profile.js";
6
+ import { type HermesLocalExecutor, type HermesLocalTurnResult } from "./hermes/session-manager.js";
7
+ import { type HermesLaunchProfile } from "./hermes/launch-profile.js";
5
8
  export interface LocalModelRuntimeConfig {
6
9
  workspaceRoot: string;
10
+ executionEngine: ExecutionEngine;
7
11
  provider: string;
8
12
  model: string;
9
13
  baseUrl?: string;
@@ -16,6 +20,7 @@ export interface RunLocalModelTaskOptions {
16
20
  role?: string;
17
21
  workspaceRoot?: string;
18
22
  provider?: string;
23
+ engine?: string;
19
24
  model?: string;
20
25
  baseUrl?: string;
21
26
  ollamaUrl?: string;
@@ -24,6 +29,8 @@ export interface RunLocalModelTaskOptions {
24
29
  modelClass?: RuntimeModelClass;
25
30
  toolScope?: string[];
26
31
  clients?: ModelBridgeClients;
32
+ hermesExecutor?: HermesLocalExecutor;
33
+ hermesLaunchProfile?: HermesLaunchProfile;
27
34
  }
28
35
  export interface RunLocalModelTaskResult {
29
36
  runtime: LocalModelRuntimeConfig;
@@ -31,15 +38,19 @@ export interface RunLocalModelTaskResult {
31
38
  routingSummary?: string;
32
39
  policy: LocalModelExecutionPolicy;
33
40
  result: BridgeResult;
41
+ hermes?: HermesLocalTurnResult["metadata"];
34
42
  }
43
+ export declare function parseExecutionEngine(input?: string): ExecutionEngine | undefined;
35
44
  export declare function resolveTier(requested: RunLocalModelTaskOptions["tier"], provider: string, model: string, role: string): AceContextTier;
36
45
  export declare function createDefaultModelBridgeClients(runtime: Pick<LocalModelRuntimeConfig, "providerBaseUrls">): ModelBridgeClients;
37
46
  export declare function resolveLocalModelRuntime(input: {
38
47
  workspaceRoot?: string;
39
48
  provider?: string;
49
+ engine?: string;
40
50
  model?: string;
41
51
  baseUrl?: string;
42
52
  ollamaUrl?: string;
53
+ hermesReady?: boolean;
43
54
  }): LocalModelRuntimeConfig;
44
55
  export declare function runLocalModelTask(options: RunLocalModelTaskOptions): Promise<RunLocalModelTaskResult>;
45
56
  export { resolveLocalModelExecutionPolicy, resolveLocalModelClass } from "./local-model-policy.js";
@@ -1,12 +1,36 @@
1
1
  import { resolve } from "node:path";
2
2
  import { ROLE_ENUM } from "./shared.js";
3
3
  import { resolveWorkspaceRoot } from "./helpers.js";
4
+ import { ALL_EXECUTION_ENGINES } from "./helpers/constants.js";
4
5
  import { executeAceInternalTool } from "./ace-internal-tools.js";
5
6
  import { ModelBridge } from "./model-bridge.js";
6
7
  import { OllamaClient } from "./tui/ollama.js";
7
8
  import { OpenAICompatibleClient, diagnoseChatRuntimeConfig, } from "./tui/openai-compatible.js";
8
9
  import { discoverProviderContext } from "./tui/provider-discovery.js";
9
10
  import { defaultToolScopeForPolicy, defaultTurnsForPolicy, resolveLocalModelExecutionPolicy, } from "./local-model-policy.js";
11
+ import { HermesSubprocessExecutor, } from "./hermes/session-manager.js";
12
+ import { resolveHermesLaunchProfile, } from "./hermes/launch-profile.js";
13
+ export function parseExecutionEngine(input) {
14
+ if (!input)
15
+ return undefined;
16
+ const normalized = input.trim().toLowerCase().replace(/-/g, "_");
17
+ return ALL_EXECUTION_ENGINES.includes(normalized)
18
+ ? normalized
19
+ : undefined;
20
+ }
21
+ function isLocalProvider(provider) {
22
+ return provider === "ollama" || provider === "llama.cpp";
23
+ }
24
+ function resolveExecutionEngine(input) {
25
+ const parsed = parseExecutionEngine(input.requested);
26
+ if (parsed) {
27
+ if (parsed === "hermes_local" && !isLocalProvider(input.provider)) {
28
+ throw new Error("engine=hermes_local is only valid for local providers.");
29
+ }
30
+ return parsed;
31
+ }
32
+ return isLocalProvider(input.provider) && input.hermesReady ? "hermes_local" : "direct";
33
+ }
10
34
  function extractTextContent(result) {
11
35
  if (!result || typeof result !== "object")
12
36
  return "";
@@ -80,6 +104,11 @@ export function resolveLocalModelRuntime(input) {
80
104
  cliBaseUrl: input.baseUrl,
81
105
  cliOllamaUrl: input.ollamaUrl,
82
106
  });
107
+ const executionEngine = resolveExecutionEngine({
108
+ requested: input.engine,
109
+ provider: discovered.provider,
110
+ hermesReady: input.hermesReady,
111
+ });
83
112
  if (discovered.provider === "ollama" && !discovered.ollamaUrl) {
84
113
  throw new Error("Ollama base URL is not configured. Provide `--base-url`/`ollama_url`, set OLLAMA_HOST, or run `ace doctor --llm ollama --scan`.");
85
114
  }
@@ -93,6 +122,7 @@ export function resolveLocalModelRuntime(input) {
93
122
  }
94
123
  return {
95
124
  workspaceRoot,
125
+ executionEngine,
96
126
  provider: discovered.provider,
97
127
  model: discovered.model,
98
128
  baseUrl: discovered.baseUrl,
@@ -105,6 +135,7 @@ export async function runLocalModelTask(options) {
105
135
  const runtime = resolveLocalModelRuntime({
106
136
  workspaceRoot: options.workspaceRoot,
107
137
  provider: options.provider,
138
+ engine: options.engine,
108
139
  model: options.model,
109
140
  baseUrl: options.baseUrl,
110
141
  ollamaUrl: options.ollamaUrl,
@@ -119,15 +150,40 @@ export async function runLocalModelTask(options) {
119
150
  requested_tier: options.tier,
120
151
  requested_model_class: options.modelClass,
121
152
  });
153
+ const maxTurns = options.maxTurns ?? defaultTurnsForPolicy(role, policy);
154
+ const toolScope = options.toolScope ?? defaultToolScopeForPolicy(role, policy);
155
+ if (runtime.executionEngine === "hermes_local") {
156
+ const launchProfile = options.hermesLaunchProfile ?? resolveHermesLaunchProfile({ workspaceRoot: runtime.workspaceRoot });
157
+ const hermesExecutor = options.hermesExecutor ??
158
+ new HermesSubprocessExecutor({
159
+ launchProfile,
160
+ });
161
+ const hermes = await hermesExecutor.runTurn({
162
+ task: options.task,
163
+ role,
164
+ runtime,
165
+ policy,
166
+ toolScope,
167
+ maxTurns,
168
+ });
169
+ return {
170
+ runtime,
171
+ role,
172
+ routingSummary,
173
+ policy,
174
+ result: hermes.result,
175
+ hermes: hermes.metadata,
176
+ };
177
+ }
122
178
  const result = await bridge.run({
123
179
  task: options.task,
124
180
  role,
125
181
  workspace: runtime.workspaceRoot,
126
182
  tier: policy.tier,
127
- maxTurns: options.maxTurns ?? defaultTurnsForPolicy(role, policy),
183
+ maxTurns,
128
184
  provider: runtime.provider,
129
185
  model: runtime.model,
130
- toolScope: options.toolScope ?? defaultToolScopeForPolicy(role, policy),
186
+ toolScope,
131
187
  });
132
188
  return {
133
189
  runtime,
package/dist/schemas.js CHANGED
@@ -436,6 +436,7 @@ const vericifyProcessPostSchema = z
436
436
  agent_id: NON_EMPTY,
437
437
  kind: z.enum(["intent", "progress", "blocker", "handoff_note", "stale_ack", "completion", "plan_proposal", "plan_quality_assessment"]),
438
438
  summary: NON_EMPTY,
439
+ blocker_category: z.string().optional(),
439
440
  tool_refs: z.array(z.string()),
440
441
  evidence_refs: z.array(z.string()),
441
442
  checkpoint_ref: z.string().optional(),
package/dist/server.d.ts CHANGED
@@ -4,7 +4,10 @@ export declare const ACE_MCP_SERVER_VERSION = "0.2.1";
4
4
  export interface CreateAceServerOptions {
5
5
  toolGovernance?: boolean;
6
6
  instructions?: string;
7
+ toolAllowlist?: readonly string[];
8
+ mode?: "public" | "hermes_shadow";
7
9
  }
8
10
  export declare function createAceServer(options?: CreateAceServerOptions): McpServer;
9
11
  export declare function startStdioServer(logStartup?: boolean): Promise<void>;
12
+ export declare function startHermesShadowStdioServer(toolAllowlist: readonly string[], logStartup?: boolean): Promise<void>;
10
13
  //# sourceMappingURL=server.d.ts.map
package/dist/server.js CHANGED
@@ -12,20 +12,26 @@ import { registerTools } from "./tools.js";
12
12
  import { backfillHandoffsIntoScheduler } from "./tools-handoff.js";
13
13
  export const ACE_MCP_SERVER_NAME = "ace-swarm";
14
14
  export const ACE_MCP_SERVER_VERSION = "0.2.1";
15
+ const HERMES_SHADOW_INSTRUCTIONS = "ACE filtered shadow MCP tool transport for Hermes-local execution. Only tools allowed by the active ACE capability snapshot are registered; public ACE prompts and resources are not exposed.";
15
16
  export function createAceServer(options = {}) {
16
17
  const workspaceRoot = resolveWorkspaceRoot();
17
18
  const server = new McpServer({
18
19
  name: ACE_MCP_SERVER_NAME,
19
20
  version: ACE_MCP_SERVER_VERSION,
20
21
  }, {
21
- instructions: options.instructions ?? buildServerInstructions(workspaceRoot),
22
+ instructions: options.instructions ??
23
+ (options.mode === "hermes_shadow"
24
+ ? HERMES_SHADOW_INSTRUCTIONS
25
+ : buildServerInstructions(workspaceRoot)),
22
26
  });
23
27
  if (options.toolGovernance !== false) {
24
28
  installAceToolGovernance(server, workspaceRoot);
25
29
  }
26
- registerResources(server);
27
- registerPrompts(server);
28
- registerTools(server);
30
+ if (options.mode !== "hermes_shadow") {
31
+ registerResources(server);
32
+ registerPrompts(server);
33
+ }
34
+ registerTools(server, { toolAllowlist: options.toolAllowlist });
29
35
  return server;
30
36
  }
31
37
  function appendEmergencyMcpStatusEvent(workspaceRoot, message) {
@@ -94,4 +100,16 @@ export async function startStdioServer(logStartup = true) {
94
100
  console.error(`ACE MCP Server (${ACE_MCP_SERVER_NAME}) running on stdio`);
95
101
  }
96
102
  }
103
+ export async function startHermesShadowStdioServer(toolAllowlist, logStartup = false) {
104
+ const server = createAceServer({
105
+ mode: "hermes_shadow",
106
+ toolAllowlist,
107
+ instructions: HERMES_SHADOW_INSTRUCTIONS,
108
+ });
109
+ const transport = new StdioServerTransport();
110
+ await server.connect(transport);
111
+ if (logStartup) {
112
+ console.error(`ACE Hermes shadow MCP Server (${ACE_MCP_SERVER_NAME}) running on stdio with ${toolAllowlist.length} tools`);
113
+ }
114
+ }
97
115
  //# sourceMappingURL=server.js.map
@@ -160,6 +160,9 @@ export class VericifyProjector {
160
160
  timestamp: new Date(post.ts).toISOString(),
161
161
  branch_id: typeof post.metadata?.branch_id === "string" ? post.metadata.branch_id : undefined,
162
162
  lane_id: typeof post.metadata?.lane_id === "string" ? post.metadata.lane_id : undefined,
163
+ blocker_category: typeof post.metadata?.blocker_category === "string"
164
+ ? post.metadata.blocker_category
165
+ : undefined,
163
166
  checkpoint_ref: typeof post.metadata?.checkpoint_ref === "string"
164
167
  ? post.metadata.checkpoint_ref
165
168
  : undefined,
@@ -27,6 +27,12 @@ export interface AceSessionContinuityRecord {
27
27
  recent_decisions: string[];
28
28
  recommended_next_action?: string;
29
29
  evidence_refs: string[];
30
+ execution_engine?: "direct" | "hermes_local";
31
+ underlying_provider?: string;
32
+ underlying_model?: string;
33
+ hermes_bridge_protocol_version?: string;
34
+ hermes_session_id?: string;
35
+ shadow_mcp_session_id?: string;
30
36
  last_transition_id?: string;
31
37
  }
32
38
  export interface AceRuntimeStatusPacket {
@@ -56,6 +62,12 @@ export interface AceRuntimeStatusPacket {
56
62
  tokens_in?: number;
57
63
  tokens_out?: number;
58
64
  updated_at: number;
65
+ execution_engine?: "direct" | "hermes_local";
66
+ underlying_provider?: string;
67
+ underlying_model?: string;
68
+ hermes_bridge_protocol_version?: string;
69
+ hermes_session_id?: string;
70
+ shadow_mcp_session_id?: string;
59
71
  surface_kind?: "tui_interactive" | "unattended_runtime" | "scheduled_job" | "bridge_resumed" | "supervised_step";
60
72
  model_class?: "frontier" | "mid" | "small_local";
61
73
  waiting_on?: string;
@@ -196,6 +196,9 @@ export class LocalModelRuntimeRepository {
196
196
  session_id: record.session_id,
197
197
  bridge_status: record.bridge_status,
198
198
  preflight_state: record.preflight_state,
199
+ execution_engine: record.execution_engine,
200
+ underlying_provider: record.underlying_provider,
201
+ underlying_model: record.underlying_model,
199
202
  });
200
203
  await this.addToIndex(STATUS_INDEX_KEY, record.session_id);
201
204
  return record;
@@ -1806,6 +1806,10 @@ export function registerAgentTools(server) {
1806
1806
  .enum(["intent", "progress", "blocker", "handoff_note", "stale_ack", "completion"])
1807
1807
  .describe("Structured process post kind"),
1808
1808
  summary: z.string().describe("Short operator-facing summary"),
1809
+ blocker_category: z
1810
+ .string()
1811
+ .optional()
1812
+ .describe("Optional blocker category for blocker posts"),
1809
1813
  tool_refs: z
1810
1814
  .array(z.string())
1811
1815
  .optional()
@@ -1815,7 +1819,7 @@ export function registerAgentTools(server) {
1815
1819
  .optional()
1816
1820
  .describe("Optional evidence references attached to the process post"),
1817
1821
  checkpoint_ref: z.string().optional().describe("Optional checkpoint id"),
1818
- }, async ({ run_id, branch_id, lane_id, agent_id, kind, summary, tool_refs, evidence_refs, checkpoint_ref }) => {
1822
+ }, async ({ run_id, branch_id, lane_id, agent_id, kind, summary, blocker_category, tool_refs, evidence_refs, checkpoint_ref, }) => {
1819
1823
  const result = await appendVericifyProcessPost({
1820
1824
  run_id,
1821
1825
  branch_id,
@@ -1823,6 +1827,7 @@ export function registerAgentTools(server) {
1823
1827
  agent_id,
1824
1828
  kind,
1825
1829
  summary,
1830
+ blocker_category,
1826
1831
  tool_refs,
1827
1832
  evidence_refs,
1828
1833
  checkpoint_ref,
package/dist/tools.d.ts CHANGED
@@ -5,5 +5,8 @@
5
5
  * This keeps the registration entry-point small and each domain testable.
6
6
  */
7
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
- export declare function registerTools(server: McpServer): void;
8
+ export interface RegisterToolsOptions {
9
+ toolAllowlist?: readonly string[];
10
+ }
11
+ export declare function registerTools(server: McpServer, options?: RegisterToolsOptions): void;
9
12
  //# sourceMappingURL=tools.d.ts.map
package/dist/tools.js CHANGED
@@ -16,18 +16,40 @@ import { registerMemoryTools } from "./tools-memory.js";
16
16
  import { registerDriftTools } from "./tools-drift.js";
17
17
  import { registerSchedulerTools } from "./tools-scheduler.js";
18
18
  import { registerSkillTools } from "./tools-skills.js";
19
- export function registerTools(server) {
20
- registerAgentTools(server);
21
- registerHandoffTools(server);
22
- registerTodoTools(server);
23
- registerDiscoveryTools(server);
24
- registerLifecycleTools(server);
25
- registerFileTools(server);
26
- registerFrameworkTools(server);
27
- registerGitTools(server);
28
- registerMemoryTools(server);
29
- registerDriftTools(server);
30
- registerSchedulerTools(server);
31
- registerSkillTools(server);
19
+ const TOOL_REGISTRARS = [
20
+ registerAgentTools,
21
+ registerHandoffTools,
22
+ registerTodoTools,
23
+ registerDiscoveryTools,
24
+ registerLifecycleTools,
25
+ registerFileTools,
26
+ registerFrameworkTools,
27
+ registerGitTools,
28
+ registerMemoryTools,
29
+ registerDriftTools,
30
+ registerSchedulerTools,
31
+ registerSkillTools,
32
+ ];
33
+ function createAllowlistedServer(server, allowed) {
34
+ return new Proxy(server, {
35
+ get(target, property, receiver) {
36
+ if (property !== "tool")
37
+ return Reflect.get(target, property, receiver);
38
+ const registerTool = Reflect.get(target, property, receiver);
39
+ return (name, ...args) => {
40
+ if (!allowed.has(name))
41
+ return undefined;
42
+ return Reflect.apply(registerTool, target, [name, ...args]);
43
+ };
44
+ },
45
+ });
46
+ }
47
+ export function registerTools(server, options = {}) {
48
+ const target = options.toolAllowlist === undefined
49
+ ? server
50
+ : createAllowlistedServer(server, new Set(options.toolAllowlist));
51
+ for (const register of TOOL_REGISTRARS) {
52
+ register(target);
53
+ }
32
54
  }
33
55
  //# sourceMappingURL=tools.js.map
@@ -12,6 +12,8 @@ import type { ChatMessage } from "./layout.js";
12
12
  import { ModelBridge } from "../model-bridge.js";
13
13
  import type { AceContextTier } from "../ace-context.js";
14
14
  import { type AceRuntimeStatusPacket } from "../store/repositories/local-model-runtime-repository.js";
15
+ import type { HermesLocalExecutor } from "../hermes/session-manager.js";
16
+ import type { HermesLaunchProfile } from "../hermes/launch-profile.js";
15
17
  export interface ChatSessionOptions {
16
18
  provider: string;
17
19
  model: string;
@@ -25,7 +27,10 @@ export interface ChatSessionOptions {
25
27
  aceRole?: string;
26
28
  aceTier?: AceContextTier;
27
29
  maxTurns?: number;
30
+ engine?: string;
28
31
  bridge?: Pick<ModelBridge, "run" | "interrupt">;
32
+ hermesExecutor?: HermesLocalExecutor;
33
+ hermesLaunchProfile?: HermesLaunchProfile;
29
34
  }
30
35
  export interface ChatSessionClients {
31
36
  ollama: Pick<OllamaClient, "chat" | "abort">;
@@ -51,7 +56,10 @@ export declare class ChatSession extends EventEmitter {
51
56
  private aceRole;
52
57
  private aceTier?;
53
58
  private maxTurns;
59
+ private executionEngine;
54
60
  private aceBridge;
61
+ private hermesExecutor?;
62
+ private hermesLaunchProfile?;
55
63
  private activeAceBridge;
56
64
  private providerBaseUrls;
57
65
  private sessionId;