@pleri/olam-cli 0.1.162 → 0.1.167
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 +4 -2
- package/dist/commands/bootstrap.d.ts +6 -0
- package/dist/commands/bootstrap.d.ts.map +1 -1
- package/dist/commands/bootstrap.js +15 -0
- package/dist/commands/bootstrap.js.map +1 -1
- package/dist/commands/doctor.js +4 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +4 -3
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +103 -81
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/memory-service-container.d.ts +8 -0
- package/dist/commands/memory-service-container.d.ts.map +1 -1
- package/dist/commands/memory-service-container.js +16 -1
- package/dist/commands/memory-service-container.js.map +1 -1
- package/dist/commands/setup.d.ts +62 -14
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +373 -42
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/skills-source.d.ts.map +1 -1
- package/dist/commands/skills-source.js +89 -4
- package/dist/commands/skills-source.js.map +1 -1
- package/dist/image-digests.json +8 -7
- package/dist/index.js +672 -168
- package/dist/lib/bootstrap-kubernetes.d.ts.map +1 -1
- package/dist/lib/bootstrap-kubernetes.js +163 -106
- package/dist/lib/bootstrap-kubernetes.js.map +1 -1
- package/dist/lib/health-probes.d.ts +16 -0
- package/dist/lib/health-probes.d.ts.map +1 -1
- package/dist/lib/health-probes.js +49 -0
- package/dist/lib/health-probes.js.map +1 -1
- package/dist/lib/peripheral-registry.d.ts +9 -3
- package/dist/lib/peripheral-registry.d.ts.map +1 -1
- package/dist/lib/peripheral-registry.js +4 -4
- package/dist/lib/peripheral-registry.js.map +1 -1
- package/dist/lib/port-forward.js +1 -1
- package/dist/lib/port-forward.js.map +1 -1
- package/dist/lib/upgrade-kubernetes.d.ts +1 -1
- package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
- package/dist/lib/upgrade-kubernetes.js +35 -21
- package/dist/lib/upgrade-kubernetes.js.map +1 -1
- package/dist/mcp-server.js +990 -331
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- 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/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: path52, errorMaps, issueData } = params;
|
|
449
|
+
const fullPath = [...path52, ...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, path52, key) {
|
|
758
758
|
this._cachedPath = [];
|
|
759
759
|
this.parent = parent;
|
|
760
760
|
this.data = value;
|
|
761
|
-
this._path =
|
|
761
|
+
this._path = path52;
|
|
762
762
|
this._key = key;
|
|
763
763
|
}
|
|
764
764
|
get path() {
|
|
@@ -7332,8 +7332,8 @@ var require_utils = __commonJS({
|
|
|
7332
7332
|
}
|
|
7333
7333
|
return ind;
|
|
7334
7334
|
}
|
|
7335
|
-
function removeDotSegments(
|
|
7336
|
-
let input =
|
|
7335
|
+
function removeDotSegments(path52) {
|
|
7336
|
+
let input = path52;
|
|
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 [path52, query] = wsComponent.resourceName.split("?");
|
|
7536
|
+
wsComponent.path = path52 && path52 !== "/" ? path52 : void 0;
|
|
7537
7537
|
wsComponent.query = query;
|
|
7538
7538
|
wsComponent.resourceName = void 0;
|
|
7539
7539
|
}
|
|
@@ -10895,12 +10895,12 @@ var require_dist = __commonJS({
|
|
|
10895
10895
|
throw new Error(`Unknown format "${name}"`);
|
|
10896
10896
|
return f;
|
|
10897
10897
|
};
|
|
10898
|
-
function addFormats(ajv, list,
|
|
10898
|
+
function addFormats(ajv, list, fs51, 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, fs51[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, path52, 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, path49, ctx, rejectSource) {
|
|
|
11016
11016
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
11017
11017
|
ctx.addIssue({
|
|
11018
11018
|
code: external_exports.ZodIssueCode.custom,
|
|
11019
|
-
path: [...
|
|
11019
|
+
path: [...path52, key],
|
|
11020
11020
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
11021
11021
|
});
|
|
11022
11022
|
continue;
|
|
11023
11023
|
}
|
|
11024
|
-
if (rejectSource &&
|
|
11024
|
+
if (rejectSource && path52.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, path49, ctx, rejectSource) {
|
|
|
11029
11029
|
});
|
|
11030
11030
|
continue;
|
|
11031
11031
|
}
|
|
11032
|
-
refineForbiddenKeys(value[key], [...
|
|
11032
|
+
refineForbiddenKeys(value[key], [...path52, key], ctx, false);
|
|
11033
11033
|
}
|
|
11034
11034
|
}
|
|
11035
|
-
function rejectForbiddenKeys(value,
|
|
11035
|
+
function rejectForbiddenKeys(value, path52, 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] ${path52}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
11042
11042
|
}
|
|
11043
11043
|
if (rejectSource && key === "source") {
|
|
11044
|
-
throw new Error(`[manifest] ${
|
|
11044
|
+
throw new Error(`[manifest] ${path52}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
11045
11045
|
}
|
|
11046
|
-
rejectForbiddenKeys(value[key], `${
|
|
11046
|
+
rejectForbiddenKeys(value[key], `${path52}.${key}`, false);
|
|
11047
11047
|
}
|
|
11048
11048
|
}
|
|
11049
11049
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -11920,7 +11920,19 @@ var init_schema3 = __esm({
|
|
|
11920
11920
|
* use canonical names; `olam flywheel migrate-overlays --push` enforces
|
|
11921
11921
|
* this via the reverse validator.
|
|
11922
11922
|
*/
|
|
11923
|
-
prefix: external_exports.string().regex(PREFIX_PATTERN, "skill-source prefix must be ASCII lowercase + digits + dash/underscore (1-39 chars, no leading/trailing dash)").optional()
|
|
11923
|
+
prefix: external_exports.string().regex(PREFIX_PATTERN, "skill-source prefix must be ASCII lowercase + digits + dash/underscore (1-39 chars, no leading/trailing dash)").optional(),
|
|
11924
|
+
/**
|
|
11925
|
+
* Which artifact kinds get renamed when `prefix` is set. Optional; defaults
|
|
11926
|
+
* to `['skill', 'agent']` for back-compat with the original Phase A semantic
|
|
11927
|
+
* (Decision 6 in docs/decisions/019-skill-prefix-rules.md). Operators who
|
|
11928
|
+
* want to rebrand ONLY skills (keeping `@architect` etc. canonical) set
|
|
11929
|
+
* `['skill']`; ones who want only agents set `['agent']`.
|
|
11930
|
+
*
|
|
11931
|
+
* Empty array `[]` = same as omitting `prefix` entirely (no renaming).
|
|
11932
|
+
*
|
|
11933
|
+
* NOT applicable when `prefix` is undefined.
|
|
11934
|
+
*/
|
|
11935
|
+
prefixScope: external_exports.array(external_exports.enum(["skill", "agent"])).optional()
|
|
11924
11936
|
});
|
|
11925
11937
|
}
|
|
11926
11938
|
});
|
|
@@ -12568,29 +12580,26 @@ function updateSkillSource(id, patch) {
|
|
|
12568
12580
|
}
|
|
12569
12581
|
}
|
|
12570
12582
|
const existing = config2.skillSources[idx];
|
|
12571
|
-
let
|
|
12583
|
+
let working = { ...existing };
|
|
12572
12584
|
if (patch.prefix === null) {
|
|
12573
|
-
const { prefix:
|
|
12574
|
-
void
|
|
12575
|
-
|
|
12576
|
-
...rest,
|
|
12577
|
-
...patch.name !== void 0 ? { name: patch.name } : {},
|
|
12578
|
-
...patch.branch !== void 0 ? { branch: patch.branch } : {},
|
|
12579
|
-
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {}
|
|
12580
|
-
};
|
|
12581
|
-
const next2 = [...config2.skillSources];
|
|
12582
|
-
next2[idx] = updated2;
|
|
12583
|
-
writeGlobalConfig({ ...config2, skillSources: next2 });
|
|
12584
|
-
return updated2;
|
|
12585
|
+
const { prefix: _p, ...rest } = working;
|
|
12586
|
+
void _p;
|
|
12587
|
+
working = rest;
|
|
12585
12588
|
} else if (patch.prefix !== void 0) {
|
|
12586
|
-
|
|
12589
|
+
working = { ...working, prefix: patch.prefix };
|
|
12590
|
+
}
|
|
12591
|
+
if (patch.prefixScope === null) {
|
|
12592
|
+
const { prefixScope: _s, ...rest } = working;
|
|
12593
|
+
void _s;
|
|
12594
|
+
working = rest;
|
|
12595
|
+
} else if (patch.prefixScope !== void 0) {
|
|
12596
|
+
working = { ...working, prefixScope: [...patch.prefixScope] };
|
|
12587
12597
|
}
|
|
12588
12598
|
const updated = {
|
|
12589
|
-
...
|
|
12599
|
+
...working,
|
|
12590
12600
|
...patch.name !== void 0 ? { name: patch.name } : {},
|
|
12591
12601
|
...patch.branch !== void 0 ? { branch: patch.branch } : {},
|
|
12592
|
-
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {}
|
|
12593
|
-
...prefixUpdate
|
|
12602
|
+
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {}
|
|
12594
12603
|
};
|
|
12595
12604
|
const next = [...config2.skillSources];
|
|
12596
12605
|
next[idx] = updated;
|
|
@@ -13404,7 +13413,7 @@ function detectCollisions(artifacts) {
|
|
|
13404
13413
|
}
|
|
13405
13414
|
return { winners, collisions };
|
|
13406
13415
|
}
|
|
13407
|
-
function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences) {
|
|
13416
|
+
function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, expectedAgentWinnerNames) {
|
|
13408
13417
|
const shadowBackups = [];
|
|
13409
13418
|
for (const bucket of BUCKETS) {
|
|
13410
13419
|
const dir = path21.join(claude, bucket);
|
|
@@ -13438,8 +13447,11 @@ function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences) {
|
|
|
13438
13447
|
}
|
|
13439
13448
|
fs20.unlinkSync(p);
|
|
13440
13449
|
} else if (bucket === "agents" && stat.isFile() && !name.includes(".shadow-backup-")) {
|
|
13441
|
-
const
|
|
13442
|
-
|
|
13450
|
+
const hasWinner = expectedAgentWinnerNames !== void 0 ? expectedAgentWinnerNames.has(name) : true;
|
|
13451
|
+
if (hasWinner) {
|
|
13452
|
+
const backup = shadowBackup(p);
|
|
13453
|
+
shadowBackups.push(backup);
|
|
13454
|
+
}
|
|
13443
13455
|
}
|
|
13444
13456
|
} catch {
|
|
13445
13457
|
}
|
|
@@ -13479,8 +13491,9 @@ function deployArtifacts(artifacts, opts) {
|
|
|
13479
13491
|
for (const bucket of BUCKETS) {
|
|
13480
13492
|
fs20.mkdirSync(path21.join(claude, bucket), { recursive: true });
|
|
13481
13493
|
}
|
|
13482
|
-
const sweepShadowBackups = cleanManagedSymlinks(claude, opts?.installedOlamVersion, opts?.overlayReferences);
|
|
13483
13494
|
const { winners, collisions } = detectCollisions(artifacts);
|
|
13495
|
+
const expectedAgentWinnerNames = new Set(winners.filter((a) => a.kind === "agent").map((a) => a.deployBasename));
|
|
13496
|
+
const sweepShadowBackups = cleanManagedSymlinks(claude, opts?.installedOlamVersion, opts?.overlayReferences, expectedAgentWinnerNames);
|
|
13484
13497
|
const result = { linked: 0, shadowBackups: [...sweepShadowBackups], collisions };
|
|
13485
13498
|
for (const artifact of winners) {
|
|
13486
13499
|
const bucket = bucketFor(artifact.kind);
|
|
@@ -14945,15 +14958,18 @@ import * as fs30 from "node:fs";
|
|
|
14945
14958
|
import * as path29 from "node:path";
|
|
14946
14959
|
function buildSourcePrefixMap(sources) {
|
|
14947
14960
|
const byId = /* @__PURE__ */ new Map();
|
|
14961
|
+
const scopeById = /* @__PURE__ */ new Map();
|
|
14948
14962
|
const prefixes = /* @__PURE__ */ new Set();
|
|
14949
14963
|
for (const s of sources) {
|
|
14950
14964
|
if (s.prefix !== void 0 && s.prefix.length > 0) {
|
|
14951
14965
|
byId.set(s.id, s.prefix);
|
|
14966
|
+
scopeById.set(s.id, s.prefixScope ?? DEFAULT_SCOPE);
|
|
14952
14967
|
prefixes.add(s.prefix);
|
|
14953
14968
|
}
|
|
14954
14969
|
}
|
|
14955
14970
|
return {
|
|
14956
14971
|
get: (sourceId) => byId.get(sourceId),
|
|
14972
|
+
getScope: (sourceId) => scopeById.get(sourceId) ?? DEFAULT_SCOPE,
|
|
14957
14973
|
registeredPrefixes: Array.from(prefixes)
|
|
14958
14974
|
};
|
|
14959
14975
|
}
|
|
@@ -14965,6 +14981,9 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
|
|
|
14965
14981
|
const prefix = sourceMap.get(artifact.sourceId);
|
|
14966
14982
|
if (prefix === void 0)
|
|
14967
14983
|
continue;
|
|
14984
|
+
const scope = sourceMap.getScope(artifact.sourceId);
|
|
14985
|
+
if (!scope.includes(artifact.kind))
|
|
14986
|
+
continue;
|
|
14968
14987
|
const canonical = artifact.deployBasename;
|
|
14969
14988
|
const otherPrefixes = sourceMap.registeredPrefixes.filter((p) => p !== prefix);
|
|
14970
14989
|
const renamed = applyPrefix(canonical, prefix, otherPrefixes);
|
|
@@ -15031,11 +15050,13 @@ function detectPrefixCollisions(sources) {
|
|
|
15031
15050
|
}
|
|
15032
15051
|
return collisions;
|
|
15033
15052
|
}
|
|
15053
|
+
var DEFAULT_SCOPE;
|
|
15034
15054
|
var init_prefix_deploy = __esm({
|
|
15035
15055
|
"../core/dist/skill-sync/prefix-deploy.js"() {
|
|
15036
15056
|
"use strict";
|
|
15037
15057
|
init_prefix_rules();
|
|
15038
15058
|
init_managed_merge();
|
|
15059
|
+
DEFAULT_SCOPE = ["skill", "agent"];
|
|
15039
15060
|
}
|
|
15040
15061
|
});
|
|
15041
15062
|
|
|
@@ -15917,6 +15938,9 @@ var init_global_config = __esm({
|
|
|
15917
15938
|
}
|
|
15918
15939
|
});
|
|
15919
15940
|
|
|
15941
|
+
// ../mcp-server/src/redirect-stdout-to-stderr.ts
|
|
15942
|
+
console.log = console.error;
|
|
15943
|
+
|
|
15920
15944
|
// ../../node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
15921
15945
|
import process3 from "node:process";
|
|
15922
15946
|
|
|
@@ -16160,10 +16184,10 @@ function mergeDefs(...defs) {
|
|
|
16160
16184
|
function cloneDef(schema) {
|
|
16161
16185
|
return mergeDefs(schema._zod.def);
|
|
16162
16186
|
}
|
|
16163
|
-
function getElementAtPath(obj,
|
|
16164
|
-
if (!
|
|
16187
|
+
function getElementAtPath(obj, path52) {
|
|
16188
|
+
if (!path52)
|
|
16165
16189
|
return obj;
|
|
16166
|
-
return
|
|
16190
|
+
return path52.reduce((acc, key) => acc?.[key], obj);
|
|
16167
16191
|
}
|
|
16168
16192
|
function promiseAllObject(promisesObj) {
|
|
16169
16193
|
const keys = Object.keys(promisesObj);
|
|
@@ -16572,11 +16596,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
16572
16596
|
}
|
|
16573
16597
|
return false;
|
|
16574
16598
|
}
|
|
16575
|
-
function prefixIssues(
|
|
16599
|
+
function prefixIssues(path52, issues) {
|
|
16576
16600
|
return issues.map((iss) => {
|
|
16577
16601
|
var _a3;
|
|
16578
16602
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
16579
|
-
iss.path.unshift(
|
|
16603
|
+
iss.path.unshift(path52);
|
|
16580
16604
|
return iss;
|
|
16581
16605
|
});
|
|
16582
16606
|
}
|
|
@@ -16723,16 +16747,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
|
|
|
16723
16747
|
}
|
|
16724
16748
|
function formatError(error2, mapper = (issue2) => issue2.message) {
|
|
16725
16749
|
const fieldErrors = { _errors: [] };
|
|
16726
|
-
const processError = (error3,
|
|
16750
|
+
const processError = (error3, path52 = []) => {
|
|
16727
16751
|
for (const issue2 of error3.issues) {
|
|
16728
16752
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
16729
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
16753
|
+
issue2.errors.map((issues) => processError({ issues }, [...path52, ...issue2.path]));
|
|
16730
16754
|
} else if (issue2.code === "invalid_key") {
|
|
16731
|
-
processError({ issues: issue2.issues }, [...
|
|
16755
|
+
processError({ issues: issue2.issues }, [...path52, ...issue2.path]);
|
|
16732
16756
|
} else if (issue2.code === "invalid_element") {
|
|
16733
|
-
processError({ issues: issue2.issues }, [...
|
|
16757
|
+
processError({ issues: issue2.issues }, [...path52, ...issue2.path]);
|
|
16734
16758
|
} else {
|
|
16735
|
-
const fullpath = [...
|
|
16759
|
+
const fullpath = [...path52, ...issue2.path];
|
|
16736
16760
|
if (fullpath.length === 0) {
|
|
16737
16761
|
fieldErrors._errors.push(mapper(issue2));
|
|
16738
16762
|
} else {
|
|
@@ -26155,6 +26179,228 @@ var McpZodTypeKind;
|
|
|
26155
26179
|
McpZodTypeKind2["Completable"] = "McpCompletable";
|
|
26156
26180
|
})(McpZodTypeKind || (McpZodTypeKind = {}));
|
|
26157
26181
|
|
|
26182
|
+
// ../../node_modules/@modelcontextprotocol/sdk/dist/esm/shared/uriTemplate.js
|
|
26183
|
+
var MAX_TEMPLATE_LENGTH = 1e6;
|
|
26184
|
+
var MAX_VARIABLE_LENGTH = 1e6;
|
|
26185
|
+
var MAX_TEMPLATE_EXPRESSIONS = 1e4;
|
|
26186
|
+
var MAX_REGEX_LENGTH = 1e6;
|
|
26187
|
+
var UriTemplate = class _UriTemplate {
|
|
26188
|
+
/**
|
|
26189
|
+
* Returns true if the given string contains any URI template expressions.
|
|
26190
|
+
* A template expression is a sequence of characters enclosed in curly braces,
|
|
26191
|
+
* like {foo} or {?bar}.
|
|
26192
|
+
*/
|
|
26193
|
+
static isTemplate(str) {
|
|
26194
|
+
return /\{[^}\s]+\}/.test(str);
|
|
26195
|
+
}
|
|
26196
|
+
static validateLength(str, max, context) {
|
|
26197
|
+
if (str.length > max) {
|
|
26198
|
+
throw new Error(`${context} exceeds maximum length of ${max} characters (got ${str.length})`);
|
|
26199
|
+
}
|
|
26200
|
+
}
|
|
26201
|
+
get variableNames() {
|
|
26202
|
+
return this.parts.flatMap((part) => typeof part === "string" ? [] : part.names);
|
|
26203
|
+
}
|
|
26204
|
+
constructor(template) {
|
|
26205
|
+
_UriTemplate.validateLength(template, MAX_TEMPLATE_LENGTH, "Template");
|
|
26206
|
+
this.template = template;
|
|
26207
|
+
this.parts = this.parse(template);
|
|
26208
|
+
}
|
|
26209
|
+
toString() {
|
|
26210
|
+
return this.template;
|
|
26211
|
+
}
|
|
26212
|
+
parse(template) {
|
|
26213
|
+
const parts = [];
|
|
26214
|
+
let currentText = "";
|
|
26215
|
+
let i = 0;
|
|
26216
|
+
let expressionCount = 0;
|
|
26217
|
+
while (i < template.length) {
|
|
26218
|
+
if (template[i] === "{") {
|
|
26219
|
+
if (currentText) {
|
|
26220
|
+
parts.push(currentText);
|
|
26221
|
+
currentText = "";
|
|
26222
|
+
}
|
|
26223
|
+
const end = template.indexOf("}", i);
|
|
26224
|
+
if (end === -1)
|
|
26225
|
+
throw new Error("Unclosed template expression");
|
|
26226
|
+
expressionCount++;
|
|
26227
|
+
if (expressionCount > MAX_TEMPLATE_EXPRESSIONS) {
|
|
26228
|
+
throw new Error(`Template contains too many expressions (max ${MAX_TEMPLATE_EXPRESSIONS})`);
|
|
26229
|
+
}
|
|
26230
|
+
const expr = template.slice(i + 1, end);
|
|
26231
|
+
const operator = this.getOperator(expr);
|
|
26232
|
+
const exploded = expr.includes("*");
|
|
26233
|
+
const names = this.getNames(expr);
|
|
26234
|
+
const name = names[0];
|
|
26235
|
+
for (const name2 of names) {
|
|
26236
|
+
_UriTemplate.validateLength(name2, MAX_VARIABLE_LENGTH, "Variable name");
|
|
26237
|
+
}
|
|
26238
|
+
parts.push({ name, operator, names, exploded });
|
|
26239
|
+
i = end + 1;
|
|
26240
|
+
} else {
|
|
26241
|
+
currentText += template[i];
|
|
26242
|
+
i++;
|
|
26243
|
+
}
|
|
26244
|
+
}
|
|
26245
|
+
if (currentText) {
|
|
26246
|
+
parts.push(currentText);
|
|
26247
|
+
}
|
|
26248
|
+
return parts;
|
|
26249
|
+
}
|
|
26250
|
+
getOperator(expr) {
|
|
26251
|
+
const operators = ["+", "#", ".", "/", "?", "&"];
|
|
26252
|
+
return operators.find((op) => expr.startsWith(op)) || "";
|
|
26253
|
+
}
|
|
26254
|
+
getNames(expr) {
|
|
26255
|
+
const operator = this.getOperator(expr);
|
|
26256
|
+
return expr.slice(operator.length).split(",").map((name) => name.replace("*", "").trim()).filter((name) => name.length > 0);
|
|
26257
|
+
}
|
|
26258
|
+
encodeValue(value, operator) {
|
|
26259
|
+
_UriTemplate.validateLength(value, MAX_VARIABLE_LENGTH, "Variable value");
|
|
26260
|
+
if (operator === "+" || operator === "#") {
|
|
26261
|
+
return encodeURI(value);
|
|
26262
|
+
}
|
|
26263
|
+
return encodeURIComponent(value);
|
|
26264
|
+
}
|
|
26265
|
+
expandPart(part, variables) {
|
|
26266
|
+
if (part.operator === "?" || part.operator === "&") {
|
|
26267
|
+
const pairs = part.names.map((name) => {
|
|
26268
|
+
const value2 = variables[name];
|
|
26269
|
+
if (value2 === void 0)
|
|
26270
|
+
return "";
|
|
26271
|
+
const encoded2 = Array.isArray(value2) ? value2.map((v) => this.encodeValue(v, part.operator)).join(",") : this.encodeValue(value2.toString(), part.operator);
|
|
26272
|
+
return `${name}=${encoded2}`;
|
|
26273
|
+
}).filter((pair) => pair.length > 0);
|
|
26274
|
+
if (pairs.length === 0)
|
|
26275
|
+
return "";
|
|
26276
|
+
const separator = part.operator === "?" ? "?" : "&";
|
|
26277
|
+
return separator + pairs.join("&");
|
|
26278
|
+
}
|
|
26279
|
+
if (part.names.length > 1) {
|
|
26280
|
+
const values2 = part.names.map((name) => variables[name]).filter((v) => v !== void 0);
|
|
26281
|
+
if (values2.length === 0)
|
|
26282
|
+
return "";
|
|
26283
|
+
return values2.map((v) => Array.isArray(v) ? v[0] : v).join(",");
|
|
26284
|
+
}
|
|
26285
|
+
const value = variables[part.name];
|
|
26286
|
+
if (value === void 0)
|
|
26287
|
+
return "";
|
|
26288
|
+
const values = Array.isArray(value) ? value : [value];
|
|
26289
|
+
const encoded = values.map((v) => this.encodeValue(v, part.operator));
|
|
26290
|
+
switch (part.operator) {
|
|
26291
|
+
case "":
|
|
26292
|
+
return encoded.join(",");
|
|
26293
|
+
case "+":
|
|
26294
|
+
return encoded.join(",");
|
|
26295
|
+
case "#":
|
|
26296
|
+
return "#" + encoded.join(",");
|
|
26297
|
+
case ".":
|
|
26298
|
+
return "." + encoded.join(".");
|
|
26299
|
+
case "/":
|
|
26300
|
+
return "/" + encoded.join("/");
|
|
26301
|
+
default:
|
|
26302
|
+
return encoded.join(",");
|
|
26303
|
+
}
|
|
26304
|
+
}
|
|
26305
|
+
expand(variables) {
|
|
26306
|
+
let result = "";
|
|
26307
|
+
let hasQueryParam = false;
|
|
26308
|
+
for (const part of this.parts) {
|
|
26309
|
+
if (typeof part === "string") {
|
|
26310
|
+
result += part;
|
|
26311
|
+
continue;
|
|
26312
|
+
}
|
|
26313
|
+
const expanded = this.expandPart(part, variables);
|
|
26314
|
+
if (!expanded)
|
|
26315
|
+
continue;
|
|
26316
|
+
if ((part.operator === "?" || part.operator === "&") && hasQueryParam) {
|
|
26317
|
+
result += expanded.replace("?", "&");
|
|
26318
|
+
} else {
|
|
26319
|
+
result += expanded;
|
|
26320
|
+
}
|
|
26321
|
+
if (part.operator === "?" || part.operator === "&") {
|
|
26322
|
+
hasQueryParam = true;
|
|
26323
|
+
}
|
|
26324
|
+
}
|
|
26325
|
+
return result;
|
|
26326
|
+
}
|
|
26327
|
+
escapeRegExp(str) {
|
|
26328
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
26329
|
+
}
|
|
26330
|
+
partToRegExp(part) {
|
|
26331
|
+
const patterns = [];
|
|
26332
|
+
for (const name2 of part.names) {
|
|
26333
|
+
_UriTemplate.validateLength(name2, MAX_VARIABLE_LENGTH, "Variable name");
|
|
26334
|
+
}
|
|
26335
|
+
if (part.operator === "?" || part.operator === "&") {
|
|
26336
|
+
for (let i = 0; i < part.names.length; i++) {
|
|
26337
|
+
const name2 = part.names[i];
|
|
26338
|
+
const prefix = i === 0 ? "\\" + part.operator : "&";
|
|
26339
|
+
patterns.push({
|
|
26340
|
+
pattern: prefix + this.escapeRegExp(name2) + "=([^&]+)",
|
|
26341
|
+
name: name2
|
|
26342
|
+
});
|
|
26343
|
+
}
|
|
26344
|
+
return patterns;
|
|
26345
|
+
}
|
|
26346
|
+
let pattern;
|
|
26347
|
+
const name = part.name;
|
|
26348
|
+
switch (part.operator) {
|
|
26349
|
+
case "":
|
|
26350
|
+
pattern = part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)";
|
|
26351
|
+
break;
|
|
26352
|
+
case "+":
|
|
26353
|
+
case "#":
|
|
26354
|
+
pattern = "(.+)";
|
|
26355
|
+
break;
|
|
26356
|
+
case ".":
|
|
26357
|
+
pattern = "\\.([^/,]+)";
|
|
26358
|
+
break;
|
|
26359
|
+
case "/":
|
|
26360
|
+
pattern = "/" + (part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)");
|
|
26361
|
+
break;
|
|
26362
|
+
default:
|
|
26363
|
+
pattern = "([^/]+)";
|
|
26364
|
+
}
|
|
26365
|
+
patterns.push({ pattern, name });
|
|
26366
|
+
return patterns;
|
|
26367
|
+
}
|
|
26368
|
+
match(uri) {
|
|
26369
|
+
_UriTemplate.validateLength(uri, MAX_TEMPLATE_LENGTH, "URI");
|
|
26370
|
+
let pattern = "^";
|
|
26371
|
+
const names = [];
|
|
26372
|
+
for (const part of this.parts) {
|
|
26373
|
+
if (typeof part === "string") {
|
|
26374
|
+
pattern += this.escapeRegExp(part);
|
|
26375
|
+
} else {
|
|
26376
|
+
const patterns = this.partToRegExp(part);
|
|
26377
|
+
for (const { pattern: partPattern, name } of patterns) {
|
|
26378
|
+
pattern += partPattern;
|
|
26379
|
+
names.push({ name, exploded: part.exploded });
|
|
26380
|
+
}
|
|
26381
|
+
}
|
|
26382
|
+
}
|
|
26383
|
+
pattern += "$";
|
|
26384
|
+
_UriTemplate.validateLength(pattern, MAX_REGEX_LENGTH, "Generated regex pattern");
|
|
26385
|
+
const regex = new RegExp(pattern);
|
|
26386
|
+
const match = uri.match(regex);
|
|
26387
|
+
if (!match)
|
|
26388
|
+
return null;
|
|
26389
|
+
const result = {};
|
|
26390
|
+
for (let i = 0; i < names.length; i++) {
|
|
26391
|
+
const { name, exploded } = names[i];
|
|
26392
|
+
const value = match[i + 1];
|
|
26393
|
+
const cleanName = name.replace("*", "");
|
|
26394
|
+
if (exploded && value.includes(",")) {
|
|
26395
|
+
result[cleanName] = value.split(",");
|
|
26396
|
+
} else {
|
|
26397
|
+
result[cleanName] = value;
|
|
26398
|
+
}
|
|
26399
|
+
}
|
|
26400
|
+
return result;
|
|
26401
|
+
}
|
|
26402
|
+
};
|
|
26403
|
+
|
|
26158
26404
|
// ../../node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
|
|
26159
26405
|
var TOOL_NAME_REGEX = /^[A-Za-z0-9._-]{1,128}$/;
|
|
26160
26406
|
function validateToolName(name) {
|
|
@@ -26944,6 +27190,30 @@ var McpServer = class {
|
|
|
26944
27190
|
}
|
|
26945
27191
|
}
|
|
26946
27192
|
};
|
|
27193
|
+
var ResourceTemplate = class {
|
|
27194
|
+
constructor(uriTemplate, _callbacks) {
|
|
27195
|
+
this._callbacks = _callbacks;
|
|
27196
|
+
this._uriTemplate = typeof uriTemplate === "string" ? new UriTemplate(uriTemplate) : uriTemplate;
|
|
27197
|
+
}
|
|
27198
|
+
/**
|
|
27199
|
+
* Gets the URI template pattern.
|
|
27200
|
+
*/
|
|
27201
|
+
get uriTemplate() {
|
|
27202
|
+
return this._uriTemplate;
|
|
27203
|
+
}
|
|
27204
|
+
/**
|
|
27205
|
+
* Gets the list callback, if one was provided.
|
|
27206
|
+
*/
|
|
27207
|
+
get listCallback() {
|
|
27208
|
+
return this._callbacks.list;
|
|
27209
|
+
}
|
|
27210
|
+
/**
|
|
27211
|
+
* Gets the callback for completing a specific URI template variable, if one was provided.
|
|
27212
|
+
*/
|
|
27213
|
+
completeCallback(variable) {
|
|
27214
|
+
return this._callbacks.complete?.[variable];
|
|
27215
|
+
}
|
|
27216
|
+
};
|
|
26947
27217
|
var EMPTY_OBJECT_JSON_SCHEMA = {
|
|
26948
27218
|
type: "object",
|
|
26949
27219
|
properties: {}
|
|
@@ -27268,7 +27538,7 @@ function readSecretIfExists() {
|
|
|
27268
27538
|
|
|
27269
27539
|
// ../core/dist/auth/client.js
|
|
27270
27540
|
var DEFAULT_BASE_URL = "http://127.0.0.1:9999";
|
|
27271
|
-
var DEFAULT_TIMEOUT_MS =
|
|
27541
|
+
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
27272
27542
|
var RETRY_COUNT = 2;
|
|
27273
27543
|
var RETRY_BACKOFF_MS = 250;
|
|
27274
27544
|
var AuthClient = class {
|
|
@@ -27371,8 +27641,8 @@ var AuthClient = class {
|
|
|
27371
27641
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
27372
27642
|
}
|
|
27373
27643
|
}
|
|
27374
|
-
async request(method,
|
|
27375
|
-
const url2 = `${this.baseUrl}${
|
|
27644
|
+
async request(method, path52, body, attempt = 0) {
|
|
27645
|
+
const url2 = `${this.baseUrl}${path52}`;
|
|
27376
27646
|
const controller = new AbortController();
|
|
27377
27647
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
27378
27648
|
const headers = {};
|
|
@@ -27390,7 +27660,7 @@ var AuthClient = class {
|
|
|
27390
27660
|
} catch (err) {
|
|
27391
27661
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
27392
27662
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
27393
|
-
return this.request(method,
|
|
27663
|
+
return this.request(method, path52, body, attempt + 1);
|
|
27394
27664
|
}
|
|
27395
27665
|
throw err;
|
|
27396
27666
|
} finally {
|
|
@@ -28244,12 +28514,12 @@ function register3(server, _ctx, _initError) {
|
|
|
28244
28514
|
registry2.close();
|
|
28245
28515
|
}
|
|
28246
28516
|
try {
|
|
28247
|
-
const { default:
|
|
28248
|
-
const { default:
|
|
28249
|
-
const { default:
|
|
28250
|
-
const tokenPath =
|
|
28251
|
-
if (
|
|
28252
|
-
const token =
|
|
28517
|
+
const { default: fs51 } = await import("node:fs");
|
|
28518
|
+
const { default: os31 } = await import("node:os");
|
|
28519
|
+
const { default: path52 } = await import("node:path");
|
|
28520
|
+
const tokenPath = path52.join(os31.homedir(), ".olam", "host-cp.token");
|
|
28521
|
+
if (fs51.existsSync(tokenPath)) {
|
|
28522
|
+
const token = fs51.readFileSync(tokenPath, "utf-8").trim();
|
|
28253
28523
|
await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
|
|
28254
28524
|
method: "POST",
|
|
28255
28525
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
@@ -28669,10 +28939,10 @@ function extractMcpConfig(claudeJsonPath) {
|
|
|
28669
28939
|
}
|
|
28670
28940
|
return { mcpServers, secrets };
|
|
28671
28941
|
}
|
|
28672
|
-
function readOptional(
|
|
28673
|
-
if (!existsSync6(
|
|
28942
|
+
function readOptional(path52) {
|
|
28943
|
+
if (!existsSync6(path52)) return null;
|
|
28674
28944
|
try {
|
|
28675
|
-
return readFileSync5(
|
|
28945
|
+
return readFileSync5(path52, "utf8");
|
|
28676
28946
|
} catch {
|
|
28677
28947
|
return null;
|
|
28678
28948
|
}
|
|
@@ -30118,8 +30388,8 @@ var CloudflareProvider = class extends ComputeProvider {
|
|
|
30118
30388
|
// -----------------------------------------------------------------------
|
|
30119
30389
|
// Internal fetch helper
|
|
30120
30390
|
// -----------------------------------------------------------------------
|
|
30121
|
-
async request(
|
|
30122
|
-
const url2 = `${this.config.workerUrl}${
|
|
30391
|
+
async request(path52, method, body) {
|
|
30392
|
+
const url2 = `${this.config.workerUrl}${path52}`;
|
|
30123
30393
|
const bearer = await this.config.mintToken();
|
|
30124
30394
|
const headers = {
|
|
30125
30395
|
Authorization: `Bearer ${bearer}`
|
|
@@ -32570,10 +32840,10 @@ async function writeManifest(args) {
|
|
|
32570
32840
|
capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
32571
32841
|
shots: entries
|
|
32572
32842
|
};
|
|
32573
|
-
const
|
|
32574
|
-
await writeFile(
|
|
32843
|
+
const path52 = join13(args.outDir, "manifest.json");
|
|
32844
|
+
await writeFile(path52, `${JSON.stringify(manifest, null, 2)}
|
|
32575
32845
|
`, "utf8");
|
|
32576
|
-
return { path:
|
|
32846
|
+
return { path: path52, manifest };
|
|
32577
32847
|
}
|
|
32578
32848
|
|
|
32579
32849
|
// ../mcp-server/src/tools/_capture/proxy.ts
|
|
@@ -32827,9 +33097,9 @@ async function startProxy(opts) {
|
|
|
32827
33097
|
const liveCompiled = verified.allowedPaths.map(compileGlob);
|
|
32828
33098
|
const target = parseRequestTarget(req);
|
|
32829
33099
|
if (!target) return httpReject(400, "invalid_target");
|
|
32830
|
-
const
|
|
32831
|
-
if (!liveCompiled.some((re) => re.test(
|
|
32832
|
-
return httpReject(403, "outside_allow_list", { path:
|
|
33100
|
+
const path52 = target.pathname;
|
|
33101
|
+
if (!liveCompiled.some((re) => re.test(path52))) {
|
|
33102
|
+
return httpReject(403, "outside_allow_list", { path: path52 });
|
|
32833
33103
|
}
|
|
32834
33104
|
const headerWorld = req.headers[WORLD_ASSERT_HEADER];
|
|
32835
33105
|
const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
|
|
@@ -33608,14 +33878,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
|
|
|
33608
33878
|
await page.waitForTimeout(shot.afterLoadMs);
|
|
33609
33879
|
}
|
|
33610
33880
|
const ext = format === "jpeg" ? "jpg" : "png";
|
|
33611
|
-
const
|
|
33881
|
+
const path52 = join14(outDir, `${shot.name}.${ext}`);
|
|
33612
33882
|
await page.screenshot({
|
|
33613
|
-
path:
|
|
33883
|
+
path: path52,
|
|
33614
33884
|
type: format,
|
|
33615
33885
|
...format === "jpeg" ? { quality: jpegQuality } : {},
|
|
33616
33886
|
fullPage: false
|
|
33617
33887
|
});
|
|
33618
|
-
return { name: shot.name, path:
|
|
33888
|
+
return { name: shot.name, path: path52, urlRedacted: redactUrl(shot.url), viewport };
|
|
33619
33889
|
} finally {
|
|
33620
33890
|
await context.close();
|
|
33621
33891
|
}
|
|
@@ -34059,12 +34329,12 @@ function openUrl(url2) {
|
|
|
34059
34329
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
34060
34330
|
async function readHostCpToken2() {
|
|
34061
34331
|
try {
|
|
34062
|
-
const { default:
|
|
34063
|
-
const { default:
|
|
34064
|
-
const { default:
|
|
34065
|
-
const tp =
|
|
34066
|
-
if (!
|
|
34067
|
-
return { token:
|
|
34332
|
+
const { default: fs51 } = await import("node:fs");
|
|
34333
|
+
const { default: os31 } = await import("node:os");
|
|
34334
|
+
const { default: path52 } = await import("node:path");
|
|
34335
|
+
const tp = path52.join(os31.homedir(), ".olam", "host-cp.token");
|
|
34336
|
+
if (!fs51.existsSync(tp)) return { token: null };
|
|
34337
|
+
return { token: fs51.readFileSync(tp, "utf-8").trim() };
|
|
34068
34338
|
} catch {
|
|
34069
34339
|
return { token: null };
|
|
34070
34340
|
}
|
|
@@ -34324,9 +34594,9 @@ function register22(server, _ctx, _initError) {
|
|
|
34324
34594
|
description: external_exports.string().optional().describe("Optional human-readable description."),
|
|
34325
34595
|
defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
|
|
34326
34596
|
},
|
|
34327
|
-
async ({ name, path:
|
|
34597
|
+
async ({ name, path: path52, description, defaultBranch }) => {
|
|
34328
34598
|
try {
|
|
34329
|
-
const entry = addRepo({ name, path:
|
|
34599
|
+
const entry = addRepo({ name, path: path52, description, defaultBranch });
|
|
34330
34600
|
return {
|
|
34331
34601
|
content: [{
|
|
34332
34602
|
type: "text",
|
|
@@ -34367,9 +34637,9 @@ function register22(server, _ctx, _initError) {
|
|
|
34367
34637
|
description: external_exports.string().optional().describe("New description."),
|
|
34368
34638
|
defaultBranch: external_exports.string().optional().describe("New default branch.")
|
|
34369
34639
|
},
|
|
34370
|
-
async ({ name, path:
|
|
34640
|
+
async ({ name, path: path52, description, defaultBranch }) => {
|
|
34371
34641
|
try {
|
|
34372
|
-
const entry = updateRepo(name, { path:
|
|
34642
|
+
const entry = updateRepo(name, { path: path52, description, defaultBranch });
|
|
34373
34643
|
return {
|
|
34374
34644
|
content: [{
|
|
34375
34645
|
type: "text",
|
|
@@ -34941,10 +35211,196 @@ function register26(server, _ctx, _initError) {
|
|
|
34941
35211
|
);
|
|
34942
35212
|
}
|
|
34943
35213
|
|
|
35214
|
+
// ../mcp-server/src/tools/skills-search.ts
|
|
35215
|
+
var skills_search_exports = {};
|
|
35216
|
+
__export(skills_search_exports, {
|
|
35217
|
+
register: () => register27
|
|
35218
|
+
});
|
|
35219
|
+
init_v3();
|
|
35220
|
+
import * as path36 from "node:path";
|
|
35221
|
+
import * as os22 from "node:os";
|
|
35222
|
+
|
|
35223
|
+
// ../mcp-server/src/lib/skills-index.mjs
|
|
35224
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
35225
|
+
import * as fs36 from "node:fs";
|
|
35226
|
+
import * as path35 from "node:path";
|
|
35227
|
+
import * as os21 from "node:os";
|
|
35228
|
+
var VECTOR_DIM = 256;
|
|
35229
|
+
var SCHEMA_VERSION3 = "1";
|
|
35230
|
+
var SCHEMA_KEY = "skills_index_schema_version";
|
|
35231
|
+
var _require4 = createRequire4(import.meta.url);
|
|
35232
|
+
var _Database3 = null;
|
|
35233
|
+
function getDatabase3() {
|
|
35234
|
+
if (_Database3 === null) {
|
|
35235
|
+
_Database3 = _require4("better-sqlite3");
|
|
35236
|
+
}
|
|
35237
|
+
return _Database3;
|
|
35238
|
+
}
|
|
35239
|
+
var STOPWORDS = /* @__PURE__ */ new Set([
|
|
35240
|
+
"a",
|
|
35241
|
+
"an",
|
|
35242
|
+
"and",
|
|
35243
|
+
"the",
|
|
35244
|
+
"of",
|
|
35245
|
+
"to",
|
|
35246
|
+
"in",
|
|
35247
|
+
"on",
|
|
35248
|
+
"for",
|
|
35249
|
+
"with",
|
|
35250
|
+
"by",
|
|
35251
|
+
"is",
|
|
35252
|
+
"are",
|
|
35253
|
+
"be",
|
|
35254
|
+
"or",
|
|
35255
|
+
"as",
|
|
35256
|
+
"at",
|
|
35257
|
+
"it",
|
|
35258
|
+
"this",
|
|
35259
|
+
"that",
|
|
35260
|
+
"from",
|
|
35261
|
+
"use",
|
|
35262
|
+
"used",
|
|
35263
|
+
"when",
|
|
35264
|
+
"if",
|
|
35265
|
+
"via"
|
|
35266
|
+
]);
|
|
35267
|
+
function fnv1a32(str) {
|
|
35268
|
+
let h = 2166136261;
|
|
35269
|
+
for (let i = 0; i < str.length; i++) {
|
|
35270
|
+
h ^= str.charCodeAt(i);
|
|
35271
|
+
h = Math.imul(h, 16777619);
|
|
35272
|
+
}
|
|
35273
|
+
return h >>> 0;
|
|
35274
|
+
}
|
|
35275
|
+
function tokenize(text) {
|
|
35276
|
+
if (!text) return [];
|
|
35277
|
+
const tokens = [];
|
|
35278
|
+
for (const raw of text.toLowerCase().split(/[^a-z0-9]+/)) {
|
|
35279
|
+
if (raw.length < 2) continue;
|
|
35280
|
+
if (STOPWORDS.has(raw)) continue;
|
|
35281
|
+
tokens.push(raw);
|
|
35282
|
+
}
|
|
35283
|
+
return tokens;
|
|
35284
|
+
}
|
|
35285
|
+
function embed(text) {
|
|
35286
|
+
const vec = new Float32Array(VECTOR_DIM);
|
|
35287
|
+
const tokens = tokenize(text);
|
|
35288
|
+
if (tokens.length === 0) return vec;
|
|
35289
|
+
for (const tok of tokens) {
|
|
35290
|
+
const bucket = fnv1a32(tok) % VECTOR_DIM;
|
|
35291
|
+
vec[bucket] += 1;
|
|
35292
|
+
}
|
|
35293
|
+
let mag = 0;
|
|
35294
|
+
for (let i = 0; i < VECTOR_DIM; i++) mag += vec[i] * vec[i];
|
|
35295
|
+
mag = Math.sqrt(mag);
|
|
35296
|
+
if (mag > 0) {
|
|
35297
|
+
for (let i = 0; i < VECTOR_DIM; i++) vec[i] /= mag;
|
|
35298
|
+
}
|
|
35299
|
+
return vec;
|
|
35300
|
+
}
|
|
35301
|
+
function cosine(a, b) {
|
|
35302
|
+
let dot = 0;
|
|
35303
|
+
for (let i = 0; i < VECTOR_DIM; i++) dot += a[i] * b[i];
|
|
35304
|
+
return dot;
|
|
35305
|
+
}
|
|
35306
|
+
function bufferToVector(buf) {
|
|
35307
|
+
const ab = new ArrayBuffer(buf.byteLength);
|
|
35308
|
+
Buffer.from(ab).set(buf);
|
|
35309
|
+
const vec = new Float32Array(ab);
|
|
35310
|
+
if (vec.length !== VECTOR_DIM) {
|
|
35311
|
+
throw new Error(`vector length mismatch: expected ${VECTOR_DIM}, got ${vec.length}`);
|
|
35312
|
+
}
|
|
35313
|
+
return vec;
|
|
35314
|
+
}
|
|
35315
|
+
function openIndex(dbPath) {
|
|
35316
|
+
if (!fs36.existsSync(dbPath)) {
|
|
35317
|
+
throw new Error(
|
|
35318
|
+
`skills index not found at ${dbPath}. Run \`node scripts/skills-index-build.mjs --out ${dbPath}\` first.`
|
|
35319
|
+
);
|
|
35320
|
+
}
|
|
35321
|
+
const Database = getDatabase3();
|
|
35322
|
+
const db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
35323
|
+
let row;
|
|
35324
|
+
try {
|
|
35325
|
+
row = db.prepare("SELECT value FROM meta WHERE key = ?").get(SCHEMA_KEY);
|
|
35326
|
+
} catch (e) {
|
|
35327
|
+
db.close();
|
|
35328
|
+
throw new Error(`skills index at ${dbPath} is not a valid skills DB: ${e.message}`);
|
|
35329
|
+
}
|
|
35330
|
+
if (!row || row.value !== SCHEMA_VERSION3) {
|
|
35331
|
+
db.close();
|
|
35332
|
+
throw new Error(
|
|
35333
|
+
`skills index at ${dbPath} has schema version ${row ? row.value : "(none)"}, expected ${SCHEMA_VERSION3}. Rebuild it.`
|
|
35334
|
+
);
|
|
35335
|
+
}
|
|
35336
|
+
return db;
|
|
35337
|
+
}
|
|
35338
|
+
function searchIndex(dbPath, query, k = 5) {
|
|
35339
|
+
const db = openIndex(dbPath);
|
|
35340
|
+
try {
|
|
35341
|
+
const qvec = embed(query);
|
|
35342
|
+
let qmag = 0;
|
|
35343
|
+
for (let i = 0; i < VECTOR_DIM; i++) qmag += qvec[i] * qvec[i];
|
|
35344
|
+
if (qmag === 0) return [];
|
|
35345
|
+
const rows = db.prepare("SELECT name, description, vector FROM skills").all();
|
|
35346
|
+
const scored = rows.map((r) => {
|
|
35347
|
+
const v = bufferToVector(r.vector);
|
|
35348
|
+
const score = cosine(qvec, v);
|
|
35349
|
+
const snippet = (r.description || "").slice(0, 200);
|
|
35350
|
+
return { name: r.name, score, snippet };
|
|
35351
|
+
});
|
|
35352
|
+
scored.sort((a, b) => b.score - a.score);
|
|
35353
|
+
return scored.slice(0, Math.max(1, k));
|
|
35354
|
+
} finally {
|
|
35355
|
+
db.close();
|
|
35356
|
+
}
|
|
35357
|
+
}
|
|
35358
|
+
var DEFAULT_DB_PATH = path35.join(os21.homedir(), ".olam", "skills.vec.db");
|
|
35359
|
+
var DEFAULT_SOURCE_DIR = path35.join(os21.homedir(), ".claude", "skills");
|
|
35360
|
+
|
|
35361
|
+
// ../mcp-server/src/tools/skills-search.ts
|
|
35362
|
+
function defaultDbPath() {
|
|
35363
|
+
const override = process.env["SKILLS_INDEX_PATH"];
|
|
35364
|
+
if (override) return override;
|
|
35365
|
+
return path36.join(os22.homedir(), ".olam", "skills.vec.db");
|
|
35366
|
+
}
|
|
35367
|
+
function asMessage9(err) {
|
|
35368
|
+
return err instanceof Error ? err.message : String(err);
|
|
35369
|
+
}
|
|
35370
|
+
function ok3(data) {
|
|
35371
|
+
return {
|
|
35372
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
35373
|
+
};
|
|
35374
|
+
}
|
|
35375
|
+
function fail3(err) {
|
|
35376
|
+
return {
|
|
35377
|
+
content: [{ type: "text", text: asMessage9(err) }],
|
|
35378
|
+
isError: true
|
|
35379
|
+
};
|
|
35380
|
+
}
|
|
35381
|
+
function register27(server, _ctx, _initError) {
|
|
35382
|
+
server.tool(
|
|
35383
|
+
"olam_skills_search",
|
|
35384
|
+
"Semantic search over the local Claude skills index. Returns top-k skills ranked by cosine similarity against a deterministic bag-of-words embedding. Requires `scripts/skills-index-build.mjs` to have been run; set `SKILLS_INDEX_PATH` to override the index location (defaults to ~/.olam/skills.vec.db).",
|
|
35385
|
+
{
|
|
35386
|
+
query: external_exports.string().min(1).describe('Natural-language description of the kind of skill you want (e.g. "stage and commit my changes" or "roll out a new release").'),
|
|
35387
|
+
k: external_exports.number().int().min(1).max(50).optional().describe("Number of hits to return (default 5, max 50).")
|
|
35388
|
+
},
|
|
35389
|
+
async ({ query, k }) => {
|
|
35390
|
+
try {
|
|
35391
|
+
const hits = searchIndex(defaultDbPath(), query, k ?? 5);
|
|
35392
|
+
return ok3({ query, k: k ?? 5, count: hits.length, hits });
|
|
35393
|
+
} catch (err) {
|
|
35394
|
+
return fail3(err);
|
|
35395
|
+
}
|
|
35396
|
+
}
|
|
35397
|
+
);
|
|
35398
|
+
}
|
|
35399
|
+
|
|
34944
35400
|
// ../mcp-server/src/tools/kg-classify.ts
|
|
34945
35401
|
var kg_classify_exports = {};
|
|
34946
35402
|
__export(kg_classify_exports, {
|
|
34947
|
-
register: () =>
|
|
35403
|
+
register: () => register28
|
|
34948
35404
|
});
|
|
34949
35405
|
init_v3();
|
|
34950
35406
|
|
|
@@ -34957,8 +35413,8 @@ function port() {
|
|
|
34957
35413
|
const n = Number.parseInt(env, 10);
|
|
34958
35414
|
return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
|
|
34959
35415
|
}
|
|
34960
|
-
function url(
|
|
34961
|
-
return `http://127.0.0.1:${port()}${
|
|
35416
|
+
function url(path52) {
|
|
35417
|
+
return `http://127.0.0.1:${port()}${path52}`;
|
|
34962
35418
|
}
|
|
34963
35419
|
function kgServiceHealthUrl() {
|
|
34964
35420
|
return url("/health");
|
|
@@ -35019,7 +35475,7 @@ async function status(opts = {}) {
|
|
|
35019
35475
|
}
|
|
35020
35476
|
|
|
35021
35477
|
// ../mcp-server/src/tools/kg-classify.ts
|
|
35022
|
-
function
|
|
35478
|
+
function register28(server, _ctx, _initError) {
|
|
35023
35479
|
server.tool(
|
|
35024
35480
|
"olam_kg_classify",
|
|
35025
35481
|
"Route a question to kg | grep | both via the 4-layer classifier (kg-service container). Returns route + layer + reason + matched exemplar. Requires olam-kg-service running (see `olam services up`).",
|
|
@@ -35067,7 +35523,7 @@ function register27(server, _ctx, _initError) {
|
|
|
35067
35523
|
// ../mcp-server/src/tools/kg-doctor.ts
|
|
35068
35524
|
var kg_doctor_exports = {};
|
|
35069
35525
|
__export(kg_doctor_exports, {
|
|
35070
|
-
register: () =>
|
|
35526
|
+
register: () => register29
|
|
35071
35527
|
});
|
|
35072
35528
|
async function runProbes() {
|
|
35073
35529
|
const results = [];
|
|
@@ -35117,7 +35573,7 @@ async function runProbes() {
|
|
|
35117
35573
|
}
|
|
35118
35574
|
return results;
|
|
35119
35575
|
}
|
|
35120
|
-
function
|
|
35576
|
+
function register29(server, _ctx, _initError) {
|
|
35121
35577
|
server.tool(
|
|
35122
35578
|
"olam_kg_doctor",
|
|
35123
35579
|
"Diagnostic report for olam-kg-service over HTTP: /health readiness, workspace inventory, and /classify round-trip. Returns a JSON `probes` array. If the container isn't running, all probes fail with a hint to run `olam services up`.",
|
|
@@ -35153,13 +35609,13 @@ function register28(server, _ctx, _initError) {
|
|
|
35153
35609
|
// ../mcp-server/src/tools/kg-install-hook.ts
|
|
35154
35610
|
var kg_install_hook_exports = {};
|
|
35155
35611
|
__export(kg_install_hook_exports, {
|
|
35156
|
-
register: () =>
|
|
35612
|
+
register: () => register30
|
|
35157
35613
|
});
|
|
35158
35614
|
init_v3();
|
|
35159
35615
|
init_merge_settings();
|
|
35160
|
-
import * as
|
|
35161
|
-
import * as
|
|
35162
|
-
import * as
|
|
35616
|
+
import * as fs37 from "node:fs";
|
|
35617
|
+
import * as path37 from "node:path";
|
|
35618
|
+
import * as os23 from "node:os";
|
|
35163
35619
|
|
|
35164
35620
|
// ../core/dist/kg/hook-template.js
|
|
35165
35621
|
var KG_HOOK_SENTINEL = "kg-service-v2-classifier-hook";
|
|
@@ -35209,12 +35665,12 @@ function buildHookMatcherEntry(opts) {
|
|
|
35209
35665
|
// ../mcp-server/src/tools/kg-install-hook.ts
|
|
35210
35666
|
function settingsPathFor2(scope, projectPath) {
|
|
35211
35667
|
if (scope === "user") {
|
|
35212
|
-
return
|
|
35668
|
+
return path37.join(os23.homedir(), ".claude", "settings.json");
|
|
35213
35669
|
}
|
|
35214
35670
|
const root = projectPath ?? process.cwd();
|
|
35215
|
-
return
|
|
35671
|
+
return path37.join(root, ".claude", "settings.json");
|
|
35216
35672
|
}
|
|
35217
|
-
function
|
|
35673
|
+
function register30(server, _ctx, _initError) {
|
|
35218
35674
|
server.tool(
|
|
35219
35675
|
"olam_kg_install_hook",
|
|
35220
35676
|
"Install the kg-service PreToolUse hook into .claude/settings.json. Idempotent (sentinel-detected). Default scope=project (writes <cwd>/.claude/settings.json); scope=user writes ~/.claude/settings.json.",
|
|
@@ -35226,12 +35682,12 @@ function register29(server, _ctx, _initError) {
|
|
|
35226
35682
|
const scope = params.scope === "user" ? "user" : "project";
|
|
35227
35683
|
const filePath = settingsPathFor2(scope, params.projectPath);
|
|
35228
35684
|
try {
|
|
35229
|
-
|
|
35685
|
+
fs37.mkdirSync(path37.dirname(filePath), { recursive: true });
|
|
35230
35686
|
let backupPath = null;
|
|
35231
|
-
if (
|
|
35687
|
+
if (fs37.existsSync(filePath)) {
|
|
35232
35688
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
35233
35689
|
backupPath = `${filePath}.olam-bak.${ts}`;
|
|
35234
|
-
|
|
35690
|
+
fs37.copyFileSync(filePath, backupPath);
|
|
35235
35691
|
}
|
|
35236
35692
|
const result = mergeHomeSettingsJson(filePath, {
|
|
35237
35693
|
ensureHook: {
|
|
@@ -35242,7 +35698,7 @@ function register29(server, _ctx, _initError) {
|
|
|
35242
35698
|
});
|
|
35243
35699
|
if (result.status === "already-present" && backupPath) {
|
|
35244
35700
|
try {
|
|
35245
|
-
|
|
35701
|
+
fs37.unlinkSync(backupPath);
|
|
35246
35702
|
} catch {
|
|
35247
35703
|
}
|
|
35248
35704
|
}
|
|
@@ -35283,18 +35739,18 @@ function register29(server, _ctx, _initError) {
|
|
|
35283
35739
|
// ../mcp-server/src/tools/kg-uninstall-hook.ts
|
|
35284
35740
|
var kg_uninstall_hook_exports = {};
|
|
35285
35741
|
__export(kg_uninstall_hook_exports, {
|
|
35286
|
-
register: () =>
|
|
35742
|
+
register: () => register31
|
|
35287
35743
|
});
|
|
35288
35744
|
init_v3();
|
|
35289
|
-
import * as
|
|
35290
|
-
import * as
|
|
35291
|
-
import * as
|
|
35745
|
+
import * as fs38 from "node:fs";
|
|
35746
|
+
import * as path38 from "node:path";
|
|
35747
|
+
import * as os24 from "node:os";
|
|
35292
35748
|
function settingsPathFor3(scope, projectPath) {
|
|
35293
35749
|
if (scope === "user") {
|
|
35294
|
-
return
|
|
35750
|
+
return path38.join(os24.homedir(), ".claude", "settings.json");
|
|
35295
35751
|
}
|
|
35296
35752
|
const root = projectPath ?? process.cwd();
|
|
35297
|
-
return
|
|
35753
|
+
return path38.join(root, ".claude", "settings.json");
|
|
35298
35754
|
}
|
|
35299
35755
|
function dropSentinel(matchers) {
|
|
35300
35756
|
let changed = false;
|
|
@@ -35316,7 +35772,7 @@ function dropSentinel(matchers) {
|
|
|
35316
35772
|
}
|
|
35317
35773
|
return { matchers: out, changed };
|
|
35318
35774
|
}
|
|
35319
|
-
function
|
|
35775
|
+
function register31(server, _ctx, _initError) {
|
|
35320
35776
|
server.tool(
|
|
35321
35777
|
"olam_kg_uninstall_hook",
|
|
35322
35778
|
"Remove the kg-service PreToolUse hook from .claude/settings.json. Sentinel-matched: only the olam entry is removed; other PreToolUse hooks are preserved.",
|
|
@@ -35328,7 +35784,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35328
35784
|
const scope = params.scope === "user" ? "user" : "project";
|
|
35329
35785
|
const filePath = settingsPathFor3(scope, params.projectPath);
|
|
35330
35786
|
try {
|
|
35331
|
-
if (!
|
|
35787
|
+
if (!fs38.existsSync(filePath)) {
|
|
35332
35788
|
return {
|
|
35333
35789
|
content: [
|
|
35334
35790
|
{
|
|
@@ -35342,7 +35798,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35342
35798
|
]
|
|
35343
35799
|
};
|
|
35344
35800
|
}
|
|
35345
|
-
const raw =
|
|
35801
|
+
const raw = fs38.readFileSync(filePath, "utf-8");
|
|
35346
35802
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
35347
35803
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
35348
35804
|
if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
|
|
@@ -35377,7 +35833,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35377
35833
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
35378
35834
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
35379
35835
|
try {
|
|
35380
|
-
|
|
35836
|
+
fs38.copyFileSync(filePath, backupPath);
|
|
35381
35837
|
} catch {
|
|
35382
35838
|
}
|
|
35383
35839
|
const next = {
|
|
@@ -35389,7 +35845,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35389
35845
|
if (otherStages.length === 0) delete next.hooks;
|
|
35390
35846
|
else delete next.hooks.PreToolUse;
|
|
35391
35847
|
}
|
|
35392
|
-
|
|
35848
|
+
fs38.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
35393
35849
|
return {
|
|
35394
35850
|
content: [
|
|
35395
35851
|
{
|
|
@@ -35451,6 +35907,7 @@ var toolModules = [
|
|
|
35451
35907
|
runbook_exports,
|
|
35452
35908
|
skill_source_exports,
|
|
35453
35909
|
skills_exports,
|
|
35910
|
+
skills_search_exports,
|
|
35454
35911
|
kg_classify_exports,
|
|
35455
35912
|
kg_doctor_exports,
|
|
35456
35913
|
kg_install_hook_exports,
|
|
@@ -35462,6 +35919,207 @@ function registerAllTools(server, ctx, initError) {
|
|
|
35462
35919
|
}
|
|
35463
35920
|
}
|
|
35464
35921
|
|
|
35922
|
+
// ../mcp-server/src/resources/chunks.ts
|
|
35923
|
+
import fs39 from "node:fs";
|
|
35924
|
+
import os25 from "node:os";
|
|
35925
|
+
import path39 from "node:path";
|
|
35926
|
+
var DEFAULT_HOST_CP_URL = "http://127.0.0.1:19000";
|
|
35927
|
+
var DEFAULT_PLAN_CHAT_SECRET_PATH = path39.join(
|
|
35928
|
+
os25.homedir(),
|
|
35929
|
+
".olam",
|
|
35930
|
+
"plan-chat-secret"
|
|
35931
|
+
);
|
|
35932
|
+
var URI_SCHEME = "olam:";
|
|
35933
|
+
var URI_HOST = "worlds";
|
|
35934
|
+
var WORLD_ID_RE2 = /^[a-z0-9][a-z0-9-_.]{0,62}$/i;
|
|
35935
|
+
var SESSION_ID_RE = /^[a-zA-Z0-9_\-.]{1,128}$/;
|
|
35936
|
+
var LIMIT_RE = /^[1-9][0-9]{0,5}$/;
|
|
35937
|
+
function loadBearer(bearerOpt, secretPath) {
|
|
35938
|
+
if (typeof bearerOpt === "string" && bearerOpt.length > 0) return bearerOpt;
|
|
35939
|
+
const envBearer = process.env.OLAM_PLAN_CHAT_BEARER?.trim();
|
|
35940
|
+
if (envBearer && envBearer.length > 0) return envBearer;
|
|
35941
|
+
try {
|
|
35942
|
+
const onDisk = fs39.readFileSync(secretPath, "utf8").trim();
|
|
35943
|
+
return onDisk.length > 0 ? onDisk : null;
|
|
35944
|
+
} catch (err) {
|
|
35945
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
|
|
35946
|
+
return null;
|
|
35947
|
+
}
|
|
35948
|
+
return null;
|
|
35949
|
+
}
|
|
35950
|
+
}
|
|
35951
|
+
function parseChunksUri(uri) {
|
|
35952
|
+
let parsed;
|
|
35953
|
+
try {
|
|
35954
|
+
parsed = new URL(uri);
|
|
35955
|
+
} catch {
|
|
35956
|
+
return null;
|
|
35957
|
+
}
|
|
35958
|
+
if (parsed.protocol !== URI_SCHEME) return null;
|
|
35959
|
+
if (parsed.host !== URI_HOST) return null;
|
|
35960
|
+
const segments = parsed.pathname.split("/").filter((s) => s.length > 0);
|
|
35961
|
+
if (segments.length !== 2) return null;
|
|
35962
|
+
const [rawWorldId, kind] = segments;
|
|
35963
|
+
if (rawWorldId === void 0 || kind !== "chunks") return null;
|
|
35964
|
+
const worldId = decodeURIComponent(rawWorldId);
|
|
35965
|
+
if (!WORLD_ID_RE2.test(worldId)) return null;
|
|
35966
|
+
const sessionIdRaw = parsed.searchParams.get("sessionId");
|
|
35967
|
+
const limitRaw = parsed.searchParams.get("limit");
|
|
35968
|
+
let sessionId;
|
|
35969
|
+
if (sessionIdRaw !== null) {
|
|
35970
|
+
if (!SESSION_ID_RE.test(sessionIdRaw)) return null;
|
|
35971
|
+
sessionId = sessionIdRaw;
|
|
35972
|
+
}
|
|
35973
|
+
let limit;
|
|
35974
|
+
if (limitRaw !== null) {
|
|
35975
|
+
if (!LIMIT_RE.test(limitRaw)) return null;
|
|
35976
|
+
limit = Number.parseInt(limitRaw, 10);
|
|
35977
|
+
}
|
|
35978
|
+
return { worldId, sessionId, limit };
|
|
35979
|
+
}
|
|
35980
|
+
function buildUpstreamUrl(hostCpUrl, parts) {
|
|
35981
|
+
const upstream = new URL(hostCpUrl);
|
|
35982
|
+
upstream.pathname = "/api/plan-chat/v1/shape";
|
|
35983
|
+
upstream.searchParams.set("table", "chunks");
|
|
35984
|
+
upstream.searchParams.set("world_id", parts.worldId);
|
|
35985
|
+
if (parts.sessionId) {
|
|
35986
|
+
upstream.searchParams.set("session_id", parts.sessionId);
|
|
35987
|
+
}
|
|
35988
|
+
if (typeof parts.limit === "number") {
|
|
35989
|
+
upstream.searchParams.set("limit", String(parts.limit));
|
|
35990
|
+
}
|
|
35991
|
+
upstream.searchParams.set("offset", "-1");
|
|
35992
|
+
return upstream;
|
|
35993
|
+
}
|
|
35994
|
+
function createChunksResource(deps = {}) {
|
|
35995
|
+
const hostCpUrl = deps.hostCpUrl ?? process.env.OLAM_HOST_CP_URL?.trim() ?? DEFAULT_HOST_CP_URL;
|
|
35996
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
35997
|
+
const secretPath = deps.secretPath ?? DEFAULT_PLAN_CHAT_SECRET_PATH;
|
|
35998
|
+
const resolveBearer = () => loadBearer(deps.bearer, secretPath);
|
|
35999
|
+
return {
|
|
36000
|
+
name: "olam-world-chunks",
|
|
36001
|
+
// RFC 6570 form with required `sessionId` in the template (the SDK's
|
|
36002
|
+
// matcher treats every listed var as required, so listing both
|
|
36003
|
+
// `sessionId` AND `limit` would reject URIs that only pass sessionId).
|
|
36004
|
+
// The optional `limit` param is parsed by `parseChunksUri` from the
|
|
36005
|
+
// concrete URL instead — clients pass `?sessionId=...&limit=...` and
|
|
36006
|
+
// both fields land in `ChunksUriParts`.
|
|
36007
|
+
uriTemplate: "olam://worlds/{worldId}/chunks{?sessionId}",
|
|
36008
|
+
description: "Per-world agent reasoning chunks (the chunks substrate). Append `?sessionId=<id>` to scope to a single planning session \u2014 Electric SQL requires it server-side. Optional `&limit=<n>` caps the returned row count. Returns the Electric shape snapshot as JSON.",
|
|
36009
|
+
mimeType: "application/json",
|
|
36010
|
+
parseUri: parseChunksUri,
|
|
36011
|
+
async read(uri) {
|
|
36012
|
+
const parts = parseChunksUri(uri);
|
|
36013
|
+
if (!parts) {
|
|
36014
|
+
return {
|
|
36015
|
+
ok: false,
|
|
36016
|
+
code: "invalid_uri",
|
|
36017
|
+
message: `Invalid chunks URI: ${uri}. Expected \`olam://worlds/{worldId}/chunks?sessionId=<id>\`.`
|
|
36018
|
+
};
|
|
36019
|
+
}
|
|
36020
|
+
if (!parts.sessionId) {
|
|
36021
|
+
return {
|
|
36022
|
+
ok: false,
|
|
36023
|
+
code: "missing_session_id",
|
|
36024
|
+
message: "sessionId query param is required. Electric SQL enforces per-(world_id,session_id) scope at the proxy layer."
|
|
36025
|
+
};
|
|
36026
|
+
}
|
|
36027
|
+
const bearer = resolveBearer();
|
|
36028
|
+
if (!bearer) {
|
|
36029
|
+
return {
|
|
36030
|
+
ok: false,
|
|
36031
|
+
code: "missing_bearer",
|
|
36032
|
+
message: "No plan-chat bearer available. Set OLAM_PLAN_CHAT_BEARER or ensure ~/.olam/plan-chat-secret exists."
|
|
36033
|
+
};
|
|
36034
|
+
}
|
|
36035
|
+
const upstream = buildUpstreamUrl(hostCpUrl, parts);
|
|
36036
|
+
let res;
|
|
36037
|
+
try {
|
|
36038
|
+
res = await fetchImpl(upstream.toString(), {
|
|
36039
|
+
method: "GET",
|
|
36040
|
+
headers: {
|
|
36041
|
+
authorization: `Bearer ${bearer}`,
|
|
36042
|
+
accept: "application/json"
|
|
36043
|
+
}
|
|
36044
|
+
});
|
|
36045
|
+
} catch (err) {
|
|
36046
|
+
return {
|
|
36047
|
+
ok: false,
|
|
36048
|
+
code: "upstream_unavailable",
|
|
36049
|
+
message: `host-cp /api/plan-chat/v1/shape unreachable: ${err instanceof Error ? err.message : String(err)}`,
|
|
36050
|
+
detail: { upstream: upstream.toString() }
|
|
36051
|
+
};
|
|
36052
|
+
}
|
|
36053
|
+
if (!res.ok) {
|
|
36054
|
+
let body = "";
|
|
36055
|
+
try {
|
|
36056
|
+
body = await res.text();
|
|
36057
|
+
} catch {
|
|
36058
|
+
}
|
|
36059
|
+
return {
|
|
36060
|
+
ok: false,
|
|
36061
|
+
code: "upstream_error",
|
|
36062
|
+
message: `host-cp returned ${res.status} ${res.statusText} for chunks fetch`,
|
|
36063
|
+
detail: { upstream: upstream.toString(), body: body.slice(0, 512) }
|
|
36064
|
+
};
|
|
36065
|
+
}
|
|
36066
|
+
let payload;
|
|
36067
|
+
try {
|
|
36068
|
+
payload = await res.json();
|
|
36069
|
+
} catch (err) {
|
|
36070
|
+
return {
|
|
36071
|
+
ok: false,
|
|
36072
|
+
code: "upstream_error",
|
|
36073
|
+
message: `host-cp returned non-JSON body for chunks fetch: ${err instanceof Error ? err.message : String(err)}`,
|
|
36074
|
+
detail: { upstream: upstream.toString() }
|
|
36075
|
+
};
|
|
36076
|
+
}
|
|
36077
|
+
return {
|
|
36078
|
+
ok: true,
|
|
36079
|
+
uri,
|
|
36080
|
+
mimeType: "application/json",
|
|
36081
|
+
payload
|
|
36082
|
+
};
|
|
36083
|
+
}
|
|
36084
|
+
};
|
|
36085
|
+
}
|
|
36086
|
+
|
|
36087
|
+
// ../mcp-server/src/resources/index.ts
|
|
36088
|
+
function registerAllResources(server, deps = {}) {
|
|
36089
|
+
const chunks = deps.chunks ?? createChunksResource();
|
|
36090
|
+
server.registerResource(
|
|
36091
|
+
chunks.name,
|
|
36092
|
+
new ResourceTemplate(chunks.uriTemplate, {
|
|
36093
|
+
list: void 0
|
|
36094
|
+
}),
|
|
36095
|
+
{
|
|
36096
|
+
description: chunks.description,
|
|
36097
|
+
mimeType: chunks.mimeType
|
|
36098
|
+
},
|
|
36099
|
+
async (uri) => {
|
|
36100
|
+
const result = await chunks.read(uri.toString());
|
|
36101
|
+
if (!result.ok) {
|
|
36102
|
+
const err = new Error(result.message);
|
|
36103
|
+
err.code = result.code;
|
|
36104
|
+
throw err;
|
|
36105
|
+
}
|
|
36106
|
+
return {
|
|
36107
|
+
contents: [
|
|
36108
|
+
{
|
|
36109
|
+
uri: result.uri,
|
|
36110
|
+
mimeType: result.mimeType,
|
|
36111
|
+
text: JSON.stringify(result.payload)
|
|
36112
|
+
}
|
|
36113
|
+
]
|
|
36114
|
+
};
|
|
36115
|
+
}
|
|
36116
|
+
);
|
|
36117
|
+
logger.info("Olam MCP resources registered", {
|
|
36118
|
+
resources: [chunks.name],
|
|
36119
|
+
uriTemplate: chunks.uriTemplate
|
|
36120
|
+
});
|
|
36121
|
+
}
|
|
36122
|
+
|
|
35465
36123
|
// ../mcp-server/src/server.ts
|
|
35466
36124
|
var SERVER_NAME = "olam";
|
|
35467
36125
|
var SERVER_VERSION = "0.1.0";
|
|
@@ -35477,6 +36135,7 @@ function createServer4(ctx, initError) {
|
|
|
35477
36135
|
{ instructions: SERVER_INSTRUCTIONS }
|
|
35478
36136
|
);
|
|
35479
36137
|
registerAllTools(server, ctx, initError);
|
|
36138
|
+
registerAllResources(server);
|
|
35480
36139
|
logger.info("Olam MCP server created", {
|
|
35481
36140
|
name: SERVER_NAME,
|
|
35482
36141
|
version: SERVER_VERSION,
|
|
@@ -35486,8 +36145,8 @@ function createServer4(ctx, initError) {
|
|
|
35486
36145
|
}
|
|
35487
36146
|
|
|
35488
36147
|
// ../mcp-server/src/utils/native-probe.ts
|
|
35489
|
-
import { createRequire as
|
|
35490
|
-
var PROBE_REQUIRE =
|
|
36148
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
36149
|
+
var PROBE_REQUIRE = createRequire5(import.meta.url);
|
|
35491
36150
|
function runtimeModuleVersion() {
|
|
35492
36151
|
return Number.parseInt(process.versions.modules, 10);
|
|
35493
36152
|
}
|
|
@@ -35604,9 +36263,9 @@ init_loader();
|
|
|
35604
36263
|
// ../core/dist/world/manager.js
|
|
35605
36264
|
import * as crypto8 from "node:crypto";
|
|
35606
36265
|
import { execSync as execSync5, spawnSync as spawnSync4 } from "node:child_process";
|
|
35607
|
-
import * as
|
|
35608
|
-
import * as
|
|
35609
|
-
import * as
|
|
36266
|
+
import * as fs48 from "node:fs";
|
|
36267
|
+
import * as os29 from "node:os";
|
|
36268
|
+
import * as path49 from "node:path";
|
|
35610
36269
|
|
|
35611
36270
|
// ../core/dist/world/state.js
|
|
35612
36271
|
var VALID_TRANSITIONS = {
|
|
@@ -35702,8 +36361,8 @@ function resolveDevboxImage(config2, tag) {
|
|
|
35702
36361
|
|
|
35703
36362
|
// ../core/dist/world/worktree.js
|
|
35704
36363
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
35705
|
-
import * as
|
|
35706
|
-
import * as
|
|
36364
|
+
import * as fs40 from "node:fs";
|
|
36365
|
+
import * as path40 from "node:path";
|
|
35707
36366
|
function resolveGitDir(repo) {
|
|
35708
36367
|
if (repo.path) {
|
|
35709
36368
|
return repo.path;
|
|
@@ -35713,11 +36372,11 @@ function resolveGitDir(repo) {
|
|
|
35713
36372
|
async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
35714
36373
|
const created = [];
|
|
35715
36374
|
for (const repo of repos) {
|
|
35716
|
-
const worktreePath =
|
|
36375
|
+
const worktreePath = path40.join(workspacePath, repo.name);
|
|
35717
36376
|
const gitDir = resolveGitDir(repo);
|
|
35718
36377
|
const branchName = branch || `olam/${worldId}`;
|
|
35719
36378
|
try {
|
|
35720
|
-
|
|
36379
|
+
fs40.mkdirSync(path40.dirname(worktreePath), { recursive: true });
|
|
35721
36380
|
execFileSync4("git", ["worktree", "add", worktreePath, "-b", branchName], {
|
|
35722
36381
|
cwd: gitDir,
|
|
35723
36382
|
stdio: "pipe"
|
|
@@ -35750,7 +36409,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
|
35750
36409
|
}
|
|
35751
36410
|
async function removeWorktrees(repos, workspacePath) {
|
|
35752
36411
|
for (const repo of repos) {
|
|
35753
|
-
const worktreePath =
|
|
36412
|
+
const worktreePath = path40.join(workspacePath, repo.name);
|
|
35754
36413
|
let gitDir;
|
|
35755
36414
|
try {
|
|
35756
36415
|
gitDir = resolveGitDir(repo);
|
|
@@ -35825,12 +36484,12 @@ function removeBranch(repo, branch) {
|
|
|
35825
36484
|
|
|
35826
36485
|
// ../core/dist/world/kg-overlay.js
|
|
35827
36486
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
35828
|
-
import * as
|
|
35829
|
-
import * as
|
|
36487
|
+
import * as fs41 from "node:fs";
|
|
36488
|
+
import * as path41 from "node:path";
|
|
35830
36489
|
|
|
35831
36490
|
// ../core/dist/kg/storage-paths.js
|
|
35832
|
-
import { homedir as
|
|
35833
|
-
import { join as
|
|
36491
|
+
import { homedir as homedir24 } from "node:os";
|
|
36492
|
+
import { join as join40, resolve as resolve9 } from "node:path";
|
|
35834
36493
|
|
|
35835
36494
|
// ../core/dist/world/workspace-name.js
|
|
35836
36495
|
var InvalidWorkspaceNameError = class extends Error {
|
|
@@ -35851,25 +36510,25 @@ function validateWorkspaceName(name) {
|
|
|
35851
36510
|
|
|
35852
36511
|
// ../core/dist/kg/storage-paths.js
|
|
35853
36512
|
function olamHome() {
|
|
35854
|
-
return process.env.OLAM_HOME ??
|
|
36513
|
+
return process.env.OLAM_HOME ?? join40(homedir24(), ".olam");
|
|
35855
36514
|
}
|
|
35856
36515
|
function kgRoot() {
|
|
35857
|
-
return
|
|
36516
|
+
return join40(olamHome(), "kg");
|
|
35858
36517
|
}
|
|
35859
36518
|
function worldsRoot() {
|
|
35860
|
-
return
|
|
36519
|
+
return join40(olamHome(), "worlds");
|
|
35861
36520
|
}
|
|
35862
|
-
function assertWithinPrefix(
|
|
35863
|
-
if (!
|
|
35864
|
-
throw new Error(`${label} escape: ${
|
|
36521
|
+
function assertWithinPrefix(path52, prefix, label) {
|
|
36522
|
+
if (!path52.startsWith(prefix + "/")) {
|
|
36523
|
+
throw new Error(`${label} escape: ${path52} not under ${prefix}/`);
|
|
35865
36524
|
}
|
|
35866
36525
|
}
|
|
35867
36526
|
function kgPristinePath(workspace) {
|
|
35868
36527
|
validateWorkspaceName(workspace);
|
|
35869
36528
|
const root = kgRoot();
|
|
35870
|
-
const
|
|
35871
|
-
assertWithinPrefix(
|
|
35872
|
-
return
|
|
36529
|
+
const path52 = resolve9(join40(root, workspace));
|
|
36530
|
+
assertWithinPrefix(path52, root, "kgPristinePath");
|
|
36531
|
+
return path52;
|
|
35873
36532
|
}
|
|
35874
36533
|
var KG_PATHS_INTERNALS = Object.freeze({
|
|
35875
36534
|
olamHome,
|
|
@@ -35885,10 +36544,10 @@ var KgOverlayError = class extends Error {
|
|
|
35885
36544
|
}
|
|
35886
36545
|
};
|
|
35887
36546
|
function ensureGitignoreEntry(worldClonePath) {
|
|
35888
|
-
const gitignorePath =
|
|
35889
|
-
if (!
|
|
36547
|
+
const gitignorePath = path41.join(worldClonePath, ".gitignore");
|
|
36548
|
+
if (!fs41.existsSync(gitignorePath))
|
|
35890
36549
|
return "no-gitignore";
|
|
35891
|
-
const content =
|
|
36550
|
+
const content = fs41.readFileSync(gitignorePath, "utf-8");
|
|
35892
36551
|
const lines = content.split("\n").map((l) => l.trim());
|
|
35893
36552
|
const recognised = /* @__PURE__ */ new Set([
|
|
35894
36553
|
"graphify-out",
|
|
@@ -35903,24 +36562,24 @@ function ensureGitignoreEntry(worldClonePath) {
|
|
|
35903
36562
|
const eol = content.includes("\r\n") ? "\r\n" : "\n";
|
|
35904
36563
|
const needsLeadingNewline = content.length > 0 && !content.endsWith(eol);
|
|
35905
36564
|
const block = `${needsLeadingNewline ? eol : ""}${eol}# olam-kg-service: per-world KG overlay (Phase B1)${eol}graphify-out/${eol}`;
|
|
35906
|
-
|
|
36565
|
+
fs41.appendFileSync(gitignorePath, block, "utf-8");
|
|
35907
36566
|
return "appended";
|
|
35908
36567
|
}
|
|
35909
36568
|
function createWorldOverlay(opts) {
|
|
35910
36569
|
const pristineRoot = kgPristinePath(opts.workspace);
|
|
35911
|
-
const pristinePath =
|
|
35912
|
-
if (!
|
|
36570
|
+
const pristinePath = path41.join(pristineRoot, "graphify-out");
|
|
36571
|
+
if (!fs41.existsSync(pristinePath)) {
|
|
35913
36572
|
throw new KgOverlayError(`Pristine KG for workspace ${JSON.stringify(opts.workspace)} not found at ${pristinePath}. Run \`olam kg build ${opts.workspace}\` first.`);
|
|
35914
36573
|
}
|
|
35915
|
-
if (!
|
|
36574
|
+
if (!path41.isAbsolute(opts.worldClonePath)) {
|
|
35916
36575
|
throw new KgOverlayError(`worldClonePath must be absolute (got ${opts.worldClonePath})`);
|
|
35917
36576
|
}
|
|
35918
|
-
if (!
|
|
36577
|
+
if (!fs41.existsSync(opts.worldClonePath)) {
|
|
35919
36578
|
throw new KgOverlayError(`worldClonePath does not exist: ${opts.worldClonePath}. Create the clone before reflinking.`);
|
|
35920
36579
|
}
|
|
35921
|
-
const overlayPath =
|
|
35922
|
-
if (
|
|
35923
|
-
|
|
36580
|
+
const overlayPath = path41.join(opts.worldClonePath, "graphify-out");
|
|
36581
|
+
if (fs41.existsSync(overlayPath)) {
|
|
36582
|
+
fs41.rmSync(overlayPath, { recursive: true, force: true });
|
|
35924
36583
|
}
|
|
35925
36584
|
const useReflink = process.platform === "darwin";
|
|
35926
36585
|
let strategy;
|
|
@@ -35938,7 +36597,7 @@ function createWorldOverlay(opts) {
|
|
|
35938
36597
|
} else {
|
|
35939
36598
|
strategy = "cp-r";
|
|
35940
36599
|
}
|
|
35941
|
-
if (strategy === "cp-r" || !
|
|
36600
|
+
if (strategy === "cp-r" || !fs41.existsSync(overlayPath)) {
|
|
35942
36601
|
try {
|
|
35943
36602
|
execFileSync5("cp", ["-r", pristinePath, opts.worldClonePath], {
|
|
35944
36603
|
stdio: ["ignore", "ignore", "pipe"]
|
|
@@ -35950,7 +36609,7 @@ function createWorldOverlay(opts) {
|
|
|
35950
36609
|
throw new KgOverlayError(`cp -r failed: ${msg}${reflinkMsg}`);
|
|
35951
36610
|
}
|
|
35952
36611
|
}
|
|
35953
|
-
if (!
|
|
36612
|
+
if (!fs41.existsSync(overlayPath)) {
|
|
35954
36613
|
throw new KgOverlayError(`Overlay creation produced no ${overlayPath} after cp \u2014 filesystem returned without error?`);
|
|
35955
36614
|
}
|
|
35956
36615
|
const gitignoreAction = ensureGitignoreEntry(opts.worldClonePath);
|
|
@@ -35964,12 +36623,12 @@ function createWorldOverlay(opts) {
|
|
|
35964
36623
|
|
|
35965
36624
|
// ../core/dist/world/baseline-diff.js
|
|
35966
36625
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
35967
|
-
import * as
|
|
35968
|
-
import * as
|
|
35969
|
-
import * as
|
|
36626
|
+
import * as fs42 from "node:fs";
|
|
36627
|
+
import * as os26 from "node:os";
|
|
36628
|
+
import * as path42 from "node:path";
|
|
35970
36629
|
var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
35971
|
-
function expandHome2(p,
|
|
35972
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
36630
|
+
function expandHome2(p, homedir30) {
|
|
36631
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir30());
|
|
35973
36632
|
}
|
|
35974
36633
|
function sanitizeRepoFilename(name) {
|
|
35975
36634
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -35992,10 +36651,10 @@ ${stderr}`;
|
|
|
35992
36651
|
}
|
|
35993
36652
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
35994
36653
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
35995
|
-
const
|
|
35996
|
-
const baselineDir =
|
|
36654
|
+
const homedir30 = deps.homedir ?? (() => os26.homedir());
|
|
36655
|
+
const baselineDir = path42.join(workspacePath, ".olam", "baseline");
|
|
35997
36656
|
try {
|
|
35998
|
-
|
|
36657
|
+
fs42.mkdirSync(baselineDir, { recursive: true });
|
|
35999
36658
|
} catch (err) {
|
|
36000
36659
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36001
36660
|
console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
|
|
@@ -36007,9 +36666,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
36007
36666
|
if (!repo.path)
|
|
36008
36667
|
continue;
|
|
36009
36668
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
36010
|
-
const outPath =
|
|
36011
|
-
const repoPath = expandHome2(repo.path,
|
|
36012
|
-
if (!
|
|
36669
|
+
const outPath = path42.join(baselineDir, filename);
|
|
36670
|
+
const repoPath = expandHome2(repo.path, homedir30);
|
|
36671
|
+
if (!fs42.existsSync(repoPath)) {
|
|
36013
36672
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
36014
36673
|
# (skipped: path ${repoPath} does not exist)
|
|
36015
36674
|
`);
|
|
@@ -36076,7 +36735,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
36076
36735
|
}
|
|
36077
36736
|
function writeBaselineFile(outPath, content) {
|
|
36078
36737
|
try {
|
|
36079
|
-
|
|
36738
|
+
fs42.writeFileSync(outPath, content);
|
|
36080
36739
|
} catch (err) {
|
|
36081
36740
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36082
36741
|
console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
|
|
@@ -36084,8 +36743,8 @@ function writeBaselineFile(outPath, content) {
|
|
|
36084
36743
|
}
|
|
36085
36744
|
function stripWorktreeEdits(repos, workspacePath) {
|
|
36086
36745
|
for (const repo of repos) {
|
|
36087
|
-
const worktreePath =
|
|
36088
|
-
if (!
|
|
36746
|
+
const worktreePath = path42.join(workspacePath, repo.name);
|
|
36747
|
+
if (!fs42.existsSync(worktreePath))
|
|
36089
36748
|
continue;
|
|
36090
36749
|
try {
|
|
36091
36750
|
execFileSync6("git", ["checkout", "--", "."], {
|
|
@@ -36144,21 +36803,21 @@ function extractStderr(err) {
|
|
|
36144
36803
|
}
|
|
36145
36804
|
function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
36146
36805
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
36147
|
-
const
|
|
36148
|
-
const
|
|
36149
|
-
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) =>
|
|
36150
|
-
const
|
|
36151
|
-
|
|
36806
|
+
const homedir30 = deps.homedir ?? (() => os26.homedir());
|
|
36807
|
+
const existsSync47 = deps.existsSync ?? ((p) => fs42.existsSync(p));
|
|
36808
|
+
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs42.copyFileSync(src, dest));
|
|
36809
|
+
const mkdirSync30 = deps.mkdirSync ?? ((dirPath, opts) => {
|
|
36810
|
+
fs42.mkdirSync(dirPath, opts);
|
|
36152
36811
|
});
|
|
36153
36812
|
const plans = [];
|
|
36154
36813
|
for (const repo of repos) {
|
|
36155
36814
|
if (!repo.path)
|
|
36156
36815
|
continue;
|
|
36157
|
-
const repoPath = expandHome2(repo.path,
|
|
36158
|
-
const worktreePath =
|
|
36159
|
-
if (!
|
|
36816
|
+
const repoPath = expandHome2(repo.path, homedir30);
|
|
36817
|
+
const worktreePath = path42.join(workspacePath, repo.name);
|
|
36818
|
+
if (!existsSync47(repoPath))
|
|
36160
36819
|
continue;
|
|
36161
|
-
if (!
|
|
36820
|
+
if (!existsSync47(worktreePath)) {
|
|
36162
36821
|
console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
|
|
36163
36822
|
continue;
|
|
36164
36823
|
}
|
|
@@ -36216,12 +36875,12 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
36216
36875
|
}
|
|
36217
36876
|
}
|
|
36218
36877
|
for (const rel of plan.diff.untracked) {
|
|
36219
|
-
const src =
|
|
36220
|
-
const dest =
|
|
36221
|
-
if (!
|
|
36878
|
+
const src = path42.join(plan.repoPath, rel);
|
|
36879
|
+
const dest = path42.join(plan.worktreePath, rel);
|
|
36880
|
+
if (!existsSync47(src))
|
|
36222
36881
|
continue;
|
|
36223
36882
|
try {
|
|
36224
|
-
|
|
36883
|
+
mkdirSync30(path42.dirname(dest), { recursive: true });
|
|
36225
36884
|
copyFileSync9(src, dest);
|
|
36226
36885
|
} catch (err) {
|
|
36227
36886
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -36247,8 +36906,8 @@ function formatBaselineSummary(result) {
|
|
|
36247
36906
|
}
|
|
36248
36907
|
|
|
36249
36908
|
// ../core/dist/world/context-injection.js
|
|
36250
|
-
import * as
|
|
36251
|
-
import * as
|
|
36909
|
+
import * as fs43 from "node:fs";
|
|
36910
|
+
import * as path43 from "node:path";
|
|
36252
36911
|
|
|
36253
36912
|
// ../core/dist/world/templates/_generated.js
|
|
36254
36913
|
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';
|
|
@@ -36258,10 +36917,10 @@ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Enviro
|
|
|
36258
36917
|
// ../core/dist/world/context-injection.js
|
|
36259
36918
|
function injectWorldContext(opts) {
|
|
36260
36919
|
const { world } = opts;
|
|
36261
|
-
const claudeDir2 =
|
|
36262
|
-
|
|
36920
|
+
const claudeDir2 = path43.join(world.workspacePath, ".claude");
|
|
36921
|
+
fs43.mkdirSync(claudeDir2, { recursive: true });
|
|
36263
36922
|
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));
|
|
36264
|
-
|
|
36923
|
+
fs43.writeFileSync(path43.join(claudeDir2, "CLAUDE.md"), content);
|
|
36265
36924
|
writeOlamDocs(world.workspacePath);
|
|
36266
36925
|
}
|
|
36267
36926
|
function buildTaskBlock(opts) {
|
|
@@ -36335,10 +36994,10 @@ function buildExtraContextBlock(extra) {
|
|
|
36335
36994
|
${extra}`;
|
|
36336
36995
|
}
|
|
36337
36996
|
function writeOlamDocs(workspacePath) {
|
|
36338
|
-
const docsDir =
|
|
36339
|
-
|
|
36340
|
-
|
|
36341
|
-
|
|
36997
|
+
const docsDir = path43.join(workspacePath, ".olam", "docs");
|
|
36998
|
+
fs43.mkdirSync(docsDir, { recursive: true });
|
|
36999
|
+
fs43.writeFileSync(path43.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
|
|
37000
|
+
fs43.writeFileSync(path43.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
|
|
36342
37001
|
}
|
|
36343
37002
|
function formatTaskSource(ctx) {
|
|
36344
37003
|
if (ctx.source === "linear" && ctx.ticketId) {
|
|
@@ -36352,9 +37011,9 @@ function formatTaskSource(ctx) {
|
|
|
36352
37011
|
function hasPlanFile(world) {
|
|
36353
37012
|
if (world.repos.length === 0)
|
|
36354
37013
|
return false;
|
|
36355
|
-
const plansDir =
|
|
37014
|
+
const plansDir = path43.join(world.workspacePath, world.repos[0], "docs", "plans");
|
|
36356
37015
|
try {
|
|
36357
|
-
return
|
|
37016
|
+
return fs43.existsSync(plansDir) && fs43.readdirSync(plansDir).length > 0;
|
|
36358
37017
|
} catch {
|
|
36359
37018
|
return false;
|
|
36360
37019
|
}
|
|
@@ -36926,25 +37585,25 @@ init_repo_manifest();
|
|
|
36926
37585
|
|
|
36927
37586
|
// ../core/dist/world/snapshot.js
|
|
36928
37587
|
import * as crypto7 from "node:crypto";
|
|
36929
|
-
import * as
|
|
36930
|
-
import * as
|
|
36931
|
-
import * as
|
|
37588
|
+
import * as fs44 from "node:fs";
|
|
37589
|
+
import * as os27 from "node:os";
|
|
37590
|
+
import * as path44 from "node:path";
|
|
36932
37591
|
import { execFileSync as execFileSync7, spawn as spawn2 } from "node:child_process";
|
|
36933
37592
|
import { gunzipSync } from "node:zlib";
|
|
36934
37593
|
function snapshotsDir() {
|
|
36935
|
-
return process.env["OLAM_SNAPSHOTS_DIR"] ??
|
|
37594
|
+
return process.env["OLAM_SNAPSHOTS_DIR"] ?? path44.join(os27.homedir(), ".olam", "snapshots");
|
|
36936
37595
|
}
|
|
36937
37596
|
function snapshotKindDirByWorkspace(workspace, arch, kind) {
|
|
36938
|
-
return
|
|
37597
|
+
return path44.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
|
|
36939
37598
|
}
|
|
36940
37599
|
function cleanupLegacyByWorldDir(worldId) {
|
|
36941
|
-
const legacyDir =
|
|
37600
|
+
const legacyDir = path44.join(snapshotsDir(), worldId);
|
|
36942
37601
|
if (worldId === "by-workspace")
|
|
36943
37602
|
return;
|
|
36944
|
-
if (!
|
|
37603
|
+
if (!fs44.existsSync(legacyDir))
|
|
36945
37604
|
return;
|
|
36946
37605
|
try {
|
|
36947
|
-
|
|
37606
|
+
fs44.rmSync(legacyDir, { recursive: true, force: true });
|
|
36948
37607
|
} catch {
|
|
36949
37608
|
}
|
|
36950
37609
|
}
|
|
@@ -36963,11 +37622,11 @@ function hashBuffers(entries) {
|
|
|
36963
37622
|
return hash.digest("hex").slice(0, 12);
|
|
36964
37623
|
}
|
|
36965
37624
|
function computeGemsFingerprint(repoDir, imageDigest) {
|
|
36966
|
-
const lockfile =
|
|
36967
|
-
if (!
|
|
37625
|
+
const lockfile = path44.join(repoDir, "Gemfile.lock");
|
|
37626
|
+
if (!fs44.existsSync(lockfile))
|
|
36968
37627
|
return null;
|
|
36969
37628
|
const entries = [
|
|
36970
|
-
{ path: "Gemfile.lock", content:
|
|
37629
|
+
{ path: "Gemfile.lock", content: fs44.readFileSync(lockfile) }
|
|
36971
37630
|
];
|
|
36972
37631
|
if (imageDigest) {
|
|
36973
37632
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -36977,10 +37636,10 @@ function computeGemsFingerprint(repoDir, imageDigest) {
|
|
|
36977
37636
|
function computeNodeFingerprint(repoDir, imageDigest) {
|
|
36978
37637
|
const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
|
|
36979
37638
|
for (const name of candidates) {
|
|
36980
|
-
const lockfile =
|
|
36981
|
-
if (
|
|
37639
|
+
const lockfile = path44.join(repoDir, name);
|
|
37640
|
+
if (fs44.existsSync(lockfile)) {
|
|
36982
37641
|
const entries = [
|
|
36983
|
-
{ path: name, content:
|
|
37642
|
+
{ path: name, content: fs44.readFileSync(lockfile) }
|
|
36984
37643
|
];
|
|
36985
37644
|
if (imageDigest) {
|
|
36986
37645
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -36999,18 +37658,18 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
36999
37658
|
detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
|
|
37000
37659
|
};
|
|
37001
37660
|
}
|
|
37002
|
-
const parent =
|
|
37003
|
-
|
|
37661
|
+
const parent = path44.dirname(destDir);
|
|
37662
|
+
fs44.mkdirSync(parent, { recursive: true });
|
|
37004
37663
|
const tmpSuffix = `.tmp-${process.pid}-${crypto7.randomBytes(4).toString("hex")}`;
|
|
37005
37664
|
const tmpDir = `${destDir}${tmpSuffix}`;
|
|
37006
37665
|
try {
|
|
37007
|
-
|
|
37666
|
+
fs44.mkdirSync(tmpDir, { recursive: true });
|
|
37008
37667
|
execFileSync7("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
|
|
37009
|
-
|
|
37668
|
+
fs44.renameSync(tmpDir, destDir);
|
|
37010
37669
|
return { ok: true, entryCount: validation.entries.length };
|
|
37011
37670
|
} catch (err) {
|
|
37012
37671
|
try {
|
|
37013
|
-
|
|
37672
|
+
fs44.rmSync(tmpDir, { recursive: true, force: true });
|
|
37014
37673
|
} catch {
|
|
37015
37674
|
}
|
|
37016
37675
|
return {
|
|
@@ -37021,12 +37680,12 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
37021
37680
|
}
|
|
37022
37681
|
}
|
|
37023
37682
|
function resolvesWithin(base, target) {
|
|
37024
|
-
const resolved =
|
|
37025
|
-
const baseResolved =
|
|
37026
|
-
const rel =
|
|
37683
|
+
const resolved = path44.resolve(base, target);
|
|
37684
|
+
const baseResolved = path44.resolve(base);
|
|
37685
|
+
const rel = path44.relative(baseResolved, resolved);
|
|
37027
37686
|
if (rel === "")
|
|
37028
37687
|
return true;
|
|
37029
|
-
return !rel.startsWith("..") && !
|
|
37688
|
+
return !rel.startsWith("..") && !path44.isAbsolute(rel);
|
|
37030
37689
|
}
|
|
37031
37690
|
var TYPE_CHAR_TO_TYPE = {
|
|
37032
37691
|
"-": "file",
|
|
@@ -37076,7 +37735,7 @@ function parseTarListLine(line) {
|
|
|
37076
37735
|
function validateHardlinksBinary(tarPath, targetDir) {
|
|
37077
37736
|
let raw;
|
|
37078
37737
|
try {
|
|
37079
|
-
raw = gunzipSync(
|
|
37738
|
+
raw = gunzipSync(fs44.readFileSync(tarPath));
|
|
37080
37739
|
} catch {
|
|
37081
37740
|
return null;
|
|
37082
37741
|
}
|
|
@@ -37091,7 +37750,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
|
|
|
37091
37750
|
const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
|
|
37092
37751
|
const linkNull = block.indexOf(0, 157);
|
|
37093
37752
|
const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
|
|
37094
|
-
if (linkname && (
|
|
37753
|
+
if (linkname && (path44.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
|
|
37095
37754
|
return {
|
|
37096
37755
|
valid: false,
|
|
37097
37756
|
reason: "hardlink-escape",
|
|
@@ -37129,7 +37788,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
37129
37788
|
const entry = parseTarListLine(line);
|
|
37130
37789
|
if (!entry)
|
|
37131
37790
|
continue;
|
|
37132
|
-
if (
|
|
37791
|
+
if (path44.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
|
|
37133
37792
|
return {
|
|
37134
37793
|
valid: false,
|
|
37135
37794
|
reason: "path-traversal",
|
|
@@ -37137,8 +37796,8 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
37137
37796
|
};
|
|
37138
37797
|
}
|
|
37139
37798
|
if (entry.type === "symlink" && entry.linkname !== void 0) {
|
|
37140
|
-
const symlinkParent =
|
|
37141
|
-
if (
|
|
37799
|
+
const symlinkParent = path44.join(targetDir, path44.dirname(entry.name));
|
|
37800
|
+
if (path44.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path44.join(path44.dirname(entry.name), entry.linkname))) {
|
|
37142
37801
|
return {
|
|
37143
37802
|
valid: false,
|
|
37144
37803
|
reason: "symlink-escape",
|
|
@@ -37148,7 +37807,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
37148
37807
|
}
|
|
37149
37808
|
}
|
|
37150
37809
|
if (entry.type === "hardlink" && entry.linkname !== void 0) {
|
|
37151
|
-
if (
|
|
37810
|
+
if (path44.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
|
|
37152
37811
|
return {
|
|
37153
37812
|
valid: false,
|
|
37154
37813
|
reason: "hardlink-escape",
|
|
@@ -37181,8 +37840,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37181
37840
|
}
|
|
37182
37841
|
const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
|
|
37183
37842
|
const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
|
|
37184
|
-
const tarPath =
|
|
37185
|
-
if (!
|
|
37843
|
+
const tarPath = path44.join(archDir, tarFilename);
|
|
37844
|
+
if (!fs44.existsSync(tarPath)) {
|
|
37186
37845
|
outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
|
|
37187
37846
|
continue;
|
|
37188
37847
|
}
|
|
@@ -37197,9 +37856,9 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37197
37856
|
});
|
|
37198
37857
|
continue;
|
|
37199
37858
|
}
|
|
37200
|
-
const targetDir =
|
|
37859
|
+
const targetDir = path44.join(repo.worktreeDir, targetSubpath);
|
|
37201
37860
|
try {
|
|
37202
|
-
|
|
37861
|
+
fs44.rmSync(targetDir, { recursive: true, force: true });
|
|
37203
37862
|
} catch {
|
|
37204
37863
|
}
|
|
37205
37864
|
const result = unpackTarballAtomic(tarPath, targetDir);
|
|
@@ -37212,8 +37871,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37212
37871
|
fingerprint
|
|
37213
37872
|
});
|
|
37214
37873
|
try {
|
|
37215
|
-
|
|
37216
|
-
|
|
37874
|
+
fs44.rmSync(tarPath, { force: true });
|
|
37875
|
+
fs44.rmSync(manifestPath(tarPath), { force: true });
|
|
37217
37876
|
} catch {
|
|
37218
37877
|
}
|
|
37219
37878
|
continue;
|
|
@@ -37229,10 +37888,10 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37229
37888
|
}
|
|
37230
37889
|
function readManifest(tarPath) {
|
|
37231
37890
|
const mPath = manifestPath(tarPath);
|
|
37232
|
-
if (!
|
|
37891
|
+
if (!fs44.existsSync(mPath))
|
|
37233
37892
|
return null;
|
|
37234
37893
|
try {
|
|
37235
|
-
return JSON.parse(
|
|
37894
|
+
return JSON.parse(fs44.readFileSync(mPath, "utf-8"));
|
|
37236
37895
|
} catch {
|
|
37237
37896
|
return null;
|
|
37238
37897
|
}
|
|
@@ -37247,17 +37906,17 @@ function isPidAlive(pid) {
|
|
|
37247
37906
|
}
|
|
37248
37907
|
}
|
|
37249
37908
|
function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
37250
|
-
|
|
37251
|
-
const lockPath =
|
|
37909
|
+
fs44.mkdirSync(dir, { recursive: true });
|
|
37910
|
+
const lockPath = path44.join(dir, EVICT_LOCK_FILENAME);
|
|
37252
37911
|
let fd;
|
|
37253
37912
|
try {
|
|
37254
|
-
fd =
|
|
37913
|
+
fd = fs44.openSync(lockPath, fs44.constants.O_WRONLY | fs44.constants.O_CREAT | fs44.constants.O_EXCL, 384);
|
|
37255
37914
|
} catch (err) {
|
|
37256
37915
|
if (err.code !== "EEXIST")
|
|
37257
37916
|
return 0;
|
|
37258
37917
|
let holderPid = null;
|
|
37259
37918
|
try {
|
|
37260
|
-
holderPid = parseInt(
|
|
37919
|
+
holderPid = parseInt(fs44.readFileSync(lockPath, "utf-8").trim(), 10);
|
|
37261
37920
|
} catch {
|
|
37262
37921
|
holderPid = null;
|
|
37263
37922
|
}
|
|
@@ -37265,23 +37924,23 @@ function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
|
37265
37924
|
return 0;
|
|
37266
37925
|
}
|
|
37267
37926
|
try {
|
|
37268
|
-
|
|
37269
|
-
fd =
|
|
37927
|
+
fs44.unlinkSync(lockPath);
|
|
37928
|
+
fd = fs44.openSync(lockPath, fs44.constants.O_WRONLY | fs44.constants.O_CREAT | fs44.constants.O_EXCL, 384);
|
|
37270
37929
|
} catch {
|
|
37271
37930
|
return 0;
|
|
37272
37931
|
}
|
|
37273
37932
|
}
|
|
37274
37933
|
try {
|
|
37275
|
-
|
|
37934
|
+
fs44.writeSync(fd, `${process.pid}
|
|
37276
37935
|
`);
|
|
37277
37936
|
} finally {
|
|
37278
|
-
|
|
37937
|
+
fs44.closeSync(fd);
|
|
37279
37938
|
}
|
|
37280
37939
|
try {
|
|
37281
37940
|
return evictOldSnapshots(maxBytes, dir);
|
|
37282
37941
|
} finally {
|
|
37283
37942
|
try {
|
|
37284
|
-
|
|
37943
|
+
fs44.unlinkSync(lockPath);
|
|
37285
37944
|
} catch {
|
|
37286
37945
|
}
|
|
37287
37946
|
}
|
|
@@ -37314,16 +37973,16 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
|
|
|
37314
37973
|
}
|
|
37315
37974
|
}
|
|
37316
37975
|
function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
37317
|
-
if (!
|
|
37976
|
+
if (!fs44.existsSync(dir))
|
|
37318
37977
|
return 0;
|
|
37319
37978
|
const allTars = [];
|
|
37320
37979
|
const walk = (d) => {
|
|
37321
|
-
for (const entry of
|
|
37322
|
-
const full =
|
|
37980
|
+
for (const entry of fs44.readdirSync(d, { withFileTypes: true })) {
|
|
37981
|
+
const full = path44.join(d, entry.name);
|
|
37323
37982
|
if (entry.isDirectory()) {
|
|
37324
37983
|
walk(full);
|
|
37325
37984
|
} else if (entry.name.endsWith(".tar.gz")) {
|
|
37326
|
-
const stat =
|
|
37985
|
+
const stat = fs44.statSync(full);
|
|
37327
37986
|
allTars.push({ path: full, size: stat.size, mtime: stat.mtimeMs });
|
|
37328
37987
|
}
|
|
37329
37988
|
}
|
|
@@ -37338,8 +37997,8 @@ function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
|
37338
37997
|
for (const tar of allTars) {
|
|
37339
37998
|
if (remaining <= maxBytes)
|
|
37340
37999
|
break;
|
|
37341
|
-
|
|
37342
|
-
|
|
38000
|
+
fs44.rmSync(tar.path, { force: true });
|
|
38001
|
+
fs44.rmSync(manifestPath(tar.path), { force: true });
|
|
37343
38002
|
freed += tar.size;
|
|
37344
38003
|
remaining -= tar.size;
|
|
37345
38004
|
}
|
|
@@ -37456,14 +38115,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
|
|
|
37456
38115
|
|
|
37457
38116
|
// ../core/dist/world/olam-yaml.js
|
|
37458
38117
|
init_repo_manifest();
|
|
37459
|
-
import * as
|
|
38118
|
+
import * as path45 from "node:path";
|
|
37460
38119
|
import YAML2 from "yaml";
|
|
37461
38120
|
function enrichReposWithManifests(repos, workspacePath) {
|
|
37462
38121
|
return repos.map((repo) => {
|
|
37463
38122
|
if (repo.manifest !== void 0 && repo.manifest !== null) {
|
|
37464
38123
|
return repo;
|
|
37465
38124
|
}
|
|
37466
|
-
const repoDir =
|
|
38125
|
+
const repoDir = path45.join(workspacePath, repo.name);
|
|
37467
38126
|
let manifest = null;
|
|
37468
38127
|
try {
|
|
37469
38128
|
manifest = loadRepoManifest(repoDir);
|
|
@@ -37478,8 +38137,8 @@ function enrichReposWithManifests(repos, workspacePath) {
|
|
|
37478
38137
|
}
|
|
37479
38138
|
|
|
37480
38139
|
// ../core/dist/policies/loader.js
|
|
37481
|
-
import * as
|
|
37482
|
-
import * as
|
|
38140
|
+
import * as fs45 from "node:fs";
|
|
38141
|
+
import * as path46 from "node:path";
|
|
37483
38142
|
import { parse as parseYaml4 } from "yaml";
|
|
37484
38143
|
function parseFrontmatter2(content) {
|
|
37485
38144
|
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
|
|
@@ -37499,20 +38158,20 @@ function toStringArray(v) {
|
|
|
37499
38158
|
return v.filter((x) => typeof x === "string");
|
|
37500
38159
|
}
|
|
37501
38160
|
function loadPolicies(workspaceRoot) {
|
|
37502
|
-
const policiesDir =
|
|
37503
|
-
if (!
|
|
38161
|
+
const policiesDir = path46.join(workspaceRoot, ".olam", "policies");
|
|
38162
|
+
if (!fs45.existsSync(policiesDir))
|
|
37504
38163
|
return [];
|
|
37505
38164
|
let files;
|
|
37506
38165
|
try {
|
|
37507
|
-
files =
|
|
38166
|
+
files = fs45.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
|
|
37508
38167
|
} catch {
|
|
37509
38168
|
return [];
|
|
37510
38169
|
}
|
|
37511
38170
|
const policies = [];
|
|
37512
38171
|
for (const file of files) {
|
|
37513
|
-
const filePath =
|
|
38172
|
+
const filePath = path46.join(policiesDir, file);
|
|
37514
38173
|
try {
|
|
37515
|
-
const content =
|
|
38174
|
+
const content = fs45.readFileSync(filePath, "utf8");
|
|
37516
38175
|
const parsed = parseFrontmatter2(content);
|
|
37517
38176
|
if (!parsed) {
|
|
37518
38177
|
console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
|
|
@@ -37659,12 +38318,12 @@ init_store();
|
|
|
37659
38318
|
init_bridge();
|
|
37660
38319
|
|
|
37661
38320
|
// ../core/dist/global-config/runbook-resolver.js
|
|
37662
|
-
import * as
|
|
37663
|
-
import * as
|
|
37664
|
-
import * as
|
|
38321
|
+
import * as fs46 from "node:fs";
|
|
38322
|
+
import * as os28 from "node:os";
|
|
38323
|
+
import * as path47 from "node:path";
|
|
37665
38324
|
function expandTilde(p) {
|
|
37666
38325
|
if (p === "~" || p.startsWith("~/")) {
|
|
37667
|
-
return
|
|
38326
|
+
return path47.join(os28.homedir(), p.slice(1));
|
|
37668
38327
|
}
|
|
37669
38328
|
return p;
|
|
37670
38329
|
}
|
|
@@ -37676,7 +38335,7 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
37676
38335
|
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.`);
|
|
37677
38336
|
}
|
|
37678
38337
|
const resolvedPath = expandTilde(entry.path);
|
|
37679
|
-
if (!
|
|
38338
|
+
if (!fs46.existsSync(resolvedPath)) {
|
|
37680
38339
|
throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
|
|
37681
38340
|
}
|
|
37682
38341
|
}
|
|
@@ -37692,19 +38351,19 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
37692
38351
|
init_port_validator();
|
|
37693
38352
|
|
|
37694
38353
|
// ../core/dist/world/bootstrap-hooks.js
|
|
37695
|
-
import * as
|
|
37696
|
-
import * as
|
|
38354
|
+
import * as fs47 from "node:fs";
|
|
38355
|
+
import * as path48 from "node:path";
|
|
37697
38356
|
function runFixtureCopySeeds(seeds, workspacePath) {
|
|
37698
38357
|
if (!seeds)
|
|
37699
38358
|
return;
|
|
37700
38359
|
for (const seed of seeds) {
|
|
37701
38360
|
if (seed.type !== "fixture-copy")
|
|
37702
38361
|
continue;
|
|
37703
|
-
const srcAbs =
|
|
37704
|
-
const destAbs =
|
|
37705
|
-
const destDir =
|
|
37706
|
-
|
|
37707
|
-
|
|
38362
|
+
const srcAbs = path48.resolve(workspacePath, seed.repo, seed.src);
|
|
38363
|
+
const destAbs = path48.resolve(workspacePath, seed.repo, seed.dest);
|
|
38364
|
+
const destDir = path48.dirname(destAbs);
|
|
38365
|
+
fs47.mkdirSync(destDir, { recursive: true });
|
|
38366
|
+
fs47.cpSync(srcAbs, destAbs, { recursive: true, force: true });
|
|
37708
38367
|
}
|
|
37709
38368
|
}
|
|
37710
38369
|
async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
|
|
@@ -38340,7 +38999,7 @@ ${detail}`);
|
|
|
38340
38999
|
runbookSeeds = resolved.seeds;
|
|
38341
39000
|
}
|
|
38342
39001
|
const worldId = generateWorldId();
|
|
38343
|
-
const workspacePath =
|
|
39002
|
+
const workspacePath = path49.join(os29.homedir(), ".olam", "worlds", worldId);
|
|
38344
39003
|
const portOffset = this.registry.getNextPortOffset();
|
|
38345
39004
|
const branch = opts.branchName ?? `olam/${worldId}`;
|
|
38346
39005
|
const repos = this.resolveReposWithWorkspace(opts);
|
|
@@ -38421,38 +39080,38 @@ ${detail}`);
|
|
|
38421
39080
|
for (const repo of repos) {
|
|
38422
39081
|
if (!repo.path)
|
|
38423
39082
|
continue;
|
|
38424
|
-
const sourceRoot = repo.path.replace(/^~/,
|
|
38425
|
-
const worktreeRoot =
|
|
38426
|
-
if (!
|
|
39083
|
+
const sourceRoot = repo.path.replace(/^~/, os29.homedir());
|
|
39084
|
+
const worktreeRoot = path49.join(workspacePath, repo.name);
|
|
39085
|
+
if (!fs48.existsSync(sourceRoot) || !fs48.existsSync(worktreeRoot))
|
|
38427
39086
|
continue;
|
|
38428
39087
|
let copied = 0;
|
|
38429
39088
|
for (const pattern of RUNTIME_FILE_PATTERNS) {
|
|
38430
39089
|
const matches2 = [];
|
|
38431
39090
|
if (pattern.includes("*")) {
|
|
38432
|
-
const [dir, glob] = [
|
|
38433
|
-
const sourceDir =
|
|
38434
|
-
if (
|
|
39091
|
+
const [dir, glob] = [path49.dirname(pattern), path49.basename(pattern)];
|
|
39092
|
+
const sourceDir = path49.join(sourceRoot, dir);
|
|
39093
|
+
if (fs48.existsSync(sourceDir)) {
|
|
38435
39094
|
const ext = glob.replace(/^\*+/, "");
|
|
38436
39095
|
try {
|
|
38437
|
-
for (const entry of
|
|
39096
|
+
for (const entry of fs48.readdirSync(sourceDir)) {
|
|
38438
39097
|
if (ext === "" || entry.endsWith(ext))
|
|
38439
|
-
matches2.push(
|
|
39098
|
+
matches2.push(path49.join(dir, entry));
|
|
38440
39099
|
}
|
|
38441
39100
|
} catch {
|
|
38442
39101
|
}
|
|
38443
39102
|
}
|
|
38444
|
-
} else if (
|
|
39103
|
+
} else if (fs48.existsSync(path49.join(sourceRoot, pattern))) {
|
|
38445
39104
|
matches2.push(pattern);
|
|
38446
39105
|
}
|
|
38447
39106
|
for (const rel of matches2) {
|
|
38448
|
-
const src =
|
|
38449
|
-
const dst =
|
|
39107
|
+
const src = path49.join(sourceRoot, rel);
|
|
39108
|
+
const dst = path49.join(worktreeRoot, rel);
|
|
38450
39109
|
try {
|
|
38451
|
-
const st =
|
|
39110
|
+
const st = fs48.statSync(src);
|
|
38452
39111
|
if (!st.isFile())
|
|
38453
39112
|
continue;
|
|
38454
|
-
|
|
38455
|
-
|
|
39113
|
+
fs48.mkdirSync(path49.dirname(dst), { recursive: true });
|
|
39114
|
+
fs48.copyFileSync(src, dst);
|
|
38456
39115
|
copied++;
|
|
38457
39116
|
} catch {
|
|
38458
39117
|
}
|
|
@@ -38538,7 +39197,7 @@ ${detail}`);
|
|
|
38538
39197
|
}
|
|
38539
39198
|
const overlayAttachments = [];
|
|
38540
39199
|
for (const repo of repos) {
|
|
38541
|
-
const worldClonePath =
|
|
39200
|
+
const worldClonePath = path49.join(workspacePath, repo.name);
|
|
38542
39201
|
try {
|
|
38543
39202
|
const result = createWorldOverlay({
|
|
38544
39203
|
workspace: repo.name,
|
|
@@ -38593,7 +39252,7 @@ ${detail}`);
|
|
|
38593
39252
|
try {
|
|
38594
39253
|
const hostExec = makeHostExecFn();
|
|
38595
39254
|
for (const repo of repos) {
|
|
38596
|
-
const repoDir =
|
|
39255
|
+
const repoDir = path49.join(workspacePath, repo.name);
|
|
38597
39256
|
if (repo.stack && Object.keys(repo.stack).length > 0) {
|
|
38598
39257
|
preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
|
|
38599
39258
|
} else {
|
|
@@ -38637,10 +39296,10 @@ ${detail}`);
|
|
|
38637
39296
|
const worldEnv = {};
|
|
38638
39297
|
if (opts.task)
|
|
38639
39298
|
worldEnv.OLAM_TASK = opts.task;
|
|
38640
|
-
const r2CredsPath =
|
|
38641
|
-
if (
|
|
39299
|
+
const r2CredsPath = path49.join(os29.homedir(), ".olam", "r2-credentials.json");
|
|
39300
|
+
if (fs48.existsSync(r2CredsPath)) {
|
|
38642
39301
|
try {
|
|
38643
|
-
const r2Raw =
|
|
39302
|
+
const r2Raw = fs48.readFileSync(r2CredsPath, "utf-8").trim();
|
|
38644
39303
|
if (r2Raw.length > 0) {
|
|
38645
39304
|
const r2 = JSON.parse(r2Raw);
|
|
38646
39305
|
if (typeof r2.account_id === "string")
|
|
@@ -38657,10 +39316,10 @@ ${detail}`);
|
|
|
38657
39316
|
} catch {
|
|
38658
39317
|
}
|
|
38659
39318
|
}
|
|
38660
|
-
const keysYamlPath =
|
|
38661
|
-
if (
|
|
39319
|
+
const keysYamlPath = path49.join(os29.homedir(), ".olam", "keys.yaml");
|
|
39320
|
+
if (fs48.existsSync(keysYamlPath)) {
|
|
38662
39321
|
try {
|
|
38663
|
-
const keysRaw =
|
|
39322
|
+
const keysRaw = fs48.readFileSync(keysYamlPath, "utf-8").trim();
|
|
38664
39323
|
if (keysRaw.length > 0) {
|
|
38665
39324
|
const parsed = YAML3.parse(keysRaw);
|
|
38666
39325
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
@@ -38719,10 +39378,10 @@ ${detail}`);
|
|
|
38719
39378
|
worldEnv[k] = v;
|
|
38720
39379
|
}
|
|
38721
39380
|
for (const { repoName, relativePath, content } of fileWrites) {
|
|
38722
|
-
const absPath =
|
|
39381
|
+
const absPath = path49.join(workspacePath, repoName, relativePath);
|
|
38723
39382
|
try {
|
|
38724
|
-
|
|
38725
|
-
|
|
39383
|
+
fs48.mkdirSync(path49.dirname(absPath), { recursive: true });
|
|
39384
|
+
fs48.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
|
|
38726
39385
|
mode: 384
|
|
38727
39386
|
});
|
|
38728
39387
|
console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
|
|
@@ -38899,7 +39558,7 @@ ${detail}`);
|
|
|
38899
39558
|
imageDigest: void 0,
|
|
38900
39559
|
repos: enrichedRepos.map((r) => ({
|
|
38901
39560
|
name: r.name,
|
|
38902
|
-
worktreeDir:
|
|
39561
|
+
worktreeDir: path49.join(workspacePath, r.name)
|
|
38903
39562
|
}))
|
|
38904
39563
|
});
|
|
38905
39564
|
for (const out of restoreResult.outcomes) {
|
|
@@ -39005,7 +39664,7 @@ ${detail}`);
|
|
|
39005
39664
|
}
|
|
39006
39665
|
if (opts.task) {
|
|
39007
39666
|
const allPolicies = repos.flatMap((repo) => {
|
|
39008
|
-
const repoWorktree =
|
|
39667
|
+
const repoWorktree = path49.join(workspacePath, repo.name);
|
|
39009
39668
|
try {
|
|
39010
39669
|
return loadPolicies(repoWorktree);
|
|
39011
39670
|
} catch (err) {
|
|
@@ -39018,8 +39677,8 @@ ${detail}`);
|
|
|
39018
39677
|
try {
|
|
39019
39678
|
execSync5(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
39020
39679
|
for (const repo of repos) {
|
|
39021
|
-
const policiesDir =
|
|
39022
|
-
if (
|
|
39680
|
+
const policiesDir = path49.join(workspacePath, repo.name, ".olam", "policies");
|
|
39681
|
+
if (fs48.existsSync(policiesDir)) {
|
|
39023
39682
|
execSync5(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
39024
39683
|
}
|
|
39025
39684
|
}
|
|
@@ -39127,8 +39786,8 @@ ${detail}`);
|
|
|
39127
39786
|
} catch {
|
|
39128
39787
|
}
|
|
39129
39788
|
try {
|
|
39130
|
-
|
|
39131
|
-
if (
|
|
39789
|
+
fs48.rmSync(world.workspacePath, { recursive: true, force: true });
|
|
39790
|
+
if (fs48.existsSync(world.workspacePath)) {
|
|
39132
39791
|
console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
|
|
39133
39792
|
}
|
|
39134
39793
|
} catch (err) {
|
|
@@ -39237,14 +39896,14 @@ ${detail}`);
|
|
|
39237
39896
|
}).filter((r) => r !== void 0);
|
|
39238
39897
|
}
|
|
39239
39898
|
transportPlanFile(planFilePath, workspacePath, repoNames) {
|
|
39240
|
-
const planContent =
|
|
39241
|
-
const planFileName =
|
|
39899
|
+
const planContent = fs48.readFileSync(planFilePath, "utf-8");
|
|
39900
|
+
const planFileName = path49.basename(planFilePath);
|
|
39242
39901
|
const targetRepo = repoNames[0];
|
|
39243
39902
|
if (!targetRepo)
|
|
39244
39903
|
return;
|
|
39245
|
-
const plansDir =
|
|
39246
|
-
|
|
39247
|
-
|
|
39904
|
+
const plansDir = path49.join(workspacePath, targetRepo, "docs", "plans");
|
|
39905
|
+
fs48.mkdirSync(plansDir, { recursive: true });
|
|
39906
|
+
fs48.writeFileSync(path49.join(plansDir, planFileName), planContent);
|
|
39248
39907
|
}
|
|
39249
39908
|
resolveServices(repos) {
|
|
39250
39909
|
const services = [];
|
|
@@ -39678,8 +40337,8 @@ import * as http2 from "node:http";
|
|
|
39678
40337
|
|
|
39679
40338
|
// ../core/dist/dashboard/server.js
|
|
39680
40339
|
import * as http from "node:http";
|
|
39681
|
-
import * as
|
|
39682
|
-
import * as
|
|
40340
|
+
import * as fs49 from "node:fs";
|
|
40341
|
+
import * as path50 from "node:path";
|
|
39683
40342
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
39684
40343
|
|
|
39685
40344
|
// ../core/dist/dashboard/serialize.js
|
|
@@ -40014,7 +40673,7 @@ function notFound(res) {
|
|
|
40014
40673
|
}
|
|
40015
40674
|
function openThoughtStore(workspacePath) {
|
|
40016
40675
|
const dbPath = getWorldDbPath(workspacePath);
|
|
40017
|
-
if (!
|
|
40676
|
+
if (!fs49.existsSync(dbPath))
|
|
40018
40677
|
return null;
|
|
40019
40678
|
return new ThoughtLocalStore(dbPath);
|
|
40020
40679
|
}
|
|
@@ -40185,13 +40844,13 @@ function findSessionInWorld(registry2, sessionId) {
|
|
|
40185
40844
|
}
|
|
40186
40845
|
function createDashboardServer(opts) {
|
|
40187
40846
|
const { port: port2, registry: registry2 } = opts;
|
|
40188
|
-
const thisDir =
|
|
40189
|
-
const defaultPublicDir =
|
|
40847
|
+
const thisDir = path50.dirname(fileURLToPath3(import.meta.url));
|
|
40848
|
+
const defaultPublicDir = path50.resolve(thisDir, "../../../control-plane/public");
|
|
40190
40849
|
const publicDir = opts.publicDir ?? defaultPublicDir;
|
|
40191
|
-
let hasPublicDir =
|
|
40850
|
+
let hasPublicDir = fs49.existsSync(publicDir);
|
|
40192
40851
|
const server = http.createServer((req, res) => {
|
|
40193
40852
|
if (!hasPublicDir) {
|
|
40194
|
-
hasPublicDir =
|
|
40853
|
+
hasPublicDir = fs49.existsSync(publicDir);
|
|
40195
40854
|
}
|
|
40196
40855
|
const host = req.headers.host ?? `localhost:${port2}`;
|
|
40197
40856
|
const url2 = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -40465,22 +41124,22 @@ function createDashboardServer(opts) {
|
|
|
40465
41124
|
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>`);
|
|
40466
41125
|
return;
|
|
40467
41126
|
}
|
|
40468
|
-
let filePath =
|
|
41127
|
+
let filePath = path50.join(publicDir, pathname === "/" ? "index.html" : pathname);
|
|
40469
41128
|
if (!filePath.startsWith(publicDir)) {
|
|
40470
41129
|
notFound(res);
|
|
40471
41130
|
return;
|
|
40472
41131
|
}
|
|
40473
|
-
if (
|
|
40474
|
-
const ext =
|
|
41132
|
+
if (fs49.existsSync(filePath) && fs49.statSync(filePath).isFile()) {
|
|
41133
|
+
const ext = path50.extname(filePath);
|
|
40475
41134
|
const contentType = MIME[ext] ?? "application/octet-stream";
|
|
40476
41135
|
res.writeHead(200, { "Content-Type": contentType });
|
|
40477
|
-
|
|
41136
|
+
fs49.createReadStream(filePath).pipe(res);
|
|
40478
41137
|
return;
|
|
40479
41138
|
}
|
|
40480
|
-
filePath =
|
|
40481
|
-
if (
|
|
41139
|
+
filePath = path50.join(publicDir, "index.html");
|
|
41140
|
+
if (fs49.existsSync(filePath)) {
|
|
40482
41141
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
40483
|
-
|
|
41142
|
+
fs49.createReadStream(filePath).pipe(res);
|
|
40484
41143
|
return;
|
|
40485
41144
|
}
|
|
40486
41145
|
notFound(res);
|
|
@@ -40490,17 +41149,17 @@ function createDashboardServer(opts) {
|
|
|
40490
41149
|
}
|
|
40491
41150
|
|
|
40492
41151
|
// ../core/dist/dashboard/state.js
|
|
40493
|
-
import * as
|
|
40494
|
-
import * as
|
|
40495
|
-
import * as
|
|
40496
|
-
var STATE_PATH =
|
|
41152
|
+
import * as fs50 from "node:fs";
|
|
41153
|
+
import * as os30 from "node:os";
|
|
41154
|
+
import * as path51 from "node:path";
|
|
41155
|
+
var STATE_PATH = path51.join(os30.homedir(), ".olam", "dashboard.json");
|
|
40497
41156
|
function saveDashboardState(state) {
|
|
40498
|
-
|
|
40499
|
-
|
|
41157
|
+
fs50.mkdirSync(path51.dirname(STATE_PATH), { recursive: true });
|
|
41158
|
+
fs50.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
|
|
40500
41159
|
}
|
|
40501
41160
|
function loadDashboardState() {
|
|
40502
41161
|
try {
|
|
40503
|
-
const raw =
|
|
41162
|
+
const raw = fs50.readFileSync(STATE_PATH, "utf-8");
|
|
40504
41163
|
return JSON.parse(raw);
|
|
40505
41164
|
} catch {
|
|
40506
41165
|
return null;
|
|
@@ -40508,7 +41167,7 @@ function loadDashboardState() {
|
|
|
40508
41167
|
}
|
|
40509
41168
|
function clearDashboardState() {
|
|
40510
41169
|
try {
|
|
40511
|
-
|
|
41170
|
+
fs50.unlinkSync(STATE_PATH);
|
|
40512
41171
|
} catch {
|
|
40513
41172
|
}
|
|
40514
41173
|
}
|
|
@@ -40788,8 +41447,8 @@ var PleriClient = class {
|
|
|
40788
41447
|
};
|
|
40789
41448
|
|
|
40790
41449
|
// ../mcp-server/src/env-loader.ts
|
|
40791
|
-
import { readFileSync as
|
|
40792
|
-
import { join as
|
|
41450
|
+
import { readFileSync as readFileSync38, existsSync as existsSync46, statSync as statSync14 } from "node:fs";
|
|
41451
|
+
import { join as join51, dirname as dirname29, resolve as resolve13 } from "node:path";
|
|
40793
41452
|
var PROJECT_MARKERS = [
|
|
40794
41453
|
".olam/config.yaml",
|
|
40795
41454
|
".olam/config.yml",
|
|
@@ -40801,26 +41460,26 @@ function findProjectRoot2(startDir) {
|
|
|
40801
41460
|
const root = resolve13("/");
|
|
40802
41461
|
while (true) {
|
|
40803
41462
|
for (const marker of PROJECT_MARKERS) {
|
|
40804
|
-
if (
|
|
41463
|
+
if (existsSync46(join51(dir, marker))) return dir;
|
|
40805
41464
|
}
|
|
40806
|
-
const pkg =
|
|
40807
|
-
if (
|
|
41465
|
+
const pkg = join51(dir, "package.json");
|
|
41466
|
+
if (existsSync46(pkg)) {
|
|
40808
41467
|
try {
|
|
40809
|
-
const json = JSON.parse(
|
|
41468
|
+
const json = JSON.parse(readFileSync38(pkg, "utf8"));
|
|
40810
41469
|
const isOlamWorkspace = typeof json.name === "string" && json.name.startsWith("@olam/");
|
|
40811
41470
|
const hasOlamDep = json.dependencies && Object.keys(json.dependencies).some((k) => k.startsWith("@olam/")) || json.devDependencies && Object.keys(json.devDependencies).some((k) => k.startsWith("@olam/"));
|
|
40812
41471
|
if (isOlamWorkspace || hasOlamDep) return dir;
|
|
40813
41472
|
} catch {
|
|
40814
41473
|
}
|
|
40815
41474
|
}
|
|
40816
|
-
const parent =
|
|
41475
|
+
const parent = dirname29(dir);
|
|
40817
41476
|
if (parent === dir || parent === root) return null;
|
|
40818
41477
|
dir = parent;
|
|
40819
41478
|
}
|
|
40820
41479
|
}
|
|
40821
|
-
function parseEnvFile(
|
|
41480
|
+
function parseEnvFile(path52) {
|
|
40822
41481
|
const out = {};
|
|
40823
|
-
const raw =
|
|
41482
|
+
const raw = readFileSync38(path52, "utf8");
|
|
40824
41483
|
for (const line of raw.split(/\r?\n/)) {
|
|
40825
41484
|
const trimmed = line.trim();
|
|
40826
41485
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -40843,8 +41502,8 @@ function loadProjectEnv(startDir = process.cwd()) {
|
|
|
40843
41502
|
const filesRead = [];
|
|
40844
41503
|
const merged = {};
|
|
40845
41504
|
for (const name of [".env", ".env.local"]) {
|
|
40846
|
-
const p =
|
|
40847
|
-
if (
|
|
41505
|
+
const p = join51(root, name);
|
|
41506
|
+
if (existsSync46(p) && statSync14(p).isFile()) {
|
|
40848
41507
|
Object.assign(merged, parseEnvFile(p));
|
|
40849
41508
|
filesRead.push(p);
|
|
40850
41509
|
}
|
|
@@ -40880,12 +41539,12 @@ async function main() {
|
|
|
40880
41539
|
maxDailyUsd: config2.cost.max_daily_usd,
|
|
40881
41540
|
warningThreshold: config2.cost.warning_threshold
|
|
40882
41541
|
});
|
|
40883
|
-
const
|
|
41542
|
+
const WORLD_ID_RE3 = /^[a-z0-9-]+$/;
|
|
40884
41543
|
const callerWorldIdRaw = (process.env.OLAM_CALLER_WORLD_ID ?? "").trim();
|
|
40885
41544
|
let callerWorldId;
|
|
40886
41545
|
if (callerWorldIdRaw.length === 0) {
|
|
40887
41546
|
callerWorldId = void 0;
|
|
40888
|
-
} else if (
|
|
41547
|
+
} else if (WORLD_ID_RE3.test(callerWorldIdRaw)) {
|
|
40889
41548
|
callerWorldId = callerWorldIdRaw;
|
|
40890
41549
|
} else {
|
|
40891
41550
|
logger.warn(
|