@pleri/olam-cli 0.1.168 → 0.1.170
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/README.md +38 -0
- package/dist/commands/auth-status.d.ts +1 -0
- package/dist/commands/auth-status.d.ts.map +1 -1
- package/dist/commands/auth-status.js +45 -4
- package/dist/commands/auth-status.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +26 -0
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/enter.d.ts.map +1 -1
- package/dist/commands/enter.js +5 -0
- package/dist/commands/enter.js.map +1 -1
- package/dist/commands/resume.d.ts +63 -0
- package/dist/commands/resume.d.ts.map +1 -0
- package/dist/commands/resume.js +174 -0
- package/dist/commands/resume.js.map +1 -0
- package/dist/commands/setup.d.ts +19 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +157 -19
- package/dist/commands/setup.js.map +1 -1
- package/dist/image-digests.json +8 -8
- package/dist/index.js +1021 -576
- package/dist/index.js.map +1 -1
- package/dist/lib/health-probes.d.ts +28 -0
- package/dist/lib/health-probes.d.ts.map +1 -1
- package/dist/lib/health-probes.js +75 -0
- package/dist/lib/health-probes.js.map +1 -1
- package/dist/lib/k8s-context-discovery.d.ts +80 -0
- package/dist/lib/k8s-context-discovery.d.ts.map +1 -0
- package/dist/lib/k8s-context-discovery.js +102 -0
- package/dist/lib/k8s-context-discovery.js.map +1 -0
- package/dist/mcp-server.js +1273 -771
- package/dist/spawn/home-override.d.ts +82 -0
- package/dist/spawn/home-override.d.ts.map +1 -0
- package/dist/spawn/home-override.js +107 -0
- package/dist/spawn/home-override.js.map +1 -0
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/30-configmap.yaml +5 -0
- package/host-cp/k8s/manifests/50-deployment.yaml +9 -2
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
- package/host-cp/lifecycle/classify.mjs +110 -0
- package/host-cp/lifecycle/emit.mjs +119 -0
- package/host-cp/lifecycle/evidence.mjs +45 -0
- package/host-cp/lifecycle/failure-kinds.mjs +56 -0
- package/host-cp/lifecycle/index.mjs +22 -0
- package/host-cp/lifecycle/phases.mjs +52 -0
- package/host-cp/observability/grafana-port-forward.sh +1 -1
- package/host-cp/observability/kyverno-cardinality-mutate.sh +2 -2
- package/host-cp/observability/loki-ingest.sh +1 -1
- package/host-cp/observability/ndjson-span-sink.mjs +131 -0
- package/host-cp/observability/prom-no-double-grafana.sh +4 -4
- package/host-cp/observability/redactor.mjs +72 -0
- package/host-cp/recovery/engine.mjs +148 -0
- package/host-cp/recovery/index.mjs +16 -0
- package/host-cp/recovery/ledger.mjs +105 -0
- package/host-cp/recovery/recipes.mjs +46 -0
- package/host-cp/recovery/scenarios.mjs +124 -0
- package/host-cp/recovery/step-runners.mjs +263 -0
- package/host-cp/src/docker-events.mjs +30 -6
- package/host-cp/src/pr-nanny.mjs +55 -3
- package/host-cp/src/server.mjs +173 -0
- 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: path53, errorMaps, issueData } = params;
|
|
449
|
+
const fullPath = [...path53, ...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, path53, key) {
|
|
758
758
|
this._cachedPath = [];
|
|
759
759
|
this.parent = parent;
|
|
760
760
|
this.data = value;
|
|
761
|
-
this._path =
|
|
761
|
+
this._path = path53;
|
|
762
762
|
this._key = key;
|
|
763
763
|
}
|
|
764
764
|
get path() {
|
|
@@ -7090,7 +7090,7 @@ var require_compile = __commonJS({
|
|
|
7090
7090
|
const schOrFunc = root.refs[ref];
|
|
7091
7091
|
if (schOrFunc)
|
|
7092
7092
|
return schOrFunc;
|
|
7093
|
-
let _sch =
|
|
7093
|
+
let _sch = resolve15.call(this, root, ref);
|
|
7094
7094
|
if (_sch === void 0) {
|
|
7095
7095
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
7096
7096
|
const { schemaId } = this.opts;
|
|
@@ -7117,7 +7117,7 @@ var require_compile = __commonJS({
|
|
|
7117
7117
|
function sameSchemaEnv(s1, s2) {
|
|
7118
7118
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
7119
7119
|
}
|
|
7120
|
-
function
|
|
7120
|
+
function resolve15(root, ref) {
|
|
7121
7121
|
let sch;
|
|
7122
7122
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
7123
7123
|
ref = sch;
|
|
@@ -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(path53) {
|
|
7336
|
+
let input = path53;
|
|
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 [path53, query] = wsComponent.resourceName.split("?");
|
|
7536
|
+
wsComponent.path = path53 && path53 !== "/" ? path53 : void 0;
|
|
7537
7537
|
wsComponent.query = query;
|
|
7538
7538
|
wsComponent.resourceName = void 0;
|
|
7539
7539
|
}
|
|
@@ -7692,7 +7692,7 @@ var require_fast_uri = __commonJS({
|
|
|
7692
7692
|
}
|
|
7693
7693
|
return uri;
|
|
7694
7694
|
}
|
|
7695
|
-
function
|
|
7695
|
+
function resolve15(baseURI, relativeURI, options) {
|
|
7696
7696
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
7697
7697
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
7698
7698
|
schemelessOptions.skipEscape = true;
|
|
@@ -7919,7 +7919,7 @@ var require_fast_uri = __commonJS({
|
|
|
7919
7919
|
var fastUri = {
|
|
7920
7920
|
SCHEMES,
|
|
7921
7921
|
normalize,
|
|
7922
|
-
resolve:
|
|
7922
|
+
resolve: resolve15,
|
|
7923
7923
|
resolveComponent,
|
|
7924
7924
|
equal,
|
|
7925
7925
|
serialize,
|
|
@@ -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, fs52, 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, fs52[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, path53, 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, path52, ctx, rejectSource) {
|
|
|
11016
11016
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
11017
11017
|
ctx.addIssue({
|
|
11018
11018
|
code: external_exports.ZodIssueCode.custom,
|
|
11019
|
-
path: [...
|
|
11019
|
+
path: [...path53, key],
|
|
11020
11020
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
11021
11021
|
});
|
|
11022
11022
|
continue;
|
|
11023
11023
|
}
|
|
11024
|
-
if (rejectSource &&
|
|
11024
|
+
if (rejectSource && path53.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, path52, ctx, rejectSource) {
|
|
|
11029
11029
|
});
|
|
11030
11030
|
continue;
|
|
11031
11031
|
}
|
|
11032
|
-
refineForbiddenKeys(value[key], [...
|
|
11032
|
+
refineForbiddenKeys(value[key], [...path53, key], ctx, false);
|
|
11033
11033
|
}
|
|
11034
11034
|
}
|
|
11035
|
-
function rejectForbiddenKeys(value,
|
|
11035
|
+
function rejectForbiddenKeys(value, path53, 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] ${path53}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
11042
11042
|
}
|
|
11043
11043
|
if (rejectSource && key === "source") {
|
|
11044
|
-
throw new Error(`[manifest] ${
|
|
11044
|
+
throw new Error(`[manifest] ${path53}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
11045
11045
|
}
|
|
11046
|
-
rejectForbiddenKeys(value[key], `${
|
|
11046
|
+
rejectForbiddenKeys(value[key], `${path53}.${key}`, false);
|
|
11047
11047
|
}
|
|
11048
11048
|
}
|
|
11049
11049
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -11080,8 +11080,8 @@ function loadRepoManifest(repoDir) {
|
|
|
11080
11080
|
} else {
|
|
11081
11081
|
return null;
|
|
11082
11082
|
}
|
|
11083
|
-
const
|
|
11084
|
-
if (
|
|
11083
|
+
const stat2 = lstatSync(manifestPath2);
|
|
11084
|
+
if (stat2.isSymbolicLink()) {
|
|
11085
11085
|
throw new Error(`[manifest] ${manifestPath2}: symbolic links are not permitted`);
|
|
11086
11086
|
}
|
|
11087
11087
|
const raw = readFileSync3(manifestPath2, "utf-8");
|
|
@@ -11432,7 +11432,13 @@ var init_schema2 = __esm({
|
|
|
11432
11432
|
user: external_exports.string().min(1),
|
|
11433
11433
|
key: external_exports.string().optional()
|
|
11434
11434
|
});
|
|
11435
|
-
computeProviderType = external_exports.enum([
|
|
11435
|
+
computeProviderType = external_exports.enum([
|
|
11436
|
+
"docker",
|
|
11437
|
+
"ssh",
|
|
11438
|
+
"e2b",
|
|
11439
|
+
"cloudflare",
|
|
11440
|
+
"cloudflare-isolate"
|
|
11441
|
+
]);
|
|
11436
11442
|
stackImageSchema = external_exports.object({
|
|
11437
11443
|
enabled: external_exports.boolean().optional().default(true),
|
|
11438
11444
|
auto_commit: external_exports.boolean().optional().default(true),
|
|
@@ -11444,6 +11450,15 @@ var init_schema2 = __esm({
|
|
|
11444
11450
|
}).optional(),
|
|
11445
11451
|
ssh: external_exports.object({ hosts: external_exports.array(sshHostSchema).optional() }).optional(),
|
|
11446
11452
|
e2b: external_exports.object({ template: external_exports.string().optional() }).optional(),
|
|
11453
|
+
// V8-isolate runtime tier per ADR 022. Pure isolate, no DO, no Container.
|
|
11454
|
+
// worker_url points at the deployed olam-worker-runner-isolate Worker.
|
|
11455
|
+
// Same https-or-localhost guard as the cloudflare profile — bearer token
|
|
11456
|
+
// in cleartext would leak the OLAM_TASK_TOKEN.
|
|
11457
|
+
"cloudflare-isolate": external_exports.object({
|
|
11458
|
+
worker_url: external_exports.string().url("worker_url must be a valid URL").refine(isSecureOrLocalhost, {
|
|
11459
|
+
message: "worker_url must use https:// (or http://localhost for dev)"
|
|
11460
|
+
}).optional()
|
|
11461
|
+
}).optional(),
|
|
11447
11462
|
cloudflare: external_exports.object({
|
|
11448
11463
|
account_id: external_exports.string().optional(),
|
|
11449
11464
|
// https-only refine: bare http:// would send the operator's Pylon
|
|
@@ -12076,23 +12091,23 @@ var init_schema4 = __esm({
|
|
|
12076
12091
|
});
|
|
12077
12092
|
|
|
12078
12093
|
// ../core/dist/global-config/store.js
|
|
12079
|
-
import * as
|
|
12094
|
+
import * as fs11 from "node:fs";
|
|
12080
12095
|
import * as os7 from "node:os";
|
|
12081
|
-
import * as
|
|
12096
|
+
import * as path14 from "node:path";
|
|
12082
12097
|
function globalConfigPath() {
|
|
12083
12098
|
const override = process.env["OLAM_GLOBAL_CONFIG_PATH"];
|
|
12084
12099
|
if (override && override.length > 0)
|
|
12085
12100
|
return override;
|
|
12086
|
-
return
|
|
12101
|
+
return path14.join(os7.homedir(), ".olam", "config.json");
|
|
12087
12102
|
}
|
|
12088
12103
|
function readGlobalConfig() {
|
|
12089
12104
|
const configPath = globalConfigPath();
|
|
12090
|
-
if (!
|
|
12105
|
+
if (!fs11.existsSync(configPath)) {
|
|
12091
12106
|
return { ...DEFAULT_GLOBAL_CONFIG };
|
|
12092
12107
|
}
|
|
12093
12108
|
let raw;
|
|
12094
12109
|
try {
|
|
12095
|
-
raw =
|
|
12110
|
+
raw = fs11.readFileSync(configPath, "utf-8");
|
|
12096
12111
|
} catch (err) {
|
|
12097
12112
|
throw new GlobalConfigReadError(configPath, err);
|
|
12098
12113
|
}
|
|
@@ -12129,11 +12144,11 @@ function migrateSchemaVersion(parsed) {
|
|
|
12129
12144
|
function writeGlobalConfig(config2) {
|
|
12130
12145
|
const configPath = globalConfigPath();
|
|
12131
12146
|
const validated = GlobalConfigSchema.parse(config2);
|
|
12132
|
-
const dir =
|
|
12133
|
-
|
|
12147
|
+
const dir = path14.dirname(configPath);
|
|
12148
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
12134
12149
|
const tmp = `${configPath}.tmp-${process.pid}`;
|
|
12135
|
-
|
|
12136
|
-
|
|
12150
|
+
fs11.writeFileSync(tmp, JSON.stringify(validated, null, 2) + "\n", { mode: 420 });
|
|
12151
|
+
fs11.renameSync(tmp, configPath);
|
|
12137
12152
|
}
|
|
12138
12153
|
var GlobalConfigReadError;
|
|
12139
12154
|
var init_store = __esm({
|
|
@@ -12152,12 +12167,12 @@ var init_store = __esm({
|
|
|
12152
12167
|
});
|
|
12153
12168
|
|
|
12154
12169
|
// ../core/dist/global-config/repos.js
|
|
12155
|
-
import * as
|
|
12170
|
+
import * as fs12 from "node:fs";
|
|
12156
12171
|
import * as os8 from "node:os";
|
|
12157
|
-
import * as
|
|
12172
|
+
import * as path15 from "node:path";
|
|
12158
12173
|
function expandPath(p) {
|
|
12159
12174
|
if (p === "~" || p.startsWith("~/")) {
|
|
12160
|
-
return
|
|
12175
|
+
return path15.join(os8.homedir(), p.slice(1));
|
|
12161
12176
|
}
|
|
12162
12177
|
return p;
|
|
12163
12178
|
}
|
|
@@ -12170,7 +12185,7 @@ function addRepo(entry) {
|
|
|
12170
12185
|
throw new Error(`repo "${entry.name}" already registered. Use "olam repos update" to change its path.`);
|
|
12171
12186
|
}
|
|
12172
12187
|
const resolvedPath = expandPath(entry.path);
|
|
12173
|
-
if (!
|
|
12188
|
+
if (!fs12.existsSync(resolvedPath)) {
|
|
12174
12189
|
throw new Error(`path "${entry.path}" does not exist. Verify the path is correct.`);
|
|
12175
12190
|
}
|
|
12176
12191
|
const now = Date.now();
|
|
@@ -12199,7 +12214,7 @@ function updateRepo(name, updates) {
|
|
|
12199
12214
|
throw new Error(`repo "${name}" is not registered. Run "olam repos list" to see registered repos.`);
|
|
12200
12215
|
}
|
|
12201
12216
|
const resolvedUpdatePath = updates.path !== void 0 ? expandPath(updates.path) : void 0;
|
|
12202
|
-
if (resolvedUpdatePath !== void 0 && !
|
|
12217
|
+
if (resolvedUpdatePath !== void 0 && !fs12.existsSync(resolvedUpdatePath)) {
|
|
12203
12218
|
throw new Error(`path "${updates.path}" does not exist. Verify the path is correct.`);
|
|
12204
12219
|
}
|
|
12205
12220
|
const existing = config2.repos[idx];
|
|
@@ -12396,7 +12411,7 @@ var init_port_validator = __esm({
|
|
|
12396
12411
|
});
|
|
12397
12412
|
|
|
12398
12413
|
// ../core/dist/global-config/bridge.js
|
|
12399
|
-
import * as
|
|
12414
|
+
import * as fs13 from "node:fs";
|
|
12400
12415
|
function repoEntryToRepoConfig(entry) {
|
|
12401
12416
|
if (!entry.url) {
|
|
12402
12417
|
throw new Error(`Repo "${entry.name}" has no url. Re-register:
|
|
@@ -12404,7 +12419,7 @@ function repoEntryToRepoConfig(entry) {
|
|
|
12404
12419
|
olam repos add ${entry.name} --path ${entry.path}`);
|
|
12405
12420
|
}
|
|
12406
12421
|
const repoPath = resolveTildePath(entry.path);
|
|
12407
|
-
if (!
|
|
12422
|
+
if (!fs13.existsSync(repoPath)) {
|
|
12408
12423
|
throw new Error(`Repo "${entry.name}" path "${repoPath}" no longer exists. Run: olam repos update ${entry.name} --path <new-path>`);
|
|
12409
12424
|
}
|
|
12410
12425
|
let manifest = null;
|
|
@@ -12435,15 +12450,15 @@ var init_bridge = __esm({
|
|
|
12435
12450
|
});
|
|
12436
12451
|
|
|
12437
12452
|
// ../core/dist/skill-sources/trust-audit-log.js
|
|
12438
|
-
import * as
|
|
12439
|
-
import * as
|
|
12453
|
+
import * as fs14 from "node:fs";
|
|
12454
|
+
import * as path16 from "node:path";
|
|
12440
12455
|
import * as os9 from "node:os";
|
|
12441
12456
|
function skillSourcesAuditLogPath() {
|
|
12442
12457
|
const override = process.env["OLAM_SKILL_SOURCES_AUDIT_LOG_PATH"];
|
|
12443
12458
|
if (override && override.length > 0)
|
|
12444
12459
|
return override;
|
|
12445
|
-
const stateDir = process.env["OLAM_STATE_DIR"] ??
|
|
12446
|
-
return
|
|
12460
|
+
const stateDir = process.env["OLAM_STATE_DIR"] ?? path16.join(os9.homedir(), ".olam", "state");
|
|
12461
|
+
return path16.join(stateDir, SKILL_SOURCES_AUDIT_LOG_FILENAME);
|
|
12447
12462
|
}
|
|
12448
12463
|
function appendTrustAudit(entry) {
|
|
12449
12464
|
const candidate = {
|
|
@@ -12452,20 +12467,20 @@ function appendTrustAudit(entry) {
|
|
|
12452
12467
|
};
|
|
12453
12468
|
const validated = TrustAuditEntrySchema.parse(candidate);
|
|
12454
12469
|
const filePath = skillSourcesAuditLogPath();
|
|
12455
|
-
|
|
12456
|
-
const fd =
|
|
12470
|
+
fs14.mkdirSync(path16.dirname(filePath), { recursive: true, mode: 448 });
|
|
12471
|
+
const fd = fs14.openSync(filePath, "a", 384);
|
|
12457
12472
|
try {
|
|
12458
|
-
|
|
12473
|
+
fs14.writeSync(fd, JSON.stringify(validated) + "\n");
|
|
12459
12474
|
} finally {
|
|
12460
|
-
|
|
12475
|
+
fs14.closeSync(fd);
|
|
12461
12476
|
}
|
|
12462
12477
|
return validated;
|
|
12463
12478
|
}
|
|
12464
12479
|
function readTrustAuditLog() {
|
|
12465
12480
|
const filePath = skillSourcesAuditLogPath();
|
|
12466
|
-
if (!
|
|
12481
|
+
if (!fs14.existsSync(filePath))
|
|
12467
12482
|
return { entries: [], errors: [] };
|
|
12468
|
-
const raw =
|
|
12483
|
+
const raw = fs14.readFileSync(filePath, "utf-8");
|
|
12469
12484
|
const lines = raw.split("\n");
|
|
12470
12485
|
const entries = [];
|
|
12471
12486
|
const errors = [];
|
|
@@ -12666,17 +12681,17 @@ var init_store2 = __esm({
|
|
|
12666
12681
|
|
|
12667
12682
|
// ../core/dist/skill-sources/clone.js
|
|
12668
12683
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
12669
|
-
import * as
|
|
12684
|
+
import * as fs15 from "node:fs";
|
|
12670
12685
|
import * as os10 from "node:os";
|
|
12671
|
-
import * as
|
|
12686
|
+
import * as path17 from "node:path";
|
|
12672
12687
|
function skillSourcesRootDir() {
|
|
12673
12688
|
const override = process.env["OLAM_SKILL_SOURCES_DIR"];
|
|
12674
12689
|
if (override && override.length > 0)
|
|
12675
12690
|
return override;
|
|
12676
|
-
return
|
|
12691
|
+
return path17.join(os10.homedir(), ".olam", "state", "skill-sources");
|
|
12677
12692
|
}
|
|
12678
12693
|
function skillSourceClonePath(id) {
|
|
12679
|
-
return
|
|
12694
|
+
return path17.join(skillSourcesRootDir(), id);
|
|
12680
12695
|
}
|
|
12681
12696
|
function runGit(args, cwd) {
|
|
12682
12697
|
try {
|
|
@@ -12691,15 +12706,15 @@ function runGit(args, cwd) {
|
|
|
12691
12706
|
}
|
|
12692
12707
|
function cloneSkillSource(opts) {
|
|
12693
12708
|
const clonePath = skillSourceClonePath(opts.id);
|
|
12694
|
-
if (
|
|
12709
|
+
if (fs15.existsSync(clonePath)) {
|
|
12695
12710
|
throw new Error(`clone path "${clonePath}" already exists. Remove the existing skill-source first.`);
|
|
12696
12711
|
}
|
|
12697
|
-
|
|
12712
|
+
fs15.mkdirSync(skillSourcesRootDir(), { recursive: true });
|
|
12698
12713
|
try {
|
|
12699
12714
|
runGit(["clone", "--depth", "1", "--branch", opts.branch, opts.gitUrl, clonePath]);
|
|
12700
12715
|
} catch (err) {
|
|
12701
|
-
if (
|
|
12702
|
-
|
|
12716
|
+
if (fs15.existsSync(clonePath)) {
|
|
12717
|
+
fs15.rmSync(clonePath, { recursive: true, force: true });
|
|
12703
12718
|
}
|
|
12704
12719
|
throw new SkillSourceGitError("clone", opts.gitUrl, err);
|
|
12705
12720
|
}
|
|
@@ -12713,7 +12728,7 @@ function cloneSkillSource(opts) {
|
|
|
12713
12728
|
}
|
|
12714
12729
|
function pullSkillSource(opts) {
|
|
12715
12730
|
const clonePath = skillSourceClonePath(opts.id);
|
|
12716
|
-
if (!
|
|
12731
|
+
if (!fs15.existsSync(clonePath)) {
|
|
12717
12732
|
throw new Error(`clone path "${clonePath}" does not exist. Run "olam skills source add" first.`);
|
|
12718
12733
|
}
|
|
12719
12734
|
try {
|
|
@@ -12731,8 +12746,8 @@ function pullSkillSource(opts) {
|
|
|
12731
12746
|
}
|
|
12732
12747
|
function removeSkillSourceClone(id) {
|
|
12733
12748
|
const clonePath = skillSourceClonePath(id);
|
|
12734
|
-
if (
|
|
12735
|
-
|
|
12749
|
+
if (fs15.existsSync(clonePath)) {
|
|
12750
|
+
fs15.rmSync(clonePath, { recursive: true, force: true });
|
|
12736
12751
|
}
|
|
12737
12752
|
}
|
|
12738
12753
|
var SkillSourceGitError;
|
|
@@ -12755,7 +12770,7 @@ var init_clone = __esm({
|
|
|
12755
12770
|
});
|
|
12756
12771
|
|
|
12757
12772
|
// ../core/dist/skill-sources/hook-template.js
|
|
12758
|
-
import * as
|
|
12773
|
+
import * as fs16 from "node:fs";
|
|
12759
12774
|
function buildSkillsHookEntry() {
|
|
12760
12775
|
return {
|
|
12761
12776
|
matcher: "",
|
|
@@ -12814,14 +12829,14 @@ function computeUninstall(settings) {
|
|
|
12814
12829
|
return { status: "removed", settingsAfter: next };
|
|
12815
12830
|
}
|
|
12816
12831
|
function uninstallSkillsHookFromFile(filePath) {
|
|
12817
|
-
if (!
|
|
12832
|
+
if (!fs16.existsSync(filePath)) {
|
|
12818
12833
|
return { status: "no-settings" };
|
|
12819
12834
|
}
|
|
12820
|
-
const raw =
|
|
12835
|
+
const raw = fs16.readFileSync(filePath, "utf-8");
|
|
12821
12836
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
12822
12837
|
const result = computeUninstall(settings);
|
|
12823
12838
|
if (result.status === "removed" && result.settingsAfter) {
|
|
12824
|
-
|
|
12839
|
+
fs16.writeFileSync(filePath, JSON.stringify(result.settingsAfter, null, 2) + "\n");
|
|
12825
12840
|
}
|
|
12826
12841
|
return result;
|
|
12827
12842
|
}
|
|
@@ -12837,8 +12852,8 @@ var init_hook_template = __esm({
|
|
|
12837
12852
|
});
|
|
12838
12853
|
|
|
12839
12854
|
// ../core/dist/world/merge-settings.js
|
|
12840
|
-
import * as
|
|
12841
|
-
import * as
|
|
12855
|
+
import * as fs17 from "node:fs";
|
|
12856
|
+
import * as path18 from "node:path";
|
|
12842
12857
|
import * as crypto4 from "node:crypto";
|
|
12843
12858
|
function mergeHomeSettingsJson(filePath, options) {
|
|
12844
12859
|
let settings;
|
|
@@ -12898,10 +12913,10 @@ function mergeHomeSettingsJson(filePath, options) {
|
|
|
12898
12913
|
return { status: "installed", message: `settings.json updated at ${filePath}` };
|
|
12899
12914
|
}
|
|
12900
12915
|
function readSettings(filePath) {
|
|
12901
|
-
if (!
|
|
12916
|
+
if (!fs17.existsSync(filePath)) {
|
|
12902
12917
|
return {};
|
|
12903
12918
|
}
|
|
12904
|
-
const raw =
|
|
12919
|
+
const raw = fs17.readFileSync(filePath, "utf-8");
|
|
12905
12920
|
if (!raw.trim())
|
|
12906
12921
|
return {};
|
|
12907
12922
|
return JSON.parse(raw);
|
|
@@ -12922,13 +12937,13 @@ function isHookSentinelPresent(matchers, sentinel) {
|
|
|
12922
12937
|
return false;
|
|
12923
12938
|
}
|
|
12924
12939
|
function atomicWriteJson(filePath, data) {
|
|
12925
|
-
const dir =
|
|
12926
|
-
|
|
12940
|
+
const dir = path18.dirname(filePath);
|
|
12941
|
+
fs17.mkdirSync(dir, { recursive: true });
|
|
12927
12942
|
const rand = crypto4.randomBytes(6).toString("hex");
|
|
12928
12943
|
const tmp = `${filePath}.tmp.${process.pid}.${rand}`;
|
|
12929
12944
|
const json = JSON.stringify(data, null, 2) + "\n";
|
|
12930
|
-
|
|
12931
|
-
|
|
12945
|
+
fs17.writeFileSync(tmp, json, { mode: 420 });
|
|
12946
|
+
fs17.renameSync(tmp, filePath);
|
|
12932
12947
|
}
|
|
12933
12948
|
var init_merge_settings = __esm({
|
|
12934
12949
|
"../core/dist/world/merge-settings.js"() {
|
|
@@ -12937,25 +12952,25 @@ var init_merge_settings = __esm({
|
|
|
12937
12952
|
});
|
|
12938
12953
|
|
|
12939
12954
|
// ../core/dist/skill-sources/hook-install.js
|
|
12940
|
-
import * as
|
|
12941
|
-
import * as
|
|
12955
|
+
import * as fs18 from "node:fs";
|
|
12956
|
+
import * as path19 from "node:path";
|
|
12942
12957
|
import * as os11 from "node:os";
|
|
12943
12958
|
function settingsPathFor(scope, cwd) {
|
|
12944
12959
|
if (scope === "user") {
|
|
12945
|
-
return
|
|
12960
|
+
return path19.join(os11.homedir(), ".claude", "settings.json");
|
|
12946
12961
|
}
|
|
12947
|
-
return
|
|
12962
|
+
return path19.join(cwd ?? process.cwd(), ".claude", "settings.json");
|
|
12948
12963
|
}
|
|
12949
12964
|
function backupFile(filePath) {
|
|
12950
|
-
if (!
|
|
12965
|
+
if (!fs18.existsSync(filePath))
|
|
12951
12966
|
return null;
|
|
12952
12967
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
12953
12968
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
12954
|
-
|
|
12969
|
+
fs18.copyFileSync(filePath, backupPath);
|
|
12955
12970
|
return backupPath;
|
|
12956
12971
|
}
|
|
12957
12972
|
function installSkillsHookToFile(filePath) {
|
|
12958
|
-
|
|
12973
|
+
fs18.mkdirSync(path19.dirname(filePath), { recursive: true });
|
|
12959
12974
|
const backupPath = backupFile(filePath);
|
|
12960
12975
|
const result = mergeHomeSettingsJson(filePath, {
|
|
12961
12976
|
ensureHook: {
|
|
@@ -12966,7 +12981,7 @@ function installSkillsHookToFile(filePath) {
|
|
|
12966
12981
|
});
|
|
12967
12982
|
if (result.status === "already-present" && backupPath) {
|
|
12968
12983
|
try {
|
|
12969
|
-
|
|
12984
|
+
fs18.unlinkSync(backupPath);
|
|
12970
12985
|
} catch {
|
|
12971
12986
|
}
|
|
12972
12987
|
return { status: "already-present", filePath, backupPath: null };
|
|
@@ -12974,11 +12989,11 @@ function installSkillsHookToFile(filePath) {
|
|
|
12974
12989
|
return { status: result.status, filePath, backupPath };
|
|
12975
12990
|
}
|
|
12976
12991
|
function isSkillsHookInstalled(filePath) {
|
|
12977
|
-
if (!
|
|
12992
|
+
if (!fs18.existsSync(filePath))
|
|
12978
12993
|
return false;
|
|
12979
12994
|
let parsed;
|
|
12980
12995
|
try {
|
|
12981
|
-
parsed = JSON.parse(
|
|
12996
|
+
parsed = JSON.parse(fs18.readFileSync(filePath, "utf-8"));
|
|
12982
12997
|
} catch {
|
|
12983
12998
|
return false;
|
|
12984
12999
|
}
|
|
@@ -13016,36 +13031,36 @@ var init_hook_install = __esm({
|
|
|
13016
13031
|
});
|
|
13017
13032
|
|
|
13018
13033
|
// ../core/dist/skill-sources/migration-snapshot.js
|
|
13019
|
-
import * as
|
|
13034
|
+
import * as fs19 from "node:fs";
|
|
13020
13035
|
import * as os12 from "node:os";
|
|
13021
|
-
import * as
|
|
13036
|
+
import * as path20 from "node:path";
|
|
13022
13037
|
function claudeDirInternal() {
|
|
13023
13038
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
13024
13039
|
if (override && override.length > 0)
|
|
13025
13040
|
return override;
|
|
13026
|
-
return
|
|
13041
|
+
return path20.join(os12.homedir(), ".claude");
|
|
13027
13042
|
}
|
|
13028
13043
|
function migrationSnapshotsDir() {
|
|
13029
13044
|
const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
|
|
13030
13045
|
if (override && override.length > 0)
|
|
13031
13046
|
return override;
|
|
13032
|
-
return
|
|
13047
|
+
return path20.join(os12.homedir(), ".olam", "state", "migration-snapshots");
|
|
13033
13048
|
}
|
|
13034
13049
|
function listToolboxManagedSymlinks(toolboxPath) {
|
|
13035
13050
|
const claude = claudeDirInternal();
|
|
13036
13051
|
const out = [];
|
|
13037
13052
|
const BUCKETS2 = ["skills", "agents", "scripts", "rules", "commands"];
|
|
13038
13053
|
for (const bucket of BUCKETS2) {
|
|
13039
|
-
const dir =
|
|
13040
|
-
if (!
|
|
13054
|
+
const dir = path20.join(claude, bucket);
|
|
13055
|
+
if (!fs19.existsSync(dir))
|
|
13041
13056
|
continue;
|
|
13042
|
-
for (const name of
|
|
13043
|
-
const link =
|
|
13057
|
+
for (const name of fs19.readdirSync(dir)) {
|
|
13058
|
+
const link = path20.join(dir, name);
|
|
13044
13059
|
try {
|
|
13045
|
-
const
|
|
13046
|
-
if (!
|
|
13060
|
+
const stat2 = fs19.lstatSync(link);
|
|
13061
|
+
if (!stat2.isSymbolicLink())
|
|
13047
13062
|
continue;
|
|
13048
|
-
const target =
|
|
13063
|
+
const target = fs19.readlinkSync(link);
|
|
13049
13064
|
if (target.startsWith(toolboxPath)) {
|
|
13050
13065
|
out.push({ link, target });
|
|
13051
13066
|
}
|
|
@@ -13058,25 +13073,25 @@ function listToolboxManagedSymlinks(toolboxPath) {
|
|
|
13058
13073
|
function detectToolboxState(opts) {
|
|
13059
13074
|
const claude = claudeDirInternal();
|
|
13060
13075
|
const toolboxPath = opts.toolboxPath;
|
|
13061
|
-
const namespace = opts.namespace ??
|
|
13062
|
-
const atlasUserFile =
|
|
13063
|
-
const atlasUser =
|
|
13076
|
+
const namespace = opts.namespace ?? path20.basename(toolboxPath);
|
|
13077
|
+
const atlasUserFile = path20.join(claude, ".atlas-user");
|
|
13078
|
+
const atlasUser = fs19.existsSync(atlasUserFile) ? fs19.readFileSync(atlasUserFile, "utf-8").trim() || void 0 : void 0;
|
|
13064
13079
|
let subscriptionsJson;
|
|
13065
13080
|
if (atlasUser) {
|
|
13066
|
-
const sp =
|
|
13067
|
-
if (
|
|
13081
|
+
const sp = path20.join(toolboxPath, "members", atlasUser, "subscriptions.json");
|
|
13082
|
+
if (fs19.existsSync(sp)) {
|
|
13068
13083
|
try {
|
|
13069
|
-
subscriptionsJson = JSON.parse(
|
|
13084
|
+
subscriptionsJson = JSON.parse(fs19.readFileSync(sp, "utf-8"));
|
|
13070
13085
|
} catch {
|
|
13071
13086
|
}
|
|
13072
13087
|
}
|
|
13073
13088
|
}
|
|
13074
13089
|
const atlasManagedSymlinks = listToolboxManagedSymlinks(toolboxPath);
|
|
13075
13090
|
let originalSessionStartHook;
|
|
13076
|
-
const settingsPath =
|
|
13077
|
-
if (
|
|
13091
|
+
const settingsPath = path20.join(claude, "settings.json");
|
|
13092
|
+
if (fs19.existsSync(settingsPath)) {
|
|
13078
13093
|
try {
|
|
13079
|
-
const settings = JSON.parse(
|
|
13094
|
+
const settings = JSON.parse(fs19.readFileSync(settingsPath, "utf-8"));
|
|
13080
13095
|
const ss = settings?.hooks?.SessionStart;
|
|
13081
13096
|
if (Array.isArray(ss))
|
|
13082
13097
|
originalSessionStartHook = ss;
|
|
@@ -13099,21 +13114,21 @@ function detectToolboxState(opts) {
|
|
|
13099
13114
|
}
|
|
13100
13115
|
function writeMigrationSnapshot(snapshot) {
|
|
13101
13116
|
const dir = migrationSnapshotsDir();
|
|
13102
|
-
|
|
13117
|
+
fs19.mkdirSync(dir, { recursive: true });
|
|
13103
13118
|
const stamp = snapshot.takenAt.replace(/[:.]/g, "-");
|
|
13104
|
-
const file =
|
|
13105
|
-
|
|
13119
|
+
const file = path20.join(dir, `${snapshot.namespace}-${stamp}.json`);
|
|
13120
|
+
fs19.writeFileSync(file, JSON.stringify(snapshot, null, 2) + "\n", { mode: 420 });
|
|
13106
13121
|
return file;
|
|
13107
13122
|
}
|
|
13108
13123
|
function readLatestMigrationSnapshot(opts = {}) {
|
|
13109
13124
|
const dir = migrationSnapshotsDir();
|
|
13110
|
-
if (!
|
|
13125
|
+
if (!fs19.existsSync(dir))
|
|
13111
13126
|
return void 0;
|
|
13112
|
-
const files =
|
|
13127
|
+
const files = fs19.readdirSync(dir).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
13113
13128
|
for (const f of files) {
|
|
13114
|
-
const full =
|
|
13129
|
+
const full = path20.join(dir, f);
|
|
13115
13130
|
try {
|
|
13116
|
-
const snapshot = JSON.parse(
|
|
13131
|
+
const snapshot = JSON.parse(fs19.readFileSync(full, "utf-8"));
|
|
13117
13132
|
if (snapshot.schemaVersion !== MIGRATION_SNAPSHOT_SCHEMA_VERSION)
|
|
13118
13133
|
continue;
|
|
13119
13134
|
if (opts.namespace !== void 0 && snapshot.namespace !== opts.namespace)
|
|
@@ -13126,7 +13141,7 @@ function readLatestMigrationSnapshot(opts = {}) {
|
|
|
13126
13141
|
return void 0;
|
|
13127
13142
|
}
|
|
13128
13143
|
function readMigrationSnapshotFromPath(p) {
|
|
13129
|
-
return JSON.parse(
|
|
13144
|
+
return JSON.parse(fs19.readFileSync(p, "utf-8"));
|
|
13130
13145
|
}
|
|
13131
13146
|
var MIGRATION_SNAPSHOT_SCHEMA_VERSION;
|
|
13132
13147
|
var init_migration_snapshot = __esm({
|
|
@@ -13137,15 +13152,15 @@ var init_migration_snapshot = __esm({
|
|
|
13137
13152
|
});
|
|
13138
13153
|
|
|
13139
13154
|
// ../core/dist/skill-sync/artifact-resolver.js
|
|
13140
|
-
import * as
|
|
13141
|
-
import * as
|
|
13155
|
+
import * as fs20 from "node:fs";
|
|
13156
|
+
import * as path21 from "node:path";
|
|
13142
13157
|
function resolveSubscriptions(opts) {
|
|
13143
13158
|
const { clonePath, atlasUser } = opts;
|
|
13144
13159
|
if (atlasUser) {
|
|
13145
|
-
const subsPath =
|
|
13146
|
-
if (
|
|
13160
|
+
const subsPath = path21.join(clonePath, "members", atlasUser, "subscriptions.json");
|
|
13161
|
+
if (fs20.existsSync(subsPath)) {
|
|
13147
13162
|
try {
|
|
13148
|
-
const parsed = JSON.parse(
|
|
13163
|
+
const parsed = JSON.parse(fs20.readFileSync(subsPath, "utf-8"));
|
|
13149
13164
|
if (Array.isArray(parsed?.categories)) {
|
|
13150
13165
|
return {
|
|
13151
13166
|
categories: parsed.categories.filter((c) => typeof c === "string"),
|
|
@@ -13157,10 +13172,10 @@ function resolveSubscriptions(opts) {
|
|
|
13157
13172
|
}
|
|
13158
13173
|
}
|
|
13159
13174
|
}
|
|
13160
|
-
const catsPath =
|
|
13161
|
-
if (
|
|
13175
|
+
const catsPath = path21.join(clonePath, "shared", "categories.json");
|
|
13176
|
+
if (fs20.existsSync(catsPath)) {
|
|
13162
13177
|
try {
|
|
13163
|
-
const parsed = JSON.parse(
|
|
13178
|
+
const parsed = JSON.parse(fs20.readFileSync(catsPath, "utf-8"));
|
|
13164
13179
|
if (Array.isArray(parsed?.categories)) {
|
|
13165
13180
|
return {
|
|
13166
13181
|
categories: parsed.categories.map((c) => c.id).filter((id) => typeof id === "string"),
|
|
@@ -13171,14 +13186,14 @@ function resolveSubscriptions(opts) {
|
|
|
13171
13186
|
} catch {
|
|
13172
13187
|
}
|
|
13173
13188
|
}
|
|
13174
|
-
const sharedDir =
|
|
13189
|
+
const sharedDir = path21.join(clonePath, "shared");
|
|
13175
13190
|
const cats = [];
|
|
13176
|
-
if (
|
|
13177
|
-
for (const name of
|
|
13178
|
-
const dir =
|
|
13179
|
-
if (!
|
|
13191
|
+
if (fs20.existsSync(sharedDir)) {
|
|
13192
|
+
for (const name of fs20.readdirSync(sharedDir)) {
|
|
13193
|
+
const dir = path21.join(sharedDir, name);
|
|
13194
|
+
if (!fs20.statSync(dir).isDirectory())
|
|
13180
13195
|
continue;
|
|
13181
|
-
if (
|
|
13196
|
+
if (fs20.existsSync(path21.join(dir, "skills")) || fs20.existsSync(path21.join(dir, "agents"))) {
|
|
13182
13197
|
cats.push(name);
|
|
13183
13198
|
}
|
|
13184
13199
|
}
|
|
@@ -13186,29 +13201,29 @@ function resolveSubscriptions(opts) {
|
|
|
13186
13201
|
return { categories: cats, fromSubscriptionsFile: false, atlasUser };
|
|
13187
13202
|
}
|
|
13188
13203
|
function listDirSafe(dir) {
|
|
13189
|
-
if (!
|
|
13204
|
+
if (!fs20.existsSync(dir))
|
|
13190
13205
|
return [];
|
|
13191
|
-
return
|
|
13206
|
+
return fs20.readdirSync(dir);
|
|
13192
13207
|
}
|
|
13193
13208
|
function resolveSkillsDir(opts) {
|
|
13194
13209
|
const { sourceId, baseDir } = opts;
|
|
13195
13210
|
const out = [];
|
|
13196
13211
|
for (const name of listDirSafe(baseDir)) {
|
|
13197
|
-
const subdir =
|
|
13198
|
-
if (!
|
|
13212
|
+
const subdir = path21.join(baseDir, name);
|
|
13213
|
+
if (!fs20.statSync(subdir).isDirectory())
|
|
13199
13214
|
continue;
|
|
13200
|
-
if (!
|
|
13215
|
+
if (!fs20.existsSync(path21.join(subdir, "SKILL.md")))
|
|
13201
13216
|
continue;
|
|
13202
13217
|
out.push({ kind: "skill", sourceId, sourcePath: subdir, deployBasename: name });
|
|
13203
|
-
const subagentsDir =
|
|
13204
|
-
if (
|
|
13218
|
+
const subagentsDir = path21.join(subdir, "references", "agents");
|
|
13219
|
+
if (fs20.existsSync(subagentsDir) && fs20.statSync(subagentsDir).isDirectory()) {
|
|
13205
13220
|
for (const f of listDirSafe(subagentsDir)) {
|
|
13206
13221
|
if (!f.endsWith(".md"))
|
|
13207
13222
|
continue;
|
|
13208
13223
|
out.push({
|
|
13209
13224
|
kind: "subagent",
|
|
13210
13225
|
sourceId,
|
|
13211
|
-
sourcePath:
|
|
13226
|
+
sourcePath: path21.join(subagentsDir, f),
|
|
13212
13227
|
deployBasename: f,
|
|
13213
13228
|
parentSkill: name
|
|
13214
13229
|
});
|
|
@@ -13221,18 +13236,18 @@ function resolveAgentsDir(opts) {
|
|
|
13221
13236
|
const { sourceId, baseDir } = opts;
|
|
13222
13237
|
const out = [];
|
|
13223
13238
|
for (const name of listDirSafe(baseDir)) {
|
|
13224
|
-
const full =
|
|
13225
|
-
const
|
|
13226
|
-
if (
|
|
13239
|
+
const full = path21.join(baseDir, name);
|
|
13240
|
+
const stat2 = fs20.statSync(full);
|
|
13241
|
+
if (stat2.isFile() && name.endsWith(".md")) {
|
|
13227
13242
|
out.push({ kind: "agent", sourceId, sourcePath: full, deployBasename: name });
|
|
13228
|
-
} else if (
|
|
13243
|
+
} else if (stat2.isDirectory()) {
|
|
13229
13244
|
for (const f of listDirSafe(full)) {
|
|
13230
13245
|
if (!f.endsWith(".md"))
|
|
13231
13246
|
continue;
|
|
13232
13247
|
out.push({
|
|
13233
13248
|
kind: "agent",
|
|
13234
13249
|
sourceId,
|
|
13235
|
-
sourcePath:
|
|
13250
|
+
sourcePath: path21.join(full, f),
|
|
13236
13251
|
deployBasename: `${name}-${f}`
|
|
13237
13252
|
});
|
|
13238
13253
|
}
|
|
@@ -13244,11 +13259,11 @@ function resolveScriptsDir(opts) {
|
|
|
13244
13259
|
const { sourceId, baseDir } = opts;
|
|
13245
13260
|
const out = [];
|
|
13246
13261
|
for (const name of listDirSafe(baseDir)) {
|
|
13247
|
-
const full =
|
|
13248
|
-
const
|
|
13249
|
-
if (
|
|
13262
|
+
const full = path21.join(baseDir, name);
|
|
13263
|
+
const stat2 = fs20.statSync(full);
|
|
13264
|
+
if (stat2.isFile() && name.endsWith(".sh")) {
|
|
13250
13265
|
out.push({ kind: "script", sourceId, sourcePath: full, deployBasename: name });
|
|
13251
|
-
} else if (
|
|
13266
|
+
} else if (stat2.isDirectory()) {
|
|
13252
13267
|
out.push({ kind: "script", sourceId, sourcePath: full, deployBasename: name });
|
|
13253
13268
|
}
|
|
13254
13269
|
}
|
|
@@ -13260,8 +13275,8 @@ function resolveRulesDir(opts) {
|
|
|
13260
13275
|
for (const name of listDirSafe(baseDir)) {
|
|
13261
13276
|
if (!name.endsWith(".md"))
|
|
13262
13277
|
continue;
|
|
13263
|
-
const full =
|
|
13264
|
-
if (!
|
|
13278
|
+
const full = path21.join(baseDir, name);
|
|
13279
|
+
if (!fs20.statSync(full).isFile())
|
|
13265
13280
|
continue;
|
|
13266
13281
|
out.push({ kind: "rule", sourceId, sourcePath: full, deployBasename: name });
|
|
13267
13282
|
}
|
|
@@ -13273,8 +13288,8 @@ function resolveJsonDir(opts) {
|
|
|
13273
13288
|
for (const name of listDirSafe(baseDir)) {
|
|
13274
13289
|
if (!name.endsWith(".json"))
|
|
13275
13290
|
continue;
|
|
13276
|
-
const full =
|
|
13277
|
-
if (!
|
|
13291
|
+
const full = path21.join(baseDir, name);
|
|
13292
|
+
if (!fs20.statSync(full).isFile())
|
|
13278
13293
|
continue;
|
|
13279
13294
|
out.push({ kind, sourceId, sourcePath: full, deployBasename: name });
|
|
13280
13295
|
}
|
|
@@ -13286,8 +13301,8 @@ function resolveOverlaysDir(opts) {
|
|
|
13286
13301
|
for (const name of listDirSafe(baseDir)) {
|
|
13287
13302
|
if (!name.endsWith(".md"))
|
|
13288
13303
|
continue;
|
|
13289
|
-
const full =
|
|
13290
|
-
if (!
|
|
13304
|
+
const full = path21.join(baseDir, name);
|
|
13305
|
+
if (!fs20.statSync(full).isFile())
|
|
13291
13306
|
continue;
|
|
13292
13307
|
const deployBasename = name.replace(/\.md$/, "");
|
|
13293
13308
|
out.push({
|
|
@@ -13305,33 +13320,33 @@ function resolveSourceArtifacts(opts) {
|
|
|
13305
13320
|
const subscription = resolveSubscriptions({ clonePath, atlasUser });
|
|
13306
13321
|
const artifacts = [];
|
|
13307
13322
|
for (const cat of subscription.categories) {
|
|
13308
|
-
const catDir =
|
|
13309
|
-
if (!
|
|
13323
|
+
const catDir = path21.join(clonePath, "shared", cat);
|
|
13324
|
+
if (!fs20.existsSync(catDir))
|
|
13310
13325
|
continue;
|
|
13311
|
-
artifacts.push(...resolveSkillsDir({ sourceId, baseDir:
|
|
13312
|
-
artifacts.push(...resolveAgentsDir({ sourceId, baseDir:
|
|
13313
|
-
artifacts.push(...resolveScriptsDir({ sourceId, baseDir:
|
|
13314
|
-
artifacts.push(...resolveRulesDir({ sourceId, baseDir:
|
|
13315
|
-
artifacts.push(...resolveJsonDir({ sourceId, baseDir:
|
|
13316
|
-
artifacts.push(...resolveJsonDir({ sourceId, baseDir:
|
|
13326
|
+
artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path21.join(catDir, "skills") }));
|
|
13327
|
+
artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path21.join(catDir, "agents") }));
|
|
13328
|
+
artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path21.join(catDir, "scripts") }));
|
|
13329
|
+
artifacts.push(...resolveRulesDir({ sourceId, baseDir: path21.join(catDir, "rules") }));
|
|
13330
|
+
artifacts.push(...resolveJsonDir({ sourceId, baseDir: path21.join(catDir, "hooks"), kind: "hook" }));
|
|
13331
|
+
artifacts.push(...resolveJsonDir({ sourceId, baseDir: path21.join(catDir, "permissions"), kind: "permission" }));
|
|
13317
13332
|
}
|
|
13318
13333
|
if (atlasUser) {
|
|
13319
|
-
const memberRoot =
|
|
13320
|
-
if (
|
|
13321
|
-
artifacts.push(...resolveSkillsDir({ sourceId, baseDir:
|
|
13322
|
-
artifacts.push(...resolveAgentsDir({ sourceId, baseDir:
|
|
13323
|
-
artifacts.push(...resolveScriptsDir({ sourceId, baseDir:
|
|
13324
|
-
artifacts.push(...resolveRulesDir({ sourceId, baseDir:
|
|
13325
|
-
artifacts.push(...resolveJsonDir({ sourceId, baseDir:
|
|
13326
|
-
artifacts.push(...resolveJsonDir({ sourceId, baseDir:
|
|
13334
|
+
const memberRoot = path21.join(clonePath, "members", atlasUser);
|
|
13335
|
+
if (fs20.existsSync(memberRoot)) {
|
|
13336
|
+
artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path21.join(memberRoot, "skills") }));
|
|
13337
|
+
artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path21.join(memberRoot, "agents") }));
|
|
13338
|
+
artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path21.join(memberRoot, "scripts") }));
|
|
13339
|
+
artifacts.push(...resolveRulesDir({ sourceId, baseDir: path21.join(memberRoot, "rules") }));
|
|
13340
|
+
artifacts.push(...resolveJsonDir({ sourceId, baseDir: path21.join(memberRoot, "hooks"), kind: "hook" }));
|
|
13341
|
+
artifacts.push(...resolveJsonDir({ sourceId, baseDir: path21.join(memberRoot, "permissions"), kind: "permission" }));
|
|
13327
13342
|
artifacts.push(...resolveOverlaysDir({
|
|
13328
13343
|
sourceId,
|
|
13329
|
-
baseDir:
|
|
13344
|
+
baseDir: path21.join(memberRoot, "skills.overrides"),
|
|
13330
13345
|
targetKind: "skill"
|
|
13331
13346
|
}));
|
|
13332
13347
|
artifacts.push(...resolveOverlaysDir({
|
|
13333
13348
|
sourceId,
|
|
13334
|
-
baseDir:
|
|
13349
|
+
baseDir: path21.join(memberRoot, "agents.overrides"),
|
|
13335
13350
|
targetKind: "agent"
|
|
13336
13351
|
}));
|
|
13337
13352
|
}
|
|
@@ -13396,14 +13411,14 @@ var init_shim_targets = __esm({
|
|
|
13396
13411
|
});
|
|
13397
13412
|
|
|
13398
13413
|
// ../core/dist/skill-sync/symlink-deployer.js
|
|
13399
|
-
import * as
|
|
13414
|
+
import * as fs21 from "node:fs";
|
|
13400
13415
|
import * as os13 from "node:os";
|
|
13401
|
-
import * as
|
|
13416
|
+
import * as path22 from "node:path";
|
|
13402
13417
|
function claudeDir() {
|
|
13403
13418
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
13404
13419
|
if (override && override.length > 0)
|
|
13405
13420
|
return override;
|
|
13406
|
-
return
|
|
13421
|
+
return path22.join(os13.homedir(), ".claude");
|
|
13407
13422
|
}
|
|
13408
13423
|
function bucketFor(kind) {
|
|
13409
13424
|
switch (kind) {
|
|
@@ -13463,16 +13478,16 @@ function detectCollisions(artifacts) {
|
|
|
13463
13478
|
function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, expectedAgentWinnerNames) {
|
|
13464
13479
|
const shadowBackups = [];
|
|
13465
13480
|
for (const bucket of BUCKETS) {
|
|
13466
|
-
const dir =
|
|
13467
|
-
if (!
|
|
13481
|
+
const dir = path22.join(claude, bucket);
|
|
13482
|
+
if (!fs21.existsSync(dir))
|
|
13468
13483
|
continue;
|
|
13469
|
-
for (const name of
|
|
13484
|
+
for (const name of fs21.readdirSync(dir)) {
|
|
13470
13485
|
if (name === ".olam-merged")
|
|
13471
13486
|
continue;
|
|
13472
|
-
const p =
|
|
13487
|
+
const p = path22.join(dir, name);
|
|
13473
13488
|
try {
|
|
13474
|
-
const
|
|
13475
|
-
if (
|
|
13489
|
+
const stat2 = fs21.lstatSync(p);
|
|
13490
|
+
if (stat2.isSymbolicLink()) {
|
|
13476
13491
|
if (bucket === "scripts" && overlayReferences !== void 0) {
|
|
13477
13492
|
const refs = overlayReferences.get(name);
|
|
13478
13493
|
if (refs !== void 0 && refs.length > 0 && checkShimRemoval(name, "0.0.0") !== null) {
|
|
@@ -13492,8 +13507,8 @@ function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, e
|
|
|
13492
13507
|
`);
|
|
13493
13508
|
}
|
|
13494
13509
|
}
|
|
13495
|
-
|
|
13496
|
-
} else if (bucket === "agents" &&
|
|
13510
|
+
fs21.unlinkSync(p);
|
|
13511
|
+
} else if (bucket === "agents" && stat2.isFile() && !name.includes(".shadow-backup-")) {
|
|
13497
13512
|
const hasWinner = expectedAgentWinnerNames !== void 0 ? expectedAgentWinnerNames.has(name) : true;
|
|
13498
13513
|
if (hasWinner) {
|
|
13499
13514
|
const backup = shadowBackup(p);
|
|
@@ -13509,34 +13524,34 @@ function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, e
|
|
|
13509
13524
|
function shadowBackup(link) {
|
|
13510
13525
|
const epoch = Math.floor(Date.now() / 1e3);
|
|
13511
13526
|
const backup = `${link}.shadow-backup-${epoch}`;
|
|
13512
|
-
|
|
13527
|
+
fs21.renameSync(link, backup);
|
|
13513
13528
|
return backup;
|
|
13514
13529
|
}
|
|
13515
13530
|
function linkIfNeeded(target, link) {
|
|
13516
13531
|
try {
|
|
13517
|
-
const existing =
|
|
13532
|
+
const existing = fs21.readlinkSync(link);
|
|
13518
13533
|
if (existing === target)
|
|
13519
13534
|
return { created: false };
|
|
13520
13535
|
} catch {
|
|
13521
13536
|
}
|
|
13522
13537
|
let isLink = false;
|
|
13523
13538
|
try {
|
|
13524
|
-
isLink =
|
|
13539
|
+
isLink = fs21.lstatSync(link).isSymbolicLink();
|
|
13525
13540
|
} catch {
|
|
13526
13541
|
}
|
|
13527
13542
|
let backup;
|
|
13528
13543
|
if (isLink) {
|
|
13529
|
-
|
|
13530
|
-
} else if (
|
|
13544
|
+
fs21.unlinkSync(link);
|
|
13545
|
+
} else if (fs21.existsSync(link)) {
|
|
13531
13546
|
backup = shadowBackup(link);
|
|
13532
13547
|
}
|
|
13533
|
-
|
|
13548
|
+
fs21.symlinkSync(target, link);
|
|
13534
13549
|
return { created: true, shadowBackup: backup };
|
|
13535
13550
|
}
|
|
13536
13551
|
function deployArtifacts(artifacts, opts) {
|
|
13537
13552
|
const claude = claudeDir();
|
|
13538
13553
|
for (const bucket of BUCKETS) {
|
|
13539
|
-
|
|
13554
|
+
fs21.mkdirSync(path22.join(claude, bucket), { recursive: true });
|
|
13540
13555
|
}
|
|
13541
13556
|
const { winners, collisions } = detectCollisions(artifacts);
|
|
13542
13557
|
const expectedAgentWinnerNames = new Set(winners.filter((a) => a.kind === "agent").map((a) => a.deployBasename));
|
|
@@ -13546,11 +13561,11 @@ function deployArtifacts(artifacts, opts) {
|
|
|
13546
13561
|
const bucket = bucketFor(artifact.kind);
|
|
13547
13562
|
if (!bucket)
|
|
13548
13563
|
continue;
|
|
13549
|
-
const linkPath =
|
|
13564
|
+
const linkPath = path22.join(claude, bucket, artifact.deployBasename);
|
|
13550
13565
|
if (artifact.kind === "agent" && artifact.resolvedContent !== void 0) {
|
|
13551
13566
|
const tmpPath = `${linkPath}.tmp-${process.pid}-${Date.now()}`;
|
|
13552
|
-
|
|
13553
|
-
|
|
13567
|
+
fs21.writeFileSync(tmpPath, artifact.resolvedContent);
|
|
13568
|
+
fs21.renameSync(tmpPath, linkPath);
|
|
13554
13569
|
result.linked += 1;
|
|
13555
13570
|
continue;
|
|
13556
13571
|
}
|
|
@@ -13572,7 +13587,7 @@ var init_symlink_deployer = __esm({
|
|
|
13572
13587
|
});
|
|
13573
13588
|
|
|
13574
13589
|
// ../core/dist/meta-hooks/memory-recall.js
|
|
13575
|
-
import * as
|
|
13590
|
+
import * as fs22 from "node:fs";
|
|
13576
13591
|
function buildMemoryRecallHookEntry() {
|
|
13577
13592
|
return {
|
|
13578
13593
|
matcher: OLAM_META_MEMORY_RECALL_MATCHER,
|
|
@@ -13647,7 +13662,7 @@ var init_memory_recall = __esm({
|
|
|
13647
13662
|
});
|
|
13648
13663
|
|
|
13649
13664
|
// ../core/dist/meta-hooks/memory-classify.js
|
|
13650
|
-
import * as
|
|
13665
|
+
import * as fs23 from "node:fs";
|
|
13651
13666
|
function buildMemoryClassifyHookEntry() {
|
|
13652
13667
|
return {
|
|
13653
13668
|
matcher: OLAM_META_MEMORY_CLASSIFY_MATCHER,
|
|
@@ -13731,26 +13746,26 @@ var init_meta_hooks = __esm({
|
|
|
13731
13746
|
});
|
|
13732
13747
|
|
|
13733
13748
|
// ../core/dist/skill-sync/settings-merger.js
|
|
13734
|
-
import * as
|
|
13749
|
+
import * as fs24 from "node:fs";
|
|
13735
13750
|
import * as os14 from "node:os";
|
|
13736
|
-
import * as
|
|
13751
|
+
import * as path23 from "node:path";
|
|
13737
13752
|
function claudeSettingsPath() {
|
|
13738
13753
|
const override = process.env["OLAM_CLAUDE_SETTINGS_PATH"];
|
|
13739
13754
|
if (override && override.length > 0)
|
|
13740
13755
|
return override;
|
|
13741
|
-
return
|
|
13756
|
+
return path23.join(claudeDirInternal2(), "settings.json");
|
|
13742
13757
|
}
|
|
13743
13758
|
function claudeDirInternal2() {
|
|
13744
13759
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
13745
13760
|
if (override && override.length > 0)
|
|
13746
13761
|
return override;
|
|
13747
|
-
return
|
|
13762
|
+
return path23.join(os14.homedir(), ".claude");
|
|
13748
13763
|
}
|
|
13749
13764
|
function settingsBackupDir() {
|
|
13750
13765
|
const override = process.env["OLAM_SETTINGS_BACKUP_DIR"];
|
|
13751
13766
|
if (override && override.length > 0)
|
|
13752
13767
|
return override;
|
|
13753
|
-
return
|
|
13768
|
+
return path23.join(os14.homedir(), ".olam", "state", "settings-backups");
|
|
13754
13769
|
}
|
|
13755
13770
|
function dedupeByMatcher(entries) {
|
|
13756
13771
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -13797,28 +13812,28 @@ function tagOlam(entry) {
|
|
|
13797
13812
|
return { ...entry, [OLAM_SKILLS_MARKER]: true };
|
|
13798
13813
|
}
|
|
13799
13814
|
function readJson(file) {
|
|
13800
|
-
return JSON.parse(
|
|
13815
|
+
return JSON.parse(fs24.readFileSync(file, "utf-8"));
|
|
13801
13816
|
}
|
|
13802
13817
|
function rotateBackups(backupDir) {
|
|
13803
|
-
if (!
|
|
13818
|
+
if (!fs24.existsSync(backupDir))
|
|
13804
13819
|
return;
|
|
13805
|
-
const files =
|
|
13820
|
+
const files = fs24.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path23.join(backupDir, f), mtime: fs24.statSync(path23.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
13806
13821
|
for (const f of files.slice(BACKUP_RETENTION)) {
|
|
13807
13822
|
try {
|
|
13808
|
-
|
|
13823
|
+
fs24.unlinkSync(f.full);
|
|
13809
13824
|
} catch {
|
|
13810
13825
|
}
|
|
13811
13826
|
}
|
|
13812
13827
|
}
|
|
13813
13828
|
function backupSettings() {
|
|
13814
13829
|
const src = claudeSettingsPath();
|
|
13815
|
-
if (!
|
|
13830
|
+
if (!fs24.existsSync(src))
|
|
13816
13831
|
return void 0;
|
|
13817
13832
|
const dir = settingsBackupDir();
|
|
13818
|
-
|
|
13833
|
+
fs24.mkdirSync(dir, { recursive: true });
|
|
13819
13834
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
13820
|
-
const dest =
|
|
13821
|
-
|
|
13835
|
+
const dest = path23.join(dir, `settings-${stamp}.json`);
|
|
13836
|
+
fs24.copyFileSync(src, dest);
|
|
13822
13837
|
rotateBackups(dir);
|
|
13823
13838
|
return dest;
|
|
13824
13839
|
}
|
|
@@ -13826,7 +13841,7 @@ function mergeSettings(input) {
|
|
|
13826
13841
|
const settingsPath = claudeSettingsPath();
|
|
13827
13842
|
const backupPath = backupSettings();
|
|
13828
13843
|
let base = {};
|
|
13829
|
-
if (
|
|
13844
|
+
if (fs24.existsSync(settingsPath)) {
|
|
13830
13845
|
try {
|
|
13831
13846
|
base = readJson(settingsPath);
|
|
13832
13847
|
} catch {
|
|
@@ -13894,10 +13909,10 @@ function mergeSettings(input) {
|
|
|
13894
13909
|
...input.permissionFiles.length > 0 ? { allow: [...permSet] } : {}
|
|
13895
13910
|
}
|
|
13896
13911
|
};
|
|
13897
|
-
|
|
13912
|
+
fs24.mkdirSync(path23.dirname(settingsPath), { recursive: true });
|
|
13898
13913
|
const tmp = `${settingsPath}.tmp-${process.pid}`;
|
|
13899
|
-
|
|
13900
|
-
|
|
13914
|
+
fs24.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
|
|
13915
|
+
fs24.renameSync(tmp, settingsPath);
|
|
13901
13916
|
return { backupPath, hooksAdded, permissionsCount: permSet.size, dualWriteDeduped, dualWriteDroppedCommands };
|
|
13902
13917
|
}
|
|
13903
13918
|
var OLAM_SKILLS_MARKER, BACKUP_RETENTION, DUAL_WRITE_DEDUP_RULES;
|
|
@@ -13954,16 +13969,16 @@ var init_schema5 = __esm({
|
|
|
13954
13969
|
|
|
13955
13970
|
// ../core/dist/skill-sync/per-project-override.js
|
|
13956
13971
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
13957
|
-
import * as
|
|
13958
|
-
import * as
|
|
13972
|
+
import * as fs25 from "node:fs";
|
|
13973
|
+
import * as path24 from "node:path";
|
|
13959
13974
|
import { parse as parseYaml3 } from "yaml";
|
|
13960
13975
|
function findProjectOverride(startDir) {
|
|
13961
|
-
let dir =
|
|
13962
|
-
const root =
|
|
13976
|
+
let dir = path24.resolve(startDir);
|
|
13977
|
+
const root = path24.parse(dir).root;
|
|
13963
13978
|
while (true) {
|
|
13964
|
-
const candidate =
|
|
13965
|
-
if (
|
|
13966
|
-
const raw =
|
|
13979
|
+
const candidate = path24.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
|
|
13980
|
+
if (fs25.existsSync(candidate) && fs25.statSync(candidate).isFile()) {
|
|
13981
|
+
const raw = fs25.readFileSync(candidate, "utf-8");
|
|
13967
13982
|
let parsed;
|
|
13968
13983
|
try {
|
|
13969
13984
|
parsed = parseYaml3(raw);
|
|
@@ -13976,7 +13991,7 @@ function findProjectOverride(startDir) {
|
|
|
13976
13991
|
}
|
|
13977
13992
|
if (dir === root)
|
|
13978
13993
|
return void 0;
|
|
13979
|
-
dir =
|
|
13994
|
+
dir = path24.dirname(dir);
|
|
13980
13995
|
}
|
|
13981
13996
|
}
|
|
13982
13997
|
function applyOverrideToArtifacts(artifacts, override) {
|
|
@@ -14017,14 +14032,14 @@ var init_per_project_override = __esm({
|
|
|
14017
14032
|
"../core/dist/skill-sync/per-project-override.js"() {
|
|
14018
14033
|
"use strict";
|
|
14019
14034
|
init_schema5();
|
|
14020
|
-
PROJECT_OVERRIDE_RELATIVE_PATH =
|
|
14035
|
+
PROJECT_OVERRIDE_RELATIVE_PATH = path24.join(".olam", "skill-overrides.yaml");
|
|
14021
14036
|
}
|
|
14022
14037
|
});
|
|
14023
14038
|
|
|
14024
14039
|
// ../core/dist/lib/file-lock.js
|
|
14025
|
-
import * as
|
|
14040
|
+
import * as fs26 from "node:fs";
|
|
14026
14041
|
import * as os15 from "node:os";
|
|
14027
|
-
import * as
|
|
14042
|
+
import * as path25 from "node:path";
|
|
14028
14043
|
function defaultIsPidAlive(pid) {
|
|
14029
14044
|
try {
|
|
14030
14045
|
process.kill(pid, 0);
|
|
@@ -14035,11 +14050,11 @@ function defaultIsPidAlive(pid) {
|
|
|
14035
14050
|
}
|
|
14036
14051
|
}
|
|
14037
14052
|
function sleep3(ms) {
|
|
14038
|
-
return new Promise((
|
|
14053
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
14039
14054
|
}
|
|
14040
14055
|
function readLockMeta(lockPath) {
|
|
14041
14056
|
try {
|
|
14042
|
-
const raw =
|
|
14057
|
+
const raw = fs26.readFileSync(lockPath, "utf-8");
|
|
14043
14058
|
const parsed = JSON.parse(raw);
|
|
14044
14059
|
if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
|
|
14045
14060
|
return parsed;
|
|
@@ -14058,12 +14073,12 @@ function isLockStale(meta2, opts) {
|
|
|
14058
14073
|
}
|
|
14059
14074
|
function tryAcquireOnce(lockPath, meta2, opts) {
|
|
14060
14075
|
try {
|
|
14061
|
-
|
|
14062
|
-
const fd =
|
|
14076
|
+
fs26.mkdirSync(path25.dirname(lockPath), { recursive: true });
|
|
14077
|
+
const fd = fs26.openSync(lockPath, "wx", 384);
|
|
14063
14078
|
try {
|
|
14064
|
-
|
|
14079
|
+
fs26.writeSync(fd, JSON.stringify(meta2));
|
|
14065
14080
|
} finally {
|
|
14066
|
-
|
|
14081
|
+
fs26.closeSync(fd);
|
|
14067
14082
|
}
|
|
14068
14083
|
return true;
|
|
14069
14084
|
} catch (err) {
|
|
@@ -14073,14 +14088,14 @@ function tryAcquireOnce(lockPath, meta2, opts) {
|
|
|
14073
14088
|
const existing = readLockMeta(lockPath);
|
|
14074
14089
|
if (existing === void 0) {
|
|
14075
14090
|
try {
|
|
14076
|
-
|
|
14091
|
+
fs26.unlinkSync(lockPath);
|
|
14077
14092
|
} catch {
|
|
14078
14093
|
}
|
|
14079
14094
|
return tryAcquireOnce(lockPath, meta2, opts);
|
|
14080
14095
|
}
|
|
14081
14096
|
if (isLockStale(existing, opts)) {
|
|
14082
14097
|
try {
|
|
14083
|
-
|
|
14098
|
+
fs26.unlinkSync(lockPath);
|
|
14084
14099
|
} catch {
|
|
14085
14100
|
}
|
|
14086
14101
|
return tryAcquireOnce(lockPath, meta2, opts);
|
|
@@ -14090,7 +14105,7 @@ function tryAcquireOnce(lockPath, meta2, opts) {
|
|
|
14090
14105
|
}
|
|
14091
14106
|
async function acquireFileLock(lockDir, options = {}) {
|
|
14092
14107
|
const lockFilename = options.lockFilename ?? DEFAULT_LOCK_FILENAME;
|
|
14093
|
-
const lockPath =
|
|
14108
|
+
const lockPath = path25.join(lockDir, lockFilename);
|
|
14094
14109
|
const acquireTimeoutMs = options.acquireTimeoutMs ?? DEFAULT_ACQUIRE_TIMEOUT_MS;
|
|
14095
14110
|
const staleLockMs = options.staleLockMs ?? DEFAULT_STALE_LOCK_MS;
|
|
14096
14111
|
const now = options.now ?? Date.now;
|
|
@@ -14110,7 +14125,7 @@ async function acquireFileLock(lockDir, options = {}) {
|
|
|
14110
14125
|
lockPath,
|
|
14111
14126
|
release: () => {
|
|
14112
14127
|
try {
|
|
14113
|
-
|
|
14128
|
+
fs26.unlinkSync(lockPath);
|
|
14114
14129
|
} catch {
|
|
14115
14130
|
}
|
|
14116
14131
|
}
|
|
@@ -14214,11 +14229,11 @@ var init_min_version_filter = __esm({
|
|
|
14214
14229
|
});
|
|
14215
14230
|
|
|
14216
14231
|
// ../core/dist/skill-sync/overlay-scan.js
|
|
14217
|
-
import * as
|
|
14218
|
-
import * as
|
|
14232
|
+
import * as fs27 from "node:fs";
|
|
14233
|
+
import * as path26 from "node:path";
|
|
14219
14234
|
function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
14220
14235
|
const result = /* @__PURE__ */ new Map();
|
|
14221
|
-
if (!
|
|
14236
|
+
if (!fs27.existsSync(overlayRoot)) {
|
|
14222
14237
|
return result;
|
|
14223
14238
|
}
|
|
14224
14239
|
if (basenames.length === 0) {
|
|
@@ -14227,13 +14242,13 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
14227
14242
|
const mdFiles = [];
|
|
14228
14243
|
let overlayRootReal;
|
|
14229
14244
|
try {
|
|
14230
|
-
overlayRootReal =
|
|
14245
|
+
overlayRootReal = fs27.realpathSync(overlayRoot);
|
|
14231
14246
|
} catch {
|
|
14232
14247
|
return result;
|
|
14233
14248
|
}
|
|
14234
14249
|
for (const subdir of OVERRIDE_SUBDIRS) {
|
|
14235
|
-
const dir =
|
|
14236
|
-
if (!
|
|
14250
|
+
const dir = path26.join(overlayRoot, subdir);
|
|
14251
|
+
if (!fs27.existsSync(dir))
|
|
14237
14252
|
continue;
|
|
14238
14253
|
walkMarkdown(dir, mdFiles, caps.maxFiles);
|
|
14239
14254
|
}
|
|
@@ -14241,25 +14256,25 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
14241
14256
|
for (const filepath of mdFiles) {
|
|
14242
14257
|
let realFile;
|
|
14243
14258
|
try {
|
|
14244
|
-
realFile =
|
|
14259
|
+
realFile = fs27.realpathSync(filepath);
|
|
14245
14260
|
} catch (err) {
|
|
14246
14261
|
const code = err.code;
|
|
14247
14262
|
if (code === "ENOENT" || code === "EACCES")
|
|
14248
14263
|
continue;
|
|
14249
14264
|
throw err;
|
|
14250
14265
|
}
|
|
14251
|
-
const rel =
|
|
14252
|
-
if (rel.startsWith("..") ||
|
|
14266
|
+
const rel = path26.relative(overlayRootReal, realFile);
|
|
14267
|
+
if (rel.startsWith("..") || path26.isAbsolute(rel)) {
|
|
14253
14268
|
continue;
|
|
14254
14269
|
}
|
|
14255
14270
|
let content;
|
|
14256
14271
|
try {
|
|
14257
|
-
const
|
|
14258
|
-
totalBytes +=
|
|
14272
|
+
const stat2 = fs27.statSync(filepath);
|
|
14273
|
+
totalBytes += stat2.size;
|
|
14259
14274
|
if (totalBytes > caps.maxTotalBytes) {
|
|
14260
14275
|
throw new Error(`[overlay-scan] aborted: overlay tree exceeds ${caps.maxTotalBytes} total bytes. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
|
|
14261
14276
|
}
|
|
14262
|
-
content =
|
|
14277
|
+
content = fs27.readFileSync(filepath, "utf8");
|
|
14263
14278
|
} catch (err) {
|
|
14264
14279
|
const code = err.code;
|
|
14265
14280
|
if (code === "ENOENT" || code === "EACCES") {
|
|
@@ -14267,7 +14282,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
14267
14282
|
}
|
|
14268
14283
|
throw err;
|
|
14269
14284
|
}
|
|
14270
|
-
const relpath =
|
|
14285
|
+
const relpath = path26.relative(overlayRoot, filepath).split(path26.sep).join("/");
|
|
14271
14286
|
for (const basename6 of basenames) {
|
|
14272
14287
|
if (content.includes(basename6)) {
|
|
14273
14288
|
const list = result.get(basename6) ?? [];
|
|
@@ -14281,7 +14296,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
14281
14296
|
function walkMarkdown(dir, out, cap) {
|
|
14282
14297
|
let entries;
|
|
14283
14298
|
try {
|
|
14284
|
-
entries =
|
|
14299
|
+
entries = fs27.readdirSync(dir, { withFileTypes: true });
|
|
14285
14300
|
} catch (err) {
|
|
14286
14301
|
if (err.code === "ENOENT")
|
|
14287
14302
|
return;
|
|
@@ -14291,7 +14306,7 @@ function walkMarkdown(dir, out, cap) {
|
|
|
14291
14306
|
if (out.length >= cap) {
|
|
14292
14307
|
throw new Error(`[overlay-scan] aborted: overlay tree contains > ${cap} markdown files. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
|
|
14293
14308
|
}
|
|
14294
|
-
const full =
|
|
14309
|
+
const full = path26.join(dir, entry.name);
|
|
14295
14310
|
if (entry.isSymbolicLink())
|
|
14296
14311
|
continue;
|
|
14297
14312
|
if (entry.isDirectory()) {
|
|
@@ -14316,12 +14331,12 @@ var init_overlay_scan = __esm({
|
|
|
14316
14331
|
});
|
|
14317
14332
|
|
|
14318
14333
|
// ../core/dist/skill-sync/settings-json-lock.js
|
|
14319
|
-
import * as
|
|
14334
|
+
import * as fs28 from "node:fs";
|
|
14320
14335
|
import * as os16 from "node:os";
|
|
14321
|
-
import * as
|
|
14336
|
+
import * as path27 from "node:path";
|
|
14322
14337
|
function defaultSettingsJsonLockPath() {
|
|
14323
|
-
const stateDir = process.env["OLAM_STATE_DIR"] ??
|
|
14324
|
-
return
|
|
14338
|
+
const stateDir = process.env["OLAM_STATE_DIR"] ?? path27.join(os16.homedir(), ".olam", "state");
|
|
14339
|
+
return path27.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
|
|
14325
14340
|
}
|
|
14326
14341
|
function defaultIsPidAlive2(pid) {
|
|
14327
14342
|
try {
|
|
@@ -14333,11 +14348,11 @@ function defaultIsPidAlive2(pid) {
|
|
|
14333
14348
|
}
|
|
14334
14349
|
}
|
|
14335
14350
|
function sleep4(ms) {
|
|
14336
|
-
return new Promise((
|
|
14351
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
14337
14352
|
}
|
|
14338
14353
|
function readLockMeta2(lockPath) {
|
|
14339
14354
|
try {
|
|
14340
|
-
const raw =
|
|
14355
|
+
const raw = fs28.readFileSync(lockPath, "utf-8");
|
|
14341
14356
|
const parsed = JSON.parse(raw);
|
|
14342
14357
|
if (typeof parsed?.pid === "number" && typeof parsed?.hostname === "string" && typeof parsed?.timestamp === "number") {
|
|
14343
14358
|
return parsed;
|
|
@@ -14360,12 +14375,12 @@ function isLockStale2(meta2, opts) {
|
|
|
14360
14375
|
function tryAcquireOnce2(lockPath, meta2, opts) {
|
|
14361
14376
|
for (let attempt = 0; attempt <= MAX_STEAL_ATTEMPTS; attempt += 1) {
|
|
14362
14377
|
try {
|
|
14363
|
-
|
|
14364
|
-
const fd =
|
|
14378
|
+
fs28.mkdirSync(path27.dirname(lockPath), { recursive: true });
|
|
14379
|
+
const fd = fs28.openSync(lockPath, "wx", 384);
|
|
14365
14380
|
try {
|
|
14366
|
-
|
|
14381
|
+
fs28.writeSync(fd, JSON.stringify(meta2));
|
|
14367
14382
|
} finally {
|
|
14368
|
-
|
|
14383
|
+
fs28.closeSync(fd);
|
|
14369
14384
|
}
|
|
14370
14385
|
return true;
|
|
14371
14386
|
} catch (err) {
|
|
@@ -14383,9 +14398,9 @@ function tryAcquireOnce2(lockPath, meta2, opts) {
|
|
|
14383
14398
|
}
|
|
14384
14399
|
const victimPath = `${lockPath}.victim-${process.pid}-${attempt}-${Date.now()}`;
|
|
14385
14400
|
try {
|
|
14386
|
-
|
|
14401
|
+
fs28.renameSync(lockPath, victimPath);
|
|
14387
14402
|
try {
|
|
14388
|
-
|
|
14403
|
+
fs28.unlinkSync(victimPath);
|
|
14389
14404
|
} catch {
|
|
14390
14405
|
}
|
|
14391
14406
|
} catch (err) {
|
|
@@ -14417,7 +14432,7 @@ async function acquireSettingsJsonLock(options = {}) {
|
|
|
14417
14432
|
lockPath,
|
|
14418
14433
|
release: () => {
|
|
14419
14434
|
try {
|
|
14420
|
-
|
|
14435
|
+
fs28.unlinkSync(lockPath);
|
|
14421
14436
|
} catch {
|
|
14422
14437
|
}
|
|
14423
14438
|
}
|
|
@@ -14520,14 +14535,14 @@ var init_services_status = __esm({
|
|
|
14520
14535
|
|
|
14521
14536
|
// ../core/dist/skill-sources/meta-hooks-migration-snapshot.js
|
|
14522
14537
|
import * as crypto5 from "node:crypto";
|
|
14523
|
-
import * as
|
|
14538
|
+
import * as fs29 from "node:fs";
|
|
14524
14539
|
import * as os17 from "node:os";
|
|
14525
|
-
import * as
|
|
14540
|
+
import * as path28 from "node:path";
|
|
14526
14541
|
function migrationSnapshotsDir2() {
|
|
14527
14542
|
const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
|
|
14528
14543
|
if (override && override.length > 0)
|
|
14529
14544
|
return override;
|
|
14530
|
-
return
|
|
14545
|
+
return path28.join(os17.homedir(), ".olam", "state", "migration-snapshots");
|
|
14531
14546
|
}
|
|
14532
14547
|
function writeMetaHooksSnapshot(originalSettings) {
|
|
14533
14548
|
const snapshot = {
|
|
@@ -14538,11 +14553,11 @@ function writeMetaHooksSnapshot(originalSettings) {
|
|
|
14538
14553
|
};
|
|
14539
14554
|
const validated = MetaHooksMigrationSnapshotSchema.parse(snapshot);
|
|
14540
14555
|
const dir = migrationSnapshotsDir2();
|
|
14541
|
-
|
|
14556
|
+
fs29.mkdirSync(dir, { recursive: true });
|
|
14542
14557
|
const stamp = validated.takenAt.replace(/[:.]/g, "-");
|
|
14543
14558
|
const rand = crypto5.randomBytes(3).toString("hex");
|
|
14544
|
-
const file =
|
|
14545
|
-
|
|
14559
|
+
const file = path28.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
|
|
14560
|
+
fs29.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
|
|
14546
14561
|
return file;
|
|
14547
14562
|
}
|
|
14548
14563
|
var META_HOOKS_SNAPSHOT_SCHEMA_VERSION, META_HOOKS_SNAPSHOT_PREFIX, SettingsLooseSchema, MetaHooksMigrationSnapshotSchema;
|
|
@@ -14909,44 +14924,44 @@ var init_markdown_merger = __esm({
|
|
|
14909
14924
|
});
|
|
14910
14925
|
|
|
14911
14926
|
// ../core/dist/skill-sync/managed-merge.js
|
|
14912
|
-
import * as
|
|
14913
|
-
import * as
|
|
14927
|
+
import * as fs30 from "node:fs";
|
|
14928
|
+
import * as path29 from "node:path";
|
|
14914
14929
|
function materializeMergedSkill(opts) {
|
|
14915
14930
|
const { sourceId, sourcePath, deployBasename, mergedContent, claudeDir: claudeDir2 } = opts;
|
|
14916
|
-
const managedDir =
|
|
14917
|
-
const sourceRoot =
|
|
14918
|
-
const managedResolved =
|
|
14919
|
-
if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot +
|
|
14931
|
+
const managedDir = path29.join(claudeDir2, ".olam-merged", sourceId, deployBasename);
|
|
14932
|
+
const sourceRoot = path29.resolve(path29.join(claudeDir2, ".olam-merged", sourceId));
|
|
14933
|
+
const managedResolved = path29.resolve(managedDir);
|
|
14934
|
+
if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot + path29.sep))) {
|
|
14920
14935
|
throw new Error(`[managed-merge] refusing to materialize: deployBasename "${deployBasename}" escapes managed root "${sourceRoot}" (resolved to "${managedResolved}")`);
|
|
14921
14936
|
}
|
|
14922
|
-
|
|
14923
|
-
const skillMdPath =
|
|
14937
|
+
fs30.mkdirSync(managedDir, { recursive: true });
|
|
14938
|
+
const skillMdPath = path29.join(managedDir, "SKILL.md");
|
|
14924
14939
|
const tmpPath = `${skillMdPath}.tmp-${process.pid}-${Date.now()}`;
|
|
14925
|
-
|
|
14926
|
-
|
|
14927
|
-
const baseEntries =
|
|
14940
|
+
fs30.writeFileSync(tmpPath, mergedContent);
|
|
14941
|
+
fs30.renameSync(tmpPath, skillMdPath);
|
|
14942
|
+
const baseEntries = fs30.readdirSync(sourcePath);
|
|
14928
14943
|
for (const entry of baseEntries) {
|
|
14929
14944
|
if (entry === "SKILL.md")
|
|
14930
14945
|
continue;
|
|
14931
|
-
const linkPath =
|
|
14932
|
-
const targetAbsolute =
|
|
14933
|
-
const targetRelative =
|
|
14946
|
+
const linkPath = path29.join(managedDir, entry);
|
|
14947
|
+
const targetAbsolute = path29.join(sourcePath, entry);
|
|
14948
|
+
const targetRelative = path29.relative(managedDir, targetAbsolute);
|
|
14934
14949
|
try {
|
|
14935
|
-
|
|
14936
|
-
|
|
14950
|
+
fs30.lstatSync(linkPath);
|
|
14951
|
+
fs30.rmSync(linkPath, { recursive: true, force: true });
|
|
14937
14952
|
} catch {
|
|
14938
14953
|
}
|
|
14939
|
-
|
|
14954
|
+
fs30.symlinkSync(targetRelative, linkPath);
|
|
14940
14955
|
}
|
|
14941
|
-
const managedEntries =
|
|
14956
|
+
const managedEntries = fs30.readdirSync(managedDir);
|
|
14942
14957
|
const baseEntrySet = new Set(baseEntries);
|
|
14943
14958
|
for (const entry of managedEntries) {
|
|
14944
14959
|
if (entry === "SKILL.md")
|
|
14945
14960
|
continue;
|
|
14946
14961
|
if (!baseEntrySet.has(entry)) {
|
|
14947
|
-
const stalePath =
|
|
14962
|
+
const stalePath = path29.join(managedDir, entry);
|
|
14948
14963
|
try {
|
|
14949
|
-
|
|
14964
|
+
fs30.rmSync(stalePath, { recursive: true, force: true });
|
|
14950
14965
|
} catch {
|
|
14951
14966
|
}
|
|
14952
14967
|
}
|
|
@@ -14954,7 +14969,7 @@ function materializeMergedSkill(opts) {
|
|
|
14954
14969
|
return managedDir;
|
|
14955
14970
|
}
|
|
14956
14971
|
function cleanMergedDir(claudeDir2) {
|
|
14957
|
-
|
|
14972
|
+
fs30.rmSync(path29.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
|
|
14958
14973
|
}
|
|
14959
14974
|
var init_managed_merge = __esm({
|
|
14960
14975
|
"../core/dist/skill-sync/managed-merge.js"() {
|
|
@@ -15001,8 +15016,8 @@ var init_prefix_rules = __esm({
|
|
|
15001
15016
|
});
|
|
15002
15017
|
|
|
15003
15018
|
// ../core/dist/skill-sync/prefix-deploy.js
|
|
15004
|
-
import * as
|
|
15005
|
-
import * as
|
|
15019
|
+
import * as fs31 from "node:fs";
|
|
15020
|
+
import * as path30 from "node:path";
|
|
15006
15021
|
function buildSourcePrefixMap(sources) {
|
|
15007
15022
|
const byId = /* @__PURE__ */ new Map();
|
|
15008
15023
|
const scopeById = /* @__PURE__ */ new Map();
|
|
@@ -15050,8 +15065,8 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
|
|
|
15050
15065
|
continue;
|
|
15051
15066
|
}
|
|
15052
15067
|
if (artifact.kind === "skill") {
|
|
15053
|
-
const skillMdPath =
|
|
15054
|
-
const content =
|
|
15068
|
+
const skillMdPath = path30.join(artifact.sourcePath, "SKILL.md");
|
|
15069
|
+
const content = fs31.readFileSync(skillMdPath);
|
|
15055
15070
|
const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
|
|
15056
15071
|
const managedDir = materializeMergedSkill({
|
|
15057
15072
|
sourceId: artifact.sourceId,
|
|
@@ -15063,7 +15078,7 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
|
|
|
15063
15078
|
artifact.sourcePath = managedDir;
|
|
15064
15079
|
artifact.deployBasename = renamed;
|
|
15065
15080
|
} else {
|
|
15066
|
-
const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent :
|
|
15081
|
+
const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs31.readFileSync(artifact.sourcePath);
|
|
15067
15082
|
const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
|
|
15068
15083
|
artifact.resolvedContent = rewritten;
|
|
15069
15084
|
artifact.deployBasename = renamed;
|
|
@@ -15115,12 +15130,12 @@ function sourceConfigPath(clonePath) {
|
|
|
15115
15130
|
return join31(clonePath, "shared", "source-config.yaml");
|
|
15116
15131
|
}
|
|
15117
15132
|
function readSourceConfig(clonePath, sourceId) {
|
|
15118
|
-
const
|
|
15119
|
-
if (!existsSync31(
|
|
15133
|
+
const path53 = sourceConfigPath(clonePath);
|
|
15134
|
+
if (!existsSync31(path53))
|
|
15120
15135
|
return void 0;
|
|
15121
15136
|
let raw;
|
|
15122
15137
|
try {
|
|
15123
|
-
raw = readFileSync29(
|
|
15138
|
+
raw = readFileSync29(path53, "utf-8");
|
|
15124
15139
|
} catch (err) {
|
|
15125
15140
|
emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
|
|
15126
15141
|
return void 0;
|
|
@@ -15199,16 +15214,16 @@ var init_resolve_source_config = __esm({
|
|
|
15199
15214
|
});
|
|
15200
15215
|
|
|
15201
15216
|
// ../core/dist/skill-sync/engine.js
|
|
15202
|
-
import * as
|
|
15217
|
+
import * as fs32 from "node:fs";
|
|
15203
15218
|
import * as os18 from "node:os";
|
|
15204
|
-
import * as
|
|
15219
|
+
import * as path31 from "node:path";
|
|
15205
15220
|
function resolveAtlasUser(override) {
|
|
15206
15221
|
if (override)
|
|
15207
15222
|
return override;
|
|
15208
|
-
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] ||
|
|
15209
|
-
const f =
|
|
15210
|
-
if (
|
|
15211
|
-
return
|
|
15223
|
+
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path31.join(os18.homedir(), ".claude");
|
|
15224
|
+
const f = path31.join(claudeDir2, ".atlas-user");
|
|
15225
|
+
if (fs32.existsSync(f)) {
|
|
15226
|
+
return fs32.readFileSync(f, "utf-8").trim() || void 0;
|
|
15212
15227
|
}
|
|
15213
15228
|
return void 0;
|
|
15214
15229
|
}
|
|
@@ -15220,7 +15235,7 @@ async function syncSkills(opts = {}) {
|
|
|
15220
15235
|
const perSource = [];
|
|
15221
15236
|
for (const source of sources) {
|
|
15222
15237
|
const clonePath = skillSourceClonePath(source.id);
|
|
15223
|
-
if (!
|
|
15238
|
+
if (!fs32.existsSync(clonePath))
|
|
15224
15239
|
continue;
|
|
15225
15240
|
const { artifacts, subscription } = await withFileLock(clonePath, () => {
|
|
15226
15241
|
const pinRef = projectOverride?.override.pin?.[source.id];
|
|
@@ -15260,7 +15275,7 @@ async function syncSkills(opts = {}) {
|
|
|
15260
15275
|
const overlayArtifacts = memberOverlaysEnabled ? projectFilteredArtifacts.filter((a) => a.kind === "overlay") : [];
|
|
15261
15276
|
const effectiveSources = sources.map((s) => {
|
|
15262
15277
|
const clonePath = skillSourceClonePath(s.id);
|
|
15263
|
-
const sourceConfig =
|
|
15278
|
+
const sourceConfig = fs32.existsSync(clonePath) ? readSourceConfig(clonePath, s.id) : void 0;
|
|
15264
15279
|
const eff = resolveEffectivePrefix(s, sourceConfig);
|
|
15265
15280
|
const entry = {
|
|
15266
15281
|
id: s.id,
|
|
@@ -15363,13 +15378,13 @@ async function syncSkills(opts = {}) {
|
|
|
15363
15378
|
let baseContent;
|
|
15364
15379
|
let basePath;
|
|
15365
15380
|
if (overlay.targetKind === "skill") {
|
|
15366
|
-
basePath =
|
|
15367
|
-
baseContent =
|
|
15381
|
+
basePath = path31.join(base.sourcePath, "SKILL.md");
|
|
15382
|
+
baseContent = fs32.readFileSync(basePath, "utf-8");
|
|
15368
15383
|
} else {
|
|
15369
15384
|
basePath = base.sourcePath;
|
|
15370
|
-
baseContent =
|
|
15385
|
+
baseContent = fs32.readFileSync(basePath, "utf-8");
|
|
15371
15386
|
}
|
|
15372
|
-
const overlayContent =
|
|
15387
|
+
const overlayContent = fs32.readFileSync(overlay.sourcePath, "utf-8");
|
|
15373
15388
|
const label = `${overlay.sourceId}/${overlay.deployBasename}`;
|
|
15374
15389
|
const mergeResult = mergeMarkdown(baseContent, overlayContent, label, basePath, overlay.sourcePath);
|
|
15375
15390
|
if ("error" in mergeResult) {
|
|
@@ -15430,7 +15445,7 @@ async function syncSkills(opts = {}) {
|
|
|
15430
15445
|
summary.collisions = detectCollisions(baseArtifacts).collisions;
|
|
15431
15446
|
return summary;
|
|
15432
15447
|
}
|
|
15433
|
-
const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] ||
|
|
15448
|
+
const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] || path31.join(os18.homedir(), ".claude");
|
|
15434
15449
|
const overlayReferences = scanOverlayReferences(claudeDirPath, SHIM_TARGETS.map((t) => t.basename));
|
|
15435
15450
|
summary.deploy = deployArtifacts(baseArtifacts, {
|
|
15436
15451
|
installedOlamVersion,
|
|
@@ -15456,19 +15471,19 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
15456
15471
|
const result = await withSettingsJsonLock(() => {
|
|
15457
15472
|
let currentSettings = {};
|
|
15458
15473
|
let settingsExisted = false;
|
|
15459
|
-
if (
|
|
15474
|
+
if (fs32.existsSync(settingsFile)) {
|
|
15460
15475
|
settingsExisted = true;
|
|
15461
15476
|
try {
|
|
15462
|
-
const raw =
|
|
15477
|
+
const raw = fs32.readFileSync(settingsFile, "utf-8");
|
|
15463
15478
|
currentSettings = raw.trim() ? JSON.parse(raw) : {};
|
|
15464
15479
|
} catch {
|
|
15465
15480
|
try {
|
|
15466
|
-
const raw =
|
|
15467
|
-
const bakDir =
|
|
15468
|
-
|
|
15481
|
+
const raw = fs32.readFileSync(settingsFile);
|
|
15482
|
+
const bakDir = path31.join(path31.dirname(settingsFile), ".malformed-backups");
|
|
15483
|
+
fs32.mkdirSync(bakDir, { recursive: true });
|
|
15469
15484
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
15470
|
-
const bakFile =
|
|
15471
|
-
|
|
15485
|
+
const bakFile = path31.join(bakDir, `settings.json.malformed.${stamp}.bak`);
|
|
15486
|
+
fs32.writeFileSync(bakFile, raw, { mode: 384 });
|
|
15472
15487
|
snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
|
|
15473
15488
|
} catch (bakErr) {
|
|
15474
15489
|
snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
|
|
@@ -15518,10 +15533,10 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
15518
15533
|
} catch {
|
|
15519
15534
|
}
|
|
15520
15535
|
}
|
|
15521
|
-
|
|
15536
|
+
fs32.mkdirSync(path31.dirname(settingsFile), { recursive: true });
|
|
15522
15537
|
const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
|
|
15523
|
-
|
|
15524
|
-
|
|
15538
|
+
fs32.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
|
|
15539
|
+
fs32.renameSync(tmpPath, settingsFile);
|
|
15525
15540
|
return inject;
|
|
15526
15541
|
}, { reason: `syncSkills meta-hook injection (mode=${mode})` });
|
|
15527
15542
|
return {
|
|
@@ -15562,19 +15577,19 @@ var init_engine = __esm({
|
|
|
15562
15577
|
});
|
|
15563
15578
|
|
|
15564
15579
|
// ../core/dist/skill-sync/shadow-backup-manager.js
|
|
15565
|
-
import * as
|
|
15566
|
-
import * as
|
|
15580
|
+
import * as fs33 from "node:fs";
|
|
15581
|
+
import * as path32 from "node:path";
|
|
15567
15582
|
function listShadowBackups(opts = {}) {
|
|
15568
15583
|
const claude = opts.claudeDirOverride ?? claudeDir();
|
|
15569
15584
|
const now = opts.now ?? Date.now();
|
|
15570
15585
|
const out = [];
|
|
15571
15586
|
for (const bucket of SHADOW_BACKUP_BUCKETS) {
|
|
15572
|
-
const bucketDir =
|
|
15573
|
-
if (!
|
|
15587
|
+
const bucketDir = path32.join(claude, bucket);
|
|
15588
|
+
if (!fs33.existsSync(bucketDir))
|
|
15574
15589
|
continue;
|
|
15575
15590
|
let entries;
|
|
15576
15591
|
try {
|
|
15577
|
-
entries =
|
|
15592
|
+
entries = fs33.readdirSync(bucketDir);
|
|
15578
15593
|
} catch {
|
|
15579
15594
|
continue;
|
|
15580
15595
|
}
|
|
@@ -15585,10 +15600,10 @@ function listShadowBackups(opts = {}) {
|
|
|
15585
15600
|
const epochSeconds = Number.parseInt(match[1], 10);
|
|
15586
15601
|
if (!Number.isFinite(epochSeconds) || epochSeconds < 0)
|
|
15587
15602
|
continue;
|
|
15588
|
-
const full =
|
|
15603
|
+
const full = path32.join(bucketDir, name);
|
|
15589
15604
|
let sizeBytes = 0;
|
|
15590
15605
|
try {
|
|
15591
|
-
const st =
|
|
15606
|
+
const st = fs33.statSync(full);
|
|
15592
15607
|
if (st.isDirectory())
|
|
15593
15608
|
continue;
|
|
15594
15609
|
sizeBytes = st.size;
|
|
@@ -15601,7 +15616,7 @@ function listShadowBackups(opts = {}) {
|
|
|
15601
15616
|
bucket,
|
|
15602
15617
|
basename: name,
|
|
15603
15618
|
originalBasename,
|
|
15604
|
-
originalPath:
|
|
15619
|
+
originalPath: path32.join(bucketDir, originalBasename),
|
|
15605
15620
|
epochSeconds,
|
|
15606
15621
|
ageMs: now - epochSeconds * 1e3,
|
|
15607
15622
|
sizeBytes
|
|
@@ -15644,7 +15659,7 @@ function pruneShadowBackups(opts) {
|
|
|
15644
15659
|
}
|
|
15645
15660
|
if (!opts.dryRun) {
|
|
15646
15661
|
try {
|
|
15647
|
-
|
|
15662
|
+
fs33.unlinkSync(b.path);
|
|
15648
15663
|
} catch {
|
|
15649
15664
|
skipped.push(b);
|
|
15650
15665
|
continue;
|
|
@@ -15655,24 +15670,24 @@ function pruneShadowBackups(opts) {
|
|
|
15655
15670
|
return { deleted, skipped };
|
|
15656
15671
|
}
|
|
15657
15672
|
function restoreShadowBackup(opts) {
|
|
15658
|
-
const abs =
|
|
15659
|
-
if (!
|
|
15673
|
+
const abs = path32.resolve(opts.backupPath);
|
|
15674
|
+
if (!fs33.existsSync(abs)) {
|
|
15660
15675
|
throw new Error(`backup file not found: ${abs}`);
|
|
15661
15676
|
}
|
|
15662
|
-
const basename6 =
|
|
15677
|
+
const basename6 = path32.basename(abs);
|
|
15663
15678
|
const match = SHADOW_BACKUP_SUFFIX_RE.exec(basename6);
|
|
15664
15679
|
if (!match) {
|
|
15665
15680
|
throw new Error(`not a shadow-backup file (basename "${basename6}" does not match \`.shadow-backup-<epoch>\`): ${abs}`);
|
|
15666
15681
|
}
|
|
15667
15682
|
const originalBasename = basename6.slice(0, basename6.length - match[0].length);
|
|
15668
|
-
const originalPath =
|
|
15669
|
-
if (
|
|
15683
|
+
const originalPath = path32.join(path32.dirname(abs), originalBasename);
|
|
15684
|
+
if (fs33.existsSync(originalPath) && !opts.force) {
|
|
15670
15685
|
throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
|
|
15671
15686
|
}
|
|
15672
|
-
if (opts.force &&
|
|
15673
|
-
|
|
15687
|
+
if (opts.force && fs33.existsSync(originalPath)) {
|
|
15688
|
+
fs33.unlinkSync(originalPath);
|
|
15674
15689
|
}
|
|
15675
|
-
|
|
15690
|
+
fs33.renameSync(abs, originalPath);
|
|
15676
15691
|
return { restoredTo: originalPath };
|
|
15677
15692
|
}
|
|
15678
15693
|
var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
|
|
@@ -15686,14 +15701,14 @@ var init_shadow_backup_manager = __esm({
|
|
|
15686
15701
|
});
|
|
15687
15702
|
|
|
15688
15703
|
// ../core/dist/skill-sources/doctor-checks.js
|
|
15689
|
-
import * as
|
|
15690
|
-
import * as
|
|
15704
|
+
import * as fs34 from "node:fs";
|
|
15705
|
+
import * as path33 from "node:path";
|
|
15691
15706
|
import * as os19 from "node:os";
|
|
15692
15707
|
function claudeDirInternal3() {
|
|
15693
15708
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
15694
15709
|
if (override && override.length > 0)
|
|
15695
15710
|
return override;
|
|
15696
|
-
return
|
|
15711
|
+
return path33.join(os19.homedir(), ".claude");
|
|
15697
15712
|
}
|
|
15698
15713
|
function checkStateFileParse() {
|
|
15699
15714
|
const filePath = globalConfigPath();
|
|
@@ -15702,11 +15717,11 @@ function checkStateFileParse() {
|
|
|
15702
15717
|
healthy: true,
|
|
15703
15718
|
description: `~/.olam state file (${filePath})`
|
|
15704
15719
|
};
|
|
15705
|
-
if (!
|
|
15720
|
+
if (!fs34.existsSync(filePath)) {
|
|
15706
15721
|
result.details = ["(file does not yet exist \u2014 will be created on first write)"];
|
|
15707
15722
|
return result;
|
|
15708
15723
|
}
|
|
15709
|
-
const raw =
|
|
15724
|
+
const raw = fs34.readFileSync(filePath, "utf-8");
|
|
15710
15725
|
let parsed;
|
|
15711
15726
|
try {
|
|
15712
15727
|
parsed = JSON.parse(raw);
|
|
@@ -15716,8 +15731,8 @@ function checkStateFileParse() {
|
|
|
15716
15731
|
result.details = [err instanceof Error ? err.message : String(err)];
|
|
15717
15732
|
result.repair = () => {
|
|
15718
15733
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
15719
|
-
|
|
15720
|
-
|
|
15734
|
+
fs34.renameSync(filePath, aside);
|
|
15735
|
+
fs34.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
|
|
15721
15736
|
};
|
|
15722
15737
|
return result;
|
|
15723
15738
|
}
|
|
@@ -15728,7 +15743,7 @@ function checkStateFileParse() {
|
|
|
15728
15743
|
result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
|
|
15729
15744
|
result.repair = () => {
|
|
15730
15745
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
15731
|
-
|
|
15746
|
+
fs34.copyFileSync(filePath, aside);
|
|
15732
15747
|
const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
15733
15748
|
const next = {
|
|
15734
15749
|
...base,
|
|
@@ -15737,7 +15752,7 @@ function checkStateFileParse() {
|
|
|
15737
15752
|
runbooks: [],
|
|
15738
15753
|
skillSources: []
|
|
15739
15754
|
};
|
|
15740
|
-
|
|
15755
|
+
fs34.writeFileSync(filePath, JSON.stringify(next, null, 2));
|
|
15741
15756
|
};
|
|
15742
15757
|
return result;
|
|
15743
15758
|
}
|
|
@@ -15748,16 +15763,16 @@ function checkDanglingSymlinks() {
|
|
|
15748
15763
|
const buckets = ["commands", "agents", "skills", "scripts", "rules"];
|
|
15749
15764
|
const dangling = [];
|
|
15750
15765
|
for (const bucket of buckets) {
|
|
15751
|
-
const dir =
|
|
15752
|
-
if (!
|
|
15766
|
+
const dir = path33.join(claude, bucket);
|
|
15767
|
+
if (!fs34.existsSync(dir))
|
|
15753
15768
|
continue;
|
|
15754
|
-
for (const name of
|
|
15755
|
-
const linkPath =
|
|
15769
|
+
for (const name of fs34.readdirSync(dir)) {
|
|
15770
|
+
const linkPath = path33.join(dir, name);
|
|
15756
15771
|
try {
|
|
15757
|
-
const lst =
|
|
15772
|
+
const lst = fs34.lstatSync(linkPath);
|
|
15758
15773
|
if (!lst.isSymbolicLink())
|
|
15759
15774
|
continue;
|
|
15760
|
-
if (!
|
|
15775
|
+
if (!fs34.existsSync(linkPath)) {
|
|
15761
15776
|
dangling.push(linkPath);
|
|
15762
15777
|
}
|
|
15763
15778
|
} catch {
|
|
@@ -15775,7 +15790,7 @@ function checkDanglingSymlinks() {
|
|
|
15775
15790
|
result.repair = () => {
|
|
15776
15791
|
for (const p of dangling) {
|
|
15777
15792
|
try {
|
|
15778
|
-
|
|
15793
|
+
fs34.unlinkSync(p);
|
|
15779
15794
|
} catch {
|
|
15780
15795
|
}
|
|
15781
15796
|
}
|
|
@@ -15790,19 +15805,19 @@ function checkOrphanedSnapshots() {
|
|
|
15790
15805
|
healthy: true,
|
|
15791
15806
|
description: `orphaned migration snapshots under ${dir}`
|
|
15792
15807
|
};
|
|
15793
|
-
if (!
|
|
15808
|
+
if (!fs34.existsSync(dir)) {
|
|
15794
15809
|
return result;
|
|
15795
15810
|
}
|
|
15796
15811
|
const orphans = [];
|
|
15797
|
-
for (const name of
|
|
15812
|
+
for (const name of fs34.readdirSync(dir)) {
|
|
15798
15813
|
if (!name.endsWith(".json"))
|
|
15799
15814
|
continue;
|
|
15800
|
-
const full =
|
|
15815
|
+
const full = path33.join(dir, name);
|
|
15801
15816
|
try {
|
|
15802
|
-
const
|
|
15803
|
-
if (!
|
|
15817
|
+
const stat2 = fs34.statSync(full);
|
|
15818
|
+
if (!stat2.isFile())
|
|
15804
15819
|
continue;
|
|
15805
|
-
const raw =
|
|
15820
|
+
const raw = fs34.readFileSync(full, "utf-8");
|
|
15806
15821
|
let parsed;
|
|
15807
15822
|
try {
|
|
15808
15823
|
parsed = JSON.parse(raw);
|
|
@@ -15827,7 +15842,7 @@ function checkOrphanedSnapshots() {
|
|
|
15827
15842
|
result.repair = () => {
|
|
15828
15843
|
for (const o of orphans) {
|
|
15829
15844
|
try {
|
|
15830
|
-
|
|
15845
|
+
fs34.unlinkSync(o.path);
|
|
15831
15846
|
} catch {
|
|
15832
15847
|
}
|
|
15833
15848
|
}
|
|
@@ -15842,12 +15857,12 @@ function checkSentinelDrift() {
|
|
|
15842
15857
|
healthy: true,
|
|
15843
15858
|
description: `olam-skills sentinel block in ${filePath}`
|
|
15844
15859
|
};
|
|
15845
|
-
if (!
|
|
15860
|
+
if (!fs34.existsSync(filePath)) {
|
|
15846
15861
|
return result;
|
|
15847
15862
|
}
|
|
15848
15863
|
let parsed;
|
|
15849
15864
|
try {
|
|
15850
|
-
parsed = JSON.parse(
|
|
15865
|
+
parsed = JSON.parse(fs34.readFileSync(filePath, "utf-8"));
|
|
15851
15866
|
} catch {
|
|
15852
15867
|
return result;
|
|
15853
15868
|
}
|
|
@@ -15888,7 +15903,7 @@ function checkSentinelDrift() {
|
|
|
15888
15903
|
backupSettings();
|
|
15889
15904
|
} catch {
|
|
15890
15905
|
}
|
|
15891
|
-
const next = JSON.parse(
|
|
15906
|
+
const next = JSON.parse(fs34.readFileSync(filePath, "utf-8"));
|
|
15892
15907
|
if (!next.hooks)
|
|
15893
15908
|
return;
|
|
15894
15909
|
for (const stage of Object.keys(next.hooks)) {
|
|
@@ -15911,7 +15926,7 @@ function checkSentinelDrift() {
|
|
|
15911
15926
|
return bad === void 0;
|
|
15912
15927
|
});
|
|
15913
15928
|
}
|
|
15914
|
-
|
|
15929
|
+
fs34.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
15915
15930
|
};
|
|
15916
15931
|
}
|
|
15917
15932
|
return result;
|
|
@@ -15935,8 +15950,8 @@ function checkMemberNameMissing() {
|
|
|
15935
15950
|
return result;
|
|
15936
15951
|
}
|
|
15937
15952
|
const claudeDir2 = claudeDirInternal3();
|
|
15938
|
-
const atlasUserPath =
|
|
15939
|
-
const value =
|
|
15953
|
+
const atlasUserPath = path33.join(claudeDir2, ".atlas-user");
|
|
15954
|
+
const value = fs34.existsSync(atlasUserPath) ? fs34.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
15940
15955
|
if (value.length > 0) {
|
|
15941
15956
|
result.details = [`atlas-user: ${value}`];
|
|
15942
15957
|
return result;
|
|
@@ -15944,10 +15959,10 @@ function checkMemberNameMissing() {
|
|
|
15944
15959
|
result.healthy = false;
|
|
15945
15960
|
result.issue = "atlas-toolbox source registered but ~/.claude/.atlas-user not set";
|
|
15946
15961
|
const clonePath = skillSourceClonePath(atlasSource.id);
|
|
15947
|
-
const membersDir =
|
|
15948
|
-
const existing =
|
|
15962
|
+
const membersDir = path33.join(clonePath, "members");
|
|
15963
|
+
const existing = fs34.existsSync(membersDir) ? fs34.readdirSync(membersDir).filter((e) => {
|
|
15949
15964
|
try {
|
|
15950
|
-
return
|
|
15965
|
+
return fs34.statSync(path33.join(membersDir, e)).isDirectory();
|
|
15951
15966
|
} catch {
|
|
15952
15967
|
return false;
|
|
15953
15968
|
}
|
|
@@ -15961,8 +15976,8 @@ function checkMemberNameMissing() {
|
|
|
15961
15976
|
}
|
|
15962
15977
|
function checkMemberOverlayDrift() {
|
|
15963
15978
|
const claudeDir2 = claudeDirInternal3();
|
|
15964
|
-
const atlasUserPath =
|
|
15965
|
-
const atlasUser =
|
|
15979
|
+
const atlasUserPath = path33.join(claudeDir2, ".atlas-user");
|
|
15980
|
+
const atlasUser = fs34.existsSync(atlasUserPath) ? fs34.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
15966
15981
|
if (atlasUser.length === 0) {
|
|
15967
15982
|
return [];
|
|
15968
15983
|
}
|
|
@@ -15978,26 +15993,26 @@ function checkMemberOverlayDrift() {
|
|
|
15978
15993
|
const clonePath = skillSourceClonePath(atlasSource.id);
|
|
15979
15994
|
const results = [];
|
|
15980
15995
|
for (const kind of ["skills", "agents"]) {
|
|
15981
|
-
const localRoot =
|
|
15982
|
-
if (!
|
|
15996
|
+
const localRoot = path33.join(claudeDir2, `${kind}.overrides`);
|
|
15997
|
+
if (!fs34.existsSync(localRoot))
|
|
15983
15998
|
continue;
|
|
15984
15999
|
let entries;
|
|
15985
16000
|
try {
|
|
15986
|
-
entries =
|
|
16001
|
+
entries = fs34.readdirSync(localRoot);
|
|
15987
16002
|
} catch {
|
|
15988
16003
|
continue;
|
|
15989
16004
|
}
|
|
15990
16005
|
for (const entry of entries) {
|
|
15991
|
-
const localFile =
|
|
15992
|
-
let
|
|
16006
|
+
const localFile = path33.join(localRoot, entry);
|
|
16007
|
+
let stat2;
|
|
15993
16008
|
try {
|
|
15994
|
-
|
|
16009
|
+
stat2 = fs34.statSync(localFile);
|
|
15995
16010
|
} catch {
|
|
15996
16011
|
continue;
|
|
15997
16012
|
}
|
|
15998
|
-
if (!
|
|
16013
|
+
if (!stat2.isFile())
|
|
15999
16014
|
continue;
|
|
16000
|
-
const cloneFile =
|
|
16015
|
+
const cloneFile = path33.join(clonePath, "members", atlasUser, `${kind}.overrides`, entry);
|
|
16001
16016
|
const localSha = sha256OfPath(localFile);
|
|
16002
16017
|
const cloneSha = sha256OfPath(cloneFile);
|
|
16003
16018
|
if (localSha === cloneSha) {
|
|
@@ -16421,10 +16436,10 @@ function mergeDefs(...defs) {
|
|
|
16421
16436
|
function cloneDef(schema) {
|
|
16422
16437
|
return mergeDefs(schema._zod.def);
|
|
16423
16438
|
}
|
|
16424
|
-
function getElementAtPath(obj,
|
|
16425
|
-
if (!
|
|
16439
|
+
function getElementAtPath(obj, path53) {
|
|
16440
|
+
if (!path53)
|
|
16426
16441
|
return obj;
|
|
16427
|
-
return
|
|
16442
|
+
return path53.reduce((acc, key) => acc?.[key], obj);
|
|
16428
16443
|
}
|
|
16429
16444
|
function promiseAllObject(promisesObj) {
|
|
16430
16445
|
const keys = Object.keys(promisesObj);
|
|
@@ -16833,11 +16848,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
16833
16848
|
}
|
|
16834
16849
|
return false;
|
|
16835
16850
|
}
|
|
16836
|
-
function prefixIssues(
|
|
16851
|
+
function prefixIssues(path53, issues) {
|
|
16837
16852
|
return issues.map((iss) => {
|
|
16838
16853
|
var _a3;
|
|
16839
16854
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
16840
|
-
iss.path.unshift(
|
|
16855
|
+
iss.path.unshift(path53);
|
|
16841
16856
|
return iss;
|
|
16842
16857
|
});
|
|
16843
16858
|
}
|
|
@@ -16984,16 +16999,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
|
|
|
16984
16999
|
}
|
|
16985
17000
|
function formatError(error2, mapper = (issue2) => issue2.message) {
|
|
16986
17001
|
const fieldErrors = { _errors: [] };
|
|
16987
|
-
const processError = (error3,
|
|
17002
|
+
const processError = (error3, path53 = []) => {
|
|
16988
17003
|
for (const issue2 of error3.issues) {
|
|
16989
17004
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
16990
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
17005
|
+
issue2.errors.map((issues) => processError({ issues }, [...path53, ...issue2.path]));
|
|
16991
17006
|
} else if (issue2.code === "invalid_key") {
|
|
16992
|
-
processError({ issues: issue2.issues }, [...
|
|
17007
|
+
processError({ issues: issue2.issues }, [...path53, ...issue2.path]);
|
|
16993
17008
|
} else if (issue2.code === "invalid_element") {
|
|
16994
|
-
processError({ issues: issue2.issues }, [...
|
|
17009
|
+
processError({ issues: issue2.issues }, [...path53, ...issue2.path]);
|
|
16995
17010
|
} else {
|
|
16996
|
-
const fullpath = [...
|
|
17011
|
+
const fullpath = [...path53, ...issue2.path];
|
|
16997
17012
|
if (fullpath.length === 0) {
|
|
16998
17013
|
fieldErrors._errors.push(mapper(issue2));
|
|
16999
17014
|
} else {
|
|
@@ -23210,12 +23225,12 @@ var StdioServerTransport = class {
|
|
|
23210
23225
|
this.onclose?.();
|
|
23211
23226
|
}
|
|
23212
23227
|
send(message) {
|
|
23213
|
-
return new Promise((
|
|
23228
|
+
return new Promise((resolve15) => {
|
|
23214
23229
|
const json = serializeMessage(message);
|
|
23215
23230
|
if (this._stdout.write(json)) {
|
|
23216
|
-
|
|
23231
|
+
resolve15();
|
|
23217
23232
|
} else {
|
|
23218
|
-
this._stdout.once("drain",
|
|
23233
|
+
this._stdout.once("drain", resolve15);
|
|
23219
23234
|
}
|
|
23220
23235
|
});
|
|
23221
23236
|
}
|
|
@@ -25252,7 +25267,7 @@ var Protocol = class {
|
|
|
25252
25267
|
return;
|
|
25253
25268
|
}
|
|
25254
25269
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
25255
|
-
await new Promise((
|
|
25270
|
+
await new Promise((resolve15) => setTimeout(resolve15, pollInterval));
|
|
25256
25271
|
options?.signal?.throwIfAborted();
|
|
25257
25272
|
}
|
|
25258
25273
|
} catch (error2) {
|
|
@@ -25269,7 +25284,7 @@ var Protocol = class {
|
|
|
25269
25284
|
*/
|
|
25270
25285
|
request(request2, resultSchema, options) {
|
|
25271
25286
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
25272
|
-
return new Promise((
|
|
25287
|
+
return new Promise((resolve15, reject2) => {
|
|
25273
25288
|
const earlyReject = (error2) => {
|
|
25274
25289
|
reject2(error2);
|
|
25275
25290
|
};
|
|
@@ -25347,7 +25362,7 @@ var Protocol = class {
|
|
|
25347
25362
|
if (!parseResult.success) {
|
|
25348
25363
|
reject2(parseResult.error);
|
|
25349
25364
|
} else {
|
|
25350
|
-
|
|
25365
|
+
resolve15(parseResult.data);
|
|
25351
25366
|
}
|
|
25352
25367
|
} catch (error2) {
|
|
25353
25368
|
reject2(error2);
|
|
@@ -25608,12 +25623,12 @@ var Protocol = class {
|
|
|
25608
25623
|
}
|
|
25609
25624
|
} catch {
|
|
25610
25625
|
}
|
|
25611
|
-
return new Promise((
|
|
25626
|
+
return new Promise((resolve15, reject2) => {
|
|
25612
25627
|
if (signal.aborted) {
|
|
25613
25628
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
25614
25629
|
return;
|
|
25615
25630
|
}
|
|
25616
|
-
const timeoutId = setTimeout(
|
|
25631
|
+
const timeoutId = setTimeout(resolve15, interval);
|
|
25617
25632
|
signal.addEventListener("abort", () => {
|
|
25618
25633
|
clearTimeout(timeoutId);
|
|
25619
25634
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -26935,7 +26950,7 @@ var McpServer = class {
|
|
|
26935
26950
|
let task = createTaskResult.task;
|
|
26936
26951
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
26937
26952
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
26938
|
-
await new Promise((
|
|
26953
|
+
await new Promise((resolve15) => setTimeout(resolve15, pollInterval));
|
|
26939
26954
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
26940
26955
|
if (!updatedTask) {
|
|
26941
26956
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -27527,6 +27542,59 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
27527
27542
|
}
|
|
27528
27543
|
};
|
|
27529
27544
|
|
|
27545
|
+
// ../mcp-server/src/tool-filter.ts
|
|
27546
|
+
function getToolFilterContextFromEnv() {
|
|
27547
|
+
const raw = process.env.OLAM_ALLOWED_TOOLS;
|
|
27548
|
+
const worldId = process.env.OLAM_WORLD_ID;
|
|
27549
|
+
const context = {};
|
|
27550
|
+
if (worldId && worldId.trim() !== "") {
|
|
27551
|
+
context.worldId = worldId;
|
|
27552
|
+
}
|
|
27553
|
+
if (raw && raw.trim() !== "") {
|
|
27554
|
+
const allowedTools = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
27555
|
+
if (allowedTools.length > 0) {
|
|
27556
|
+
context.allowedTools = allowedTools;
|
|
27557
|
+
}
|
|
27558
|
+
}
|
|
27559
|
+
return context;
|
|
27560
|
+
}
|
|
27561
|
+
function withFilteredTools(server, context) {
|
|
27562
|
+
const allowed = context.allowedTools;
|
|
27563
|
+
if (!allowed || allowed.length === 0) {
|
|
27564
|
+
return { server, finalize: () => {
|
|
27565
|
+
} };
|
|
27566
|
+
}
|
|
27567
|
+
const allowedSet = new Set(allowed);
|
|
27568
|
+
const registered = /* @__PURE__ */ new Set();
|
|
27569
|
+
const host = server;
|
|
27570
|
+
const original = host.tool;
|
|
27571
|
+
const filtered = function(name, ...rest) {
|
|
27572
|
+
if (typeof name === "string" && allowedSet.has(name)) {
|
|
27573
|
+
registered.add(name);
|
|
27574
|
+
return original.apply(
|
|
27575
|
+
server,
|
|
27576
|
+
[name, ...rest]
|
|
27577
|
+
);
|
|
27578
|
+
}
|
|
27579
|
+
return void 0;
|
|
27580
|
+
};
|
|
27581
|
+
host.tool = filtered;
|
|
27582
|
+
return {
|
|
27583
|
+
server,
|
|
27584
|
+
finalize: () => {
|
|
27585
|
+
host.tool = original;
|
|
27586
|
+
for (const name of allowedSet) {
|
|
27587
|
+
if (!registered.has(name)) {
|
|
27588
|
+
process.stderr.write(
|
|
27589
|
+
`[tool-filter] warning: unknown tool name in OLAM_ALLOWED_TOOLS: "${name}"
|
|
27590
|
+
`
|
|
27591
|
+
);
|
|
27592
|
+
}
|
|
27593
|
+
}
|
|
27594
|
+
}
|
|
27595
|
+
};
|
|
27596
|
+
}
|
|
27597
|
+
|
|
27530
27598
|
// ../mcp-server/src/tools/init.ts
|
|
27531
27599
|
var init_exports = {};
|
|
27532
27600
|
__export(init_exports, {
|
|
@@ -27728,6 +27796,7 @@ To reinitialize, delete .olam/ first.`
|
|
|
27728
27796
|
// ../mcp-server/src/tools/auth.ts
|
|
27729
27797
|
var auth_exports = {};
|
|
27730
27798
|
__export(auth_exports, {
|
|
27799
|
+
formatAccountFlag: () => formatAccountFlag,
|
|
27731
27800
|
register: () => register2
|
|
27732
27801
|
});
|
|
27733
27802
|
init_v3();
|
|
@@ -27878,8 +27947,8 @@ var AuthClient = class {
|
|
|
27878
27947
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
27879
27948
|
}
|
|
27880
27949
|
}
|
|
27881
|
-
async request(method,
|
|
27882
|
-
const url2 = `${this.baseUrl}${
|
|
27950
|
+
async request(method, path53, body, attempt = 0) {
|
|
27951
|
+
const url2 = `${this.baseUrl}${path53}`;
|
|
27883
27952
|
const controller = new AbortController();
|
|
27884
27953
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
27885
27954
|
const headers = {};
|
|
@@ -27897,7 +27966,7 @@ var AuthClient = class {
|
|
|
27897
27966
|
} catch (err) {
|
|
27898
27967
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
27899
27968
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
27900
|
-
return this.request(method,
|
|
27969
|
+
return this.request(method, path53, body, attempt + 1);
|
|
27901
27970
|
}
|
|
27902
27971
|
throw err;
|
|
27903
27972
|
} finally {
|
|
@@ -27924,7 +27993,7 @@ async function safeText(res) {
|
|
|
27924
27993
|
}
|
|
27925
27994
|
}
|
|
27926
27995
|
function sleep(ms) {
|
|
27927
|
-
return new Promise((
|
|
27996
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
27928
27997
|
}
|
|
27929
27998
|
|
|
27930
27999
|
// ../core/dist/auth/container.js
|
|
@@ -28056,7 +28125,7 @@ function resolveAuthServicePath() {
|
|
|
28056
28125
|
return path3.join(pkgsDir, "auth-service");
|
|
28057
28126
|
}
|
|
28058
28127
|
function sleep2(ms) {
|
|
28059
|
-
return new Promise((
|
|
28128
|
+
return new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
28060
28129
|
}
|
|
28061
28130
|
|
|
28062
28131
|
// ../core/dist/auth/preflight.js
|
|
@@ -28134,6 +28203,21 @@ function describe2(err) {
|
|
|
28134
28203
|
}
|
|
28135
28204
|
|
|
28136
28205
|
// ../mcp-server/src/tools/auth.ts
|
|
28206
|
+
function formatAccountFlag(a, now = Date.now()) {
|
|
28207
|
+
if (a.state === "disabled") return "disabled";
|
|
28208
|
+
if (a.state === "usage-capped") {
|
|
28209
|
+
if (a.weeklyResetsAt && new Date(a.weeklyResetsAt).getTime() > now) {
|
|
28210
|
+
return "weekly limit";
|
|
28211
|
+
}
|
|
28212
|
+
return "usage cap";
|
|
28213
|
+
}
|
|
28214
|
+
if (a.state === "cooldown") return "rate-limited";
|
|
28215
|
+
if (a.state === "expired") return "expired";
|
|
28216
|
+
if (a.state === "active") return "valid";
|
|
28217
|
+
if (a.rateLimited) return "rate-limited";
|
|
28218
|
+
if (!a.tokenValid) return "expired";
|
|
28219
|
+
return "valid";
|
|
28220
|
+
}
|
|
28137
28221
|
function register2(server, _ctx, _initError) {
|
|
28138
28222
|
server.tool(
|
|
28139
28223
|
"olam_auth_status",
|
|
@@ -28156,7 +28240,7 @@ function register2(server, _ctx, _initError) {
|
|
|
28156
28240
|
lines.push(" (none \u2014 run olam_auth_login)");
|
|
28157
28241
|
} else {
|
|
28158
28242
|
for (const a of status2.accounts) {
|
|
28159
|
-
const flag = a
|
|
28243
|
+
const flag = formatAccountFlag(a);
|
|
28160
28244
|
lines.push(` - ${a.id.padEnd(20)} ${flag.padEnd(14)} expires in ${a.expiresIn}`);
|
|
28161
28245
|
}
|
|
28162
28246
|
}
|
|
@@ -28347,7 +28431,8 @@ function rowToMetadata(row) {
|
|
|
28347
28431
|
...expectedServices !== void 0 ? { expectedServices } : {},
|
|
28348
28432
|
...appPortUrls !== void 0 ? { appPortUrls } : {},
|
|
28349
28433
|
...worldDbNames !== void 0 ? { worldDbNames } : {},
|
|
28350
|
-
...row.world_role_name ? { worldRoleName: row.world_role_name } : {}
|
|
28434
|
+
...row.world_role_name ? { worldRoleName: row.world_role_name } : {},
|
|
28435
|
+
...row.claude_home ? { claudeHome: row.claude_home } : {}
|
|
28351
28436
|
};
|
|
28352
28437
|
}
|
|
28353
28438
|
var SCHEMA_VERSION = "1";
|
|
@@ -28402,7 +28487,9 @@ var WorldRegistry = class {
|
|
|
28402
28487
|
// world_db_names (SQLite has no native array; matches repos column shape).
|
|
28403
28488
|
// TEXT[] would fail at DDL time (closes OQ13/OQ22 / FS-03).
|
|
28404
28489
|
"world_db_names TEXT",
|
|
28405
|
-
"world_role_name TEXT"
|
|
28490
|
+
"world_role_name TEXT",
|
|
28491
|
+
// ADR 045 — per-world Claude Code HOME path. Additive migration.
|
|
28492
|
+
"claude_home TEXT"
|
|
28406
28493
|
]) {
|
|
28407
28494
|
try {
|
|
28408
28495
|
this.db.exec(`ALTER TABLE worlds ADD COLUMN ${col}`);
|
|
@@ -28433,8 +28520,8 @@ var WorldRegistry = class {
|
|
|
28433
28520
|
compute_provider, total_cost_usd, thought_count, created_at, updated_at,
|
|
28434
28521
|
pr_url, pr_number, pr_repo, pr_created_at, pr_state, pr_merged_at, auto_destroy_on_merge,
|
|
28435
28522
|
readiness_chain, expected_services, app_port_urls,
|
|
28436
|
-
world_db_names, world_role_name)
|
|
28437
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(world.id, world.name, world.status, JSON.stringify(world.repos), world.branch, world.portOffset, world.workspacePath, world.computeProvider, world.totalCostUsd, world.thoughtCount, world.createdAt, world.updatedAt, world.prUrl ?? null, world.prNumber ?? null, world.prRepo ?? null, world.prCreatedAt ?? null, world.prState ?? "none", world.prMergedAt ?? null, world.autoDestroyOnMerge === false ? 0 : 1, world.readinessChain !== void 0 ? JSON.stringify(world.readinessChain) : null, world.expectedServices !== void 0 ? JSON.stringify(world.expectedServices) : null, world.appPortUrls !== void 0 ? JSON.stringify(world.appPortUrls) : null, world.worldDbNames !== void 0 ? JSON.stringify(world.worldDbNames) : null, world.worldRoleName ?? null);
|
|
28523
|
+
world_db_names, world_role_name, claude_home)
|
|
28524
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(world.id, world.name, world.status, JSON.stringify(world.repos), world.branch, world.portOffset, world.workspacePath, world.computeProvider, world.totalCostUsd, world.thoughtCount, world.createdAt, world.updatedAt, world.prUrl ?? null, world.prNumber ?? null, world.prRepo ?? null, world.prCreatedAt ?? null, world.prState ?? "none", world.prMergedAt ?? null, world.autoDestroyOnMerge === false ? 0 : 1, world.readinessChain !== void 0 ? JSON.stringify(world.readinessChain) : null, world.expectedServices !== void 0 ? JSON.stringify(world.expectedServices) : null, world.appPortUrls !== void 0 ? JSON.stringify(world.appPortUrls) : null, world.worldDbNames !== void 0 ? JSON.stringify(world.worldDbNames) : null, world.worldRoleName ?? null, world.claudeHome ?? null);
|
|
28438
28525
|
}
|
|
28439
28526
|
update(worldId, updates) {
|
|
28440
28527
|
const setClauses = [];
|
|
@@ -28462,7 +28549,9 @@ var WorldRegistry = class {
|
|
|
28462
28549
|
appPortUrls: "app_port_urls",
|
|
28463
28550
|
// olam-hybrid-shared-postgres Phase A task A7.
|
|
28464
28551
|
worldDbNames: "world_db_names",
|
|
28465
|
-
worldRoleName: "world_role_name"
|
|
28552
|
+
worldRoleName: "world_role_name",
|
|
28553
|
+
// ADR 045 — per-world Claude Code HOME (multi-account isolation).
|
|
28554
|
+
claudeHome: "claude_home"
|
|
28466
28555
|
};
|
|
28467
28556
|
const jsonColumns = /* @__PURE__ */ new Set(["repos", "readinessChain", "expectedServices", "appPortUrls", "worldDbNames"]);
|
|
28468
28557
|
for (const [key, col] of Object.entries(columnMap)) {
|
|
@@ -28751,12 +28840,12 @@ function register3(server, _ctx, _initError) {
|
|
|
28751
28840
|
registry2.close();
|
|
28752
28841
|
}
|
|
28753
28842
|
try {
|
|
28754
|
-
const { default:
|
|
28843
|
+
const { default: fs52 } = await import("node:fs");
|
|
28755
28844
|
const { default: os31 } = await import("node:os");
|
|
28756
|
-
const { default:
|
|
28757
|
-
const tokenPath =
|
|
28758
|
-
if (
|
|
28759
|
-
const token =
|
|
28845
|
+
const { default: path53 } = await import("node:path");
|
|
28846
|
+
const tokenPath = path53.join(os31.homedir(), ".olam", "host-cp.token");
|
|
28847
|
+
if (fs52.existsSync(tokenPath)) {
|
|
28848
|
+
const token = fs52.readFileSync(tokenPath, "utf-8").trim();
|
|
28760
28849
|
await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
|
|
28761
28850
|
method: "POST",
|
|
28762
28851
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
@@ -29176,10 +29265,10 @@ function extractMcpConfig(claudeJsonPath) {
|
|
|
29176
29265
|
}
|
|
29177
29266
|
return { mcpServers, secrets };
|
|
29178
29267
|
}
|
|
29179
|
-
function readOptional(
|
|
29180
|
-
if (!existsSync6(
|
|
29268
|
+
function readOptional(path53) {
|
|
29269
|
+
if (!existsSync6(path53)) return null;
|
|
29181
29270
|
try {
|
|
29182
|
-
return readFileSync5(
|
|
29271
|
+
return readFileSync5(path53, "utf8");
|
|
29183
29272
|
} catch {
|
|
29184
29273
|
return null;
|
|
29185
29274
|
}
|
|
@@ -29304,7 +29393,7 @@ var realDocker = {
|
|
|
29304
29393
|
}
|
|
29305
29394
|
};
|
|
29306
29395
|
function spawnAsync(cmd, args, opts = {}) {
|
|
29307
|
-
return new Promise((
|
|
29396
|
+
return new Promise((resolve15) => {
|
|
29308
29397
|
const child = spawn(cmd, [...args], {
|
|
29309
29398
|
stdio: ["ignore", "pipe", "pipe"],
|
|
29310
29399
|
signal: opts.signal
|
|
@@ -29318,10 +29407,10 @@ function spawnAsync(cmd, args, opts = {}) {
|
|
|
29318
29407
|
stderr += chunk.toString();
|
|
29319
29408
|
});
|
|
29320
29409
|
child.on("error", (err) => {
|
|
29321
|
-
|
|
29410
|
+
resolve15({ exitCode: -1, stdout, stderr: stderr + err.message });
|
|
29322
29411
|
});
|
|
29323
29412
|
child.on("close", (code) => {
|
|
29324
|
-
|
|
29413
|
+
resolve15({ exitCode: code ?? -1, stdout, stderr });
|
|
29325
29414
|
});
|
|
29326
29415
|
});
|
|
29327
29416
|
}
|
|
@@ -29772,7 +29861,7 @@ var stopAndRemove = async (container) => {
|
|
|
29772
29861
|
|
|
29773
29862
|
// ../adapters/dist/docker/exec.js
|
|
29774
29863
|
import { PassThrough } from "node:stream";
|
|
29775
|
-
var demuxStream = (stream) => new Promise((
|
|
29864
|
+
var demuxStream = (stream) => new Promise((resolve15, reject2) => {
|
|
29776
29865
|
const stdoutChunks = [];
|
|
29777
29866
|
const stderrChunks = [];
|
|
29778
29867
|
const stdout = new PassThrough();
|
|
@@ -29786,7 +29875,7 @@ var demuxStream = (stream) => new Promise((resolve14, reject2) => {
|
|
|
29786
29875
|
stream.pipe(stdout);
|
|
29787
29876
|
}
|
|
29788
29877
|
stream.on("end", () => {
|
|
29789
|
-
|
|
29878
|
+
resolve15({
|
|
29790
29879
|
stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
|
|
29791
29880
|
stderr: Buffer.concat(stderrChunks).toString("utf-8")
|
|
29792
29881
|
});
|
|
@@ -30159,7 +30248,7 @@ var SSHConnectionPool = class {
|
|
|
30159
30248
|
// -----------------------------------------------------------------------
|
|
30160
30249
|
async exec(host, command) {
|
|
30161
30250
|
const client = await this.getConnection(host);
|
|
30162
|
-
return new Promise((
|
|
30251
|
+
return new Promise((resolve15, reject2) => {
|
|
30163
30252
|
client.exec(command, (err, stream) => {
|
|
30164
30253
|
if (err) {
|
|
30165
30254
|
reject2(new Error(`SSH exec failed on ${host}: ${err.message}`));
|
|
@@ -30174,7 +30263,7 @@ var SSHConnectionPool = class {
|
|
|
30174
30263
|
stderr += data.toString();
|
|
30175
30264
|
});
|
|
30176
30265
|
stream.on("close", (code) => {
|
|
30177
|
-
|
|
30266
|
+
resolve15({
|
|
30178
30267
|
exitCode: code ?? 0,
|
|
30179
30268
|
stdout: stdout.trimEnd(),
|
|
30180
30269
|
stderr: stderr.trimEnd()
|
|
@@ -30205,10 +30294,10 @@ var SSHConnectionPool = class {
|
|
|
30205
30294
|
throw new Error(`No SSH configuration found for host: ${host}`);
|
|
30206
30295
|
}
|
|
30207
30296
|
const client = new SSHClient();
|
|
30208
|
-
return new Promise((
|
|
30297
|
+
return new Promise((resolve15, reject2) => {
|
|
30209
30298
|
client.on("ready", () => {
|
|
30210
30299
|
this.connections.set(host, client);
|
|
30211
|
-
|
|
30300
|
+
resolve15(client);
|
|
30212
30301
|
}).on("error", (err) => {
|
|
30213
30302
|
this.connections.delete(host);
|
|
30214
30303
|
reject2(new Error(`SSH connection to ${host} failed: ${err.message}`));
|
|
@@ -30625,8 +30714,8 @@ var CloudflareProvider = class extends ComputeProvider {
|
|
|
30625
30714
|
// -----------------------------------------------------------------------
|
|
30626
30715
|
// Internal fetch helper
|
|
30627
30716
|
// -----------------------------------------------------------------------
|
|
30628
|
-
async request(
|
|
30629
|
-
const url2 = `${this.config.workerUrl}${
|
|
30717
|
+
async request(path53, method, body) {
|
|
30718
|
+
const url2 = `${this.config.workerUrl}${path53}`;
|
|
30630
30719
|
const bearer = await this.config.mintToken();
|
|
30631
30720
|
const headers = {
|
|
30632
30721
|
Authorization: `Bearer ${bearer}`
|
|
@@ -30902,6 +30991,10 @@ function selectComputeProvider(config2, env) {
|
|
|
30902
30991
|
throw new Error(
|
|
30903
30992
|
"Compute provider 'e2b' is not implemented. Use 'docker', 'ssh', or 'cloudflare'."
|
|
30904
30993
|
);
|
|
30994
|
+
case "cloudflare-isolate":
|
|
30995
|
+
throw new Error(
|
|
30996
|
+
"Compute provider 'cloudflare-isolate' is not yet wired for world dispatch. v1 ships the substrate (@olam/worker-runner-cloudflare-isolate) for direct POST /lookup invocation; per-world tier selection arrives in a follow-up PR (see docs/decisions/022-v8-isolate-runtime-tier.md \xA7Consequences)."
|
|
30997
|
+
);
|
|
30905
30998
|
case "docker":
|
|
30906
30999
|
return new DockerProvider(resolveDockerHostOptions());
|
|
30907
31000
|
default: {
|
|
@@ -31188,7 +31281,7 @@ function register6(server, ctx, initError) {
|
|
|
31188
31281
|
}
|
|
31189
31282
|
} catch {
|
|
31190
31283
|
}
|
|
31191
|
-
await new Promise((
|
|
31284
|
+
await new Promise((resolve15) => setTimeout(resolve15, POLL_INTERVAL_MS));
|
|
31192
31285
|
}
|
|
31193
31286
|
}
|
|
31194
31287
|
if (authenticated) {
|
|
@@ -31318,6 +31411,8 @@ function formatAge(createdAt) {
|
|
|
31318
31411
|
// ../mcp-server/src/tools/world-dispatch.ts
|
|
31319
31412
|
var world_dispatch_exports = {};
|
|
31320
31413
|
__export(world_dispatch_exports, {
|
|
31414
|
+
dispatchInputObject: () => dispatchInputObject,
|
|
31415
|
+
dispatchInputSchema: () => dispatchInputSchema,
|
|
31321
31416
|
register: () => register9
|
|
31322
31417
|
});
|
|
31323
31418
|
init_v3();
|
|
@@ -31905,17 +32000,17 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
|
|
|
31905
32000
|
const srcPath = path10.join(src, name);
|
|
31906
32001
|
const destPath = path10.join(dest, name);
|
|
31907
32002
|
if (entry.isSymbolicLink()) {
|
|
31908
|
-
let
|
|
32003
|
+
let stat2;
|
|
31909
32004
|
try {
|
|
31910
|
-
|
|
32005
|
+
stat2 = fs8.statSync(srcPath);
|
|
31911
32006
|
} catch {
|
|
31912
32007
|
continue;
|
|
31913
32008
|
}
|
|
31914
|
-
if (
|
|
32009
|
+
if (stat2.isDirectory()) {
|
|
31915
32010
|
if (SKIP_DIRS_ANYWHERE.has(name))
|
|
31916
32011
|
continue;
|
|
31917
32012
|
copyDirRecursive(srcPath, destPath, depth + 1, skipFiles);
|
|
31918
|
-
} else if (
|
|
32013
|
+
} else if (stat2.isFile()) {
|
|
31919
32014
|
fs8.copyFileSync(srcPath, destPath);
|
|
31920
32015
|
}
|
|
31921
32016
|
} else if (entry.isDirectory()) {
|
|
@@ -32078,9 +32173,9 @@ function buildRepoEnvBundle(repoName, serviceEnv, crossRepoEnv, envOverrides) {
|
|
|
32078
32173
|
const merged = { ...serviceEnv, ...injectables };
|
|
32079
32174
|
return { merged, injectables };
|
|
32080
32175
|
}
|
|
32081
|
-
function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, configCtx) {
|
|
32176
|
+
function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, configCtx, claudeHomeOverride) {
|
|
32082
32177
|
try {
|
|
32083
|
-
copyClaudeConfig(workspacePath,
|
|
32178
|
+
copyClaudeConfig(workspacePath, claudeHomeOverride, configCtx);
|
|
32084
32179
|
} catch {
|
|
32085
32180
|
}
|
|
32086
32181
|
if (configCtx) {
|
|
@@ -32173,19 +32268,278 @@ function applyEnvOverrides(repoPath, overrides) {
|
|
|
32173
32268
|
}
|
|
32174
32269
|
}
|
|
32175
32270
|
|
|
32271
|
+
// ../mcp-server/src/dispatch/goal-verifier.ts
|
|
32272
|
+
init_v3();
|
|
32273
|
+
import * as fs9 from "node:fs/promises";
|
|
32274
|
+
import * as path11 from "node:path";
|
|
32275
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
32276
|
+
var GoalSpecSchema = external_exports.object({
|
|
32277
|
+
type: external_exports.enum([
|
|
32278
|
+
"pr-merged",
|
|
32279
|
+
"pr-green",
|
|
32280
|
+
"file-exists",
|
|
32281
|
+
"test-passes",
|
|
32282
|
+
"comment-posted"
|
|
32283
|
+
]),
|
|
32284
|
+
spec: external_exports.string().min(1).describe(
|
|
32285
|
+
"Type-specific spec: PR number, file path, test name, or comment marker"
|
|
32286
|
+
),
|
|
32287
|
+
timeoutMinutes: external_exports.number().int().min(1).max(720).default(90)
|
|
32288
|
+
}).describe(
|
|
32289
|
+
"Optional structured completion condition; when set, the world loops between turns checking this until met or timeout"
|
|
32290
|
+
);
|
|
32291
|
+
async function defaultExecGh(args) {
|
|
32292
|
+
return new Promise((resolve15) => {
|
|
32293
|
+
const child = spawn2("gh", [...args], {
|
|
32294
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
32295
|
+
});
|
|
32296
|
+
let stdout = "";
|
|
32297
|
+
let stderr = "";
|
|
32298
|
+
child.stdout.on("data", (chunk) => {
|
|
32299
|
+
stdout += chunk.toString("utf8");
|
|
32300
|
+
});
|
|
32301
|
+
child.stderr.on("data", (chunk) => {
|
|
32302
|
+
stderr += chunk.toString("utf8");
|
|
32303
|
+
});
|
|
32304
|
+
child.on("close", (code) => {
|
|
32305
|
+
resolve15({ stdout, stderr, exitCode: code ?? 1 });
|
|
32306
|
+
});
|
|
32307
|
+
child.on("error", (err) => {
|
|
32308
|
+
resolve15({
|
|
32309
|
+
stdout: "",
|
|
32310
|
+
stderr: err instanceof Error ? err.message : String(err),
|
|
32311
|
+
exitCode: 1
|
|
32312
|
+
});
|
|
32313
|
+
});
|
|
32314
|
+
});
|
|
32315
|
+
}
|
|
32316
|
+
async function defaultExecVitest(testNamePattern, cwd) {
|
|
32317
|
+
return new Promise((resolve15) => {
|
|
32318
|
+
const child = spawn2(
|
|
32319
|
+
"npx",
|
|
32320
|
+
[
|
|
32321
|
+
"vitest",
|
|
32322
|
+
"run",
|
|
32323
|
+
"--reporter=basic",
|
|
32324
|
+
"--testNamePattern",
|
|
32325
|
+
testNamePattern
|
|
32326
|
+
],
|
|
32327
|
+
{ cwd, stdio: ["ignore", "pipe", "pipe"] }
|
|
32328
|
+
);
|
|
32329
|
+
child.on("close", (code) => {
|
|
32330
|
+
resolve15({ exitCode: code ?? 1 });
|
|
32331
|
+
});
|
|
32332
|
+
child.on("error", () => {
|
|
32333
|
+
resolve15({ exitCode: 1 });
|
|
32334
|
+
});
|
|
32335
|
+
});
|
|
32336
|
+
}
|
|
32337
|
+
async function verifyGoal(goal, worldId, opts = {}) {
|
|
32338
|
+
const execGh = opts.execGh ?? defaultExecGh;
|
|
32339
|
+
const execVitest = opts.execVitest ?? defaultExecVitest;
|
|
32340
|
+
const statFn = opts.fsStat ?? fs9.stat;
|
|
32341
|
+
const workspaceRoot = opts.workspaceRoot ?? process.cwd();
|
|
32342
|
+
try {
|
|
32343
|
+
switch (goal.type) {
|
|
32344
|
+
case "pr-merged":
|
|
32345
|
+
return await verifyPrMerged(goal.spec, execGh);
|
|
32346
|
+
case "pr-green":
|
|
32347
|
+
return await verifyPrGreen(goal.spec, execGh);
|
|
32348
|
+
case "file-exists":
|
|
32349
|
+
return await verifyFileExists(goal.spec, workspaceRoot, statFn);
|
|
32350
|
+
case "test-passes":
|
|
32351
|
+
return await verifyTestPasses(goal.spec, workspaceRoot, execVitest);
|
|
32352
|
+
case "comment-posted":
|
|
32353
|
+
return await verifyCommentPosted(goal.spec, worldId, execGh);
|
|
32354
|
+
default: {
|
|
32355
|
+
const _exhaustive = goal.type;
|
|
32356
|
+
return {
|
|
32357
|
+
met: false,
|
|
32358
|
+
details: `unknown goal type: ${String(_exhaustive)}`
|
|
32359
|
+
};
|
|
32360
|
+
}
|
|
32361
|
+
}
|
|
32362
|
+
} catch (err) {
|
|
32363
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
32364
|
+
return { met: false, details: `verifier error: ${msg}` };
|
|
32365
|
+
}
|
|
32366
|
+
}
|
|
32367
|
+
async function verifyPrMerged(spec, execGh) {
|
|
32368
|
+
const { stdout, exitCode } = await execGh([
|
|
32369
|
+
"pr",
|
|
32370
|
+
"view",
|
|
32371
|
+
spec,
|
|
32372
|
+
"--json",
|
|
32373
|
+
"state"
|
|
32374
|
+
]);
|
|
32375
|
+
if (exitCode !== 0) {
|
|
32376
|
+
return { met: false, details: `gh pr view failed: exit ${exitCode}` };
|
|
32377
|
+
}
|
|
32378
|
+
let parsed;
|
|
32379
|
+
try {
|
|
32380
|
+
parsed = JSON.parse(stdout);
|
|
32381
|
+
} catch {
|
|
32382
|
+
return { met: false, details: `gh pr view returned non-JSON` };
|
|
32383
|
+
}
|
|
32384
|
+
if (parsed.state === "MERGED") {
|
|
32385
|
+
return { met: true, details: `PR ${spec} merged` };
|
|
32386
|
+
}
|
|
32387
|
+
return {
|
|
32388
|
+
met: false,
|
|
32389
|
+
details: `PR ${spec} state=${parsed.state ?? "unknown"}`
|
|
32390
|
+
};
|
|
32391
|
+
}
|
|
32392
|
+
async function verifyPrGreen(spec, execGh) {
|
|
32393
|
+
const { stdout, exitCode } = await execGh([
|
|
32394
|
+
"pr",
|
|
32395
|
+
"checks",
|
|
32396
|
+
spec,
|
|
32397
|
+
"--json",
|
|
32398
|
+
"name,state"
|
|
32399
|
+
]);
|
|
32400
|
+
if (exitCode !== 0) {
|
|
32401
|
+
return { met: false, details: `gh pr checks failed: exit ${exitCode}` };
|
|
32402
|
+
}
|
|
32403
|
+
let checks;
|
|
32404
|
+
try {
|
|
32405
|
+
checks = JSON.parse(stdout);
|
|
32406
|
+
} catch {
|
|
32407
|
+
return { met: false, details: `gh pr checks returned non-JSON` };
|
|
32408
|
+
}
|
|
32409
|
+
if (!Array.isArray(checks) || checks.length === 0) {
|
|
32410
|
+
return { met: false, details: "no checks reported" };
|
|
32411
|
+
}
|
|
32412
|
+
const PASSING = /* @__PURE__ */ new Set([
|
|
32413
|
+
"SUCCESS",
|
|
32414
|
+
"PASS",
|
|
32415
|
+
"PASSING",
|
|
32416
|
+
"SKIPPING",
|
|
32417
|
+
"SKIPPED",
|
|
32418
|
+
"NEUTRAL"
|
|
32419
|
+
]);
|
|
32420
|
+
const failing = checks.filter(
|
|
32421
|
+
(c) => !PASSING.has(String(c.state ?? "").toUpperCase())
|
|
32422
|
+
);
|
|
32423
|
+
if (failing.length === 0) {
|
|
32424
|
+
return { met: true, details: `all ${checks.length} checks pass/skip` };
|
|
32425
|
+
}
|
|
32426
|
+
const detail = failing.map((c) => `${c.name}=${c.state}`).slice(0, 5).join(", ");
|
|
32427
|
+
return {
|
|
32428
|
+
met: false,
|
|
32429
|
+
details: `${failing.length}/${checks.length} non-passing: ${detail}`
|
|
32430
|
+
};
|
|
32431
|
+
}
|
|
32432
|
+
async function verifyFileExists(spec, workspaceRoot, statFn) {
|
|
32433
|
+
const target = path11.resolve(workspaceRoot, spec);
|
|
32434
|
+
try {
|
|
32435
|
+
await statFn(target);
|
|
32436
|
+
return { met: true, details: `${target} exists` };
|
|
32437
|
+
} catch {
|
|
32438
|
+
return { met: false, details: `${target} not found` };
|
|
32439
|
+
}
|
|
32440
|
+
}
|
|
32441
|
+
async function verifyTestPasses(spec, workspaceRoot, execVitest) {
|
|
32442
|
+
const { exitCode } = await execVitest(spec, workspaceRoot);
|
|
32443
|
+
if (exitCode === 0) {
|
|
32444
|
+
return { met: true, details: `test "${spec}" passed` };
|
|
32445
|
+
}
|
|
32446
|
+
return { met: false, details: `test "${spec}" exit=${exitCode}` };
|
|
32447
|
+
}
|
|
32448
|
+
async function verifyCommentPosted(spec, worldId, execGh) {
|
|
32449
|
+
let prNum;
|
|
32450
|
+
let marker;
|
|
32451
|
+
const colon = spec.indexOf(":");
|
|
32452
|
+
if (colon > 0) {
|
|
32453
|
+
prNum = spec.slice(0, colon);
|
|
32454
|
+
marker = spec.slice(colon + 1);
|
|
32455
|
+
} else {
|
|
32456
|
+
const lookup = await execGh([
|
|
32457
|
+
"pr",
|
|
32458
|
+
"list",
|
|
32459
|
+
"--search",
|
|
32460
|
+
worldId,
|
|
32461
|
+
"--json",
|
|
32462
|
+
"number",
|
|
32463
|
+
"--limit",
|
|
32464
|
+
"1"
|
|
32465
|
+
]);
|
|
32466
|
+
if (lookup.exitCode !== 0) {
|
|
32467
|
+
return {
|
|
32468
|
+
met: false,
|
|
32469
|
+
details: `pr lookup failed for world ${worldId}: exit ${lookup.exitCode}`
|
|
32470
|
+
};
|
|
32471
|
+
}
|
|
32472
|
+
let arr;
|
|
32473
|
+
try {
|
|
32474
|
+
arr = JSON.parse(lookup.stdout);
|
|
32475
|
+
} catch {
|
|
32476
|
+
return { met: false, details: `pr lookup returned non-JSON` };
|
|
32477
|
+
}
|
|
32478
|
+
if (!Array.isArray(arr) || arr.length === 0 || arr[0] === void 0) {
|
|
32479
|
+
return { met: false, details: `no PR found for world ${worldId}` };
|
|
32480
|
+
}
|
|
32481
|
+
prNum = String(arr[0].number);
|
|
32482
|
+
marker = spec;
|
|
32483
|
+
}
|
|
32484
|
+
if (marker.length === 0) {
|
|
32485
|
+
return { met: false, details: "marker is empty" };
|
|
32486
|
+
}
|
|
32487
|
+
const { stdout, exitCode } = await execGh([
|
|
32488
|
+
"pr",
|
|
32489
|
+
"view",
|
|
32490
|
+
prNum,
|
|
32491
|
+
"--json",
|
|
32492
|
+
"comments"
|
|
32493
|
+
]);
|
|
32494
|
+
if (exitCode !== 0) {
|
|
32495
|
+
return {
|
|
32496
|
+
met: false,
|
|
32497
|
+
details: `gh pr view comments failed: exit ${exitCode}`
|
|
32498
|
+
};
|
|
32499
|
+
}
|
|
32500
|
+
let parsed;
|
|
32501
|
+
try {
|
|
32502
|
+
parsed = JSON.parse(stdout);
|
|
32503
|
+
} catch {
|
|
32504
|
+
return { met: false, details: `gh pr view comments returned non-JSON` };
|
|
32505
|
+
}
|
|
32506
|
+
const found = (parsed.comments ?? []).some(
|
|
32507
|
+
(c) => (c.body ?? "").includes(marker)
|
|
32508
|
+
);
|
|
32509
|
+
if (found) {
|
|
32510
|
+
return {
|
|
32511
|
+
met: true,
|
|
32512
|
+
details: `marker "${marker}" found in PR ${prNum} comments`
|
|
32513
|
+
};
|
|
32514
|
+
}
|
|
32515
|
+
return {
|
|
32516
|
+
met: false,
|
|
32517
|
+
details: `marker "${marker}" not found in PR ${prNum} comments`
|
|
32518
|
+
};
|
|
32519
|
+
}
|
|
32520
|
+
|
|
32176
32521
|
// ../mcp-server/src/tools/world-dispatch.ts
|
|
32177
|
-
|
|
32522
|
+
var dispatchInputSchema = {
|
|
32523
|
+
worldId: external_exports.string(),
|
|
32524
|
+
prompt: external_exports.string(),
|
|
32525
|
+
maxTurns: external_exports.number().optional(),
|
|
32526
|
+
mode: external_exports.enum(["deep", "fast", "auto"]).optional().describe(
|
|
32527
|
+
"Execution mode: 'deep' appends ultrathink + sub-agent instructions for complex/generative tasks, 'fast' for simple chores, 'auto' (default) detects from prompt complexity"
|
|
32528
|
+
),
|
|
32529
|
+
goal: GoalSpecSchema.optional().describe(
|
|
32530
|
+
"Optional structured completion condition. When set, the world's dispatch loop checks this condition after each turn until met or the timeout window closes. v1 ships a single post-dispatch check; v2 will close the loop. /goal-mode parity with Claude Code 2.1.139."
|
|
32531
|
+
),
|
|
32532
|
+
escalationTiers: external_exports.array(external_exports.enum(["haiku", "sonnet", "opus"])).optional().default(["sonnet"]).describe(
|
|
32533
|
+
"Ordered model-tier escalation chain for dispatch retries. On each retry, host-cp advances to the next tier instead of repeating the failed model. Default ['sonnet'] = no escalation (current behaviour, no cost surprise). Operators opt in via e.g. ['sonnet','opus'] or ['haiku','sonnet','opus']."
|
|
32534
|
+
)
|
|
32535
|
+
};
|
|
32536
|
+
var dispatchInputObject = external_exports.object(dispatchInputSchema);
|
|
32537
|
+
function register9(server, ctx, initError, deps) {
|
|
32538
|
+
const verify = deps?.verifyGoal ?? verifyGoal;
|
|
32178
32539
|
server.tool(
|
|
32179
32540
|
"olam_dispatch",
|
|
32180
32541
|
"Send a task prompt to a world for autonomous execution.",
|
|
32181
|
-
|
|
32182
|
-
worldId: external_exports.string(),
|
|
32183
|
-
prompt: external_exports.string(),
|
|
32184
|
-
maxTurns: external_exports.number().optional(),
|
|
32185
|
-
mode: external_exports.enum(["deep", "fast", "auto"]).optional().describe(
|
|
32186
|
-
"Execution mode: 'deep' appends ultrathink + sub-agent instructions for complex/generative tasks, 'fast' for simple chores, 'auto' (default) detects from prompt complexity"
|
|
32187
|
-
)
|
|
32188
|
-
},
|
|
32542
|
+
dispatchInputSchema,
|
|
32189
32543
|
async (params) => {
|
|
32190
32544
|
if (!ctx) {
|
|
32191
32545
|
const errorMsg = initError?.message ?? "Olam is not configured. Run /olam:init to set up.";
|
|
@@ -32283,6 +32637,31 @@ function register9(server, ctx, initError) {
|
|
|
32283
32637
|
` full context between dispatches. Watch live in browser terminal`,
|
|
32284
32638
|
` or via: docker exec -it olam-${params.worldId}-devbox tmux attach -t ${claudeSession} -r`
|
|
32285
32639
|
];
|
|
32640
|
+
if (params.goal) {
|
|
32641
|
+
try {
|
|
32642
|
+
const result = await verify(params.goal, params.worldId, {
|
|
32643
|
+
workspaceRoot: worldMeta.workspacePath
|
|
32644
|
+
});
|
|
32645
|
+
lines.push(
|
|
32646
|
+
``,
|
|
32647
|
+
` goal: ${params.goal.type} (${params.goal.spec})`,
|
|
32648
|
+
` goal-met: ${result.met}`,
|
|
32649
|
+
` goal-info: ${result.details}`
|
|
32650
|
+
);
|
|
32651
|
+
} catch (goalErr) {
|
|
32652
|
+
const msg = goalErr instanceof Error ? goalErr.message : String(goalErr);
|
|
32653
|
+
logger.warn("Goal verifier threw unexpectedly", {
|
|
32654
|
+
worldId: params.worldId,
|
|
32655
|
+
error: msg
|
|
32656
|
+
});
|
|
32657
|
+
lines.push(
|
|
32658
|
+
``,
|
|
32659
|
+
` goal: ${params.goal.type} (${params.goal.spec})`,
|
|
32660
|
+
` goal-met: false`,
|
|
32661
|
+
` goal-info: verifier-exception: ${msg}`
|
|
32662
|
+
);
|
|
32663
|
+
}
|
|
32664
|
+
}
|
|
32286
32665
|
return {
|
|
32287
32666
|
content: [{ type: "text", text: lines.join("\n") }]
|
|
32288
32667
|
};
|
|
@@ -32428,7 +32807,7 @@ __export(world_crystallize_exports, {
|
|
|
32428
32807
|
});
|
|
32429
32808
|
init_v3();
|
|
32430
32809
|
import "node:path";
|
|
32431
|
-
import * as
|
|
32810
|
+
import * as fs10 from "node:fs";
|
|
32432
32811
|
|
|
32433
32812
|
// ../core/dist/crystallize/checksum.js
|
|
32434
32813
|
import { createHash as createHash2 } from "node:crypto";
|
|
@@ -32484,7 +32863,7 @@ function register12(server, ctx, initError) {
|
|
|
32484
32863
|
}
|
|
32485
32864
|
try {
|
|
32486
32865
|
const thoughtDbPath = getWorldDbPath(world.workspacePath);
|
|
32487
|
-
if (!
|
|
32866
|
+
if (!fs10.existsSync(thoughtDbPath)) {
|
|
32488
32867
|
return {
|
|
32489
32868
|
content: [{
|
|
32490
32869
|
type: "text",
|
|
@@ -32571,10 +32950,139 @@ __export(world_status_exports, {
|
|
|
32571
32950
|
register: () => register13
|
|
32572
32951
|
});
|
|
32573
32952
|
init_v3();
|
|
32953
|
+
|
|
32954
|
+
// ../skill-runtime/dist/skills/olam-status.js
|
|
32955
|
+
init_v3();
|
|
32956
|
+
|
|
32957
|
+
// ../skill-runtime/dist/define-skill.js
|
|
32958
|
+
var KEBAB_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
32959
|
+
function defineSkill(spec) {
|
|
32960
|
+
if (!KEBAB_RE.test(spec.name)) {
|
|
32961
|
+
throw new Error(`defineSkill: name "${spec.name}" must be kebab-case (lowercase letters, digits, and hyphens only; no leading/trailing/double hyphens).`);
|
|
32962
|
+
}
|
|
32963
|
+
return {
|
|
32964
|
+
asMcpTool() {
|
|
32965
|
+
return {
|
|
32966
|
+
name: spec.name,
|
|
32967
|
+
description: spec.description,
|
|
32968
|
+
inputSchema: spec.inputSchema,
|
|
32969
|
+
async handler(params) {
|
|
32970
|
+
try {
|
|
32971
|
+
const parsed = spec.inputSchema.safeParse(params);
|
|
32972
|
+
if (!parsed.success) {
|
|
32973
|
+
return {
|
|
32974
|
+
content: [
|
|
32975
|
+
{
|
|
32976
|
+
type: "text",
|
|
32977
|
+
text: `Invalid input: ${parsed.error.message}`
|
|
32978
|
+
}
|
|
32979
|
+
],
|
|
32980
|
+
isError: true
|
|
32981
|
+
};
|
|
32982
|
+
}
|
|
32983
|
+
const output = await spec.handler(parsed.data);
|
|
32984
|
+
return {
|
|
32985
|
+
content: [
|
|
32986
|
+
{
|
|
32987
|
+
type: "text",
|
|
32988
|
+
text: typeof output === "string" ? output : JSON.stringify(output)
|
|
32989
|
+
}
|
|
32990
|
+
]
|
|
32991
|
+
};
|
|
32992
|
+
} catch (err) {
|
|
32993
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
32994
|
+
return {
|
|
32995
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
32996
|
+
isError: true
|
|
32997
|
+
};
|
|
32998
|
+
}
|
|
32999
|
+
}
|
|
33000
|
+
};
|
|
33001
|
+
},
|
|
33002
|
+
asHttpHandler() {
|
|
33003
|
+
return async (req, res) => {
|
|
33004
|
+
const parsed = spec.inputSchema.safeParse(req.body);
|
|
33005
|
+
if (!parsed.success) {
|
|
33006
|
+
res.status(400).json({
|
|
33007
|
+
error: "Invalid input",
|
|
33008
|
+
issues: parsed.error.issues
|
|
33009
|
+
});
|
|
33010
|
+
return;
|
|
33011
|
+
}
|
|
33012
|
+
try {
|
|
33013
|
+
const output = await spec.handler(parsed.data);
|
|
33014
|
+
res.status(200).json({ result: output });
|
|
33015
|
+
} catch (err) {
|
|
33016
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
33017
|
+
res.status(500).json({ error: message });
|
|
33018
|
+
}
|
|
33019
|
+
};
|
|
33020
|
+
},
|
|
33021
|
+
toJsonSchema() {
|
|
33022
|
+
return zodToJsonSchema(spec.inputSchema, { target: "openApi3" });
|
|
33023
|
+
}
|
|
33024
|
+
};
|
|
33025
|
+
}
|
|
33026
|
+
|
|
33027
|
+
// ../skill-runtime/dist/skills/olam-status.js
|
|
33028
|
+
var olamStatusInputSchema = external_exports.object({
|
|
33029
|
+
world: external_exports.object({
|
|
33030
|
+
id: external_exports.string(),
|
|
33031
|
+
name: external_exports.string(),
|
|
33032
|
+
status: external_exports.string(),
|
|
33033
|
+
repos: external_exports.array(external_exports.string()),
|
|
33034
|
+
branch: external_exports.string(),
|
|
33035
|
+
computeProvider: external_exports.string(),
|
|
33036
|
+
portOffset: external_exports.number(),
|
|
33037
|
+
workspacePath: external_exports.string(),
|
|
33038
|
+
thoughtCount: external_exports.number(),
|
|
33039
|
+
createdAt: external_exports.string(),
|
|
33040
|
+
updatedAt: external_exports.string(),
|
|
33041
|
+
cost: external_exports.number()
|
|
33042
|
+
})
|
|
33043
|
+
});
|
|
33044
|
+
function formatUptime(createdAt) {
|
|
33045
|
+
const ms = Date.now() - new Date(createdAt).getTime();
|
|
33046
|
+
const seconds = Math.floor(ms / 1e3);
|
|
33047
|
+
const minutes = Math.floor(seconds / 60);
|
|
33048
|
+
const hours = Math.floor(minutes / 60);
|
|
33049
|
+
const days = Math.floor(hours / 24);
|
|
33050
|
+
if (days > 0)
|
|
33051
|
+
return `${days}d ${hours % 24}h ${minutes % 60}m`;
|
|
33052
|
+
if (hours > 0)
|
|
33053
|
+
return `${hours}h ${minutes % 60}m`;
|
|
33054
|
+
return `${minutes}m`;
|
|
33055
|
+
}
|
|
33056
|
+
var olamStatusSkill = defineSkill({
|
|
33057
|
+
name: "olam-status",
|
|
33058
|
+
description: "Get detailed status information for a specific world.",
|
|
33059
|
+
inputSchema: olamStatusInputSchema,
|
|
33060
|
+
handler: ({ world }) => {
|
|
33061
|
+
const uptime = formatUptime(world.createdAt);
|
|
33062
|
+
const lines = [
|
|
33063
|
+
`World: ${world.name} (${world.id})`,
|
|
33064
|
+
``,
|
|
33065
|
+
` Status: ${world.status}`,
|
|
33066
|
+
` Repos: ${world.repos.join(", ")}`,
|
|
33067
|
+
` Branch: ${world.branch}`,
|
|
33068
|
+
` Provider: ${world.computeProvider}`,
|
|
33069
|
+
` Port Offset: ${world.portOffset}`,
|
|
33070
|
+
` Workspace: ${world.workspacePath}`,
|
|
33071
|
+
` Total Cost: $${world.cost.toFixed(4)}`,
|
|
33072
|
+
` Thought Count: ${world.thoughtCount}`,
|
|
33073
|
+
` Created: ${world.createdAt}`,
|
|
33074
|
+
` Uptime: ${uptime}`,
|
|
33075
|
+
` Last Updated: ${world.updatedAt}`
|
|
33076
|
+
];
|
|
33077
|
+
return lines.join("\n");
|
|
33078
|
+
}
|
|
33079
|
+
});
|
|
33080
|
+
|
|
33081
|
+
// ../mcp-server/src/tools/world-status.ts
|
|
32574
33082
|
function register13(server, ctx, initError) {
|
|
32575
33083
|
server.tool(
|
|
32576
33084
|
"olam_status",
|
|
32577
|
-
|
|
33085
|
+
olamStatusSkill.asMcpTool().description,
|
|
32578
33086
|
{
|
|
32579
33087
|
worldId: external_exports.string()
|
|
32580
33088
|
},
|
|
@@ -32594,26 +33102,23 @@ function register13(server, ctx, initError) {
|
|
|
32594
33102
|
isError: true
|
|
32595
33103
|
};
|
|
32596
33104
|
}
|
|
32597
|
-
const uptime = formatUptime(world.createdAt);
|
|
32598
33105
|
const cost = ctx.costTracker.getWorldCost(params.worldId);
|
|
32599
|
-
|
|
32600
|
-
|
|
32601
|
-
|
|
32602
|
-
|
|
32603
|
-
|
|
32604
|
-
|
|
32605
|
-
|
|
32606
|
-
|
|
32607
|
-
|
|
32608
|
-
|
|
32609
|
-
|
|
32610
|
-
|
|
32611
|
-
|
|
32612
|
-
|
|
32613
|
-
|
|
32614
|
-
|
|
32615
|
-
content: [{ type: "text", text: lines.join("\n") }]
|
|
32616
|
-
};
|
|
33106
|
+
return olamStatusSkill.asMcpTool().handler({
|
|
33107
|
+
world: {
|
|
33108
|
+
id: world.id,
|
|
33109
|
+
name: world.name,
|
|
33110
|
+
status: world.status,
|
|
33111
|
+
repos: [...world.repos],
|
|
33112
|
+
branch: world.branch,
|
|
33113
|
+
computeProvider: world.computeProvider,
|
|
33114
|
+
portOffset: world.portOffset,
|
|
33115
|
+
workspacePath: world.workspacePath,
|
|
33116
|
+
thoughtCount: world.thoughtCount,
|
|
33117
|
+
createdAt: world.createdAt,
|
|
33118
|
+
updatedAt: world.updatedAt,
|
|
33119
|
+
cost
|
|
33120
|
+
}
|
|
33121
|
+
});
|
|
32617
33122
|
} catch (err) {
|
|
32618
33123
|
const message = err instanceof Error ? err.message : String(err);
|
|
32619
33124
|
return {
|
|
@@ -32624,16 +33129,6 @@ function register13(server, ctx, initError) {
|
|
|
32624
33129
|
}
|
|
32625
33130
|
);
|
|
32626
33131
|
}
|
|
32627
|
-
function formatUptime(createdAt) {
|
|
32628
|
-
const ms = Date.now() - new Date(createdAt).getTime();
|
|
32629
|
-
const seconds = Math.floor(ms / 1e3);
|
|
32630
|
-
const minutes = Math.floor(seconds / 60);
|
|
32631
|
-
const hours = Math.floor(minutes / 60);
|
|
32632
|
-
const days = Math.floor(hours / 24);
|
|
32633
|
-
if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`;
|
|
32634
|
-
if (hours > 0) return `${hours}h ${minutes % 60}m`;
|
|
32635
|
-
return `${minutes}m`;
|
|
32636
|
-
}
|
|
32637
33132
|
|
|
32638
33133
|
// ../mcp-server/src/tools/control-plane.ts
|
|
32639
33134
|
var control_plane_exports = {};
|
|
@@ -33077,10 +33572,10 @@ async function writeManifest(args) {
|
|
|
33077
33572
|
capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
33078
33573
|
shots: entries
|
|
33079
33574
|
};
|
|
33080
|
-
const
|
|
33081
|
-
await writeFile(
|
|
33575
|
+
const path53 = join13(args.outDir, "manifest.json");
|
|
33576
|
+
await writeFile(path53, `${JSON.stringify(manifest, null, 2)}
|
|
33082
33577
|
`, "utf8");
|
|
33083
|
-
return { path:
|
|
33578
|
+
return { path: path53, manifest };
|
|
33084
33579
|
}
|
|
33085
33580
|
|
|
33086
33581
|
// ../mcp-server/src/tools/_capture/proxy.ts
|
|
@@ -33334,9 +33829,9 @@ async function startProxy(opts) {
|
|
|
33334
33829
|
const liveCompiled = verified.allowedPaths.map(compileGlob);
|
|
33335
33830
|
const target = parseRequestTarget(req);
|
|
33336
33831
|
if (!target) return httpReject(400, "invalid_target");
|
|
33337
|
-
const
|
|
33338
|
-
if (!liveCompiled.some((re) => re.test(
|
|
33339
|
-
return httpReject(403, "outside_allow_list", { path:
|
|
33832
|
+
const path53 = target.pathname;
|
|
33833
|
+
if (!liveCompiled.some((re) => re.test(path53))) {
|
|
33834
|
+
return httpReject(403, "outside_allow_list", { path: path53 });
|
|
33340
33835
|
}
|
|
33341
33836
|
const headerWorld = req.headers[WORLD_ASSERT_HEADER];
|
|
33342
33837
|
const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
|
|
@@ -33440,15 +33935,15 @@ ${JSON.stringify({ error: reason })}`
|
|
|
33440
33935
|
unlinkSync2(udsPath);
|
|
33441
33936
|
} catch {
|
|
33442
33937
|
}
|
|
33443
|
-
await new Promise((
|
|
33444
|
-
server.listen(udsPath, () =>
|
|
33938
|
+
await new Promise((resolve15, reject2) => {
|
|
33939
|
+
server.listen(udsPath, () => resolve15());
|
|
33445
33940
|
server.once("error", reject2);
|
|
33446
33941
|
});
|
|
33447
33942
|
chmodSync3(udsPath, 384);
|
|
33448
33943
|
port2 = 0;
|
|
33449
33944
|
} else {
|
|
33450
|
-
await new Promise((
|
|
33451
|
-
server.listen(opts.port ?? 0, "127.0.0.1", () =>
|
|
33945
|
+
await new Promise((resolve15, reject2) => {
|
|
33946
|
+
server.listen(opts.port ?? 0, "127.0.0.1", () => resolve15());
|
|
33452
33947
|
server.once("error", reject2);
|
|
33453
33948
|
});
|
|
33454
33949
|
const addr = server.address();
|
|
@@ -33464,10 +33959,10 @@ ${JSON.stringify({ error: reason })}`
|
|
|
33464
33959
|
} catch {
|
|
33465
33960
|
}
|
|
33466
33961
|
await Promise.race([
|
|
33467
|
-
new Promise((
|
|
33468
|
-
server.close((err) => err ? reject2(err) :
|
|
33962
|
+
new Promise((resolve15, reject2) => {
|
|
33963
|
+
server.close((err) => err ? reject2(err) : resolve15());
|
|
33469
33964
|
}),
|
|
33470
|
-
new Promise((
|
|
33965
|
+
new Promise((resolve15) => setTimeout(resolve15, 5e3))
|
|
33471
33966
|
]);
|
|
33472
33967
|
if (udsPath) {
|
|
33473
33968
|
try {
|
|
@@ -33497,9 +33992,9 @@ function ensureUdsParentDirSafe(udsPath) {
|
|
|
33497
33992
|
`uds_parent_path_invalid: bindUdsPath "${udsPath}" has no manageable parent directory`
|
|
33498
33993
|
);
|
|
33499
33994
|
}
|
|
33500
|
-
let
|
|
33995
|
+
let stat2 = null;
|
|
33501
33996
|
try {
|
|
33502
|
-
|
|
33997
|
+
stat2 = statSync3(parent);
|
|
33503
33998
|
} catch (err) {
|
|
33504
33999
|
if (err.code !== "ENOENT") {
|
|
33505
34000
|
throw new Error(
|
|
@@ -33507,25 +34002,25 @@ function ensureUdsParentDirSafe(udsPath) {
|
|
|
33507
34002
|
);
|
|
33508
34003
|
}
|
|
33509
34004
|
}
|
|
33510
|
-
if (!
|
|
34005
|
+
if (!stat2) {
|
|
33511
34006
|
mkdirSync7(parent, { recursive: true, mode: 448 });
|
|
33512
34007
|
return;
|
|
33513
34008
|
}
|
|
33514
|
-
if (!
|
|
34009
|
+
if (!stat2.isDirectory()) {
|
|
33515
34010
|
throw new Error(
|
|
33516
34011
|
`uds_parent_dir_unsafe: "${parent}" exists but is not a directory`
|
|
33517
34012
|
);
|
|
33518
34013
|
}
|
|
33519
|
-
const mode =
|
|
34014
|
+
const mode = stat2.mode & 511;
|
|
33520
34015
|
if (process.platform !== "win32" && mode !== 448) {
|
|
33521
34016
|
throw new Error(
|
|
33522
34017
|
`uds_parent_dir_unsafe: "${parent}" mode is 0o${mode.toString(8)}, expected 0o700 (other local UIDs could traverse the dir and access the socket)`
|
|
33523
34018
|
);
|
|
33524
34019
|
}
|
|
33525
34020
|
const me = userInfo().uid;
|
|
33526
|
-
if (process.platform !== "win32" &&
|
|
34021
|
+
if (process.platform !== "win32" && stat2.uid !== me) {
|
|
33527
34022
|
throw new Error(
|
|
33528
|
-
`uds_parent_dir_unsafe: "${parent}" owned by uid=${
|
|
34023
|
+
`uds_parent_dir_unsafe: "${parent}" owned by uid=${stat2.uid}, current process uid=${me}`
|
|
33529
34024
|
);
|
|
33530
34025
|
}
|
|
33531
34026
|
}
|
|
@@ -33799,10 +34294,10 @@ async function acquireLaunchSlot() {
|
|
|
33799
34294
|
_inFlightLaunches++;
|
|
33800
34295
|
return releaseLaunchSlot;
|
|
33801
34296
|
}
|
|
33802
|
-
return new Promise((
|
|
34297
|
+
return new Promise((resolve15) => {
|
|
33803
34298
|
_launchQueue.push(() => {
|
|
33804
34299
|
_inFlightLaunches++;
|
|
33805
|
-
|
|
34300
|
+
resolve15(releaseLaunchSlot);
|
|
33806
34301
|
});
|
|
33807
34302
|
});
|
|
33808
34303
|
}
|
|
@@ -34115,14 +34610,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
|
|
|
34115
34610
|
await page.waitForTimeout(shot.afterLoadMs);
|
|
34116
34611
|
}
|
|
34117
34612
|
const ext = format === "jpeg" ? "jpg" : "png";
|
|
34118
|
-
const
|
|
34613
|
+
const path53 = join14(outDir, `${shot.name}.${ext}`);
|
|
34119
34614
|
await page.screenshot({
|
|
34120
|
-
path:
|
|
34615
|
+
path: path53,
|
|
34121
34616
|
type: format,
|
|
34122
34617
|
...format === "jpeg" ? { quality: jpegQuality } : {},
|
|
34123
34618
|
fullPage: false
|
|
34124
34619
|
});
|
|
34125
|
-
return { name: shot.name, path:
|
|
34620
|
+
return { name: shot.name, path: path53, urlRedacted: redactUrl(shot.url), viewport };
|
|
34126
34621
|
} finally {
|
|
34127
34622
|
await context.close();
|
|
34128
34623
|
}
|
|
@@ -34566,12 +35061,12 @@ function openUrl(url2) {
|
|
|
34566
35061
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
34567
35062
|
async function readHostCpToken2() {
|
|
34568
35063
|
try {
|
|
34569
|
-
const { default:
|
|
35064
|
+
const { default: fs52 } = await import("node:fs");
|
|
34570
35065
|
const { default: os31 } = await import("node:os");
|
|
34571
|
-
const { default:
|
|
34572
|
-
const tp =
|
|
34573
|
-
if (!
|
|
34574
|
-
return { token:
|
|
35066
|
+
const { default: path53 } = await import("node:path");
|
|
35067
|
+
const tp = path53.join(os31.homedir(), ".olam", "host-cp.token");
|
|
35068
|
+
if (!fs52.existsSync(tp)) return { token: null };
|
|
35069
|
+
return { token: fs52.readFileSync(tp, "utf-8").trim() };
|
|
34575
35070
|
} catch {
|
|
34576
35071
|
return { token: null };
|
|
34577
35072
|
}
|
|
@@ -34831,9 +35326,9 @@ function register22(server, _ctx, _initError) {
|
|
|
34831
35326
|
description: external_exports.string().optional().describe("Optional human-readable description."),
|
|
34832
35327
|
defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
|
|
34833
35328
|
},
|
|
34834
|
-
async ({ name, path:
|
|
35329
|
+
async ({ name, path: path53, description, defaultBranch }) => {
|
|
34835
35330
|
try {
|
|
34836
|
-
const entry = addRepo({ name, path:
|
|
35331
|
+
const entry = addRepo({ name, path: path53, description, defaultBranch });
|
|
34837
35332
|
return {
|
|
34838
35333
|
content: [{
|
|
34839
35334
|
type: "text",
|
|
@@ -34874,9 +35369,9 @@ function register22(server, _ctx, _initError) {
|
|
|
34874
35369
|
description: external_exports.string().optional().describe("New description."),
|
|
34875
35370
|
defaultBranch: external_exports.string().optional().describe("New default branch.")
|
|
34876
35371
|
},
|
|
34877
|
-
async ({ name, path:
|
|
35372
|
+
async ({ name, path: path53, description, defaultBranch }) => {
|
|
34878
35373
|
try {
|
|
34879
|
-
const entry = updateRepo(name, { path:
|
|
35374
|
+
const entry = updateRepo(name, { path: path53, description, defaultBranch });
|
|
34880
35375
|
return {
|
|
34881
35376
|
content: [{
|
|
34882
35377
|
type: "text",
|
|
@@ -34897,15 +35392,15 @@ __export(process_port_exports, {
|
|
|
34897
35392
|
resolveHostCpToken: () => resolveHostCpToken
|
|
34898
35393
|
});
|
|
34899
35394
|
init_v3();
|
|
34900
|
-
import
|
|
35395
|
+
import fs35 from "node:fs";
|
|
34901
35396
|
import os20 from "node:os";
|
|
34902
|
-
import
|
|
35397
|
+
import path34 from "node:path";
|
|
34903
35398
|
var HOST_CP_BASE = "http://127.0.0.1:19000";
|
|
34904
35399
|
function resolveHostCpToken() {
|
|
34905
35400
|
const envToken = process.env["OLAM_HOST_CP_TOKEN"];
|
|
34906
35401
|
if (envToken) return envToken;
|
|
34907
|
-
const tokenPath =
|
|
34908
|
-
if (
|
|
35402
|
+
const tokenPath = path34.join(os20.homedir(), ".olam", "host-cp.token");
|
|
35403
|
+
if (fs35.existsSync(tokenPath)) return fs35.readFileSync(tokenPath, "utf-8").trim();
|
|
34909
35404
|
return null;
|
|
34910
35405
|
}
|
|
34911
35406
|
function tokenMissingError() {
|
|
@@ -35337,8 +35832,8 @@ __export(skills_exports, {
|
|
|
35337
35832
|
});
|
|
35338
35833
|
init_v3();
|
|
35339
35834
|
init_skill_sources();
|
|
35340
|
-
import * as
|
|
35341
|
-
import * as
|
|
35835
|
+
import * as fs36 from "node:fs";
|
|
35836
|
+
import * as path35 from "node:path";
|
|
35342
35837
|
function asMessage8(err) {
|
|
35343
35838
|
return err instanceof Error ? err.message : String(err);
|
|
35344
35839
|
}
|
|
@@ -35361,14 +35856,14 @@ function listDeployed() {
|
|
|
35361
35856
|
);
|
|
35362
35857
|
const entries = [];
|
|
35363
35858
|
for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
|
|
35364
|
-
const bucketDir =
|
|
35365
|
-
if (!
|
|
35366
|
-
for (const name of
|
|
35367
|
-
const full =
|
|
35859
|
+
const bucketDir = path35.join(dir, bucket);
|
|
35860
|
+
if (!fs36.existsSync(bucketDir)) continue;
|
|
35861
|
+
for (const name of fs36.readdirSync(bucketDir)) {
|
|
35862
|
+
const full = path35.join(bucketDir, name);
|
|
35368
35863
|
try {
|
|
35369
|
-
const
|
|
35370
|
-
if (!
|
|
35371
|
-
const target =
|
|
35864
|
+
const stat2 = fs36.lstatSync(full);
|
|
35865
|
+
if (!stat2.isSymbolicLink()) continue;
|
|
35866
|
+
const target = fs36.readlinkSync(full);
|
|
35372
35867
|
let sourceId;
|
|
35373
35868
|
for (const [clonePath, id] of sourcePaths.entries()) {
|
|
35374
35869
|
if (target.startsWith(clonePath)) {
|
|
@@ -35454,13 +35949,13 @@ __export(skills_search_exports, {
|
|
|
35454
35949
|
register: () => register27
|
|
35455
35950
|
});
|
|
35456
35951
|
init_v3();
|
|
35457
|
-
import * as
|
|
35952
|
+
import * as path37 from "node:path";
|
|
35458
35953
|
import * as os22 from "node:os";
|
|
35459
35954
|
|
|
35460
35955
|
// ../mcp-server/src/lib/skills-index.mjs
|
|
35461
35956
|
import { createRequire as createRequire4 } from "node:module";
|
|
35462
|
-
import * as
|
|
35463
|
-
import * as
|
|
35957
|
+
import * as fs37 from "node:fs";
|
|
35958
|
+
import * as path36 from "node:path";
|
|
35464
35959
|
import * as os21 from "node:os";
|
|
35465
35960
|
var VECTOR_DIM = 256;
|
|
35466
35961
|
var SCHEMA_VERSION3 = "1";
|
|
@@ -35550,7 +36045,7 @@ function bufferToVector(buf) {
|
|
|
35550
36045
|
return vec;
|
|
35551
36046
|
}
|
|
35552
36047
|
function openIndex(dbPath) {
|
|
35553
|
-
if (!
|
|
36048
|
+
if (!fs37.existsSync(dbPath)) {
|
|
35554
36049
|
throw new Error(
|
|
35555
36050
|
`skills index not found at ${dbPath}. Run \`node scripts/skills-index-build.mjs --out ${dbPath}\` first.`
|
|
35556
36051
|
);
|
|
@@ -35592,14 +36087,14 @@ function searchIndex(dbPath, query, k = 5) {
|
|
|
35592
36087
|
db.close();
|
|
35593
36088
|
}
|
|
35594
36089
|
}
|
|
35595
|
-
var DEFAULT_DB_PATH =
|
|
35596
|
-
var DEFAULT_SOURCE_DIR =
|
|
36090
|
+
var DEFAULT_DB_PATH = path36.join(os21.homedir(), ".olam", "skills.vec.db");
|
|
36091
|
+
var DEFAULT_SOURCE_DIR = path36.join(os21.homedir(), ".claude", "skills");
|
|
35597
36092
|
|
|
35598
36093
|
// ../mcp-server/src/tools/skills-search.ts
|
|
35599
36094
|
function defaultDbPath() {
|
|
35600
36095
|
const override = process.env["SKILLS_INDEX_PATH"];
|
|
35601
36096
|
if (override) return override;
|
|
35602
|
-
return
|
|
36097
|
+
return path37.join(os22.homedir(), ".olam", "skills.vec.db");
|
|
35603
36098
|
}
|
|
35604
36099
|
function asMessage9(err) {
|
|
35605
36100
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -35650,8 +36145,8 @@ function port() {
|
|
|
35650
36145
|
const n = Number.parseInt(env, 10);
|
|
35651
36146
|
return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
|
|
35652
36147
|
}
|
|
35653
|
-
function url(
|
|
35654
|
-
return `http://127.0.0.1:${port()}${
|
|
36148
|
+
function url(path53) {
|
|
36149
|
+
return `http://127.0.0.1:${port()}${path53}`;
|
|
35655
36150
|
}
|
|
35656
36151
|
function kgServiceHealthUrl() {
|
|
35657
36152
|
return url("/health");
|
|
@@ -35850,8 +36345,8 @@ __export(kg_install_hook_exports, {
|
|
|
35850
36345
|
});
|
|
35851
36346
|
init_v3();
|
|
35852
36347
|
init_merge_settings();
|
|
35853
|
-
import * as
|
|
35854
|
-
import * as
|
|
36348
|
+
import * as fs38 from "node:fs";
|
|
36349
|
+
import * as path38 from "node:path";
|
|
35855
36350
|
import * as os23 from "node:os";
|
|
35856
36351
|
|
|
35857
36352
|
// ../core/dist/kg/hook-template.js
|
|
@@ -35902,10 +36397,10 @@ function buildHookMatcherEntry(opts) {
|
|
|
35902
36397
|
// ../mcp-server/src/tools/kg-install-hook.ts
|
|
35903
36398
|
function settingsPathFor2(scope, projectPath) {
|
|
35904
36399
|
if (scope === "user") {
|
|
35905
|
-
return
|
|
36400
|
+
return path38.join(os23.homedir(), ".claude", "settings.json");
|
|
35906
36401
|
}
|
|
35907
36402
|
const root = projectPath ?? process.cwd();
|
|
35908
|
-
return
|
|
36403
|
+
return path38.join(root, ".claude", "settings.json");
|
|
35909
36404
|
}
|
|
35910
36405
|
function register30(server, _ctx, _initError) {
|
|
35911
36406
|
server.tool(
|
|
@@ -35919,12 +36414,12 @@ function register30(server, _ctx, _initError) {
|
|
|
35919
36414
|
const scope = params.scope === "user" ? "user" : "project";
|
|
35920
36415
|
const filePath = settingsPathFor2(scope, params.projectPath);
|
|
35921
36416
|
try {
|
|
35922
|
-
|
|
36417
|
+
fs38.mkdirSync(path38.dirname(filePath), { recursive: true });
|
|
35923
36418
|
let backupPath = null;
|
|
35924
|
-
if (
|
|
36419
|
+
if (fs38.existsSync(filePath)) {
|
|
35925
36420
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
35926
36421
|
backupPath = `${filePath}.olam-bak.${ts}`;
|
|
35927
|
-
|
|
36422
|
+
fs38.copyFileSync(filePath, backupPath);
|
|
35928
36423
|
}
|
|
35929
36424
|
const result = mergeHomeSettingsJson(filePath, {
|
|
35930
36425
|
ensureHook: {
|
|
@@ -35935,7 +36430,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35935
36430
|
});
|
|
35936
36431
|
if (result.status === "already-present" && backupPath) {
|
|
35937
36432
|
try {
|
|
35938
|
-
|
|
36433
|
+
fs38.unlinkSync(backupPath);
|
|
35939
36434
|
} catch {
|
|
35940
36435
|
}
|
|
35941
36436
|
}
|
|
@@ -35979,15 +36474,15 @@ __export(kg_uninstall_hook_exports, {
|
|
|
35979
36474
|
register: () => register31
|
|
35980
36475
|
});
|
|
35981
36476
|
init_v3();
|
|
35982
|
-
import * as
|
|
35983
|
-
import * as
|
|
36477
|
+
import * as fs39 from "node:fs";
|
|
36478
|
+
import * as path39 from "node:path";
|
|
35984
36479
|
import * as os24 from "node:os";
|
|
35985
36480
|
function settingsPathFor3(scope, projectPath) {
|
|
35986
36481
|
if (scope === "user") {
|
|
35987
|
-
return
|
|
36482
|
+
return path39.join(os24.homedir(), ".claude", "settings.json");
|
|
35988
36483
|
}
|
|
35989
36484
|
const root = projectPath ?? process.cwd();
|
|
35990
|
-
return
|
|
36485
|
+
return path39.join(root, ".claude", "settings.json");
|
|
35991
36486
|
}
|
|
35992
36487
|
function dropSentinel(matchers) {
|
|
35993
36488
|
let changed = false;
|
|
@@ -36021,7 +36516,7 @@ function register31(server, _ctx, _initError) {
|
|
|
36021
36516
|
const scope = params.scope === "user" ? "user" : "project";
|
|
36022
36517
|
const filePath = settingsPathFor3(scope, params.projectPath);
|
|
36023
36518
|
try {
|
|
36024
|
-
if (!
|
|
36519
|
+
if (!fs39.existsSync(filePath)) {
|
|
36025
36520
|
return {
|
|
36026
36521
|
content: [
|
|
36027
36522
|
{
|
|
@@ -36035,7 +36530,7 @@ function register31(server, _ctx, _initError) {
|
|
|
36035
36530
|
]
|
|
36036
36531
|
};
|
|
36037
36532
|
}
|
|
36038
|
-
const raw =
|
|
36533
|
+
const raw = fs39.readFileSync(filePath, "utf-8");
|
|
36039
36534
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
36040
36535
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
36041
36536
|
if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
|
|
@@ -36070,7 +36565,7 @@ function register31(server, _ctx, _initError) {
|
|
|
36070
36565
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
36071
36566
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
36072
36567
|
try {
|
|
36073
|
-
|
|
36568
|
+
fs39.copyFileSync(filePath, backupPath);
|
|
36074
36569
|
} catch {
|
|
36075
36570
|
}
|
|
36076
36571
|
const next = {
|
|
@@ -36082,7 +36577,7 @@ function register31(server, _ctx, _initError) {
|
|
|
36082
36577
|
if (otherStages.length === 0) delete next.hooks;
|
|
36083
36578
|
else delete next.hooks.PreToolUse;
|
|
36084
36579
|
}
|
|
36085
|
-
|
|
36580
|
+
fs39.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
36086
36581
|
return {
|
|
36087
36582
|
content: [
|
|
36088
36583
|
{
|
|
@@ -36151,17 +36646,23 @@ var toolModules = [
|
|
|
36151
36646
|
kg_uninstall_hook_exports
|
|
36152
36647
|
];
|
|
36153
36648
|
function registerAllTools(server, ctx, initError) {
|
|
36154
|
-
|
|
36155
|
-
|
|
36649
|
+
const filterContext = getToolFilterContextFromEnv();
|
|
36650
|
+
const { server: filtered, finalize: finalize2 } = withFilteredTools(server, filterContext);
|
|
36651
|
+
try {
|
|
36652
|
+
for (const mod of toolModules) {
|
|
36653
|
+
mod.register(filtered, ctx, initError);
|
|
36654
|
+
}
|
|
36655
|
+
} finally {
|
|
36656
|
+
finalize2();
|
|
36156
36657
|
}
|
|
36157
36658
|
}
|
|
36158
36659
|
|
|
36159
36660
|
// ../mcp-server/src/resources/chunks.ts
|
|
36160
|
-
import
|
|
36661
|
+
import fs40 from "node:fs";
|
|
36161
36662
|
import os25 from "node:os";
|
|
36162
|
-
import
|
|
36663
|
+
import path40 from "node:path";
|
|
36163
36664
|
var DEFAULT_HOST_CP_URL = "http://127.0.0.1:19000";
|
|
36164
|
-
var DEFAULT_PLAN_CHAT_SECRET_PATH =
|
|
36665
|
+
var DEFAULT_PLAN_CHAT_SECRET_PATH = path40.join(
|
|
36165
36666
|
os25.homedir(),
|
|
36166
36667
|
".olam",
|
|
36167
36668
|
"plan-chat-secret"
|
|
@@ -36176,7 +36677,7 @@ function loadBearer(bearerOpt, secretPath) {
|
|
|
36176
36677
|
const envBearer = process.env.OLAM_PLAN_CHAT_BEARER?.trim();
|
|
36177
36678
|
if (envBearer && envBearer.length > 0) return envBearer;
|
|
36178
36679
|
try {
|
|
36179
|
-
const onDisk =
|
|
36680
|
+
const onDisk = fs40.readFileSync(secretPath, "utf8").trim();
|
|
36180
36681
|
return onDisk.length > 0 ? onDisk : null;
|
|
36181
36682
|
} catch (err) {
|
|
36182
36683
|
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
|
|
@@ -36500,9 +37001,9 @@ init_loader();
|
|
|
36500
37001
|
// ../core/dist/world/manager.js
|
|
36501
37002
|
import * as crypto8 from "node:crypto";
|
|
36502
37003
|
import { execSync as execSync5, spawnSync as spawnSync4 } from "node:child_process";
|
|
36503
|
-
import * as
|
|
37004
|
+
import * as fs49 from "node:fs";
|
|
36504
37005
|
import * as os29 from "node:os";
|
|
36505
|
-
import * as
|
|
37006
|
+
import * as path50 from "node:path";
|
|
36506
37007
|
|
|
36507
37008
|
// ../core/dist/world/state.js
|
|
36508
37009
|
var VALID_TRANSITIONS = {
|
|
@@ -36598,8 +37099,8 @@ function resolveDevboxImage(config2, tag) {
|
|
|
36598
37099
|
|
|
36599
37100
|
// ../core/dist/world/worktree.js
|
|
36600
37101
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
36601
|
-
import * as
|
|
36602
|
-
import * as
|
|
37102
|
+
import * as fs41 from "node:fs";
|
|
37103
|
+
import * as path41 from "node:path";
|
|
36603
37104
|
function resolveGitDir(repo) {
|
|
36604
37105
|
if (repo.path) {
|
|
36605
37106
|
return repo.path;
|
|
@@ -36609,11 +37110,11 @@ function resolveGitDir(repo) {
|
|
|
36609
37110
|
async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
36610
37111
|
const created = [];
|
|
36611
37112
|
for (const repo of repos) {
|
|
36612
|
-
const worktreePath =
|
|
37113
|
+
const worktreePath = path41.join(workspacePath, repo.name);
|
|
36613
37114
|
const gitDir = resolveGitDir(repo);
|
|
36614
37115
|
const branchName = branch || `olam/${worldId}`;
|
|
36615
37116
|
try {
|
|
36616
|
-
|
|
37117
|
+
fs41.mkdirSync(path41.dirname(worktreePath), { recursive: true });
|
|
36617
37118
|
execFileSync4("git", ["worktree", "add", worktreePath, "-b", branchName], {
|
|
36618
37119
|
cwd: gitDir,
|
|
36619
37120
|
stdio: "pipe"
|
|
@@ -36646,7 +37147,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
|
36646
37147
|
}
|
|
36647
37148
|
async function removeWorktrees(repos, workspacePath) {
|
|
36648
37149
|
for (const repo of repos) {
|
|
36649
|
-
const worktreePath =
|
|
37150
|
+
const worktreePath = path41.join(workspacePath, repo.name);
|
|
36650
37151
|
let gitDir;
|
|
36651
37152
|
try {
|
|
36652
37153
|
gitDir = resolveGitDir(repo);
|
|
@@ -36721,12 +37222,12 @@ function removeBranch(repo, branch) {
|
|
|
36721
37222
|
|
|
36722
37223
|
// ../core/dist/world/kg-overlay.js
|
|
36723
37224
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
36724
|
-
import * as
|
|
36725
|
-
import * as
|
|
37225
|
+
import * as fs42 from "node:fs";
|
|
37226
|
+
import * as path42 from "node:path";
|
|
36726
37227
|
|
|
36727
37228
|
// ../core/dist/kg/storage-paths.js
|
|
36728
37229
|
import { homedir as homedir24 } from "node:os";
|
|
36729
|
-
import { join as join41, resolve as
|
|
37230
|
+
import { join as join41, resolve as resolve10 } from "node:path";
|
|
36730
37231
|
|
|
36731
37232
|
// ../core/dist/world/workspace-name.js
|
|
36732
37233
|
var InvalidWorkspaceNameError = class extends Error {
|
|
@@ -36755,17 +37256,17 @@ function kgRoot() {
|
|
|
36755
37256
|
function worldsRoot() {
|
|
36756
37257
|
return join41(olamHome(), "worlds");
|
|
36757
37258
|
}
|
|
36758
|
-
function assertWithinPrefix(
|
|
36759
|
-
if (!
|
|
36760
|
-
throw new Error(`${label} escape: ${
|
|
37259
|
+
function assertWithinPrefix(path53, prefix, label) {
|
|
37260
|
+
if (!path53.startsWith(prefix + "/")) {
|
|
37261
|
+
throw new Error(`${label} escape: ${path53} not under ${prefix}/`);
|
|
36761
37262
|
}
|
|
36762
37263
|
}
|
|
36763
37264
|
function kgPristinePath(workspace) {
|
|
36764
37265
|
validateWorkspaceName(workspace);
|
|
36765
37266
|
const root = kgRoot();
|
|
36766
|
-
const
|
|
36767
|
-
assertWithinPrefix(
|
|
36768
|
-
return
|
|
37267
|
+
const path53 = resolve10(join41(root, workspace));
|
|
37268
|
+
assertWithinPrefix(path53, root, "kgPristinePath");
|
|
37269
|
+
return path53;
|
|
36769
37270
|
}
|
|
36770
37271
|
var KG_PATHS_INTERNALS = Object.freeze({
|
|
36771
37272
|
olamHome,
|
|
@@ -36781,10 +37282,10 @@ var KgOverlayError = class extends Error {
|
|
|
36781
37282
|
}
|
|
36782
37283
|
};
|
|
36783
37284
|
function ensureGitignoreEntry(worldClonePath) {
|
|
36784
|
-
const gitignorePath =
|
|
36785
|
-
if (!
|
|
37285
|
+
const gitignorePath = path42.join(worldClonePath, ".gitignore");
|
|
37286
|
+
if (!fs42.existsSync(gitignorePath))
|
|
36786
37287
|
return "no-gitignore";
|
|
36787
|
-
const content =
|
|
37288
|
+
const content = fs42.readFileSync(gitignorePath, "utf-8");
|
|
36788
37289
|
const lines = content.split("\n").map((l) => l.trim());
|
|
36789
37290
|
const recognised = /* @__PURE__ */ new Set([
|
|
36790
37291
|
"graphify-out",
|
|
@@ -36799,24 +37300,24 @@ function ensureGitignoreEntry(worldClonePath) {
|
|
|
36799
37300
|
const eol = content.includes("\r\n") ? "\r\n" : "\n";
|
|
36800
37301
|
const needsLeadingNewline = content.length > 0 && !content.endsWith(eol);
|
|
36801
37302
|
const block = `${needsLeadingNewline ? eol : ""}${eol}# olam-kg-service: per-world KG overlay (Phase B1)${eol}graphify-out/${eol}`;
|
|
36802
|
-
|
|
37303
|
+
fs42.appendFileSync(gitignorePath, block, "utf-8");
|
|
36803
37304
|
return "appended";
|
|
36804
37305
|
}
|
|
36805
37306
|
function createWorldOverlay(opts) {
|
|
36806
37307
|
const pristineRoot = kgPristinePath(opts.workspace);
|
|
36807
|
-
const pristinePath =
|
|
36808
|
-
if (!
|
|
37308
|
+
const pristinePath = path42.join(pristineRoot, "graphify-out");
|
|
37309
|
+
if (!fs42.existsSync(pristinePath)) {
|
|
36809
37310
|
throw new KgOverlayError(`Pristine KG for workspace ${JSON.stringify(opts.workspace)} not found at ${pristinePath}. Run \`olam kg build ${opts.workspace}\` first.`);
|
|
36810
37311
|
}
|
|
36811
|
-
if (!
|
|
37312
|
+
if (!path42.isAbsolute(opts.worldClonePath)) {
|
|
36812
37313
|
throw new KgOverlayError(`worldClonePath must be absolute (got ${opts.worldClonePath})`);
|
|
36813
37314
|
}
|
|
36814
|
-
if (!
|
|
37315
|
+
if (!fs42.existsSync(opts.worldClonePath)) {
|
|
36815
37316
|
throw new KgOverlayError(`worldClonePath does not exist: ${opts.worldClonePath}. Create the clone before reflinking.`);
|
|
36816
37317
|
}
|
|
36817
|
-
const overlayPath =
|
|
36818
|
-
if (
|
|
36819
|
-
|
|
37318
|
+
const overlayPath = path42.join(opts.worldClonePath, "graphify-out");
|
|
37319
|
+
if (fs42.existsSync(overlayPath)) {
|
|
37320
|
+
fs42.rmSync(overlayPath, { recursive: true, force: true });
|
|
36820
37321
|
}
|
|
36821
37322
|
const useReflink = process.platform === "darwin";
|
|
36822
37323
|
let strategy;
|
|
@@ -36834,7 +37335,7 @@ function createWorldOverlay(opts) {
|
|
|
36834
37335
|
} else {
|
|
36835
37336
|
strategy = "cp-r";
|
|
36836
37337
|
}
|
|
36837
|
-
if (strategy === "cp-r" || !
|
|
37338
|
+
if (strategy === "cp-r" || !fs42.existsSync(overlayPath)) {
|
|
36838
37339
|
try {
|
|
36839
37340
|
execFileSync5("cp", ["-r", pristinePath, opts.worldClonePath], {
|
|
36840
37341
|
stdio: ["ignore", "ignore", "pipe"]
|
|
@@ -36846,7 +37347,7 @@ function createWorldOverlay(opts) {
|
|
|
36846
37347
|
throw new KgOverlayError(`cp -r failed: ${msg}${reflinkMsg}`);
|
|
36847
37348
|
}
|
|
36848
37349
|
}
|
|
36849
|
-
if (!
|
|
37350
|
+
if (!fs42.existsSync(overlayPath)) {
|
|
36850
37351
|
throw new KgOverlayError(`Overlay creation produced no ${overlayPath} after cp \u2014 filesystem returned without error?`);
|
|
36851
37352
|
}
|
|
36852
37353
|
const gitignoreAction = ensureGitignoreEntry(opts.worldClonePath);
|
|
@@ -36860,9 +37361,9 @@ function createWorldOverlay(opts) {
|
|
|
36860
37361
|
|
|
36861
37362
|
// ../core/dist/world/baseline-diff.js
|
|
36862
37363
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
36863
|
-
import * as
|
|
37364
|
+
import * as fs43 from "node:fs";
|
|
36864
37365
|
import * as os26 from "node:os";
|
|
36865
|
-
import * as
|
|
37366
|
+
import * as path43 from "node:path";
|
|
36866
37367
|
var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
36867
37368
|
function expandHome2(p, homedir30) {
|
|
36868
37369
|
return p.replace(/^~(?=$|\/|\\)/, homedir30());
|
|
@@ -36889,9 +37390,9 @@ ${stderr}`;
|
|
|
36889
37390
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
36890
37391
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
36891
37392
|
const homedir30 = deps.homedir ?? (() => os26.homedir());
|
|
36892
|
-
const baselineDir =
|
|
37393
|
+
const baselineDir = path43.join(workspacePath, ".olam", "baseline");
|
|
36893
37394
|
try {
|
|
36894
|
-
|
|
37395
|
+
fs43.mkdirSync(baselineDir, { recursive: true });
|
|
36895
37396
|
} catch (err) {
|
|
36896
37397
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36897
37398
|
console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
|
|
@@ -36903,9 +37404,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
36903
37404
|
if (!repo.path)
|
|
36904
37405
|
continue;
|
|
36905
37406
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
36906
|
-
const outPath =
|
|
37407
|
+
const outPath = path43.join(baselineDir, filename);
|
|
36907
37408
|
const repoPath = expandHome2(repo.path, homedir30);
|
|
36908
|
-
if (!
|
|
37409
|
+
if (!fs43.existsSync(repoPath)) {
|
|
36909
37410
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
36910
37411
|
# (skipped: path ${repoPath} does not exist)
|
|
36911
37412
|
`);
|
|
@@ -36972,7 +37473,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
36972
37473
|
}
|
|
36973
37474
|
function writeBaselineFile(outPath, content) {
|
|
36974
37475
|
try {
|
|
36975
|
-
|
|
37476
|
+
fs43.writeFileSync(outPath, content);
|
|
36976
37477
|
} catch (err) {
|
|
36977
37478
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36978
37479
|
console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
|
|
@@ -36980,8 +37481,8 @@ function writeBaselineFile(outPath, content) {
|
|
|
36980
37481
|
}
|
|
36981
37482
|
function stripWorktreeEdits(repos, workspacePath) {
|
|
36982
37483
|
for (const repo of repos) {
|
|
36983
|
-
const worktreePath =
|
|
36984
|
-
if (!
|
|
37484
|
+
const worktreePath = path43.join(workspacePath, repo.name);
|
|
37485
|
+
if (!fs43.existsSync(worktreePath))
|
|
36985
37486
|
continue;
|
|
36986
37487
|
try {
|
|
36987
37488
|
execFileSync6("git", ["checkout", "--", "."], {
|
|
@@ -37041,17 +37542,17 @@ function extractStderr(err) {
|
|
|
37041
37542
|
function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
37042
37543
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
37043
37544
|
const homedir30 = deps.homedir ?? (() => os26.homedir());
|
|
37044
|
-
const existsSync48 = deps.existsSync ?? ((p) =>
|
|
37045
|
-
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) =>
|
|
37545
|
+
const existsSync48 = deps.existsSync ?? ((p) => fs43.existsSync(p));
|
|
37546
|
+
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs43.copyFileSync(src, dest));
|
|
37046
37547
|
const mkdirSync30 = deps.mkdirSync ?? ((dirPath, opts) => {
|
|
37047
|
-
|
|
37548
|
+
fs43.mkdirSync(dirPath, opts);
|
|
37048
37549
|
});
|
|
37049
37550
|
const plans = [];
|
|
37050
37551
|
for (const repo of repos) {
|
|
37051
37552
|
if (!repo.path)
|
|
37052
37553
|
continue;
|
|
37053
37554
|
const repoPath = expandHome2(repo.path, homedir30);
|
|
37054
|
-
const worktreePath =
|
|
37555
|
+
const worktreePath = path43.join(workspacePath, repo.name);
|
|
37055
37556
|
if (!existsSync48(repoPath))
|
|
37056
37557
|
continue;
|
|
37057
37558
|
if (!existsSync48(worktreePath)) {
|
|
@@ -37112,12 +37613,12 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
37112
37613
|
}
|
|
37113
37614
|
}
|
|
37114
37615
|
for (const rel of plan.diff.untracked) {
|
|
37115
|
-
const src =
|
|
37116
|
-
const dest =
|
|
37616
|
+
const src = path43.join(plan.repoPath, rel);
|
|
37617
|
+
const dest = path43.join(plan.worktreePath, rel);
|
|
37117
37618
|
if (!existsSync48(src))
|
|
37118
37619
|
continue;
|
|
37119
37620
|
try {
|
|
37120
|
-
mkdirSync30(
|
|
37621
|
+
mkdirSync30(path43.dirname(dest), { recursive: true });
|
|
37121
37622
|
copyFileSync9(src, dest);
|
|
37122
37623
|
} catch (err) {
|
|
37123
37624
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -37143,8 +37644,8 @@ function formatBaselineSummary(result) {
|
|
|
37143
37644
|
}
|
|
37144
37645
|
|
|
37145
37646
|
// ../core/dist/world/context-injection.js
|
|
37146
|
-
import * as
|
|
37147
|
-
import * as
|
|
37647
|
+
import * as fs44 from "node:fs";
|
|
37648
|
+
import * as path44 from "node:path";
|
|
37148
37649
|
|
|
37149
37650
|
// ../core/dist/world/templates/_generated.js
|
|
37150
37651
|
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';
|
|
@@ -37154,10 +37655,10 @@ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Enviro
|
|
|
37154
37655
|
// ../core/dist/world/context-injection.js
|
|
37155
37656
|
function injectWorldContext(opts) {
|
|
37156
37657
|
const { world } = opts;
|
|
37157
|
-
const claudeDir2 =
|
|
37158
|
-
|
|
37658
|
+
const claudeDir2 = path44.join(world.workspacePath, ".claude");
|
|
37659
|
+
fs44.mkdirSync(claudeDir2, { recursive: true });
|
|
37159
37660
|
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));
|
|
37160
|
-
|
|
37661
|
+
fs44.writeFileSync(path44.join(claudeDir2, "CLAUDE.md"), content);
|
|
37161
37662
|
writeOlamDocs(world.workspacePath);
|
|
37162
37663
|
}
|
|
37163
37664
|
function buildTaskBlock(opts) {
|
|
@@ -37231,10 +37732,10 @@ function buildExtraContextBlock(extra) {
|
|
|
37231
37732
|
${extra}`;
|
|
37232
37733
|
}
|
|
37233
37734
|
function writeOlamDocs(workspacePath) {
|
|
37234
|
-
const docsDir =
|
|
37235
|
-
|
|
37236
|
-
|
|
37237
|
-
|
|
37735
|
+
const docsDir = path44.join(workspacePath, ".olam", "docs");
|
|
37736
|
+
fs44.mkdirSync(docsDir, { recursive: true });
|
|
37737
|
+
fs44.writeFileSync(path44.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
|
|
37738
|
+
fs44.writeFileSync(path44.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
|
|
37238
37739
|
}
|
|
37239
37740
|
function formatTaskSource(ctx) {
|
|
37240
37741
|
if (ctx.source === "linear" && ctx.ticketId) {
|
|
@@ -37248,9 +37749,9 @@ function formatTaskSource(ctx) {
|
|
|
37248
37749
|
function hasPlanFile(world) {
|
|
37249
37750
|
if (world.repos.length === 0)
|
|
37250
37751
|
return false;
|
|
37251
|
-
const plansDir =
|
|
37752
|
+
const plansDir = path44.join(world.workspacePath, world.repos[0], "docs", "plans");
|
|
37252
37753
|
try {
|
|
37253
|
-
return
|
|
37754
|
+
return fs44.existsSync(plansDir) && fs44.readdirSync(plansDir).length > 0;
|
|
37254
37755
|
} catch {
|
|
37255
37756
|
return false;
|
|
37256
37757
|
}
|
|
@@ -37822,25 +38323,25 @@ init_repo_manifest();
|
|
|
37822
38323
|
|
|
37823
38324
|
// ../core/dist/world/snapshot.js
|
|
37824
38325
|
import * as crypto7 from "node:crypto";
|
|
37825
|
-
import * as
|
|
38326
|
+
import * as fs45 from "node:fs";
|
|
37826
38327
|
import * as os27 from "node:os";
|
|
37827
|
-
import * as
|
|
37828
|
-
import { execFileSync as execFileSync7, spawn as
|
|
38328
|
+
import * as path45 from "node:path";
|
|
38329
|
+
import { execFileSync as execFileSync7, spawn as spawn3 } from "node:child_process";
|
|
37829
38330
|
import { gunzipSync } from "node:zlib";
|
|
37830
38331
|
function snapshotsDir() {
|
|
37831
|
-
return process.env["OLAM_SNAPSHOTS_DIR"] ??
|
|
38332
|
+
return process.env["OLAM_SNAPSHOTS_DIR"] ?? path45.join(os27.homedir(), ".olam", "snapshots");
|
|
37832
38333
|
}
|
|
37833
38334
|
function snapshotKindDirByWorkspace(workspace, arch, kind) {
|
|
37834
|
-
return
|
|
38335
|
+
return path45.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
|
|
37835
38336
|
}
|
|
37836
38337
|
function cleanupLegacyByWorldDir(worldId) {
|
|
37837
|
-
const legacyDir =
|
|
38338
|
+
const legacyDir = path45.join(snapshotsDir(), worldId);
|
|
37838
38339
|
if (worldId === "by-workspace")
|
|
37839
38340
|
return;
|
|
37840
|
-
if (!
|
|
38341
|
+
if (!fs45.existsSync(legacyDir))
|
|
37841
38342
|
return;
|
|
37842
38343
|
try {
|
|
37843
|
-
|
|
38344
|
+
fs45.rmSync(legacyDir, { recursive: true, force: true });
|
|
37844
38345
|
} catch {
|
|
37845
38346
|
}
|
|
37846
38347
|
}
|
|
@@ -37859,11 +38360,11 @@ function hashBuffers(entries) {
|
|
|
37859
38360
|
return hash.digest("hex").slice(0, 12);
|
|
37860
38361
|
}
|
|
37861
38362
|
function computeGemsFingerprint(repoDir, imageDigest) {
|
|
37862
|
-
const lockfile =
|
|
37863
|
-
if (!
|
|
38363
|
+
const lockfile = path45.join(repoDir, "Gemfile.lock");
|
|
38364
|
+
if (!fs45.existsSync(lockfile))
|
|
37864
38365
|
return null;
|
|
37865
38366
|
const entries = [
|
|
37866
|
-
{ path: "Gemfile.lock", content:
|
|
38367
|
+
{ path: "Gemfile.lock", content: fs45.readFileSync(lockfile) }
|
|
37867
38368
|
];
|
|
37868
38369
|
if (imageDigest) {
|
|
37869
38370
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -37873,10 +38374,10 @@ function computeGemsFingerprint(repoDir, imageDigest) {
|
|
|
37873
38374
|
function computeNodeFingerprint(repoDir, imageDigest) {
|
|
37874
38375
|
const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
|
|
37875
38376
|
for (const name of candidates) {
|
|
37876
|
-
const lockfile =
|
|
37877
|
-
if (
|
|
38377
|
+
const lockfile = path45.join(repoDir, name);
|
|
38378
|
+
if (fs45.existsSync(lockfile)) {
|
|
37878
38379
|
const entries = [
|
|
37879
|
-
{ path: name, content:
|
|
38380
|
+
{ path: name, content: fs45.readFileSync(lockfile) }
|
|
37880
38381
|
];
|
|
37881
38382
|
if (imageDigest) {
|
|
37882
38383
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -37895,18 +38396,18 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
37895
38396
|
detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
|
|
37896
38397
|
};
|
|
37897
38398
|
}
|
|
37898
|
-
const parent =
|
|
37899
|
-
|
|
38399
|
+
const parent = path45.dirname(destDir);
|
|
38400
|
+
fs45.mkdirSync(parent, { recursive: true });
|
|
37900
38401
|
const tmpSuffix = `.tmp-${process.pid}-${crypto7.randomBytes(4).toString("hex")}`;
|
|
37901
38402
|
const tmpDir = `${destDir}${tmpSuffix}`;
|
|
37902
38403
|
try {
|
|
37903
|
-
|
|
38404
|
+
fs45.mkdirSync(tmpDir, { recursive: true });
|
|
37904
38405
|
execFileSync7("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
|
|
37905
|
-
|
|
38406
|
+
fs45.renameSync(tmpDir, destDir);
|
|
37906
38407
|
return { ok: true, entryCount: validation.entries.length };
|
|
37907
38408
|
} catch (err) {
|
|
37908
38409
|
try {
|
|
37909
|
-
|
|
38410
|
+
fs45.rmSync(tmpDir, { recursive: true, force: true });
|
|
37910
38411
|
} catch {
|
|
37911
38412
|
}
|
|
37912
38413
|
return {
|
|
@@ -37917,12 +38418,12 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
37917
38418
|
}
|
|
37918
38419
|
}
|
|
37919
38420
|
function resolvesWithin(base, target) {
|
|
37920
|
-
const resolved =
|
|
37921
|
-
const baseResolved =
|
|
37922
|
-
const rel =
|
|
38421
|
+
const resolved = path45.resolve(base, target);
|
|
38422
|
+
const baseResolved = path45.resolve(base);
|
|
38423
|
+
const rel = path45.relative(baseResolved, resolved);
|
|
37923
38424
|
if (rel === "")
|
|
37924
38425
|
return true;
|
|
37925
|
-
return !rel.startsWith("..") && !
|
|
38426
|
+
return !rel.startsWith("..") && !path45.isAbsolute(rel);
|
|
37926
38427
|
}
|
|
37927
38428
|
var TYPE_CHAR_TO_TYPE = {
|
|
37928
38429
|
"-": "file",
|
|
@@ -37972,7 +38473,7 @@ function parseTarListLine(line) {
|
|
|
37972
38473
|
function validateHardlinksBinary(tarPath, targetDir) {
|
|
37973
38474
|
let raw;
|
|
37974
38475
|
try {
|
|
37975
|
-
raw = gunzipSync(
|
|
38476
|
+
raw = gunzipSync(fs45.readFileSync(tarPath));
|
|
37976
38477
|
} catch {
|
|
37977
38478
|
return null;
|
|
37978
38479
|
}
|
|
@@ -37987,7 +38488,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
|
|
|
37987
38488
|
const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
|
|
37988
38489
|
const linkNull = block.indexOf(0, 157);
|
|
37989
38490
|
const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
|
|
37990
|
-
if (linkname && (
|
|
38491
|
+
if (linkname && (path45.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
|
|
37991
38492
|
return {
|
|
37992
38493
|
valid: false,
|
|
37993
38494
|
reason: "hardlink-escape",
|
|
@@ -38025,7 +38526,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
38025
38526
|
const entry = parseTarListLine(line);
|
|
38026
38527
|
if (!entry)
|
|
38027
38528
|
continue;
|
|
38028
|
-
if (
|
|
38529
|
+
if (path45.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
|
|
38029
38530
|
return {
|
|
38030
38531
|
valid: false,
|
|
38031
38532
|
reason: "path-traversal",
|
|
@@ -38033,8 +38534,8 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
38033
38534
|
};
|
|
38034
38535
|
}
|
|
38035
38536
|
if (entry.type === "symlink" && entry.linkname !== void 0) {
|
|
38036
|
-
const symlinkParent =
|
|
38037
|
-
if (
|
|
38537
|
+
const symlinkParent = path45.join(targetDir, path45.dirname(entry.name));
|
|
38538
|
+
if (path45.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path45.join(path45.dirname(entry.name), entry.linkname))) {
|
|
38038
38539
|
return {
|
|
38039
38540
|
valid: false,
|
|
38040
38541
|
reason: "symlink-escape",
|
|
@@ -38044,7 +38545,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
38044
38545
|
}
|
|
38045
38546
|
}
|
|
38046
38547
|
if (entry.type === "hardlink" && entry.linkname !== void 0) {
|
|
38047
|
-
if (
|
|
38548
|
+
if (path45.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
|
|
38048
38549
|
return {
|
|
38049
38550
|
valid: false,
|
|
38050
38551
|
reason: "hardlink-escape",
|
|
@@ -38077,8 +38578,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
38077
38578
|
}
|
|
38078
38579
|
const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
|
|
38079
38580
|
const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
|
|
38080
|
-
const tarPath =
|
|
38081
|
-
if (!
|
|
38581
|
+
const tarPath = path45.join(archDir, tarFilename);
|
|
38582
|
+
if (!fs45.existsSync(tarPath)) {
|
|
38082
38583
|
outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
|
|
38083
38584
|
continue;
|
|
38084
38585
|
}
|
|
@@ -38093,9 +38594,9 @@ function restoreSnapshotsForRepos(input) {
|
|
|
38093
38594
|
});
|
|
38094
38595
|
continue;
|
|
38095
38596
|
}
|
|
38096
|
-
const targetDir =
|
|
38597
|
+
const targetDir = path45.join(repo.worktreeDir, targetSubpath);
|
|
38097
38598
|
try {
|
|
38098
|
-
|
|
38599
|
+
fs45.rmSync(targetDir, { recursive: true, force: true });
|
|
38099
38600
|
} catch {
|
|
38100
38601
|
}
|
|
38101
38602
|
const result = unpackTarballAtomic(tarPath, targetDir);
|
|
@@ -38108,8 +38609,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
38108
38609
|
fingerprint
|
|
38109
38610
|
});
|
|
38110
38611
|
try {
|
|
38111
|
-
|
|
38112
|
-
|
|
38612
|
+
fs45.rmSync(tarPath, { force: true });
|
|
38613
|
+
fs45.rmSync(manifestPath(tarPath), { force: true });
|
|
38113
38614
|
} catch {
|
|
38114
38615
|
}
|
|
38115
38616
|
continue;
|
|
@@ -38125,10 +38626,10 @@ function restoreSnapshotsForRepos(input) {
|
|
|
38125
38626
|
}
|
|
38126
38627
|
function readManifest(tarPath) {
|
|
38127
38628
|
const mPath = manifestPath(tarPath);
|
|
38128
|
-
if (!
|
|
38629
|
+
if (!fs45.existsSync(mPath))
|
|
38129
38630
|
return null;
|
|
38130
38631
|
try {
|
|
38131
|
-
return JSON.parse(
|
|
38632
|
+
return JSON.parse(fs45.readFileSync(mPath, "utf-8"));
|
|
38132
38633
|
} catch {
|
|
38133
38634
|
return null;
|
|
38134
38635
|
}
|
|
@@ -38143,17 +38644,17 @@ function isPidAlive(pid) {
|
|
|
38143
38644
|
}
|
|
38144
38645
|
}
|
|
38145
38646
|
function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
38146
|
-
|
|
38147
|
-
const lockPath =
|
|
38647
|
+
fs45.mkdirSync(dir, { recursive: true });
|
|
38648
|
+
const lockPath = path45.join(dir, EVICT_LOCK_FILENAME);
|
|
38148
38649
|
let fd;
|
|
38149
38650
|
try {
|
|
38150
|
-
fd =
|
|
38651
|
+
fd = fs45.openSync(lockPath, fs45.constants.O_WRONLY | fs45.constants.O_CREAT | fs45.constants.O_EXCL, 384);
|
|
38151
38652
|
} catch (err) {
|
|
38152
38653
|
if (err.code !== "EEXIST")
|
|
38153
38654
|
return 0;
|
|
38154
38655
|
let holderPid = null;
|
|
38155
38656
|
try {
|
|
38156
|
-
holderPid = parseInt(
|
|
38657
|
+
holderPid = parseInt(fs45.readFileSync(lockPath, "utf-8").trim(), 10);
|
|
38157
38658
|
} catch {
|
|
38158
38659
|
holderPid = null;
|
|
38159
38660
|
}
|
|
@@ -38161,23 +38662,23 @@ function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
|
38161
38662
|
return 0;
|
|
38162
38663
|
}
|
|
38163
38664
|
try {
|
|
38164
|
-
|
|
38165
|
-
fd =
|
|
38665
|
+
fs45.unlinkSync(lockPath);
|
|
38666
|
+
fd = fs45.openSync(lockPath, fs45.constants.O_WRONLY | fs45.constants.O_CREAT | fs45.constants.O_EXCL, 384);
|
|
38166
38667
|
} catch {
|
|
38167
38668
|
return 0;
|
|
38168
38669
|
}
|
|
38169
38670
|
}
|
|
38170
38671
|
try {
|
|
38171
|
-
|
|
38672
|
+
fs45.writeSync(fd, `${process.pid}
|
|
38172
38673
|
`);
|
|
38173
38674
|
} finally {
|
|
38174
|
-
|
|
38675
|
+
fs45.closeSync(fd);
|
|
38175
38676
|
}
|
|
38176
38677
|
try {
|
|
38177
38678
|
return evictOldSnapshots(maxBytes, dir);
|
|
38178
38679
|
} finally {
|
|
38179
38680
|
try {
|
|
38180
|
-
|
|
38681
|
+
fs45.unlinkSync(lockPath);
|
|
38181
38682
|
} catch {
|
|
38182
38683
|
}
|
|
38183
38684
|
}
|
|
@@ -38188,7 +38689,7 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
|
|
|
38188
38689
|
if (!/^[a-zA-Z0-9_\-.]+$/.test(worldId))
|
|
38189
38690
|
return null;
|
|
38190
38691
|
try {
|
|
38191
|
-
const child =
|
|
38692
|
+
const child = spawn3(olamBin, ["world", "snapshot", "create", worldId, "--kind", "all"], {
|
|
38192
38693
|
detached: true,
|
|
38193
38694
|
stdio: "ignore",
|
|
38194
38695
|
// OLAM_INTERNAL_SNAPSHOT=1 sentinel — Phase D D1's deprecation
|
|
@@ -38210,17 +38711,17 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
|
|
|
38210
38711
|
}
|
|
38211
38712
|
}
|
|
38212
38713
|
function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
38213
|
-
if (!
|
|
38714
|
+
if (!fs45.existsSync(dir))
|
|
38214
38715
|
return 0;
|
|
38215
38716
|
const allTars = [];
|
|
38216
38717
|
const walk = (d) => {
|
|
38217
|
-
for (const entry of
|
|
38218
|
-
const full =
|
|
38718
|
+
for (const entry of fs45.readdirSync(d, { withFileTypes: true })) {
|
|
38719
|
+
const full = path45.join(d, entry.name);
|
|
38219
38720
|
if (entry.isDirectory()) {
|
|
38220
38721
|
walk(full);
|
|
38221
38722
|
} else if (entry.name.endsWith(".tar.gz")) {
|
|
38222
|
-
const
|
|
38223
|
-
allTars.push({ path: full, size:
|
|
38723
|
+
const stat2 = fs45.statSync(full);
|
|
38724
|
+
allTars.push({ path: full, size: stat2.size, mtime: stat2.mtimeMs });
|
|
38224
38725
|
}
|
|
38225
38726
|
}
|
|
38226
38727
|
};
|
|
@@ -38234,8 +38735,8 @@ function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
|
38234
38735
|
for (const tar of allTars) {
|
|
38235
38736
|
if (remaining <= maxBytes)
|
|
38236
38737
|
break;
|
|
38237
|
-
|
|
38238
|
-
|
|
38738
|
+
fs45.rmSync(tar.path, { force: true });
|
|
38739
|
+
fs45.rmSync(manifestPath(tar.path), { force: true });
|
|
38239
38740
|
freed += tar.size;
|
|
38240
38741
|
remaining -= tar.size;
|
|
38241
38742
|
}
|
|
@@ -38352,14 +38853,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
|
|
|
38352
38853
|
|
|
38353
38854
|
// ../core/dist/world/olam-yaml.js
|
|
38354
38855
|
init_repo_manifest();
|
|
38355
|
-
import * as
|
|
38856
|
+
import * as path46 from "node:path";
|
|
38356
38857
|
import YAML2 from "yaml";
|
|
38357
38858
|
function enrichReposWithManifests(repos, workspacePath) {
|
|
38358
38859
|
return repos.map((repo) => {
|
|
38359
38860
|
if (repo.manifest !== void 0 && repo.manifest !== null) {
|
|
38360
38861
|
return repo;
|
|
38361
38862
|
}
|
|
38362
|
-
const repoDir =
|
|
38863
|
+
const repoDir = path46.join(workspacePath, repo.name);
|
|
38363
38864
|
let manifest = null;
|
|
38364
38865
|
try {
|
|
38365
38866
|
manifest = loadRepoManifest(repoDir);
|
|
@@ -38374,8 +38875,8 @@ function enrichReposWithManifests(repos, workspacePath) {
|
|
|
38374
38875
|
}
|
|
38375
38876
|
|
|
38376
38877
|
// ../core/dist/policies/loader.js
|
|
38377
|
-
import * as
|
|
38378
|
-
import * as
|
|
38878
|
+
import * as fs46 from "node:fs";
|
|
38879
|
+
import * as path47 from "node:path";
|
|
38379
38880
|
import { parse as parseYaml5 } from "yaml";
|
|
38380
38881
|
function parseFrontmatter2(content) {
|
|
38381
38882
|
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
|
|
@@ -38395,20 +38896,20 @@ function toStringArray(v) {
|
|
|
38395
38896
|
return v.filter((x) => typeof x === "string");
|
|
38396
38897
|
}
|
|
38397
38898
|
function loadPolicies(workspaceRoot) {
|
|
38398
|
-
const policiesDir =
|
|
38399
|
-
if (!
|
|
38899
|
+
const policiesDir = path47.join(workspaceRoot, ".olam", "policies");
|
|
38900
|
+
if (!fs46.existsSync(policiesDir))
|
|
38400
38901
|
return [];
|
|
38401
38902
|
let files;
|
|
38402
38903
|
try {
|
|
38403
|
-
files =
|
|
38904
|
+
files = fs46.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
|
|
38404
38905
|
} catch {
|
|
38405
38906
|
return [];
|
|
38406
38907
|
}
|
|
38407
38908
|
const policies = [];
|
|
38408
38909
|
for (const file of files) {
|
|
38409
|
-
const filePath =
|
|
38910
|
+
const filePath = path47.join(policiesDir, file);
|
|
38410
38911
|
try {
|
|
38411
|
-
const content =
|
|
38912
|
+
const content = fs46.readFileSync(filePath, "utf8");
|
|
38412
38913
|
const parsed = parseFrontmatter2(content);
|
|
38413
38914
|
if (!parsed) {
|
|
38414
38915
|
console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
|
|
@@ -38491,7 +38992,7 @@ var TaskDispatchError = class extends Error {
|
|
|
38491
38992
|
this.name = "TaskDispatchError";
|
|
38492
38993
|
}
|
|
38493
38994
|
};
|
|
38494
|
-
var DEFAULT_SLEEP = (ms) => new Promise((
|
|
38995
|
+
var DEFAULT_SLEEP = (ms) => new Promise((resolve15) => setTimeout(resolve15, ms));
|
|
38495
38996
|
async function probeHealth(containerName, dockerExec, budgetMs, sleep5) {
|
|
38496
38997
|
const deadline = Date.now() + budgetMs;
|
|
38497
38998
|
const cadenceMs = 100;
|
|
@@ -38555,12 +39056,12 @@ init_store();
|
|
|
38555
39056
|
init_bridge();
|
|
38556
39057
|
|
|
38557
39058
|
// ../core/dist/global-config/runbook-resolver.js
|
|
38558
|
-
import * as
|
|
39059
|
+
import * as fs47 from "node:fs";
|
|
38559
39060
|
import * as os28 from "node:os";
|
|
38560
|
-
import * as
|
|
39061
|
+
import * as path48 from "node:path";
|
|
38561
39062
|
function expandTilde(p) {
|
|
38562
39063
|
if (p === "~" || p.startsWith("~/")) {
|
|
38563
|
-
return
|
|
39064
|
+
return path48.join(os28.homedir(), p.slice(1));
|
|
38564
39065
|
}
|
|
38565
39066
|
return p;
|
|
38566
39067
|
}
|
|
@@ -38572,7 +39073,7 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
38572
39073
|
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.`);
|
|
38573
39074
|
}
|
|
38574
39075
|
const resolvedPath = expandTilde(entry.path);
|
|
38575
|
-
if (!
|
|
39076
|
+
if (!fs47.existsSync(resolvedPath)) {
|
|
38576
39077
|
throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
|
|
38577
39078
|
}
|
|
38578
39079
|
}
|
|
@@ -38588,19 +39089,19 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
38588
39089
|
init_port_validator();
|
|
38589
39090
|
|
|
38590
39091
|
// ../core/dist/world/bootstrap-hooks.js
|
|
38591
|
-
import * as
|
|
38592
|
-
import * as
|
|
39092
|
+
import * as fs48 from "node:fs";
|
|
39093
|
+
import * as path49 from "node:path";
|
|
38593
39094
|
function runFixtureCopySeeds(seeds, workspacePath) {
|
|
38594
39095
|
if (!seeds)
|
|
38595
39096
|
return;
|
|
38596
39097
|
for (const seed of seeds) {
|
|
38597
39098
|
if (seed.type !== "fixture-copy")
|
|
38598
39099
|
continue;
|
|
38599
|
-
const srcAbs =
|
|
38600
|
-
const destAbs =
|
|
38601
|
-
const destDir =
|
|
38602
|
-
|
|
38603
|
-
|
|
39100
|
+
const srcAbs = path49.resolve(workspacePath, seed.repo, seed.src);
|
|
39101
|
+
const destAbs = path49.resolve(workspacePath, seed.repo, seed.dest);
|
|
39102
|
+
const destDir = path49.dirname(destAbs);
|
|
39103
|
+
fs48.mkdirSync(destDir, { recursive: true });
|
|
39104
|
+
fs48.cpSync(srcAbs, destAbs, { recursive: true, force: true });
|
|
38604
39105
|
}
|
|
38605
39106
|
}
|
|
38606
39107
|
async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
|
|
@@ -39236,7 +39737,7 @@ ${detail}`);
|
|
|
39236
39737
|
runbookSeeds = resolved.seeds;
|
|
39237
39738
|
}
|
|
39238
39739
|
const worldId = generateWorldId();
|
|
39239
|
-
const workspacePath =
|
|
39740
|
+
const workspacePath = path50.join(os29.homedir(), ".olam", "worlds", worldId);
|
|
39240
39741
|
const portOffset = this.registry.getNextPortOffset();
|
|
39241
39742
|
const branch = opts.branchName ?? `olam/${worldId}`;
|
|
39242
39743
|
const repos = this.resolveReposWithWorkspace(opts);
|
|
@@ -39257,7 +39758,8 @@ ${detail}`);
|
|
|
39257
39758
|
createdAt: now,
|
|
39258
39759
|
updatedAt: now,
|
|
39259
39760
|
readinessChain,
|
|
39260
|
-
expectedServices
|
|
39761
|
+
expectedServices,
|
|
39762
|
+
...opts.claudeHome ? { claudeHome: opts.claudeHome } : {}
|
|
39261
39763
|
};
|
|
39262
39764
|
const sm = new WorldStateMachine(worldId, "creating");
|
|
39263
39765
|
this.registry.register(metadata);
|
|
@@ -39318,37 +39820,37 @@ ${detail}`);
|
|
|
39318
39820
|
if (!repo.path)
|
|
39319
39821
|
continue;
|
|
39320
39822
|
const sourceRoot = repo.path.replace(/^~/, os29.homedir());
|
|
39321
|
-
const worktreeRoot =
|
|
39322
|
-
if (!
|
|
39823
|
+
const worktreeRoot = path50.join(workspacePath, repo.name);
|
|
39824
|
+
if (!fs49.existsSync(sourceRoot) || !fs49.existsSync(worktreeRoot))
|
|
39323
39825
|
continue;
|
|
39324
39826
|
let copied = 0;
|
|
39325
39827
|
for (const pattern of RUNTIME_FILE_PATTERNS) {
|
|
39326
39828
|
const matches2 = [];
|
|
39327
39829
|
if (pattern.includes("*")) {
|
|
39328
|
-
const [dir, glob] = [
|
|
39329
|
-
const sourceDir =
|
|
39330
|
-
if (
|
|
39830
|
+
const [dir, glob] = [path50.dirname(pattern), path50.basename(pattern)];
|
|
39831
|
+
const sourceDir = path50.join(sourceRoot, dir);
|
|
39832
|
+
if (fs49.existsSync(sourceDir)) {
|
|
39331
39833
|
const ext = glob.replace(/^\*+/, "");
|
|
39332
39834
|
try {
|
|
39333
|
-
for (const entry of
|
|
39835
|
+
for (const entry of fs49.readdirSync(sourceDir)) {
|
|
39334
39836
|
if (ext === "" || entry.endsWith(ext))
|
|
39335
|
-
matches2.push(
|
|
39837
|
+
matches2.push(path50.join(dir, entry));
|
|
39336
39838
|
}
|
|
39337
39839
|
} catch {
|
|
39338
39840
|
}
|
|
39339
39841
|
}
|
|
39340
|
-
} else if (
|
|
39842
|
+
} else if (fs49.existsSync(path50.join(sourceRoot, pattern))) {
|
|
39341
39843
|
matches2.push(pattern);
|
|
39342
39844
|
}
|
|
39343
39845
|
for (const rel of matches2) {
|
|
39344
|
-
const src =
|
|
39345
|
-
const dst =
|
|
39846
|
+
const src = path50.join(sourceRoot, rel);
|
|
39847
|
+
const dst = path50.join(worktreeRoot, rel);
|
|
39346
39848
|
try {
|
|
39347
|
-
const st =
|
|
39849
|
+
const st = fs49.statSync(src);
|
|
39348
39850
|
if (!st.isFile())
|
|
39349
39851
|
continue;
|
|
39350
|
-
|
|
39351
|
-
|
|
39852
|
+
fs49.mkdirSync(path50.dirname(dst), { recursive: true });
|
|
39853
|
+
fs49.copyFileSync(src, dst);
|
|
39352
39854
|
copied++;
|
|
39353
39855
|
} catch {
|
|
39354
39856
|
}
|
|
@@ -39395,7 +39897,7 @@ ${detail}`);
|
|
|
39395
39897
|
worlds_default: this.config.worlds_default,
|
|
39396
39898
|
repos: enrichedRepos
|
|
39397
39899
|
};
|
|
39398
|
-
setupWorldEnv(enrichedRepos, workspacePath, serviceEnv, crossRepoEnv, configCtx);
|
|
39900
|
+
setupWorldEnv(enrichedRepos, workspacePath, serviceEnv, crossRepoEnv, configCtx, opts.claudeHome);
|
|
39399
39901
|
} catch (err) {
|
|
39400
39902
|
const msg = err instanceof Error ? err.message : String(err);
|
|
39401
39903
|
console.warn(`[WorldManager] env setup failed: ${msg}`);
|
|
@@ -39434,7 +39936,7 @@ ${detail}`);
|
|
|
39434
39936
|
}
|
|
39435
39937
|
const overlayAttachments = [];
|
|
39436
39938
|
for (const repo of repos) {
|
|
39437
|
-
const worldClonePath =
|
|
39939
|
+
const worldClonePath = path50.join(workspacePath, repo.name);
|
|
39438
39940
|
try {
|
|
39439
39941
|
const result = createWorldOverlay({
|
|
39440
39942
|
workspace: repo.name,
|
|
@@ -39489,7 +39991,7 @@ ${detail}`);
|
|
|
39489
39991
|
try {
|
|
39490
39992
|
const hostExec = makeHostExecFn();
|
|
39491
39993
|
for (const repo of repos) {
|
|
39492
|
-
const repoDir =
|
|
39994
|
+
const repoDir = path50.join(workspacePath, repo.name);
|
|
39493
39995
|
if (repo.stack && Object.keys(repo.stack).length > 0) {
|
|
39494
39996
|
preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
|
|
39495
39997
|
} else {
|
|
@@ -39533,10 +40035,10 @@ ${detail}`);
|
|
|
39533
40035
|
const worldEnv = {};
|
|
39534
40036
|
if (opts.task)
|
|
39535
40037
|
worldEnv.OLAM_TASK = opts.task;
|
|
39536
|
-
const r2CredsPath =
|
|
39537
|
-
if (
|
|
40038
|
+
const r2CredsPath = path50.join(os29.homedir(), ".olam", "r2-credentials.json");
|
|
40039
|
+
if (fs49.existsSync(r2CredsPath)) {
|
|
39538
40040
|
try {
|
|
39539
|
-
const r2Raw =
|
|
40041
|
+
const r2Raw = fs49.readFileSync(r2CredsPath, "utf-8").trim();
|
|
39540
40042
|
if (r2Raw.length > 0) {
|
|
39541
40043
|
const r2 = JSON.parse(r2Raw);
|
|
39542
40044
|
if (typeof r2.account_id === "string")
|
|
@@ -39553,10 +40055,10 @@ ${detail}`);
|
|
|
39553
40055
|
} catch {
|
|
39554
40056
|
}
|
|
39555
40057
|
}
|
|
39556
|
-
const keysYamlPath =
|
|
39557
|
-
if (
|
|
40058
|
+
const keysYamlPath = path50.join(os29.homedir(), ".olam", "keys.yaml");
|
|
40059
|
+
if (fs49.existsSync(keysYamlPath)) {
|
|
39558
40060
|
try {
|
|
39559
|
-
const keysRaw =
|
|
40061
|
+
const keysRaw = fs49.readFileSync(keysYamlPath, "utf-8").trim();
|
|
39560
40062
|
if (keysRaw.length > 0) {
|
|
39561
40063
|
const parsed = YAML3.parse(keysRaw);
|
|
39562
40064
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
@@ -39615,10 +40117,10 @@ ${detail}`);
|
|
|
39615
40117
|
worldEnv[k] = v;
|
|
39616
40118
|
}
|
|
39617
40119
|
for (const { repoName, relativePath, content } of fileWrites) {
|
|
39618
|
-
const absPath =
|
|
40120
|
+
const absPath = path50.join(workspacePath, repoName, relativePath);
|
|
39619
40121
|
try {
|
|
39620
|
-
|
|
39621
|
-
|
|
40122
|
+
fs49.mkdirSync(path50.dirname(absPath), { recursive: true });
|
|
40123
|
+
fs49.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
|
|
39622
40124
|
mode: 384
|
|
39623
40125
|
});
|
|
39624
40126
|
console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
|
|
@@ -39795,7 +40297,7 @@ ${detail}`);
|
|
|
39795
40297
|
imageDigest: void 0,
|
|
39796
40298
|
repos: enrichedRepos.map((r) => ({
|
|
39797
40299
|
name: r.name,
|
|
39798
|
-
worktreeDir:
|
|
40300
|
+
worktreeDir: path50.join(workspacePath, r.name)
|
|
39799
40301
|
}))
|
|
39800
40302
|
});
|
|
39801
40303
|
for (const out of restoreResult.outcomes) {
|
|
@@ -39901,7 +40403,7 @@ ${detail}`);
|
|
|
39901
40403
|
}
|
|
39902
40404
|
if (opts.task) {
|
|
39903
40405
|
const allPolicies = repos.flatMap((repo) => {
|
|
39904
|
-
const repoWorktree =
|
|
40406
|
+
const repoWorktree = path50.join(workspacePath, repo.name);
|
|
39905
40407
|
try {
|
|
39906
40408
|
return loadPolicies(repoWorktree);
|
|
39907
40409
|
} catch (err) {
|
|
@@ -39914,8 +40416,8 @@ ${detail}`);
|
|
|
39914
40416
|
try {
|
|
39915
40417
|
execSync5(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
39916
40418
|
for (const repo of repos) {
|
|
39917
|
-
const policiesDir =
|
|
39918
|
-
if (
|
|
40419
|
+
const policiesDir = path50.join(workspacePath, repo.name, ".olam", "policies");
|
|
40420
|
+
if (fs49.existsSync(policiesDir)) {
|
|
39919
40421
|
execSync5(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
39920
40422
|
}
|
|
39921
40423
|
}
|
|
@@ -40023,8 +40525,8 @@ ${detail}`);
|
|
|
40023
40525
|
} catch {
|
|
40024
40526
|
}
|
|
40025
40527
|
try {
|
|
40026
|
-
|
|
40027
|
-
if (
|
|
40528
|
+
fs49.rmSync(world.workspacePath, { recursive: true, force: true });
|
|
40529
|
+
if (fs49.existsSync(world.workspacePath)) {
|
|
40028
40530
|
console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
|
|
40029
40531
|
}
|
|
40030
40532
|
} catch (err) {
|
|
@@ -40133,14 +40635,14 @@ ${detail}`);
|
|
|
40133
40635
|
}).filter((r) => r !== void 0);
|
|
40134
40636
|
}
|
|
40135
40637
|
transportPlanFile(planFilePath, workspacePath, repoNames) {
|
|
40136
|
-
const planContent =
|
|
40137
|
-
const planFileName =
|
|
40638
|
+
const planContent = fs49.readFileSync(planFilePath, "utf-8");
|
|
40639
|
+
const planFileName = path50.basename(planFilePath);
|
|
40138
40640
|
const targetRepo = repoNames[0];
|
|
40139
40641
|
if (!targetRepo)
|
|
40140
40642
|
return;
|
|
40141
|
-
const plansDir =
|
|
40142
|
-
|
|
40143
|
-
|
|
40643
|
+
const plansDir = path50.join(workspacePath, targetRepo, "docs", "plans");
|
|
40644
|
+
fs49.mkdirSync(plansDir, { recursive: true });
|
|
40645
|
+
fs49.writeFileSync(path50.join(plansDir, planFileName), planContent);
|
|
40144
40646
|
}
|
|
40145
40647
|
resolveServices(repos) {
|
|
40146
40648
|
const services = [];
|
|
@@ -40272,7 +40774,7 @@ function applyPostgresTemplateClone(worldId, enrichedRepos, options = {}) {
|
|
|
40272
40774
|
if (seedTemplates.length === 0) {
|
|
40273
40775
|
return { worldDbNames: [] };
|
|
40274
40776
|
}
|
|
40275
|
-
const
|
|
40777
|
+
const spawn5 = options.spawn ?? spawnSync4;
|
|
40276
40778
|
const seedToWorldDb = /* @__PURE__ */ new Map();
|
|
40277
40779
|
for (const seed of seedTemplates) {
|
|
40278
40780
|
seedToWorldDb.set(seed, deriveWorldDbName(seed, worldId));
|
|
@@ -40280,7 +40782,7 @@ function applyPostgresTemplateClone(worldId, enrichedRepos, options = {}) {
|
|
|
40280
40782
|
const created = [];
|
|
40281
40783
|
for (const seed of seedTemplates) {
|
|
40282
40784
|
const worldDb = seedToWorldDb.get(seed);
|
|
40283
|
-
const exists =
|
|
40785
|
+
const exists = spawn5("docker", [
|
|
40284
40786
|
"exec",
|
|
40285
40787
|
container,
|
|
40286
40788
|
"psql",
|
|
@@ -40292,7 +40794,7 @@ function applyPostgresTemplateClone(worldId, enrichedRepos, options = {}) {
|
|
|
40292
40794
|
const dbAlreadyExists = exists.status === 0 && (exists.stdout || "").trim() === "1";
|
|
40293
40795
|
if (!dbAlreadyExists) {
|
|
40294
40796
|
const sql = `CREATE DATABASE "${worldDb}" TEMPLATE "${seed}"`;
|
|
40295
|
-
const create =
|
|
40797
|
+
const create = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", "postgres", "-v", "ON_ERROR_STOP=1", "-c", sql], { encoding: "utf-8" });
|
|
40296
40798
|
if (create.status !== 0) {
|
|
40297
40799
|
throw new Error(`failed to CREATE DATABASE "${worldDb}" TEMPLATE "${seed}": ${(create.stderr || "").trim()}`);
|
|
40298
40800
|
}
|
|
@@ -40302,7 +40804,7 @@ function applyPostgresTemplateClone(worldId, enrichedRepos, options = {}) {
|
|
|
40302
40804
|
if (stmts !== void 0 && stmts.length > 0) {
|
|
40303
40805
|
for (const rawStmt of stmts) {
|
|
40304
40806
|
const stmt = interpolatePostCloneSql(rawStmt, worldId, seedToWorldDb);
|
|
40305
|
-
const fixup =
|
|
40807
|
+
const fixup = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", worldDb, "-v", "ON_ERROR_STOP=1", "-c", stmt], { encoding: "utf-8" });
|
|
40306
40808
|
if (fixup.status !== 0) {
|
|
40307
40809
|
throw new Error(`post_clone_sql against "${worldDb}" failed (statement: ${truncate(stmt, 120)}): ${(fixup.stderr || "").trim()}`);
|
|
40308
40810
|
}
|
|
@@ -40330,11 +40832,11 @@ function applyPostgresTestTemplateClone(worldId, enrichedRepos, options = {}) {
|
|
|
40330
40832
|
if (testTemplates.length === 0) {
|
|
40331
40833
|
return { worldTestDbNames: [] };
|
|
40332
40834
|
}
|
|
40333
|
-
const
|
|
40835
|
+
const spawn5 = options.spawn ?? spawnSync4;
|
|
40334
40836
|
const created = [];
|
|
40335
40837
|
for (const seed of testTemplates) {
|
|
40336
40838
|
const worldDb = deriveWorldDbName(seed, worldId);
|
|
40337
|
-
const exists =
|
|
40839
|
+
const exists = spawn5("docker", [
|
|
40338
40840
|
"exec",
|
|
40339
40841
|
container,
|
|
40340
40842
|
"psql",
|
|
@@ -40346,7 +40848,7 @@ function applyPostgresTestTemplateClone(worldId, enrichedRepos, options = {}) {
|
|
|
40346
40848
|
const dbAlreadyExists = exists.status === 0 && (exists.stdout || "").trim() === "1";
|
|
40347
40849
|
if (!dbAlreadyExists) {
|
|
40348
40850
|
const sql = `CREATE DATABASE "${worldDb}" TEMPLATE "${seed}"`;
|
|
40349
|
-
const create =
|
|
40851
|
+
const create = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", "postgres", "-v", "ON_ERROR_STOP=1", "-c", sql], { encoding: "utf-8" });
|
|
40350
40852
|
if (create.status !== 0) {
|
|
40351
40853
|
throw new Error(`failed to CREATE DATABASE "${worldDb}" TEMPLATE "${seed}": ${(create.stderr || "").trim()}`);
|
|
40352
40854
|
}
|
|
@@ -40387,13 +40889,13 @@ function applyPostgresWorldRole(worldId, worldDbNames, options = {}) {
|
|
|
40387
40889
|
if (worldDbNames.length === 0) {
|
|
40388
40890
|
throw new Error(`applyPostgresWorldRole called with empty worldDbNames for "${worldId}" \u2014 should only run when applyPostgresTemplateClone produced clones`);
|
|
40389
40891
|
}
|
|
40390
|
-
const
|
|
40892
|
+
const spawn5 = options.spawn ?? spawnSync4;
|
|
40391
40893
|
const container = options.singletonContainer ?? "olam-postgres";
|
|
40392
40894
|
const user = options.postgresUser ?? "development";
|
|
40393
40895
|
const genPassword = options.generatePassword ?? defaultPasswordGenerator;
|
|
40394
40896
|
const worldRoleName = deriveWorldRoleName(worldId);
|
|
40395
40897
|
const password = genPassword();
|
|
40396
|
-
const exists =
|
|
40898
|
+
const exists = spawn5("docker", [
|
|
40397
40899
|
"exec",
|
|
40398
40900
|
container,
|
|
40399
40901
|
"psql",
|
|
@@ -40405,12 +40907,12 @@ function applyPostgresWorldRole(worldId, worldDbNames, options = {}) {
|
|
|
40405
40907
|
const roleExists = exists.status === 0 && (exists.stdout || "").trim() === "1";
|
|
40406
40908
|
const escapedPassword = escapeSqlLiteral(password);
|
|
40407
40909
|
const roleDdl = roleExists ? `ALTER ROLE "${worldRoleName}" WITH LOGIN PASSWORD '${escapedPassword}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION` : `CREATE ROLE "${worldRoleName}" WITH LOGIN PASSWORD '${escapedPassword}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION`;
|
|
40408
|
-
const dml =
|
|
40910
|
+
const dml = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", "postgres", "-v", "ON_ERROR_STOP=1", "-c", roleDdl], { encoding: "utf-8" });
|
|
40409
40911
|
if (dml.status !== 0) {
|
|
40410
40912
|
throw new Error(`failed to ${roleExists ? "ALTER" : "CREATE"} ROLE "${worldRoleName}": ` + redactCreateRolePassword((dml.stderr || "").trim()));
|
|
40411
40913
|
}
|
|
40412
40914
|
for (const worldDb of worldDbNames) {
|
|
40413
|
-
const grantConnect =
|
|
40915
|
+
const grantConnect = spawn5("docker", [
|
|
40414
40916
|
"exec",
|
|
40415
40917
|
container,
|
|
40416
40918
|
"psql",
|
|
@@ -40435,7 +40937,7 @@ function applyPostgresWorldRole(worldId, worldDbNames, options = {}) {
|
|
|
40435
40937
|
`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO "${worldRoleName}"`,
|
|
40436
40938
|
`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO "${worldRoleName}"`
|
|
40437
40939
|
].join("; ");
|
|
40438
|
-
const grantResult =
|
|
40940
|
+
const grantResult = spawn5("docker", ["exec", container, "psql", "-U", user, "-d", worldDb, "-v", "ON_ERROR_STOP=1", "-c", perDbGrants], { encoding: "utf-8" });
|
|
40439
40941
|
if (grantResult.status !== 0) {
|
|
40440
40942
|
throw new Error(`failed to GRANT privileges on "${worldDb}" to "${worldRoleName}": ${(grantResult.stderr || "").trim()}`);
|
|
40441
40943
|
}
|
|
@@ -40455,11 +40957,11 @@ function dropPostgresWorldDbs(worldId, worldDbNames, options = {}) {
|
|
|
40455
40957
|
if (worldDbNames.length === 0)
|
|
40456
40958
|
return;
|
|
40457
40959
|
assertSafeWorldId(worldId);
|
|
40458
|
-
const
|
|
40960
|
+
const spawn5 = options.spawn ?? spawnSync4;
|
|
40459
40961
|
const container = options.container ?? "olam-postgres";
|
|
40460
40962
|
const user = options.user ?? "development";
|
|
40461
40963
|
for (const db of worldDbNames) {
|
|
40462
|
-
const drop =
|
|
40964
|
+
const drop = spawn5("docker", [
|
|
40463
40965
|
"exec",
|
|
40464
40966
|
container,
|
|
40465
40967
|
"psql",
|
|
@@ -40479,10 +40981,10 @@ function dropPostgresWorldRole(worldId, worldRoleName, options = {}) {
|
|
|
40479
40981
|
if (!worldRoleName)
|
|
40480
40982
|
return;
|
|
40481
40983
|
assertSafeWorldId(worldId);
|
|
40482
|
-
const
|
|
40984
|
+
const spawn5 = options.spawn ?? spawnSync4;
|
|
40483
40985
|
const container = options.container ?? "olam-postgres";
|
|
40484
40986
|
const user = options.user ?? "development";
|
|
40485
|
-
const cleanup =
|
|
40987
|
+
const cleanup = spawn5("docker", [
|
|
40486
40988
|
"exec",
|
|
40487
40989
|
container,
|
|
40488
40990
|
"psql",
|
|
@@ -40574,8 +41076,8 @@ import * as http2 from "node:http";
|
|
|
40574
41076
|
|
|
40575
41077
|
// ../core/dist/dashboard/server.js
|
|
40576
41078
|
import * as http from "node:http";
|
|
40577
|
-
import * as
|
|
40578
|
-
import * as
|
|
41079
|
+
import * as fs50 from "node:fs";
|
|
41080
|
+
import * as path51 from "node:path";
|
|
40579
41081
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
40580
41082
|
|
|
40581
41083
|
// ../core/dist/dashboard/serialize.js
|
|
@@ -40634,15 +41136,15 @@ function parsePsAux(stdout) {
|
|
|
40634
41136
|
continue;
|
|
40635
41137
|
const cpuPercent = parseFloat(parts[2]) || 0;
|
|
40636
41138
|
const rssKb = parseInt(parts[5], 10) || 0;
|
|
40637
|
-
const
|
|
41139
|
+
const stat2 = parts[7] ?? "";
|
|
40638
41140
|
const command = parts.slice(10).join(" ");
|
|
40639
41141
|
const name = command.split(/\s/)[0]?.split("/").pop() ?? command;
|
|
40640
41142
|
let status2 = "running";
|
|
40641
|
-
if (
|
|
41143
|
+
if (stat2.startsWith("T"))
|
|
40642
41144
|
status2 = "stopped";
|
|
40643
|
-
else if (
|
|
41145
|
+
else if (stat2.startsWith("Z"))
|
|
40644
41146
|
status2 = "error";
|
|
40645
|
-
else if (
|
|
41147
|
+
else if (stat2.startsWith("S") && cpuPercent === 0)
|
|
40646
41148
|
status2 = "idle";
|
|
40647
41149
|
result.push({
|
|
40648
41150
|
pid,
|
|
@@ -40910,7 +41412,7 @@ function notFound(res) {
|
|
|
40910
41412
|
}
|
|
40911
41413
|
function openThoughtStore(workspacePath) {
|
|
40912
41414
|
const dbPath = getWorldDbPath(workspacePath);
|
|
40913
|
-
if (!
|
|
41415
|
+
if (!fs50.existsSync(dbPath))
|
|
40914
41416
|
return null;
|
|
40915
41417
|
return new ThoughtLocalStore(dbPath);
|
|
40916
41418
|
}
|
|
@@ -41081,13 +41583,13 @@ function findSessionInWorld(registry2, sessionId) {
|
|
|
41081
41583
|
}
|
|
41082
41584
|
function createDashboardServer(opts) {
|
|
41083
41585
|
const { port: port2, registry: registry2 } = opts;
|
|
41084
|
-
const thisDir =
|
|
41085
|
-
const defaultPublicDir =
|
|
41586
|
+
const thisDir = path51.dirname(fileURLToPath3(import.meta.url));
|
|
41587
|
+
const defaultPublicDir = path51.resolve(thisDir, "../../../control-plane/public");
|
|
41086
41588
|
const publicDir = opts.publicDir ?? defaultPublicDir;
|
|
41087
|
-
let hasPublicDir =
|
|
41589
|
+
let hasPublicDir = fs50.existsSync(publicDir);
|
|
41088
41590
|
const server = http.createServer((req, res) => {
|
|
41089
41591
|
if (!hasPublicDir) {
|
|
41090
|
-
hasPublicDir =
|
|
41592
|
+
hasPublicDir = fs50.existsSync(publicDir);
|
|
41091
41593
|
}
|
|
41092
41594
|
const host = req.headers.host ?? `localhost:${port2}`;
|
|
41093
41595
|
const url2 = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -41361,22 +41863,22 @@ function createDashboardServer(opts) {
|
|
|
41361
41863
|
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>`);
|
|
41362
41864
|
return;
|
|
41363
41865
|
}
|
|
41364
|
-
let filePath =
|
|
41866
|
+
let filePath = path51.join(publicDir, pathname === "/" ? "index.html" : pathname);
|
|
41365
41867
|
if (!filePath.startsWith(publicDir)) {
|
|
41366
41868
|
notFound(res);
|
|
41367
41869
|
return;
|
|
41368
41870
|
}
|
|
41369
|
-
if (
|
|
41370
|
-
const ext =
|
|
41871
|
+
if (fs50.existsSync(filePath) && fs50.statSync(filePath).isFile()) {
|
|
41872
|
+
const ext = path51.extname(filePath);
|
|
41371
41873
|
const contentType = MIME[ext] ?? "application/octet-stream";
|
|
41372
41874
|
res.writeHead(200, { "Content-Type": contentType });
|
|
41373
|
-
|
|
41875
|
+
fs50.createReadStream(filePath).pipe(res);
|
|
41374
41876
|
return;
|
|
41375
41877
|
}
|
|
41376
|
-
filePath =
|
|
41377
|
-
if (
|
|
41878
|
+
filePath = path51.join(publicDir, "index.html");
|
|
41879
|
+
if (fs50.existsSync(filePath)) {
|
|
41378
41880
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
41379
|
-
|
|
41881
|
+
fs50.createReadStream(filePath).pipe(res);
|
|
41380
41882
|
return;
|
|
41381
41883
|
}
|
|
41382
41884
|
notFound(res);
|
|
@@ -41386,17 +41888,17 @@ function createDashboardServer(opts) {
|
|
|
41386
41888
|
}
|
|
41387
41889
|
|
|
41388
41890
|
// ../core/dist/dashboard/state.js
|
|
41389
|
-
import * as
|
|
41891
|
+
import * as fs51 from "node:fs";
|
|
41390
41892
|
import * as os30 from "node:os";
|
|
41391
|
-
import * as
|
|
41392
|
-
var STATE_PATH =
|
|
41893
|
+
import * as path52 from "node:path";
|
|
41894
|
+
var STATE_PATH = path52.join(os30.homedir(), ".olam", "dashboard.json");
|
|
41393
41895
|
function saveDashboardState(state) {
|
|
41394
|
-
|
|
41395
|
-
|
|
41896
|
+
fs51.mkdirSync(path52.dirname(STATE_PATH), { recursive: true });
|
|
41897
|
+
fs51.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
|
|
41396
41898
|
}
|
|
41397
41899
|
function loadDashboardState() {
|
|
41398
41900
|
try {
|
|
41399
|
-
const raw =
|
|
41901
|
+
const raw = fs51.readFileSync(STATE_PATH, "utf-8");
|
|
41400
41902
|
return JSON.parse(raw);
|
|
41401
41903
|
} catch {
|
|
41402
41904
|
return null;
|
|
@@ -41404,7 +41906,7 @@ function loadDashboardState() {
|
|
|
41404
41906
|
}
|
|
41405
41907
|
function clearDashboardState() {
|
|
41406
41908
|
try {
|
|
41407
|
-
|
|
41909
|
+
fs51.unlinkSync(STATE_PATH);
|
|
41408
41910
|
} catch {
|
|
41409
41911
|
}
|
|
41410
41912
|
}
|
|
@@ -41422,7 +41924,7 @@ function isDashboardRunning() {
|
|
|
41422
41924
|
}
|
|
41423
41925
|
|
|
41424
41926
|
// ../core/dist/dashboard/tunnel.js
|
|
41425
|
-
import { spawn as
|
|
41927
|
+
import { spawn as spawn4, execSync as execSync6 } from "node:child_process";
|
|
41426
41928
|
var tunnelProcess = null;
|
|
41427
41929
|
function isCloudflaredAvailable() {
|
|
41428
41930
|
try {
|
|
@@ -41433,8 +41935,8 @@ function isCloudflaredAvailable() {
|
|
|
41433
41935
|
}
|
|
41434
41936
|
}
|
|
41435
41937
|
function startTunnel(port2) {
|
|
41436
|
-
return new Promise((
|
|
41437
|
-
const child =
|
|
41938
|
+
return new Promise((resolve15, reject2) => {
|
|
41939
|
+
const child = spawn4("cloudflared", ["tunnel", "--url", `http://localhost:${port2}`], {
|
|
41438
41940
|
stdio: ["ignore", "pipe", "pipe"],
|
|
41439
41941
|
detached: false
|
|
41440
41942
|
});
|
|
@@ -41455,7 +41957,7 @@ function startTunnel(port2) {
|
|
|
41455
41957
|
if (match) {
|
|
41456
41958
|
resolved = true;
|
|
41457
41959
|
clearTimeout(timeout);
|
|
41458
|
-
|
|
41960
|
+
resolve15(match[0]);
|
|
41459
41961
|
}
|
|
41460
41962
|
}
|
|
41461
41963
|
child.stdout?.on("data", scan);
|
|
@@ -41523,8 +42025,8 @@ var DashboardManager = class {
|
|
|
41523
42025
|
}
|
|
41524
42026
|
throw err;
|
|
41525
42027
|
}
|
|
41526
|
-
await new Promise((
|
|
41527
|
-
this.server.on("listening",
|
|
42028
|
+
await new Promise((resolve15, reject2) => {
|
|
42029
|
+
this.server.on("listening", resolve15);
|
|
41528
42030
|
this.server.on("error", reject2);
|
|
41529
42031
|
});
|
|
41530
42032
|
this.info = { localUrl: `http://localhost:${port2}` };
|
|
@@ -41570,8 +42072,8 @@ var DashboardManager = class {
|
|
|
41570
42072
|
async stop() {
|
|
41571
42073
|
stopTunnel();
|
|
41572
42074
|
if (this.server) {
|
|
41573
|
-
await new Promise((
|
|
41574
|
-
this.server.close(() =>
|
|
42075
|
+
await new Promise((resolve15) => {
|
|
42076
|
+
this.server.close(() => resolve15());
|
|
41575
42077
|
});
|
|
41576
42078
|
this.server = null;
|
|
41577
42079
|
}
|
|
@@ -41685,7 +42187,7 @@ var PleriClient = class {
|
|
|
41685
42187
|
|
|
41686
42188
|
// ../mcp-server/src/env-loader.ts
|
|
41687
42189
|
import { readFileSync as readFileSync39, existsSync as existsSync47, statSync as statSync14 } from "node:fs";
|
|
41688
|
-
import { join as join52, dirname as dirname29, resolve as
|
|
42190
|
+
import { join as join52, dirname as dirname29, resolve as resolve14 } from "node:path";
|
|
41689
42191
|
var PROJECT_MARKERS = [
|
|
41690
42192
|
".olam/config.yaml",
|
|
41691
42193
|
".olam/config.yml",
|
|
@@ -41693,8 +42195,8 @@ var PROJECT_MARKERS = [
|
|
|
41693
42195
|
"olam.yml"
|
|
41694
42196
|
];
|
|
41695
42197
|
function findProjectRoot2(startDir) {
|
|
41696
|
-
let dir =
|
|
41697
|
-
const root =
|
|
42198
|
+
let dir = resolve14(startDir);
|
|
42199
|
+
const root = resolve14("/");
|
|
41698
42200
|
while (true) {
|
|
41699
42201
|
for (const marker of PROJECT_MARKERS) {
|
|
41700
42202
|
if (existsSync47(join52(dir, marker))) return dir;
|
|
@@ -41714,9 +42216,9 @@ function findProjectRoot2(startDir) {
|
|
|
41714
42216
|
dir = parent;
|
|
41715
42217
|
}
|
|
41716
42218
|
}
|
|
41717
|
-
function parseEnvFile(
|
|
42219
|
+
function parseEnvFile(path53) {
|
|
41718
42220
|
const out = {};
|
|
41719
|
-
const raw = readFileSync39(
|
|
42221
|
+
const raw = readFileSync39(path53, "utf8");
|
|
41720
42222
|
for (const line of raw.split(/\r?\n/)) {
|
|
41721
42223
|
const trimmed = line.trim();
|
|
41722
42224
|
if (!trimmed || trimmed.startsWith("#")) continue;
|