eminiar 0.13.0 → 0.13.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.
- package/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +43 -15
- package/bin/_resolve.sh +7 -4
- package/bin/em-hook +2 -1
- package/bin/em-server +2 -1
- package/bin/eminiar +2 -1
- package/dist/cli.js +10113 -8385
- package/dist/{hook-async-4MIP3VHX.js → hook-async-3TLK23ZY.js} +3 -3
- package/dist/{hook-chunk-IYHVLMJ4.js → hook-chunk-ETYHCPPH.js} +52 -25
- package/dist/{hook-chunk-77I6QQ43.js → hook-chunk-MVSMFCKL.js} +2 -2
- package/dist/{hook-chunk-MVOBVFQL.js → hook-chunk-ZLRLOPLR.js} +98 -33
- package/dist/{hook-hooks-U6GDOQSY.js → hook-hooks-5U2AI6W7.js} +8 -6
- package/dist/hook.js +318 -74
- package/dist/server.js +4417 -4078
- package/dist/ui/app.global.js +78 -72
- package/dist/ui/styles.css +4724 -1508
- package/eminiar.config.schema.json +2 -1
- package/package.json +1 -1
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
parseJob,
|
|
5
5
|
runAsyncJob,
|
|
6
6
|
spawnAsyncJob
|
|
7
|
-
} from "./hook-chunk-
|
|
8
|
-
import "./hook-chunk-
|
|
7
|
+
} from "./hook-chunk-MVSMFCKL.js";
|
|
8
|
+
import "./hook-chunk-ETYHCPPH.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-
|
|
15
|
+
//# sourceMappingURL=hook-async-3TLK23ZY.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.
|
|
20036
|
-
*
|
|
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({
|
|
@@ -20211,8 +20217,11 @@ var BaseConfigSchema = external_exports.object({
|
|
|
20211
20217
|
backend: external_exports.enum(["tree-sitter"]).default("tree-sitter")
|
|
20212
20218
|
}).prefault({}),
|
|
20213
20219
|
memories: external_exports.object({
|
|
20214
|
-
/**
|
|
20215
|
-
|
|
20220
|
+
/**
|
|
20221
|
+
* Project-relative directory of markdown memory files (`<topic>/<name>.md`); commit it.
|
|
20222
|
+
* Absolute paths and `..` segments are refused: reconcile repairs the headers of files there.
|
|
20223
|
+
*/
|
|
20224
|
+
dir: external_exports.string().regex(PROJECT_RELATIVE_PATH_RE, "must be a path inside the project (no leading / or ..)").default(".eminiar/memories")
|
|
20216
20225
|
}).prefault({}),
|
|
20217
20226
|
recall: external_exports.object({
|
|
20218
20227
|
/** Inject the memories and doc pages that match each prompt (UserPromptSubmit). */
|
|
@@ -20384,22 +20393,22 @@ function envOverrides() {
|
|
|
20384
20393
|
}
|
|
20385
20394
|
var PROJECT_ADJUDICATOR_KEYS = [
|
|
20386
20395
|
"enabled",
|
|
20387
|
-
"mode",
|
|
20388
20396
|
"surfaces",
|
|
20389
20397
|
"promptMode",
|
|
20390
20398
|
"minPromptChars",
|
|
20391
|
-
"tiers",
|
|
20392
20399
|
"weights",
|
|
20393
|
-
"apply",
|
|
20394
20400
|
"advice",
|
|
20395
20401
|
"embedding",
|
|
20396
20402
|
"learning",
|
|
20397
20403
|
"cache"
|
|
20398
20404
|
];
|
|
20405
|
+
function projectKeeps(adj, k) {
|
|
20406
|
+
return PROJECT_ADJUDICATOR_KEYS.includes(k) || k === "mode" && adj.mode === "advise";
|
|
20407
|
+
}
|
|
20399
20408
|
function droppedProjectAdjudicatorKeys(raw) {
|
|
20400
20409
|
const adj = raw.adjudicator;
|
|
20401
20410
|
if (!isPlainObject2(adj)) return [];
|
|
20402
|
-
return Object.keys(adj).filter((k) => !
|
|
20411
|
+
return Object.keys(adj).filter((k) => !projectKeeps(adj, k)).sort();
|
|
20403
20412
|
}
|
|
20404
20413
|
var CASE_INSENSITIVE_FS = process.platform === "darwin" || process.platform === "win32";
|
|
20405
20414
|
function realPath(p) {
|
|
@@ -20516,32 +20525,40 @@ function projectLayer(raw) {
|
|
|
20516
20525
|
if (!isPlainObject2(adj)) return raw;
|
|
20517
20526
|
if (findSecretFields(adj).length) return raw;
|
|
20518
20527
|
const kept = {};
|
|
20519
|
-
for (const k of
|
|
20528
|
+
for (const k of Object.keys(adj)) if (projectKeeps(adj, k)) kept[k] = adj[k];
|
|
20520
20529
|
return { ...ownJson(raw), adjudicator: kept };
|
|
20521
20530
|
}
|
|
20522
|
-
|
|
20523
|
-
|
|
20524
|
-
|
|
20525
|
-
|
|
20526
|
-
|
|
20527
|
-
|
|
20528
|
-
|
|
20531
|
+
var PROJECT_PATH_KEYS = [
|
|
20532
|
+
["docs", "manifest"],
|
|
20533
|
+
["memories", "dir"]
|
|
20534
|
+
];
|
|
20535
|
+
function withoutUnsafePaths(raw, source) {
|
|
20536
|
+
let out = raw;
|
|
20537
|
+
for (const [section, key] of PROJECT_PATH_KEYS) {
|
|
20538
|
+
const sec = out[section];
|
|
20539
|
+
if (!isPlainObject2(sec) || !Object.hasOwn(sec, key)) continue;
|
|
20540
|
+
const v = sec[key];
|
|
20541
|
+
if (typeof v === "string" && PROJECT_RELATIVE_PATH_RE.test(v)) continue;
|
|
20542
|
+
process.stderr.write(
|
|
20543
|
+
`eminiar: ignoring ${section}.${key} ${JSON.stringify(v)} in ${source}: it must be a path inside the project
|
|
20529
20544
|
`
|
|
20530
|
-
|
|
20531
|
-
|
|
20532
|
-
|
|
20545
|
+
);
|
|
20546
|
+
const { [key]: _dropped, ...rest } = ownJson(sec);
|
|
20547
|
+
out = { ...ownJson(out), [section]: rest };
|
|
20548
|
+
}
|
|
20549
|
+
return out;
|
|
20533
20550
|
}
|
|
20534
20551
|
function personalLayer(projectRoot) {
|
|
20535
20552
|
const file2 = paths().configFile;
|
|
20536
20553
|
const raw = readJson(file2);
|
|
20537
20554
|
const layer = !droppedProjectAdjudicatorKeys(raw).length || personalConfigTrusted(projectRoot, file2) ? raw : projectLayer(raw);
|
|
20538
|
-
return
|
|
20555
|
+
return withoutUnsafePaths(layer, file2);
|
|
20539
20556
|
}
|
|
20540
20557
|
function loadConfig(projectRoot) {
|
|
20541
20558
|
const merged = deepMerge(
|
|
20542
20559
|
deepMerge(
|
|
20543
20560
|
personalLayer(projectRoot),
|
|
20544
|
-
|
|
20561
|
+
withoutUnsafePaths(
|
|
20545
20562
|
projectLayer(readJson(join2(projectRoot, "eminiar.config.json"))),
|
|
20546
20563
|
"eminiar.config.json"
|
|
20547
20564
|
)
|
|
@@ -22603,7 +22620,7 @@ function usageWhere(f, opts = {}) {
|
|
|
22603
22620
|
var SqliteAdapter = class _SqliteAdapter {
|
|
22604
22621
|
constructor(path2, opts = {}) {
|
|
22605
22622
|
this.path = path2;
|
|
22606
|
-
this.db = new Database(path2, { timeout: 2e3 });
|
|
22623
|
+
this.db = new Database(path2, { timeout: opts.busyTimeoutMs ?? 2e3 });
|
|
22607
22624
|
this.swarm = new SqliteSwarmStore(this.db);
|
|
22608
22625
|
this.adjudicator = new SqliteAdjudicatorStore(this.db);
|
|
22609
22626
|
this.db.pragma("journal_mode = WAL");
|
|
@@ -23817,13 +23834,18 @@ var SqliteAdapter = class _SqliteAdapter {
|
|
|
23817
23834
|
|
|
23818
23835
|
// src/storage/index.ts
|
|
23819
23836
|
var open2 = /* @__PURE__ */ new Map();
|
|
23837
|
+
var busyTimeoutMs;
|
|
23838
|
+
function setStorageBusyTimeout(ms) {
|
|
23839
|
+
busyTimeoutMs = ms;
|
|
23840
|
+
}
|
|
23820
23841
|
function getStorage(ctx, opts = {}) {
|
|
23821
23842
|
const key = `${ctx.dbPath}|${opts.vectors === false ? "novec" : "vec"}`;
|
|
23822
23843
|
let adapter = open2.get(key);
|
|
23823
23844
|
if (!adapter) {
|
|
23824
23845
|
adapter = new SqliteAdapter(ctx.dbPath, {
|
|
23825
23846
|
dims: ctx.config.embeddings.dims,
|
|
23826
|
-
vectors: opts.vectors ?? true
|
|
23847
|
+
vectors: opts.vectors ?? true,
|
|
23848
|
+
...busyTimeoutMs === void 0 ? {} : { busyTimeoutMs }
|
|
23827
23849
|
});
|
|
23828
23850
|
open2.set(key, adapter);
|
|
23829
23851
|
}
|
|
@@ -24077,16 +24099,21 @@ export {
|
|
|
24077
24099
|
AGENT_EFFORT_SINCE,
|
|
24078
24100
|
TOOL_IDS,
|
|
24079
24101
|
DEFAULT_ROLES,
|
|
24102
|
+
claudeConfigDir,
|
|
24103
|
+
claudePluginsDir,
|
|
24080
24104
|
paths,
|
|
24081
24105
|
ensureDirs,
|
|
24082
24106
|
projectDir,
|
|
24107
|
+
PROJECT_RELATIVE_PATH_RE,
|
|
24083
24108
|
AdjudicatorConfigSchema,
|
|
24084
24109
|
loadConfig,
|
|
24085
24110
|
findProjectRoot,
|
|
24111
|
+
resolveProjectRoot,
|
|
24086
24112
|
getContext,
|
|
24087
24113
|
tierOf,
|
|
24088
24114
|
KEPT_MODEL_FLAG,
|
|
24089
24115
|
keptModel,
|
|
24116
|
+
setStorageBusyTimeout,
|
|
24090
24117
|
getStorage,
|
|
24091
24118
|
GUIDE_ORDER,
|
|
24092
24119
|
ev,
|
|
@@ -24096,4 +24123,4 @@ export {
|
|
|
24096
24123
|
classifyToolCall,
|
|
24097
24124
|
classifyAssistant
|
|
24098
24125
|
};
|
|
24099
|
-
//# sourceMappingURL=hook-chunk-
|
|
24126
|
+
//# sourceMappingURL=hook-chunk-ETYHCPPH.js.map
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
init_esm_shims,
|
|
14
14
|
loadConfig,
|
|
15
15
|
paths
|
|
16
|
-
} from "./hook-chunk-
|
|
16
|
+
} from "./hook-chunk-ETYHCPPH.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-
|
|
3780
|
+
//# sourceMappingURL=hook-chunk-MVSMFCKL.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createRequire as __emCreateRequire } from "node:module"; const require = __emCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
+
PROJECT_RELATIVE_PATH_RE,
|
|
3
4
|
TIERS,
|
|
4
5
|
__commonJS,
|
|
5
6
|
__require,
|
|
@@ -11,8 +12,9 @@ import {
|
|
|
11
12
|
getStorage,
|
|
12
13
|
init_esm_shims,
|
|
13
14
|
paths,
|
|
15
|
+
resolveProjectRoot,
|
|
14
16
|
tierOf
|
|
15
|
-
} from "./hook-chunk-
|
|
17
|
+
} from "./hook-chunk-ETYHCPPH.js";
|
|
16
18
|
|
|
17
19
|
// node_modules/fast-glob/out/utils/array.js
|
|
18
20
|
var require_array = __commonJS({
|
|
@@ -5883,9 +5885,10 @@ function empty() {
|
|
|
5883
5885
|
return { version: 1, sources: [] };
|
|
5884
5886
|
}
|
|
5885
5887
|
function normalize(raw) {
|
|
5886
|
-
if (!raw || typeof raw !== "object") return { manifest: empty(), dropped: 0 };
|
|
5888
|
+
if (!raw || typeof raw !== "object") return { manifest: empty(), dropped: 0, outside: [] };
|
|
5887
5889
|
const sources = Array.isArray(raw.sources) ? raw.sources : [];
|
|
5888
5890
|
const out = [];
|
|
5891
|
+
const outside = [];
|
|
5889
5892
|
const seen = /* @__PURE__ */ new Set();
|
|
5890
5893
|
for (const s of sources) {
|
|
5891
5894
|
if (!s || typeof s !== "object" || typeof s.name !== "string") continue;
|
|
@@ -5893,22 +5896,37 @@ function normalize(raw) {
|
|
|
5893
5896
|
if (s.kind !== "url" && s.kind !== "path") continue;
|
|
5894
5897
|
if (s.kind === "url" && !(Array.isArray(s.urls) && s.urls.length)) continue;
|
|
5895
5898
|
if (s.kind === "path" && typeof s.path !== "string") continue;
|
|
5899
|
+
if (s.kind === "path" && !PROJECT_RELATIVE_PATH_RE.test(s.path)) {
|
|
5900
|
+
process.stderr.write(
|
|
5901
|
+
`eminiar: ignoring docs source ${JSON.stringify(s.name)}: its path ${JSON.stringify(s.path)} must be inside the project
|
|
5902
|
+
`
|
|
5903
|
+
);
|
|
5904
|
+
outside.push(s.name);
|
|
5905
|
+
continue;
|
|
5906
|
+
}
|
|
5896
5907
|
seen.add(s.name);
|
|
5897
5908
|
out.push({
|
|
5898
5909
|
...s,
|
|
5899
5910
|
addedAt: typeof s.addedAt === "string" ? s.addedAt : (/* @__PURE__ */ new Date(0)).toISOString()
|
|
5900
5911
|
});
|
|
5901
5912
|
}
|
|
5902
|
-
return {
|
|
5913
|
+
return {
|
|
5914
|
+
manifest: { version: 1, sources: out },
|
|
5915
|
+
dropped: sources.length - out.length,
|
|
5916
|
+
outside
|
|
5917
|
+
};
|
|
5903
5918
|
}
|
|
5904
|
-
function lossyReason(raw, dropped) {
|
|
5919
|
+
function lossyReason(raw, dropped, outside, removing) {
|
|
5905
5920
|
if (raw.version !== 1)
|
|
5906
5921
|
return raw.version === void 0 ? "it has no version (this eminiar writes version 1)" : `it has version ${JSON.stringify(raw.version)}, and this eminiar only writes version 1`;
|
|
5907
5922
|
const extra = Object.keys(raw).filter((k) => k !== "version" && k !== "sources");
|
|
5908
5923
|
if (extra.length) return `it has keys this eminiar does not know (${extra.sort().join(", ")})`;
|
|
5909
5924
|
if (Object.hasOwn(raw, "sources") && !Array.isArray(raw.sources))
|
|
5910
5925
|
return "its sources is not an array";
|
|
5911
|
-
|
|
5926
|
+
const rest = outside.filter((n) => n !== removing);
|
|
5927
|
+
const lost = dropped - (outside.length - rest.length);
|
|
5928
|
+
if (lost)
|
|
5929
|
+
return `${lost} of its sources ${lost === 1 ? "is" : "are"} not valid entries${rest.length ? ` (${rest.join(", ")}: path outside the project)` : ""}`;
|
|
5912
5930
|
return void 0;
|
|
5913
5931
|
}
|
|
5914
5932
|
var MANIFEST_MAX_BYTES = 1024 * 1024;
|
|
@@ -5985,12 +6003,12 @@ function probeManifestAt(file, opts = {}) {
|
|
|
5985
6003
|
}
|
|
5986
6004
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
5987
6005
|
return { state: "refused", reason: "it is not a JSON object" };
|
|
5988
|
-
const { manifest, dropped } = normalize(raw);
|
|
6006
|
+
const { manifest, dropped, outside } = normalize(raw);
|
|
5989
6007
|
if (opts.write) {
|
|
5990
|
-
const lossy = lossyReason(raw, dropped);
|
|
6008
|
+
const lossy = lossyReason(raw, dropped, outside, opts.removing);
|
|
5991
6009
|
if (lossy) return { state: "refused", reason: lossy };
|
|
5992
6010
|
}
|
|
5993
|
-
return { state: "ok", manifest };
|
|
6011
|
+
return { state: "ok", manifest, ...outside.length ? { outside } : {} };
|
|
5994
6012
|
} catch (err) {
|
|
5995
6013
|
const code = err.code;
|
|
5996
6014
|
if (code === "ENOENT") return { state: "missing" };
|
|
@@ -6018,7 +6036,7 @@ function readManifest(ctx) {
|
|
|
6018
6036
|
// src/swarm/hooks.ts
|
|
6019
6037
|
init_esm_shims();
|
|
6020
6038
|
import { execFileSync } from "child_process";
|
|
6021
|
-
import { readFileSync as readFileSync7, realpathSync as
|
|
6039
|
+
import { readFileSync as readFileSync7, realpathSync as realpathSync5, statSync as statSync5 } from "fs";
|
|
6022
6040
|
import { basename as basename2, dirname as dirname3, join as join8, resolve as resolve3 } from "path";
|
|
6023
6041
|
|
|
6024
6042
|
// src/swarm/agents.ts
|
|
@@ -6065,6 +6083,14 @@ function yaml() {
|
|
|
6065
6083
|
yamlLib ??= createRequire(import.meta.url)("yaml");
|
|
6066
6084
|
return yamlLib;
|
|
6067
6085
|
}
|
|
6086
|
+
var EXEC_TOOLS = /* @__PURE__ */ new Set([
|
|
6087
|
+
"em_execute",
|
|
6088
|
+
"em_execute_file",
|
|
6089
|
+
"em_batch_execute"
|
|
6090
|
+
]);
|
|
6091
|
+
function roleHasShell(role) {
|
|
6092
|
+
return (role.tools?.includes("Bash") ?? true) && !role.disallowedTools?.includes("Bash");
|
|
6093
|
+
}
|
|
6068
6094
|
var EM_MCP_PREFIXES = ["mcp__plugin_eminiar_eminiar__", "mcp__eminiar__"];
|
|
6069
6095
|
var AGENTS_REL = ".claude/agents";
|
|
6070
6096
|
function agentsDir(root) {
|
|
@@ -6078,21 +6104,26 @@ var TOPOLOGY_RULE = {
|
|
|
6078
6104
|
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
6105
|
pipeline: "work moves in stages. You can claim a task only once every task of the earlier stages is done."
|
|
6080
6106
|
};
|
|
6081
|
-
function workerTools(tools) {
|
|
6107
|
+
function workerTools(tools, shell = tools.includes("Bash")) {
|
|
6082
6108
|
const out = tools.includes("ToolSearch") ? [...tools] : [...tools, "ToolSearch"];
|
|
6083
6109
|
for (const prefix of EM_MCP_PREFIXES)
|
|
6084
|
-
for (const t of WORKER_EM_TOOLS)
|
|
6110
|
+
for (const t of WORKER_EM_TOOLS)
|
|
6111
|
+
if ((shell || !EXEC_TOOLS.has(t)) && !out.includes(prefix + t)) out.push(prefix + t);
|
|
6085
6112
|
return out;
|
|
6086
6113
|
}
|
|
6114
|
+
var execToolNames = () => EM_MCP_PREFIXES.flatMap((prefix) => [...EXEC_TOOLS].map((t) => prefix + t));
|
|
6087
6115
|
function frontmatter(swarm, role) {
|
|
6088
6116
|
const fm = {
|
|
6089
6117
|
name: role.agentType,
|
|
6090
6118
|
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
6119
|
};
|
|
6092
6120
|
if (role.model) fm.model = role.model;
|
|
6093
|
-
if (role.tools) fm.tools = workerTools(role.tools).join(", ");
|
|
6121
|
+
if (role.tools) fm.tools = workerTools(role.tools, roleHasShell(role)).join(", ");
|
|
6094
6122
|
const spawns = role.tools?.some((t) => t === "Agent" || t === "Task");
|
|
6095
|
-
const
|
|
6123
|
+
const noShell = role.disallowedTools?.includes("Bash") ? execToolNames() : [];
|
|
6124
|
+
const disallowed = [
|
|
6125
|
+
.../* @__PURE__ */ new Set([...role.disallowedTools ?? [], ...spawns ? [] : ["Agent"], ...noShell])
|
|
6126
|
+
];
|
|
6096
6127
|
if (disallowed.length) fm.disallowedTools = disallowed.join(", ");
|
|
6097
6128
|
if (role.skills.length) fm.skills = role.skills;
|
|
6098
6129
|
if (role.hooks) {
|
|
@@ -6111,6 +6142,7 @@ var hashOf = (fm, rest, range) => createHash("sha1").update(range ? `range=${ran
|
|
|
6111
6142
|
${fm}
|
|
6112
6143
|
${rest}` : `${fm}
|
|
6113
6144
|
${rest}`).digest("hex").slice(0, 12);
|
|
6145
|
+
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
6146
|
function renderAgentFile(config, swarm, role) {
|
|
6115
6147
|
const fm = yaml().stringify(frontmatter(swarm, role), { lineWidth: 0 }).trimEnd();
|
|
6116
6148
|
if (fm.includes("---"))
|
|
@@ -6124,12 +6156,15 @@ function renderAgentFile(config, swarm, role) {
|
|
|
6124
6156
|
...role.prompt ? [role.prompt, ""] : [],
|
|
6125
6157
|
"## Swarm protocol",
|
|
6126
6158
|
"",
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6159
|
+
...[
|
|
6160
|
+
'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.',
|
|
6161
|
+
'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.',
|
|
6162
|
+
...!role.isolation && roleHasShell(role) ? [SHARED_TREE_RULE] : [],
|
|
6163
|
+
'Share what other workers need with `em_swarm {action:"post", key, value}` and read theirs with `em_swarm {action:"read"}`.',
|
|
6164
|
+
'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.',
|
|
6165
|
+
"Record durable decisions with `em_remember` so later sessions know them.",
|
|
6166
|
+
"Your final message goes back to the coordinator: lead with the outcome, then the files you changed and anything left open."
|
|
6167
|
+
].map((step, i) => `${i + 1}. ${step}`),
|
|
6133
6168
|
""
|
|
6134
6169
|
].join("\n");
|
|
6135
6170
|
const range = role.range ? modelRangeText(role.range) : void 0;
|
|
@@ -6336,7 +6371,7 @@ init_esm_shims();
|
|
|
6336
6371
|
// src/index/indexer.ts
|
|
6337
6372
|
init_esm_shims();
|
|
6338
6373
|
var import_fast_glob = __toESM(require_out4(), 1);
|
|
6339
|
-
import { readFileSync as readFileSync2, statSync as statSync2 } from "fs";
|
|
6374
|
+
import { existsSync, readFileSync as readFileSync2, realpathSync as realpathSync3, statSync as statSync2 } from "fs";
|
|
6340
6375
|
import { relative as relative3, resolve } from "path";
|
|
6341
6376
|
|
|
6342
6377
|
// src/chunker/index.ts
|
|
@@ -6717,7 +6752,7 @@ function readFileRisk(db) {
|
|
|
6717
6752
|
|
|
6718
6753
|
// src/session/brief.ts
|
|
6719
6754
|
init_esm_shims();
|
|
6720
|
-
import { existsSync as
|
|
6755
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
|
|
6721
6756
|
import { join as join4 } from "path";
|
|
6722
6757
|
|
|
6723
6758
|
// src/memory/frontmatter.ts
|
|
@@ -6752,9 +6787,12 @@ function parseMemoryFile(text) {
|
|
|
6752
6787
|
init_esm_shims();
|
|
6753
6788
|
var import_fast_glob2 = __toESM(require_out4(), 1);
|
|
6754
6789
|
import {
|
|
6755
|
-
existsSync,
|
|
6790
|
+
existsSync as existsSync2,
|
|
6791
|
+
lstatSync as lstatSync3,
|
|
6756
6792
|
mkdirSync as mkdirSync3,
|
|
6793
|
+
readdirSync as readdirSync2,
|
|
6757
6794
|
readFileSync as readFileSync3,
|
|
6795
|
+
realpathSync as realpathSync4,
|
|
6758
6796
|
renameSync as renameSync3,
|
|
6759
6797
|
statSync as statSync3,
|
|
6760
6798
|
unlinkSync as unlinkSync2,
|
|
@@ -6830,7 +6868,7 @@ function historyLine(db) {
|
|
|
6830
6868
|
}
|
|
6831
6869
|
function overviewParagraph(ctx) {
|
|
6832
6870
|
const file = join4(memoriesDir(ctx), "onboarding", "overview.md");
|
|
6833
|
-
if (!
|
|
6871
|
+
if (!existsSync3(file)) return void 0;
|
|
6834
6872
|
try {
|
|
6835
6873
|
const body = parseMemoryFile(readFileSync4(file, "utf8")).body.trim();
|
|
6836
6874
|
const para = body.split(/\n\s*\n/).map(
|
|
@@ -7704,13 +7742,13 @@ init_esm_shims();
|
|
|
7704
7742
|
// src/swarm/runtime.ts
|
|
7705
7743
|
init_esm_shims();
|
|
7706
7744
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
7707
|
-
import { existsSync as
|
|
7745
|
+
import { existsSync as existsSync5, statSync as statSync4 } from "fs";
|
|
7708
7746
|
import { isAbsolute as isAbsolute2, join as join6, relative as relative5 } from "path";
|
|
7709
7747
|
|
|
7710
7748
|
// src/swarm/config.ts
|
|
7711
7749
|
init_esm_shims();
|
|
7712
7750
|
import { createHash as createHash3 } from "crypto";
|
|
7713
|
-
import { existsSync as
|
|
7751
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5 } from "fs";
|
|
7714
7752
|
import { createRequire as createRequire2 } from "module";
|
|
7715
7753
|
import { join as join5 } from "path";
|
|
7716
7754
|
|
|
@@ -8088,7 +8126,7 @@ function roleRange(defaults, a, at, issue) {
|
|
|
8088
8126
|
function swarmFile(root) {
|
|
8089
8127
|
for (const rel of SWARM_FILES) {
|
|
8090
8128
|
const file = join5(root, rel);
|
|
8091
|
-
if (
|
|
8129
|
+
if (existsSync4(file)) return { file, rel, exists: true };
|
|
8092
8130
|
}
|
|
8093
8131
|
return { file: join5(root, SWARM_FILES[0]), rel: SWARM_FILES[0], exists: false };
|
|
8094
8132
|
}
|
|
@@ -9082,7 +9120,7 @@ function coordinationRoot(root) {
|
|
|
9082
9120
|
} catch {
|
|
9083
9121
|
return root;
|
|
9084
9122
|
}
|
|
9085
|
-
if (basename2(common) === ".git") return
|
|
9123
|
+
if (basename2(common) === ".git") return realpathSync5(dirname3(common));
|
|
9086
9124
|
const out = execFileSync("git", ["worktree", "list", "--porcelain"], {
|
|
9087
9125
|
cwd: root,
|
|
9088
9126
|
encoding: "utf8",
|
|
@@ -9091,8 +9129,8 @@ function coordinationRoot(root) {
|
|
|
9091
9129
|
});
|
|
9092
9130
|
const first = /^worktree (.+)$/m.exec(out)?.[1];
|
|
9093
9131
|
if (!first || /^bare$/m.test(out.split("\n\n")[0] ?? "")) return root;
|
|
9094
|
-
const main =
|
|
9095
|
-
return main !==
|
|
9132
|
+
const main = realpathSync5(first);
|
|
9133
|
+
return main !== realpathSync5(common) && statSync5(join8(main, ".git"), { throwIfNoEntry: false }) ? main : root;
|
|
9096
9134
|
} catch {
|
|
9097
9135
|
return root;
|
|
9098
9136
|
}
|
|
@@ -9109,7 +9147,7 @@ function sessionRoot() {
|
|
|
9109
9147
|
process.env.CLAUDE_PROJECT_DIR || process.env.EMINIAR_PROJECT_ROOT || process.cwd()
|
|
9110
9148
|
);
|
|
9111
9149
|
try {
|
|
9112
|
-
return
|
|
9150
|
+
return realpathSync5(root);
|
|
9113
9151
|
} catch {
|
|
9114
9152
|
return root;
|
|
9115
9153
|
}
|
|
@@ -9123,6 +9161,18 @@ function orderedRoots(hookRoot) {
|
|
|
9123
9161
|
if (hookRoot && !out.includes(hookRoot)) out.push(hookRoot);
|
|
9124
9162
|
return out;
|
|
9125
9163
|
}
|
|
9164
|
+
function swarmRoots(input) {
|
|
9165
|
+
let hook;
|
|
9166
|
+
try {
|
|
9167
|
+
hook = resolveProjectRoot(input.cwd || void 0);
|
|
9168
|
+
} catch {
|
|
9169
|
+
}
|
|
9170
|
+
const out = [];
|
|
9171
|
+
for (const r of orderedRoots(hook)) {
|
|
9172
|
+
for (const d of [r, coordinationRoot(r)]) if (!out.includes(d)) out.push(d);
|
|
9173
|
+
}
|
|
9174
|
+
return out;
|
|
9175
|
+
}
|
|
9126
9176
|
function enforcementRoots() {
|
|
9127
9177
|
try {
|
|
9128
9178
|
const r = sessionRoot();
|
|
@@ -9383,6 +9433,19 @@ function swarmTouch(ctx, input) {
|
|
|
9383
9433
|
fail("touch", err);
|
|
9384
9434
|
}
|
|
9385
9435
|
}
|
|
9436
|
+
function workerLacksTool(input, agentType, tool) {
|
|
9437
|
+
if (!EXEC_TOOLS.has(tool) || !isSwarmAgentType(agentType)) return false;
|
|
9438
|
+
try {
|
|
9439
|
+
for (const dir of swarmRoots(input)) {
|
|
9440
|
+
const config = activeSwarmConfig(dir);
|
|
9441
|
+
const found = config && findRole(config, agentType);
|
|
9442
|
+
if (found) return !roleHasShell(found.role);
|
|
9443
|
+
}
|
|
9444
|
+
} catch (err) {
|
|
9445
|
+
fail("shell", err);
|
|
9446
|
+
}
|
|
9447
|
+
return false;
|
|
9448
|
+
}
|
|
9386
9449
|
function allowWith(updatedInput) {
|
|
9387
9450
|
return {
|
|
9388
9451
|
hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "allow", updatedInput }
|
|
@@ -9757,12 +9820,12 @@ var FALLBACK_MODEL = "claude-sonnet-5-5";
|
|
|
9757
9820
|
export {
|
|
9758
9821
|
hookLog,
|
|
9759
9822
|
agentFileRange,
|
|
9760
|
-
indexContent,
|
|
9761
|
-
git,
|
|
9762
9823
|
DOCS_PREFIX,
|
|
9763
9824
|
manifestPath,
|
|
9764
9825
|
readManifestAt,
|
|
9765
9826
|
readManifest,
|
|
9827
|
+
indexContent,
|
|
9828
|
+
git,
|
|
9766
9829
|
memoriesDir,
|
|
9767
9830
|
renderProjectBrief,
|
|
9768
9831
|
recordShown,
|
|
@@ -9773,12 +9836,14 @@ export {
|
|
|
9773
9836
|
commitContext,
|
|
9774
9837
|
recallForError,
|
|
9775
9838
|
isSwarmTool,
|
|
9839
|
+
spawnType,
|
|
9776
9840
|
coordinationRoot,
|
|
9777
9841
|
swarmPreAgent,
|
|
9778
9842
|
failedText,
|
|
9779
9843
|
rawEnforced,
|
|
9780
9844
|
swarmGate,
|
|
9781
9845
|
swarmTouch,
|
|
9846
|
+
workerLacksTool,
|
|
9782
9847
|
swarmStampCaller,
|
|
9783
9848
|
swarmAgentReturned,
|
|
9784
9849
|
swarmSessionEnd,
|
|
@@ -9840,4 +9905,4 @@ queue-microtask/index.js:
|
|
|
9840
9905
|
run-parallel/index.js:
|
|
9841
9906
|
(*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
|
|
9842
9907
|
*/
|
|
9843
|
-
//# sourceMappingURL=hook-chunk-
|
|
9908
|
+
//# sourceMappingURL=hook-chunk-ZLRLOPLR.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
manifestPath,
|
|
9
9
|
readManifestAt,
|
|
10
10
|
resolvePrice
|
|
11
|
-
} from "./hook-chunk-
|
|
11
|
+
} from "./hook-chunk-ZLRLOPLR.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-
|
|
21
|
+
} from "./hook-chunk-MVSMFCKL.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-
|
|
33
|
+
} from "./hook-chunk-ETYHCPPH.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
|
|
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(
|
|
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-
|
|
1829
|
+
//# sourceMappingURL=hook-hooks-5U2AI6W7.js.map
|