@pleri/olam-cli 0.1.146 → 0.1.148
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/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +26 -1
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/doctor.d.ts +31 -3
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +274 -6
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/services.d.ts +41 -3
- package/dist/commands/services.d.ts.map +1 -1
- package/dist/commands/services.js +221 -13
- package/dist/commands/services.js.map +1 -1
- package/dist/commands/skills-migrate-hooks-back.d.ts +19 -0
- package/dist/commands/skills-migrate-hooks-back.d.ts.map +1 -0
- package/dist/commands/skills-migrate-hooks-back.js +83 -0
- package/dist/commands/skills-migrate-hooks-back.js.map +1 -0
- package/dist/commands/skills-migrate-hooks.d.ts +40 -0
- package/dist/commands/skills-migrate-hooks.d.ts.map +1 -0
- package/dist/commands/skills-migrate-hooks.js +178 -0
- package/dist/commands/skills-migrate-hooks.js.map +1 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +49 -1
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/substrate-audit-log.d.ts +2 -0
- package/dist/commands/substrate-audit-log.d.ts.map +1 -1
- package/dist/commands/substrate-audit-log.js +13 -0
- package/dist/commands/substrate-audit-log.js.map +1 -1
- package/dist/image-digests.json +7 -7
- package/dist/index.js +4390 -2615
- package/dist/index.js.map +1 -1
- package/dist/lib/auth-refresh-kubernetes.d.ts +62 -0
- package/dist/lib/auth-refresh-kubernetes.d.ts.map +1 -0
- package/dist/lib/auth-refresh-kubernetes.js +127 -0
- package/dist/lib/auth-refresh-kubernetes.js.map +1 -0
- package/dist/lib/kubectl-wrap.d.ts +6 -0
- package/dist/lib/kubectl-wrap.d.ts.map +1 -1
- package/dist/lib/kubectl-wrap.js +6 -1
- package/dist/lib/kubectl-wrap.js.map +1 -1
- package/dist/lib/manifest-refresh.d.ts +8 -1
- package/dist/lib/manifest-refresh.d.ts.map +1 -1
- package/dist/lib/manifest-refresh.js +17 -7
- package/dist/lib/manifest-refresh.js.map +1 -1
- package/dist/lib/peripheral-registry.d.ts +36 -0
- package/dist/lib/peripheral-registry.d.ts.map +1 -0
- package/dist/lib/peripheral-registry.js +55 -0
- package/dist/lib/peripheral-registry.js.map +1 -0
- package/dist/lib/port-forward.d.ts +67 -0
- package/dist/lib/port-forward.d.ts.map +1 -1
- package/dist/lib/port-forward.js +153 -0
- package/dist/lib/port-forward.js.map +1 -1
- package/dist/lib/upgrade-kubernetes.d.ts +35 -11
- package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
- package/dist/lib/upgrade-kubernetes.js +265 -21
- package/dist/lib/upgrade-kubernetes.js.map +1 -1
- package/dist/mcp-server.js +1196 -412
- package/host-cp/k8s/manifests/auth-service/10-serviceaccount.yaml +8 -0
- package/host-cp/k8s/manifests/auth-service/20-rbac.yaml +34 -0
- package/host-cp/k8s/manifests/auth-service/30-configmap.yaml +24 -0
- package/host-cp/k8s/manifests/auth-service/45-pvc.yaml +25 -0
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +114 -0
- package/host-cp/k8s/manifests/auth-service/60-service.yaml +21 -0
- package/host-cp/k8s/manifests/kg-service/10-serviceaccount.yaml +8 -0
- package/host-cp/k8s/manifests/kg-service/20-rbac.yaml +34 -0
- package/host-cp/k8s/manifests/kg-service/30-configmap.yaml +18 -0
- package/host-cp/k8s/manifests/kg-service/45-pvc.yaml +25 -0
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +108 -0
- package/host-cp/k8s/manifests/kg-service/60-service.yaml +21 -0
- package/host-cp/k8s/manifests/mcp-auth-service/10-serviceaccount.yaml +8 -0
- package/host-cp/k8s/manifests/mcp-auth-service/20-rbac.yaml +34 -0
- package/host-cp/k8s/manifests/mcp-auth-service/30-configmap.yaml +18 -0
- package/host-cp/k8s/manifests/mcp-auth-service/45-pvc.yaml +25 -0
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +114 -0
- package/host-cp/k8s/manifests/mcp-auth-service/60-service.yaml +21 -0
- package/host-cp/k8s/manifests/memory-service/10-serviceaccount.yaml +8 -0
- package/host-cp/k8s/manifests/memory-service/20-rbac.yaml +34 -0
- package/host-cp/k8s/manifests/memory-service/30-configmap.yaml +20 -0
- package/host-cp/k8s/manifests/memory-service/45-pvc.yaml +25 -0
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +116 -0
- package/host-cp/k8s/manifests/memory-service/60-service.yaml +21 -0
- package/host-cp/k8s/templates/auth-service-secret-template.yaml +28 -0
- package/host-cp/k8s/templates/kg-service-secret-template.yaml +28 -0
- package/host-cp/k8s/templates/mcp-auth-service-secret-template.yaml +28 -0
- package/host-cp/k8s/templates/memory-service-secret-template.yaml +29 -0
- package/host-cp/src/plan-chat-service.mjs +22 -3
- package/host-cp/src/server.mjs +4 -4
- package/package.json +1 -1
package/dist/mcp-server.js
CHANGED
|
@@ -445,8 +445,8 @@ var init_parseUtil = __esm({
|
|
|
445
445
|
init_errors();
|
|
446
446
|
init_en();
|
|
447
447
|
makeIssue = (params) => {
|
|
448
|
-
const { data, path:
|
|
449
|
-
const fullPath = [...
|
|
448
|
+
const { data, path: path46, errorMaps, issueData } = params;
|
|
449
|
+
const fullPath = [...path46, ...issueData.path || []];
|
|
450
450
|
const fullIssue = {
|
|
451
451
|
...issueData,
|
|
452
452
|
path: fullPath
|
|
@@ -754,11 +754,11 @@ var init_types = __esm({
|
|
|
754
754
|
init_parseUtil();
|
|
755
755
|
init_util();
|
|
756
756
|
ParseInputLazyPath = class {
|
|
757
|
-
constructor(parent, value,
|
|
757
|
+
constructor(parent, value, path46, key) {
|
|
758
758
|
this._cachedPath = [];
|
|
759
759
|
this.parent = parent;
|
|
760
760
|
this.data = value;
|
|
761
|
-
this._path =
|
|
761
|
+
this._path = path46;
|
|
762
762
|
this._key = key;
|
|
763
763
|
}
|
|
764
764
|
get path() {
|
|
@@ -7332,8 +7332,8 @@ var require_utils = __commonJS({
|
|
|
7332
7332
|
}
|
|
7333
7333
|
return ind;
|
|
7334
7334
|
}
|
|
7335
|
-
function removeDotSegments(
|
|
7336
|
-
let input =
|
|
7335
|
+
function removeDotSegments(path46) {
|
|
7336
|
+
let input = path46;
|
|
7337
7337
|
const output = [];
|
|
7338
7338
|
let nextSlash = -1;
|
|
7339
7339
|
let len = 0;
|
|
@@ -7532,8 +7532,8 @@ var require_schemes = __commonJS({
|
|
|
7532
7532
|
wsComponent.secure = void 0;
|
|
7533
7533
|
}
|
|
7534
7534
|
if (wsComponent.resourceName) {
|
|
7535
|
-
const [
|
|
7536
|
-
wsComponent.path =
|
|
7535
|
+
const [path46, query] = wsComponent.resourceName.split("?");
|
|
7536
|
+
wsComponent.path = path46 && path46 !== "/" ? path46 : void 0;
|
|
7537
7537
|
wsComponent.query = query;
|
|
7538
7538
|
wsComponent.resourceName = void 0;
|
|
7539
7539
|
}
|
|
@@ -10895,12 +10895,12 @@ var require_dist = __commonJS({
|
|
|
10895
10895
|
throw new Error(`Unknown format "${name}"`);
|
|
10896
10896
|
return f;
|
|
10897
10897
|
};
|
|
10898
|
-
function addFormats(ajv, list,
|
|
10898
|
+
function addFormats(ajv, list, fs46, exportName) {
|
|
10899
10899
|
var _a3;
|
|
10900
10900
|
var _b;
|
|
10901
10901
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
10902
10902
|
for (const f of list)
|
|
10903
|
-
ajv.addFormat(f,
|
|
10903
|
+
ajv.addFormat(f, fs46[f]);
|
|
10904
10904
|
}
|
|
10905
10905
|
module.exports = exports = formatsPlugin;
|
|
10906
10906
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -11008,7 +11008,7 @@ import YAML from "yaml";
|
|
|
11008
11008
|
function bootstrapStepCmd(entry) {
|
|
11009
11009
|
return typeof entry === "string" ? entry : entry.cmd;
|
|
11010
11010
|
}
|
|
11011
|
-
function refineForbiddenKeys(value,
|
|
11011
|
+
function refineForbiddenKeys(value, path46, ctx, rejectSource) {
|
|
11012
11012
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
11013
11013
|
return;
|
|
11014
11014
|
}
|
|
@@ -11016,12 +11016,12 @@ function refineForbiddenKeys(value, path44, ctx, rejectSource) {
|
|
|
11016
11016
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
11017
11017
|
ctx.addIssue({
|
|
11018
11018
|
code: external_exports.ZodIssueCode.custom,
|
|
11019
|
-
path: [...
|
|
11019
|
+
path: [...path46, key],
|
|
11020
11020
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
11021
11021
|
});
|
|
11022
11022
|
continue;
|
|
11023
11023
|
}
|
|
11024
|
-
if (rejectSource &&
|
|
11024
|
+
if (rejectSource && path46.length === 0 && key === "source") {
|
|
11025
11025
|
ctx.addIssue({
|
|
11026
11026
|
code: external_exports.ZodIssueCode.custom,
|
|
11027
11027
|
path: ["source"],
|
|
@@ -11029,21 +11029,21 @@ function refineForbiddenKeys(value, path44, ctx, rejectSource) {
|
|
|
11029
11029
|
});
|
|
11030
11030
|
continue;
|
|
11031
11031
|
}
|
|
11032
|
-
refineForbiddenKeys(value[key], [...
|
|
11032
|
+
refineForbiddenKeys(value[key], [...path46, key], ctx, false);
|
|
11033
11033
|
}
|
|
11034
11034
|
}
|
|
11035
|
-
function rejectForbiddenKeys(value,
|
|
11035
|
+
function rejectForbiddenKeys(value, path46, rejectSource) {
|
|
11036
11036
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
11037
11037
|
return;
|
|
11038
11038
|
}
|
|
11039
11039
|
for (const key of Object.keys(value)) {
|
|
11040
11040
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
11041
|
-
throw new Error(`[manifest] ${
|
|
11041
|
+
throw new Error(`[manifest] ${path46}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
11042
11042
|
}
|
|
11043
11043
|
if (rejectSource && key === "source") {
|
|
11044
|
-
throw new Error(`[manifest] ${
|
|
11044
|
+
throw new Error(`[manifest] ${path46}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
11045
11045
|
}
|
|
11046
|
-
rejectForbiddenKeys(value[key], `${
|
|
11046
|
+
rejectForbiddenKeys(value[key], `${path46}.${key}`, false);
|
|
11047
11047
|
}
|
|
11048
11048
|
}
|
|
11049
11049
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -11921,7 +11921,7 @@ function isAbsoluteOrTilde(p) {
|
|
|
11921
11921
|
function hasNoTraversalComponents(p) {
|
|
11922
11922
|
return !p.split("/").some((seg) => seg === "..");
|
|
11923
11923
|
}
|
|
11924
|
-
var RepoEntrySchema, PortMapSchema, SeedSqlFileSchema, SeedCommandSchema, SeedFixtureCopySchema, SeedSchema, RunbookSchema, GlobalConfigSchema, DEFAULT_GLOBAL_CONFIG;
|
|
11924
|
+
var RepoEntrySchema, PortMapSchema, SeedSqlFileSchema, SeedCommandSchema, SeedFixtureCopySchema, SeedSchema, RunbookSchema, MetaHookBlockKindSchema, GlobalConfigSchema, DEFAULT_GLOBAL_CONFIG;
|
|
11925
11925
|
var init_schema4 = __esm({
|
|
11926
11926
|
"../core/dist/global-config/schema.js"() {
|
|
11927
11927
|
"use strict";
|
|
@@ -11971,11 +11971,19 @@ var init_schema4 = __esm({
|
|
|
11971
11971
|
env: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.string())).optional(),
|
|
11972
11972
|
updatedAt: external_exports.number().int().nonnegative()
|
|
11973
11973
|
});
|
|
11974
|
+
MetaHookBlockKindSchema = external_exports.enum(["memory-recall", "memory-classify"]);
|
|
11974
11975
|
GlobalConfigSchema = external_exports.object({
|
|
11975
11976
|
schemaVersion: external_exports.literal(1),
|
|
11976
11977
|
repos: external_exports.array(RepoEntrySchema).optional().default([]),
|
|
11977
11978
|
runbooks: external_exports.array(RunbookSchema).optional().default([]),
|
|
11978
|
-
skillSources: external_exports.array(SkillSourceSchema).optional().default([])
|
|
11979
|
+
skillSources: external_exports.array(SkillSourceSchema).optional().default([]),
|
|
11980
|
+
/**
|
|
11981
|
+
* Phase B B4 — per-block disable list. Operator escape-hatch when a
|
|
11982
|
+
* specific meta-hook misbehaves; engine `injectMetaHooks` filters
|
|
11983
|
+
* these out regardless of services-status detection. CLI
|
|
11984
|
+
* `--meta-hooks-disabled <a,b>` flag (deferred) can override per-call.
|
|
11985
|
+
*/
|
|
11986
|
+
metaHooksDisabled: external_exports.array(MetaHookBlockKindSchema).optional().default([])
|
|
11979
11987
|
}).strip().superRefine((val, ctx) => {
|
|
11980
11988
|
const repoNames = val.repos.map((r) => r.name);
|
|
11981
11989
|
const repoDupes = repoNames.filter((n, i) => repoNames.indexOf(n) !== i);
|
|
@@ -12002,7 +12010,8 @@ var init_schema4 = __esm({
|
|
|
12002
12010
|
schemaVersion: 1,
|
|
12003
12011
|
repos: [],
|
|
12004
12012
|
runbooks: [],
|
|
12005
|
-
skillSources: []
|
|
12013
|
+
skillSources: [],
|
|
12014
|
+
metaHooksDisabled: []
|
|
12006
12015
|
};
|
|
12007
12016
|
}
|
|
12008
12017
|
});
|
|
@@ -12402,7 +12411,14 @@ var init_trust_audit_log = __esm({
|
|
|
12402
12411
|
"use strict";
|
|
12403
12412
|
init_v3();
|
|
12404
12413
|
SKILL_SOURCES_AUDIT_LOG_FILENAME = "skill-sources-audit.log";
|
|
12405
|
-
TrustActionSchema = external_exports.enum([
|
|
12414
|
+
TrustActionSchema = external_exports.enum([
|
|
12415
|
+
"added",
|
|
12416
|
+
"rejected",
|
|
12417
|
+
"auto-rejected",
|
|
12418
|
+
"failed",
|
|
12419
|
+
"removed",
|
|
12420
|
+
"meta-hook-stripped"
|
|
12421
|
+
]);
|
|
12406
12422
|
TrustMethodSchema = external_exports.enum(["flag", "interactive", "auto-reject-tty", "none"]);
|
|
12407
12423
|
TrustAuditEntrySchema = external_exports.object({
|
|
12408
12424
|
timestamp: external_exports.string().min(1),
|
|
@@ -13317,8 +13333,167 @@ var init_symlink_deployer = __esm({
|
|
|
13317
13333
|
}
|
|
13318
13334
|
});
|
|
13319
13335
|
|
|
13320
|
-
// ../core/dist/
|
|
13336
|
+
// ../core/dist/meta-hooks/memory-recall.js
|
|
13321
13337
|
import * as fs21 from "node:fs";
|
|
13338
|
+
function buildMemoryRecallHookEntry() {
|
|
13339
|
+
return {
|
|
13340
|
+
matcher: OLAM_META_MEMORY_RECALL_MATCHER,
|
|
13341
|
+
hooks: [
|
|
13342
|
+
{
|
|
13343
|
+
type: "command",
|
|
13344
|
+
command: `OLAM_META_SENTINEL=${OLAM_META_MEMORY_RECALL_SENTINEL}; ${OLAM_META_NOOP_GUARD} node "${OLAM_META_MEMORY_RECALL_SCRIPT_PATH}"`,
|
|
13345
|
+
timeout: OLAM_META_MEMORY_RECALL_TIMEOUT_MS
|
|
13346
|
+
}
|
|
13347
|
+
]
|
|
13348
|
+
};
|
|
13349
|
+
}
|
|
13350
|
+
function computeMemoryRecallUninstall(settings) {
|
|
13351
|
+
const matchers = settings.hooks?.PreToolUse;
|
|
13352
|
+
if (!Array.isArray(matchers) || matchers.length === 0) {
|
|
13353
|
+
return { status: "not-found" };
|
|
13354
|
+
}
|
|
13355
|
+
let changed = false;
|
|
13356
|
+
const filteredMatchers = [];
|
|
13357
|
+
for (const matcher of matchers) {
|
|
13358
|
+
const innerHooks = matcher.hooks ?? [];
|
|
13359
|
+
const keptInner = innerHooks.filter((h) => {
|
|
13360
|
+
if (typeof h.command === "string" && h.command.includes(OLAM_META_MEMORY_RECALL_SENTINEL)) {
|
|
13361
|
+
changed = true;
|
|
13362
|
+
return false;
|
|
13363
|
+
}
|
|
13364
|
+
return true;
|
|
13365
|
+
});
|
|
13366
|
+
if (keptInner.length === 0 && innerHooks.length > 0) {
|
|
13367
|
+
changed = true;
|
|
13368
|
+
continue;
|
|
13369
|
+
}
|
|
13370
|
+
if (keptInner.length === innerHooks.length) {
|
|
13371
|
+
filteredMatchers.push(matcher);
|
|
13372
|
+
} else {
|
|
13373
|
+
filteredMatchers.push({ ...matcher, hooks: keptInner });
|
|
13374
|
+
}
|
|
13375
|
+
}
|
|
13376
|
+
if (!changed)
|
|
13377
|
+
return { status: "not-found" };
|
|
13378
|
+
const next = {
|
|
13379
|
+
...settings,
|
|
13380
|
+
hooks: {
|
|
13381
|
+
...settings.hooks,
|
|
13382
|
+
PreToolUse: filteredMatchers
|
|
13383
|
+
}
|
|
13384
|
+
};
|
|
13385
|
+
if (filteredMatchers.length === 0) {
|
|
13386
|
+
const otherStages = Object.keys(next.hooks ?? {}).filter((k) => k !== "PreToolUse");
|
|
13387
|
+
if (otherStages.length === 0) {
|
|
13388
|
+
delete next.hooks;
|
|
13389
|
+
} else {
|
|
13390
|
+
delete next.hooks.PreToolUse;
|
|
13391
|
+
}
|
|
13392
|
+
}
|
|
13393
|
+
return { status: "removed", settingsAfter: next };
|
|
13394
|
+
}
|
|
13395
|
+
function matchMemoryRecallSentinel(commandLine) {
|
|
13396
|
+
return commandLine.includes(OLAM_META_MEMORY_RECALL_SENTINEL);
|
|
13397
|
+
}
|
|
13398
|
+
var OLAM_META_MEMORY_RECALL_SENTINEL, OLAM_META_MEMORY_RECALL_STAGE, OLAM_META_MEMORY_RECALL_MATCHER, OLAM_META_MEMORY_RECALL_TIMEOUT_MS, OLAM_META_MEMORY_RECALL_SCRIPT_PATH, OLAM_META_NOOP_GUARD;
|
|
13399
|
+
var init_memory_recall = __esm({
|
|
13400
|
+
"../core/dist/meta-hooks/memory-recall.js"() {
|
|
13401
|
+
"use strict";
|
|
13402
|
+
OLAM_META_MEMORY_RECALL_SENTINEL = "olam-meta-memory-recall-v1";
|
|
13403
|
+
OLAM_META_MEMORY_RECALL_STAGE = "PreToolUse";
|
|
13404
|
+
OLAM_META_MEMORY_RECALL_MATCHER = "Bash|Edit|MultiEdit|Write|Read|NotebookEdit";
|
|
13405
|
+
OLAM_META_MEMORY_RECALL_TIMEOUT_MS = 5e3;
|
|
13406
|
+
OLAM_META_MEMORY_RECALL_SCRIPT_PATH = "$HOME/.claude/scripts/agentmemory-classifier/agentmemory-recall-trigger.mjs";
|
|
13407
|
+
OLAM_META_NOOP_GUARD = "command -v olam >/dev/null 2>&1 || exit 0;";
|
|
13408
|
+
}
|
|
13409
|
+
});
|
|
13410
|
+
|
|
13411
|
+
// ../core/dist/meta-hooks/memory-classify.js
|
|
13412
|
+
import * as fs22 from "node:fs";
|
|
13413
|
+
function buildMemoryClassifyHookEntry() {
|
|
13414
|
+
return {
|
|
13415
|
+
matcher: OLAM_META_MEMORY_CLASSIFY_MATCHER,
|
|
13416
|
+
hooks: [
|
|
13417
|
+
{
|
|
13418
|
+
type: "command",
|
|
13419
|
+
command: `OLAM_META_SENTINEL=${OLAM_META_MEMORY_CLASSIFY_SENTINEL}; ${OLAM_META_NOOP_GUARD2} node "${OLAM_META_MEMORY_CLASSIFY_SCRIPT_PATH}"`,
|
|
13420
|
+
timeout: OLAM_META_MEMORY_CLASSIFY_TIMEOUT_MS
|
|
13421
|
+
}
|
|
13422
|
+
]
|
|
13423
|
+
};
|
|
13424
|
+
}
|
|
13425
|
+
function computeMemoryClassifyUninstall(settings) {
|
|
13426
|
+
const matchers = settings.hooks?.PostToolUse;
|
|
13427
|
+
if (!Array.isArray(matchers) || matchers.length === 0) {
|
|
13428
|
+
return { status: "not-found" };
|
|
13429
|
+
}
|
|
13430
|
+
let changed = false;
|
|
13431
|
+
const filteredMatchers = [];
|
|
13432
|
+
for (const matcher of matchers) {
|
|
13433
|
+
const innerHooks = matcher.hooks ?? [];
|
|
13434
|
+
const keptInner = innerHooks.filter((h) => {
|
|
13435
|
+
if (typeof h.command === "string" && h.command.includes(OLAM_META_MEMORY_CLASSIFY_SENTINEL)) {
|
|
13436
|
+
changed = true;
|
|
13437
|
+
return false;
|
|
13438
|
+
}
|
|
13439
|
+
return true;
|
|
13440
|
+
});
|
|
13441
|
+
if (keptInner.length === 0 && innerHooks.length > 0) {
|
|
13442
|
+
changed = true;
|
|
13443
|
+
continue;
|
|
13444
|
+
}
|
|
13445
|
+
if (keptInner.length === innerHooks.length) {
|
|
13446
|
+
filteredMatchers.push(matcher);
|
|
13447
|
+
} else {
|
|
13448
|
+
filteredMatchers.push({ ...matcher, hooks: keptInner });
|
|
13449
|
+
}
|
|
13450
|
+
}
|
|
13451
|
+
if (!changed)
|
|
13452
|
+
return { status: "not-found" };
|
|
13453
|
+
const next = {
|
|
13454
|
+
...settings,
|
|
13455
|
+
hooks: {
|
|
13456
|
+
...settings.hooks,
|
|
13457
|
+
PostToolUse: filteredMatchers
|
|
13458
|
+
}
|
|
13459
|
+
};
|
|
13460
|
+
if (filteredMatchers.length === 0) {
|
|
13461
|
+
const otherStages = Object.keys(next.hooks ?? {}).filter((k) => k !== "PostToolUse");
|
|
13462
|
+
if (otherStages.length === 0) {
|
|
13463
|
+
delete next.hooks;
|
|
13464
|
+
} else {
|
|
13465
|
+
delete next.hooks.PostToolUse;
|
|
13466
|
+
}
|
|
13467
|
+
}
|
|
13468
|
+
return { status: "removed", settingsAfter: next };
|
|
13469
|
+
}
|
|
13470
|
+
function matchMemoryClassifySentinel(commandLine) {
|
|
13471
|
+
return commandLine.includes(OLAM_META_MEMORY_CLASSIFY_SENTINEL);
|
|
13472
|
+
}
|
|
13473
|
+
var OLAM_META_MEMORY_CLASSIFY_SENTINEL, OLAM_META_MEMORY_CLASSIFY_STAGE, OLAM_META_MEMORY_CLASSIFY_MATCHER, OLAM_META_MEMORY_CLASSIFY_TIMEOUT_MS, OLAM_META_MEMORY_CLASSIFY_SCRIPT_PATH, OLAM_META_NOOP_GUARD2;
|
|
13474
|
+
var init_memory_classify = __esm({
|
|
13475
|
+
"../core/dist/meta-hooks/memory-classify.js"() {
|
|
13476
|
+
"use strict";
|
|
13477
|
+
OLAM_META_MEMORY_CLASSIFY_SENTINEL = "olam-meta-memory-classify-v1";
|
|
13478
|
+
OLAM_META_MEMORY_CLASSIFY_STAGE = "PostToolUse";
|
|
13479
|
+
OLAM_META_MEMORY_CLASSIFY_MATCHER = "Bash|Edit|MultiEdit|Write|Read|NotebookEdit";
|
|
13480
|
+
OLAM_META_MEMORY_CLASSIFY_TIMEOUT_MS = 5e3;
|
|
13481
|
+
OLAM_META_MEMORY_CLASSIFY_SCRIPT_PATH = "$HOME/.claude/scripts/agentmemory-classifier/agentmemory-classify-queue.mjs";
|
|
13482
|
+
OLAM_META_NOOP_GUARD2 = "command -v olam >/dev/null 2>&1 || exit 0;";
|
|
13483
|
+
}
|
|
13484
|
+
});
|
|
13485
|
+
|
|
13486
|
+
// ../core/dist/meta-hooks/index.js
|
|
13487
|
+
var init_meta_hooks = __esm({
|
|
13488
|
+
"../core/dist/meta-hooks/index.js"() {
|
|
13489
|
+
"use strict";
|
|
13490
|
+
init_memory_recall();
|
|
13491
|
+
init_memory_classify();
|
|
13492
|
+
}
|
|
13493
|
+
});
|
|
13494
|
+
|
|
13495
|
+
// ../core/dist/skill-sync/settings-merger.js
|
|
13496
|
+
import * as fs23 from "node:fs";
|
|
13322
13497
|
import * as os14 from "node:os";
|
|
13323
13498
|
import * as path22 from "node:path";
|
|
13324
13499
|
function claudeSettingsPath() {
|
|
@@ -13346,32 +13521,66 @@ function dedupeByMatcher(entries) {
|
|
|
13346
13521
|
}
|
|
13347
13522
|
return [...map.values()];
|
|
13348
13523
|
}
|
|
13524
|
+
function commandsInEntry(entry) {
|
|
13525
|
+
const cmds = [];
|
|
13526
|
+
const direct = entry["command"];
|
|
13527
|
+
if (typeof direct === "string")
|
|
13528
|
+
cmds.push(direct);
|
|
13529
|
+
const inner = entry["hooks"];
|
|
13530
|
+
if (Array.isArray(inner)) {
|
|
13531
|
+
for (const h of inner) {
|
|
13532
|
+
if (h && typeof h === "object" && typeof h.command === "string") {
|
|
13533
|
+
cmds.push(h.command);
|
|
13534
|
+
}
|
|
13535
|
+
}
|
|
13536
|
+
}
|
|
13537
|
+
return cmds;
|
|
13538
|
+
}
|
|
13539
|
+
function applyDualWriteDedup(incoming, preserved) {
|
|
13540
|
+
const preservedCommands = preserved.flatMap(commandsInEntry);
|
|
13541
|
+
const preservedHas = (sentinel) => preservedCommands.some((c) => c.includes(sentinel));
|
|
13542
|
+
let droppedCount = 0;
|
|
13543
|
+
const droppedCommands = [];
|
|
13544
|
+
const kept = incoming.filter((entry) => {
|
|
13545
|
+
const incomingCommands = commandsInEntry(entry);
|
|
13546
|
+
for (const rule of DUAL_WRITE_DEDUP_RULES) {
|
|
13547
|
+
const hasIncomingScript = incomingCommands.some((c) => c.includes(rule.incomingCommandSubstring));
|
|
13548
|
+
if (hasIncomingScript && preservedHas(rule.preservedSentinel)) {
|
|
13549
|
+
droppedCount += 1;
|
|
13550
|
+
droppedCommands.push(...incomingCommands.filter((c) => c.includes(rule.incomingCommandSubstring)));
|
|
13551
|
+
return false;
|
|
13552
|
+
}
|
|
13553
|
+
}
|
|
13554
|
+
return true;
|
|
13555
|
+
});
|
|
13556
|
+
return { kept, droppedCount, droppedCommands };
|
|
13557
|
+
}
|
|
13349
13558
|
function tagOlam(entry) {
|
|
13350
13559
|
return { ...entry, [OLAM_SKILLS_MARKER]: true };
|
|
13351
13560
|
}
|
|
13352
13561
|
function readJson(file) {
|
|
13353
|
-
return JSON.parse(
|
|
13562
|
+
return JSON.parse(fs23.readFileSync(file, "utf-8"));
|
|
13354
13563
|
}
|
|
13355
13564
|
function rotateBackups(backupDir) {
|
|
13356
|
-
if (!
|
|
13565
|
+
if (!fs23.existsSync(backupDir))
|
|
13357
13566
|
return;
|
|
13358
|
-
const files =
|
|
13567
|
+
const files = fs23.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path22.join(backupDir, f), mtime: fs23.statSync(path22.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
13359
13568
|
for (const f of files.slice(BACKUP_RETENTION)) {
|
|
13360
13569
|
try {
|
|
13361
|
-
|
|
13570
|
+
fs23.unlinkSync(f.full);
|
|
13362
13571
|
} catch {
|
|
13363
13572
|
}
|
|
13364
13573
|
}
|
|
13365
13574
|
}
|
|
13366
13575
|
function backupSettings() {
|
|
13367
13576
|
const src = claudeSettingsPath();
|
|
13368
|
-
if (!
|
|
13577
|
+
if (!fs23.existsSync(src))
|
|
13369
13578
|
return void 0;
|
|
13370
13579
|
const dir = settingsBackupDir();
|
|
13371
|
-
|
|
13580
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
13372
13581
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
13373
13582
|
const dest = path22.join(dir, `settings-${stamp}.json`);
|
|
13374
|
-
|
|
13583
|
+
fs23.copyFileSync(src, dest);
|
|
13375
13584
|
rotateBackups(dir);
|
|
13376
13585
|
return dest;
|
|
13377
13586
|
}
|
|
@@ -13379,7 +13588,7 @@ function mergeSettings(input) {
|
|
|
13379
13588
|
const settingsPath = claudeSettingsPath();
|
|
13380
13589
|
const backupPath = backupSettings();
|
|
13381
13590
|
let base = {};
|
|
13382
|
-
if (
|
|
13591
|
+
if (fs23.existsSync(settingsPath)) {
|
|
13383
13592
|
try {
|
|
13384
13593
|
base = readJson(settingsPath);
|
|
13385
13594
|
} catch {
|
|
@@ -13411,13 +13620,18 @@ function mergeSettings(input) {
|
|
|
13411
13620
|
...olamHooksByCategory.keys()
|
|
13412
13621
|
]);
|
|
13413
13622
|
let hooksAdded = 0;
|
|
13623
|
+
let dualWriteDeduped = 0;
|
|
13624
|
+
const dualWriteDroppedCommands = [];
|
|
13414
13625
|
for (const cat of categories) {
|
|
13415
13626
|
const existing = Array.isArray(existingHooks[cat]) ? existingHooks[cat] : [];
|
|
13416
13627
|
const preserved = existing.filter((e) => !e[OLAM_SKILLS_MARKER]);
|
|
13417
13628
|
const olam = olamHooksByCategory.get(cat) ?? [];
|
|
13418
13629
|
const olamDeduped = dedupeByMatcher(olam);
|
|
13419
|
-
|
|
13420
|
-
|
|
13630
|
+
const { kept: olamFinal, droppedCount, droppedCommands } = applyDualWriteDedup(olamDeduped, preserved);
|
|
13631
|
+
dualWriteDeduped += droppedCount;
|
|
13632
|
+
dualWriteDroppedCommands.push(...droppedCommands);
|
|
13633
|
+
mergedHooks[cat] = [...preserved, ...olamFinal];
|
|
13634
|
+
hooksAdded += olamFinal.length;
|
|
13421
13635
|
}
|
|
13422
13636
|
const permSet = /* @__PURE__ */ new Set();
|
|
13423
13637
|
for (const file of input.permissionFiles) {
|
|
@@ -13442,18 +13656,29 @@ function mergeSettings(input) {
|
|
|
13442
13656
|
...input.permissionFiles.length > 0 ? { allow: [...permSet] } : {}
|
|
13443
13657
|
}
|
|
13444
13658
|
};
|
|
13445
|
-
|
|
13659
|
+
fs23.mkdirSync(path22.dirname(settingsPath), { recursive: true });
|
|
13446
13660
|
const tmp = `${settingsPath}.tmp-${process.pid}`;
|
|
13447
|
-
|
|
13448
|
-
|
|
13449
|
-
return { backupPath, hooksAdded, permissionsCount: permSet.size };
|
|
13661
|
+
fs23.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
|
|
13662
|
+
fs23.renameSync(tmp, settingsPath);
|
|
13663
|
+
return { backupPath, hooksAdded, permissionsCount: permSet.size, dualWriteDeduped, dualWriteDroppedCommands };
|
|
13450
13664
|
}
|
|
13451
|
-
var OLAM_SKILLS_MARKER, BACKUP_RETENTION;
|
|
13665
|
+
var OLAM_SKILLS_MARKER, BACKUP_RETENTION, DUAL_WRITE_DEDUP_RULES;
|
|
13452
13666
|
var init_settings_merger = __esm({
|
|
13453
13667
|
"../core/dist/skill-sync/settings-merger.js"() {
|
|
13454
13668
|
"use strict";
|
|
13669
|
+
init_meta_hooks();
|
|
13455
13670
|
OLAM_SKILLS_MARKER = "_olamSkillsManaged";
|
|
13456
13671
|
BACKUP_RETENTION = 30;
|
|
13672
|
+
DUAL_WRITE_DEDUP_RULES = [
|
|
13673
|
+
{
|
|
13674
|
+
preservedSentinel: OLAM_META_MEMORY_RECALL_SENTINEL,
|
|
13675
|
+
incomingCommandSubstring: "agentmemory-recall-trigger.mjs"
|
|
13676
|
+
},
|
|
13677
|
+
{
|
|
13678
|
+
preservedSentinel: OLAM_META_MEMORY_CLASSIFY_SENTINEL,
|
|
13679
|
+
incomingCommandSubstring: "agentmemory-classify-queue.mjs"
|
|
13680
|
+
}
|
|
13681
|
+
];
|
|
13457
13682
|
}
|
|
13458
13683
|
});
|
|
13459
13684
|
|
|
@@ -13491,7 +13716,7 @@ var init_schema5 = __esm({
|
|
|
13491
13716
|
|
|
13492
13717
|
// ../core/dist/skill-sync/per-project-override.js
|
|
13493
13718
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
13494
|
-
import * as
|
|
13719
|
+
import * as fs24 from "node:fs";
|
|
13495
13720
|
import * as path23 from "node:path";
|
|
13496
13721
|
import { parse as parseYaml3 } from "yaml";
|
|
13497
13722
|
function findProjectOverride(startDir) {
|
|
@@ -13499,8 +13724,8 @@ function findProjectOverride(startDir) {
|
|
|
13499
13724
|
const root = path23.parse(dir).root;
|
|
13500
13725
|
while (true) {
|
|
13501
13726
|
const candidate = path23.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
|
|
13502
|
-
if (
|
|
13503
|
-
const raw =
|
|
13727
|
+
if (fs24.existsSync(candidate) && fs24.statSync(candidate).isFile()) {
|
|
13728
|
+
const raw = fs24.readFileSync(candidate, "utf-8");
|
|
13504
13729
|
let parsed;
|
|
13505
13730
|
try {
|
|
13506
13731
|
parsed = parseYaml3(raw);
|
|
@@ -13559,7 +13784,7 @@ var init_per_project_override = __esm({
|
|
|
13559
13784
|
});
|
|
13560
13785
|
|
|
13561
13786
|
// ../core/dist/skill-sync/source-lock.js
|
|
13562
|
-
import * as
|
|
13787
|
+
import * as fs25 from "node:fs";
|
|
13563
13788
|
import * as os15 from "node:os";
|
|
13564
13789
|
import * as path24 from "node:path";
|
|
13565
13790
|
function defaultIsPidAlive(pid) {
|
|
@@ -13576,7 +13801,7 @@ function sleep3(ms) {
|
|
|
13576
13801
|
}
|
|
13577
13802
|
function readLockMeta(lockPath) {
|
|
13578
13803
|
try {
|
|
13579
|
-
const raw =
|
|
13804
|
+
const raw = fs25.readFileSync(lockPath, "utf-8");
|
|
13580
13805
|
const parsed = JSON.parse(raw);
|
|
13581
13806
|
if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
|
|
13582
13807
|
return parsed;
|
|
@@ -13595,12 +13820,12 @@ function isLockStale(meta2, opts) {
|
|
|
13595
13820
|
}
|
|
13596
13821
|
function tryAcquireOnce(lockPath, meta2, opts) {
|
|
13597
13822
|
try {
|
|
13598
|
-
|
|
13599
|
-
const fd =
|
|
13823
|
+
fs25.mkdirSync(path24.dirname(lockPath), { recursive: true });
|
|
13824
|
+
const fd = fs25.openSync(lockPath, "wx", 384);
|
|
13600
13825
|
try {
|
|
13601
|
-
|
|
13826
|
+
fs25.writeSync(fd, JSON.stringify(meta2));
|
|
13602
13827
|
} finally {
|
|
13603
|
-
|
|
13828
|
+
fs25.closeSync(fd);
|
|
13604
13829
|
}
|
|
13605
13830
|
return true;
|
|
13606
13831
|
} catch (err) {
|
|
@@ -13610,14 +13835,14 @@ function tryAcquireOnce(lockPath, meta2, opts) {
|
|
|
13610
13835
|
const existing = readLockMeta(lockPath);
|
|
13611
13836
|
if (existing === void 0) {
|
|
13612
13837
|
try {
|
|
13613
|
-
|
|
13838
|
+
fs25.unlinkSync(lockPath);
|
|
13614
13839
|
} catch {
|
|
13615
13840
|
}
|
|
13616
13841
|
return tryAcquireOnce(lockPath, meta2, opts);
|
|
13617
13842
|
}
|
|
13618
13843
|
if (isLockStale(existing, opts)) {
|
|
13619
13844
|
try {
|
|
13620
|
-
|
|
13845
|
+
fs25.unlinkSync(lockPath);
|
|
13621
13846
|
} catch {
|
|
13622
13847
|
}
|
|
13623
13848
|
return tryAcquireOnce(lockPath, meta2, opts);
|
|
@@ -13646,7 +13871,7 @@ async function acquireSourceLock(clonePath, options = {}) {
|
|
|
13646
13871
|
lockPath,
|
|
13647
13872
|
release: () => {
|
|
13648
13873
|
try {
|
|
13649
|
-
|
|
13874
|
+
fs25.unlinkSync(lockPath);
|
|
13650
13875
|
} catch {
|
|
13651
13876
|
}
|
|
13652
13877
|
}
|
|
@@ -13685,17 +13910,475 @@ var init_source_lock = __esm({
|
|
|
13685
13910
|
}
|
|
13686
13911
|
});
|
|
13687
13912
|
|
|
13688
|
-
// ../core/dist/skill-sync/
|
|
13689
|
-
import * as
|
|
13913
|
+
// ../core/dist/skill-sync/settings-json-lock.js
|
|
13914
|
+
import * as fs26 from "node:fs";
|
|
13690
13915
|
import * as os16 from "node:os";
|
|
13691
13916
|
import * as path25 from "node:path";
|
|
13917
|
+
function defaultSettingsJsonLockPath() {
|
|
13918
|
+
const stateDir = process.env["OLAM_STATE_DIR"] ?? path25.join(os16.homedir(), ".olam", "state");
|
|
13919
|
+
return path25.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
|
|
13920
|
+
}
|
|
13921
|
+
function defaultIsPidAlive2(pid) {
|
|
13922
|
+
try {
|
|
13923
|
+
process.kill(pid, 0);
|
|
13924
|
+
return true;
|
|
13925
|
+
} catch (err) {
|
|
13926
|
+
const code = err.code;
|
|
13927
|
+
return code === "EPERM";
|
|
13928
|
+
}
|
|
13929
|
+
}
|
|
13930
|
+
function sleep4(ms) {
|
|
13931
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
13932
|
+
}
|
|
13933
|
+
function readLockMeta2(lockPath) {
|
|
13934
|
+
try {
|
|
13935
|
+
const raw = fs26.readFileSync(lockPath, "utf-8");
|
|
13936
|
+
const parsed = JSON.parse(raw);
|
|
13937
|
+
if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
|
|
13938
|
+
return parsed;
|
|
13939
|
+
}
|
|
13940
|
+
} catch {
|
|
13941
|
+
}
|
|
13942
|
+
return void 0;
|
|
13943
|
+
}
|
|
13944
|
+
function isLockStale2(meta2, opts) {
|
|
13945
|
+
const ageMs = opts.now - meta2.timestamp;
|
|
13946
|
+
if (ageMs < opts.staleLockMs / 2)
|
|
13947
|
+
return false;
|
|
13948
|
+
if (meta2.hostname !== os16.hostname()) {
|
|
13949
|
+
return ageMs > opts.staleLockMs * 2;
|
|
13950
|
+
}
|
|
13951
|
+
if (!opts.isPidAlive(meta2.pid))
|
|
13952
|
+
return true;
|
|
13953
|
+
return ageMs > opts.staleLockMs;
|
|
13954
|
+
}
|
|
13955
|
+
function tryAcquireOnce2(lockPath, meta2, opts) {
|
|
13956
|
+
for (let attempt = 0; attempt <= MAX_STEAL_ATTEMPTS; attempt += 1) {
|
|
13957
|
+
try {
|
|
13958
|
+
fs26.mkdirSync(path25.dirname(lockPath), { recursive: true });
|
|
13959
|
+
const fd = fs26.openSync(lockPath, "wx", 384);
|
|
13960
|
+
try {
|
|
13961
|
+
fs26.writeSync(fd, JSON.stringify(meta2));
|
|
13962
|
+
} finally {
|
|
13963
|
+
fs26.closeSync(fd);
|
|
13964
|
+
}
|
|
13965
|
+
return true;
|
|
13966
|
+
} catch (err) {
|
|
13967
|
+
const code = err.code;
|
|
13968
|
+
if (code !== "EEXIST")
|
|
13969
|
+
throw err;
|
|
13970
|
+
}
|
|
13971
|
+
if (attempt >= MAX_STEAL_ATTEMPTS) {
|
|
13972
|
+
return false;
|
|
13973
|
+
}
|
|
13974
|
+
const existing = readLockMeta2(lockPath);
|
|
13975
|
+
const isStale = existing === void 0 || isLockStale2(existing, opts);
|
|
13976
|
+
if (!isStale) {
|
|
13977
|
+
return false;
|
|
13978
|
+
}
|
|
13979
|
+
const victimPath = `${lockPath}.victim-${process.pid}-${attempt}-${Date.now()}`;
|
|
13980
|
+
try {
|
|
13981
|
+
fs26.renameSync(lockPath, victimPath);
|
|
13982
|
+
try {
|
|
13983
|
+
fs26.unlinkSync(victimPath);
|
|
13984
|
+
} catch {
|
|
13985
|
+
}
|
|
13986
|
+
} catch (err) {
|
|
13987
|
+
const code = err.code;
|
|
13988
|
+
if (code !== "ENOENT")
|
|
13989
|
+
throw err;
|
|
13990
|
+
}
|
|
13991
|
+
}
|
|
13992
|
+
return false;
|
|
13993
|
+
}
|
|
13994
|
+
async function acquireSettingsJsonLock(options = {}) {
|
|
13995
|
+
const lockPath = options.lockPath ?? defaultSettingsJsonLockPath();
|
|
13996
|
+
const acquireTimeoutMs = options.acquireTimeoutMs ?? DEFAULT_ACQUIRE_TIMEOUT_MS2;
|
|
13997
|
+
const staleLockMs = options.staleLockMs ?? DEFAULT_STALE_LOCK_MS2;
|
|
13998
|
+
const now = options.now ?? Date.now;
|
|
13999
|
+
const isPidAlive2 = options.isPidAlive ?? defaultIsPidAlive2;
|
|
14000
|
+
const deadline = now() + acquireTimeoutMs;
|
|
14001
|
+
let backoffMs = 25;
|
|
14002
|
+
while (true) {
|
|
14003
|
+
const meta2 = {
|
|
14004
|
+
pid: process.pid,
|
|
14005
|
+
hostname: os16.hostname(),
|
|
14006
|
+
timestamp: now(),
|
|
14007
|
+
...options.reason ? { reason: options.reason } : {}
|
|
14008
|
+
};
|
|
14009
|
+
const acquired = tryAcquireOnce2(lockPath, meta2, { now: now(), staleLockMs, isPidAlive: isPidAlive2 });
|
|
14010
|
+
if (acquired) {
|
|
14011
|
+
return {
|
|
14012
|
+
lockPath,
|
|
14013
|
+
release: () => {
|
|
14014
|
+
try {
|
|
14015
|
+
fs26.unlinkSync(lockPath);
|
|
14016
|
+
} catch {
|
|
14017
|
+
}
|
|
14018
|
+
}
|
|
14019
|
+
};
|
|
14020
|
+
}
|
|
14021
|
+
if (now() >= deadline) {
|
|
14022
|
+
const existing = readLockMeta2(lockPath);
|
|
14023
|
+
const held = existing ? `(held by pid ${existing.pid} on ${existing.hostname}, since ${new Date(existing.timestamp).toISOString()})` : "(holder unknown)";
|
|
14024
|
+
throw new SettingsJsonLockError(`failed to acquire settings.json lock at ${lockPath} within ${acquireTimeoutMs}ms ${held}`);
|
|
14025
|
+
}
|
|
14026
|
+
await sleep4(Math.min(backoffMs, 200));
|
|
14027
|
+
backoffMs = Math.min(backoffMs * 2, 200);
|
|
14028
|
+
}
|
|
14029
|
+
}
|
|
14030
|
+
async function withSettingsJsonLock(fn, options) {
|
|
14031
|
+
const { release } = await acquireSettingsJsonLock(options);
|
|
14032
|
+
try {
|
|
14033
|
+
return await fn();
|
|
14034
|
+
} finally {
|
|
14035
|
+
release();
|
|
14036
|
+
}
|
|
14037
|
+
}
|
|
14038
|
+
var SETTINGS_JSON_LOCK_FILENAME, DEFAULT_ACQUIRE_TIMEOUT_MS2, DEFAULT_STALE_LOCK_MS2, SettingsJsonLockError, MAX_STEAL_ATTEMPTS;
|
|
14039
|
+
var init_settings_json_lock = __esm({
|
|
14040
|
+
"../core/dist/skill-sync/settings-json-lock.js"() {
|
|
14041
|
+
"use strict";
|
|
14042
|
+
SETTINGS_JSON_LOCK_FILENAME = ".settings-json.lock";
|
|
14043
|
+
DEFAULT_ACQUIRE_TIMEOUT_MS2 = 1e4;
|
|
14044
|
+
DEFAULT_STALE_LOCK_MS2 = 5 * 6e4;
|
|
14045
|
+
SettingsJsonLockError = class extends Error {
|
|
14046
|
+
constructor(message) {
|
|
14047
|
+
super(message);
|
|
14048
|
+
this.name = "SettingsJsonLockError";
|
|
14049
|
+
}
|
|
14050
|
+
};
|
|
14051
|
+
MAX_STEAL_ATTEMPTS = 3;
|
|
14052
|
+
}
|
|
14053
|
+
});
|
|
14054
|
+
|
|
14055
|
+
// ../core/dist/services-status/memory-probe.js
|
|
14056
|
+
async function probeMemoryBridge(opts = {}) {
|
|
14057
|
+
const port2 = opts.port ?? DEFAULT_MEMORY_PORT;
|
|
14058
|
+
const healthPath = opts.healthPath ?? DEFAULT_HEALTH_PATH;
|
|
14059
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
14060
|
+
const url2 = `http://127.0.0.1:${port2}${healthPath}`;
|
|
14061
|
+
const t0 = Date.now();
|
|
14062
|
+
try {
|
|
14063
|
+
const res = await fetch(url2, {
|
|
14064
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
14065
|
+
// CP3 LOW fix: refuse to follow redirects. A local attacker
|
|
14066
|
+
// controlling the bridge port (or a misconfigured bridge
|
|
14067
|
+
// returning 3xx) could redirect to an external URL; default
|
|
14068
|
+
// `redirect: 'follow'` would leak timing + reachability.
|
|
14069
|
+
redirect: "error"
|
|
14070
|
+
});
|
|
14071
|
+
await res.text().catch(() => "");
|
|
14072
|
+
const latencyMs = Date.now() - t0;
|
|
14073
|
+
if (res.ok) {
|
|
14074
|
+
return { up: true, latencyMs };
|
|
14075
|
+
}
|
|
14076
|
+
return {
|
|
14077
|
+
up: false,
|
|
14078
|
+
latencyMs,
|
|
14079
|
+
detail: `http ${res.status}`
|
|
14080
|
+
};
|
|
14081
|
+
} catch (err) {
|
|
14082
|
+
const latencyMs = Date.now() - t0;
|
|
14083
|
+
const code = err?.code;
|
|
14084
|
+
const name = err?.name;
|
|
14085
|
+
if (name === "AbortError" || name === "TimeoutError") {
|
|
14086
|
+
return { up: false, latencyMs, detail: `timeout after ${timeoutMs}ms` };
|
|
14087
|
+
}
|
|
14088
|
+
if (code === "ECONNREFUSED") {
|
|
14089
|
+
return { up: false, latencyMs, detail: "connection refused (bridge not running)" };
|
|
14090
|
+
}
|
|
14091
|
+
return {
|
|
14092
|
+
up: false,
|
|
14093
|
+
latencyMs,
|
|
14094
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
14095
|
+
};
|
|
14096
|
+
}
|
|
14097
|
+
}
|
|
14098
|
+
var DEFAULT_TIMEOUT_MS3, DEFAULT_MEMORY_PORT, DEFAULT_HEALTH_PATH;
|
|
14099
|
+
var init_memory_probe = __esm({
|
|
14100
|
+
"../core/dist/services-status/memory-probe.js"() {
|
|
14101
|
+
"use strict";
|
|
14102
|
+
DEFAULT_TIMEOUT_MS3 = 2e3;
|
|
14103
|
+
DEFAULT_MEMORY_PORT = 3111;
|
|
14104
|
+
DEFAULT_HEALTH_PATH = "/agentmemory/livez";
|
|
14105
|
+
}
|
|
14106
|
+
});
|
|
14107
|
+
|
|
14108
|
+
// ../core/dist/services-status/index.js
|
|
14109
|
+
var init_services_status = __esm({
|
|
14110
|
+
"../core/dist/services-status/index.js"() {
|
|
14111
|
+
"use strict";
|
|
14112
|
+
init_memory_probe();
|
|
14113
|
+
}
|
|
14114
|
+
});
|
|
14115
|
+
|
|
14116
|
+
// ../core/dist/skill-sources/meta-hooks-migration-snapshot.js
|
|
14117
|
+
import * as crypto5 from "node:crypto";
|
|
14118
|
+
import * as fs27 from "node:fs";
|
|
14119
|
+
import * as os17 from "node:os";
|
|
14120
|
+
import * as path26 from "node:path";
|
|
14121
|
+
function migrationSnapshotsDir2() {
|
|
14122
|
+
const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
|
|
14123
|
+
if (override && override.length > 0)
|
|
14124
|
+
return override;
|
|
14125
|
+
return path26.join(os17.homedir(), ".olam", "state", "migration-snapshots");
|
|
14126
|
+
}
|
|
14127
|
+
function writeMetaHooksSnapshot(originalSettings) {
|
|
14128
|
+
const snapshot = {
|
|
14129
|
+
schemaVersion: META_HOOKS_SNAPSHOT_SCHEMA_VERSION,
|
|
14130
|
+
takenAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14131
|
+
namespace: "meta-hooks",
|
|
14132
|
+
originalSettings
|
|
14133
|
+
};
|
|
14134
|
+
const validated = MetaHooksMigrationSnapshotSchema.parse(snapshot);
|
|
14135
|
+
const dir = migrationSnapshotsDir2();
|
|
14136
|
+
fs27.mkdirSync(dir, { recursive: true });
|
|
14137
|
+
const stamp = validated.takenAt.replace(/[:.]/g, "-");
|
|
14138
|
+
const rand = crypto5.randomBytes(3).toString("hex");
|
|
14139
|
+
const file = path26.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
|
|
14140
|
+
fs27.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
|
|
14141
|
+
return file;
|
|
14142
|
+
}
|
|
14143
|
+
var META_HOOKS_SNAPSHOT_SCHEMA_VERSION, META_HOOKS_SNAPSHOT_PREFIX, SettingsLooseSchema, MetaHooksMigrationSnapshotSchema;
|
|
14144
|
+
var init_meta_hooks_migration_snapshot = __esm({
|
|
14145
|
+
"../core/dist/skill-sources/meta-hooks-migration-snapshot.js"() {
|
|
14146
|
+
"use strict";
|
|
14147
|
+
init_v3();
|
|
14148
|
+
META_HOOKS_SNAPSHOT_SCHEMA_VERSION = 1;
|
|
14149
|
+
META_HOOKS_SNAPSHOT_PREFIX = "meta-hooks-";
|
|
14150
|
+
SettingsLooseSchema = external_exports.record(external_exports.unknown());
|
|
14151
|
+
MetaHooksMigrationSnapshotSchema = external_exports.object({
|
|
14152
|
+
schemaVersion: external_exports.literal(META_HOOKS_SNAPSHOT_SCHEMA_VERSION),
|
|
14153
|
+
takenAt: external_exports.string().min(1),
|
|
14154
|
+
namespace: external_exports.literal("meta-hooks"),
|
|
14155
|
+
/**
|
|
14156
|
+
* Full settings.json content captured before injection. Reverting
|
|
14157
|
+
* writes this back verbatim. May be `null` when no settings.json
|
|
14158
|
+
* existed pre-injection (operator's first sync wrote a fresh one);
|
|
14159
|
+
* revert in that case deletes the file.
|
|
14160
|
+
*/
|
|
14161
|
+
originalSettings: external_exports.union([SettingsLooseSchema, external_exports.null()])
|
|
14162
|
+
});
|
|
14163
|
+
}
|
|
14164
|
+
});
|
|
14165
|
+
|
|
14166
|
+
// ../core/dist/skill-sync/atlas-hook-strip.js
|
|
14167
|
+
function isStripCommand(command) {
|
|
14168
|
+
for (const sentinel of OLAM_META_SENTINELS_GUARDED) {
|
|
14169
|
+
if (command.includes(sentinel))
|
|
14170
|
+
return { match: false };
|
|
14171
|
+
}
|
|
14172
|
+
for (const pattern of AGENTMEMORY_SCRIPT_PATTERNS) {
|
|
14173
|
+
if (command.includes(pattern))
|
|
14174
|
+
return { match: true, pattern };
|
|
14175
|
+
}
|
|
14176
|
+
return { match: false };
|
|
14177
|
+
}
|
|
14178
|
+
function findStripCandidates(settings) {
|
|
14179
|
+
const stages = ["PreToolUse", "PostToolUse"];
|
|
14180
|
+
const out = [];
|
|
14181
|
+
for (const stage of stages) {
|
|
14182
|
+
const matchers = settings.hooks?.[stage];
|
|
14183
|
+
if (!Array.isArray(matchers))
|
|
14184
|
+
continue;
|
|
14185
|
+
for (let mi = 0; mi < matchers.length; mi += 1) {
|
|
14186
|
+
const matcher = matchers[mi];
|
|
14187
|
+
const inner = Array.isArray(matcher.hooks) ? matcher.hooks : [];
|
|
14188
|
+
for (let ii = 0; ii < inner.length; ii += 1) {
|
|
14189
|
+
const cmd = inner[ii]?.command;
|
|
14190
|
+
if (typeof cmd !== "string")
|
|
14191
|
+
continue;
|
|
14192
|
+
const verdict = isStripCommand(cmd);
|
|
14193
|
+
if (verdict.match) {
|
|
14194
|
+
out.push({
|
|
14195
|
+
stage,
|
|
14196
|
+
matcherIndex: mi,
|
|
14197
|
+
innerIndex: ii,
|
|
14198
|
+
command: cmd,
|
|
14199
|
+
matcher: matcher.matcher,
|
|
14200
|
+
matchedPattern: verdict.pattern
|
|
14201
|
+
});
|
|
14202
|
+
}
|
|
14203
|
+
}
|
|
14204
|
+
}
|
|
14205
|
+
}
|
|
14206
|
+
return out;
|
|
14207
|
+
}
|
|
14208
|
+
function applyStrip(settings, candidates) {
|
|
14209
|
+
if (candidates.length === 0) {
|
|
14210
|
+
return { nextSettings: settings, removedCount: 0 };
|
|
14211
|
+
}
|
|
14212
|
+
const stripByStageMatcher = /* @__PURE__ */ new Map();
|
|
14213
|
+
for (const c of candidates) {
|
|
14214
|
+
const key = `${c.stage}:${c.matcherIndex}`;
|
|
14215
|
+
if (!stripByStageMatcher.has(key))
|
|
14216
|
+
stripByStageMatcher.set(key, /* @__PURE__ */ new Set());
|
|
14217
|
+
stripByStageMatcher.get(key).add(c.innerIndex);
|
|
14218
|
+
}
|
|
14219
|
+
const nextHooks = { ...settings.hooks ?? {} };
|
|
14220
|
+
const stages = ["PreToolUse", "PostToolUse"];
|
|
14221
|
+
for (const stage of stages) {
|
|
14222
|
+
const matchers = settings.hooks?.[stage];
|
|
14223
|
+
if (!Array.isArray(matchers))
|
|
14224
|
+
continue;
|
|
14225
|
+
const nextMatchers = [];
|
|
14226
|
+
for (let mi = 0; mi < matchers.length; mi += 1) {
|
|
14227
|
+
const matcher = matchers[mi];
|
|
14228
|
+
const innerHooks = Array.isArray(matcher.hooks) ? matcher.hooks : [];
|
|
14229
|
+
const stripIdx = stripByStageMatcher.get(`${stage}:${mi}`);
|
|
14230
|
+
const keptInner = stripIdx === void 0 ? innerHooks : innerHooks.filter((_, ii) => !stripIdx.has(ii));
|
|
14231
|
+
if (keptInner.length === innerHooks.length) {
|
|
14232
|
+
nextMatchers.push(matcher);
|
|
14233
|
+
} else if (keptInner.length === 0) {
|
|
14234
|
+
} else {
|
|
14235
|
+
nextMatchers.push({ ...matcher, hooks: keptInner });
|
|
14236
|
+
}
|
|
14237
|
+
}
|
|
14238
|
+
if (nextMatchers.length === 0) {
|
|
14239
|
+
delete nextHooks[stage];
|
|
14240
|
+
} else {
|
|
14241
|
+
nextHooks[stage] = nextMatchers;
|
|
14242
|
+
}
|
|
14243
|
+
}
|
|
14244
|
+
const next = { ...settings };
|
|
14245
|
+
if (Object.keys(nextHooks).length === 0) {
|
|
14246
|
+
delete next.hooks;
|
|
14247
|
+
} else {
|
|
14248
|
+
next.hooks = nextHooks;
|
|
14249
|
+
}
|
|
14250
|
+
return { nextSettings: next, removedCount: candidates.length };
|
|
14251
|
+
}
|
|
14252
|
+
var AGENTMEMORY_SCRIPT_PATTERNS, OLAM_META_SENTINELS_GUARDED;
|
|
14253
|
+
var init_atlas_hook_strip = __esm({
|
|
14254
|
+
"../core/dist/skill-sync/atlas-hook-strip.js"() {
|
|
14255
|
+
"use strict";
|
|
14256
|
+
init_memory_recall();
|
|
14257
|
+
init_memory_classify();
|
|
14258
|
+
AGENTMEMORY_SCRIPT_PATTERNS = [
|
|
14259
|
+
"agentmemory-recall-trigger.mjs",
|
|
14260
|
+
"agentmemory-classify-queue.mjs"
|
|
14261
|
+
];
|
|
14262
|
+
OLAM_META_SENTINELS_GUARDED = [
|
|
14263
|
+
OLAM_META_MEMORY_RECALL_SENTINEL,
|
|
14264
|
+
OLAM_META_MEMORY_CLASSIFY_SENTINEL
|
|
14265
|
+
];
|
|
14266
|
+
}
|
|
14267
|
+
});
|
|
14268
|
+
|
|
14269
|
+
// ../core/dist/skill-sync/meta-hook-injector.js
|
|
14270
|
+
function decideTargetBlocks(opts) {
|
|
14271
|
+
const mode = opts.mode ?? "auto";
|
|
14272
|
+
const disabled = new Set(opts.disabledBlocks ?? []);
|
|
14273
|
+
if (mode === "never")
|
|
14274
|
+
return /* @__PURE__ */ new Set();
|
|
14275
|
+
const wantMemory = mode === "always" || opts.servicesStatus.memory;
|
|
14276
|
+
const target = /* @__PURE__ */ new Set();
|
|
14277
|
+
if (wantMemory && !disabled.has("memory-recall"))
|
|
14278
|
+
target.add("memory-recall");
|
|
14279
|
+
if (wantMemory && !disabled.has("memory-classify"))
|
|
14280
|
+
target.add("memory-classify");
|
|
14281
|
+
return target;
|
|
14282
|
+
}
|
|
14283
|
+
function injectMetaHooks(opts) {
|
|
14284
|
+
const target = decideTargetBlocks(opts);
|
|
14285
|
+
let working = JSON.parse(JSON.stringify(opts.currentSettings ?? {}));
|
|
14286
|
+
const blocksAdded = [];
|
|
14287
|
+
const blocksRemoved = [];
|
|
14288
|
+
const memoryRecallPresent = hasMemoryRecallBlock(working);
|
|
14289
|
+
if (target.has("memory-recall")) {
|
|
14290
|
+
if (!memoryRecallPresent) {
|
|
14291
|
+
working = appendBlock(working, OLAM_META_MEMORY_RECALL_STAGE, buildMemoryRecallHookEntry());
|
|
14292
|
+
blocksAdded.push("memory-recall");
|
|
14293
|
+
}
|
|
14294
|
+
} else {
|
|
14295
|
+
if (memoryRecallPresent) {
|
|
14296
|
+
const r = computeMemoryRecallUninstall(working);
|
|
14297
|
+
if (r.status === "removed" && r.settingsAfter) {
|
|
14298
|
+
working = r.settingsAfter;
|
|
14299
|
+
blocksRemoved.push("memory-recall");
|
|
14300
|
+
}
|
|
14301
|
+
}
|
|
14302
|
+
}
|
|
14303
|
+
const memoryClassifyPresent = hasMemoryClassifyBlock(working);
|
|
14304
|
+
if (target.has("memory-classify")) {
|
|
14305
|
+
if (!memoryClassifyPresent) {
|
|
14306
|
+
working = appendBlock(working, OLAM_META_MEMORY_CLASSIFY_STAGE, buildMemoryClassifyHookEntry());
|
|
14307
|
+
blocksAdded.push("memory-classify");
|
|
14308
|
+
}
|
|
14309
|
+
} else {
|
|
14310
|
+
if (memoryClassifyPresent) {
|
|
14311
|
+
const r = computeMemoryClassifyUninstall(working);
|
|
14312
|
+
if (r.status === "removed" && r.settingsAfter) {
|
|
14313
|
+
working = r.settingsAfter;
|
|
14314
|
+
blocksRemoved.push("memory-classify");
|
|
14315
|
+
}
|
|
14316
|
+
}
|
|
14317
|
+
}
|
|
14318
|
+
return {
|
|
14319
|
+
nextSettings: working,
|
|
14320
|
+
blocksAdded,
|
|
14321
|
+
blocksRemoved,
|
|
14322
|
+
mode: opts.mode ?? "auto"
|
|
14323
|
+
};
|
|
14324
|
+
}
|
|
14325
|
+
function hasMemoryRecallBlock(settings) {
|
|
14326
|
+
const entries = settings.hooks?.PreToolUse;
|
|
14327
|
+
if (!Array.isArray(entries))
|
|
14328
|
+
return false;
|
|
14329
|
+
for (const matcher of entries) {
|
|
14330
|
+
const inner = matcher?.hooks ?? [];
|
|
14331
|
+
if (!Array.isArray(inner))
|
|
14332
|
+
continue;
|
|
14333
|
+
for (const h of inner) {
|
|
14334
|
+
if (typeof h?.command === "string" && matchMemoryRecallSentinel(h.command))
|
|
14335
|
+
return true;
|
|
14336
|
+
}
|
|
14337
|
+
}
|
|
14338
|
+
return false;
|
|
14339
|
+
}
|
|
14340
|
+
function hasMemoryClassifyBlock(settings) {
|
|
14341
|
+
const entries = settings.hooks?.PostToolUse;
|
|
14342
|
+
if (!Array.isArray(entries))
|
|
14343
|
+
return false;
|
|
14344
|
+
for (const matcher of entries) {
|
|
14345
|
+
const inner = matcher?.hooks ?? [];
|
|
14346
|
+
if (!Array.isArray(inner))
|
|
14347
|
+
continue;
|
|
14348
|
+
for (const h of inner) {
|
|
14349
|
+
if (typeof h?.command === "string" && matchMemoryClassifySentinel(h.command))
|
|
14350
|
+
return true;
|
|
14351
|
+
}
|
|
14352
|
+
}
|
|
14353
|
+
return false;
|
|
14354
|
+
}
|
|
14355
|
+
function appendBlock(settings, stage, entry) {
|
|
14356
|
+
const next = { ...settings };
|
|
14357
|
+
const hooks = { ...settings.hooks ?? {} };
|
|
14358
|
+
const stageEntries = Array.isArray(hooks[stage]) ? [...hooks[stage]] : [];
|
|
14359
|
+
stageEntries.push(entry);
|
|
14360
|
+
hooks[stage] = stageEntries;
|
|
14361
|
+
next.hooks = hooks;
|
|
14362
|
+
return next;
|
|
14363
|
+
}
|
|
14364
|
+
var init_meta_hook_injector = __esm({
|
|
14365
|
+
"../core/dist/skill-sync/meta-hook-injector.js"() {
|
|
14366
|
+
"use strict";
|
|
14367
|
+
init_meta_hooks();
|
|
14368
|
+
}
|
|
14369
|
+
});
|
|
14370
|
+
|
|
14371
|
+
// ../core/dist/skill-sync/engine.js
|
|
14372
|
+
import * as fs28 from "node:fs";
|
|
14373
|
+
import * as os18 from "node:os";
|
|
14374
|
+
import * as path27 from "node:path";
|
|
13692
14375
|
function resolveAtlasUser(override) {
|
|
13693
14376
|
if (override)
|
|
13694
14377
|
return override;
|
|
13695
|
-
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] ||
|
|
13696
|
-
const f =
|
|
13697
|
-
if (
|
|
13698
|
-
return
|
|
14378
|
+
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path27.join(os18.homedir(), ".claude");
|
|
14379
|
+
const f = path27.join(claudeDir2, ".atlas-user");
|
|
14380
|
+
if (fs28.existsSync(f)) {
|
|
14381
|
+
return fs28.readFileSync(f, "utf-8").trim() || void 0;
|
|
13699
14382
|
}
|
|
13700
14383
|
return void 0;
|
|
13701
14384
|
}
|
|
@@ -13707,7 +14390,7 @@ async function syncSkills(opts = {}) {
|
|
|
13707
14390
|
const perSource = [];
|
|
13708
14391
|
for (const source of sources) {
|
|
13709
14392
|
const clonePath = skillSourceClonePath(source.id);
|
|
13710
|
-
if (!
|
|
14393
|
+
if (!fs28.existsSync(clonePath))
|
|
13711
14394
|
continue;
|
|
13712
14395
|
const { artifacts, subscription } = await withSourceLock(clonePath, () => {
|
|
13713
14396
|
const pinRef = projectOverride?.override.pin?.[source.id];
|
|
@@ -13743,6 +14426,7 @@ async function syncSkills(opts = {}) {
|
|
|
13743
14426
|
projectOverride,
|
|
13744
14427
|
deploy: void 0,
|
|
13745
14428
|
merge: void 0,
|
|
14429
|
+
metaHooks: void 0,
|
|
13746
14430
|
perSource
|
|
13747
14431
|
};
|
|
13748
14432
|
if (opts.dryRun) {
|
|
@@ -13752,35 +14436,135 @@ async function syncSkills(opts = {}) {
|
|
|
13752
14436
|
summary.deploy = deployArtifacts(projectFilteredArtifacts);
|
|
13753
14437
|
summary.collisions = summary.deploy.collisions;
|
|
13754
14438
|
summary.merge = mergeSettings({ hookFiles, permissionFiles });
|
|
14439
|
+
if (opts.metaHooks !== "never") {
|
|
14440
|
+
summary.metaHooks = await injectMetaHooksIntoSettings(opts);
|
|
14441
|
+
}
|
|
13755
14442
|
return summary;
|
|
13756
14443
|
}
|
|
14444
|
+
async function injectMetaHooksIntoSettings(opts) {
|
|
14445
|
+
const mode = opts.metaHooks ?? "auto";
|
|
14446
|
+
const memoryProbe = await probeMemoryBridge();
|
|
14447
|
+
const servicesStatus = {
|
|
14448
|
+
memory: memoryProbe.up,
|
|
14449
|
+
...memoryProbe.detail !== void 0 ? { memoryDetail: memoryProbe.detail } : {}
|
|
14450
|
+
};
|
|
14451
|
+
const settingsFile = claudeSettingsPath();
|
|
14452
|
+
let snapshotError;
|
|
14453
|
+
let stripCandidates = [];
|
|
14454
|
+
const result = await withSettingsJsonLock(() => {
|
|
14455
|
+
let currentSettings = {};
|
|
14456
|
+
let settingsExisted = false;
|
|
14457
|
+
if (fs28.existsSync(settingsFile)) {
|
|
14458
|
+
settingsExisted = true;
|
|
14459
|
+
try {
|
|
14460
|
+
const raw = fs28.readFileSync(settingsFile, "utf-8");
|
|
14461
|
+
currentSettings = raw.trim() ? JSON.parse(raw) : {};
|
|
14462
|
+
} catch {
|
|
14463
|
+
try {
|
|
14464
|
+
const raw = fs28.readFileSync(settingsFile);
|
|
14465
|
+
const bakDir = path27.join(path27.dirname(settingsFile), ".malformed-backups");
|
|
14466
|
+
fs28.mkdirSync(bakDir, { recursive: true });
|
|
14467
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
14468
|
+
const bakFile = path27.join(bakDir, `settings.json.malformed.${stamp}.bak`);
|
|
14469
|
+
fs28.writeFileSync(bakFile, raw, { mode: 384 });
|
|
14470
|
+
snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
|
|
14471
|
+
} catch (bakErr) {
|
|
14472
|
+
snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
|
|
14473
|
+
}
|
|
14474
|
+
currentSettings = {};
|
|
14475
|
+
settingsExisted = false;
|
|
14476
|
+
}
|
|
14477
|
+
}
|
|
14478
|
+
stripCandidates = findStripCandidates(currentSettings);
|
|
14479
|
+
const settingsForInject = stripCandidates.length > 0 ? applyStrip(currentSettings, stripCandidates).nextSettings : currentSettings;
|
|
14480
|
+
let configDisabled = [];
|
|
14481
|
+
try {
|
|
14482
|
+
const cfg = readGlobalConfig();
|
|
14483
|
+
configDisabled = cfg.metaHooksDisabled ?? [];
|
|
14484
|
+
} catch {
|
|
14485
|
+
}
|
|
14486
|
+
const disabledBlocks = Array.from(/* @__PURE__ */ new Set([
|
|
14487
|
+
...configDisabled,
|
|
14488
|
+
...opts.metaHooksDisabled ?? []
|
|
14489
|
+
]));
|
|
14490
|
+
const inject = injectMetaHooks({
|
|
14491
|
+
servicesStatus,
|
|
14492
|
+
currentSettings: settingsForInject,
|
|
14493
|
+
mode,
|
|
14494
|
+
...disabledBlocks.length > 0 ? { disabledBlocks } : {}
|
|
14495
|
+
});
|
|
14496
|
+
const noInjectDelta = inject.blocksAdded.length === 0 && inject.blocksRemoved.length === 0;
|
|
14497
|
+
const noStripDelta = stripCandidates.length === 0;
|
|
14498
|
+
if (noInjectDelta && noStripDelta) {
|
|
14499
|
+
return inject;
|
|
14500
|
+
}
|
|
14501
|
+
let snapshotPath;
|
|
14502
|
+
try {
|
|
14503
|
+
snapshotPath = writeMetaHooksSnapshot(settingsExisted ? currentSettings : null);
|
|
14504
|
+
} catch (err) {
|
|
14505
|
+
snapshotError = err instanceof Error ? err.message : String(err);
|
|
14506
|
+
}
|
|
14507
|
+
if (stripCandidates.length > 0) {
|
|
14508
|
+
try {
|
|
14509
|
+
appendTrustAudit({
|
|
14510
|
+
gitUrl: "internal:olam-meta-hooks",
|
|
14511
|
+
action: "meta-hook-stripped",
|
|
14512
|
+
trustMethod: "none",
|
|
14513
|
+
sourceId: "atlas-toolbox",
|
|
14514
|
+
note: `auto-migration during syncSkills stripped ${stripCandidates.length} agentmemory hook entry(ies)${snapshotPath ? `; snapshot at ${snapshotPath}` : ""}`
|
|
14515
|
+
});
|
|
14516
|
+
} catch {
|
|
14517
|
+
}
|
|
14518
|
+
}
|
|
14519
|
+
fs28.mkdirSync(path27.dirname(settingsFile), { recursive: true });
|
|
14520
|
+
const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
|
|
14521
|
+
fs28.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
|
|
14522
|
+
fs28.renameSync(tmpPath, settingsFile);
|
|
14523
|
+
return inject;
|
|
14524
|
+
}, { reason: `syncSkills meta-hook injection (mode=${mode})` });
|
|
14525
|
+
return {
|
|
14526
|
+
mode: result.mode,
|
|
14527
|
+
servicesStatus,
|
|
14528
|
+
blocksAdded: result.blocksAdded,
|
|
14529
|
+
blocksRemoved: result.blocksRemoved,
|
|
14530
|
+
...snapshotError !== void 0 ? { snapshotError } : {},
|
|
14531
|
+
...stripCandidates.length > 0 ? { autoMigrated: { strippedCount: stripCandidates.length, stripCandidates } } : {}
|
|
14532
|
+
};
|
|
14533
|
+
}
|
|
13757
14534
|
var init_engine = __esm({
|
|
13758
14535
|
"../core/dist/skill-sync/engine.js"() {
|
|
13759
14536
|
"use strict";
|
|
13760
14537
|
init_store2();
|
|
13761
14538
|
init_clone();
|
|
14539
|
+
init_store();
|
|
13762
14540
|
init_artifact_resolver();
|
|
13763
14541
|
init_symlink_deployer();
|
|
13764
14542
|
init_settings_merger();
|
|
13765
14543
|
init_per_project_override();
|
|
13766
14544
|
init_source_lock();
|
|
14545
|
+
init_settings_json_lock();
|
|
14546
|
+
init_services_status();
|
|
14547
|
+
init_meta_hooks_migration_snapshot();
|
|
14548
|
+
init_trust_audit_log();
|
|
14549
|
+
init_atlas_hook_strip();
|
|
14550
|
+
init_meta_hook_injector();
|
|
13767
14551
|
}
|
|
13768
14552
|
});
|
|
13769
14553
|
|
|
13770
14554
|
// ../core/dist/skill-sync/shadow-backup-manager.js
|
|
13771
|
-
import * as
|
|
13772
|
-
import * as
|
|
14555
|
+
import * as fs29 from "node:fs";
|
|
14556
|
+
import * as path28 from "node:path";
|
|
13773
14557
|
function listShadowBackups(opts = {}) {
|
|
13774
14558
|
const claude = opts.claudeDirOverride ?? claudeDir();
|
|
13775
14559
|
const now = opts.now ?? Date.now();
|
|
13776
14560
|
const out = [];
|
|
13777
14561
|
for (const bucket of SHADOW_BACKUP_BUCKETS) {
|
|
13778
|
-
const bucketDir =
|
|
13779
|
-
if (!
|
|
14562
|
+
const bucketDir = path28.join(claude, bucket);
|
|
14563
|
+
if (!fs29.existsSync(bucketDir))
|
|
13780
14564
|
continue;
|
|
13781
14565
|
let entries;
|
|
13782
14566
|
try {
|
|
13783
|
-
entries =
|
|
14567
|
+
entries = fs29.readdirSync(bucketDir);
|
|
13784
14568
|
} catch {
|
|
13785
14569
|
continue;
|
|
13786
14570
|
}
|
|
@@ -13791,10 +14575,10 @@ function listShadowBackups(opts = {}) {
|
|
|
13791
14575
|
const epochSeconds = Number.parseInt(match[1], 10);
|
|
13792
14576
|
if (!Number.isFinite(epochSeconds) || epochSeconds < 0)
|
|
13793
14577
|
continue;
|
|
13794
|
-
const full =
|
|
14578
|
+
const full = path28.join(bucketDir, name);
|
|
13795
14579
|
let sizeBytes = 0;
|
|
13796
14580
|
try {
|
|
13797
|
-
const st =
|
|
14581
|
+
const st = fs29.statSync(full);
|
|
13798
14582
|
if (st.isDirectory())
|
|
13799
14583
|
continue;
|
|
13800
14584
|
sizeBytes = st.size;
|
|
@@ -13807,7 +14591,7 @@ function listShadowBackups(opts = {}) {
|
|
|
13807
14591
|
bucket,
|
|
13808
14592
|
basename: name,
|
|
13809
14593
|
originalBasename,
|
|
13810
|
-
originalPath:
|
|
14594
|
+
originalPath: path28.join(bucketDir, originalBasename),
|
|
13811
14595
|
epochSeconds,
|
|
13812
14596
|
ageMs: now - epochSeconds * 1e3,
|
|
13813
14597
|
sizeBytes
|
|
@@ -13850,7 +14634,7 @@ function pruneShadowBackups(opts) {
|
|
|
13850
14634
|
}
|
|
13851
14635
|
if (!opts.dryRun) {
|
|
13852
14636
|
try {
|
|
13853
|
-
|
|
14637
|
+
fs29.unlinkSync(b.path);
|
|
13854
14638
|
} catch {
|
|
13855
14639
|
skipped.push(b);
|
|
13856
14640
|
continue;
|
|
@@ -13861,24 +14645,24 @@ function pruneShadowBackups(opts) {
|
|
|
13861
14645
|
return { deleted, skipped };
|
|
13862
14646
|
}
|
|
13863
14647
|
function restoreShadowBackup(opts) {
|
|
13864
|
-
const abs =
|
|
13865
|
-
if (!
|
|
14648
|
+
const abs = path28.resolve(opts.backupPath);
|
|
14649
|
+
if (!fs29.existsSync(abs)) {
|
|
13866
14650
|
throw new Error(`backup file not found: ${abs}`);
|
|
13867
14651
|
}
|
|
13868
|
-
const basename6 =
|
|
14652
|
+
const basename6 = path28.basename(abs);
|
|
13869
14653
|
const match = SHADOW_BACKUP_SUFFIX_RE.exec(basename6);
|
|
13870
14654
|
if (!match) {
|
|
13871
14655
|
throw new Error(`not a shadow-backup file (basename "${basename6}" does not match \`.shadow-backup-<epoch>\`): ${abs}`);
|
|
13872
14656
|
}
|
|
13873
14657
|
const originalBasename = basename6.slice(0, basename6.length - match[0].length);
|
|
13874
|
-
const originalPath =
|
|
13875
|
-
if (
|
|
14658
|
+
const originalPath = path28.join(path28.dirname(abs), originalBasename);
|
|
14659
|
+
if (fs29.existsSync(originalPath) && !opts.force) {
|
|
13876
14660
|
throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
|
|
13877
14661
|
}
|
|
13878
|
-
if (opts.force &&
|
|
13879
|
-
|
|
14662
|
+
if (opts.force && fs29.existsSync(originalPath)) {
|
|
14663
|
+
fs29.unlinkSync(originalPath);
|
|
13880
14664
|
}
|
|
13881
|
-
|
|
14665
|
+
fs29.renameSync(abs, originalPath);
|
|
13882
14666
|
return { restoredTo: originalPath };
|
|
13883
14667
|
}
|
|
13884
14668
|
var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
|
|
@@ -13892,14 +14676,14 @@ var init_shadow_backup_manager = __esm({
|
|
|
13892
14676
|
});
|
|
13893
14677
|
|
|
13894
14678
|
// ../core/dist/skill-sources/doctor-checks.js
|
|
13895
|
-
import * as
|
|
13896
|
-
import * as
|
|
13897
|
-
import * as
|
|
14679
|
+
import * as fs30 from "node:fs";
|
|
14680
|
+
import * as path29 from "node:path";
|
|
14681
|
+
import * as os19 from "node:os";
|
|
13898
14682
|
function claudeDirInternal3() {
|
|
13899
14683
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
13900
14684
|
if (override && override.length > 0)
|
|
13901
14685
|
return override;
|
|
13902
|
-
return
|
|
14686
|
+
return path29.join(os19.homedir(), ".claude");
|
|
13903
14687
|
}
|
|
13904
14688
|
function checkStateFileParse() {
|
|
13905
14689
|
const filePath = globalConfigPath();
|
|
@@ -13908,11 +14692,11 @@ function checkStateFileParse() {
|
|
|
13908
14692
|
healthy: true,
|
|
13909
14693
|
description: `~/.olam state file (${filePath})`
|
|
13910
14694
|
};
|
|
13911
|
-
if (!
|
|
14695
|
+
if (!fs30.existsSync(filePath)) {
|
|
13912
14696
|
result.details = ["(file does not yet exist \u2014 will be created on first write)"];
|
|
13913
14697
|
return result;
|
|
13914
14698
|
}
|
|
13915
|
-
const raw =
|
|
14699
|
+
const raw = fs30.readFileSync(filePath, "utf-8");
|
|
13916
14700
|
let parsed;
|
|
13917
14701
|
try {
|
|
13918
14702
|
parsed = JSON.parse(raw);
|
|
@@ -13922,8 +14706,8 @@ function checkStateFileParse() {
|
|
|
13922
14706
|
result.details = [err instanceof Error ? err.message : String(err)];
|
|
13923
14707
|
result.repair = () => {
|
|
13924
14708
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
13925
|
-
|
|
13926
|
-
|
|
14709
|
+
fs30.renameSync(filePath, aside);
|
|
14710
|
+
fs30.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
|
|
13927
14711
|
};
|
|
13928
14712
|
return result;
|
|
13929
14713
|
}
|
|
@@ -13934,7 +14718,7 @@ function checkStateFileParse() {
|
|
|
13934
14718
|
result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
|
|
13935
14719
|
result.repair = () => {
|
|
13936
14720
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
13937
|
-
|
|
14721
|
+
fs30.copyFileSync(filePath, aside);
|
|
13938
14722
|
const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
13939
14723
|
const next = {
|
|
13940
14724
|
...base,
|
|
@@ -13943,7 +14727,7 @@ function checkStateFileParse() {
|
|
|
13943
14727
|
runbooks: [],
|
|
13944
14728
|
skillSources: []
|
|
13945
14729
|
};
|
|
13946
|
-
|
|
14730
|
+
fs30.writeFileSync(filePath, JSON.stringify(next, null, 2));
|
|
13947
14731
|
};
|
|
13948
14732
|
return result;
|
|
13949
14733
|
}
|
|
@@ -13954,16 +14738,16 @@ function checkDanglingSymlinks() {
|
|
|
13954
14738
|
const buckets = ["commands", "agents", "skills", "scripts", "rules"];
|
|
13955
14739
|
const dangling = [];
|
|
13956
14740
|
for (const bucket of buckets) {
|
|
13957
|
-
const dir =
|
|
13958
|
-
if (!
|
|
14741
|
+
const dir = path29.join(claude, bucket);
|
|
14742
|
+
if (!fs30.existsSync(dir))
|
|
13959
14743
|
continue;
|
|
13960
|
-
for (const name of
|
|
13961
|
-
const linkPath =
|
|
14744
|
+
for (const name of fs30.readdirSync(dir)) {
|
|
14745
|
+
const linkPath = path29.join(dir, name);
|
|
13962
14746
|
try {
|
|
13963
|
-
const lst =
|
|
14747
|
+
const lst = fs30.lstatSync(linkPath);
|
|
13964
14748
|
if (!lst.isSymbolicLink())
|
|
13965
14749
|
continue;
|
|
13966
|
-
if (!
|
|
14750
|
+
if (!fs30.existsSync(linkPath)) {
|
|
13967
14751
|
dangling.push(linkPath);
|
|
13968
14752
|
}
|
|
13969
14753
|
} catch {
|
|
@@ -13981,7 +14765,7 @@ function checkDanglingSymlinks() {
|
|
|
13981
14765
|
result.repair = () => {
|
|
13982
14766
|
for (const p of dangling) {
|
|
13983
14767
|
try {
|
|
13984
|
-
|
|
14768
|
+
fs30.unlinkSync(p);
|
|
13985
14769
|
} catch {
|
|
13986
14770
|
}
|
|
13987
14771
|
}
|
|
@@ -13996,19 +14780,19 @@ function checkOrphanedSnapshots() {
|
|
|
13996
14780
|
healthy: true,
|
|
13997
14781
|
description: `orphaned migration snapshots under ${dir}`
|
|
13998
14782
|
};
|
|
13999
|
-
if (!
|
|
14783
|
+
if (!fs30.existsSync(dir)) {
|
|
14000
14784
|
return result;
|
|
14001
14785
|
}
|
|
14002
14786
|
const orphans = [];
|
|
14003
|
-
for (const name of
|
|
14787
|
+
for (const name of fs30.readdirSync(dir)) {
|
|
14004
14788
|
if (!name.endsWith(".json"))
|
|
14005
14789
|
continue;
|
|
14006
|
-
const full =
|
|
14790
|
+
const full = path29.join(dir, name);
|
|
14007
14791
|
try {
|
|
14008
|
-
const stat =
|
|
14792
|
+
const stat = fs30.statSync(full);
|
|
14009
14793
|
if (!stat.isFile())
|
|
14010
14794
|
continue;
|
|
14011
|
-
const raw =
|
|
14795
|
+
const raw = fs30.readFileSync(full, "utf-8");
|
|
14012
14796
|
let parsed;
|
|
14013
14797
|
try {
|
|
14014
14798
|
parsed = JSON.parse(raw);
|
|
@@ -14033,7 +14817,7 @@ function checkOrphanedSnapshots() {
|
|
|
14033
14817
|
result.repair = () => {
|
|
14034
14818
|
for (const o of orphans) {
|
|
14035
14819
|
try {
|
|
14036
|
-
|
|
14820
|
+
fs30.unlinkSync(o.path);
|
|
14037
14821
|
} catch {
|
|
14038
14822
|
}
|
|
14039
14823
|
}
|
|
@@ -14048,12 +14832,12 @@ function checkSentinelDrift() {
|
|
|
14048
14832
|
healthy: true,
|
|
14049
14833
|
description: `olam-skills sentinel block in ${filePath}`
|
|
14050
14834
|
};
|
|
14051
|
-
if (!
|
|
14835
|
+
if (!fs30.existsSync(filePath)) {
|
|
14052
14836
|
return result;
|
|
14053
14837
|
}
|
|
14054
14838
|
let parsed;
|
|
14055
14839
|
try {
|
|
14056
|
-
parsed = JSON.parse(
|
|
14840
|
+
parsed = JSON.parse(fs30.readFileSync(filePath, "utf-8"));
|
|
14057
14841
|
} catch {
|
|
14058
14842
|
return result;
|
|
14059
14843
|
}
|
|
@@ -14094,7 +14878,7 @@ function checkSentinelDrift() {
|
|
|
14094
14878
|
backupSettings();
|
|
14095
14879
|
} catch {
|
|
14096
14880
|
}
|
|
14097
|
-
const next = JSON.parse(
|
|
14881
|
+
const next = JSON.parse(fs30.readFileSync(filePath, "utf-8"));
|
|
14098
14882
|
if (!next.hooks)
|
|
14099
14883
|
return;
|
|
14100
14884
|
for (const stage of Object.keys(next.hooks)) {
|
|
@@ -14117,7 +14901,7 @@ function checkSentinelDrift() {
|
|
|
14117
14901
|
return bad === void 0;
|
|
14118
14902
|
});
|
|
14119
14903
|
}
|
|
14120
|
-
|
|
14904
|
+
fs30.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
14121
14905
|
};
|
|
14122
14906
|
}
|
|
14123
14907
|
return result;
|
|
@@ -14502,10 +15286,10 @@ function mergeDefs(...defs) {
|
|
|
14502
15286
|
function cloneDef(schema) {
|
|
14503
15287
|
return mergeDefs(schema._zod.def);
|
|
14504
15288
|
}
|
|
14505
|
-
function getElementAtPath(obj,
|
|
14506
|
-
if (!
|
|
15289
|
+
function getElementAtPath(obj, path46) {
|
|
15290
|
+
if (!path46)
|
|
14507
15291
|
return obj;
|
|
14508
|
-
return
|
|
15292
|
+
return path46.reduce((acc, key) => acc?.[key], obj);
|
|
14509
15293
|
}
|
|
14510
15294
|
function promiseAllObject(promisesObj) {
|
|
14511
15295
|
const keys = Object.keys(promisesObj);
|
|
@@ -14914,11 +15698,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
14914
15698
|
}
|
|
14915
15699
|
return false;
|
|
14916
15700
|
}
|
|
14917
|
-
function prefixIssues(
|
|
15701
|
+
function prefixIssues(path46, issues) {
|
|
14918
15702
|
return issues.map((iss) => {
|
|
14919
15703
|
var _a3;
|
|
14920
15704
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
14921
|
-
iss.path.unshift(
|
|
15705
|
+
iss.path.unshift(path46);
|
|
14922
15706
|
return iss;
|
|
14923
15707
|
});
|
|
14924
15708
|
}
|
|
@@ -15065,16 +15849,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
|
|
|
15065
15849
|
}
|
|
15066
15850
|
function formatError(error2, mapper = (issue2) => issue2.message) {
|
|
15067
15851
|
const fieldErrors = { _errors: [] };
|
|
15068
|
-
const processError = (error3,
|
|
15852
|
+
const processError = (error3, path46 = []) => {
|
|
15069
15853
|
for (const issue2 of error3.issues) {
|
|
15070
15854
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
15071
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
15855
|
+
issue2.errors.map((issues) => processError({ issues }, [...path46, ...issue2.path]));
|
|
15072
15856
|
} else if (issue2.code === "invalid_key") {
|
|
15073
|
-
processError({ issues: issue2.issues }, [...
|
|
15857
|
+
processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
|
|
15074
15858
|
} else if (issue2.code === "invalid_element") {
|
|
15075
|
-
processError({ issues: issue2.issues }, [...
|
|
15859
|
+
processError({ issues: issue2.issues }, [...path46, ...issue2.path]);
|
|
15076
15860
|
} else {
|
|
15077
|
-
const fullpath = [...
|
|
15861
|
+
const fullpath = [...path46, ...issue2.path];
|
|
15078
15862
|
if (fullpath.length === 0) {
|
|
15079
15863
|
fieldErrors._errors.push(mapper(issue2));
|
|
15080
15864
|
} else {
|
|
@@ -25713,8 +26497,8 @@ var AuthClient = class {
|
|
|
25713
26497
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
25714
26498
|
}
|
|
25715
26499
|
}
|
|
25716
|
-
async request(method,
|
|
25717
|
-
const url2 = `${this.baseUrl}${
|
|
26500
|
+
async request(method, path46, body, attempt = 0) {
|
|
26501
|
+
const url2 = `${this.baseUrl}${path46}`;
|
|
25718
26502
|
const controller = new AbortController();
|
|
25719
26503
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
25720
26504
|
const headers = {};
|
|
@@ -25732,7 +26516,7 @@ var AuthClient = class {
|
|
|
25732
26516
|
} catch (err) {
|
|
25733
26517
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
25734
26518
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
25735
|
-
return this.request(method,
|
|
26519
|
+
return this.request(method, path46, body, attempt + 1);
|
|
25736
26520
|
}
|
|
25737
26521
|
throw err;
|
|
25738
26522
|
} finally {
|
|
@@ -26583,12 +27367,12 @@ function register3(server, _ctx, _initError) {
|
|
|
26583
27367
|
registry2.close();
|
|
26584
27368
|
}
|
|
26585
27369
|
try {
|
|
26586
|
-
const { default:
|
|
26587
|
-
const { default:
|
|
26588
|
-
const { default:
|
|
26589
|
-
const tokenPath =
|
|
26590
|
-
if (
|
|
26591
|
-
const token =
|
|
27370
|
+
const { default: fs46 } = await import("node:fs");
|
|
27371
|
+
const { default: os28 } = await import("node:os");
|
|
27372
|
+
const { default: path46 } = await import("node:path");
|
|
27373
|
+
const tokenPath = path46.join(os28.homedir(), ".olam", "host-cp.token");
|
|
27374
|
+
if (fs46.existsSync(tokenPath)) {
|
|
27375
|
+
const token = fs46.readFileSync(tokenPath, "utf-8").trim();
|
|
26592
27376
|
await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
|
|
26593
27377
|
method: "POST",
|
|
26594
27378
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
@@ -27008,10 +27792,10 @@ function extractMcpConfig(claudeJsonPath) {
|
|
|
27008
27792
|
}
|
|
27009
27793
|
return { mcpServers, secrets };
|
|
27010
27794
|
}
|
|
27011
|
-
function readOptional(
|
|
27012
|
-
if (!existsSync6(
|
|
27795
|
+
function readOptional(path46) {
|
|
27796
|
+
if (!existsSync6(path46)) return null;
|
|
27013
27797
|
try {
|
|
27014
|
-
return readFileSync5(
|
|
27798
|
+
return readFileSync5(path46, "utf8");
|
|
27015
27799
|
} catch {
|
|
27016
27800
|
return null;
|
|
27017
27801
|
}
|
|
@@ -28427,8 +29211,8 @@ var CloudflareProvider = class extends ComputeProvider {
|
|
|
28427
29211
|
// -----------------------------------------------------------------------
|
|
28428
29212
|
// Internal fetch helper
|
|
28429
29213
|
// -----------------------------------------------------------------------
|
|
28430
|
-
async request(
|
|
28431
|
-
const url2 = `${this.config.workerUrl}${
|
|
29214
|
+
async request(path46, method, body) {
|
|
29215
|
+
const url2 = `${this.config.workerUrl}${path46}`;
|
|
28432
29216
|
const bearer = await this.config.mintToken();
|
|
28433
29217
|
const headers = {
|
|
28434
29218
|
Authorization: `Bearer ${bearer}`
|
|
@@ -30879,10 +31663,10 @@ async function writeManifest(args) {
|
|
|
30879
31663
|
capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
30880
31664
|
shots: entries
|
|
30881
31665
|
};
|
|
30882
|
-
const
|
|
30883
|
-
await writeFile(
|
|
31666
|
+
const path46 = join13(args.outDir, "manifest.json");
|
|
31667
|
+
await writeFile(path46, `${JSON.stringify(manifest, null, 2)}
|
|
30884
31668
|
`, "utf8");
|
|
30885
|
-
return { path:
|
|
31669
|
+
return { path: path46, manifest };
|
|
30886
31670
|
}
|
|
30887
31671
|
|
|
30888
31672
|
// ../mcp-server/src/tools/_capture/proxy.ts
|
|
@@ -31136,9 +31920,9 @@ async function startProxy(opts) {
|
|
|
31136
31920
|
const liveCompiled = verified.allowedPaths.map(compileGlob);
|
|
31137
31921
|
const target = parseRequestTarget(req);
|
|
31138
31922
|
if (!target) return httpReject(400, "invalid_target");
|
|
31139
|
-
const
|
|
31140
|
-
if (!liveCompiled.some((re) => re.test(
|
|
31141
|
-
return httpReject(403, "outside_allow_list", { path:
|
|
31923
|
+
const path46 = target.pathname;
|
|
31924
|
+
if (!liveCompiled.some((re) => re.test(path46))) {
|
|
31925
|
+
return httpReject(403, "outside_allow_list", { path: path46 });
|
|
31142
31926
|
}
|
|
31143
31927
|
const headerWorld = req.headers[WORLD_ASSERT_HEADER];
|
|
31144
31928
|
const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
|
|
@@ -31501,16 +32285,16 @@ var UnsafeUrlError = class extends Error {
|
|
|
31501
32285
|
this.reason = reason;
|
|
31502
32286
|
}
|
|
31503
32287
|
};
|
|
31504
|
-
async function lookupWithTimeout(
|
|
32288
|
+
async function lookupWithTimeout(hostname3, lookup, timeoutMs) {
|
|
31505
32289
|
let timer;
|
|
31506
32290
|
const timeout = new Promise((_, reject2) => {
|
|
31507
32291
|
timer = setTimeout(
|
|
31508
|
-
() => reject2(new Error(`dns_lookup_timeout: ${
|
|
32292
|
+
() => reject2(new Error(`dns_lookup_timeout: ${hostname3} (>${timeoutMs}ms)`)),
|
|
31509
32293
|
timeoutMs
|
|
31510
32294
|
);
|
|
31511
32295
|
});
|
|
31512
32296
|
try {
|
|
31513
|
-
return await Promise.race([lookup(
|
|
32297
|
+
return await Promise.race([lookup(hostname3), timeout]);
|
|
31514
32298
|
} finally {
|
|
31515
32299
|
if (timer) clearTimeout(timer);
|
|
31516
32300
|
}
|
|
@@ -31917,14 +32701,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
|
|
|
31917
32701
|
await page.waitForTimeout(shot.afterLoadMs);
|
|
31918
32702
|
}
|
|
31919
32703
|
const ext = format === "jpeg" ? "jpg" : "png";
|
|
31920
|
-
const
|
|
32704
|
+
const path46 = join14(outDir, `${shot.name}.${ext}`);
|
|
31921
32705
|
await page.screenshot({
|
|
31922
|
-
path:
|
|
32706
|
+
path: path46,
|
|
31923
32707
|
type: format,
|
|
31924
32708
|
...format === "jpeg" ? { quality: jpegQuality } : {},
|
|
31925
32709
|
fullPage: false
|
|
31926
32710
|
});
|
|
31927
|
-
return { name: shot.name, path:
|
|
32711
|
+
return { name: shot.name, path: path46, urlRedacted: redactUrl(shot.url), viewport };
|
|
31928
32712
|
} finally {
|
|
31929
32713
|
await context.close();
|
|
31930
32714
|
}
|
|
@@ -32368,12 +33152,12 @@ function openUrl(url2) {
|
|
|
32368
33152
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
32369
33153
|
async function readHostCpToken2() {
|
|
32370
33154
|
try {
|
|
32371
|
-
const { default:
|
|
32372
|
-
const { default:
|
|
32373
|
-
const { default:
|
|
32374
|
-
const tp =
|
|
32375
|
-
if (!
|
|
32376
|
-
return { token:
|
|
33155
|
+
const { default: fs46 } = await import("node:fs");
|
|
33156
|
+
const { default: os28 } = await import("node:os");
|
|
33157
|
+
const { default: path46 } = await import("node:path");
|
|
33158
|
+
const tp = path46.join(os28.homedir(), ".olam", "host-cp.token");
|
|
33159
|
+
if (!fs46.existsSync(tp)) return { token: null };
|
|
33160
|
+
return { token: fs46.readFileSync(tp, "utf-8").trim() };
|
|
32377
33161
|
} catch {
|
|
32378
33162
|
return { token: null };
|
|
32379
33163
|
}
|
|
@@ -32633,9 +33417,9 @@ function register22(server, _ctx, _initError) {
|
|
|
32633
33417
|
description: external_exports.string().optional().describe("Optional human-readable description."),
|
|
32634
33418
|
defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
|
|
32635
33419
|
},
|
|
32636
|
-
async ({ name, path:
|
|
33420
|
+
async ({ name, path: path46, description, defaultBranch }) => {
|
|
32637
33421
|
try {
|
|
32638
|
-
const entry = addRepo({ name, path:
|
|
33422
|
+
const entry = addRepo({ name, path: path46, description, defaultBranch });
|
|
32639
33423
|
return {
|
|
32640
33424
|
content: [{
|
|
32641
33425
|
type: "text",
|
|
@@ -32676,9 +33460,9 @@ function register22(server, _ctx, _initError) {
|
|
|
32676
33460
|
description: external_exports.string().optional().describe("New description."),
|
|
32677
33461
|
defaultBranch: external_exports.string().optional().describe("New default branch.")
|
|
32678
33462
|
},
|
|
32679
|
-
async ({ name, path:
|
|
33463
|
+
async ({ name, path: path46, description, defaultBranch }) => {
|
|
32680
33464
|
try {
|
|
32681
|
-
const entry = updateRepo(name, { path:
|
|
33465
|
+
const entry = updateRepo(name, { path: path46, description, defaultBranch });
|
|
32682
33466
|
return {
|
|
32683
33467
|
content: [{
|
|
32684
33468
|
type: "text",
|
|
@@ -32699,15 +33483,15 @@ __export(process_port_exports, {
|
|
|
32699
33483
|
resolveHostCpToken: () => resolveHostCpToken
|
|
32700
33484
|
});
|
|
32701
33485
|
init_v3();
|
|
32702
|
-
import
|
|
32703
|
-
import
|
|
32704
|
-
import
|
|
33486
|
+
import fs31 from "node:fs";
|
|
33487
|
+
import os20 from "node:os";
|
|
33488
|
+
import path30 from "node:path";
|
|
32705
33489
|
var HOST_CP_BASE = "http://127.0.0.1:19000";
|
|
32706
33490
|
function resolveHostCpToken() {
|
|
32707
33491
|
const envToken = process.env["OLAM_HOST_CP_TOKEN"];
|
|
32708
33492
|
if (envToken) return envToken;
|
|
32709
|
-
const tokenPath =
|
|
32710
|
-
if (
|
|
33493
|
+
const tokenPath = path30.join(os20.homedir(), ".olam", "host-cp.token");
|
|
33494
|
+
if (fs31.existsSync(tokenPath)) return fs31.readFileSync(tokenPath, "utf-8").trim();
|
|
32711
33495
|
return null;
|
|
32712
33496
|
}
|
|
32713
33497
|
function tokenMissingError() {
|
|
@@ -33139,8 +33923,8 @@ __export(skills_exports, {
|
|
|
33139
33923
|
});
|
|
33140
33924
|
init_v3();
|
|
33141
33925
|
init_skill_sources();
|
|
33142
|
-
import * as
|
|
33143
|
-
import * as
|
|
33926
|
+
import * as fs32 from "node:fs";
|
|
33927
|
+
import * as path31 from "node:path";
|
|
33144
33928
|
function asMessage8(err) {
|
|
33145
33929
|
return err instanceof Error ? err.message : String(err);
|
|
33146
33930
|
}
|
|
@@ -33163,14 +33947,14 @@ function listDeployed() {
|
|
|
33163
33947
|
);
|
|
33164
33948
|
const entries = [];
|
|
33165
33949
|
for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
|
|
33166
|
-
const bucketDir =
|
|
33167
|
-
if (!
|
|
33168
|
-
for (const name of
|
|
33169
|
-
const full =
|
|
33950
|
+
const bucketDir = path31.join(dir, bucket);
|
|
33951
|
+
if (!fs32.existsSync(bucketDir)) continue;
|
|
33952
|
+
for (const name of fs32.readdirSync(bucketDir)) {
|
|
33953
|
+
const full = path31.join(bucketDir, name);
|
|
33170
33954
|
try {
|
|
33171
|
-
const stat =
|
|
33955
|
+
const stat = fs32.lstatSync(full);
|
|
33172
33956
|
if (!stat.isSymbolicLink()) continue;
|
|
33173
|
-
const target =
|
|
33957
|
+
const target = fs32.readlinkSync(full);
|
|
33174
33958
|
let sourceId;
|
|
33175
33959
|
for (const [clonePath, id] of sourcePaths.entries()) {
|
|
33176
33960
|
if (target.startsWith(clonePath)) {
|
|
@@ -33266,8 +34050,8 @@ function port() {
|
|
|
33266
34050
|
const n = Number.parseInt(env, 10);
|
|
33267
34051
|
return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
|
|
33268
34052
|
}
|
|
33269
|
-
function url(
|
|
33270
|
-
return `http://127.0.0.1:${port()}${
|
|
34053
|
+
function url(path46) {
|
|
34054
|
+
return `http://127.0.0.1:${port()}${path46}`;
|
|
33271
34055
|
}
|
|
33272
34056
|
function kgServiceHealthUrl() {
|
|
33273
34057
|
return url("/health");
|
|
@@ -33286,8 +34070,8 @@ var KgServiceUnreachableError = class extends Error {
|
|
|
33286
34070
|
this.name = "KgServiceUnreachableError";
|
|
33287
34071
|
}
|
|
33288
34072
|
};
|
|
33289
|
-
var
|
|
33290
|
-
async function postJson(endpointUrl, body, timeoutMs =
|
|
34073
|
+
var DEFAULT_TIMEOUT_MS4 = 5e3;
|
|
34074
|
+
async function postJson(endpointUrl, body, timeoutMs = DEFAULT_TIMEOUT_MS4) {
|
|
33291
34075
|
let res;
|
|
33292
34076
|
try {
|
|
33293
34077
|
res = await fetch(endpointUrl, {
|
|
@@ -33305,7 +34089,7 @@ async function postJson(endpointUrl, body, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
|
33305
34089
|
}
|
|
33306
34090
|
return await res.json();
|
|
33307
34091
|
}
|
|
33308
|
-
async function getJson(endpointUrl, timeoutMs =
|
|
34092
|
+
async function getJson(endpointUrl, timeoutMs = DEFAULT_TIMEOUT_MS4) {
|
|
33309
34093
|
let res;
|
|
33310
34094
|
try {
|
|
33311
34095
|
res = await fetch(endpointUrl, { signal: AbortSignal.timeout(timeoutMs) });
|
|
@@ -33466,9 +34250,9 @@ __export(kg_install_hook_exports, {
|
|
|
33466
34250
|
});
|
|
33467
34251
|
init_v3();
|
|
33468
34252
|
init_merge_settings();
|
|
33469
|
-
import * as
|
|
33470
|
-
import * as
|
|
33471
|
-
import * as
|
|
34253
|
+
import * as fs33 from "node:fs";
|
|
34254
|
+
import * as path32 from "node:path";
|
|
34255
|
+
import * as os21 from "node:os";
|
|
33472
34256
|
|
|
33473
34257
|
// ../core/dist/kg/hook-template.js
|
|
33474
34258
|
var KG_HOOK_SENTINEL = "kg-service-v2-classifier-hook";
|
|
@@ -33518,10 +34302,10 @@ function buildHookMatcherEntry(opts) {
|
|
|
33518
34302
|
// ../mcp-server/src/tools/kg-install-hook.ts
|
|
33519
34303
|
function settingsPathFor2(scope, projectPath) {
|
|
33520
34304
|
if (scope === "user") {
|
|
33521
|
-
return
|
|
34305
|
+
return path32.join(os21.homedir(), ".claude", "settings.json");
|
|
33522
34306
|
}
|
|
33523
34307
|
const root = projectPath ?? process.cwd();
|
|
33524
|
-
return
|
|
34308
|
+
return path32.join(root, ".claude", "settings.json");
|
|
33525
34309
|
}
|
|
33526
34310
|
function register29(server, _ctx, _initError) {
|
|
33527
34311
|
server.tool(
|
|
@@ -33535,12 +34319,12 @@ function register29(server, _ctx, _initError) {
|
|
|
33535
34319
|
const scope = params.scope === "user" ? "user" : "project";
|
|
33536
34320
|
const filePath = settingsPathFor2(scope, params.projectPath);
|
|
33537
34321
|
try {
|
|
33538
|
-
|
|
34322
|
+
fs33.mkdirSync(path32.dirname(filePath), { recursive: true });
|
|
33539
34323
|
let backupPath = null;
|
|
33540
|
-
if (
|
|
34324
|
+
if (fs33.existsSync(filePath)) {
|
|
33541
34325
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
33542
34326
|
backupPath = `${filePath}.olam-bak.${ts}`;
|
|
33543
|
-
|
|
34327
|
+
fs33.copyFileSync(filePath, backupPath);
|
|
33544
34328
|
}
|
|
33545
34329
|
const result = mergeHomeSettingsJson(filePath, {
|
|
33546
34330
|
ensureHook: {
|
|
@@ -33551,7 +34335,7 @@ function register29(server, _ctx, _initError) {
|
|
|
33551
34335
|
});
|
|
33552
34336
|
if (result.status === "already-present" && backupPath) {
|
|
33553
34337
|
try {
|
|
33554
|
-
|
|
34338
|
+
fs33.unlinkSync(backupPath);
|
|
33555
34339
|
} catch {
|
|
33556
34340
|
}
|
|
33557
34341
|
}
|
|
@@ -33595,15 +34379,15 @@ __export(kg_uninstall_hook_exports, {
|
|
|
33595
34379
|
register: () => register30
|
|
33596
34380
|
});
|
|
33597
34381
|
init_v3();
|
|
33598
|
-
import * as
|
|
33599
|
-
import * as
|
|
33600
|
-
import * as
|
|
34382
|
+
import * as fs34 from "node:fs";
|
|
34383
|
+
import * as path33 from "node:path";
|
|
34384
|
+
import * as os22 from "node:os";
|
|
33601
34385
|
function settingsPathFor3(scope, projectPath) {
|
|
33602
34386
|
if (scope === "user") {
|
|
33603
|
-
return
|
|
34387
|
+
return path33.join(os22.homedir(), ".claude", "settings.json");
|
|
33604
34388
|
}
|
|
33605
34389
|
const root = projectPath ?? process.cwd();
|
|
33606
|
-
return
|
|
34390
|
+
return path33.join(root, ".claude", "settings.json");
|
|
33607
34391
|
}
|
|
33608
34392
|
function dropSentinel(matchers) {
|
|
33609
34393
|
let changed = false;
|
|
@@ -33637,7 +34421,7 @@ function register30(server, _ctx, _initError) {
|
|
|
33637
34421
|
const scope = params.scope === "user" ? "user" : "project";
|
|
33638
34422
|
const filePath = settingsPathFor3(scope, params.projectPath);
|
|
33639
34423
|
try {
|
|
33640
|
-
if (!
|
|
34424
|
+
if (!fs34.existsSync(filePath)) {
|
|
33641
34425
|
return {
|
|
33642
34426
|
content: [
|
|
33643
34427
|
{
|
|
@@ -33651,7 +34435,7 @@ function register30(server, _ctx, _initError) {
|
|
|
33651
34435
|
]
|
|
33652
34436
|
};
|
|
33653
34437
|
}
|
|
33654
|
-
const raw =
|
|
34438
|
+
const raw = fs34.readFileSync(filePath, "utf-8");
|
|
33655
34439
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
33656
34440
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
33657
34441
|
if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
|
|
@@ -33686,7 +34470,7 @@ function register30(server, _ctx, _initError) {
|
|
|
33686
34470
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
33687
34471
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
33688
34472
|
try {
|
|
33689
|
-
|
|
34473
|
+
fs34.copyFileSync(filePath, backupPath);
|
|
33690
34474
|
} catch {
|
|
33691
34475
|
}
|
|
33692
34476
|
const next = {
|
|
@@ -33698,7 +34482,7 @@ function register30(server, _ctx, _initError) {
|
|
|
33698
34482
|
if (otherStages.length === 0) delete next.hooks;
|
|
33699
34483
|
else delete next.hooks.PreToolUse;
|
|
33700
34484
|
}
|
|
33701
|
-
|
|
34485
|
+
fs34.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
33702
34486
|
return {
|
|
33703
34487
|
content: [
|
|
33704
34488
|
{
|
|
@@ -33911,11 +34695,11 @@ function assertBetterSqlite3Loadable(deps = {}) {
|
|
|
33911
34695
|
init_loader();
|
|
33912
34696
|
|
|
33913
34697
|
// ../core/dist/world/manager.js
|
|
33914
|
-
import * as
|
|
34698
|
+
import * as crypto8 from "node:crypto";
|
|
33915
34699
|
import { execSync as execSync5, spawnSync as spawnSync4 } from "node:child_process";
|
|
33916
|
-
import * as
|
|
33917
|
-
import * as
|
|
33918
|
-
import * as
|
|
34700
|
+
import * as fs43 from "node:fs";
|
|
34701
|
+
import * as os26 from "node:os";
|
|
34702
|
+
import * as path43 from "node:path";
|
|
33919
34703
|
|
|
33920
34704
|
// ../core/dist/world/state.js
|
|
33921
34705
|
var VALID_TRANSITIONS = {
|
|
@@ -34011,8 +34795,8 @@ function resolveDevboxImage(config2, tag) {
|
|
|
34011
34795
|
|
|
34012
34796
|
// ../core/dist/world/worktree.js
|
|
34013
34797
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
34014
|
-
import * as
|
|
34015
|
-
import * as
|
|
34798
|
+
import * as fs35 from "node:fs";
|
|
34799
|
+
import * as path34 from "node:path";
|
|
34016
34800
|
function resolveGitDir(repo) {
|
|
34017
34801
|
if (repo.path) {
|
|
34018
34802
|
return repo.path;
|
|
@@ -34022,11 +34806,11 @@ function resolveGitDir(repo) {
|
|
|
34022
34806
|
async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
34023
34807
|
const created = [];
|
|
34024
34808
|
for (const repo of repos) {
|
|
34025
|
-
const worktreePath =
|
|
34809
|
+
const worktreePath = path34.join(workspacePath, repo.name);
|
|
34026
34810
|
const gitDir = resolveGitDir(repo);
|
|
34027
34811
|
const branchName = branch || `olam/${worldId}`;
|
|
34028
34812
|
try {
|
|
34029
|
-
|
|
34813
|
+
fs35.mkdirSync(path34.dirname(worktreePath), { recursive: true });
|
|
34030
34814
|
execFileSync4("git", ["worktree", "add", worktreePath, "-b", branchName], {
|
|
34031
34815
|
cwd: gitDir,
|
|
34032
34816
|
stdio: "pipe"
|
|
@@ -34059,7 +34843,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
|
34059
34843
|
}
|
|
34060
34844
|
async function removeWorktrees(repos, workspacePath) {
|
|
34061
34845
|
for (const repo of repos) {
|
|
34062
|
-
const worktreePath =
|
|
34846
|
+
const worktreePath = path34.join(workspacePath, repo.name);
|
|
34063
34847
|
let gitDir;
|
|
34064
34848
|
try {
|
|
34065
34849
|
gitDir = resolveGitDir(repo);
|
|
@@ -34134,12 +34918,12 @@ function removeBranch(repo, branch) {
|
|
|
34134
34918
|
|
|
34135
34919
|
// ../core/dist/world/kg-overlay.js
|
|
34136
34920
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
34137
|
-
import * as
|
|
34138
|
-
import * as
|
|
34921
|
+
import * as fs36 from "node:fs";
|
|
34922
|
+
import * as path35 from "node:path";
|
|
34139
34923
|
|
|
34140
34924
|
// ../core/dist/kg/storage-paths.js
|
|
34141
|
-
import { homedir as
|
|
34142
|
-
import { join as
|
|
34925
|
+
import { homedir as homedir22 } from "node:os";
|
|
34926
|
+
import { join as join35, resolve as resolve7 } from "node:path";
|
|
34143
34927
|
|
|
34144
34928
|
// ../core/dist/world/workspace-name.js
|
|
34145
34929
|
var InvalidWorkspaceNameError = class extends Error {
|
|
@@ -34160,25 +34944,25 @@ function validateWorkspaceName(name) {
|
|
|
34160
34944
|
|
|
34161
34945
|
// ../core/dist/kg/storage-paths.js
|
|
34162
34946
|
function olamHome() {
|
|
34163
|
-
return process.env.OLAM_HOME ??
|
|
34947
|
+
return process.env.OLAM_HOME ?? join35(homedir22(), ".olam");
|
|
34164
34948
|
}
|
|
34165
34949
|
function kgRoot() {
|
|
34166
|
-
return
|
|
34950
|
+
return join35(olamHome(), "kg");
|
|
34167
34951
|
}
|
|
34168
34952
|
function worldsRoot() {
|
|
34169
|
-
return
|
|
34953
|
+
return join35(olamHome(), "worlds");
|
|
34170
34954
|
}
|
|
34171
|
-
function assertWithinPrefix(
|
|
34172
|
-
if (!
|
|
34173
|
-
throw new Error(`${label} escape: ${
|
|
34955
|
+
function assertWithinPrefix(path46, prefix, label) {
|
|
34956
|
+
if (!path46.startsWith(prefix + "/")) {
|
|
34957
|
+
throw new Error(`${label} escape: ${path46} not under ${prefix}/`);
|
|
34174
34958
|
}
|
|
34175
34959
|
}
|
|
34176
34960
|
function kgPristinePath(workspace) {
|
|
34177
34961
|
validateWorkspaceName(workspace);
|
|
34178
34962
|
const root = kgRoot();
|
|
34179
|
-
const
|
|
34180
|
-
assertWithinPrefix(
|
|
34181
|
-
return
|
|
34963
|
+
const path46 = resolve7(join35(root, workspace));
|
|
34964
|
+
assertWithinPrefix(path46, root, "kgPristinePath");
|
|
34965
|
+
return path46;
|
|
34182
34966
|
}
|
|
34183
34967
|
var KG_PATHS_INTERNALS = Object.freeze({
|
|
34184
34968
|
olamHome,
|
|
@@ -34194,10 +34978,10 @@ var KgOverlayError = class extends Error {
|
|
|
34194
34978
|
}
|
|
34195
34979
|
};
|
|
34196
34980
|
function ensureGitignoreEntry(worldClonePath) {
|
|
34197
|
-
const gitignorePath =
|
|
34198
|
-
if (!
|
|
34981
|
+
const gitignorePath = path35.join(worldClonePath, ".gitignore");
|
|
34982
|
+
if (!fs36.existsSync(gitignorePath))
|
|
34199
34983
|
return "no-gitignore";
|
|
34200
|
-
const content =
|
|
34984
|
+
const content = fs36.readFileSync(gitignorePath, "utf-8");
|
|
34201
34985
|
const lines = content.split("\n").map((l) => l.trim());
|
|
34202
34986
|
const recognised = /* @__PURE__ */ new Set([
|
|
34203
34987
|
"graphify-out",
|
|
@@ -34212,24 +34996,24 @@ function ensureGitignoreEntry(worldClonePath) {
|
|
|
34212
34996
|
const eol = content.includes("\r\n") ? "\r\n" : "\n";
|
|
34213
34997
|
const needsLeadingNewline = content.length > 0 && !content.endsWith(eol);
|
|
34214
34998
|
const block = `${needsLeadingNewline ? eol : ""}${eol}# olam-kg-service: per-world KG overlay (Phase B1)${eol}graphify-out/${eol}`;
|
|
34215
|
-
|
|
34999
|
+
fs36.appendFileSync(gitignorePath, block, "utf-8");
|
|
34216
35000
|
return "appended";
|
|
34217
35001
|
}
|
|
34218
35002
|
function createWorldOverlay(opts) {
|
|
34219
35003
|
const pristineRoot = kgPristinePath(opts.workspace);
|
|
34220
|
-
const pristinePath =
|
|
34221
|
-
if (!
|
|
35004
|
+
const pristinePath = path35.join(pristineRoot, "graphify-out");
|
|
35005
|
+
if (!fs36.existsSync(pristinePath)) {
|
|
34222
35006
|
throw new KgOverlayError(`Pristine KG for workspace ${JSON.stringify(opts.workspace)} not found at ${pristinePath}. Run \`olam kg build ${opts.workspace}\` first.`);
|
|
34223
35007
|
}
|
|
34224
|
-
if (!
|
|
35008
|
+
if (!path35.isAbsolute(opts.worldClonePath)) {
|
|
34225
35009
|
throw new KgOverlayError(`worldClonePath must be absolute (got ${opts.worldClonePath})`);
|
|
34226
35010
|
}
|
|
34227
|
-
if (!
|
|
35011
|
+
if (!fs36.existsSync(opts.worldClonePath)) {
|
|
34228
35012
|
throw new KgOverlayError(`worldClonePath does not exist: ${opts.worldClonePath}. Create the clone before reflinking.`);
|
|
34229
35013
|
}
|
|
34230
|
-
const overlayPath =
|
|
34231
|
-
if (
|
|
34232
|
-
|
|
35014
|
+
const overlayPath = path35.join(opts.worldClonePath, "graphify-out");
|
|
35015
|
+
if (fs36.existsSync(overlayPath)) {
|
|
35016
|
+
fs36.rmSync(overlayPath, { recursive: true, force: true });
|
|
34233
35017
|
}
|
|
34234
35018
|
const useReflink = process.platform === "darwin";
|
|
34235
35019
|
let strategy;
|
|
@@ -34247,7 +35031,7 @@ function createWorldOverlay(opts) {
|
|
|
34247
35031
|
} else {
|
|
34248
35032
|
strategy = "cp-r";
|
|
34249
35033
|
}
|
|
34250
|
-
if (strategy === "cp-r" || !
|
|
35034
|
+
if (strategy === "cp-r" || !fs36.existsSync(overlayPath)) {
|
|
34251
35035
|
try {
|
|
34252
35036
|
execFileSync5("cp", ["-r", pristinePath, opts.worldClonePath], {
|
|
34253
35037
|
stdio: ["ignore", "ignore", "pipe"]
|
|
@@ -34259,7 +35043,7 @@ function createWorldOverlay(opts) {
|
|
|
34259
35043
|
throw new KgOverlayError(`cp -r failed: ${msg}${reflinkMsg}`);
|
|
34260
35044
|
}
|
|
34261
35045
|
}
|
|
34262
|
-
if (!
|
|
35046
|
+
if (!fs36.existsSync(overlayPath)) {
|
|
34263
35047
|
throw new KgOverlayError(`Overlay creation produced no ${overlayPath} after cp \u2014 filesystem returned without error?`);
|
|
34264
35048
|
}
|
|
34265
35049
|
const gitignoreAction = ensureGitignoreEntry(opts.worldClonePath);
|
|
@@ -34273,12 +35057,12 @@ function createWorldOverlay(opts) {
|
|
|
34273
35057
|
|
|
34274
35058
|
// ../core/dist/world/baseline-diff.js
|
|
34275
35059
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
34276
|
-
import * as
|
|
34277
|
-
import * as
|
|
34278
|
-
import * as
|
|
35060
|
+
import * as fs37 from "node:fs";
|
|
35061
|
+
import * as os23 from "node:os";
|
|
35062
|
+
import * as path36 from "node:path";
|
|
34279
35063
|
var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
34280
|
-
function expandHome2(p,
|
|
34281
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
35064
|
+
function expandHome2(p, homedir28) {
|
|
35065
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir28());
|
|
34282
35066
|
}
|
|
34283
35067
|
function sanitizeRepoFilename(name) {
|
|
34284
35068
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -34301,10 +35085,10 @@ ${stderr}`;
|
|
|
34301
35085
|
}
|
|
34302
35086
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
34303
35087
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
34304
|
-
const
|
|
34305
|
-
const baselineDir =
|
|
35088
|
+
const homedir28 = deps.homedir ?? (() => os23.homedir());
|
|
35089
|
+
const baselineDir = path36.join(workspacePath, ".olam", "baseline");
|
|
34306
35090
|
try {
|
|
34307
|
-
|
|
35091
|
+
fs37.mkdirSync(baselineDir, { recursive: true });
|
|
34308
35092
|
} catch (err) {
|
|
34309
35093
|
const msg = err instanceof Error ? err.message : String(err);
|
|
34310
35094
|
console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
|
|
@@ -34316,9 +35100,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
34316
35100
|
if (!repo.path)
|
|
34317
35101
|
continue;
|
|
34318
35102
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
34319
|
-
const outPath =
|
|
34320
|
-
const repoPath = expandHome2(repo.path,
|
|
34321
|
-
if (!
|
|
35103
|
+
const outPath = path36.join(baselineDir, filename);
|
|
35104
|
+
const repoPath = expandHome2(repo.path, homedir28);
|
|
35105
|
+
if (!fs37.existsSync(repoPath)) {
|
|
34322
35106
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
34323
35107
|
# (skipped: path ${repoPath} does not exist)
|
|
34324
35108
|
`);
|
|
@@ -34385,7 +35169,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
34385
35169
|
}
|
|
34386
35170
|
function writeBaselineFile(outPath, content) {
|
|
34387
35171
|
try {
|
|
34388
|
-
|
|
35172
|
+
fs37.writeFileSync(outPath, content);
|
|
34389
35173
|
} catch (err) {
|
|
34390
35174
|
const msg = err instanceof Error ? err.message : String(err);
|
|
34391
35175
|
console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
|
|
@@ -34393,8 +35177,8 @@ function writeBaselineFile(outPath, content) {
|
|
|
34393
35177
|
}
|
|
34394
35178
|
function stripWorktreeEdits(repos, workspacePath) {
|
|
34395
35179
|
for (const repo of repos) {
|
|
34396
|
-
const worktreePath =
|
|
34397
|
-
if (!
|
|
35180
|
+
const worktreePath = path36.join(workspacePath, repo.name);
|
|
35181
|
+
if (!fs37.existsSync(worktreePath))
|
|
34398
35182
|
continue;
|
|
34399
35183
|
try {
|
|
34400
35184
|
execFileSync6("git", ["checkout", "--", "."], {
|
|
@@ -34453,21 +35237,21 @@ function extractStderr(err) {
|
|
|
34453
35237
|
}
|
|
34454
35238
|
function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
34455
35239
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
34456
|
-
const
|
|
34457
|
-
const
|
|
34458
|
-
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) =>
|
|
34459
|
-
const
|
|
34460
|
-
|
|
35240
|
+
const homedir28 = deps.homedir ?? (() => os23.homedir());
|
|
35241
|
+
const existsSync43 = deps.existsSync ?? ((p) => fs37.existsSync(p));
|
|
35242
|
+
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs37.copyFileSync(src, dest));
|
|
35243
|
+
const mkdirSync28 = deps.mkdirSync ?? ((dirPath, opts) => {
|
|
35244
|
+
fs37.mkdirSync(dirPath, opts);
|
|
34461
35245
|
});
|
|
34462
35246
|
const plans = [];
|
|
34463
35247
|
for (const repo of repos) {
|
|
34464
35248
|
if (!repo.path)
|
|
34465
35249
|
continue;
|
|
34466
|
-
const repoPath = expandHome2(repo.path,
|
|
34467
|
-
const worktreePath =
|
|
34468
|
-
if (!
|
|
35250
|
+
const repoPath = expandHome2(repo.path, homedir28);
|
|
35251
|
+
const worktreePath = path36.join(workspacePath, repo.name);
|
|
35252
|
+
if (!existsSync43(repoPath))
|
|
34469
35253
|
continue;
|
|
34470
|
-
if (!
|
|
35254
|
+
if (!existsSync43(worktreePath)) {
|
|
34471
35255
|
console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
|
|
34472
35256
|
continue;
|
|
34473
35257
|
}
|
|
@@ -34525,12 +35309,12 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
34525
35309
|
}
|
|
34526
35310
|
}
|
|
34527
35311
|
for (const rel of plan.diff.untracked) {
|
|
34528
|
-
const src =
|
|
34529
|
-
const dest =
|
|
34530
|
-
if (!
|
|
35312
|
+
const src = path36.join(plan.repoPath, rel);
|
|
35313
|
+
const dest = path36.join(plan.worktreePath, rel);
|
|
35314
|
+
if (!existsSync43(src))
|
|
34531
35315
|
continue;
|
|
34532
35316
|
try {
|
|
34533
|
-
|
|
35317
|
+
mkdirSync28(path36.dirname(dest), { recursive: true });
|
|
34534
35318
|
copyFileSync9(src, dest);
|
|
34535
35319
|
} catch (err) {
|
|
34536
35320
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -34556,8 +35340,8 @@ function formatBaselineSummary(result) {
|
|
|
34556
35340
|
}
|
|
34557
35341
|
|
|
34558
35342
|
// ../core/dist/world/context-injection.js
|
|
34559
|
-
import * as
|
|
34560
|
-
import * as
|
|
35343
|
+
import * as fs38 from "node:fs";
|
|
35344
|
+
import * as path37 from "node:path";
|
|
34561
35345
|
|
|
34562
35346
|
// ../core/dist/world/templates/_generated.js
|
|
34563
35347
|
var GH_PR_CREATE = '# Creating PRs from inside an Olam world\n\n## The problem\n\nCalling `gh pr create` directly inside an Olam container **hangs forever** on a\nTTY confirmation prompt that the agent cannot answer. This is a known, reproduced issue.\n\n## The fix\n\nAlways use this exact pattern:\n\n```bash\necho y | timeout 30 gh pr create \\\n --base main \\\n --head <branch> \\\n --title "<title>" \\\n --body-file /tmp/pr-body.md\n```\n\n## Why each part matters\n\n- **`echo y |`** \u2014 answers the "Submit?" confirmation prompt up front so `gh` never pauses.\n- **`timeout 30`** \u2014 hard deadline. If `gh` hangs anyway, the command exits non-zero so the\n agent can react instead of stalling the world indefinitely.\n- **`--body-file /tmp/pr-body.md`** \u2014 write the PR body to a temp file first. Avoids\n shell-escaping bugs that occur with `--body "..."` for long or multi-line bodies.\n- **`--head` and `--base` explicitly** \u2014 removes all interactive prompts; `gh` has nothing to ask.\n\n## Troubleshooting\n\n**"no commits" or "branch not found" error:**\n\n```bash\ngit push -u origin <branch>\n# then retry:\necho y | timeout 30 gh pr create --base main --head <branch> --title "..." --body-file /tmp/pr-body.md\n```\n\n**Timeout exceeded (command exits 124):**\n\n- Check if the branch was pushed: `git log origin/<branch> --oneline -1`\n- Check GitHub CLI auth: `gh auth status`\n- Retry once; if it hangs again, open the PR via the GitHub web UI.\n';
|
|
@@ -34567,10 +35351,10 @@ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Enviro
|
|
|
34567
35351
|
// ../core/dist/world/context-injection.js
|
|
34568
35352
|
function injectWorldContext(opts) {
|
|
34569
35353
|
const { world } = opts;
|
|
34570
|
-
const claudeDir2 =
|
|
34571
|
-
|
|
35354
|
+
const claudeDir2 = path37.join(world.workspacePath, ".claude");
|
|
35355
|
+
fs38.mkdirSync(claudeDir2, { recursive: true });
|
|
34572
35356
|
const content = WORLD_CLAUDE_MD.replace("{{worldName}}", world.name).replace("{{worldId}}", world.id).replace("{{branch}}", world.branch).replace("{{taskBlock}}", buildTaskBlock(opts)).replace("{{reposList}}", buildReposList(world)).replace("{{servicesLine}}", buildServicesLine(opts.services)).replace("{{pleriPlaneLine}}", buildPleriPlaneLine(opts.pleriPlaneUrl)).replace("{{planFileBlock}}", buildPlanFileBlock(world)).replace("{{extraContextBlock}}", buildExtraContextBlock(opts.claudeMdExtra));
|
|
34573
|
-
|
|
35357
|
+
fs38.writeFileSync(path37.join(claudeDir2, "CLAUDE.md"), content);
|
|
34574
35358
|
writeOlamDocs(world.workspacePath);
|
|
34575
35359
|
}
|
|
34576
35360
|
function buildTaskBlock(opts) {
|
|
@@ -34644,10 +35428,10 @@ function buildExtraContextBlock(extra) {
|
|
|
34644
35428
|
${extra}`;
|
|
34645
35429
|
}
|
|
34646
35430
|
function writeOlamDocs(workspacePath) {
|
|
34647
|
-
const docsDir =
|
|
34648
|
-
|
|
34649
|
-
|
|
34650
|
-
|
|
35431
|
+
const docsDir = path37.join(workspacePath, ".olam", "docs");
|
|
35432
|
+
fs38.mkdirSync(docsDir, { recursive: true });
|
|
35433
|
+
fs38.writeFileSync(path37.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
|
|
35434
|
+
fs38.writeFileSync(path37.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
|
|
34651
35435
|
}
|
|
34652
35436
|
function formatTaskSource(ctx) {
|
|
34653
35437
|
if (ctx.source === "linear" && ctx.ticketId) {
|
|
@@ -34661,9 +35445,9 @@ function formatTaskSource(ctx) {
|
|
|
34661
35445
|
function hasPlanFile(world) {
|
|
34662
35446
|
if (world.repos.length === 0)
|
|
34663
35447
|
return false;
|
|
34664
|
-
const plansDir =
|
|
35448
|
+
const plansDir = path37.join(world.workspacePath, world.repos[0], "docs", "plans");
|
|
34665
35449
|
try {
|
|
34666
|
-
return
|
|
35450
|
+
return fs38.existsSync(plansDir) && fs38.readdirSync(plansDir).length > 0;
|
|
34667
35451
|
} catch {
|
|
34668
35452
|
return false;
|
|
34669
35453
|
}
|
|
@@ -34891,7 +35675,7 @@ async function installStack(exec, repos, stacks) {
|
|
|
34891
35675
|
|
|
34892
35676
|
// ../core/dist/world/stack-image.js
|
|
34893
35677
|
import { execSync as execSync3 } from "node:child_process";
|
|
34894
|
-
import * as
|
|
35678
|
+
import * as crypto6 from "node:crypto";
|
|
34895
35679
|
var BASE_IMAGE = "olam-devbox";
|
|
34896
35680
|
var LABEL_PREFIX = "olam.stack-image";
|
|
34897
35681
|
var MAX_TAG_LENGTH = 128;
|
|
@@ -34947,7 +35731,7 @@ function getImageDigest(imageRef) {
|
|
|
34947
35731
|
cachedImageDigests.set(imageRef, short);
|
|
34948
35732
|
return short;
|
|
34949
35733
|
} catch {
|
|
34950
|
-
const fallback =
|
|
35734
|
+
const fallback = crypto6.createHash("sha256").update(imageRef).digest("hex").slice(0, 16);
|
|
34951
35735
|
cachedImageDigests.set(imageRef, fallback);
|
|
34952
35736
|
return fallback;
|
|
34953
35737
|
}
|
|
@@ -34958,7 +35742,7 @@ function getBaseImageDigest() {
|
|
|
34958
35742
|
function sanitizeTag(raw) {
|
|
34959
35743
|
let tag = raw.toLowerCase().replace(/[^a-z0-9._-]/g, "-");
|
|
34960
35744
|
if (tag.length > MAX_TAG_LENGTH) {
|
|
34961
|
-
const hash =
|
|
35745
|
+
const hash = crypto6.createHash("sha256").update(raw).digest("hex").slice(0, 12);
|
|
34962
35746
|
tag = tag.slice(0, MAX_TAG_LENGTH - 13) + "_" + hash;
|
|
34963
35747
|
}
|
|
34964
35748
|
return tag;
|
|
@@ -35234,26 +36018,26 @@ function shellQuote(s) {
|
|
|
35234
36018
|
init_repo_manifest();
|
|
35235
36019
|
|
|
35236
36020
|
// ../core/dist/world/snapshot.js
|
|
35237
|
-
import * as
|
|
35238
|
-
import * as
|
|
35239
|
-
import * as
|
|
35240
|
-
import * as
|
|
36021
|
+
import * as crypto7 from "node:crypto";
|
|
36022
|
+
import * as fs39 from "node:fs";
|
|
36023
|
+
import * as os24 from "node:os";
|
|
36024
|
+
import * as path38 from "node:path";
|
|
35241
36025
|
import { execFileSync as execFileSync7, spawn as spawn2 } from "node:child_process";
|
|
35242
36026
|
import { gunzipSync } from "node:zlib";
|
|
35243
36027
|
function snapshotsDir() {
|
|
35244
|
-
return process.env["OLAM_SNAPSHOTS_DIR"] ??
|
|
36028
|
+
return process.env["OLAM_SNAPSHOTS_DIR"] ?? path38.join(os24.homedir(), ".olam", "snapshots");
|
|
35245
36029
|
}
|
|
35246
36030
|
function snapshotKindDirByWorkspace(workspace, arch, kind) {
|
|
35247
|
-
return
|
|
36031
|
+
return path38.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
|
|
35248
36032
|
}
|
|
35249
36033
|
function cleanupLegacyByWorldDir(worldId) {
|
|
35250
|
-
const legacyDir =
|
|
36034
|
+
const legacyDir = path38.join(snapshotsDir(), worldId);
|
|
35251
36035
|
if (worldId === "by-workspace")
|
|
35252
36036
|
return;
|
|
35253
|
-
if (!
|
|
36037
|
+
if (!fs39.existsSync(legacyDir))
|
|
35254
36038
|
return;
|
|
35255
36039
|
try {
|
|
35256
|
-
|
|
36040
|
+
fs39.rmSync(legacyDir, { recursive: true, force: true });
|
|
35257
36041
|
} catch {
|
|
35258
36042
|
}
|
|
35259
36043
|
}
|
|
@@ -35262,7 +36046,7 @@ function manifestPath(tarPath) {
|
|
|
35262
36046
|
}
|
|
35263
36047
|
function hashBuffers(entries) {
|
|
35264
36048
|
const sorted = [...entries].sort((a, b) => a.path.localeCompare(b.path));
|
|
35265
|
-
const hash =
|
|
36049
|
+
const hash = crypto7.createHash("sha256");
|
|
35266
36050
|
for (const entry of sorted) {
|
|
35267
36051
|
hash.update(entry.path);
|
|
35268
36052
|
hash.update("\0");
|
|
@@ -35272,11 +36056,11 @@ function hashBuffers(entries) {
|
|
|
35272
36056
|
return hash.digest("hex").slice(0, 12);
|
|
35273
36057
|
}
|
|
35274
36058
|
function computeGemsFingerprint(repoDir, imageDigest) {
|
|
35275
|
-
const lockfile =
|
|
35276
|
-
if (!
|
|
36059
|
+
const lockfile = path38.join(repoDir, "Gemfile.lock");
|
|
36060
|
+
if (!fs39.existsSync(lockfile))
|
|
35277
36061
|
return null;
|
|
35278
36062
|
const entries = [
|
|
35279
|
-
{ path: "Gemfile.lock", content:
|
|
36063
|
+
{ path: "Gemfile.lock", content: fs39.readFileSync(lockfile) }
|
|
35280
36064
|
];
|
|
35281
36065
|
if (imageDigest) {
|
|
35282
36066
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -35286,10 +36070,10 @@ function computeGemsFingerprint(repoDir, imageDigest) {
|
|
|
35286
36070
|
function computeNodeFingerprint(repoDir, imageDigest) {
|
|
35287
36071
|
const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
|
|
35288
36072
|
for (const name of candidates) {
|
|
35289
|
-
const lockfile =
|
|
35290
|
-
if (
|
|
36073
|
+
const lockfile = path38.join(repoDir, name);
|
|
36074
|
+
if (fs39.existsSync(lockfile)) {
|
|
35291
36075
|
const entries = [
|
|
35292
|
-
{ path: name, content:
|
|
36076
|
+
{ path: name, content: fs39.readFileSync(lockfile) }
|
|
35293
36077
|
];
|
|
35294
36078
|
if (imageDigest) {
|
|
35295
36079
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -35308,18 +36092,18 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
35308
36092
|
detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
|
|
35309
36093
|
};
|
|
35310
36094
|
}
|
|
35311
|
-
const parent =
|
|
35312
|
-
|
|
35313
|
-
const tmpSuffix = `.tmp-${process.pid}-${
|
|
36095
|
+
const parent = path38.dirname(destDir);
|
|
36096
|
+
fs39.mkdirSync(parent, { recursive: true });
|
|
36097
|
+
const tmpSuffix = `.tmp-${process.pid}-${crypto7.randomBytes(4).toString("hex")}`;
|
|
35314
36098
|
const tmpDir = `${destDir}${tmpSuffix}`;
|
|
35315
36099
|
try {
|
|
35316
|
-
|
|
36100
|
+
fs39.mkdirSync(tmpDir, { recursive: true });
|
|
35317
36101
|
execFileSync7("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
|
|
35318
|
-
|
|
36102
|
+
fs39.renameSync(tmpDir, destDir);
|
|
35319
36103
|
return { ok: true, entryCount: validation.entries.length };
|
|
35320
36104
|
} catch (err) {
|
|
35321
36105
|
try {
|
|
35322
|
-
|
|
36106
|
+
fs39.rmSync(tmpDir, { recursive: true, force: true });
|
|
35323
36107
|
} catch {
|
|
35324
36108
|
}
|
|
35325
36109
|
return {
|
|
@@ -35330,12 +36114,12 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
35330
36114
|
}
|
|
35331
36115
|
}
|
|
35332
36116
|
function resolvesWithin(base, target) {
|
|
35333
|
-
const resolved =
|
|
35334
|
-
const baseResolved =
|
|
35335
|
-
const rel =
|
|
36117
|
+
const resolved = path38.resolve(base, target);
|
|
36118
|
+
const baseResolved = path38.resolve(base);
|
|
36119
|
+
const rel = path38.relative(baseResolved, resolved);
|
|
35336
36120
|
if (rel === "")
|
|
35337
36121
|
return true;
|
|
35338
|
-
return !rel.startsWith("..") && !
|
|
36122
|
+
return !rel.startsWith("..") && !path38.isAbsolute(rel);
|
|
35339
36123
|
}
|
|
35340
36124
|
var TYPE_CHAR_TO_TYPE = {
|
|
35341
36125
|
"-": "file",
|
|
@@ -35385,7 +36169,7 @@ function parseTarListLine(line) {
|
|
|
35385
36169
|
function validateHardlinksBinary(tarPath, targetDir) {
|
|
35386
36170
|
let raw;
|
|
35387
36171
|
try {
|
|
35388
|
-
raw = gunzipSync(
|
|
36172
|
+
raw = gunzipSync(fs39.readFileSync(tarPath));
|
|
35389
36173
|
} catch {
|
|
35390
36174
|
return null;
|
|
35391
36175
|
}
|
|
@@ -35400,7 +36184,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
|
|
|
35400
36184
|
const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
|
|
35401
36185
|
const linkNull = block.indexOf(0, 157);
|
|
35402
36186
|
const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
|
|
35403
|
-
if (linkname && (
|
|
36187
|
+
if (linkname && (path38.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
|
|
35404
36188
|
return {
|
|
35405
36189
|
valid: false,
|
|
35406
36190
|
reason: "hardlink-escape",
|
|
@@ -35438,7 +36222,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
35438
36222
|
const entry = parseTarListLine(line);
|
|
35439
36223
|
if (!entry)
|
|
35440
36224
|
continue;
|
|
35441
|
-
if (
|
|
36225
|
+
if (path38.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
|
|
35442
36226
|
return {
|
|
35443
36227
|
valid: false,
|
|
35444
36228
|
reason: "path-traversal",
|
|
@@ -35446,8 +36230,8 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
35446
36230
|
};
|
|
35447
36231
|
}
|
|
35448
36232
|
if (entry.type === "symlink" && entry.linkname !== void 0) {
|
|
35449
|
-
const symlinkParent =
|
|
35450
|
-
if (
|
|
36233
|
+
const symlinkParent = path38.join(targetDir, path38.dirname(entry.name));
|
|
36234
|
+
if (path38.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path38.join(path38.dirname(entry.name), entry.linkname))) {
|
|
35451
36235
|
return {
|
|
35452
36236
|
valid: false,
|
|
35453
36237
|
reason: "symlink-escape",
|
|
@@ -35457,7 +36241,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
35457
36241
|
}
|
|
35458
36242
|
}
|
|
35459
36243
|
if (entry.type === "hardlink" && entry.linkname !== void 0) {
|
|
35460
|
-
if (
|
|
36244
|
+
if (path38.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
|
|
35461
36245
|
return {
|
|
35462
36246
|
valid: false,
|
|
35463
36247
|
reason: "hardlink-escape",
|
|
@@ -35490,8 +36274,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
35490
36274
|
}
|
|
35491
36275
|
const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
|
|
35492
36276
|
const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
|
|
35493
|
-
const tarPath =
|
|
35494
|
-
if (!
|
|
36277
|
+
const tarPath = path38.join(archDir, tarFilename);
|
|
36278
|
+
if (!fs39.existsSync(tarPath)) {
|
|
35495
36279
|
outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
|
|
35496
36280
|
continue;
|
|
35497
36281
|
}
|
|
@@ -35506,9 +36290,9 @@ function restoreSnapshotsForRepos(input) {
|
|
|
35506
36290
|
});
|
|
35507
36291
|
continue;
|
|
35508
36292
|
}
|
|
35509
|
-
const targetDir =
|
|
36293
|
+
const targetDir = path38.join(repo.worktreeDir, targetSubpath);
|
|
35510
36294
|
try {
|
|
35511
|
-
|
|
36295
|
+
fs39.rmSync(targetDir, { recursive: true, force: true });
|
|
35512
36296
|
} catch {
|
|
35513
36297
|
}
|
|
35514
36298
|
const result = unpackTarballAtomic(tarPath, targetDir);
|
|
@@ -35521,8 +36305,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
35521
36305
|
fingerprint
|
|
35522
36306
|
});
|
|
35523
36307
|
try {
|
|
35524
|
-
|
|
35525
|
-
|
|
36308
|
+
fs39.rmSync(tarPath, { force: true });
|
|
36309
|
+
fs39.rmSync(manifestPath(tarPath), { force: true });
|
|
35526
36310
|
} catch {
|
|
35527
36311
|
}
|
|
35528
36312
|
continue;
|
|
@@ -35538,10 +36322,10 @@ function restoreSnapshotsForRepos(input) {
|
|
|
35538
36322
|
}
|
|
35539
36323
|
function readManifest(tarPath) {
|
|
35540
36324
|
const mPath = manifestPath(tarPath);
|
|
35541
|
-
if (!
|
|
36325
|
+
if (!fs39.existsSync(mPath))
|
|
35542
36326
|
return null;
|
|
35543
36327
|
try {
|
|
35544
|
-
return JSON.parse(
|
|
36328
|
+
return JSON.parse(fs39.readFileSync(mPath, "utf-8"));
|
|
35545
36329
|
} catch {
|
|
35546
36330
|
return null;
|
|
35547
36331
|
}
|
|
@@ -35556,17 +36340,17 @@ function isPidAlive(pid) {
|
|
|
35556
36340
|
}
|
|
35557
36341
|
}
|
|
35558
36342
|
function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
35559
|
-
|
|
35560
|
-
const lockPath =
|
|
36343
|
+
fs39.mkdirSync(dir, { recursive: true });
|
|
36344
|
+
const lockPath = path38.join(dir, EVICT_LOCK_FILENAME);
|
|
35561
36345
|
let fd;
|
|
35562
36346
|
try {
|
|
35563
|
-
fd =
|
|
36347
|
+
fd = fs39.openSync(lockPath, fs39.constants.O_WRONLY | fs39.constants.O_CREAT | fs39.constants.O_EXCL, 384);
|
|
35564
36348
|
} catch (err) {
|
|
35565
36349
|
if (err.code !== "EEXIST")
|
|
35566
36350
|
return 0;
|
|
35567
36351
|
let holderPid = null;
|
|
35568
36352
|
try {
|
|
35569
|
-
holderPid = parseInt(
|
|
36353
|
+
holderPid = parseInt(fs39.readFileSync(lockPath, "utf-8").trim(), 10);
|
|
35570
36354
|
} catch {
|
|
35571
36355
|
holderPid = null;
|
|
35572
36356
|
}
|
|
@@ -35574,23 +36358,23 @@ function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
|
35574
36358
|
return 0;
|
|
35575
36359
|
}
|
|
35576
36360
|
try {
|
|
35577
|
-
|
|
35578
|
-
fd =
|
|
36361
|
+
fs39.unlinkSync(lockPath);
|
|
36362
|
+
fd = fs39.openSync(lockPath, fs39.constants.O_WRONLY | fs39.constants.O_CREAT | fs39.constants.O_EXCL, 384);
|
|
35579
36363
|
} catch {
|
|
35580
36364
|
return 0;
|
|
35581
36365
|
}
|
|
35582
36366
|
}
|
|
35583
36367
|
try {
|
|
35584
|
-
|
|
36368
|
+
fs39.writeSync(fd, `${process.pid}
|
|
35585
36369
|
`);
|
|
35586
36370
|
} finally {
|
|
35587
|
-
|
|
36371
|
+
fs39.closeSync(fd);
|
|
35588
36372
|
}
|
|
35589
36373
|
try {
|
|
35590
36374
|
return evictOldSnapshots(maxBytes, dir);
|
|
35591
36375
|
} finally {
|
|
35592
36376
|
try {
|
|
35593
|
-
|
|
36377
|
+
fs39.unlinkSync(lockPath);
|
|
35594
36378
|
} catch {
|
|
35595
36379
|
}
|
|
35596
36380
|
}
|
|
@@ -35623,16 +36407,16 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
|
|
|
35623
36407
|
}
|
|
35624
36408
|
}
|
|
35625
36409
|
function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
35626
|
-
if (!
|
|
36410
|
+
if (!fs39.existsSync(dir))
|
|
35627
36411
|
return 0;
|
|
35628
36412
|
const allTars = [];
|
|
35629
36413
|
const walk = (d) => {
|
|
35630
|
-
for (const entry of
|
|
35631
|
-
const full =
|
|
36414
|
+
for (const entry of fs39.readdirSync(d, { withFileTypes: true })) {
|
|
36415
|
+
const full = path38.join(d, entry.name);
|
|
35632
36416
|
if (entry.isDirectory()) {
|
|
35633
36417
|
walk(full);
|
|
35634
36418
|
} else if (entry.name.endsWith(".tar.gz")) {
|
|
35635
|
-
const stat =
|
|
36419
|
+
const stat = fs39.statSync(full);
|
|
35636
36420
|
allTars.push({ path: full, size: stat.size, mtime: stat.mtimeMs });
|
|
35637
36421
|
}
|
|
35638
36422
|
}
|
|
@@ -35647,8 +36431,8 @@ function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
|
35647
36431
|
for (const tar of allTars) {
|
|
35648
36432
|
if (remaining <= maxBytes)
|
|
35649
36433
|
break;
|
|
35650
|
-
|
|
35651
|
-
|
|
36434
|
+
fs39.rmSync(tar.path, { force: true });
|
|
36435
|
+
fs39.rmSync(manifestPath(tar.path), { force: true });
|
|
35652
36436
|
freed += tar.size;
|
|
35653
36437
|
remaining -= tar.size;
|
|
35654
36438
|
}
|
|
@@ -35765,14 +36549,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
|
|
|
35765
36549
|
|
|
35766
36550
|
// ../core/dist/world/olam-yaml.js
|
|
35767
36551
|
init_repo_manifest();
|
|
35768
|
-
import * as
|
|
36552
|
+
import * as path39 from "node:path";
|
|
35769
36553
|
import YAML2 from "yaml";
|
|
35770
36554
|
function enrichReposWithManifests(repos, workspacePath) {
|
|
35771
36555
|
return repos.map((repo) => {
|
|
35772
36556
|
if (repo.manifest !== void 0 && repo.manifest !== null) {
|
|
35773
36557
|
return repo;
|
|
35774
36558
|
}
|
|
35775
|
-
const repoDir =
|
|
36559
|
+
const repoDir = path39.join(workspacePath, repo.name);
|
|
35776
36560
|
let manifest = null;
|
|
35777
36561
|
try {
|
|
35778
36562
|
manifest = loadRepoManifest(repoDir);
|
|
@@ -35787,8 +36571,8 @@ function enrichReposWithManifests(repos, workspacePath) {
|
|
|
35787
36571
|
}
|
|
35788
36572
|
|
|
35789
36573
|
// ../core/dist/policies/loader.js
|
|
35790
|
-
import * as
|
|
35791
|
-
import * as
|
|
36574
|
+
import * as fs40 from "node:fs";
|
|
36575
|
+
import * as path40 from "node:path";
|
|
35792
36576
|
import { parse as parseYaml4 } from "yaml";
|
|
35793
36577
|
function parseFrontmatter(content) {
|
|
35794
36578
|
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
|
|
@@ -35808,20 +36592,20 @@ function toStringArray(v) {
|
|
|
35808
36592
|
return v.filter((x) => typeof x === "string");
|
|
35809
36593
|
}
|
|
35810
36594
|
function loadPolicies(workspaceRoot) {
|
|
35811
|
-
const policiesDir =
|
|
35812
|
-
if (!
|
|
36595
|
+
const policiesDir = path40.join(workspaceRoot, ".olam", "policies");
|
|
36596
|
+
if (!fs40.existsSync(policiesDir))
|
|
35813
36597
|
return [];
|
|
35814
36598
|
let files;
|
|
35815
36599
|
try {
|
|
35816
|
-
files =
|
|
36600
|
+
files = fs40.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
|
|
35817
36601
|
} catch {
|
|
35818
36602
|
return [];
|
|
35819
36603
|
}
|
|
35820
36604
|
const policies = [];
|
|
35821
36605
|
for (const file of files) {
|
|
35822
|
-
const filePath =
|
|
36606
|
+
const filePath = path40.join(policiesDir, file);
|
|
35823
36607
|
try {
|
|
35824
|
-
const content =
|
|
36608
|
+
const content = fs40.readFileSync(filePath, "utf8");
|
|
35825
36609
|
const parsed = parseFrontmatter(content);
|
|
35826
36610
|
if (!parsed) {
|
|
35827
36611
|
console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
|
|
@@ -35905,7 +36689,7 @@ var TaskDispatchError = class extends Error {
|
|
|
35905
36689
|
}
|
|
35906
36690
|
};
|
|
35907
36691
|
var DEFAULT_SLEEP = (ms) => new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
35908
|
-
async function probeHealth(containerName, dockerExec, budgetMs,
|
|
36692
|
+
async function probeHealth(containerName, dockerExec, budgetMs, sleep5) {
|
|
35909
36693
|
const deadline = Date.now() + budgetMs;
|
|
35910
36694
|
const cadenceMs = 100;
|
|
35911
36695
|
let lastErr = "";
|
|
@@ -35918,7 +36702,7 @@ async function probeHealth(containerName, dockerExec, budgetMs, sleep4) {
|
|
|
35918
36702
|
} catch (err) {
|
|
35919
36703
|
lastErr = err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200);
|
|
35920
36704
|
}
|
|
35921
|
-
await
|
|
36705
|
+
await sleep5(cadenceMs);
|
|
35922
36706
|
}
|
|
35923
36707
|
throw new TaskDispatchError(`container-cp /health did not return 200 within ${budgetMs}ms`, "health-probe", lastErr || "no response");
|
|
35924
36708
|
}
|
|
@@ -35954,9 +36738,9 @@ function composeTaskPrompt(task, policies, formatPoliciesBrief2) {
|
|
|
35954
36738
|
${task}`;
|
|
35955
36739
|
}
|
|
35956
36740
|
async function autoDispatchTask(opts) {
|
|
35957
|
-
const { containerName, task, policies, dockerExec, healthBudgetMs = 15e3, sleep:
|
|
36741
|
+
const { containerName, task, policies, dockerExec, healthBudgetMs = 15e3, sleep: sleep5 = DEFAULT_SLEEP, logger: logger2 = console, formatPoliciesBrief: formatPoliciesBrief2 } = opts;
|
|
35958
36742
|
const finalPrompt = composeTaskPrompt(task, policies, formatPoliciesBrief2);
|
|
35959
|
-
await probeHealth(containerName, dockerExec, healthBudgetMs,
|
|
36743
|
+
await probeHealth(containerName, dockerExec, healthBudgetMs, sleep5);
|
|
35960
36744
|
startAgent(containerName, dockerExec);
|
|
35961
36745
|
dispatch2(containerName, finalPrompt, dockerExec);
|
|
35962
36746
|
logger2.log(`[world] Task auto-dispatched (${finalPrompt.length} chars)`);
|
|
@@ -35968,12 +36752,12 @@ init_store();
|
|
|
35968
36752
|
init_bridge();
|
|
35969
36753
|
|
|
35970
36754
|
// ../core/dist/global-config/runbook-resolver.js
|
|
35971
|
-
import * as
|
|
35972
|
-
import * as
|
|
35973
|
-
import * as
|
|
36755
|
+
import * as fs41 from "node:fs";
|
|
36756
|
+
import * as os25 from "node:os";
|
|
36757
|
+
import * as path41 from "node:path";
|
|
35974
36758
|
function expandTilde(p) {
|
|
35975
36759
|
if (p === "~" || p.startsWith("~/")) {
|
|
35976
|
-
return
|
|
36760
|
+
return path41.join(os25.homedir(), p.slice(1));
|
|
35977
36761
|
}
|
|
35978
36762
|
return p;
|
|
35979
36763
|
}
|
|
@@ -35985,7 +36769,7 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
35985
36769
|
throw new Error(`repo "${repoName}" is referenced by runbook "${runbook.name}" but is not in the registry. Run "olam repos add ${repoName} --path <path>" to register it.`);
|
|
35986
36770
|
}
|
|
35987
36771
|
const resolvedPath = expandTilde(entry.path);
|
|
35988
|
-
if (!
|
|
36772
|
+
if (!fs41.existsSync(resolvedPath)) {
|
|
35989
36773
|
throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
|
|
35990
36774
|
}
|
|
35991
36775
|
}
|
|
@@ -36001,19 +36785,19 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
36001
36785
|
init_port_validator();
|
|
36002
36786
|
|
|
36003
36787
|
// ../core/dist/world/bootstrap-hooks.js
|
|
36004
|
-
import * as
|
|
36005
|
-
import * as
|
|
36788
|
+
import * as fs42 from "node:fs";
|
|
36789
|
+
import * as path42 from "node:path";
|
|
36006
36790
|
function runFixtureCopySeeds(seeds, workspacePath) {
|
|
36007
36791
|
if (!seeds)
|
|
36008
36792
|
return;
|
|
36009
36793
|
for (const seed of seeds) {
|
|
36010
36794
|
if (seed.type !== "fixture-copy")
|
|
36011
36795
|
continue;
|
|
36012
|
-
const srcAbs =
|
|
36013
|
-
const destAbs =
|
|
36014
|
-
const destDir =
|
|
36015
|
-
|
|
36016
|
-
|
|
36796
|
+
const srcAbs = path42.resolve(workspacePath, seed.repo, seed.src);
|
|
36797
|
+
const destAbs = path42.resolve(workspacePath, seed.repo, seed.dest);
|
|
36798
|
+
const destDir = path42.dirname(destAbs);
|
|
36799
|
+
fs42.mkdirSync(destDir, { recursive: true });
|
|
36800
|
+
fs42.cpSync(srcAbs, destAbs, { recursive: true, force: true });
|
|
36017
36801
|
}
|
|
36018
36802
|
}
|
|
36019
36803
|
async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
|
|
@@ -36107,7 +36891,7 @@ async function startSupervisedApps(containerName, worldId, repos, exec, options
|
|
|
36107
36891
|
const probeTimeoutMs = options.probeTimeoutMs ?? 3e4;
|
|
36108
36892
|
const probeIntervalMs = options.probeIntervalMs ?? 1e3;
|
|
36109
36893
|
const clock = options.clock ?? Date.now;
|
|
36110
|
-
const
|
|
36894
|
+
const sleep5 = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
36111
36895
|
for (const repo of repos) {
|
|
36112
36896
|
if (isPortBound(exec, containerName, repo.hostPort)) {
|
|
36113
36897
|
throw new PortInUseError(repo.hostPort, repo.name, repo.manifestPath);
|
|
@@ -36132,7 +36916,7 @@ async function startSupervisedApps(containerName, worldId, repos, exec, options
|
|
|
36132
36916
|
probeTimeoutMs,
|
|
36133
36917
|
probeIntervalMs,
|
|
36134
36918
|
clock,
|
|
36135
|
-
sleep:
|
|
36919
|
+
sleep: sleep5
|
|
36136
36920
|
})));
|
|
36137
36921
|
return {
|
|
36138
36922
|
sessionName,
|
|
@@ -36649,7 +37433,7 @@ ${detail}`);
|
|
|
36649
37433
|
runbookSeeds = resolved.seeds;
|
|
36650
37434
|
}
|
|
36651
37435
|
const worldId = generateWorldId();
|
|
36652
|
-
const workspacePath =
|
|
37436
|
+
const workspacePath = path43.join(os26.homedir(), ".olam", "worlds", worldId);
|
|
36653
37437
|
const portOffset = this.registry.getNextPortOffset();
|
|
36654
37438
|
const branch = opts.branchName ?? `olam/${worldId}`;
|
|
36655
37439
|
const repos = this.resolveReposWithWorkspace(opts);
|
|
@@ -36730,38 +37514,38 @@ ${detail}`);
|
|
|
36730
37514
|
for (const repo of repos) {
|
|
36731
37515
|
if (!repo.path)
|
|
36732
37516
|
continue;
|
|
36733
|
-
const sourceRoot = repo.path.replace(/^~/,
|
|
36734
|
-
const worktreeRoot =
|
|
36735
|
-
if (!
|
|
37517
|
+
const sourceRoot = repo.path.replace(/^~/, os26.homedir());
|
|
37518
|
+
const worktreeRoot = path43.join(workspacePath, repo.name);
|
|
37519
|
+
if (!fs43.existsSync(sourceRoot) || !fs43.existsSync(worktreeRoot))
|
|
36736
37520
|
continue;
|
|
36737
37521
|
let copied = 0;
|
|
36738
37522
|
for (const pattern of RUNTIME_FILE_PATTERNS) {
|
|
36739
37523
|
const matches2 = [];
|
|
36740
37524
|
if (pattern.includes("*")) {
|
|
36741
|
-
const [dir, glob] = [
|
|
36742
|
-
const sourceDir =
|
|
36743
|
-
if (
|
|
37525
|
+
const [dir, glob] = [path43.dirname(pattern), path43.basename(pattern)];
|
|
37526
|
+
const sourceDir = path43.join(sourceRoot, dir);
|
|
37527
|
+
if (fs43.existsSync(sourceDir)) {
|
|
36744
37528
|
const ext = glob.replace(/^\*+/, "");
|
|
36745
37529
|
try {
|
|
36746
|
-
for (const entry of
|
|
37530
|
+
for (const entry of fs43.readdirSync(sourceDir)) {
|
|
36747
37531
|
if (ext === "" || entry.endsWith(ext))
|
|
36748
|
-
matches2.push(
|
|
37532
|
+
matches2.push(path43.join(dir, entry));
|
|
36749
37533
|
}
|
|
36750
37534
|
} catch {
|
|
36751
37535
|
}
|
|
36752
37536
|
}
|
|
36753
|
-
} else if (
|
|
37537
|
+
} else if (fs43.existsSync(path43.join(sourceRoot, pattern))) {
|
|
36754
37538
|
matches2.push(pattern);
|
|
36755
37539
|
}
|
|
36756
37540
|
for (const rel of matches2) {
|
|
36757
|
-
const src =
|
|
36758
|
-
const dst =
|
|
37541
|
+
const src = path43.join(sourceRoot, rel);
|
|
37542
|
+
const dst = path43.join(worktreeRoot, rel);
|
|
36759
37543
|
try {
|
|
36760
|
-
const st =
|
|
37544
|
+
const st = fs43.statSync(src);
|
|
36761
37545
|
if (!st.isFile())
|
|
36762
37546
|
continue;
|
|
36763
|
-
|
|
36764
|
-
|
|
37547
|
+
fs43.mkdirSync(path43.dirname(dst), { recursive: true });
|
|
37548
|
+
fs43.copyFileSync(src, dst);
|
|
36765
37549
|
copied++;
|
|
36766
37550
|
} catch {
|
|
36767
37551
|
}
|
|
@@ -36847,7 +37631,7 @@ ${detail}`);
|
|
|
36847
37631
|
}
|
|
36848
37632
|
const overlayAttachments = [];
|
|
36849
37633
|
for (const repo of repos) {
|
|
36850
|
-
const worldClonePath =
|
|
37634
|
+
const worldClonePath = path43.join(workspacePath, repo.name);
|
|
36851
37635
|
try {
|
|
36852
37636
|
const result = createWorldOverlay({
|
|
36853
37637
|
workspace: repo.name,
|
|
@@ -36902,7 +37686,7 @@ ${detail}`);
|
|
|
36902
37686
|
try {
|
|
36903
37687
|
const hostExec = makeHostExecFn();
|
|
36904
37688
|
for (const repo of repos) {
|
|
36905
|
-
const repoDir =
|
|
37689
|
+
const repoDir = path43.join(workspacePath, repo.name);
|
|
36906
37690
|
if (repo.stack && Object.keys(repo.stack).length > 0) {
|
|
36907
37691
|
preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
|
|
36908
37692
|
} else {
|
|
@@ -36946,10 +37730,10 @@ ${detail}`);
|
|
|
36946
37730
|
const worldEnv = {};
|
|
36947
37731
|
if (opts.task)
|
|
36948
37732
|
worldEnv.OLAM_TASK = opts.task;
|
|
36949
|
-
const r2CredsPath =
|
|
36950
|
-
if (
|
|
37733
|
+
const r2CredsPath = path43.join(os26.homedir(), ".olam", "r2-credentials.json");
|
|
37734
|
+
if (fs43.existsSync(r2CredsPath)) {
|
|
36951
37735
|
try {
|
|
36952
|
-
const r2Raw =
|
|
37736
|
+
const r2Raw = fs43.readFileSync(r2CredsPath, "utf-8").trim();
|
|
36953
37737
|
if (r2Raw.length > 0) {
|
|
36954
37738
|
const r2 = JSON.parse(r2Raw);
|
|
36955
37739
|
if (typeof r2.account_id === "string")
|
|
@@ -36966,10 +37750,10 @@ ${detail}`);
|
|
|
36966
37750
|
} catch {
|
|
36967
37751
|
}
|
|
36968
37752
|
}
|
|
36969
|
-
const keysYamlPath =
|
|
36970
|
-
if (
|
|
37753
|
+
const keysYamlPath = path43.join(os26.homedir(), ".olam", "keys.yaml");
|
|
37754
|
+
if (fs43.existsSync(keysYamlPath)) {
|
|
36971
37755
|
try {
|
|
36972
|
-
const keysRaw =
|
|
37756
|
+
const keysRaw = fs43.readFileSync(keysYamlPath, "utf-8").trim();
|
|
36973
37757
|
if (keysRaw.length > 0) {
|
|
36974
37758
|
const parsed = YAML3.parse(keysRaw);
|
|
36975
37759
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
@@ -37028,10 +37812,10 @@ ${detail}`);
|
|
|
37028
37812
|
worldEnv[k] = v;
|
|
37029
37813
|
}
|
|
37030
37814
|
for (const { repoName, relativePath, content } of fileWrites) {
|
|
37031
|
-
const absPath =
|
|
37815
|
+
const absPath = path43.join(workspacePath, repoName, relativePath);
|
|
37032
37816
|
try {
|
|
37033
|
-
|
|
37034
|
-
|
|
37817
|
+
fs43.mkdirSync(path43.dirname(absPath), { recursive: true });
|
|
37818
|
+
fs43.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
|
|
37035
37819
|
mode: 384
|
|
37036
37820
|
});
|
|
37037
37821
|
console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
|
|
@@ -37202,7 +37986,7 @@ ${detail}`);
|
|
|
37202
37986
|
imageDigest: void 0,
|
|
37203
37987
|
repos: enrichedRepos.map((r) => ({
|
|
37204
37988
|
name: r.name,
|
|
37205
|
-
worktreeDir:
|
|
37989
|
+
worktreeDir: path43.join(workspacePath, r.name)
|
|
37206
37990
|
}))
|
|
37207
37991
|
});
|
|
37208
37992
|
for (const out of restoreResult.outcomes) {
|
|
@@ -37308,7 +38092,7 @@ ${detail}`);
|
|
|
37308
38092
|
}
|
|
37309
38093
|
if (opts.task) {
|
|
37310
38094
|
const allPolicies = repos.flatMap((repo) => {
|
|
37311
|
-
const repoWorktree =
|
|
38095
|
+
const repoWorktree = path43.join(workspacePath, repo.name);
|
|
37312
38096
|
try {
|
|
37313
38097
|
return loadPolicies(repoWorktree);
|
|
37314
38098
|
} catch (err) {
|
|
@@ -37321,8 +38105,8 @@ ${detail}`);
|
|
|
37321
38105
|
try {
|
|
37322
38106
|
execSync5(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
37323
38107
|
for (const repo of repos) {
|
|
37324
|
-
const policiesDir =
|
|
37325
|
-
if (
|
|
38108
|
+
const policiesDir = path43.join(workspacePath, repo.name, ".olam", "policies");
|
|
38109
|
+
if (fs43.existsSync(policiesDir)) {
|
|
37326
38110
|
execSync5(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
37327
38111
|
}
|
|
37328
38112
|
}
|
|
@@ -37430,8 +38214,8 @@ ${detail}`);
|
|
|
37430
38214
|
} catch {
|
|
37431
38215
|
}
|
|
37432
38216
|
try {
|
|
37433
|
-
|
|
37434
|
-
if (
|
|
38217
|
+
fs43.rmSync(world.workspacePath, { recursive: true, force: true });
|
|
38218
|
+
if (fs43.existsSync(world.workspacePath)) {
|
|
37435
38219
|
console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
|
|
37436
38220
|
}
|
|
37437
38221
|
} catch (err) {
|
|
@@ -37540,14 +38324,14 @@ ${detail}`);
|
|
|
37540
38324
|
}).filter((r) => r !== void 0);
|
|
37541
38325
|
}
|
|
37542
38326
|
transportPlanFile(planFilePath, workspacePath, repoNames) {
|
|
37543
|
-
const planContent =
|
|
37544
|
-
const planFileName =
|
|
38327
|
+
const planContent = fs43.readFileSync(planFilePath, "utf-8");
|
|
38328
|
+
const planFileName = path43.basename(planFilePath);
|
|
37545
38329
|
const targetRepo = repoNames[0];
|
|
37546
38330
|
if (!targetRepo)
|
|
37547
38331
|
return;
|
|
37548
|
-
const plansDir =
|
|
37549
|
-
|
|
37550
|
-
|
|
38332
|
+
const plansDir = path43.join(workspacePath, targetRepo, "docs", "plans");
|
|
38333
|
+
fs43.mkdirSync(plansDir, { recursive: true });
|
|
38334
|
+
fs43.writeFileSync(path43.join(plansDir, planFileName), planContent);
|
|
37551
38335
|
}
|
|
37552
38336
|
resolveServices(repos) {
|
|
37553
38337
|
const services = [];
|
|
@@ -37850,7 +38634,7 @@ function applyPostgresWorldRole(worldId, worldDbNames, options = {}) {
|
|
|
37850
38634
|
return { worldRoleName, password };
|
|
37851
38635
|
}
|
|
37852
38636
|
function defaultPasswordGenerator() {
|
|
37853
|
-
return
|
|
38637
|
+
return crypto8.randomBytes(24).toString("base64url");
|
|
37854
38638
|
}
|
|
37855
38639
|
function escapeSqlLiteral(s) {
|
|
37856
38640
|
return s.replace(/'/g, "''");
|
|
@@ -37981,8 +38765,8 @@ import * as http2 from "node:http";
|
|
|
37981
38765
|
|
|
37982
38766
|
// ../core/dist/dashboard/server.js
|
|
37983
38767
|
import * as http from "node:http";
|
|
37984
|
-
import * as
|
|
37985
|
-
import * as
|
|
38768
|
+
import * as fs44 from "node:fs";
|
|
38769
|
+
import * as path44 from "node:path";
|
|
37986
38770
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
37987
38771
|
|
|
37988
38772
|
// ../core/dist/dashboard/serialize.js
|
|
@@ -38317,7 +39101,7 @@ function notFound(res) {
|
|
|
38317
39101
|
}
|
|
38318
39102
|
function openThoughtStore(workspacePath) {
|
|
38319
39103
|
const dbPath = getWorldDbPath(workspacePath);
|
|
38320
|
-
if (!
|
|
39104
|
+
if (!fs44.existsSync(dbPath))
|
|
38321
39105
|
return null;
|
|
38322
39106
|
return new ThoughtLocalStore(dbPath);
|
|
38323
39107
|
}
|
|
@@ -38488,13 +39272,13 @@ function findSessionInWorld(registry2, sessionId) {
|
|
|
38488
39272
|
}
|
|
38489
39273
|
function createDashboardServer(opts) {
|
|
38490
39274
|
const { port: port2, registry: registry2 } = opts;
|
|
38491
|
-
const thisDir =
|
|
38492
|
-
const defaultPublicDir =
|
|
39275
|
+
const thisDir = path44.dirname(fileURLToPath2(import.meta.url));
|
|
39276
|
+
const defaultPublicDir = path44.resolve(thisDir, "../../../control-plane/public");
|
|
38493
39277
|
const publicDir = opts.publicDir ?? defaultPublicDir;
|
|
38494
|
-
let hasPublicDir =
|
|
39278
|
+
let hasPublicDir = fs44.existsSync(publicDir);
|
|
38495
39279
|
const server = http.createServer((req, res) => {
|
|
38496
39280
|
if (!hasPublicDir) {
|
|
38497
|
-
hasPublicDir =
|
|
39281
|
+
hasPublicDir = fs44.existsSync(publicDir);
|
|
38498
39282
|
}
|
|
38499
39283
|
const host = req.headers.host ?? `localhost:${port2}`;
|
|
38500
39284
|
const url2 = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -38768,22 +39552,22 @@ function createDashboardServer(opts) {
|
|
|
38768
39552
|
res.end(`<html><body style="font-family:system-ui;padding:2rem"><h1>Olam Dashboard</h1><p>The React app has not been built yet.</p><p>Run <code>npm run build:app</code> in <code>packages/control-plane</code> to build it.</p><p>API routes are available at <code>/api/*</code>.</p></body></html>`);
|
|
38769
39553
|
return;
|
|
38770
39554
|
}
|
|
38771
|
-
let filePath =
|
|
39555
|
+
let filePath = path44.join(publicDir, pathname === "/" ? "index.html" : pathname);
|
|
38772
39556
|
if (!filePath.startsWith(publicDir)) {
|
|
38773
39557
|
notFound(res);
|
|
38774
39558
|
return;
|
|
38775
39559
|
}
|
|
38776
|
-
if (
|
|
38777
|
-
const ext =
|
|
39560
|
+
if (fs44.existsSync(filePath) && fs44.statSync(filePath).isFile()) {
|
|
39561
|
+
const ext = path44.extname(filePath);
|
|
38778
39562
|
const contentType = MIME[ext] ?? "application/octet-stream";
|
|
38779
39563
|
res.writeHead(200, { "Content-Type": contentType });
|
|
38780
|
-
|
|
39564
|
+
fs44.createReadStream(filePath).pipe(res);
|
|
38781
39565
|
return;
|
|
38782
39566
|
}
|
|
38783
|
-
filePath =
|
|
38784
|
-
if (
|
|
39567
|
+
filePath = path44.join(publicDir, "index.html");
|
|
39568
|
+
if (fs44.existsSync(filePath)) {
|
|
38785
39569
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
38786
|
-
|
|
39570
|
+
fs44.createReadStream(filePath).pipe(res);
|
|
38787
39571
|
return;
|
|
38788
39572
|
}
|
|
38789
39573
|
notFound(res);
|
|
@@ -38793,17 +39577,17 @@ function createDashboardServer(opts) {
|
|
|
38793
39577
|
}
|
|
38794
39578
|
|
|
38795
39579
|
// ../core/dist/dashboard/state.js
|
|
38796
|
-
import * as
|
|
38797
|
-
import * as
|
|
38798
|
-
import * as
|
|
38799
|
-
var STATE_PATH =
|
|
39580
|
+
import * as fs45 from "node:fs";
|
|
39581
|
+
import * as os27 from "node:os";
|
|
39582
|
+
import * as path45 from "node:path";
|
|
39583
|
+
var STATE_PATH = path45.join(os27.homedir(), ".olam", "dashboard.json");
|
|
38800
39584
|
function saveDashboardState(state) {
|
|
38801
|
-
|
|
38802
|
-
|
|
39585
|
+
fs45.mkdirSync(path45.dirname(STATE_PATH), { recursive: true });
|
|
39586
|
+
fs45.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
|
|
38803
39587
|
}
|
|
38804
39588
|
function loadDashboardState() {
|
|
38805
39589
|
try {
|
|
38806
|
-
const raw =
|
|
39590
|
+
const raw = fs45.readFileSync(STATE_PATH, "utf-8");
|
|
38807
39591
|
return JSON.parse(raw);
|
|
38808
39592
|
} catch {
|
|
38809
39593
|
return null;
|
|
@@ -38811,7 +39595,7 @@ function loadDashboardState() {
|
|
|
38811
39595
|
}
|
|
38812
39596
|
function clearDashboardState() {
|
|
38813
39597
|
try {
|
|
38814
|
-
|
|
39598
|
+
fs45.unlinkSync(STATE_PATH);
|
|
38815
39599
|
} catch {
|
|
38816
39600
|
}
|
|
38817
39601
|
}
|
|
@@ -39091,8 +39875,8 @@ var PleriClient = class {
|
|
|
39091
39875
|
};
|
|
39092
39876
|
|
|
39093
39877
|
// ../mcp-server/src/env-loader.ts
|
|
39094
|
-
import { readFileSync as
|
|
39095
|
-
import { join as
|
|
39878
|
+
import { readFileSync as readFileSync33, existsSync as existsSync42, statSync as statSync12 } from "node:fs";
|
|
39879
|
+
import { join as join46, dirname as dirname27, resolve as resolve11 } from "node:path";
|
|
39096
39880
|
var PROJECT_MARKERS = [
|
|
39097
39881
|
".olam/config.yaml",
|
|
39098
39882
|
".olam/config.yml",
|
|
@@ -39104,26 +39888,26 @@ function findProjectRoot2(startDir) {
|
|
|
39104
39888
|
const root = resolve11("/");
|
|
39105
39889
|
while (true) {
|
|
39106
39890
|
for (const marker of PROJECT_MARKERS) {
|
|
39107
|
-
if (
|
|
39891
|
+
if (existsSync42(join46(dir, marker))) return dir;
|
|
39108
39892
|
}
|
|
39109
|
-
const pkg =
|
|
39110
|
-
if (
|
|
39893
|
+
const pkg = join46(dir, "package.json");
|
|
39894
|
+
if (existsSync42(pkg)) {
|
|
39111
39895
|
try {
|
|
39112
|
-
const json = JSON.parse(
|
|
39896
|
+
const json = JSON.parse(readFileSync33(pkg, "utf8"));
|
|
39113
39897
|
const isOlamWorkspace = typeof json.name === "string" && json.name.startsWith("@olam/");
|
|
39114
39898
|
const hasOlamDep = json.dependencies && Object.keys(json.dependencies).some((k) => k.startsWith("@olam/")) || json.devDependencies && Object.keys(json.devDependencies).some((k) => k.startsWith("@olam/"));
|
|
39115
39899
|
if (isOlamWorkspace || hasOlamDep) return dir;
|
|
39116
39900
|
} catch {
|
|
39117
39901
|
}
|
|
39118
39902
|
}
|
|
39119
|
-
const parent =
|
|
39903
|
+
const parent = dirname27(dir);
|
|
39120
39904
|
if (parent === dir || parent === root) return null;
|
|
39121
39905
|
dir = parent;
|
|
39122
39906
|
}
|
|
39123
39907
|
}
|
|
39124
|
-
function parseEnvFile(
|
|
39908
|
+
function parseEnvFile(path46) {
|
|
39125
39909
|
const out = {};
|
|
39126
|
-
const raw =
|
|
39910
|
+
const raw = readFileSync33(path46, "utf8");
|
|
39127
39911
|
for (const line of raw.split(/\r?\n/)) {
|
|
39128
39912
|
const trimmed = line.trim();
|
|
39129
39913
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -39146,8 +39930,8 @@ function loadProjectEnv(startDir = process.cwd()) {
|
|
|
39146
39930
|
const filesRead = [];
|
|
39147
39931
|
const merged = {};
|
|
39148
39932
|
for (const name of [".env", ".env.local"]) {
|
|
39149
|
-
const p =
|
|
39150
|
-
if (
|
|
39933
|
+
const p = join46(root, name);
|
|
39934
|
+
if (existsSync42(p) && statSync12(p).isFile()) {
|
|
39151
39935
|
Object.assign(merged, parseEnvFile(p));
|
|
39152
39936
|
filesRead.push(p);
|
|
39153
39937
|
}
|