@algosuite/vo-mcp 0.2.0-beta.58 → 0.2.0-beta.60

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/dist/cli.js CHANGED
@@ -2170,8 +2170,8 @@ import { existsSync as existsSync8, readdirSync as readdirSync5, readFileSync as
2170
2170
  function extractMemoryTitle(fileName, content) {
2171
2171
  const frontmatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
2172
2172
  if (frontmatter) {
2173
- const description23 = frontmatter[1].match(/^description:\s*(.+)$/m);
2174
- if (description23 && description23[1].trim()) return description23[1].trim().slice(0, 200);
2173
+ const description24 = frontmatter[1].match(/^description:\s*(.+)$/m);
2174
+ if (description24 && description24[1].trim()) return description24[1].trim().slice(0, 200);
2175
2175
  }
2176
2176
  const heading = content.match(/^#\s+(.+)$/m);
2177
2177
  if (heading && heading[1].trim()) return heading[1].trim().slice(0, 200);
@@ -2284,12 +2284,12 @@ var init_memory_knowledge_bridge = __esm({
2284
2284
  // src/tools/memory/sync-config.ts
2285
2285
  var sync_config_exports = {};
2286
2286
  __export(sync_config_exports, {
2287
- TOOL_NAME: () => TOOL_NAME22,
2287
+ TOOL_NAME: () => TOOL_NAME23,
2288
2288
  deriveProjectSlug: () => deriveProjectSlug,
2289
- description: () => description22,
2289
+ description: () => description23,
2290
2290
  getMemoryDir: () => getMemoryDir,
2291
2291
  handleSyncConfig: () => handleSyncConfig,
2292
- inputSchema: () => inputSchema22,
2292
+ inputSchema: () => inputSchema23,
2293
2293
  isNoopSyncReason: () => isNoopSyncReason,
2294
2294
  runMemorySync: () => runMemorySync
2295
2295
  });
@@ -2416,15 +2416,15 @@ async function runMemorySync(action, cwd, sessionId, fetchFn = globalThis.fetch,
2416
2416
  async function handleSyncConfig(deps, rawInput, _signal, fetchFn = globalThis.fetch) {
2417
2417
  if (!isToolInput22(rawInput)) {
2418
2418
  throw invalidParams(
2419
- TOOL_NAME22,
2419
+ TOOL_NAME23,
2420
2420
  'invalid input. Required: { action: "pull" | "push" }. Optional: { cwd: "<path>" }.'
2421
2421
  );
2422
2422
  }
2423
2423
  const cwd = rawInput.cwd?.trim() || process.cwd();
2424
2424
  const result = await runMemorySync(rawInput.action, cwd, deps.session.sessionId, fetchFn);
2425
- return jsonContent({ tool: TOOL_NAME22, schema_version: 1, payload: result });
2425
+ return jsonContent({ tool: TOOL_NAME23, schema_version: 1, payload: result });
2426
2426
  }
2427
- var TOOL_NAME22, inputSchema22, description22;
2427
+ var TOOL_NAME23, inputSchema23, description23;
2428
2428
  var init_sync_config = __esm({
2429
2429
  "src/tools/memory/sync-config.ts"() {
2430
2430
  "use strict";
@@ -2434,8 +2434,8 @@ var init_sync_config = __esm({
2434
2434
  init_memory_push_cache();
2435
2435
  init_sync_lock();
2436
2436
  init_sync_kill_switch();
2437
- TOOL_NAME22 = "vo_sync_config";
2438
- inputSchema22 = {
2437
+ TOOL_NAME23 = "vo_sync_config";
2438
+ inputSchema23 = {
2439
2439
  type: "object",
2440
2440
  properties: {
2441
2441
  action: {
@@ -2451,7 +2451,7 @@ var init_sync_config = __esm({
2451
2451
  required: ["action"],
2452
2452
  additionalProperties: false
2453
2453
  };
2454
- description22 = "Syncs memory entries between local ~/.claude/projects/<slug>/memory/ and cloud control-plane /api/v1/agent-config/memory/me. Requires operator auth (vo-mcp login). Actions: pull (cloud\u2192local), push (local\u2192cloud). Idempotent; push creates/updates as needed. Serialized across concurrent sessions by an exclusive lock in the memory dir.";
2454
+ description23 = "Syncs memory entries between local ~/.claude/projects/<slug>/memory/ and cloud control-plane /api/v1/agent-config/memory/me. Requires operator auth (vo-mcp login). Actions: pull (cloud\u2192local), push (local\u2192cloud). Idempotent; push creates/updates as needed. Serialized across concurrent sessions by an exclusive lock in the memory dir.";
2455
2455
  }
2456
2456
  });
2457
2457
 
@@ -5014,15 +5014,27 @@ init_common();
5014
5014
  init_auth_token_source();
5015
5015
  init_credential_store();
5016
5016
  var AdminCallableError = class extends Error {
5017
- constructor(status, path4, message) {
5017
+ constructor(status, path4, message, body) {
5018
5018
  super(message);
5019
5019
  this.status = status;
5020
5020
  this.path = path4;
5021
+ this.body = body;
5021
5022
  this.name = "AdminCallableError";
5022
5023
  }
5023
5024
  status;
5024
5025
  path;
5026
+ body;
5025
5027
  };
5028
+ function parseJsonObject(text) {
5029
+ try {
5030
+ const parsed = JSON.parse(text);
5031
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
5032
+ return parsed;
5033
+ }
5034
+ } catch {
5035
+ }
5036
+ return void 0;
5037
+ }
5026
5038
  var HttpAdminCallableClient = class {
5027
5039
  baseUrl;
5028
5040
  tokenSource;
@@ -5058,21 +5070,25 @@ var HttpAdminCallableClient = class {
5058
5070
  `admin proxy ${path4}: no auth token available (check VO_USER_REFRESH_TOKEN / VO_USER_ID_TOKEN / VO_CONTROL_PLANE_ADMIN_TOKEN)`
5059
5071
  );
5060
5072
  }
5061
- const url = `${this.baseUrl}${path4}`;
5062
- const response = await this.fetchFn(url, {
5063
- method: "POST",
5073
+ const method = opts?.method ?? "POST";
5074
+ const queryString = opts?.query ? new URLSearchParams(Object.entries(opts.query)).toString() : "";
5075
+ const url = `${this.baseUrl}${path4}${queryString ? `?${queryString}` : ""}`;
5076
+ const init = method === "GET" ? { method, headers: { "authorization": `Bearer ${token}` } } : {
5077
+ method,
5064
5078
  headers: {
5065
5079
  "authorization": `Bearer ${token}`,
5066
5080
  "content-type": "application/json"
5067
5081
  },
5068
5082
  body: JSON.stringify(body)
5069
- });
5083
+ };
5084
+ const response = await this.fetchFn(url, init);
5070
5085
  const text = await response.text();
5071
5086
  if (response.status < 200 || response.status >= 300) {
5072
5087
  throw new AdminCallableError(
5073
5088
  response.status,
5074
5089
  path4,
5075
- `admin proxy ${path4} returned HTTP ${response.status}: ${text.slice(0, 200)}`
5090
+ `admin proxy ${path4} returned HTTP ${response.status}: ${text.slice(0, 200)}`,
5091
+ parseJsonObject(text)
5076
5092
  );
5077
5093
  }
5078
5094
  let parsed;
@@ -5097,7 +5113,8 @@ var HttpAdminCallableClient = class {
5097
5113
  throw new AdminCallableError(
5098
5114
  response.status,
5099
5115
  path4,
5100
- `admin proxy ${path4} returned ok=false: ${JSON.stringify(obj).slice(0, 200)}`
5116
+ `admin proxy ${path4} returned ok=false: ${JSON.stringify(obj).slice(0, 200)}`,
5117
+ obj
5101
5118
  );
5102
5119
  }
5103
5120
  if (opts?.rawEnvelope) {
@@ -5171,11 +5188,12 @@ async function buildCloudOrStubResponse(args) {
5171
5188
  args.deps.events.append(event);
5172
5189
  return jsonContent(envelope);
5173
5190
  }
5191
+ const invokeOptions = args.rawEnvelope || args.invokeOptions ? { ...args.rawEnvelope ? { rawEnvelope: true } : {}, ...args.invokeOptions } : void 0;
5174
5192
  try {
5175
5193
  const result = await args.deps.adminCallables.invoke(
5176
5194
  args.adminPath,
5177
5195
  args.cloudBody ?? args.normalizedInput,
5178
- args.rawEnvelope ? { rawEnvelope: true } : void 0
5196
+ invokeOptions
5179
5197
  );
5180
5198
  const payload = {
5181
5199
  verdict: "pass",
@@ -5195,11 +5213,13 @@ async function buildCloudOrStubResponse(args) {
5195
5213
  } catch (err) {
5196
5214
  const status = err instanceof AdminCallableError ? err.status : void 0;
5197
5215
  const message = err instanceof Error ? err.message : String(err);
5216
+ const errorBody = err instanceof AdminCallableError && err.body !== void 0 ? err.body : void 0;
5198
5217
  const payload = {
5199
5218
  verdict: "fail",
5200
5219
  reason: status !== void 0 ? `vo-control-plane returned HTTP ${status}: ${message.slice(0, 300)}` : `cloud invocation failed: ${message.slice(0, 300)}`,
5201
5220
  callable: args.callableName,
5202
- normalized_input: args.normalizedInput
5221
+ normalized_input: args.normalizedInput,
5222
+ ...errorBody ? { response_data: errorBody } : {}
5203
5223
  };
5204
5224
  const envelope = {
5205
5225
  tool: args.toolName,
@@ -5888,6 +5908,136 @@ async function handleReviewMerge(deps, rawInput, signal) {
5888
5908
  });
5889
5909
  }
5890
5910
 
5911
+ // src/tools/runner/prepared-job-mode.ts
5912
+ init_common();
5913
+ var TOOL_NAME19 = "vo_prepared_job_mode";
5914
+ var CALLABLE_NAME10 = "GET|POST /api/v1/runner/prepared-job-mode";
5915
+ var PLANE_PATH = "/api/v1/runner/prepared-job-mode";
5916
+ var PREPARED_JOB_MODE_GATE_TYPE = "admin-action";
5917
+ var PREPARED_JOB_MODE_STUB_REASON = "cloud mode is not configured on this session, so vo-control-plane was not reached. Sign in with `vo-mcp login` to route this tool to the plane. This route is NOT under /api/v1/admin/*, so a tenant-scoped operator credential is the CORRECT principal for it \u2014 the target operator is derived from that principal, never from this input.";
5918
+ var PREPARED_JOB_MODES = ["off", "shadow", "prepared"];
5919
+ var MIN_REASON_CHARS = 10;
5920
+ var MAX_REASON_CHARS = 500;
5921
+ var MAX_RUNNER_ID_CHARS = 100;
5922
+ var inputSchema19 = {
5923
+ type: "object",
5924
+ properties: {
5925
+ action: {
5926
+ type: "string",
5927
+ enum: ["get", "set"],
5928
+ description: "Required. 'get' reads the delivered mode (read-only; stays live under VO_ADMIN_CALLABLES_READONLY). 'set' writes it (a write; gated to the stub in read-only mode)."
5929
+ },
5930
+ runner_id: {
5931
+ type: "string",
5932
+ minLength: 1,
5933
+ maxLength: MAX_RUNNER_ID_CHARS,
5934
+ description: "Required. Runner to read/configure, e.g. 'vo-code-runner-JacksPC'. Must belong to the authenticated operator \u2014 the plane scopes by principal, so another operator's runner simply reads as unset."
5935
+ },
5936
+ prepared_job_mode: {
5937
+ type: "string",
5938
+ enum: [...PREPARED_JOB_MODES],
5939
+ description: "Required for action='set'. 'off' = the runner's machine-local env rules; 'shadow' = compare the plane's prepared job without consuming it. 'prepared' is recognized but REFUSED by the plane with 409 prepared_mode_not_flippable (ADR-004 11.1c owns the flip)."
5940
+ },
5941
+ expected_revision: {
5942
+ type: "integer",
5943
+ minimum: 0,
5944
+ description: "Required for action='set'. Optimistic-concurrency revision read from a prior 'get' (use 0 when no config exists). A stale value returns 409 stale_prepared_job_revision carrying the authoritative current_revision."
5945
+ },
5946
+ reason: {
5947
+ type: "string",
5948
+ minLength: MIN_REASON_CHARS,
5949
+ maxLength: MAX_REASON_CHARS,
5950
+ description: `Required for action='set'. Audit reason stored on the config-change record; at least ${MIN_REASON_CHARS} characters after trimming.`
5951
+ }
5952
+ },
5953
+ required: ["action", "runner_id"],
5954
+ additionalProperties: false
5955
+ };
5956
+ var description19 = "Gets or sets a paired runner's plane-delivered prepared-job mode (ADR-004 \xA7 11.1) via vo-control-plane GET/POST /api/v1/runner/prepared-job-mode. action='get' returns the stored config ({prepared_job_mode, revision, reason, updated_at, updated_by}, or null when unset); action='set' writes it with optimistic concurrency and returns the new config plus an audit_id. THE TARGET OPERATOR IS DERIVED FROM THE AUTHENTICATED PRINCIPAL, never from this input \u2014 an admin token therefore writes under operator 'admin' and does NOT reach a scoped operator's runner, so use the operator credential from `vo-mcp login`. 'prepared' is refused by the plane with 409 prepared_mode_not_flippable; 'get' is read-only while 'set' is a write and is gated to a stub under VO_ADMIN_CALLABLES_READONLY. Falls back to a clearly-marked `unimplemented` envelope when cloud mode is not configured.";
5957
+ var SHAPE_HINT = `invalid input. Shape: { action: 'get' | 'set', runner_id: non-empty string \u2264${MAX_RUNNER_ID_CHARS} chars }. For action='set' also required: prepared_job_mode ('${PREPARED_JOB_MODES.join("' | '")}'), expected_revision (integer \u2265 0), reason (string \u2265${MIN_REASON_CHARS} chars after trim). Those three fields are NOT accepted with action='get'.`;
5958
+ function parseInput(v) {
5959
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return null;
5960
+ const o = v;
5961
+ const action = o["action"];
5962
+ if (action !== "get" && action !== "set") return null;
5963
+ const rawRunnerId = o["runner_id"];
5964
+ if (typeof rawRunnerId !== "string") return null;
5965
+ const runner_id = rawRunnerId.trim();
5966
+ if (runner_id.length === 0 || runner_id.length > MAX_RUNNER_ID_CHARS) return null;
5967
+ const setOnly = ["prepared_job_mode", "expected_revision", "reason"];
5968
+ if (action === "get") {
5969
+ if (setOnly.some((key) => o[key] !== void 0)) return null;
5970
+ return { action, runner_id };
5971
+ }
5972
+ const mode = o["prepared_job_mode"];
5973
+ if (typeof mode !== "string") return null;
5974
+ if (!PREPARED_JOB_MODES.includes(mode)) return null;
5975
+ const revision = o["expected_revision"];
5976
+ if (typeof revision !== "number") return null;
5977
+ if (!Number.isInteger(revision) || revision < 0) return null;
5978
+ const rawReason = o["reason"];
5979
+ if (typeof rawReason !== "string") return null;
5980
+ const reason = rawReason.trim();
5981
+ if (reason.length < MIN_REASON_CHARS || reason.length > MAX_REASON_CHARS) return null;
5982
+ return {
5983
+ action,
5984
+ runner_id,
5985
+ prepared_job_mode: mode,
5986
+ expected_revision: revision,
5987
+ reason
5988
+ };
5989
+ }
5990
+ async function handlePreparedJobMode(deps, rawInput, _signal) {
5991
+ const input = parseInput(rawInput);
5992
+ if (!input) {
5993
+ throw invalidParams(TOOL_NAME19, SHAPE_HINT);
5994
+ }
5995
+ if (input.action === "get") {
5996
+ return buildCloudOrStubResponse({
5997
+ toolName: TOOL_NAME19,
5998
+ callableName: CALLABLE_NAME10,
5999
+ adminPath: PLANE_PATH,
6000
+ normalizedInput: { action: "get", runner_id: input.runner_id },
6001
+ // A GET carries no body; the runner id rides the query string.
6002
+ cloudBody: {},
6003
+ invokeOptions: { method: "GET", query: { runner_id: input.runner_id } },
6004
+ // The plane answers `{ok, config}` — not the `{ok, callable, result}`
6005
+ // admin-proxy envelope — so take the whole object with `ok` stripped.
6006
+ rawEnvelope: true,
6007
+ gateType: PREPARED_JOB_MODE_GATE_TYPE,
6008
+ stubReason: PREPARED_JOB_MODE_STUB_REASON,
6009
+ readOnly: true,
6010
+ deps
6011
+ });
6012
+ }
6013
+ return buildCloudOrStubResponse({
6014
+ toolName: TOOL_NAME19,
6015
+ callableName: CALLABLE_NAME10,
6016
+ adminPath: PLANE_PATH,
6017
+ normalizedInput: {
6018
+ action: "set",
6019
+ runner_id: input.runner_id,
6020
+ prepared_job_mode: input.prepared_job_mode,
6021
+ expected_revision: input.expected_revision,
6022
+ reason: input.reason
6023
+ },
6024
+ // Exactly the four fields of `updateRunnerPreparedJobConfigInputSchema`
6025
+ // (.strict()) — no `operator_id`, which the route would ignore anyway.
6026
+ cloudBody: {
6027
+ runner_id: input.runner_id,
6028
+ prepared_job_mode: input.prepared_job_mode,
6029
+ expected_revision: input.expected_revision,
6030
+ reason: input.reason
6031
+ },
6032
+ rawEnvelope: true,
6033
+ gateType: PREPARED_JOB_MODE_GATE_TYPE,
6034
+ stubReason: PREPARED_JOB_MODE_STUB_REASON,
6035
+ // A write: stays gated behind VO_ADMIN_CALLABLES_READONLY.
6036
+ readOnly: false,
6037
+ deps
6038
+ });
6039
+ }
6040
+
5891
6041
  // src/tools/session/report-session-state.ts
5892
6042
  init_common();
5893
6043
 
@@ -5924,12 +6074,12 @@ function suggestedHandoffPath(session_id, isoTimestamp) {
5924
6074
  // src/tools/session/report-session-state.ts
5925
6075
  init_auth_token_source();
5926
6076
  init_credential_store();
5927
- var TOOL_NAME19 = "vo_report_session_state";
6077
+ var TOOL_NAME20 = "vo_report_session_state";
5928
6078
  var VALID_AGENT_TYPES = ["claude-code", "codex", "cursor", "continue"];
5929
6079
  var MAX_GOAL_CHARS = 500;
5930
6080
  var MAX_RECENT_FILES = 20;
5931
6081
  var MAX_RECENT_TOOLS = 50;
5932
- var inputSchema19 = {
6082
+ var inputSchema20 = {
5933
6083
  type: "object",
5934
6084
  properties: {
5935
6085
  operator_id: {
@@ -5974,7 +6124,7 @@ var inputSchema19 = {
5974
6124
  required: ["operator_id", "session_id", "agent_type", "context_used_pct"],
5975
6125
  additionalProperties: false
5976
6126
  };
5977
- var description19 = "Reports per-session context-window utilization to AlgoHQ and returns a directive: 'continue' (under 70%), 'prepare_handoff' (70-84%), or 'execute_handoff_now' (\u226585%). Implements V1 launch gate #9 (fleet context lifecycle management) per the official AlgoHQ roadmap. Cloud-control-plane mode when VO_CONTROL_PLANE_URL plus a user/scoped HQ credential (or legacy admin token) is available; auto-allocates the session on first report so interactive agents (Claude Code, Cursor, Codex, Continue) appear on the live fleet whiteboard. Stub-local fallback when cloud config is absent or fails. The response shape stays stable across modes (`backend_mode` field in the payload tells the caller which mode produced the verdict).";
6127
+ var description20 = "Reports per-session context-window utilization to AlgoHQ and returns a directive: 'continue' (under 70%), 'prepare_handoff' (70-84%), or 'execute_handoff_now' (\u226585%). Implements V1 launch gate #9 (fleet context lifecycle management) per the official AlgoHQ roadmap. Cloud-control-plane mode when VO_CONTROL_PLANE_URL plus a user/scoped HQ credential (or legacy admin token) is available; auto-allocates the session on first report so interactive agents (Claude Code, Cursor, Codex, Continue) appear on the live fleet whiteboard. Stub-local fallback when cloud config is absent or fails. The response shape stays stable across modes (`backend_mode` field in the payload tells the caller which mode produced the verdict).";
5978
6128
  function isStringArray2(v, maxItems) {
5979
6129
  if (!Array.isArray(v)) return false;
5980
6130
  if (v.length > maxItems) return false;
@@ -6112,7 +6262,7 @@ async function tryCloudReportState(cloud, input, fetchFn = fetch) {
6112
6262
  async function handleReportSessionState(deps, rawInput, _signal) {
6113
6263
  if (!isToolInput19(rawInput)) {
6114
6264
  throw invalidParams(
6115
- TOOL_NAME19,
6265
+ TOOL_NAME20,
6116
6266
  `invalid input. Required fields: operator_id (non-empty string), session_id (non-empty string), agent_type (one of: ${VALID_AGENT_TYPES.join(" | ")}), context_used_pct (number 0-100). Optional: current_goal (string \u2264${MAX_GOAL_CHARS} chars), recent_files_touched (string[] \u2264${MAX_RECENT_FILES}), recent_tool_uses (string[] \u2264${MAX_RECENT_TOOLS}).`
6117
6267
  );
6118
6268
  }
@@ -6743,9 +6893,9 @@ function checkSuccessorLiveness(child, logPath, config, deps = {}) {
6743
6893
  }
6744
6894
 
6745
6895
  // src/tools/session/spawn-successor.ts
6746
- var TOOL_NAME20 = "vo_spawn_successor";
6896
+ var TOOL_NAME21 = "vo_spawn_successor";
6747
6897
  var MAX_HANDOFF_BYTES = 64e3;
6748
- var inputSchema20 = {
6898
+ var inputSchema21 = {
6749
6899
  type: "object",
6750
6900
  properties: {
6751
6901
  handoff_path: {
@@ -6773,7 +6923,7 @@ var inputSchema20 = {
6773
6923
  additionalProperties: false
6774
6924
  };
6775
6925
  var RETIRED_COUNTER_INPUT = "spawns_so_far";
6776
- var description20 = "Mode B auto-handoff (roadmap \xA73.4): spawn a DETACHED headless `claude -p` successor with a handoff doc pre-injected into its prompt. Defaults to the newest handoff in ~/.vo/handoffs/. Verifies the child is actually alive (survives an early-exit window; an optional log-output window is off by default) before reporting success. Returns {spawned, pid, log_path, handoff_path}. The successor works under the same gates as any session (ADR-001: verify-before-act, human merge approval) \u2014 this tool never fires autonomously.";
6926
+ var description21 = "Mode B auto-handoff (roadmap \xA73.4): spawn a DETACHED headless `claude -p` successor with a handoff doc pre-injected into its prompt. Defaults to the newest handoff in ~/.vo/handoffs/. Verifies the child is actually alive (survives an early-exit window; an optional log-output window is off by default) before reporting success. Returns {spawned, pid, log_path, handoff_path}. The successor works under the same gates as any session (ADR-001: verify-before-act, human merge approval) \u2014 this tool never fires autonomously.";
6777
6927
  function isToolInput20(v) {
6778
6928
  if (typeof v !== "object" || v === null) return false;
6779
6929
  const o = v;
@@ -6831,14 +6981,14 @@ function buildSuccessorPrompt(handoffMarkdown, goal) {
6831
6981
  }
6832
6982
  async function handleSpawnSuccessor(_deps, rawInput, _signal, spawnImpl = spawn, overrides = {}) {
6833
6983
  const retired = retiredCounterRefusal(rawInput);
6834
- if (retired !== null) throw invalidParams(TOOL_NAME20, retired);
6984
+ if (retired !== null) throw invalidParams(TOOL_NAME21, retired);
6835
6985
  if (!isToolInput20(rawInput)) {
6836
- throw invalidParams(TOOL_NAME20, "invalid input. Optional: { handoff_path, goal, cwd, max_turns, agent }.");
6986
+ throw invalidParams(TOOL_NAME21, "invalid input. Optional: { handoff_path, goal, cwd, max_turns, agent }.");
6837
6987
  }
6838
6988
  const handoffPath = rawInput.handoff_path?.trim() || newestHandoff();
6839
6989
  if (!handoffPath || !existsSync5(handoffPath)) {
6840
6990
  return jsonContent({
6841
- tool: TOOL_NAME20,
6991
+ tool: TOOL_NAME21,
6842
6992
  schema_version: 1,
6843
6993
  payload: {
6844
6994
  spawned: false,
@@ -6851,7 +7001,7 @@ async function handleSpawnSuccessor(_deps, rawInput, _signal, spawnImpl = spawn,
6851
7001
  const plan = resolveSpawnPlan(process.env, rawInput, (/* @__PURE__ */ new Date()).toISOString());
6852
7002
  if (!plan.ok) {
6853
7003
  return jsonContent({
6854
- tool: TOOL_NAME20,
7004
+ tool: TOOL_NAME21,
6855
7005
  schema_version: 1,
6856
7006
  payload: {
6857
7007
  spawned: false,
@@ -6867,7 +7017,7 @@ async function handleSpawnSuccessor(_deps, rawInput, _signal, spawnImpl = spawn,
6867
7017
  const resolution = resolveNativeWindowsExecutable(plan.bin, process.env, overrides.resolveWindowsExecutable);
6868
7018
  if (!resolution.ok) {
6869
7019
  return jsonContent({
6870
- tool: TOOL_NAME20,
7020
+ tool: TOOL_NAME21,
6871
7021
  schema_version: 1,
6872
7022
  payload: {
6873
7023
  spawned: false,
@@ -6916,7 +7066,7 @@ async function handleSpawnSuccessor(_deps, rawInput, _signal, spawnImpl = spawn,
6916
7066
  await new Promise((r) => setTimeout(r, 150));
6917
7067
  if (spawnError) {
6918
7068
  return jsonContent({
6919
- tool: TOOL_NAME20,
7069
+ tool: TOOL_NAME21,
6920
7070
  schema_version: 1,
6921
7071
  payload: {
6922
7072
  spawned: false,
@@ -6931,7 +7081,7 @@ async function handleSpawnSuccessor(_deps, rawInput, _signal, spawnImpl = spawn,
6931
7081
  const liveness = await checkLiveness(child, logPath);
6932
7082
  if (!liveness.ok) {
6933
7083
  return jsonContent({
6934
- tool: TOOL_NAME20,
7084
+ tool: TOOL_NAME21,
6935
7085
  schema_version: 1,
6936
7086
  payload: {
6937
7087
  spawned: false,
@@ -6945,7 +7095,7 @@ async function handleSpawnSuccessor(_deps, rawInput, _signal, spawnImpl = spawn,
6945
7095
  });
6946
7096
  }
6947
7097
  return jsonContent({
6948
- tool: TOOL_NAME20,
7098
+ tool: TOOL_NAME21,
6949
7099
  schema_version: 1,
6950
7100
  payload: {
6951
7101
  spawned: true,
@@ -6988,10 +7138,10 @@ function isKnownConciergePack(value) {
6988
7138
  }
6989
7139
 
6990
7140
  // src/tools/concierge/dispatch.ts
6991
- var TOOL_NAME21 = "vo_concierge_dispatch";
6992
- var CALLABLE_NAME10 = "voConciergeDispatch";
7141
+ var TOOL_NAME22 = "vo_concierge_dispatch";
7142
+ var CALLABLE_NAME11 = "voConciergeDispatch";
6993
7143
  var ADMIN_PATH10 = "/api/v1/admin/concierge/dispatch";
6994
- var inputSchema21 = {
7144
+ var inputSchema22 = {
6995
7145
  type: "object",
6996
7146
  properties: {
6997
7147
  pack: {
@@ -7006,7 +7156,7 @@ var inputSchema21 = {
7006
7156
  },
7007
7157
  additionalProperties: false
7008
7158
  };
7009
- var description21 = "Dispatches a provider-scoped knowledge pack (gcp | firebase | aws | cloudflare | vercel | netlify | tax | hybrid). Cross-vendor MCP equivalent of the /vo-concierge Claude-Code slash command. Route explicitly via `pack`, or via tenant.cloud_provider by passing `tenant_id`. Returns the pack's README (`readme_markdown`) + file index. In cloud mode, dispatches via vo-control-plane and returns `verdict: 'pass'` with the pack/directory data; without cloud config, returns `verdict: 'unimplemented'`.";
7159
+ var description22 = "Dispatches a provider-scoped knowledge pack (gcp | firebase | aws | cloudflare | vercel | netlify | tax | hybrid). Cross-vendor MCP equivalent of the /vo-concierge Claude-Code slash command. Route explicitly via `pack`, or via tenant.cloud_provider by passing `tenant_id`. Returns the pack's README (`readme_markdown`) + file index. In cloud mode, dispatches via vo-control-plane and returns `verdict: 'pass'` with the pack/directory data; without cloud config, returns `verdict: 'unimplemented'`.";
7010
7160
  function isToolInput21(v) {
7011
7161
  if (typeof v !== "object" || v === null) return false;
7012
7162
  const obj = v;
@@ -7017,13 +7167,13 @@ function isToolInput21(v) {
7017
7167
  async function handleConciergeDispatch(deps, rawInput, _signal) {
7018
7168
  if (!isToolInput21(rawInput)) {
7019
7169
  throw invalidParams(
7020
- TOOL_NAME21,
7170
+ TOOL_NAME22,
7021
7171
  "invalid input. Expected { pack?: string, tenant_id?: string }."
7022
7172
  );
7023
7173
  }
7024
7174
  if (rawInput.pack !== void 0 && rawInput.pack !== "" && !isKnownConciergePack(rawInput.pack)) {
7025
7175
  throw invalidParams(
7026
- TOOL_NAME21,
7176
+ TOOL_NAME22,
7027
7177
  `unknown pack: ${JSON.stringify(rawInput.pack)}. Known packs: ${KNOWN_CONCIERGE_PACKS.join(", ")}.`
7028
7178
  );
7029
7179
  }
@@ -7034,8 +7184,8 @@ async function handleConciergeDispatch(deps, rawInput, _signal) {
7034
7184
  if (rawInput.pack) cloudBody.pack = rawInput.pack;
7035
7185
  if (rawInput.tenant_id) cloudBody.tenantId = rawInput.tenant_id;
7036
7186
  return buildCloudOrStubResponse({
7037
- toolName: TOOL_NAME21,
7038
- callableName: CALLABLE_NAME10,
7187
+ toolName: TOOL_NAME22,
7188
+ callableName: CALLABLE_NAME11,
7039
7189
  adminPath: ADMIN_PATH10,
7040
7190
  normalizedInput,
7041
7191
  cloudBody,
@@ -7402,7 +7552,7 @@ ${FRONTMATTER_DELIMITER}
7402
7552
  ${FRONTMATTER_DELIMITER}
7403
7553
  `.length);
7404
7554
  let name = "";
7405
- let description23 = "";
7555
+ let description24 = "";
7406
7556
  for (const line of frontmatterText.split("\n")) {
7407
7557
  const trimmed = line.trim();
7408
7558
  if (trimmed.length === 0) continue;
@@ -7411,15 +7561,15 @@ ${FRONTMATTER_DELIMITER}
7411
7561
  const key = trimmed.slice(0, colonIdx).trim();
7412
7562
  const value = trimmed.slice(colonIdx + 1).trim();
7413
7563
  if (key === "name") name = value;
7414
- else if (key === "description") description23 = value;
7564
+ else if (key === "description") description24 = value;
7415
7565
  }
7416
7566
  if (name.length === 0) {
7417
7567
  throw new InvalidSkillFrontmatterError(sourcePath, 'missing required field "name"');
7418
7568
  }
7419
- if (description23.length === 0) {
7569
+ if (description24.length === 0) {
7420
7570
  throw new InvalidSkillFrontmatterError(sourcePath, 'missing required field "description"');
7421
7571
  }
7422
- return { name, description: description23, body };
7572
+ return { name, description: description24, body };
7423
7573
  }
7424
7574
  function loadSkillsFromDir(skillsDir) {
7425
7575
  const entries = readdirSync6(skillsDir);
@@ -7440,8 +7590,8 @@ function loadSkillsFromDir(skillsDir) {
7440
7590
  } catch {
7441
7591
  continue;
7442
7592
  }
7443
- const { name, description: description23, body } = parseFrontmatter(raw, skillFile);
7444
- skills.push({ name, description: description23, body, sourcePath: skillFile });
7593
+ const { name, description: description24, body } = parseFrontmatter(raw, skillFile);
7594
+ skills.push({ name, description: description24, body, sourcePath: skillFile });
7445
7595
  }
7446
7596
  return [...skills].sort((a, b) => a.name.localeCompare(b.name));
7447
7597
  }
@@ -7709,7 +7859,7 @@ function buildToolRegistry() {
7709
7859
  description: description19,
7710
7860
  inputSchema: inputSchema19
7711
7861
  },
7712
- handler: handleReportSessionState
7862
+ handler: handlePreparedJobMode
7713
7863
  },
7714
7864
  [TOOL_NAME20]: {
7715
7865
  definition: {
@@ -7717,7 +7867,7 @@ function buildToolRegistry() {
7717
7867
  description: description20,
7718
7868
  inputSchema: inputSchema20
7719
7869
  },
7720
- handler: handleSpawnSuccessor
7870
+ handler: handleReportSessionState
7721
7871
  },
7722
7872
  [TOOL_NAME21]: {
7723
7873
  definition: {
@@ -7725,7 +7875,7 @@ function buildToolRegistry() {
7725
7875
  description: description21,
7726
7876
  inputSchema: inputSchema21
7727
7877
  },
7728
- handler: handleConciergeDispatch
7878
+ handler: handleSpawnSuccessor
7729
7879
  },
7730
7880
  [TOOL_NAME22]: {
7731
7881
  definition: {
@@ -7733,6 +7883,14 @@ function buildToolRegistry() {
7733
7883
  description: description22,
7734
7884
  inputSchema: inputSchema22
7735
7885
  },
7886
+ handler: handleConciergeDispatch
7887
+ },
7888
+ [TOOL_NAME23]: {
7889
+ definition: {
7890
+ name: TOOL_NAME23,
7891
+ description: description23,
7892
+ inputSchema: inputSchema23
7893
+ },
7736
7894
  handler: handleSyncConfig
7737
7895
  },
7738
7896
  [UPSERT_TOOL_NAME]: {