eminiar 0.13.0 → 0.13.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.
@@ -4,12 +4,12 @@ import {
4
4
  parseJob,
5
5
  runAsyncJob,
6
6
  spawnAsyncJob
7
- } from "./hook-chunk-77I6QQ43.js";
8
- import "./hook-chunk-IYHVLMJ4.js";
7
+ } from "./hook-chunk-RYZAFUTT.js";
8
+ import "./hook-chunk-BECSRJFD.js";
9
9
  export {
10
10
  ASYNC_JOB_MAX_MS,
11
11
  parseJob,
12
12
  runAsyncJob,
13
13
  spawnAsyncJob
14
14
  };
15
- //# sourceMappingURL=hook-async-4MIP3VHX.js.map
15
+ //# sourceMappingURL=hook-async-J3UKDO62.js.map
@@ -19929,6 +19929,12 @@ import { join } from "path";
19929
19929
  function eminiarHome() {
19930
19930
  return process.env.EMINIAR_HOME || join(homedir(), ".eminiar");
19931
19931
  }
19932
+ function claudeConfigDir(env = process.env, home = homedir()) {
19933
+ return env.CLAUDE_CONFIG_DIR?.trim() || join(home, ".claude");
19934
+ }
19935
+ function claudePluginsDir(env = process.env, home = homedir()) {
19936
+ return env.CLAUDE_CODE_PLUGIN_CACHE_DIR?.trim() || join(claudeConfigDir(env, home), "plugins");
19937
+ }
19932
19938
  function paths() {
19933
19939
  const home = eminiarHome();
19934
19940
  return {
@@ -20032,9 +20038,9 @@ var buildAdjudicatorObject = () => external_exports.object({
20032
20038
  }).prefault({}),
20033
20039
  minPromptChars: external_exports.number().int().min(0).default(12),
20034
20040
  /**
20035
- * Ordered ladder, smallest first; "fable" may be inserted by the user. Every provider request
20036
- * carries the whole ladder and a committed project file may set it, so it is bounded: each
20037
- * tier at most once (task #56).
20041
+ * Ordered ladder, smallest first; "fable" may be inserted by the user. Personal config only
20042
+ * (a committed project file cannot set it). Every provider request carries the whole ladder,
20043
+ * so it is bounded: each tier at most once (task #56).
20038
20044
  */
20039
20045
  tiers: external_exports.array(external_exports.enum(TIERS)).min(1).max(TIERS.length).refine((t) => new Set(t).size === t.length, "adjudicator.tiers must not repeat a tier").meta({ uniqueItems: true }).default(["haiku", "sonnet", "opus"]),
20040
20046
  weights: external_exports.object({
@@ -20384,22 +20390,22 @@ function envOverrides() {
20384
20390
  }
20385
20391
  var PROJECT_ADJUDICATOR_KEYS = [
20386
20392
  "enabled",
20387
- "mode",
20388
20393
  "surfaces",
20389
20394
  "promptMode",
20390
20395
  "minPromptChars",
20391
- "tiers",
20392
20396
  "weights",
20393
- "apply",
20394
20397
  "advice",
20395
20398
  "embedding",
20396
20399
  "learning",
20397
20400
  "cache"
20398
20401
  ];
20402
+ function projectKeeps(adj, k) {
20403
+ return PROJECT_ADJUDICATOR_KEYS.includes(k) || k === "mode" && adj.mode === "advise";
20404
+ }
20399
20405
  function droppedProjectAdjudicatorKeys(raw) {
20400
20406
  const adj = raw.adjudicator;
20401
20407
  if (!isPlainObject2(adj)) return [];
20402
- return Object.keys(adj).filter((k) => !PROJECT_ADJUDICATOR_KEYS.includes(k)).sort();
20408
+ return Object.keys(adj).filter((k) => !projectKeeps(adj, k)).sort();
20403
20409
  }
20404
20410
  var CASE_INSENSITIVE_FS = process.platform === "darwin" || process.platform === "win32";
20405
20411
  function realPath(p) {
@@ -20516,7 +20522,7 @@ function projectLayer(raw) {
20516
20522
  if (!isPlainObject2(adj)) return raw;
20517
20523
  if (findSecretFields(adj).length) return raw;
20518
20524
  const kept = {};
20519
- for (const k of PROJECT_ADJUDICATOR_KEYS) if (Object.hasOwn(adj, k)) kept[k] = adj[k];
20525
+ for (const k of Object.keys(adj)) if (projectKeeps(adj, k)) kept[k] = adj[k];
20520
20526
  return { ...ownJson(raw), adjudicator: kept };
20521
20527
  }
20522
20528
  function withoutUnsafeDocsManifest(raw, source) {
@@ -22603,7 +22609,7 @@ function usageWhere(f, opts = {}) {
22603
22609
  var SqliteAdapter = class _SqliteAdapter {
22604
22610
  constructor(path2, opts = {}) {
22605
22611
  this.path = path2;
22606
- this.db = new Database(path2, { timeout: 2e3 });
22612
+ this.db = new Database(path2, { timeout: opts.busyTimeoutMs ?? 2e3 });
22607
22613
  this.swarm = new SqliteSwarmStore(this.db);
22608
22614
  this.adjudicator = new SqliteAdjudicatorStore(this.db);
22609
22615
  this.db.pragma("journal_mode = WAL");
@@ -23817,13 +23823,18 @@ var SqliteAdapter = class _SqliteAdapter {
23817
23823
 
23818
23824
  // src/storage/index.ts
23819
23825
  var open2 = /* @__PURE__ */ new Map();
23826
+ var busyTimeoutMs;
23827
+ function setStorageBusyTimeout(ms) {
23828
+ busyTimeoutMs = ms;
23829
+ }
23820
23830
  function getStorage(ctx, opts = {}) {
23821
23831
  const key = `${ctx.dbPath}|${opts.vectors === false ? "novec" : "vec"}`;
23822
23832
  let adapter = open2.get(key);
23823
23833
  if (!adapter) {
23824
23834
  adapter = new SqliteAdapter(ctx.dbPath, {
23825
23835
  dims: ctx.config.embeddings.dims,
23826
- vectors: opts.vectors ?? true
23836
+ vectors: opts.vectors ?? true,
23837
+ ...busyTimeoutMs === void 0 ? {} : { busyTimeoutMs }
23827
23838
  });
23828
23839
  open2.set(key, adapter);
23829
23840
  }
@@ -24077,16 +24088,20 @@ export {
24077
24088
  AGENT_EFFORT_SINCE,
24078
24089
  TOOL_IDS,
24079
24090
  DEFAULT_ROLES,
24091
+ claudeConfigDir,
24092
+ claudePluginsDir,
24080
24093
  paths,
24081
24094
  ensureDirs,
24082
24095
  projectDir,
24083
24096
  AdjudicatorConfigSchema,
24084
24097
  loadConfig,
24085
24098
  findProjectRoot,
24099
+ resolveProjectRoot,
24086
24100
  getContext,
24087
24101
  tierOf,
24088
24102
  KEPT_MODEL_FLAG,
24089
24103
  keptModel,
24104
+ setStorageBusyTimeout,
24090
24105
  getStorage,
24091
24106
  GUIDE_ORDER,
24092
24107
  ev,
@@ -24096,4 +24111,4 @@ export {
24096
24111
  classifyToolCall,
24097
24112
  classifyAssistant
24098
24113
  };
24099
- //# sourceMappingURL=hook-chunk-IYHVLMJ4.js.map
24114
+ //# sourceMappingURL=hook-chunk-BECSRJFD.js.map
@@ -11,8 +11,9 @@ import {
11
11
  getStorage,
12
12
  init_esm_shims,
13
13
  paths,
14
+ resolveProjectRoot,
14
15
  tierOf
15
- } from "./hook-chunk-IYHVLMJ4.js";
16
+ } from "./hook-chunk-BECSRJFD.js";
16
17
 
17
18
  // node_modules/fast-glob/out/utils/array.js
18
19
  var require_array = __commonJS({
@@ -6065,6 +6066,14 @@ function yaml() {
6065
6066
  yamlLib ??= createRequire(import.meta.url)("yaml");
6066
6067
  return yamlLib;
6067
6068
  }
6069
+ var EXEC_TOOLS = /* @__PURE__ */ new Set([
6070
+ "em_execute",
6071
+ "em_execute_file",
6072
+ "em_batch_execute"
6073
+ ]);
6074
+ function roleHasShell(role) {
6075
+ return (role.tools?.includes("Bash") ?? true) && !role.disallowedTools?.includes("Bash");
6076
+ }
6068
6077
  var EM_MCP_PREFIXES = ["mcp__plugin_eminiar_eminiar__", "mcp__eminiar__"];
6069
6078
  var AGENTS_REL = ".claude/agents";
6070
6079
  function agentsDir(root) {
@@ -6078,21 +6087,26 @@ var TOPOLOGY_RULE = {
6078
6087
  mesh: "peers share one task board. Claim any open task (your role's first), and read the blackboard for what the other workers found.",
6079
6088
  pipeline: "work moves in stages. You can claim a task only once every task of the earlier stages is done."
6080
6089
  };
6081
- function workerTools(tools) {
6090
+ function workerTools(tools, shell = tools.includes("Bash")) {
6082
6091
  const out = tools.includes("ToolSearch") ? [...tools] : [...tools, "ToolSearch"];
6083
6092
  for (const prefix of EM_MCP_PREFIXES)
6084
- for (const t of WORKER_EM_TOOLS) if (!out.includes(prefix + t)) out.push(prefix + t);
6093
+ for (const t of WORKER_EM_TOOLS)
6094
+ if ((shell || !EXEC_TOOLS.has(t)) && !out.includes(prefix + t)) out.push(prefix + t);
6085
6095
  return out;
6086
6096
  }
6097
+ var execToolNames = () => EM_MCP_PREFIXES.flatMap((prefix) => [...EXEC_TOOLS].map((t) => prefix + t));
6087
6098
  function frontmatter(swarm, role) {
6088
6099
  const fm = {
6089
6100
  name: role.agentType,
6090
6101
  description: `Worker "${role.role}" of the eminiar swarm "${swarm.name}": ${role.description} Spawn it for a task of this swarm and name the task as "task #N" in the prompt; the em-swarm skill coordinates runs.`
6091
6102
  };
6092
6103
  if (role.model) fm.model = role.model;
6093
- if (role.tools) fm.tools = workerTools(role.tools).join(", ");
6104
+ if (role.tools) fm.tools = workerTools(role.tools, roleHasShell(role)).join(", ");
6094
6105
  const spawns = role.tools?.some((t) => t === "Agent" || t === "Task");
6095
- const disallowed = [.../* @__PURE__ */ new Set([...role.disallowedTools ?? [], ...spawns ? [] : ["Agent"]])];
6106
+ const noShell = role.disallowedTools?.includes("Bash") ? execToolNames() : [];
6107
+ const disallowed = [
6108
+ .../* @__PURE__ */ new Set([...role.disallowedTools ?? [], ...spawns ? [] : ["Agent"], ...noShell])
6109
+ ];
6096
6110
  if (disallowed.length) fm.disallowedTools = disallowed.join(", ");
6097
6111
  if (role.skills.length) fm.skills = role.skills;
6098
6112
  if (role.hooks) {
@@ -6111,6 +6125,7 @@ var hashOf = (fm, rest, range) => createHash("sha1").update(range ? `range=${ran
6111
6125
  ${fm}
6112
6126
  ${rest}` : `${fm}
6113
6127
  ${rest}`).digest("hex").slice(0, 12);
6128
+ var SHARED_TREE_RULE = "Other workers may be editing this working tree at the same time, and their changes are not committed. Never run `git stash`, `git checkout`, `git switch`, `git reset`, `git restore` or `git clean`, not even on one path: they hide or wipe another worker's work. If you commit, add only the files you changed: `git add -A` or `git commit -a` takes their unfinished work with yours. To test without your change (a mutation check), copy the files into a scratch directory outside the tree and run the tests there.";
6114
6129
  function renderAgentFile(config, swarm, role) {
6115
6130
  const fm = yaml().stringify(frontmatter(swarm, role), { lineWidth: 0 }).trimEnd();
6116
6131
  if (fm.includes("---"))
@@ -6124,12 +6139,15 @@ function renderAgentFile(config, swarm, role) {
6124
6139
  ...role.prompt ? [role.prompt, ""] : [],
6125
6140
  "## Swarm protocol",
6126
6141
  "",
6127
- '1. eminiar starts you with a swarm brief: the run goal, the open tasks, the shared notes and what the project knows (memories, history, structure). First claim the task your prompt names with `em_swarm {action:"claim", task:N}` (or the next open one with `em_swarm {action:"claim"}`); if the brief says you already hold a task, continue it.',
6128
- '2. Ask eminiar before acting: `em_recall {query}` for decisions and constraints, `em_history {action:"file", path}` before editing a file, `em_graph_impact {node}` before changing a symbol, `em_symbols` / `em_search` instead of grepping.',
6129
- '3. Share what other workers need with `em_swarm {action:"post", key, value}` and read theirs with `em_swarm {action:"read"}`.',
6130
- '4. Close every task with `em_swarm {action:"update", task, status, result}`: status `done`, `failed` or `blocked`; the result says what changed and how you verified it.',
6131
- "5. Record durable decisions with `em_remember` so later sessions know them.",
6132
- "6. Your final message goes back to the coordinator: lead with the outcome, then the files you changed and anything left open.",
6142
+ ...[
6143
+ 'eminiar starts you with a swarm brief: the run goal, the open tasks, the shared notes and what the project knows (memories, history, structure). First claim the task your prompt names with `em_swarm {action:"claim", task:N}` (or the next open one with `em_swarm {action:"claim"}`); if the brief says you already hold a task, continue it.',
6144
+ 'Ask eminiar before acting: `em_recall {query}` for decisions and constraints, `em_history {action:"file", path}` before editing a file, `em_graph_impact {node}` before changing a symbol, `em_symbols` / `em_search` instead of grepping.',
6145
+ ...!role.isolation && roleHasShell(role) ? [SHARED_TREE_RULE] : [],
6146
+ 'Share what other workers need with `em_swarm {action:"post", key, value}` and read theirs with `em_swarm {action:"read"}`.',
6147
+ 'Close every task with `em_swarm {action:"update", task, status, result}`: status `done`, `failed` or `blocked`; the result says what changed and how you verified it.',
6148
+ "Record durable decisions with `em_remember` so later sessions know them.",
6149
+ "Your final message goes back to the coordinator: lead with the outcome, then the files you changed and anything left open."
6150
+ ].map((step, i) => `${i + 1}. ${step}`),
6133
6151
  ""
6134
6152
  ].join("\n");
6135
6153
  const range = role.range ? modelRangeText(role.range) : void 0;
@@ -9123,6 +9141,18 @@ function orderedRoots(hookRoot) {
9123
9141
  if (hookRoot && !out.includes(hookRoot)) out.push(hookRoot);
9124
9142
  return out;
9125
9143
  }
9144
+ function swarmRoots(input) {
9145
+ let hook;
9146
+ try {
9147
+ hook = resolveProjectRoot(input.cwd || void 0);
9148
+ } catch {
9149
+ }
9150
+ const out = [];
9151
+ for (const r of orderedRoots(hook)) {
9152
+ for (const d of [r, coordinationRoot(r)]) if (!out.includes(d)) out.push(d);
9153
+ }
9154
+ return out;
9155
+ }
9126
9156
  function enforcementRoots() {
9127
9157
  try {
9128
9158
  const r = sessionRoot();
@@ -9383,6 +9413,19 @@ function swarmTouch(ctx, input) {
9383
9413
  fail("touch", err);
9384
9414
  }
9385
9415
  }
9416
+ function workerLacksTool(input, agentType, tool) {
9417
+ if (!EXEC_TOOLS.has(tool) || !isSwarmAgentType(agentType)) return false;
9418
+ try {
9419
+ for (const dir of swarmRoots(input)) {
9420
+ const config = activeSwarmConfig(dir);
9421
+ const found = config && findRole(config, agentType);
9422
+ if (found) return !roleHasShell(found.role);
9423
+ }
9424
+ } catch (err) {
9425
+ fail("shell", err);
9426
+ }
9427
+ return false;
9428
+ }
9386
9429
  function allowWith(updatedInput) {
9387
9430
  return {
9388
9431
  hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "allow", updatedInput }
@@ -9773,12 +9816,14 @@ export {
9773
9816
  commitContext,
9774
9817
  recallForError,
9775
9818
  isSwarmTool,
9819
+ spawnType,
9776
9820
  coordinationRoot,
9777
9821
  swarmPreAgent,
9778
9822
  failedText,
9779
9823
  rawEnforced,
9780
9824
  swarmGate,
9781
9825
  swarmTouch,
9826
+ workerLacksTool,
9782
9827
  swarmStampCaller,
9783
9828
  swarmAgentReturned,
9784
9829
  swarmSessionEnd,
@@ -9840,4 +9885,4 @@ queue-microtask/index.js:
9840
9885
  run-parallel/index.js:
9841
9886
  (*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
9842
9887
  */
9843
- //# sourceMappingURL=hook-chunk-MVOBVFQL.js.map
9888
+ //# sourceMappingURL=hook-chunk-DSLVDGOB.js.map
@@ -13,7 +13,7 @@ import {
13
13
  init_esm_shims,
14
14
  loadConfig,
15
15
  paths
16
- } from "./hook-chunk-IYHVLMJ4.js";
16
+ } from "./hook-chunk-BECSRJFD.js";
17
17
 
18
18
  // src/adjudicator/async.ts
19
19
  init_esm_shims();
@@ -3777,4 +3777,4 @@ export {
3777
3777
  parseJob,
3778
3778
  runAsyncJob
3779
3779
  };
3780
- //# sourceMappingURL=hook-chunk-77I6QQ43.js.map
3780
+ //# sourceMappingURL=hook-chunk-RYZAFUTT.js.map
@@ -8,7 +8,7 @@ import {
8
8
  manifestPath,
9
9
  readManifestAt,
10
10
  resolvePrice
11
- } from "./hook-chunk-MVOBVFQL.js";
11
+ } from "./hook-chunk-DSLVDGOB.js";
12
12
  import {
13
13
  adjudicateOne,
14
14
  briefUnitsOf,
@@ -18,17 +18,19 @@ import {
18
18
  resolveAdjudicator,
19
19
  spawnAsyncJob,
20
20
  topIntent
21
- } from "./hook-chunk-77I6QQ43.js";
21
+ } from "./hook-chunk-RYZAFUTT.js";
22
22
  import {
23
23
  AGENT_EFFORT_SINCE,
24
24
  KEPT_MODEL_FLAG,
25
25
  TIERS,
26
+ claudeConfigDir,
27
+ claudePluginsDir,
26
28
  getContext,
27
29
  getStorage,
28
30
  init_esm_shims,
29
31
  keptModel,
30
32
  tierOf
31
- } from "./hook-chunk-IYHVLMJ4.js";
33
+ } from "./hook-chunk-BECSRJFD.js";
32
34
 
33
35
  // src/adjudicator/hooks.ts
34
36
  init_esm_shims();
@@ -349,7 +351,7 @@ function projectDirs(root, cwd) {
349
351
  }
350
352
  function pluginDirs(plugin, env, home) {
351
353
  const out = /* @__PURE__ */ new Set();
352
- const pluginsRoot = env.CLAUDE_CODE_PLUGIN_CACHE_DIR?.trim() || join(home, ".claude", "plugins");
354
+ const pluginsRoot = claudePluginsDir(env, home);
353
355
  try {
354
356
  const j = JSON.parse(readFileSync(join(pluginsRoot, "installed_plugins.json"), "utf8"));
355
357
  for (const [key, val] of Object.entries(j?.plugins ?? {})) {
@@ -450,7 +452,7 @@ function resolveAgentPin(agentType, q) {
450
452
  const scopes = [];
451
453
  if (managed) scopes.push(["managed", join(managed, ".claude", "agents")]);
452
454
  for (const d of projectDirs(q.root, q.cwd)) scopes.push(["project", d]);
453
- scopes.push(["user", join(home, ".claude", "agents")]);
455
+ scopes.push(["user", join(claudeConfigDir(env, home), "agents")]);
454
456
  let truncated = false;
455
457
  for (const [source, dir] of scopes) {
456
458
  const found = byName(dir, agentType);
@@ -1824,4 +1826,4 @@ export {
1824
1826
  withModel,
1825
1827
  withNote
1826
1828
  };
1827
- //# sourceMappingURL=hook-hooks-U6GDOQSY.js.map
1829
+ //# sourceMappingURL=hook-hooks-IDTGXCFD.js.map