@pleri/olam-cli 0.1.166 → 0.1.168
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/plans.d.ts +3 -0
- package/dist/commands/plans.d.ts.map +1 -0
- package/dist/commands/plans.js +211 -0
- package/dist/commands/plans.js.map +1 -0
- package/dist/commands/setup.d.ts +78 -14
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +430 -42
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/skills-source.d.ts +24 -0
- package/dist/commands/skills-source.d.ts.map +1 -1
- package/dist/commands/skills-source.js +257 -18
- package/dist/commands/skills-source.js.map +1 -1
- package/dist/commands/skills.d.ts +21 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +44 -0
- package/dist/commands/skills.js.map +1 -1
- package/dist/image-digests.json +8 -7
- package/dist/index.js +2494 -1279
- package/dist/index.js.map +1 -1
- package/dist/lib/bootstrap-kubernetes.d.ts.map +1 -1
- package/dist/lib/bootstrap-kubernetes.js +178 -107
- 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/plans-client.d.ts +69 -0
- package/dist/lib/plans-client.d.ts.map +1 -0
- package/dist/lib/plans-client.js +137 -0
- package/dist/lib/plans-client.js.map +1 -0
- 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 +1239 -343
- 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/host-cp/src/halt-detect.mjs +43 -0
- package/host-cp/src/panic-counter.mjs +94 -0
- package/host-cp/src/plan-chat-service.mjs +12 -1
- package/host-cp/src/server.mjs +75 -0
- package/package.json +1 -1
package/dist/mcp-server.js
CHANGED
|
@@ -445,8 +445,8 @@ var init_parseUtil = __esm({
|
|
|
445
445
|
init_errors();
|
|
446
446
|
init_en();
|
|
447
447
|
makeIssue = (params) => {
|
|
448
|
-
const { data, path:
|
|
449
|
-
const fullPath = [...
|
|
448
|
+
const { data, path: 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) {
|
|
@@ -11894,16 +11894,42 @@ var init_loader = __esm({
|
|
|
11894
11894
|
}
|
|
11895
11895
|
});
|
|
11896
11896
|
|
|
11897
|
+
// ../core/dist/skill-sources/source-config-schema.js
|
|
11898
|
+
var PREFIX_PATTERN, SourceConfigSchema, SourceConfigSnapshotSchema;
|
|
11899
|
+
var init_source_config_schema = __esm({
|
|
11900
|
+
"../core/dist/skill-sources/source-config-schema.js"() {
|
|
11901
|
+
"use strict";
|
|
11902
|
+
init_v3();
|
|
11903
|
+
PREFIX_PATTERN = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
11904
|
+
SourceConfigSchema = external_exports.object({
|
|
11905
|
+
/**
|
|
11906
|
+
* Source's RECOMMENDED rename prefix. Operators inherit this when their
|
|
11907
|
+
* `~/.olam/config.json` has no explicit `prefix` override. Same regex
|
|
11908
|
+
* shape as operator-side `SkillSourceSchema.prefix`.
|
|
11909
|
+
*/
|
|
11910
|
+
prefix: external_exports.string().regex(PREFIX_PATTERN, "source-config prefix must be ASCII lowercase + digits + dash/underscore (1-39 chars, no leading/trailing dash)").optional(),
|
|
11911
|
+
/**
|
|
11912
|
+
* Source's RECOMMENDED prefix scope. Same enum as operator-side
|
|
11913
|
+
* `SkillSourceSchema.prefixScope`. Operators inherit this when their
|
|
11914
|
+
* `~/.olam/config.json` has no explicit `prefixScope` override.
|
|
11915
|
+
*/
|
|
11916
|
+
prefixScope: external_exports.array(external_exports.enum(["skill", "agent"])).optional()
|
|
11917
|
+
}).strict();
|
|
11918
|
+
SourceConfigSnapshotSchema = SourceConfigSchema;
|
|
11919
|
+
}
|
|
11920
|
+
});
|
|
11921
|
+
|
|
11897
11922
|
// ../core/dist/skill-sources/schema.js
|
|
11898
|
-
var SKILL_SOURCE_ID_LENGTH, NAME_PATTERN, URL_PATTERN,
|
|
11923
|
+
var SKILL_SOURCE_ID_LENGTH, NAME_PATTERN, URL_PATTERN, PREFIX_PATTERN2, SkillSourceSchema;
|
|
11899
11924
|
var init_schema3 = __esm({
|
|
11900
11925
|
"../core/dist/skill-sources/schema.js"() {
|
|
11901
11926
|
"use strict";
|
|
11902
11927
|
init_v3();
|
|
11928
|
+
init_source_config_schema();
|
|
11903
11929
|
SKILL_SOURCE_ID_LENGTH = 12;
|
|
11904
11930
|
NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
|
|
11905
11931
|
URL_PATTERN = /^(?:https?:\/\/|git@|ssh:\/\/|file:\/\/|\/).+/;
|
|
11906
|
-
|
|
11932
|
+
PREFIX_PATTERN2 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
11907
11933
|
SkillSourceSchema = external_exports.object({
|
|
11908
11934
|
id: external_exports.string().length(SKILL_SOURCE_ID_LENGTH, `skill-source id must be exactly ${SKILL_SOURCE_ID_LENGTH} chars (sha256-of-url prefix)`).regex(/^[a-f0-9]+$/, "skill-source id must be lowercase hex"),
|
|
11909
11935
|
name: external_exports.string().regex(NAME_PATTERN, "skill-source name must be ASCII lowercase + digits + dash (1-64 chars, no leading/trailing dash)"),
|
|
@@ -11920,7 +11946,29 @@ var init_schema3 = __esm({
|
|
|
11920
11946
|
* use canonical names; `olam flywheel migrate-overlays --push` enforces
|
|
11921
11947
|
* this via the reverse validator.
|
|
11922
11948
|
*/
|
|
11923
|
-
prefix: external_exports.string().regex(
|
|
11949
|
+
prefix: external_exports.string().regex(PREFIX_PATTERN2, "skill-source prefix must be ASCII lowercase + digits + dash/underscore (1-39 chars, no leading/trailing dash)").optional(),
|
|
11950
|
+
/**
|
|
11951
|
+
* Which artifact kinds get renamed when `prefix` is set. Optional; defaults
|
|
11952
|
+
* to `['skill', 'agent']` for back-compat with the original Phase A semantic
|
|
11953
|
+
* (Decision 6 in docs/decisions/019-skill-prefix-rules.md). Operators who
|
|
11954
|
+
* want to rebrand ONLY skills (keeping `@architect` etc. canonical) set
|
|
11955
|
+
* `['skill']`; ones who want only agents set `['agent']`.
|
|
11956
|
+
*
|
|
11957
|
+
* Empty array `[]` = same as omitting `prefix` entirely (no renaming).
|
|
11958
|
+
*
|
|
11959
|
+
* NOT applicable when `prefix` is undefined.
|
|
11960
|
+
*/
|
|
11961
|
+
prefixScope: external_exports.array(external_exports.enum(["skill", "agent"])).optional(),
|
|
11962
|
+
/**
|
|
11963
|
+
* Snapshot of the LAST source-config.yaml content this operator saw +
|
|
11964
|
+
* consented to (ADR-021). Trust-gate state: when the live source-config
|
|
11965
|
+
* differs from this snapshot, sync halts with a consent prompt instead
|
|
11966
|
+
* of silently rebranding. Snapshot is updated on accept; persists across
|
|
11967
|
+
* syncs. When undefined: operator has never seen a source-config from this
|
|
11968
|
+
* source (first-sync flow applies). Field shape mirrors SourceConfigSchema
|
|
11969
|
+
* for round-trip simplicity.
|
|
11970
|
+
*/
|
|
11971
|
+
lastSeenSourcePrefix: SourceConfigSnapshotSchema.optional()
|
|
11924
11972
|
});
|
|
11925
11973
|
}
|
|
11926
11974
|
});
|
|
@@ -12449,7 +12497,9 @@ var init_trust_audit_log = __esm({
|
|
|
12449
12497
|
"meta-hook-stripped",
|
|
12450
12498
|
"setup-skill-source-picked",
|
|
12451
12499
|
"setup-project-sweep-completed",
|
|
12452
|
-
"prefix-collision"
|
|
12500
|
+
"prefix-collision",
|
|
12501
|
+
"source-prefix-adopted",
|
|
12502
|
+
"source-prefix-changed"
|
|
12453
12503
|
]);
|
|
12454
12504
|
TrustMethodSchema = external_exports.enum(["flag", "interactive", "auto-reject-tty", "none"]);
|
|
12455
12505
|
TrustAuditEntrySchema = external_exports.object({
|
|
@@ -12563,48 +12613,54 @@ function updateSkillSource(id, patch) {
|
|
|
12563
12613
|
}
|
|
12564
12614
|
}
|
|
12565
12615
|
if (patch.prefix !== void 0 && patch.prefix !== null) {
|
|
12566
|
-
if (!
|
|
12616
|
+
if (!PREFIX_PATTERN3.test(patch.prefix)) {
|
|
12567
12617
|
throw new Error(`prefix must match /^[a-z0-9][a-z0-9_-]{0,38}$/ \u2014 got "${patch.prefix}"`);
|
|
12568
12618
|
}
|
|
12569
12619
|
}
|
|
12570
12620
|
const existing = config2.skillSources[idx];
|
|
12571
|
-
let
|
|
12621
|
+
let working = { ...existing };
|
|
12572
12622
|
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;
|
|
12623
|
+
const { prefix: _p, ...rest } = working;
|
|
12624
|
+
void _p;
|
|
12625
|
+
working = rest;
|
|
12585
12626
|
} else if (patch.prefix !== void 0) {
|
|
12586
|
-
|
|
12627
|
+
working = { ...working, prefix: patch.prefix };
|
|
12628
|
+
}
|
|
12629
|
+
if (patch.prefixScope === null) {
|
|
12630
|
+
const { prefixScope: _s, ...rest } = working;
|
|
12631
|
+
void _s;
|
|
12632
|
+
working = rest;
|
|
12633
|
+
} else if (patch.prefixScope !== void 0) {
|
|
12634
|
+
working = { ...working, prefixScope: [...patch.prefixScope] };
|
|
12635
|
+
}
|
|
12636
|
+
if (patch.lastSeenSourcePrefix === null) {
|
|
12637
|
+
const { lastSeenSourcePrefix: _l, ...rest } = working;
|
|
12638
|
+
void _l;
|
|
12639
|
+
working = rest;
|
|
12640
|
+
} else if (patch.lastSeenSourcePrefix !== void 0) {
|
|
12641
|
+
const validated = SourceConfigSnapshotSchema.parse(patch.lastSeenSourcePrefix);
|
|
12642
|
+
working = { ...working, lastSeenSourcePrefix: validated };
|
|
12587
12643
|
}
|
|
12588
12644
|
const updated = {
|
|
12589
|
-
...
|
|
12645
|
+
...working,
|
|
12590
12646
|
...patch.name !== void 0 ? { name: patch.name } : {},
|
|
12591
12647
|
...patch.branch !== void 0 ? { branch: patch.branch } : {},
|
|
12592
|
-
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {}
|
|
12593
|
-
...prefixUpdate
|
|
12648
|
+
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {}
|
|
12594
12649
|
};
|
|
12595
12650
|
const next = [...config2.skillSources];
|
|
12596
12651
|
next[idx] = updated;
|
|
12597
12652
|
writeGlobalConfig({ ...config2, skillSources: next });
|
|
12598
12653
|
return updated;
|
|
12599
12654
|
}
|
|
12600
|
-
var
|
|
12655
|
+
var PREFIX_PATTERN3;
|
|
12601
12656
|
var init_store2 = __esm({
|
|
12602
12657
|
"../core/dist/skill-sources/store.js"() {
|
|
12603
12658
|
"use strict";
|
|
12604
12659
|
init_store();
|
|
12605
12660
|
init_schema3();
|
|
12606
12661
|
init_trust_audit_log();
|
|
12607
|
-
|
|
12662
|
+
init_source_config_schema();
|
|
12663
|
+
PREFIX_PATTERN3 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
12608
12664
|
}
|
|
12609
12665
|
});
|
|
12610
12666
|
|
|
@@ -13404,7 +13460,7 @@ function detectCollisions(artifacts) {
|
|
|
13404
13460
|
}
|
|
13405
13461
|
return { winners, collisions };
|
|
13406
13462
|
}
|
|
13407
|
-
function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences) {
|
|
13463
|
+
function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, expectedAgentWinnerNames) {
|
|
13408
13464
|
const shadowBackups = [];
|
|
13409
13465
|
for (const bucket of BUCKETS) {
|
|
13410
13466
|
const dir = path21.join(claude, bucket);
|
|
@@ -13438,8 +13494,11 @@ function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences) {
|
|
|
13438
13494
|
}
|
|
13439
13495
|
fs20.unlinkSync(p);
|
|
13440
13496
|
} else if (bucket === "agents" && stat.isFile() && !name.includes(".shadow-backup-")) {
|
|
13441
|
-
const
|
|
13442
|
-
|
|
13497
|
+
const hasWinner = expectedAgentWinnerNames !== void 0 ? expectedAgentWinnerNames.has(name) : true;
|
|
13498
|
+
if (hasWinner) {
|
|
13499
|
+
const backup = shadowBackup(p);
|
|
13500
|
+
shadowBackups.push(backup);
|
|
13501
|
+
}
|
|
13443
13502
|
}
|
|
13444
13503
|
} catch {
|
|
13445
13504
|
}
|
|
@@ -13479,8 +13538,9 @@ function deployArtifacts(artifacts, opts) {
|
|
|
13479
13538
|
for (const bucket of BUCKETS) {
|
|
13480
13539
|
fs20.mkdirSync(path21.join(claude, bucket), { recursive: true });
|
|
13481
13540
|
}
|
|
13482
|
-
const sweepShadowBackups = cleanManagedSymlinks(claude, opts?.installedOlamVersion, opts?.overlayReferences);
|
|
13483
13541
|
const { winners, collisions } = detectCollisions(artifacts);
|
|
13542
|
+
const expectedAgentWinnerNames = new Set(winners.filter((a) => a.kind === "agent").map((a) => a.deployBasename));
|
|
13543
|
+
const sweepShadowBackups = cleanManagedSymlinks(claude, opts?.installedOlamVersion, opts?.overlayReferences, expectedAgentWinnerNames);
|
|
13484
13544
|
const result = { linked: 0, shadowBackups: [...sweepShadowBackups], collisions };
|
|
13485
13545
|
for (const artifact of winners) {
|
|
13486
13546
|
const bucket = bucketFor(artifact.kind);
|
|
@@ -14945,15 +15005,18 @@ import * as fs30 from "node:fs";
|
|
|
14945
15005
|
import * as path29 from "node:path";
|
|
14946
15006
|
function buildSourcePrefixMap(sources) {
|
|
14947
15007
|
const byId = /* @__PURE__ */ new Map();
|
|
15008
|
+
const scopeById = /* @__PURE__ */ new Map();
|
|
14948
15009
|
const prefixes = /* @__PURE__ */ new Set();
|
|
14949
15010
|
for (const s of sources) {
|
|
14950
15011
|
if (s.prefix !== void 0 && s.prefix.length > 0) {
|
|
14951
15012
|
byId.set(s.id, s.prefix);
|
|
15013
|
+
scopeById.set(s.id, s.prefixScope ?? DEFAULT_SCOPE);
|
|
14952
15014
|
prefixes.add(s.prefix);
|
|
14953
15015
|
}
|
|
14954
15016
|
}
|
|
14955
15017
|
return {
|
|
14956
15018
|
get: (sourceId) => byId.get(sourceId),
|
|
15019
|
+
getScope: (sourceId) => scopeById.get(sourceId) ?? DEFAULT_SCOPE,
|
|
14957
15020
|
registeredPrefixes: Array.from(prefixes)
|
|
14958
15021
|
};
|
|
14959
15022
|
}
|
|
@@ -14965,6 +15028,9 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
|
|
|
14965
15028
|
const prefix = sourceMap.get(artifact.sourceId);
|
|
14966
15029
|
if (prefix === void 0)
|
|
14967
15030
|
continue;
|
|
15031
|
+
const scope = sourceMap.getScope(artifact.sourceId);
|
|
15032
|
+
if (!scope.includes(artifact.kind))
|
|
15033
|
+
continue;
|
|
14968
15034
|
const canonical = artifact.deployBasename;
|
|
14969
15035
|
const otherPrefixes = sourceMap.registeredPrefixes.filter((p) => p !== prefix);
|
|
14970
15036
|
const renamed = applyPrefix(canonical, prefix, otherPrefixes);
|
|
@@ -15031,11 +15097,104 @@ function detectPrefixCollisions(sources) {
|
|
|
15031
15097
|
}
|
|
15032
15098
|
return collisions;
|
|
15033
15099
|
}
|
|
15100
|
+
var DEFAULT_SCOPE;
|
|
15034
15101
|
var init_prefix_deploy = __esm({
|
|
15035
15102
|
"../core/dist/skill-sync/prefix-deploy.js"() {
|
|
15036
15103
|
"use strict";
|
|
15037
15104
|
init_prefix_rules();
|
|
15038
15105
|
init_managed_merge();
|
|
15106
|
+
DEFAULT_SCOPE = ["skill", "agent"];
|
|
15107
|
+
}
|
|
15108
|
+
});
|
|
15109
|
+
|
|
15110
|
+
// ../core/dist/skill-sync/resolve-source-config.js
|
|
15111
|
+
import { readFileSync as readFileSync29, existsSync as existsSync31 } from "node:fs";
|
|
15112
|
+
import { join as join31 } from "node:path";
|
|
15113
|
+
import { parse as parseYaml4 } from "yaml";
|
|
15114
|
+
function sourceConfigPath(clonePath) {
|
|
15115
|
+
return join31(clonePath, "shared", "source-config.yaml");
|
|
15116
|
+
}
|
|
15117
|
+
function readSourceConfig(clonePath, sourceId) {
|
|
15118
|
+
const path52 = sourceConfigPath(clonePath);
|
|
15119
|
+
if (!existsSync31(path52))
|
|
15120
|
+
return void 0;
|
|
15121
|
+
let raw;
|
|
15122
|
+
try {
|
|
15123
|
+
raw = readFileSync29(path52, "utf-8");
|
|
15124
|
+
} catch (err) {
|
|
15125
|
+
emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
|
|
15126
|
+
return void 0;
|
|
15127
|
+
}
|
|
15128
|
+
let parsed;
|
|
15129
|
+
try {
|
|
15130
|
+
parsed = parseYaml4(raw);
|
|
15131
|
+
} catch (err) {
|
|
15132
|
+
emitMalformedWarning(sourceId, `YAML parse failed: ${errToMsg(err)}`);
|
|
15133
|
+
return void 0;
|
|
15134
|
+
}
|
|
15135
|
+
const candidate = parsed === null || parsed === void 0 ? {} : parsed;
|
|
15136
|
+
const result = SourceConfigSchema.safeParse(candidate);
|
|
15137
|
+
if (!result.success) {
|
|
15138
|
+
emitMalformedWarning(sourceId, `schema validation failed: ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`);
|
|
15139
|
+
return void 0;
|
|
15140
|
+
}
|
|
15141
|
+
return result.data;
|
|
15142
|
+
}
|
|
15143
|
+
function emitMalformedWarning(sourceId, reason) {
|
|
15144
|
+
const id = sourceId ?? "<unknown source>";
|
|
15145
|
+
process.stderr.write(`[source-config:malformed] ${id}: ${reason}
|
|
15146
|
+
`);
|
|
15147
|
+
}
|
|
15148
|
+
function errToMsg(err) {
|
|
15149
|
+
return err instanceof Error ? err.message : String(err);
|
|
15150
|
+
}
|
|
15151
|
+
function resolveEffectivePrefix(operatorSource, sourceConfig) {
|
|
15152
|
+
const opPrefix = operatorSource.prefix;
|
|
15153
|
+
const opScope = operatorSource.prefixScope;
|
|
15154
|
+
const srcPrefix = sourceConfig?.prefix;
|
|
15155
|
+
const srcScope = sourceConfig?.prefixScope;
|
|
15156
|
+
const effectivePrefix = opPrefix ?? srcPrefix;
|
|
15157
|
+
const effectiveScope = opScope ?? srcScope;
|
|
15158
|
+
const operatorHasAny = opPrefix !== void 0 || opScope !== void 0 && opScope.length > 0;
|
|
15159
|
+
const sourceHasAny = srcPrefix !== void 0 || srcScope !== void 0 && srcScope.length > 0;
|
|
15160
|
+
const origin = operatorHasAny ? "operator" : sourceHasAny ? "source" : "none";
|
|
15161
|
+
const result = { origin };
|
|
15162
|
+
if (effectivePrefix !== void 0)
|
|
15163
|
+
result.prefix = effectivePrefix;
|
|
15164
|
+
if (effectiveScope !== void 0)
|
|
15165
|
+
result.prefixScope = effectiveScope;
|
|
15166
|
+
return result;
|
|
15167
|
+
}
|
|
15168
|
+
function sourceConfigsEqual(a, b) {
|
|
15169
|
+
const normalize = (c) => {
|
|
15170
|
+
if (c === void 0)
|
|
15171
|
+
return {};
|
|
15172
|
+
const out = {};
|
|
15173
|
+
if (c.prefix !== void 0)
|
|
15174
|
+
out.prefix = c.prefix;
|
|
15175
|
+
if (c.prefixScope !== void 0 && c.prefixScope.length > 0) {
|
|
15176
|
+
out.prefixScope = [...c.prefixScope];
|
|
15177
|
+
}
|
|
15178
|
+
return out;
|
|
15179
|
+
};
|
|
15180
|
+
const na = normalize(a);
|
|
15181
|
+
const nb = normalize(b);
|
|
15182
|
+
if (na.prefix !== nb.prefix)
|
|
15183
|
+
return false;
|
|
15184
|
+
const sa = na.prefixScope ?? [];
|
|
15185
|
+
const sb = nb.prefixScope ?? [];
|
|
15186
|
+
if (sa.length !== sb.length)
|
|
15187
|
+
return false;
|
|
15188
|
+
for (let i = 0; i < sa.length; i++) {
|
|
15189
|
+
if (sa[i] !== sb[i])
|
|
15190
|
+
return false;
|
|
15191
|
+
}
|
|
15192
|
+
return true;
|
|
15193
|
+
}
|
|
15194
|
+
var init_resolve_source_config = __esm({
|
|
15195
|
+
"../core/dist/skill-sync/resolve-source-config.js"() {
|
|
15196
|
+
"use strict";
|
|
15197
|
+
init_source_config_schema();
|
|
15039
15198
|
}
|
|
15040
15199
|
});
|
|
15041
15200
|
|
|
@@ -15099,8 +15258,95 @@ async function syncSkills(opts = {}) {
|
|
|
15099
15258
|
const memberOverlaysEnabled = process.env["OLAM_MEMBER_OVERLAYS"] === "1";
|
|
15100
15259
|
const baseArtifacts = projectFilteredArtifacts.filter((a) => a.kind !== "overlay");
|
|
15101
15260
|
const overlayArtifacts = memberOverlaysEnabled ? projectFilteredArtifacts.filter((a) => a.kind === "overlay") : [];
|
|
15102
|
-
const
|
|
15103
|
-
|
|
15261
|
+
const effectiveSources = sources.map((s) => {
|
|
15262
|
+
const clonePath = skillSourceClonePath(s.id);
|
|
15263
|
+
const sourceConfig = fs31.existsSync(clonePath) ? readSourceConfig(clonePath, s.id) : void 0;
|
|
15264
|
+
const eff = resolveEffectivePrefix(s, sourceConfig);
|
|
15265
|
+
const entry = {
|
|
15266
|
+
id: s.id,
|
|
15267
|
+
origin: eff.origin,
|
|
15268
|
+
sourceConfig
|
|
15269
|
+
};
|
|
15270
|
+
if (eff.prefix !== void 0)
|
|
15271
|
+
entry.prefix = eff.prefix;
|
|
15272
|
+
if (eff.prefixScope !== void 0)
|
|
15273
|
+
entry.prefixScope = eff.prefixScope;
|
|
15274
|
+
return entry;
|
|
15275
|
+
});
|
|
15276
|
+
const sourcePrefixGateOutcomes = [];
|
|
15277
|
+
for (const eff of effectiveSources) {
|
|
15278
|
+
if (eff.sourceConfig === void 0) {
|
|
15279
|
+
sourcePrefixGateOutcomes.push({ sourceId: eff.id, outcome: "no-source-config" });
|
|
15280
|
+
continue;
|
|
15281
|
+
}
|
|
15282
|
+
if (eff.origin === "operator") {
|
|
15283
|
+
sourcePrefixGateOutcomes.push({ sourceId: eff.id, outcome: "no-change" });
|
|
15284
|
+
continue;
|
|
15285
|
+
}
|
|
15286
|
+
const operatorSource = sources.find((s) => s.id === eff.id);
|
|
15287
|
+
const lastSeen = operatorSource?.lastSeenSourcePrefix;
|
|
15288
|
+
const sameAsLastSeen = sourceConfigsEqual(lastSeen, eff.sourceConfig);
|
|
15289
|
+
if (sameAsLastSeen) {
|
|
15290
|
+
sourcePrefixGateOutcomes.push({ sourceId: eff.id, outcome: "no-change" });
|
|
15291
|
+
continue;
|
|
15292
|
+
}
|
|
15293
|
+
const kind = lastSeen === void 0 ? "first-time" : "changed";
|
|
15294
|
+
const flagGrant = kind === "first-time" && opts.autoAcceptSourcePrefix === true || kind === "changed" && opts.acceptSourcePrefixChanges === true;
|
|
15295
|
+
let consented = flagGrant;
|
|
15296
|
+
if (!consented && opts.sourcePrefixPrompt !== void 0) {
|
|
15297
|
+
try {
|
|
15298
|
+
const promptInput = {
|
|
15299
|
+
sourceName: operatorSource?.name ?? eff.id,
|
|
15300
|
+
sourceId: eff.id,
|
|
15301
|
+
newConfig: eff.sourceConfig,
|
|
15302
|
+
kind
|
|
15303
|
+
};
|
|
15304
|
+
if (lastSeen !== void 0)
|
|
15305
|
+
promptInput.priorConfig = lastSeen;
|
|
15306
|
+
consented = await opts.sourcePrefixPrompt(promptInput);
|
|
15307
|
+
} catch {
|
|
15308
|
+
consented = false;
|
|
15309
|
+
}
|
|
15310
|
+
}
|
|
15311
|
+
if (consented) {
|
|
15312
|
+
if (!opts.dryRun) {
|
|
15313
|
+
try {
|
|
15314
|
+
updateSkillSource(eff.id, { lastSeenSourcePrefix: eff.sourceConfig });
|
|
15315
|
+
appendTrustAudit({
|
|
15316
|
+
gitUrl: `internal:source-prefix-${kind === "first-time" ? "adopted" : "changed"}`,
|
|
15317
|
+
action: kind === "first-time" ? "source-prefix-adopted" : "source-prefix-changed",
|
|
15318
|
+
trustMethod: flagGrant ? "flag" : "interactive",
|
|
15319
|
+
sourceId: eff.id,
|
|
15320
|
+
note: kind === "first-time" ? `snapshot=${JSON.stringify(eff.sourceConfig)}` : `prior=${JSON.stringify(lastSeen ?? {})}; new=${JSON.stringify(eff.sourceConfig)}`
|
|
15321
|
+
});
|
|
15322
|
+
} catch {
|
|
15323
|
+
}
|
|
15324
|
+
}
|
|
15325
|
+
sourcePrefixGateOutcomes.push({
|
|
15326
|
+
sourceId: eff.id,
|
|
15327
|
+
outcome: kind === "first-time" ? "adopted" : "changed"
|
|
15328
|
+
});
|
|
15329
|
+
} else {
|
|
15330
|
+
delete eff.prefix;
|
|
15331
|
+
delete eff.prefixScope;
|
|
15332
|
+
eff.origin = "none";
|
|
15333
|
+
const isNonTty = opts.sourcePrefixPrompt === void 0;
|
|
15334
|
+
sourcePrefixGateOutcomes.push({
|
|
15335
|
+
sourceId: eff.id,
|
|
15336
|
+
outcome: isNonTty ? "skipped-non-tty" : "rejected"
|
|
15337
|
+
});
|
|
15338
|
+
if (isNonTty) {
|
|
15339
|
+
process.stderr.write(`[source-prefix:skipped] ${operatorSource?.name ?? eff.id}: source-config has prefix-suggestion '${eff.sourceConfig.prefix ?? "<empty>"}' but no consent (non-TTY without --auto-accept-source-prefix). Skipping for this sync; canonical names deployed.
|
|
15340
|
+
`);
|
|
15341
|
+
}
|
|
15342
|
+
}
|
|
15343
|
+
}
|
|
15344
|
+
const sourcePrefixMap = buildSourcePrefixMap(effectiveSources);
|
|
15345
|
+
const hasPrefixRewrites = effectiveSources.some((s) => s.prefix !== void 0 && s.prefix.length > 0);
|
|
15346
|
+
const effectivePrefixOrigins = {};
|
|
15347
|
+
for (const s of effectiveSources) {
|
|
15348
|
+
effectivePrefixOrigins[s.id] = s.origin;
|
|
15349
|
+
}
|
|
15104
15350
|
const willMutateManagedDir = !opts.dryRun && (memberOverlaysEnabled && overlayArtifacts.length > 0 || hasPrefixRewrites);
|
|
15105
15351
|
if (willMutateManagedDir) {
|
|
15106
15352
|
const claude = claudeDir();
|
|
@@ -15149,7 +15395,7 @@ async function syncSkills(opts = {}) {
|
|
|
15149
15395
|
const permissionFiles = projectFilteredArtifacts.filter((a) => a.kind === "permission").map((a) => a.sourcePath);
|
|
15150
15396
|
const claudeDirForRewrites = claudeDir();
|
|
15151
15397
|
const prefixRewriteResult = applyPrefixRewrites(baseArtifacts, sourcePrefixMap, claudeDirForRewrites, opts.dryRun === true);
|
|
15152
|
-
const prefixCollisions = detectPrefixCollisions(
|
|
15398
|
+
const prefixCollisions = detectPrefixCollisions(effectiveSources);
|
|
15153
15399
|
if (!opts.dryRun) {
|
|
15154
15400
|
for (const collision of prefixCollisions) {
|
|
15155
15401
|
try {
|
|
@@ -15176,7 +15422,9 @@ async function syncSkills(opts = {}) {
|
|
|
15176
15422
|
metaHooks: void 0,
|
|
15177
15423
|
perSource,
|
|
15178
15424
|
prefixRewrites: prefixRewriteResult.entries,
|
|
15179
|
-
prefixCollisions
|
|
15425
|
+
prefixCollisions,
|
|
15426
|
+
effectivePrefixOrigins,
|
|
15427
|
+
sourcePrefixGateOutcomes
|
|
15180
15428
|
};
|
|
15181
15429
|
if (opts.dryRun) {
|
|
15182
15430
|
summary.collisions = detectCollisions(baseArtifacts).collisions;
|
|
@@ -15308,6 +15556,8 @@ var init_engine = __esm({
|
|
|
15308
15556
|
init_markdown_merger();
|
|
15309
15557
|
init_managed_merge();
|
|
15310
15558
|
init_prefix_deploy();
|
|
15559
|
+
init_resolve_source_config();
|
|
15560
|
+
init_store2();
|
|
15311
15561
|
}
|
|
15312
15562
|
});
|
|
15313
15563
|
|
|
@@ -15820,6 +16070,8 @@ __export(skill_sources_exports, {
|
|
|
15820
16070
|
SkillOverrideSchema: () => SkillOverrideSchema,
|
|
15821
16071
|
SkillSourceGitError: () => SkillSourceGitError,
|
|
15822
16072
|
SkillSourceSchema: () => SkillSourceSchema,
|
|
16073
|
+
SourceConfigSchema: () => SourceConfigSchema,
|
|
16074
|
+
SourceConfigSnapshotSchema: () => SourceConfigSnapshotSchema,
|
|
15823
16075
|
TrustActionSchema: () => TrustActionSchema,
|
|
15824
16076
|
TrustAuditEntrySchema: () => TrustAuditEntrySchema,
|
|
15825
16077
|
TrustMethodSchema: () => TrustMethodSchema,
|
|
@@ -15859,12 +16111,14 @@ __export(skill_sources_exports, {
|
|
|
15859
16111
|
pullSkillSource: () => pullSkillSource,
|
|
15860
16112
|
readLatestMigrationSnapshot: () => readLatestMigrationSnapshot,
|
|
15861
16113
|
readMigrationSnapshotFromPath: () => readMigrationSnapshotFromPath,
|
|
16114
|
+
readSourceConfig: () => readSourceConfig,
|
|
15862
16115
|
readTrustAuditLog: () => readTrustAuditLog,
|
|
15863
16116
|
redactUrl: () => redactUrl2,
|
|
15864
16117
|
removeSkillSource: () => removeSkillSource,
|
|
15865
16118
|
removeSkillSourceClone: () => removeSkillSourceClone,
|
|
15866
16119
|
reorderSkillSource: () => reorderSkillSource,
|
|
15867
16120
|
resolveAtlasUser: () => resolveAtlasUser,
|
|
16121
|
+
resolveEffectivePrefix: () => resolveEffectivePrefix,
|
|
15868
16122
|
resolveSourceArtifacts: () => resolveSourceArtifacts,
|
|
15869
16123
|
resolveSubscriptions: () => resolveSubscriptions,
|
|
15870
16124
|
restoreCloneToBranchHead: () => restoreCloneToBranchHead,
|
|
@@ -15875,6 +16129,8 @@ __export(skill_sources_exports, {
|
|
|
15875
16129
|
skillSourcesAuditLogPath: () => skillSourcesAuditLogPath,
|
|
15876
16130
|
skillSourcesRootDir: () => skillSourcesRootDir,
|
|
15877
16131
|
skillsHookSettingsPathFor: () => settingsPathFor,
|
|
16132
|
+
sourceConfigPath: () => sourceConfigPath,
|
|
16133
|
+
sourceConfigsEqual: () => sourceConfigsEqual,
|
|
15878
16134
|
syncSkills: () => syncSkills,
|
|
15879
16135
|
uninstallSkillsHookFromFile: () => uninstallSkillsHookFromFile,
|
|
15880
16136
|
updateSkillSource: () => updateSkillSource,
|
|
@@ -15891,6 +16147,8 @@ var init_skill_sources = __esm({
|
|
|
15891
16147
|
init_hook_install();
|
|
15892
16148
|
init_migration_snapshot();
|
|
15893
16149
|
init_engine();
|
|
16150
|
+
init_resolve_source_config();
|
|
16151
|
+
init_source_config_schema();
|
|
15894
16152
|
init_file_lock();
|
|
15895
16153
|
init_schema5();
|
|
15896
16154
|
init_per_project_override();
|
|
@@ -15917,6 +16175,9 @@ var init_global_config = __esm({
|
|
|
15917
16175
|
}
|
|
15918
16176
|
});
|
|
15919
16177
|
|
|
16178
|
+
// ../mcp-server/src/redirect-stdout-to-stderr.ts
|
|
16179
|
+
console.log = console.error;
|
|
16180
|
+
|
|
15920
16181
|
// ../../node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
15921
16182
|
import process3 from "node:process";
|
|
15922
16183
|
|
|
@@ -16160,10 +16421,10 @@ function mergeDefs(...defs) {
|
|
|
16160
16421
|
function cloneDef(schema) {
|
|
16161
16422
|
return mergeDefs(schema._zod.def);
|
|
16162
16423
|
}
|
|
16163
|
-
function getElementAtPath(obj,
|
|
16164
|
-
if (!
|
|
16424
|
+
function getElementAtPath(obj, path52) {
|
|
16425
|
+
if (!path52)
|
|
16165
16426
|
return obj;
|
|
16166
|
-
return
|
|
16427
|
+
return path52.reduce((acc, key) => acc?.[key], obj);
|
|
16167
16428
|
}
|
|
16168
16429
|
function promiseAllObject(promisesObj) {
|
|
16169
16430
|
const keys = Object.keys(promisesObj);
|
|
@@ -16572,11 +16833,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
16572
16833
|
}
|
|
16573
16834
|
return false;
|
|
16574
16835
|
}
|
|
16575
|
-
function prefixIssues(
|
|
16836
|
+
function prefixIssues(path52, issues) {
|
|
16576
16837
|
return issues.map((iss) => {
|
|
16577
16838
|
var _a3;
|
|
16578
16839
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
16579
|
-
iss.path.unshift(
|
|
16840
|
+
iss.path.unshift(path52);
|
|
16580
16841
|
return iss;
|
|
16581
16842
|
});
|
|
16582
16843
|
}
|
|
@@ -16723,16 +16984,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
|
|
|
16723
16984
|
}
|
|
16724
16985
|
function formatError(error2, mapper = (issue2) => issue2.message) {
|
|
16725
16986
|
const fieldErrors = { _errors: [] };
|
|
16726
|
-
const processError = (error3,
|
|
16987
|
+
const processError = (error3, path52 = []) => {
|
|
16727
16988
|
for (const issue2 of error3.issues) {
|
|
16728
16989
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
16729
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
16990
|
+
issue2.errors.map((issues) => processError({ issues }, [...path52, ...issue2.path]));
|
|
16730
16991
|
} else if (issue2.code === "invalid_key") {
|
|
16731
|
-
processError({ issues: issue2.issues }, [...
|
|
16992
|
+
processError({ issues: issue2.issues }, [...path52, ...issue2.path]);
|
|
16732
16993
|
} else if (issue2.code === "invalid_element") {
|
|
16733
|
-
processError({ issues: issue2.issues }, [...
|
|
16994
|
+
processError({ issues: issue2.issues }, [...path52, ...issue2.path]);
|
|
16734
16995
|
} else {
|
|
16735
|
-
const fullpath = [...
|
|
16996
|
+
const fullpath = [...path52, ...issue2.path];
|
|
16736
16997
|
if (fullpath.length === 0) {
|
|
16737
16998
|
fieldErrors._errors.push(mapper(issue2));
|
|
16738
16999
|
} else {
|
|
@@ -26155,6 +26416,228 @@ var McpZodTypeKind;
|
|
|
26155
26416
|
McpZodTypeKind2["Completable"] = "McpCompletable";
|
|
26156
26417
|
})(McpZodTypeKind || (McpZodTypeKind = {}));
|
|
26157
26418
|
|
|
26419
|
+
// ../../node_modules/@modelcontextprotocol/sdk/dist/esm/shared/uriTemplate.js
|
|
26420
|
+
var MAX_TEMPLATE_LENGTH = 1e6;
|
|
26421
|
+
var MAX_VARIABLE_LENGTH = 1e6;
|
|
26422
|
+
var MAX_TEMPLATE_EXPRESSIONS = 1e4;
|
|
26423
|
+
var MAX_REGEX_LENGTH = 1e6;
|
|
26424
|
+
var UriTemplate = class _UriTemplate {
|
|
26425
|
+
/**
|
|
26426
|
+
* Returns true if the given string contains any URI template expressions.
|
|
26427
|
+
* A template expression is a sequence of characters enclosed in curly braces,
|
|
26428
|
+
* like {foo} or {?bar}.
|
|
26429
|
+
*/
|
|
26430
|
+
static isTemplate(str) {
|
|
26431
|
+
return /\{[^}\s]+\}/.test(str);
|
|
26432
|
+
}
|
|
26433
|
+
static validateLength(str, max, context) {
|
|
26434
|
+
if (str.length > max) {
|
|
26435
|
+
throw new Error(`${context} exceeds maximum length of ${max} characters (got ${str.length})`);
|
|
26436
|
+
}
|
|
26437
|
+
}
|
|
26438
|
+
get variableNames() {
|
|
26439
|
+
return this.parts.flatMap((part) => typeof part === "string" ? [] : part.names);
|
|
26440
|
+
}
|
|
26441
|
+
constructor(template) {
|
|
26442
|
+
_UriTemplate.validateLength(template, MAX_TEMPLATE_LENGTH, "Template");
|
|
26443
|
+
this.template = template;
|
|
26444
|
+
this.parts = this.parse(template);
|
|
26445
|
+
}
|
|
26446
|
+
toString() {
|
|
26447
|
+
return this.template;
|
|
26448
|
+
}
|
|
26449
|
+
parse(template) {
|
|
26450
|
+
const parts = [];
|
|
26451
|
+
let currentText = "";
|
|
26452
|
+
let i = 0;
|
|
26453
|
+
let expressionCount = 0;
|
|
26454
|
+
while (i < template.length) {
|
|
26455
|
+
if (template[i] === "{") {
|
|
26456
|
+
if (currentText) {
|
|
26457
|
+
parts.push(currentText);
|
|
26458
|
+
currentText = "";
|
|
26459
|
+
}
|
|
26460
|
+
const end = template.indexOf("}", i);
|
|
26461
|
+
if (end === -1)
|
|
26462
|
+
throw new Error("Unclosed template expression");
|
|
26463
|
+
expressionCount++;
|
|
26464
|
+
if (expressionCount > MAX_TEMPLATE_EXPRESSIONS) {
|
|
26465
|
+
throw new Error(`Template contains too many expressions (max ${MAX_TEMPLATE_EXPRESSIONS})`);
|
|
26466
|
+
}
|
|
26467
|
+
const expr = template.slice(i + 1, end);
|
|
26468
|
+
const operator = this.getOperator(expr);
|
|
26469
|
+
const exploded = expr.includes("*");
|
|
26470
|
+
const names = this.getNames(expr);
|
|
26471
|
+
const name = names[0];
|
|
26472
|
+
for (const name2 of names) {
|
|
26473
|
+
_UriTemplate.validateLength(name2, MAX_VARIABLE_LENGTH, "Variable name");
|
|
26474
|
+
}
|
|
26475
|
+
parts.push({ name, operator, names, exploded });
|
|
26476
|
+
i = end + 1;
|
|
26477
|
+
} else {
|
|
26478
|
+
currentText += template[i];
|
|
26479
|
+
i++;
|
|
26480
|
+
}
|
|
26481
|
+
}
|
|
26482
|
+
if (currentText) {
|
|
26483
|
+
parts.push(currentText);
|
|
26484
|
+
}
|
|
26485
|
+
return parts;
|
|
26486
|
+
}
|
|
26487
|
+
getOperator(expr) {
|
|
26488
|
+
const operators = ["+", "#", ".", "/", "?", "&"];
|
|
26489
|
+
return operators.find((op) => expr.startsWith(op)) || "";
|
|
26490
|
+
}
|
|
26491
|
+
getNames(expr) {
|
|
26492
|
+
const operator = this.getOperator(expr);
|
|
26493
|
+
return expr.slice(operator.length).split(",").map((name) => name.replace("*", "").trim()).filter((name) => name.length > 0);
|
|
26494
|
+
}
|
|
26495
|
+
encodeValue(value, operator) {
|
|
26496
|
+
_UriTemplate.validateLength(value, MAX_VARIABLE_LENGTH, "Variable value");
|
|
26497
|
+
if (operator === "+" || operator === "#") {
|
|
26498
|
+
return encodeURI(value);
|
|
26499
|
+
}
|
|
26500
|
+
return encodeURIComponent(value);
|
|
26501
|
+
}
|
|
26502
|
+
expandPart(part, variables) {
|
|
26503
|
+
if (part.operator === "?" || part.operator === "&") {
|
|
26504
|
+
const pairs = part.names.map((name) => {
|
|
26505
|
+
const value2 = variables[name];
|
|
26506
|
+
if (value2 === void 0)
|
|
26507
|
+
return "";
|
|
26508
|
+
const encoded2 = Array.isArray(value2) ? value2.map((v) => this.encodeValue(v, part.operator)).join(",") : this.encodeValue(value2.toString(), part.operator);
|
|
26509
|
+
return `${name}=${encoded2}`;
|
|
26510
|
+
}).filter((pair) => pair.length > 0);
|
|
26511
|
+
if (pairs.length === 0)
|
|
26512
|
+
return "";
|
|
26513
|
+
const separator = part.operator === "?" ? "?" : "&";
|
|
26514
|
+
return separator + pairs.join("&");
|
|
26515
|
+
}
|
|
26516
|
+
if (part.names.length > 1) {
|
|
26517
|
+
const values2 = part.names.map((name) => variables[name]).filter((v) => v !== void 0);
|
|
26518
|
+
if (values2.length === 0)
|
|
26519
|
+
return "";
|
|
26520
|
+
return values2.map((v) => Array.isArray(v) ? v[0] : v).join(",");
|
|
26521
|
+
}
|
|
26522
|
+
const value = variables[part.name];
|
|
26523
|
+
if (value === void 0)
|
|
26524
|
+
return "";
|
|
26525
|
+
const values = Array.isArray(value) ? value : [value];
|
|
26526
|
+
const encoded = values.map((v) => this.encodeValue(v, part.operator));
|
|
26527
|
+
switch (part.operator) {
|
|
26528
|
+
case "":
|
|
26529
|
+
return encoded.join(",");
|
|
26530
|
+
case "+":
|
|
26531
|
+
return encoded.join(",");
|
|
26532
|
+
case "#":
|
|
26533
|
+
return "#" + encoded.join(",");
|
|
26534
|
+
case ".":
|
|
26535
|
+
return "." + encoded.join(".");
|
|
26536
|
+
case "/":
|
|
26537
|
+
return "/" + encoded.join("/");
|
|
26538
|
+
default:
|
|
26539
|
+
return encoded.join(",");
|
|
26540
|
+
}
|
|
26541
|
+
}
|
|
26542
|
+
expand(variables) {
|
|
26543
|
+
let result = "";
|
|
26544
|
+
let hasQueryParam = false;
|
|
26545
|
+
for (const part of this.parts) {
|
|
26546
|
+
if (typeof part === "string") {
|
|
26547
|
+
result += part;
|
|
26548
|
+
continue;
|
|
26549
|
+
}
|
|
26550
|
+
const expanded = this.expandPart(part, variables);
|
|
26551
|
+
if (!expanded)
|
|
26552
|
+
continue;
|
|
26553
|
+
if ((part.operator === "?" || part.operator === "&") && hasQueryParam) {
|
|
26554
|
+
result += expanded.replace("?", "&");
|
|
26555
|
+
} else {
|
|
26556
|
+
result += expanded;
|
|
26557
|
+
}
|
|
26558
|
+
if (part.operator === "?" || part.operator === "&") {
|
|
26559
|
+
hasQueryParam = true;
|
|
26560
|
+
}
|
|
26561
|
+
}
|
|
26562
|
+
return result;
|
|
26563
|
+
}
|
|
26564
|
+
escapeRegExp(str) {
|
|
26565
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
26566
|
+
}
|
|
26567
|
+
partToRegExp(part) {
|
|
26568
|
+
const patterns = [];
|
|
26569
|
+
for (const name2 of part.names) {
|
|
26570
|
+
_UriTemplate.validateLength(name2, MAX_VARIABLE_LENGTH, "Variable name");
|
|
26571
|
+
}
|
|
26572
|
+
if (part.operator === "?" || part.operator === "&") {
|
|
26573
|
+
for (let i = 0; i < part.names.length; i++) {
|
|
26574
|
+
const name2 = part.names[i];
|
|
26575
|
+
const prefix = i === 0 ? "\\" + part.operator : "&";
|
|
26576
|
+
patterns.push({
|
|
26577
|
+
pattern: prefix + this.escapeRegExp(name2) + "=([^&]+)",
|
|
26578
|
+
name: name2
|
|
26579
|
+
});
|
|
26580
|
+
}
|
|
26581
|
+
return patterns;
|
|
26582
|
+
}
|
|
26583
|
+
let pattern;
|
|
26584
|
+
const name = part.name;
|
|
26585
|
+
switch (part.operator) {
|
|
26586
|
+
case "":
|
|
26587
|
+
pattern = part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)";
|
|
26588
|
+
break;
|
|
26589
|
+
case "+":
|
|
26590
|
+
case "#":
|
|
26591
|
+
pattern = "(.+)";
|
|
26592
|
+
break;
|
|
26593
|
+
case ".":
|
|
26594
|
+
pattern = "\\.([^/,]+)";
|
|
26595
|
+
break;
|
|
26596
|
+
case "/":
|
|
26597
|
+
pattern = "/" + (part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)");
|
|
26598
|
+
break;
|
|
26599
|
+
default:
|
|
26600
|
+
pattern = "([^/]+)";
|
|
26601
|
+
}
|
|
26602
|
+
patterns.push({ pattern, name });
|
|
26603
|
+
return patterns;
|
|
26604
|
+
}
|
|
26605
|
+
match(uri) {
|
|
26606
|
+
_UriTemplate.validateLength(uri, MAX_TEMPLATE_LENGTH, "URI");
|
|
26607
|
+
let pattern = "^";
|
|
26608
|
+
const names = [];
|
|
26609
|
+
for (const part of this.parts) {
|
|
26610
|
+
if (typeof part === "string") {
|
|
26611
|
+
pattern += this.escapeRegExp(part);
|
|
26612
|
+
} else {
|
|
26613
|
+
const patterns = this.partToRegExp(part);
|
|
26614
|
+
for (const { pattern: partPattern, name } of patterns) {
|
|
26615
|
+
pattern += partPattern;
|
|
26616
|
+
names.push({ name, exploded: part.exploded });
|
|
26617
|
+
}
|
|
26618
|
+
}
|
|
26619
|
+
}
|
|
26620
|
+
pattern += "$";
|
|
26621
|
+
_UriTemplate.validateLength(pattern, MAX_REGEX_LENGTH, "Generated regex pattern");
|
|
26622
|
+
const regex = new RegExp(pattern);
|
|
26623
|
+
const match = uri.match(regex);
|
|
26624
|
+
if (!match)
|
|
26625
|
+
return null;
|
|
26626
|
+
const result = {};
|
|
26627
|
+
for (let i = 0; i < names.length; i++) {
|
|
26628
|
+
const { name, exploded } = names[i];
|
|
26629
|
+
const value = match[i + 1];
|
|
26630
|
+
const cleanName = name.replace("*", "");
|
|
26631
|
+
if (exploded && value.includes(",")) {
|
|
26632
|
+
result[cleanName] = value.split(",");
|
|
26633
|
+
} else {
|
|
26634
|
+
result[cleanName] = value;
|
|
26635
|
+
}
|
|
26636
|
+
}
|
|
26637
|
+
return result;
|
|
26638
|
+
}
|
|
26639
|
+
};
|
|
26640
|
+
|
|
26158
26641
|
// ../../node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
|
|
26159
26642
|
var TOOL_NAME_REGEX = /^[A-Za-z0-9._-]{1,128}$/;
|
|
26160
26643
|
function validateToolName(name) {
|
|
@@ -26944,6 +27427,30 @@ var McpServer = class {
|
|
|
26944
27427
|
}
|
|
26945
27428
|
}
|
|
26946
27429
|
};
|
|
27430
|
+
var ResourceTemplate = class {
|
|
27431
|
+
constructor(uriTemplate, _callbacks) {
|
|
27432
|
+
this._callbacks = _callbacks;
|
|
27433
|
+
this._uriTemplate = typeof uriTemplate === "string" ? new UriTemplate(uriTemplate) : uriTemplate;
|
|
27434
|
+
}
|
|
27435
|
+
/**
|
|
27436
|
+
* Gets the URI template pattern.
|
|
27437
|
+
*/
|
|
27438
|
+
get uriTemplate() {
|
|
27439
|
+
return this._uriTemplate;
|
|
27440
|
+
}
|
|
27441
|
+
/**
|
|
27442
|
+
* Gets the list callback, if one was provided.
|
|
27443
|
+
*/
|
|
27444
|
+
get listCallback() {
|
|
27445
|
+
return this._callbacks.list;
|
|
27446
|
+
}
|
|
27447
|
+
/**
|
|
27448
|
+
* Gets the callback for completing a specific URI template variable, if one was provided.
|
|
27449
|
+
*/
|
|
27450
|
+
completeCallback(variable) {
|
|
27451
|
+
return this._callbacks.complete?.[variable];
|
|
27452
|
+
}
|
|
27453
|
+
};
|
|
26947
27454
|
var EMPTY_OBJECT_JSON_SCHEMA = {
|
|
26948
27455
|
type: "object",
|
|
26949
27456
|
properties: {}
|
|
@@ -27268,7 +27775,7 @@ function readSecretIfExists() {
|
|
|
27268
27775
|
|
|
27269
27776
|
// ../core/dist/auth/client.js
|
|
27270
27777
|
var DEFAULT_BASE_URL = "http://127.0.0.1:9999";
|
|
27271
|
-
var DEFAULT_TIMEOUT_MS =
|
|
27778
|
+
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
27272
27779
|
var RETRY_COUNT = 2;
|
|
27273
27780
|
var RETRY_BACKOFF_MS = 250;
|
|
27274
27781
|
var AuthClient = class {
|
|
@@ -27371,8 +27878,8 @@ var AuthClient = class {
|
|
|
27371
27878
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
27372
27879
|
}
|
|
27373
27880
|
}
|
|
27374
|
-
async request(method,
|
|
27375
|
-
const url2 = `${this.baseUrl}${
|
|
27881
|
+
async request(method, path52, body, attempt = 0) {
|
|
27882
|
+
const url2 = `${this.baseUrl}${path52}`;
|
|
27376
27883
|
const controller = new AbortController();
|
|
27377
27884
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
27378
27885
|
const headers = {};
|
|
@@ -27390,7 +27897,7 @@ var AuthClient = class {
|
|
|
27390
27897
|
} catch (err) {
|
|
27391
27898
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
27392
27899
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
27393
|
-
return this.request(method,
|
|
27900
|
+
return this.request(method, path52, body, attempt + 1);
|
|
27394
27901
|
}
|
|
27395
27902
|
throw err;
|
|
27396
27903
|
} finally {
|
|
@@ -28244,12 +28751,12 @@ function register3(server, _ctx, _initError) {
|
|
|
28244
28751
|
registry2.close();
|
|
28245
28752
|
}
|
|
28246
28753
|
try {
|
|
28247
|
-
const { default:
|
|
28248
|
-
const { default:
|
|
28249
|
-
const { default:
|
|
28250
|
-
const tokenPath =
|
|
28251
|
-
if (
|
|
28252
|
-
const token =
|
|
28754
|
+
const { default: fs51 } = await import("node:fs");
|
|
28755
|
+
const { default: os31 } = await import("node:os");
|
|
28756
|
+
const { default: path52 } = await import("node:path");
|
|
28757
|
+
const tokenPath = path52.join(os31.homedir(), ".olam", "host-cp.token");
|
|
28758
|
+
if (fs51.existsSync(tokenPath)) {
|
|
28759
|
+
const token = fs51.readFileSync(tokenPath, "utf-8").trim();
|
|
28253
28760
|
await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
|
|
28254
28761
|
method: "POST",
|
|
28255
28762
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
@@ -28669,10 +29176,10 @@ function extractMcpConfig(claudeJsonPath) {
|
|
|
28669
29176
|
}
|
|
28670
29177
|
return { mcpServers, secrets };
|
|
28671
29178
|
}
|
|
28672
|
-
function readOptional(
|
|
28673
|
-
if (!existsSync6(
|
|
29179
|
+
function readOptional(path52) {
|
|
29180
|
+
if (!existsSync6(path52)) return null;
|
|
28674
29181
|
try {
|
|
28675
|
-
return readFileSync5(
|
|
29182
|
+
return readFileSync5(path52, "utf8");
|
|
28676
29183
|
} catch {
|
|
28677
29184
|
return null;
|
|
28678
29185
|
}
|
|
@@ -30118,8 +30625,8 @@ var CloudflareProvider = class extends ComputeProvider {
|
|
|
30118
30625
|
// -----------------------------------------------------------------------
|
|
30119
30626
|
// Internal fetch helper
|
|
30120
30627
|
// -----------------------------------------------------------------------
|
|
30121
|
-
async request(
|
|
30122
|
-
const url2 = `${this.config.workerUrl}${
|
|
30628
|
+
async request(path52, method, body) {
|
|
30629
|
+
const url2 = `${this.config.workerUrl}${path52}`;
|
|
30123
30630
|
const bearer = await this.config.mintToken();
|
|
30124
30631
|
const headers = {
|
|
30125
30632
|
Authorization: `Bearer ${bearer}`
|
|
@@ -32570,10 +33077,10 @@ async function writeManifest(args) {
|
|
|
32570
33077
|
capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
32571
33078
|
shots: entries
|
|
32572
33079
|
};
|
|
32573
|
-
const
|
|
32574
|
-
await writeFile(
|
|
33080
|
+
const path52 = join13(args.outDir, "manifest.json");
|
|
33081
|
+
await writeFile(path52, `${JSON.stringify(manifest, null, 2)}
|
|
32575
33082
|
`, "utf8");
|
|
32576
|
-
return { path:
|
|
33083
|
+
return { path: path52, manifest };
|
|
32577
33084
|
}
|
|
32578
33085
|
|
|
32579
33086
|
// ../mcp-server/src/tools/_capture/proxy.ts
|
|
@@ -32827,9 +33334,9 @@ async function startProxy(opts) {
|
|
|
32827
33334
|
const liveCompiled = verified.allowedPaths.map(compileGlob);
|
|
32828
33335
|
const target = parseRequestTarget(req);
|
|
32829
33336
|
if (!target) return httpReject(400, "invalid_target");
|
|
32830
|
-
const
|
|
32831
|
-
if (!liveCompiled.some((re) => re.test(
|
|
32832
|
-
return httpReject(403, "outside_allow_list", { path:
|
|
33337
|
+
const path52 = target.pathname;
|
|
33338
|
+
if (!liveCompiled.some((re) => re.test(path52))) {
|
|
33339
|
+
return httpReject(403, "outside_allow_list", { path: path52 });
|
|
32833
33340
|
}
|
|
32834
33341
|
const headerWorld = req.headers[WORLD_ASSERT_HEADER];
|
|
32835
33342
|
const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
|
|
@@ -33608,14 +34115,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
|
|
|
33608
34115
|
await page.waitForTimeout(shot.afterLoadMs);
|
|
33609
34116
|
}
|
|
33610
34117
|
const ext = format === "jpeg" ? "jpg" : "png";
|
|
33611
|
-
const
|
|
34118
|
+
const path52 = join14(outDir, `${shot.name}.${ext}`);
|
|
33612
34119
|
await page.screenshot({
|
|
33613
|
-
path:
|
|
34120
|
+
path: path52,
|
|
33614
34121
|
type: format,
|
|
33615
34122
|
...format === "jpeg" ? { quality: jpegQuality } : {},
|
|
33616
34123
|
fullPage: false
|
|
33617
34124
|
});
|
|
33618
|
-
return { name: shot.name, path:
|
|
34125
|
+
return { name: shot.name, path: path52, urlRedacted: redactUrl(shot.url), viewport };
|
|
33619
34126
|
} finally {
|
|
33620
34127
|
await context.close();
|
|
33621
34128
|
}
|
|
@@ -34059,12 +34566,12 @@ function openUrl(url2) {
|
|
|
34059
34566
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
34060
34567
|
async function readHostCpToken2() {
|
|
34061
34568
|
try {
|
|
34062
|
-
const { default:
|
|
34063
|
-
const { default:
|
|
34064
|
-
const { default:
|
|
34065
|
-
const tp =
|
|
34066
|
-
if (!
|
|
34067
|
-
return { token:
|
|
34569
|
+
const { default: fs51 } = await import("node:fs");
|
|
34570
|
+
const { default: os31 } = await import("node:os");
|
|
34571
|
+
const { default: path52 } = await import("node:path");
|
|
34572
|
+
const tp = path52.join(os31.homedir(), ".olam", "host-cp.token");
|
|
34573
|
+
if (!fs51.existsSync(tp)) return { token: null };
|
|
34574
|
+
return { token: fs51.readFileSync(tp, "utf-8").trim() };
|
|
34068
34575
|
} catch {
|
|
34069
34576
|
return { token: null };
|
|
34070
34577
|
}
|
|
@@ -34324,9 +34831,9 @@ function register22(server, _ctx, _initError) {
|
|
|
34324
34831
|
description: external_exports.string().optional().describe("Optional human-readable description."),
|
|
34325
34832
|
defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
|
|
34326
34833
|
},
|
|
34327
|
-
async ({ name, path:
|
|
34834
|
+
async ({ name, path: path52, description, defaultBranch }) => {
|
|
34328
34835
|
try {
|
|
34329
|
-
const entry = addRepo({ name, path:
|
|
34836
|
+
const entry = addRepo({ name, path: path52, description, defaultBranch });
|
|
34330
34837
|
return {
|
|
34331
34838
|
content: [{
|
|
34332
34839
|
type: "text",
|
|
@@ -34367,9 +34874,9 @@ function register22(server, _ctx, _initError) {
|
|
|
34367
34874
|
description: external_exports.string().optional().describe("New description."),
|
|
34368
34875
|
defaultBranch: external_exports.string().optional().describe("New default branch.")
|
|
34369
34876
|
},
|
|
34370
|
-
async ({ name, path:
|
|
34877
|
+
async ({ name, path: path52, description, defaultBranch }) => {
|
|
34371
34878
|
try {
|
|
34372
|
-
const entry = updateRepo(name, { path:
|
|
34879
|
+
const entry = updateRepo(name, { path: path52, description, defaultBranch });
|
|
34373
34880
|
return {
|
|
34374
34881
|
content: [{
|
|
34375
34882
|
type: "text",
|
|
@@ -34941,10 +35448,196 @@ function register26(server, _ctx, _initError) {
|
|
|
34941
35448
|
);
|
|
34942
35449
|
}
|
|
34943
35450
|
|
|
35451
|
+
// ../mcp-server/src/tools/skills-search.ts
|
|
35452
|
+
var skills_search_exports = {};
|
|
35453
|
+
__export(skills_search_exports, {
|
|
35454
|
+
register: () => register27
|
|
35455
|
+
});
|
|
35456
|
+
init_v3();
|
|
35457
|
+
import * as path36 from "node:path";
|
|
35458
|
+
import * as os22 from "node:os";
|
|
35459
|
+
|
|
35460
|
+
// ../mcp-server/src/lib/skills-index.mjs
|
|
35461
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
35462
|
+
import * as fs36 from "node:fs";
|
|
35463
|
+
import * as path35 from "node:path";
|
|
35464
|
+
import * as os21 from "node:os";
|
|
35465
|
+
var VECTOR_DIM = 256;
|
|
35466
|
+
var SCHEMA_VERSION3 = "1";
|
|
35467
|
+
var SCHEMA_KEY = "skills_index_schema_version";
|
|
35468
|
+
var _require4 = createRequire4(import.meta.url);
|
|
35469
|
+
var _Database3 = null;
|
|
35470
|
+
function getDatabase3() {
|
|
35471
|
+
if (_Database3 === null) {
|
|
35472
|
+
_Database3 = _require4("better-sqlite3");
|
|
35473
|
+
}
|
|
35474
|
+
return _Database3;
|
|
35475
|
+
}
|
|
35476
|
+
var STOPWORDS = /* @__PURE__ */ new Set([
|
|
35477
|
+
"a",
|
|
35478
|
+
"an",
|
|
35479
|
+
"and",
|
|
35480
|
+
"the",
|
|
35481
|
+
"of",
|
|
35482
|
+
"to",
|
|
35483
|
+
"in",
|
|
35484
|
+
"on",
|
|
35485
|
+
"for",
|
|
35486
|
+
"with",
|
|
35487
|
+
"by",
|
|
35488
|
+
"is",
|
|
35489
|
+
"are",
|
|
35490
|
+
"be",
|
|
35491
|
+
"or",
|
|
35492
|
+
"as",
|
|
35493
|
+
"at",
|
|
35494
|
+
"it",
|
|
35495
|
+
"this",
|
|
35496
|
+
"that",
|
|
35497
|
+
"from",
|
|
35498
|
+
"use",
|
|
35499
|
+
"used",
|
|
35500
|
+
"when",
|
|
35501
|
+
"if",
|
|
35502
|
+
"via"
|
|
35503
|
+
]);
|
|
35504
|
+
function fnv1a32(str) {
|
|
35505
|
+
let h = 2166136261;
|
|
35506
|
+
for (let i = 0; i < str.length; i++) {
|
|
35507
|
+
h ^= str.charCodeAt(i);
|
|
35508
|
+
h = Math.imul(h, 16777619);
|
|
35509
|
+
}
|
|
35510
|
+
return h >>> 0;
|
|
35511
|
+
}
|
|
35512
|
+
function tokenize(text) {
|
|
35513
|
+
if (!text) return [];
|
|
35514
|
+
const tokens = [];
|
|
35515
|
+
for (const raw of text.toLowerCase().split(/[^a-z0-9]+/)) {
|
|
35516
|
+
if (raw.length < 2) continue;
|
|
35517
|
+
if (STOPWORDS.has(raw)) continue;
|
|
35518
|
+
tokens.push(raw);
|
|
35519
|
+
}
|
|
35520
|
+
return tokens;
|
|
35521
|
+
}
|
|
35522
|
+
function embed(text) {
|
|
35523
|
+
const vec = new Float32Array(VECTOR_DIM);
|
|
35524
|
+
const tokens = tokenize(text);
|
|
35525
|
+
if (tokens.length === 0) return vec;
|
|
35526
|
+
for (const tok of tokens) {
|
|
35527
|
+
const bucket = fnv1a32(tok) % VECTOR_DIM;
|
|
35528
|
+
vec[bucket] += 1;
|
|
35529
|
+
}
|
|
35530
|
+
let mag = 0;
|
|
35531
|
+
for (let i = 0; i < VECTOR_DIM; i++) mag += vec[i] * vec[i];
|
|
35532
|
+
mag = Math.sqrt(mag);
|
|
35533
|
+
if (mag > 0) {
|
|
35534
|
+
for (let i = 0; i < VECTOR_DIM; i++) vec[i] /= mag;
|
|
35535
|
+
}
|
|
35536
|
+
return vec;
|
|
35537
|
+
}
|
|
35538
|
+
function cosine(a, b) {
|
|
35539
|
+
let dot = 0;
|
|
35540
|
+
for (let i = 0; i < VECTOR_DIM; i++) dot += a[i] * b[i];
|
|
35541
|
+
return dot;
|
|
35542
|
+
}
|
|
35543
|
+
function bufferToVector(buf) {
|
|
35544
|
+
const ab = new ArrayBuffer(buf.byteLength);
|
|
35545
|
+
Buffer.from(ab).set(buf);
|
|
35546
|
+
const vec = new Float32Array(ab);
|
|
35547
|
+
if (vec.length !== VECTOR_DIM) {
|
|
35548
|
+
throw new Error(`vector length mismatch: expected ${VECTOR_DIM}, got ${vec.length}`);
|
|
35549
|
+
}
|
|
35550
|
+
return vec;
|
|
35551
|
+
}
|
|
35552
|
+
function openIndex(dbPath) {
|
|
35553
|
+
if (!fs36.existsSync(dbPath)) {
|
|
35554
|
+
throw new Error(
|
|
35555
|
+
`skills index not found at ${dbPath}. Run \`node scripts/skills-index-build.mjs --out ${dbPath}\` first.`
|
|
35556
|
+
);
|
|
35557
|
+
}
|
|
35558
|
+
const Database = getDatabase3();
|
|
35559
|
+
const db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
35560
|
+
let row;
|
|
35561
|
+
try {
|
|
35562
|
+
row = db.prepare("SELECT value FROM meta WHERE key = ?").get(SCHEMA_KEY);
|
|
35563
|
+
} catch (e) {
|
|
35564
|
+
db.close();
|
|
35565
|
+
throw new Error(`skills index at ${dbPath} is not a valid skills DB: ${e.message}`);
|
|
35566
|
+
}
|
|
35567
|
+
if (!row || row.value !== SCHEMA_VERSION3) {
|
|
35568
|
+
db.close();
|
|
35569
|
+
throw new Error(
|
|
35570
|
+
`skills index at ${dbPath} has schema version ${row ? row.value : "(none)"}, expected ${SCHEMA_VERSION3}. Rebuild it.`
|
|
35571
|
+
);
|
|
35572
|
+
}
|
|
35573
|
+
return db;
|
|
35574
|
+
}
|
|
35575
|
+
function searchIndex(dbPath, query, k = 5) {
|
|
35576
|
+
const db = openIndex(dbPath);
|
|
35577
|
+
try {
|
|
35578
|
+
const qvec = embed(query);
|
|
35579
|
+
let qmag = 0;
|
|
35580
|
+
for (let i = 0; i < VECTOR_DIM; i++) qmag += qvec[i] * qvec[i];
|
|
35581
|
+
if (qmag === 0) return [];
|
|
35582
|
+
const rows = db.prepare("SELECT name, description, vector FROM skills").all();
|
|
35583
|
+
const scored = rows.map((r) => {
|
|
35584
|
+
const v = bufferToVector(r.vector);
|
|
35585
|
+
const score = cosine(qvec, v);
|
|
35586
|
+
const snippet = (r.description || "").slice(0, 200);
|
|
35587
|
+
return { name: r.name, score, snippet };
|
|
35588
|
+
});
|
|
35589
|
+
scored.sort((a, b) => b.score - a.score);
|
|
35590
|
+
return scored.slice(0, Math.max(1, k));
|
|
35591
|
+
} finally {
|
|
35592
|
+
db.close();
|
|
35593
|
+
}
|
|
35594
|
+
}
|
|
35595
|
+
var DEFAULT_DB_PATH = path35.join(os21.homedir(), ".olam", "skills.vec.db");
|
|
35596
|
+
var DEFAULT_SOURCE_DIR = path35.join(os21.homedir(), ".claude", "skills");
|
|
35597
|
+
|
|
35598
|
+
// ../mcp-server/src/tools/skills-search.ts
|
|
35599
|
+
function defaultDbPath() {
|
|
35600
|
+
const override = process.env["SKILLS_INDEX_PATH"];
|
|
35601
|
+
if (override) return override;
|
|
35602
|
+
return path36.join(os22.homedir(), ".olam", "skills.vec.db");
|
|
35603
|
+
}
|
|
35604
|
+
function asMessage9(err) {
|
|
35605
|
+
return err instanceof Error ? err.message : String(err);
|
|
35606
|
+
}
|
|
35607
|
+
function ok3(data) {
|
|
35608
|
+
return {
|
|
35609
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
35610
|
+
};
|
|
35611
|
+
}
|
|
35612
|
+
function fail3(err) {
|
|
35613
|
+
return {
|
|
35614
|
+
content: [{ type: "text", text: asMessage9(err) }],
|
|
35615
|
+
isError: true
|
|
35616
|
+
};
|
|
35617
|
+
}
|
|
35618
|
+
function register27(server, _ctx, _initError) {
|
|
35619
|
+
server.tool(
|
|
35620
|
+
"olam_skills_search",
|
|
35621
|
+
"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).",
|
|
35622
|
+
{
|
|
35623
|
+
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").'),
|
|
35624
|
+
k: external_exports.number().int().min(1).max(50).optional().describe("Number of hits to return (default 5, max 50).")
|
|
35625
|
+
},
|
|
35626
|
+
async ({ query, k }) => {
|
|
35627
|
+
try {
|
|
35628
|
+
const hits = searchIndex(defaultDbPath(), query, k ?? 5);
|
|
35629
|
+
return ok3({ query, k: k ?? 5, count: hits.length, hits });
|
|
35630
|
+
} catch (err) {
|
|
35631
|
+
return fail3(err);
|
|
35632
|
+
}
|
|
35633
|
+
}
|
|
35634
|
+
);
|
|
35635
|
+
}
|
|
35636
|
+
|
|
34944
35637
|
// ../mcp-server/src/tools/kg-classify.ts
|
|
34945
35638
|
var kg_classify_exports = {};
|
|
34946
35639
|
__export(kg_classify_exports, {
|
|
34947
|
-
register: () =>
|
|
35640
|
+
register: () => register28
|
|
34948
35641
|
});
|
|
34949
35642
|
init_v3();
|
|
34950
35643
|
|
|
@@ -34957,8 +35650,8 @@ function port() {
|
|
|
34957
35650
|
const n = Number.parseInt(env, 10);
|
|
34958
35651
|
return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
|
|
34959
35652
|
}
|
|
34960
|
-
function url(
|
|
34961
|
-
return `http://127.0.0.1:${port()}${
|
|
35653
|
+
function url(path52) {
|
|
35654
|
+
return `http://127.0.0.1:${port()}${path52}`;
|
|
34962
35655
|
}
|
|
34963
35656
|
function kgServiceHealthUrl() {
|
|
34964
35657
|
return url("/health");
|
|
@@ -35019,7 +35712,7 @@ async function status(opts = {}) {
|
|
|
35019
35712
|
}
|
|
35020
35713
|
|
|
35021
35714
|
// ../mcp-server/src/tools/kg-classify.ts
|
|
35022
|
-
function
|
|
35715
|
+
function register28(server, _ctx, _initError) {
|
|
35023
35716
|
server.tool(
|
|
35024
35717
|
"olam_kg_classify",
|
|
35025
35718
|
"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 +35760,7 @@ function register27(server, _ctx, _initError) {
|
|
|
35067
35760
|
// ../mcp-server/src/tools/kg-doctor.ts
|
|
35068
35761
|
var kg_doctor_exports = {};
|
|
35069
35762
|
__export(kg_doctor_exports, {
|
|
35070
|
-
register: () =>
|
|
35763
|
+
register: () => register29
|
|
35071
35764
|
});
|
|
35072
35765
|
async function runProbes() {
|
|
35073
35766
|
const results = [];
|
|
@@ -35117,7 +35810,7 @@ async function runProbes() {
|
|
|
35117
35810
|
}
|
|
35118
35811
|
return results;
|
|
35119
35812
|
}
|
|
35120
|
-
function
|
|
35813
|
+
function register29(server, _ctx, _initError) {
|
|
35121
35814
|
server.tool(
|
|
35122
35815
|
"olam_kg_doctor",
|
|
35123
35816
|
"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 +35846,13 @@ function register28(server, _ctx, _initError) {
|
|
|
35153
35846
|
// ../mcp-server/src/tools/kg-install-hook.ts
|
|
35154
35847
|
var kg_install_hook_exports = {};
|
|
35155
35848
|
__export(kg_install_hook_exports, {
|
|
35156
|
-
register: () =>
|
|
35849
|
+
register: () => register30
|
|
35157
35850
|
});
|
|
35158
35851
|
init_v3();
|
|
35159
35852
|
init_merge_settings();
|
|
35160
|
-
import * as
|
|
35161
|
-
import * as
|
|
35162
|
-
import * as
|
|
35853
|
+
import * as fs37 from "node:fs";
|
|
35854
|
+
import * as path37 from "node:path";
|
|
35855
|
+
import * as os23 from "node:os";
|
|
35163
35856
|
|
|
35164
35857
|
// ../core/dist/kg/hook-template.js
|
|
35165
35858
|
var KG_HOOK_SENTINEL = "kg-service-v2-classifier-hook";
|
|
@@ -35209,12 +35902,12 @@ function buildHookMatcherEntry(opts) {
|
|
|
35209
35902
|
// ../mcp-server/src/tools/kg-install-hook.ts
|
|
35210
35903
|
function settingsPathFor2(scope, projectPath) {
|
|
35211
35904
|
if (scope === "user") {
|
|
35212
|
-
return
|
|
35905
|
+
return path37.join(os23.homedir(), ".claude", "settings.json");
|
|
35213
35906
|
}
|
|
35214
35907
|
const root = projectPath ?? process.cwd();
|
|
35215
|
-
return
|
|
35908
|
+
return path37.join(root, ".claude", "settings.json");
|
|
35216
35909
|
}
|
|
35217
|
-
function
|
|
35910
|
+
function register30(server, _ctx, _initError) {
|
|
35218
35911
|
server.tool(
|
|
35219
35912
|
"olam_kg_install_hook",
|
|
35220
35913
|
"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 +35919,12 @@ function register29(server, _ctx, _initError) {
|
|
|
35226
35919
|
const scope = params.scope === "user" ? "user" : "project";
|
|
35227
35920
|
const filePath = settingsPathFor2(scope, params.projectPath);
|
|
35228
35921
|
try {
|
|
35229
|
-
|
|
35922
|
+
fs37.mkdirSync(path37.dirname(filePath), { recursive: true });
|
|
35230
35923
|
let backupPath = null;
|
|
35231
|
-
if (
|
|
35924
|
+
if (fs37.existsSync(filePath)) {
|
|
35232
35925
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
35233
35926
|
backupPath = `${filePath}.olam-bak.${ts}`;
|
|
35234
|
-
|
|
35927
|
+
fs37.copyFileSync(filePath, backupPath);
|
|
35235
35928
|
}
|
|
35236
35929
|
const result = mergeHomeSettingsJson(filePath, {
|
|
35237
35930
|
ensureHook: {
|
|
@@ -35242,7 +35935,7 @@ function register29(server, _ctx, _initError) {
|
|
|
35242
35935
|
});
|
|
35243
35936
|
if (result.status === "already-present" && backupPath) {
|
|
35244
35937
|
try {
|
|
35245
|
-
|
|
35938
|
+
fs37.unlinkSync(backupPath);
|
|
35246
35939
|
} catch {
|
|
35247
35940
|
}
|
|
35248
35941
|
}
|
|
@@ -35283,18 +35976,18 @@ function register29(server, _ctx, _initError) {
|
|
|
35283
35976
|
// ../mcp-server/src/tools/kg-uninstall-hook.ts
|
|
35284
35977
|
var kg_uninstall_hook_exports = {};
|
|
35285
35978
|
__export(kg_uninstall_hook_exports, {
|
|
35286
|
-
register: () =>
|
|
35979
|
+
register: () => register31
|
|
35287
35980
|
});
|
|
35288
35981
|
init_v3();
|
|
35289
|
-
import * as
|
|
35290
|
-
import * as
|
|
35291
|
-
import * as
|
|
35982
|
+
import * as fs38 from "node:fs";
|
|
35983
|
+
import * as path38 from "node:path";
|
|
35984
|
+
import * as os24 from "node:os";
|
|
35292
35985
|
function settingsPathFor3(scope, projectPath) {
|
|
35293
35986
|
if (scope === "user") {
|
|
35294
|
-
return
|
|
35987
|
+
return path38.join(os24.homedir(), ".claude", "settings.json");
|
|
35295
35988
|
}
|
|
35296
35989
|
const root = projectPath ?? process.cwd();
|
|
35297
|
-
return
|
|
35990
|
+
return path38.join(root, ".claude", "settings.json");
|
|
35298
35991
|
}
|
|
35299
35992
|
function dropSentinel(matchers) {
|
|
35300
35993
|
let changed = false;
|
|
@@ -35316,7 +36009,7 @@ function dropSentinel(matchers) {
|
|
|
35316
36009
|
}
|
|
35317
36010
|
return { matchers: out, changed };
|
|
35318
36011
|
}
|
|
35319
|
-
function
|
|
36012
|
+
function register31(server, _ctx, _initError) {
|
|
35320
36013
|
server.tool(
|
|
35321
36014
|
"olam_kg_uninstall_hook",
|
|
35322
36015
|
"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 +36021,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35328
36021
|
const scope = params.scope === "user" ? "user" : "project";
|
|
35329
36022
|
const filePath = settingsPathFor3(scope, params.projectPath);
|
|
35330
36023
|
try {
|
|
35331
|
-
if (!
|
|
36024
|
+
if (!fs38.existsSync(filePath)) {
|
|
35332
36025
|
return {
|
|
35333
36026
|
content: [
|
|
35334
36027
|
{
|
|
@@ -35342,7 +36035,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35342
36035
|
]
|
|
35343
36036
|
};
|
|
35344
36037
|
}
|
|
35345
|
-
const raw =
|
|
36038
|
+
const raw = fs38.readFileSync(filePath, "utf-8");
|
|
35346
36039
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
35347
36040
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
35348
36041
|
if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
|
|
@@ -35377,7 +36070,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35377
36070
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
35378
36071
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
35379
36072
|
try {
|
|
35380
|
-
|
|
36073
|
+
fs38.copyFileSync(filePath, backupPath);
|
|
35381
36074
|
} catch {
|
|
35382
36075
|
}
|
|
35383
36076
|
const next = {
|
|
@@ -35389,7 +36082,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35389
36082
|
if (otherStages.length === 0) delete next.hooks;
|
|
35390
36083
|
else delete next.hooks.PreToolUse;
|
|
35391
36084
|
}
|
|
35392
|
-
|
|
36085
|
+
fs38.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
35393
36086
|
return {
|
|
35394
36087
|
content: [
|
|
35395
36088
|
{
|
|
@@ -35451,6 +36144,7 @@ var toolModules = [
|
|
|
35451
36144
|
runbook_exports,
|
|
35452
36145
|
skill_source_exports,
|
|
35453
36146
|
skills_exports,
|
|
36147
|
+
skills_search_exports,
|
|
35454
36148
|
kg_classify_exports,
|
|
35455
36149
|
kg_doctor_exports,
|
|
35456
36150
|
kg_install_hook_exports,
|
|
@@ -35462,6 +36156,207 @@ function registerAllTools(server, ctx, initError) {
|
|
|
35462
36156
|
}
|
|
35463
36157
|
}
|
|
35464
36158
|
|
|
36159
|
+
// ../mcp-server/src/resources/chunks.ts
|
|
36160
|
+
import fs39 from "node:fs";
|
|
36161
|
+
import os25 from "node:os";
|
|
36162
|
+
import path39 from "node:path";
|
|
36163
|
+
var DEFAULT_HOST_CP_URL = "http://127.0.0.1:19000";
|
|
36164
|
+
var DEFAULT_PLAN_CHAT_SECRET_PATH = path39.join(
|
|
36165
|
+
os25.homedir(),
|
|
36166
|
+
".olam",
|
|
36167
|
+
"plan-chat-secret"
|
|
36168
|
+
);
|
|
36169
|
+
var URI_SCHEME = "olam:";
|
|
36170
|
+
var URI_HOST = "worlds";
|
|
36171
|
+
var WORLD_ID_RE2 = /^[a-z0-9][a-z0-9-_.]{0,62}$/i;
|
|
36172
|
+
var SESSION_ID_RE = /^[a-zA-Z0-9_\-.]{1,128}$/;
|
|
36173
|
+
var LIMIT_RE = /^[1-9][0-9]{0,5}$/;
|
|
36174
|
+
function loadBearer(bearerOpt, secretPath) {
|
|
36175
|
+
if (typeof bearerOpt === "string" && bearerOpt.length > 0) return bearerOpt;
|
|
36176
|
+
const envBearer = process.env.OLAM_PLAN_CHAT_BEARER?.trim();
|
|
36177
|
+
if (envBearer && envBearer.length > 0) return envBearer;
|
|
36178
|
+
try {
|
|
36179
|
+
const onDisk = fs39.readFileSync(secretPath, "utf8").trim();
|
|
36180
|
+
return onDisk.length > 0 ? onDisk : null;
|
|
36181
|
+
} catch (err) {
|
|
36182
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
|
|
36183
|
+
return null;
|
|
36184
|
+
}
|
|
36185
|
+
return null;
|
|
36186
|
+
}
|
|
36187
|
+
}
|
|
36188
|
+
function parseChunksUri(uri) {
|
|
36189
|
+
let parsed;
|
|
36190
|
+
try {
|
|
36191
|
+
parsed = new URL(uri);
|
|
36192
|
+
} catch {
|
|
36193
|
+
return null;
|
|
36194
|
+
}
|
|
36195
|
+
if (parsed.protocol !== URI_SCHEME) return null;
|
|
36196
|
+
if (parsed.host !== URI_HOST) return null;
|
|
36197
|
+
const segments = parsed.pathname.split("/").filter((s) => s.length > 0);
|
|
36198
|
+
if (segments.length !== 2) return null;
|
|
36199
|
+
const [rawWorldId, kind] = segments;
|
|
36200
|
+
if (rawWorldId === void 0 || kind !== "chunks") return null;
|
|
36201
|
+
const worldId = decodeURIComponent(rawWorldId);
|
|
36202
|
+
if (!WORLD_ID_RE2.test(worldId)) return null;
|
|
36203
|
+
const sessionIdRaw = parsed.searchParams.get("sessionId");
|
|
36204
|
+
const limitRaw = parsed.searchParams.get("limit");
|
|
36205
|
+
let sessionId;
|
|
36206
|
+
if (sessionIdRaw !== null) {
|
|
36207
|
+
if (!SESSION_ID_RE.test(sessionIdRaw)) return null;
|
|
36208
|
+
sessionId = sessionIdRaw;
|
|
36209
|
+
}
|
|
36210
|
+
let limit;
|
|
36211
|
+
if (limitRaw !== null) {
|
|
36212
|
+
if (!LIMIT_RE.test(limitRaw)) return null;
|
|
36213
|
+
limit = Number.parseInt(limitRaw, 10);
|
|
36214
|
+
}
|
|
36215
|
+
return { worldId, sessionId, limit };
|
|
36216
|
+
}
|
|
36217
|
+
function buildUpstreamUrl(hostCpUrl, parts) {
|
|
36218
|
+
const upstream = new URL(hostCpUrl);
|
|
36219
|
+
upstream.pathname = "/api/plan-chat/v1/shape";
|
|
36220
|
+
upstream.searchParams.set("table", "chunks");
|
|
36221
|
+
upstream.searchParams.set("world_id", parts.worldId);
|
|
36222
|
+
if (parts.sessionId) {
|
|
36223
|
+
upstream.searchParams.set("session_id", parts.sessionId);
|
|
36224
|
+
}
|
|
36225
|
+
if (typeof parts.limit === "number") {
|
|
36226
|
+
upstream.searchParams.set("limit", String(parts.limit));
|
|
36227
|
+
}
|
|
36228
|
+
upstream.searchParams.set("offset", "-1");
|
|
36229
|
+
return upstream;
|
|
36230
|
+
}
|
|
36231
|
+
function createChunksResource(deps = {}) {
|
|
36232
|
+
const hostCpUrl = deps.hostCpUrl ?? process.env.OLAM_HOST_CP_URL?.trim() ?? DEFAULT_HOST_CP_URL;
|
|
36233
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
36234
|
+
const secretPath = deps.secretPath ?? DEFAULT_PLAN_CHAT_SECRET_PATH;
|
|
36235
|
+
const resolveBearer = () => loadBearer(deps.bearer, secretPath);
|
|
36236
|
+
return {
|
|
36237
|
+
name: "olam-world-chunks",
|
|
36238
|
+
// RFC 6570 form with required `sessionId` in the template (the SDK's
|
|
36239
|
+
// matcher treats every listed var as required, so listing both
|
|
36240
|
+
// `sessionId` AND `limit` would reject URIs that only pass sessionId).
|
|
36241
|
+
// The optional `limit` param is parsed by `parseChunksUri` from the
|
|
36242
|
+
// concrete URL instead — clients pass `?sessionId=...&limit=...` and
|
|
36243
|
+
// both fields land in `ChunksUriParts`.
|
|
36244
|
+
uriTemplate: "olam://worlds/{worldId}/chunks{?sessionId}",
|
|
36245
|
+
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.",
|
|
36246
|
+
mimeType: "application/json",
|
|
36247
|
+
parseUri: parseChunksUri,
|
|
36248
|
+
async read(uri) {
|
|
36249
|
+
const parts = parseChunksUri(uri);
|
|
36250
|
+
if (!parts) {
|
|
36251
|
+
return {
|
|
36252
|
+
ok: false,
|
|
36253
|
+
code: "invalid_uri",
|
|
36254
|
+
message: `Invalid chunks URI: ${uri}. Expected \`olam://worlds/{worldId}/chunks?sessionId=<id>\`.`
|
|
36255
|
+
};
|
|
36256
|
+
}
|
|
36257
|
+
if (!parts.sessionId) {
|
|
36258
|
+
return {
|
|
36259
|
+
ok: false,
|
|
36260
|
+
code: "missing_session_id",
|
|
36261
|
+
message: "sessionId query param is required. Electric SQL enforces per-(world_id,session_id) scope at the proxy layer."
|
|
36262
|
+
};
|
|
36263
|
+
}
|
|
36264
|
+
const bearer = resolveBearer();
|
|
36265
|
+
if (!bearer) {
|
|
36266
|
+
return {
|
|
36267
|
+
ok: false,
|
|
36268
|
+
code: "missing_bearer",
|
|
36269
|
+
message: "No plan-chat bearer available. Set OLAM_PLAN_CHAT_BEARER or ensure ~/.olam/plan-chat-secret exists."
|
|
36270
|
+
};
|
|
36271
|
+
}
|
|
36272
|
+
const upstream = buildUpstreamUrl(hostCpUrl, parts);
|
|
36273
|
+
let res;
|
|
36274
|
+
try {
|
|
36275
|
+
res = await fetchImpl(upstream.toString(), {
|
|
36276
|
+
method: "GET",
|
|
36277
|
+
headers: {
|
|
36278
|
+
authorization: `Bearer ${bearer}`,
|
|
36279
|
+
accept: "application/json"
|
|
36280
|
+
}
|
|
36281
|
+
});
|
|
36282
|
+
} catch (err) {
|
|
36283
|
+
return {
|
|
36284
|
+
ok: false,
|
|
36285
|
+
code: "upstream_unavailable",
|
|
36286
|
+
message: `host-cp /api/plan-chat/v1/shape unreachable: ${err instanceof Error ? err.message : String(err)}`,
|
|
36287
|
+
detail: { upstream: upstream.toString() }
|
|
36288
|
+
};
|
|
36289
|
+
}
|
|
36290
|
+
if (!res.ok) {
|
|
36291
|
+
let body = "";
|
|
36292
|
+
try {
|
|
36293
|
+
body = await res.text();
|
|
36294
|
+
} catch {
|
|
36295
|
+
}
|
|
36296
|
+
return {
|
|
36297
|
+
ok: false,
|
|
36298
|
+
code: "upstream_error",
|
|
36299
|
+
message: `host-cp returned ${res.status} ${res.statusText} for chunks fetch`,
|
|
36300
|
+
detail: { upstream: upstream.toString(), body: body.slice(0, 512) }
|
|
36301
|
+
};
|
|
36302
|
+
}
|
|
36303
|
+
let payload;
|
|
36304
|
+
try {
|
|
36305
|
+
payload = await res.json();
|
|
36306
|
+
} catch (err) {
|
|
36307
|
+
return {
|
|
36308
|
+
ok: false,
|
|
36309
|
+
code: "upstream_error",
|
|
36310
|
+
message: `host-cp returned non-JSON body for chunks fetch: ${err instanceof Error ? err.message : String(err)}`,
|
|
36311
|
+
detail: { upstream: upstream.toString() }
|
|
36312
|
+
};
|
|
36313
|
+
}
|
|
36314
|
+
return {
|
|
36315
|
+
ok: true,
|
|
36316
|
+
uri,
|
|
36317
|
+
mimeType: "application/json",
|
|
36318
|
+
payload
|
|
36319
|
+
};
|
|
36320
|
+
}
|
|
36321
|
+
};
|
|
36322
|
+
}
|
|
36323
|
+
|
|
36324
|
+
// ../mcp-server/src/resources/index.ts
|
|
36325
|
+
function registerAllResources(server, deps = {}) {
|
|
36326
|
+
const chunks = deps.chunks ?? createChunksResource();
|
|
36327
|
+
server.registerResource(
|
|
36328
|
+
chunks.name,
|
|
36329
|
+
new ResourceTemplate(chunks.uriTemplate, {
|
|
36330
|
+
list: void 0
|
|
36331
|
+
}),
|
|
36332
|
+
{
|
|
36333
|
+
description: chunks.description,
|
|
36334
|
+
mimeType: chunks.mimeType
|
|
36335
|
+
},
|
|
36336
|
+
async (uri) => {
|
|
36337
|
+
const result = await chunks.read(uri.toString());
|
|
36338
|
+
if (!result.ok) {
|
|
36339
|
+
const err = new Error(result.message);
|
|
36340
|
+
err.code = result.code;
|
|
36341
|
+
throw err;
|
|
36342
|
+
}
|
|
36343
|
+
return {
|
|
36344
|
+
contents: [
|
|
36345
|
+
{
|
|
36346
|
+
uri: result.uri,
|
|
36347
|
+
mimeType: result.mimeType,
|
|
36348
|
+
text: JSON.stringify(result.payload)
|
|
36349
|
+
}
|
|
36350
|
+
]
|
|
36351
|
+
};
|
|
36352
|
+
}
|
|
36353
|
+
);
|
|
36354
|
+
logger.info("Olam MCP resources registered", {
|
|
36355
|
+
resources: [chunks.name],
|
|
36356
|
+
uriTemplate: chunks.uriTemplate
|
|
36357
|
+
});
|
|
36358
|
+
}
|
|
36359
|
+
|
|
35465
36360
|
// ../mcp-server/src/server.ts
|
|
35466
36361
|
var SERVER_NAME = "olam";
|
|
35467
36362
|
var SERVER_VERSION = "0.1.0";
|
|
@@ -35477,6 +36372,7 @@ function createServer4(ctx, initError) {
|
|
|
35477
36372
|
{ instructions: SERVER_INSTRUCTIONS }
|
|
35478
36373
|
);
|
|
35479
36374
|
registerAllTools(server, ctx, initError);
|
|
36375
|
+
registerAllResources(server);
|
|
35480
36376
|
logger.info("Olam MCP server created", {
|
|
35481
36377
|
name: SERVER_NAME,
|
|
35482
36378
|
version: SERVER_VERSION,
|
|
@@ -35486,8 +36382,8 @@ function createServer4(ctx, initError) {
|
|
|
35486
36382
|
}
|
|
35487
36383
|
|
|
35488
36384
|
// ../mcp-server/src/utils/native-probe.ts
|
|
35489
|
-
import { createRequire as
|
|
35490
|
-
var PROBE_REQUIRE =
|
|
36385
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
36386
|
+
var PROBE_REQUIRE = createRequire5(import.meta.url);
|
|
35491
36387
|
function runtimeModuleVersion() {
|
|
35492
36388
|
return Number.parseInt(process.versions.modules, 10);
|
|
35493
36389
|
}
|
|
@@ -35604,9 +36500,9 @@ init_loader();
|
|
|
35604
36500
|
// ../core/dist/world/manager.js
|
|
35605
36501
|
import * as crypto8 from "node:crypto";
|
|
35606
36502
|
import { execSync as execSync5, spawnSync as spawnSync4 } from "node:child_process";
|
|
35607
|
-
import * as
|
|
35608
|
-
import * as
|
|
35609
|
-
import * as
|
|
36503
|
+
import * as fs48 from "node:fs";
|
|
36504
|
+
import * as os29 from "node:os";
|
|
36505
|
+
import * as path49 from "node:path";
|
|
35610
36506
|
|
|
35611
36507
|
// ../core/dist/world/state.js
|
|
35612
36508
|
var VALID_TRANSITIONS = {
|
|
@@ -35702,8 +36598,8 @@ function resolveDevboxImage(config2, tag) {
|
|
|
35702
36598
|
|
|
35703
36599
|
// ../core/dist/world/worktree.js
|
|
35704
36600
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
35705
|
-
import * as
|
|
35706
|
-
import * as
|
|
36601
|
+
import * as fs40 from "node:fs";
|
|
36602
|
+
import * as path40 from "node:path";
|
|
35707
36603
|
function resolveGitDir(repo) {
|
|
35708
36604
|
if (repo.path) {
|
|
35709
36605
|
return repo.path;
|
|
@@ -35713,11 +36609,11 @@ function resolveGitDir(repo) {
|
|
|
35713
36609
|
async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
35714
36610
|
const created = [];
|
|
35715
36611
|
for (const repo of repos) {
|
|
35716
|
-
const worktreePath =
|
|
36612
|
+
const worktreePath = path40.join(workspacePath, repo.name);
|
|
35717
36613
|
const gitDir = resolveGitDir(repo);
|
|
35718
36614
|
const branchName = branch || `olam/${worldId}`;
|
|
35719
36615
|
try {
|
|
35720
|
-
|
|
36616
|
+
fs40.mkdirSync(path40.dirname(worktreePath), { recursive: true });
|
|
35721
36617
|
execFileSync4("git", ["worktree", "add", worktreePath, "-b", branchName], {
|
|
35722
36618
|
cwd: gitDir,
|
|
35723
36619
|
stdio: "pipe"
|
|
@@ -35750,7 +36646,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
|
35750
36646
|
}
|
|
35751
36647
|
async function removeWorktrees(repos, workspacePath) {
|
|
35752
36648
|
for (const repo of repos) {
|
|
35753
|
-
const worktreePath =
|
|
36649
|
+
const worktreePath = path40.join(workspacePath, repo.name);
|
|
35754
36650
|
let gitDir;
|
|
35755
36651
|
try {
|
|
35756
36652
|
gitDir = resolveGitDir(repo);
|
|
@@ -35825,12 +36721,12 @@ function removeBranch(repo, branch) {
|
|
|
35825
36721
|
|
|
35826
36722
|
// ../core/dist/world/kg-overlay.js
|
|
35827
36723
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
35828
|
-
import * as
|
|
35829
|
-
import * as
|
|
36724
|
+
import * as fs41 from "node:fs";
|
|
36725
|
+
import * as path41 from "node:path";
|
|
35830
36726
|
|
|
35831
36727
|
// ../core/dist/kg/storage-paths.js
|
|
35832
|
-
import { homedir as
|
|
35833
|
-
import { join as
|
|
36728
|
+
import { homedir as homedir24 } from "node:os";
|
|
36729
|
+
import { join as join41, resolve as resolve9 } from "node:path";
|
|
35834
36730
|
|
|
35835
36731
|
// ../core/dist/world/workspace-name.js
|
|
35836
36732
|
var InvalidWorkspaceNameError = class extends Error {
|
|
@@ -35851,25 +36747,25 @@ function validateWorkspaceName(name) {
|
|
|
35851
36747
|
|
|
35852
36748
|
// ../core/dist/kg/storage-paths.js
|
|
35853
36749
|
function olamHome() {
|
|
35854
|
-
return process.env.OLAM_HOME ??
|
|
36750
|
+
return process.env.OLAM_HOME ?? join41(homedir24(), ".olam");
|
|
35855
36751
|
}
|
|
35856
36752
|
function kgRoot() {
|
|
35857
|
-
return
|
|
36753
|
+
return join41(olamHome(), "kg");
|
|
35858
36754
|
}
|
|
35859
36755
|
function worldsRoot() {
|
|
35860
|
-
return
|
|
36756
|
+
return join41(olamHome(), "worlds");
|
|
35861
36757
|
}
|
|
35862
|
-
function assertWithinPrefix(
|
|
35863
|
-
if (!
|
|
35864
|
-
throw new Error(`${label} escape: ${
|
|
36758
|
+
function assertWithinPrefix(path52, prefix, label) {
|
|
36759
|
+
if (!path52.startsWith(prefix + "/")) {
|
|
36760
|
+
throw new Error(`${label} escape: ${path52} not under ${prefix}/`);
|
|
35865
36761
|
}
|
|
35866
36762
|
}
|
|
35867
36763
|
function kgPristinePath(workspace) {
|
|
35868
36764
|
validateWorkspaceName(workspace);
|
|
35869
36765
|
const root = kgRoot();
|
|
35870
|
-
const
|
|
35871
|
-
assertWithinPrefix(
|
|
35872
|
-
return
|
|
36766
|
+
const path52 = resolve9(join41(root, workspace));
|
|
36767
|
+
assertWithinPrefix(path52, root, "kgPristinePath");
|
|
36768
|
+
return path52;
|
|
35873
36769
|
}
|
|
35874
36770
|
var KG_PATHS_INTERNALS = Object.freeze({
|
|
35875
36771
|
olamHome,
|
|
@@ -35885,10 +36781,10 @@ var KgOverlayError = class extends Error {
|
|
|
35885
36781
|
}
|
|
35886
36782
|
};
|
|
35887
36783
|
function ensureGitignoreEntry(worldClonePath) {
|
|
35888
|
-
const gitignorePath =
|
|
35889
|
-
if (!
|
|
36784
|
+
const gitignorePath = path41.join(worldClonePath, ".gitignore");
|
|
36785
|
+
if (!fs41.existsSync(gitignorePath))
|
|
35890
36786
|
return "no-gitignore";
|
|
35891
|
-
const content =
|
|
36787
|
+
const content = fs41.readFileSync(gitignorePath, "utf-8");
|
|
35892
36788
|
const lines = content.split("\n").map((l) => l.trim());
|
|
35893
36789
|
const recognised = /* @__PURE__ */ new Set([
|
|
35894
36790
|
"graphify-out",
|
|
@@ -35903,24 +36799,24 @@ function ensureGitignoreEntry(worldClonePath) {
|
|
|
35903
36799
|
const eol = content.includes("\r\n") ? "\r\n" : "\n";
|
|
35904
36800
|
const needsLeadingNewline = content.length > 0 && !content.endsWith(eol);
|
|
35905
36801
|
const block = `${needsLeadingNewline ? eol : ""}${eol}# olam-kg-service: per-world KG overlay (Phase B1)${eol}graphify-out/${eol}`;
|
|
35906
|
-
|
|
36802
|
+
fs41.appendFileSync(gitignorePath, block, "utf-8");
|
|
35907
36803
|
return "appended";
|
|
35908
36804
|
}
|
|
35909
36805
|
function createWorldOverlay(opts) {
|
|
35910
36806
|
const pristineRoot = kgPristinePath(opts.workspace);
|
|
35911
|
-
const pristinePath =
|
|
35912
|
-
if (!
|
|
36807
|
+
const pristinePath = path41.join(pristineRoot, "graphify-out");
|
|
36808
|
+
if (!fs41.existsSync(pristinePath)) {
|
|
35913
36809
|
throw new KgOverlayError(`Pristine KG for workspace ${JSON.stringify(opts.workspace)} not found at ${pristinePath}. Run \`olam kg build ${opts.workspace}\` first.`);
|
|
35914
36810
|
}
|
|
35915
|
-
if (!
|
|
36811
|
+
if (!path41.isAbsolute(opts.worldClonePath)) {
|
|
35916
36812
|
throw new KgOverlayError(`worldClonePath must be absolute (got ${opts.worldClonePath})`);
|
|
35917
36813
|
}
|
|
35918
|
-
if (!
|
|
36814
|
+
if (!fs41.existsSync(opts.worldClonePath)) {
|
|
35919
36815
|
throw new KgOverlayError(`worldClonePath does not exist: ${opts.worldClonePath}. Create the clone before reflinking.`);
|
|
35920
36816
|
}
|
|
35921
|
-
const overlayPath =
|
|
35922
|
-
if (
|
|
35923
|
-
|
|
36817
|
+
const overlayPath = path41.join(opts.worldClonePath, "graphify-out");
|
|
36818
|
+
if (fs41.existsSync(overlayPath)) {
|
|
36819
|
+
fs41.rmSync(overlayPath, { recursive: true, force: true });
|
|
35924
36820
|
}
|
|
35925
36821
|
const useReflink = process.platform === "darwin";
|
|
35926
36822
|
let strategy;
|
|
@@ -35938,7 +36834,7 @@ function createWorldOverlay(opts) {
|
|
|
35938
36834
|
} else {
|
|
35939
36835
|
strategy = "cp-r";
|
|
35940
36836
|
}
|
|
35941
|
-
if (strategy === "cp-r" || !
|
|
36837
|
+
if (strategy === "cp-r" || !fs41.existsSync(overlayPath)) {
|
|
35942
36838
|
try {
|
|
35943
36839
|
execFileSync5("cp", ["-r", pristinePath, opts.worldClonePath], {
|
|
35944
36840
|
stdio: ["ignore", "ignore", "pipe"]
|
|
@@ -35950,7 +36846,7 @@ function createWorldOverlay(opts) {
|
|
|
35950
36846
|
throw new KgOverlayError(`cp -r failed: ${msg}${reflinkMsg}`);
|
|
35951
36847
|
}
|
|
35952
36848
|
}
|
|
35953
|
-
if (!
|
|
36849
|
+
if (!fs41.existsSync(overlayPath)) {
|
|
35954
36850
|
throw new KgOverlayError(`Overlay creation produced no ${overlayPath} after cp \u2014 filesystem returned without error?`);
|
|
35955
36851
|
}
|
|
35956
36852
|
const gitignoreAction = ensureGitignoreEntry(opts.worldClonePath);
|
|
@@ -35964,12 +36860,12 @@ function createWorldOverlay(opts) {
|
|
|
35964
36860
|
|
|
35965
36861
|
// ../core/dist/world/baseline-diff.js
|
|
35966
36862
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
35967
|
-
import * as
|
|
35968
|
-
import * as
|
|
35969
|
-
import * as
|
|
36863
|
+
import * as fs42 from "node:fs";
|
|
36864
|
+
import * as os26 from "node:os";
|
|
36865
|
+
import * as path42 from "node:path";
|
|
35970
36866
|
var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
35971
|
-
function expandHome2(p,
|
|
35972
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
36867
|
+
function expandHome2(p, homedir30) {
|
|
36868
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir30());
|
|
35973
36869
|
}
|
|
35974
36870
|
function sanitizeRepoFilename(name) {
|
|
35975
36871
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -35992,10 +36888,10 @@ ${stderr}`;
|
|
|
35992
36888
|
}
|
|
35993
36889
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
35994
36890
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
35995
|
-
const
|
|
35996
|
-
const baselineDir =
|
|
36891
|
+
const homedir30 = deps.homedir ?? (() => os26.homedir());
|
|
36892
|
+
const baselineDir = path42.join(workspacePath, ".olam", "baseline");
|
|
35997
36893
|
try {
|
|
35998
|
-
|
|
36894
|
+
fs42.mkdirSync(baselineDir, { recursive: true });
|
|
35999
36895
|
} catch (err) {
|
|
36000
36896
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36001
36897
|
console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
|
|
@@ -36007,9 +36903,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
36007
36903
|
if (!repo.path)
|
|
36008
36904
|
continue;
|
|
36009
36905
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
36010
|
-
const outPath =
|
|
36011
|
-
const repoPath = expandHome2(repo.path,
|
|
36012
|
-
if (!
|
|
36906
|
+
const outPath = path42.join(baselineDir, filename);
|
|
36907
|
+
const repoPath = expandHome2(repo.path, homedir30);
|
|
36908
|
+
if (!fs42.existsSync(repoPath)) {
|
|
36013
36909
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
36014
36910
|
# (skipped: path ${repoPath} does not exist)
|
|
36015
36911
|
`);
|
|
@@ -36076,7 +36972,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
36076
36972
|
}
|
|
36077
36973
|
function writeBaselineFile(outPath, content) {
|
|
36078
36974
|
try {
|
|
36079
|
-
|
|
36975
|
+
fs42.writeFileSync(outPath, content);
|
|
36080
36976
|
} catch (err) {
|
|
36081
36977
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36082
36978
|
console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
|
|
@@ -36084,8 +36980,8 @@ function writeBaselineFile(outPath, content) {
|
|
|
36084
36980
|
}
|
|
36085
36981
|
function stripWorktreeEdits(repos, workspacePath) {
|
|
36086
36982
|
for (const repo of repos) {
|
|
36087
|
-
const worktreePath =
|
|
36088
|
-
if (!
|
|
36983
|
+
const worktreePath = path42.join(workspacePath, repo.name);
|
|
36984
|
+
if (!fs42.existsSync(worktreePath))
|
|
36089
36985
|
continue;
|
|
36090
36986
|
try {
|
|
36091
36987
|
execFileSync6("git", ["checkout", "--", "."], {
|
|
@@ -36144,21 +37040,21 @@ function extractStderr(err) {
|
|
|
36144
37040
|
}
|
|
36145
37041
|
function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
36146
37042
|
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
|
-
|
|
37043
|
+
const homedir30 = deps.homedir ?? (() => os26.homedir());
|
|
37044
|
+
const existsSync48 = deps.existsSync ?? ((p) => fs42.existsSync(p));
|
|
37045
|
+
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs42.copyFileSync(src, dest));
|
|
37046
|
+
const mkdirSync30 = deps.mkdirSync ?? ((dirPath, opts) => {
|
|
37047
|
+
fs42.mkdirSync(dirPath, opts);
|
|
36152
37048
|
});
|
|
36153
37049
|
const plans = [];
|
|
36154
37050
|
for (const repo of repos) {
|
|
36155
37051
|
if (!repo.path)
|
|
36156
37052
|
continue;
|
|
36157
|
-
const repoPath = expandHome2(repo.path,
|
|
36158
|
-
const worktreePath =
|
|
36159
|
-
if (!
|
|
37053
|
+
const repoPath = expandHome2(repo.path, homedir30);
|
|
37054
|
+
const worktreePath = path42.join(workspacePath, repo.name);
|
|
37055
|
+
if (!existsSync48(repoPath))
|
|
36160
37056
|
continue;
|
|
36161
|
-
if (!
|
|
37057
|
+
if (!existsSync48(worktreePath)) {
|
|
36162
37058
|
console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
|
|
36163
37059
|
continue;
|
|
36164
37060
|
}
|
|
@@ -36216,12 +37112,12 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
36216
37112
|
}
|
|
36217
37113
|
}
|
|
36218
37114
|
for (const rel of plan.diff.untracked) {
|
|
36219
|
-
const src =
|
|
36220
|
-
const dest =
|
|
36221
|
-
if (!
|
|
37115
|
+
const src = path42.join(plan.repoPath, rel);
|
|
37116
|
+
const dest = path42.join(plan.worktreePath, rel);
|
|
37117
|
+
if (!existsSync48(src))
|
|
36222
37118
|
continue;
|
|
36223
37119
|
try {
|
|
36224
|
-
|
|
37120
|
+
mkdirSync30(path42.dirname(dest), { recursive: true });
|
|
36225
37121
|
copyFileSync9(src, dest);
|
|
36226
37122
|
} catch (err) {
|
|
36227
37123
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -36247,8 +37143,8 @@ function formatBaselineSummary(result) {
|
|
|
36247
37143
|
}
|
|
36248
37144
|
|
|
36249
37145
|
// ../core/dist/world/context-injection.js
|
|
36250
|
-
import * as
|
|
36251
|
-
import * as
|
|
37146
|
+
import * as fs43 from "node:fs";
|
|
37147
|
+
import * as path43 from "node:path";
|
|
36252
37148
|
|
|
36253
37149
|
// ../core/dist/world/templates/_generated.js
|
|
36254
37150
|
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 +37154,10 @@ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Enviro
|
|
|
36258
37154
|
// ../core/dist/world/context-injection.js
|
|
36259
37155
|
function injectWorldContext(opts) {
|
|
36260
37156
|
const { world } = opts;
|
|
36261
|
-
const claudeDir2 =
|
|
36262
|
-
|
|
37157
|
+
const claudeDir2 = path43.join(world.workspacePath, ".claude");
|
|
37158
|
+
fs43.mkdirSync(claudeDir2, { recursive: true });
|
|
36263
37159
|
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
|
-
|
|
37160
|
+
fs43.writeFileSync(path43.join(claudeDir2, "CLAUDE.md"), content);
|
|
36265
37161
|
writeOlamDocs(world.workspacePath);
|
|
36266
37162
|
}
|
|
36267
37163
|
function buildTaskBlock(opts) {
|
|
@@ -36335,10 +37231,10 @@ function buildExtraContextBlock(extra) {
|
|
|
36335
37231
|
${extra}`;
|
|
36336
37232
|
}
|
|
36337
37233
|
function writeOlamDocs(workspacePath) {
|
|
36338
|
-
const docsDir =
|
|
36339
|
-
|
|
36340
|
-
|
|
36341
|
-
|
|
37234
|
+
const docsDir = path43.join(workspacePath, ".olam", "docs");
|
|
37235
|
+
fs43.mkdirSync(docsDir, { recursive: true });
|
|
37236
|
+
fs43.writeFileSync(path43.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
|
|
37237
|
+
fs43.writeFileSync(path43.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
|
|
36342
37238
|
}
|
|
36343
37239
|
function formatTaskSource(ctx) {
|
|
36344
37240
|
if (ctx.source === "linear" && ctx.ticketId) {
|
|
@@ -36352,9 +37248,9 @@ function formatTaskSource(ctx) {
|
|
|
36352
37248
|
function hasPlanFile(world) {
|
|
36353
37249
|
if (world.repos.length === 0)
|
|
36354
37250
|
return false;
|
|
36355
|
-
const plansDir =
|
|
37251
|
+
const plansDir = path43.join(world.workspacePath, world.repos[0], "docs", "plans");
|
|
36356
37252
|
try {
|
|
36357
|
-
return
|
|
37253
|
+
return fs43.existsSync(plansDir) && fs43.readdirSync(plansDir).length > 0;
|
|
36358
37254
|
} catch {
|
|
36359
37255
|
return false;
|
|
36360
37256
|
}
|
|
@@ -36926,25 +37822,25 @@ init_repo_manifest();
|
|
|
36926
37822
|
|
|
36927
37823
|
// ../core/dist/world/snapshot.js
|
|
36928
37824
|
import * as crypto7 from "node:crypto";
|
|
36929
|
-
import * as
|
|
36930
|
-
import * as
|
|
36931
|
-
import * as
|
|
37825
|
+
import * as fs44 from "node:fs";
|
|
37826
|
+
import * as os27 from "node:os";
|
|
37827
|
+
import * as path44 from "node:path";
|
|
36932
37828
|
import { execFileSync as execFileSync7, spawn as spawn2 } from "node:child_process";
|
|
36933
37829
|
import { gunzipSync } from "node:zlib";
|
|
36934
37830
|
function snapshotsDir() {
|
|
36935
|
-
return process.env["OLAM_SNAPSHOTS_DIR"] ??
|
|
37831
|
+
return process.env["OLAM_SNAPSHOTS_DIR"] ?? path44.join(os27.homedir(), ".olam", "snapshots");
|
|
36936
37832
|
}
|
|
36937
37833
|
function snapshotKindDirByWorkspace(workspace, arch, kind) {
|
|
36938
|
-
return
|
|
37834
|
+
return path44.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
|
|
36939
37835
|
}
|
|
36940
37836
|
function cleanupLegacyByWorldDir(worldId) {
|
|
36941
|
-
const legacyDir =
|
|
37837
|
+
const legacyDir = path44.join(snapshotsDir(), worldId);
|
|
36942
37838
|
if (worldId === "by-workspace")
|
|
36943
37839
|
return;
|
|
36944
|
-
if (!
|
|
37840
|
+
if (!fs44.existsSync(legacyDir))
|
|
36945
37841
|
return;
|
|
36946
37842
|
try {
|
|
36947
|
-
|
|
37843
|
+
fs44.rmSync(legacyDir, { recursive: true, force: true });
|
|
36948
37844
|
} catch {
|
|
36949
37845
|
}
|
|
36950
37846
|
}
|
|
@@ -36963,11 +37859,11 @@ function hashBuffers(entries) {
|
|
|
36963
37859
|
return hash.digest("hex").slice(0, 12);
|
|
36964
37860
|
}
|
|
36965
37861
|
function computeGemsFingerprint(repoDir, imageDigest) {
|
|
36966
|
-
const lockfile =
|
|
36967
|
-
if (!
|
|
37862
|
+
const lockfile = path44.join(repoDir, "Gemfile.lock");
|
|
37863
|
+
if (!fs44.existsSync(lockfile))
|
|
36968
37864
|
return null;
|
|
36969
37865
|
const entries = [
|
|
36970
|
-
{ path: "Gemfile.lock", content:
|
|
37866
|
+
{ path: "Gemfile.lock", content: fs44.readFileSync(lockfile) }
|
|
36971
37867
|
];
|
|
36972
37868
|
if (imageDigest) {
|
|
36973
37869
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -36977,10 +37873,10 @@ function computeGemsFingerprint(repoDir, imageDigest) {
|
|
|
36977
37873
|
function computeNodeFingerprint(repoDir, imageDigest) {
|
|
36978
37874
|
const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
|
|
36979
37875
|
for (const name of candidates) {
|
|
36980
|
-
const lockfile =
|
|
36981
|
-
if (
|
|
37876
|
+
const lockfile = path44.join(repoDir, name);
|
|
37877
|
+
if (fs44.existsSync(lockfile)) {
|
|
36982
37878
|
const entries = [
|
|
36983
|
-
{ path: name, content:
|
|
37879
|
+
{ path: name, content: fs44.readFileSync(lockfile) }
|
|
36984
37880
|
];
|
|
36985
37881
|
if (imageDigest) {
|
|
36986
37882
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -36999,18 +37895,18 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
36999
37895
|
detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
|
|
37000
37896
|
};
|
|
37001
37897
|
}
|
|
37002
|
-
const parent =
|
|
37003
|
-
|
|
37898
|
+
const parent = path44.dirname(destDir);
|
|
37899
|
+
fs44.mkdirSync(parent, { recursive: true });
|
|
37004
37900
|
const tmpSuffix = `.tmp-${process.pid}-${crypto7.randomBytes(4).toString("hex")}`;
|
|
37005
37901
|
const tmpDir = `${destDir}${tmpSuffix}`;
|
|
37006
37902
|
try {
|
|
37007
|
-
|
|
37903
|
+
fs44.mkdirSync(tmpDir, { recursive: true });
|
|
37008
37904
|
execFileSync7("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
|
|
37009
|
-
|
|
37905
|
+
fs44.renameSync(tmpDir, destDir);
|
|
37010
37906
|
return { ok: true, entryCount: validation.entries.length };
|
|
37011
37907
|
} catch (err) {
|
|
37012
37908
|
try {
|
|
37013
|
-
|
|
37909
|
+
fs44.rmSync(tmpDir, { recursive: true, force: true });
|
|
37014
37910
|
} catch {
|
|
37015
37911
|
}
|
|
37016
37912
|
return {
|
|
@@ -37021,12 +37917,12 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
37021
37917
|
}
|
|
37022
37918
|
}
|
|
37023
37919
|
function resolvesWithin(base, target) {
|
|
37024
|
-
const resolved =
|
|
37025
|
-
const baseResolved =
|
|
37026
|
-
const rel =
|
|
37920
|
+
const resolved = path44.resolve(base, target);
|
|
37921
|
+
const baseResolved = path44.resolve(base);
|
|
37922
|
+
const rel = path44.relative(baseResolved, resolved);
|
|
37027
37923
|
if (rel === "")
|
|
37028
37924
|
return true;
|
|
37029
|
-
return !rel.startsWith("..") && !
|
|
37925
|
+
return !rel.startsWith("..") && !path44.isAbsolute(rel);
|
|
37030
37926
|
}
|
|
37031
37927
|
var TYPE_CHAR_TO_TYPE = {
|
|
37032
37928
|
"-": "file",
|
|
@@ -37076,7 +37972,7 @@ function parseTarListLine(line) {
|
|
|
37076
37972
|
function validateHardlinksBinary(tarPath, targetDir) {
|
|
37077
37973
|
let raw;
|
|
37078
37974
|
try {
|
|
37079
|
-
raw = gunzipSync(
|
|
37975
|
+
raw = gunzipSync(fs44.readFileSync(tarPath));
|
|
37080
37976
|
} catch {
|
|
37081
37977
|
return null;
|
|
37082
37978
|
}
|
|
@@ -37091,7 +37987,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
|
|
|
37091
37987
|
const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
|
|
37092
37988
|
const linkNull = block.indexOf(0, 157);
|
|
37093
37989
|
const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
|
|
37094
|
-
if (linkname && (
|
|
37990
|
+
if (linkname && (path44.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
|
|
37095
37991
|
return {
|
|
37096
37992
|
valid: false,
|
|
37097
37993
|
reason: "hardlink-escape",
|
|
@@ -37129,7 +38025,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
37129
38025
|
const entry = parseTarListLine(line);
|
|
37130
38026
|
if (!entry)
|
|
37131
38027
|
continue;
|
|
37132
|
-
if (
|
|
38028
|
+
if (path44.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
|
|
37133
38029
|
return {
|
|
37134
38030
|
valid: false,
|
|
37135
38031
|
reason: "path-traversal",
|
|
@@ -37137,8 +38033,8 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
37137
38033
|
};
|
|
37138
38034
|
}
|
|
37139
38035
|
if (entry.type === "symlink" && entry.linkname !== void 0) {
|
|
37140
|
-
const symlinkParent =
|
|
37141
|
-
if (
|
|
38036
|
+
const symlinkParent = path44.join(targetDir, path44.dirname(entry.name));
|
|
38037
|
+
if (path44.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path44.join(path44.dirname(entry.name), entry.linkname))) {
|
|
37142
38038
|
return {
|
|
37143
38039
|
valid: false,
|
|
37144
38040
|
reason: "symlink-escape",
|
|
@@ -37148,7 +38044,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
37148
38044
|
}
|
|
37149
38045
|
}
|
|
37150
38046
|
if (entry.type === "hardlink" && entry.linkname !== void 0) {
|
|
37151
|
-
if (
|
|
38047
|
+
if (path44.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
|
|
37152
38048
|
return {
|
|
37153
38049
|
valid: false,
|
|
37154
38050
|
reason: "hardlink-escape",
|
|
@@ -37181,8 +38077,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37181
38077
|
}
|
|
37182
38078
|
const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
|
|
37183
38079
|
const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
|
|
37184
|
-
const tarPath =
|
|
37185
|
-
if (!
|
|
38080
|
+
const tarPath = path44.join(archDir, tarFilename);
|
|
38081
|
+
if (!fs44.existsSync(tarPath)) {
|
|
37186
38082
|
outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
|
|
37187
38083
|
continue;
|
|
37188
38084
|
}
|
|
@@ -37197,9 +38093,9 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37197
38093
|
});
|
|
37198
38094
|
continue;
|
|
37199
38095
|
}
|
|
37200
|
-
const targetDir =
|
|
38096
|
+
const targetDir = path44.join(repo.worktreeDir, targetSubpath);
|
|
37201
38097
|
try {
|
|
37202
|
-
|
|
38098
|
+
fs44.rmSync(targetDir, { recursive: true, force: true });
|
|
37203
38099
|
} catch {
|
|
37204
38100
|
}
|
|
37205
38101
|
const result = unpackTarballAtomic(tarPath, targetDir);
|
|
@@ -37212,8 +38108,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37212
38108
|
fingerprint
|
|
37213
38109
|
});
|
|
37214
38110
|
try {
|
|
37215
|
-
|
|
37216
|
-
|
|
38111
|
+
fs44.rmSync(tarPath, { force: true });
|
|
38112
|
+
fs44.rmSync(manifestPath(tarPath), { force: true });
|
|
37217
38113
|
} catch {
|
|
37218
38114
|
}
|
|
37219
38115
|
continue;
|
|
@@ -37229,10 +38125,10 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37229
38125
|
}
|
|
37230
38126
|
function readManifest(tarPath) {
|
|
37231
38127
|
const mPath = manifestPath(tarPath);
|
|
37232
|
-
if (!
|
|
38128
|
+
if (!fs44.existsSync(mPath))
|
|
37233
38129
|
return null;
|
|
37234
38130
|
try {
|
|
37235
|
-
return JSON.parse(
|
|
38131
|
+
return JSON.parse(fs44.readFileSync(mPath, "utf-8"));
|
|
37236
38132
|
} catch {
|
|
37237
38133
|
return null;
|
|
37238
38134
|
}
|
|
@@ -37247,17 +38143,17 @@ function isPidAlive(pid) {
|
|
|
37247
38143
|
}
|
|
37248
38144
|
}
|
|
37249
38145
|
function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
37250
|
-
|
|
37251
|
-
const lockPath =
|
|
38146
|
+
fs44.mkdirSync(dir, { recursive: true });
|
|
38147
|
+
const lockPath = path44.join(dir, EVICT_LOCK_FILENAME);
|
|
37252
38148
|
let fd;
|
|
37253
38149
|
try {
|
|
37254
|
-
fd =
|
|
38150
|
+
fd = fs44.openSync(lockPath, fs44.constants.O_WRONLY | fs44.constants.O_CREAT | fs44.constants.O_EXCL, 384);
|
|
37255
38151
|
} catch (err) {
|
|
37256
38152
|
if (err.code !== "EEXIST")
|
|
37257
38153
|
return 0;
|
|
37258
38154
|
let holderPid = null;
|
|
37259
38155
|
try {
|
|
37260
|
-
holderPid = parseInt(
|
|
38156
|
+
holderPid = parseInt(fs44.readFileSync(lockPath, "utf-8").trim(), 10);
|
|
37261
38157
|
} catch {
|
|
37262
38158
|
holderPid = null;
|
|
37263
38159
|
}
|
|
@@ -37265,23 +38161,23 @@ function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
|
37265
38161
|
return 0;
|
|
37266
38162
|
}
|
|
37267
38163
|
try {
|
|
37268
|
-
|
|
37269
|
-
fd =
|
|
38164
|
+
fs44.unlinkSync(lockPath);
|
|
38165
|
+
fd = fs44.openSync(lockPath, fs44.constants.O_WRONLY | fs44.constants.O_CREAT | fs44.constants.O_EXCL, 384);
|
|
37270
38166
|
} catch {
|
|
37271
38167
|
return 0;
|
|
37272
38168
|
}
|
|
37273
38169
|
}
|
|
37274
38170
|
try {
|
|
37275
|
-
|
|
38171
|
+
fs44.writeSync(fd, `${process.pid}
|
|
37276
38172
|
`);
|
|
37277
38173
|
} finally {
|
|
37278
|
-
|
|
38174
|
+
fs44.closeSync(fd);
|
|
37279
38175
|
}
|
|
37280
38176
|
try {
|
|
37281
38177
|
return evictOldSnapshots(maxBytes, dir);
|
|
37282
38178
|
} finally {
|
|
37283
38179
|
try {
|
|
37284
|
-
|
|
38180
|
+
fs44.unlinkSync(lockPath);
|
|
37285
38181
|
} catch {
|
|
37286
38182
|
}
|
|
37287
38183
|
}
|
|
@@ -37314,16 +38210,16 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
|
|
|
37314
38210
|
}
|
|
37315
38211
|
}
|
|
37316
38212
|
function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
37317
|
-
if (!
|
|
38213
|
+
if (!fs44.existsSync(dir))
|
|
37318
38214
|
return 0;
|
|
37319
38215
|
const allTars = [];
|
|
37320
38216
|
const walk = (d) => {
|
|
37321
|
-
for (const entry of
|
|
37322
|
-
const full =
|
|
38217
|
+
for (const entry of fs44.readdirSync(d, { withFileTypes: true })) {
|
|
38218
|
+
const full = path44.join(d, entry.name);
|
|
37323
38219
|
if (entry.isDirectory()) {
|
|
37324
38220
|
walk(full);
|
|
37325
38221
|
} else if (entry.name.endsWith(".tar.gz")) {
|
|
37326
|
-
const stat =
|
|
38222
|
+
const stat = fs44.statSync(full);
|
|
37327
38223
|
allTars.push({ path: full, size: stat.size, mtime: stat.mtimeMs });
|
|
37328
38224
|
}
|
|
37329
38225
|
}
|
|
@@ -37338,8 +38234,8 @@ function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
|
37338
38234
|
for (const tar of allTars) {
|
|
37339
38235
|
if (remaining <= maxBytes)
|
|
37340
38236
|
break;
|
|
37341
|
-
|
|
37342
|
-
|
|
38237
|
+
fs44.rmSync(tar.path, { force: true });
|
|
38238
|
+
fs44.rmSync(manifestPath(tar.path), { force: true });
|
|
37343
38239
|
freed += tar.size;
|
|
37344
38240
|
remaining -= tar.size;
|
|
37345
38241
|
}
|
|
@@ -37456,14 +38352,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
|
|
|
37456
38352
|
|
|
37457
38353
|
// ../core/dist/world/olam-yaml.js
|
|
37458
38354
|
init_repo_manifest();
|
|
37459
|
-
import * as
|
|
38355
|
+
import * as path45 from "node:path";
|
|
37460
38356
|
import YAML2 from "yaml";
|
|
37461
38357
|
function enrichReposWithManifests(repos, workspacePath) {
|
|
37462
38358
|
return repos.map((repo) => {
|
|
37463
38359
|
if (repo.manifest !== void 0 && repo.manifest !== null) {
|
|
37464
38360
|
return repo;
|
|
37465
38361
|
}
|
|
37466
|
-
const repoDir =
|
|
38362
|
+
const repoDir = path45.join(workspacePath, repo.name);
|
|
37467
38363
|
let manifest = null;
|
|
37468
38364
|
try {
|
|
37469
38365
|
manifest = loadRepoManifest(repoDir);
|
|
@@ -37478,16 +38374,16 @@ function enrichReposWithManifests(repos, workspacePath) {
|
|
|
37478
38374
|
}
|
|
37479
38375
|
|
|
37480
38376
|
// ../core/dist/policies/loader.js
|
|
37481
|
-
import * as
|
|
37482
|
-
import * as
|
|
37483
|
-
import { parse as
|
|
38377
|
+
import * as fs45 from "node:fs";
|
|
38378
|
+
import * as path46 from "node:path";
|
|
38379
|
+
import { parse as parseYaml5 } from "yaml";
|
|
37484
38380
|
function parseFrontmatter2(content) {
|
|
37485
38381
|
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
|
|
37486
38382
|
if (!match)
|
|
37487
38383
|
return null;
|
|
37488
38384
|
const [, yamlText = "", body = ""] = match;
|
|
37489
38385
|
try {
|
|
37490
|
-
const frontmatter =
|
|
38386
|
+
const frontmatter = parseYaml5(yamlText);
|
|
37491
38387
|
return { frontmatter, body };
|
|
37492
38388
|
} catch {
|
|
37493
38389
|
return null;
|
|
@@ -37499,20 +38395,20 @@ function toStringArray(v) {
|
|
|
37499
38395
|
return v.filter((x) => typeof x === "string");
|
|
37500
38396
|
}
|
|
37501
38397
|
function loadPolicies(workspaceRoot) {
|
|
37502
|
-
const policiesDir =
|
|
37503
|
-
if (!
|
|
38398
|
+
const policiesDir = path46.join(workspaceRoot, ".olam", "policies");
|
|
38399
|
+
if (!fs45.existsSync(policiesDir))
|
|
37504
38400
|
return [];
|
|
37505
38401
|
let files;
|
|
37506
38402
|
try {
|
|
37507
|
-
files =
|
|
38403
|
+
files = fs45.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
|
|
37508
38404
|
} catch {
|
|
37509
38405
|
return [];
|
|
37510
38406
|
}
|
|
37511
38407
|
const policies = [];
|
|
37512
38408
|
for (const file of files) {
|
|
37513
|
-
const filePath =
|
|
38409
|
+
const filePath = path46.join(policiesDir, file);
|
|
37514
38410
|
try {
|
|
37515
|
-
const content =
|
|
38411
|
+
const content = fs45.readFileSync(filePath, "utf8");
|
|
37516
38412
|
const parsed = parseFrontmatter2(content);
|
|
37517
38413
|
if (!parsed) {
|
|
37518
38414
|
console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
|
|
@@ -37659,12 +38555,12 @@ init_store();
|
|
|
37659
38555
|
init_bridge();
|
|
37660
38556
|
|
|
37661
38557
|
// ../core/dist/global-config/runbook-resolver.js
|
|
37662
|
-
import * as
|
|
37663
|
-
import * as
|
|
37664
|
-
import * as
|
|
38558
|
+
import * as fs46 from "node:fs";
|
|
38559
|
+
import * as os28 from "node:os";
|
|
38560
|
+
import * as path47 from "node:path";
|
|
37665
38561
|
function expandTilde(p) {
|
|
37666
38562
|
if (p === "~" || p.startsWith("~/")) {
|
|
37667
|
-
return
|
|
38563
|
+
return path47.join(os28.homedir(), p.slice(1));
|
|
37668
38564
|
}
|
|
37669
38565
|
return p;
|
|
37670
38566
|
}
|
|
@@ -37676,7 +38572,7 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
37676
38572
|
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
38573
|
}
|
|
37678
38574
|
const resolvedPath = expandTilde(entry.path);
|
|
37679
|
-
if (!
|
|
38575
|
+
if (!fs46.existsSync(resolvedPath)) {
|
|
37680
38576
|
throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
|
|
37681
38577
|
}
|
|
37682
38578
|
}
|
|
@@ -37692,19 +38588,19 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
37692
38588
|
init_port_validator();
|
|
37693
38589
|
|
|
37694
38590
|
// ../core/dist/world/bootstrap-hooks.js
|
|
37695
|
-
import * as
|
|
37696
|
-
import * as
|
|
38591
|
+
import * as fs47 from "node:fs";
|
|
38592
|
+
import * as path48 from "node:path";
|
|
37697
38593
|
function runFixtureCopySeeds(seeds, workspacePath) {
|
|
37698
38594
|
if (!seeds)
|
|
37699
38595
|
return;
|
|
37700
38596
|
for (const seed of seeds) {
|
|
37701
38597
|
if (seed.type !== "fixture-copy")
|
|
37702
38598
|
continue;
|
|
37703
|
-
const srcAbs =
|
|
37704
|
-
const destAbs =
|
|
37705
|
-
const destDir =
|
|
37706
|
-
|
|
37707
|
-
|
|
38599
|
+
const srcAbs = path48.resolve(workspacePath, seed.repo, seed.src);
|
|
38600
|
+
const destAbs = path48.resolve(workspacePath, seed.repo, seed.dest);
|
|
38601
|
+
const destDir = path48.dirname(destAbs);
|
|
38602
|
+
fs47.mkdirSync(destDir, { recursive: true });
|
|
38603
|
+
fs47.cpSync(srcAbs, destAbs, { recursive: true, force: true });
|
|
37708
38604
|
}
|
|
37709
38605
|
}
|
|
37710
38606
|
async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
|
|
@@ -38340,7 +39236,7 @@ ${detail}`);
|
|
|
38340
39236
|
runbookSeeds = resolved.seeds;
|
|
38341
39237
|
}
|
|
38342
39238
|
const worldId = generateWorldId();
|
|
38343
|
-
const workspacePath =
|
|
39239
|
+
const workspacePath = path49.join(os29.homedir(), ".olam", "worlds", worldId);
|
|
38344
39240
|
const portOffset = this.registry.getNextPortOffset();
|
|
38345
39241
|
const branch = opts.branchName ?? `olam/${worldId}`;
|
|
38346
39242
|
const repos = this.resolveReposWithWorkspace(opts);
|
|
@@ -38421,38 +39317,38 @@ ${detail}`);
|
|
|
38421
39317
|
for (const repo of repos) {
|
|
38422
39318
|
if (!repo.path)
|
|
38423
39319
|
continue;
|
|
38424
|
-
const sourceRoot = repo.path.replace(/^~/,
|
|
38425
|
-
const worktreeRoot =
|
|
38426
|
-
if (!
|
|
39320
|
+
const sourceRoot = repo.path.replace(/^~/, os29.homedir());
|
|
39321
|
+
const worktreeRoot = path49.join(workspacePath, repo.name);
|
|
39322
|
+
if (!fs48.existsSync(sourceRoot) || !fs48.existsSync(worktreeRoot))
|
|
38427
39323
|
continue;
|
|
38428
39324
|
let copied = 0;
|
|
38429
39325
|
for (const pattern of RUNTIME_FILE_PATTERNS) {
|
|
38430
39326
|
const matches2 = [];
|
|
38431
39327
|
if (pattern.includes("*")) {
|
|
38432
|
-
const [dir, glob] = [
|
|
38433
|
-
const sourceDir =
|
|
38434
|
-
if (
|
|
39328
|
+
const [dir, glob] = [path49.dirname(pattern), path49.basename(pattern)];
|
|
39329
|
+
const sourceDir = path49.join(sourceRoot, dir);
|
|
39330
|
+
if (fs48.existsSync(sourceDir)) {
|
|
38435
39331
|
const ext = glob.replace(/^\*+/, "");
|
|
38436
39332
|
try {
|
|
38437
|
-
for (const entry of
|
|
39333
|
+
for (const entry of fs48.readdirSync(sourceDir)) {
|
|
38438
39334
|
if (ext === "" || entry.endsWith(ext))
|
|
38439
|
-
matches2.push(
|
|
39335
|
+
matches2.push(path49.join(dir, entry));
|
|
38440
39336
|
}
|
|
38441
39337
|
} catch {
|
|
38442
39338
|
}
|
|
38443
39339
|
}
|
|
38444
|
-
} else if (
|
|
39340
|
+
} else if (fs48.existsSync(path49.join(sourceRoot, pattern))) {
|
|
38445
39341
|
matches2.push(pattern);
|
|
38446
39342
|
}
|
|
38447
39343
|
for (const rel of matches2) {
|
|
38448
|
-
const src =
|
|
38449
|
-
const dst =
|
|
39344
|
+
const src = path49.join(sourceRoot, rel);
|
|
39345
|
+
const dst = path49.join(worktreeRoot, rel);
|
|
38450
39346
|
try {
|
|
38451
|
-
const st =
|
|
39347
|
+
const st = fs48.statSync(src);
|
|
38452
39348
|
if (!st.isFile())
|
|
38453
39349
|
continue;
|
|
38454
|
-
|
|
38455
|
-
|
|
39350
|
+
fs48.mkdirSync(path49.dirname(dst), { recursive: true });
|
|
39351
|
+
fs48.copyFileSync(src, dst);
|
|
38456
39352
|
copied++;
|
|
38457
39353
|
} catch {
|
|
38458
39354
|
}
|
|
@@ -38538,7 +39434,7 @@ ${detail}`);
|
|
|
38538
39434
|
}
|
|
38539
39435
|
const overlayAttachments = [];
|
|
38540
39436
|
for (const repo of repos) {
|
|
38541
|
-
const worldClonePath =
|
|
39437
|
+
const worldClonePath = path49.join(workspacePath, repo.name);
|
|
38542
39438
|
try {
|
|
38543
39439
|
const result = createWorldOverlay({
|
|
38544
39440
|
workspace: repo.name,
|
|
@@ -38593,7 +39489,7 @@ ${detail}`);
|
|
|
38593
39489
|
try {
|
|
38594
39490
|
const hostExec = makeHostExecFn();
|
|
38595
39491
|
for (const repo of repos) {
|
|
38596
|
-
const repoDir =
|
|
39492
|
+
const repoDir = path49.join(workspacePath, repo.name);
|
|
38597
39493
|
if (repo.stack && Object.keys(repo.stack).length > 0) {
|
|
38598
39494
|
preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
|
|
38599
39495
|
} else {
|
|
@@ -38637,10 +39533,10 @@ ${detail}`);
|
|
|
38637
39533
|
const worldEnv = {};
|
|
38638
39534
|
if (opts.task)
|
|
38639
39535
|
worldEnv.OLAM_TASK = opts.task;
|
|
38640
|
-
const r2CredsPath =
|
|
38641
|
-
if (
|
|
39536
|
+
const r2CredsPath = path49.join(os29.homedir(), ".olam", "r2-credentials.json");
|
|
39537
|
+
if (fs48.existsSync(r2CredsPath)) {
|
|
38642
39538
|
try {
|
|
38643
|
-
const r2Raw =
|
|
39539
|
+
const r2Raw = fs48.readFileSync(r2CredsPath, "utf-8").trim();
|
|
38644
39540
|
if (r2Raw.length > 0) {
|
|
38645
39541
|
const r2 = JSON.parse(r2Raw);
|
|
38646
39542
|
if (typeof r2.account_id === "string")
|
|
@@ -38657,10 +39553,10 @@ ${detail}`);
|
|
|
38657
39553
|
} catch {
|
|
38658
39554
|
}
|
|
38659
39555
|
}
|
|
38660
|
-
const keysYamlPath =
|
|
38661
|
-
if (
|
|
39556
|
+
const keysYamlPath = path49.join(os29.homedir(), ".olam", "keys.yaml");
|
|
39557
|
+
if (fs48.existsSync(keysYamlPath)) {
|
|
38662
39558
|
try {
|
|
38663
|
-
const keysRaw =
|
|
39559
|
+
const keysRaw = fs48.readFileSync(keysYamlPath, "utf-8").trim();
|
|
38664
39560
|
if (keysRaw.length > 0) {
|
|
38665
39561
|
const parsed = YAML3.parse(keysRaw);
|
|
38666
39562
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
@@ -38719,10 +39615,10 @@ ${detail}`);
|
|
|
38719
39615
|
worldEnv[k] = v;
|
|
38720
39616
|
}
|
|
38721
39617
|
for (const { repoName, relativePath, content } of fileWrites) {
|
|
38722
|
-
const absPath =
|
|
39618
|
+
const absPath = path49.join(workspacePath, repoName, relativePath);
|
|
38723
39619
|
try {
|
|
38724
|
-
|
|
38725
|
-
|
|
39620
|
+
fs48.mkdirSync(path49.dirname(absPath), { recursive: true });
|
|
39621
|
+
fs48.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
|
|
38726
39622
|
mode: 384
|
|
38727
39623
|
});
|
|
38728
39624
|
console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
|
|
@@ -38899,7 +39795,7 @@ ${detail}`);
|
|
|
38899
39795
|
imageDigest: void 0,
|
|
38900
39796
|
repos: enrichedRepos.map((r) => ({
|
|
38901
39797
|
name: r.name,
|
|
38902
|
-
worktreeDir:
|
|
39798
|
+
worktreeDir: path49.join(workspacePath, r.name)
|
|
38903
39799
|
}))
|
|
38904
39800
|
});
|
|
38905
39801
|
for (const out of restoreResult.outcomes) {
|
|
@@ -39005,7 +39901,7 @@ ${detail}`);
|
|
|
39005
39901
|
}
|
|
39006
39902
|
if (opts.task) {
|
|
39007
39903
|
const allPolicies = repos.flatMap((repo) => {
|
|
39008
|
-
const repoWorktree =
|
|
39904
|
+
const repoWorktree = path49.join(workspacePath, repo.name);
|
|
39009
39905
|
try {
|
|
39010
39906
|
return loadPolicies(repoWorktree);
|
|
39011
39907
|
} catch (err) {
|
|
@@ -39018,8 +39914,8 @@ ${detail}`);
|
|
|
39018
39914
|
try {
|
|
39019
39915
|
execSync5(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
39020
39916
|
for (const repo of repos) {
|
|
39021
|
-
const policiesDir =
|
|
39022
|
-
if (
|
|
39917
|
+
const policiesDir = path49.join(workspacePath, repo.name, ".olam", "policies");
|
|
39918
|
+
if (fs48.existsSync(policiesDir)) {
|
|
39023
39919
|
execSync5(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
39024
39920
|
}
|
|
39025
39921
|
}
|
|
@@ -39127,8 +40023,8 @@ ${detail}`);
|
|
|
39127
40023
|
} catch {
|
|
39128
40024
|
}
|
|
39129
40025
|
try {
|
|
39130
|
-
|
|
39131
|
-
if (
|
|
40026
|
+
fs48.rmSync(world.workspacePath, { recursive: true, force: true });
|
|
40027
|
+
if (fs48.existsSync(world.workspacePath)) {
|
|
39132
40028
|
console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
|
|
39133
40029
|
}
|
|
39134
40030
|
} catch (err) {
|
|
@@ -39237,14 +40133,14 @@ ${detail}`);
|
|
|
39237
40133
|
}).filter((r) => r !== void 0);
|
|
39238
40134
|
}
|
|
39239
40135
|
transportPlanFile(planFilePath, workspacePath, repoNames) {
|
|
39240
|
-
const planContent =
|
|
39241
|
-
const planFileName =
|
|
40136
|
+
const planContent = fs48.readFileSync(planFilePath, "utf-8");
|
|
40137
|
+
const planFileName = path49.basename(planFilePath);
|
|
39242
40138
|
const targetRepo = repoNames[0];
|
|
39243
40139
|
if (!targetRepo)
|
|
39244
40140
|
return;
|
|
39245
|
-
const plansDir =
|
|
39246
|
-
|
|
39247
|
-
|
|
40141
|
+
const plansDir = path49.join(workspacePath, targetRepo, "docs", "plans");
|
|
40142
|
+
fs48.mkdirSync(plansDir, { recursive: true });
|
|
40143
|
+
fs48.writeFileSync(path49.join(plansDir, planFileName), planContent);
|
|
39248
40144
|
}
|
|
39249
40145
|
resolveServices(repos) {
|
|
39250
40146
|
const services = [];
|
|
@@ -39678,8 +40574,8 @@ import * as http2 from "node:http";
|
|
|
39678
40574
|
|
|
39679
40575
|
// ../core/dist/dashboard/server.js
|
|
39680
40576
|
import * as http from "node:http";
|
|
39681
|
-
import * as
|
|
39682
|
-
import * as
|
|
40577
|
+
import * as fs49 from "node:fs";
|
|
40578
|
+
import * as path50 from "node:path";
|
|
39683
40579
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
39684
40580
|
|
|
39685
40581
|
// ../core/dist/dashboard/serialize.js
|
|
@@ -40014,7 +40910,7 @@ function notFound(res) {
|
|
|
40014
40910
|
}
|
|
40015
40911
|
function openThoughtStore(workspacePath) {
|
|
40016
40912
|
const dbPath = getWorldDbPath(workspacePath);
|
|
40017
|
-
if (!
|
|
40913
|
+
if (!fs49.existsSync(dbPath))
|
|
40018
40914
|
return null;
|
|
40019
40915
|
return new ThoughtLocalStore(dbPath);
|
|
40020
40916
|
}
|
|
@@ -40185,13 +41081,13 @@ function findSessionInWorld(registry2, sessionId) {
|
|
|
40185
41081
|
}
|
|
40186
41082
|
function createDashboardServer(opts) {
|
|
40187
41083
|
const { port: port2, registry: registry2 } = opts;
|
|
40188
|
-
const thisDir =
|
|
40189
|
-
const defaultPublicDir =
|
|
41084
|
+
const thisDir = path50.dirname(fileURLToPath3(import.meta.url));
|
|
41085
|
+
const defaultPublicDir = path50.resolve(thisDir, "../../../control-plane/public");
|
|
40190
41086
|
const publicDir = opts.publicDir ?? defaultPublicDir;
|
|
40191
|
-
let hasPublicDir =
|
|
41087
|
+
let hasPublicDir = fs49.existsSync(publicDir);
|
|
40192
41088
|
const server = http.createServer((req, res) => {
|
|
40193
41089
|
if (!hasPublicDir) {
|
|
40194
|
-
hasPublicDir =
|
|
41090
|
+
hasPublicDir = fs49.existsSync(publicDir);
|
|
40195
41091
|
}
|
|
40196
41092
|
const host = req.headers.host ?? `localhost:${port2}`;
|
|
40197
41093
|
const url2 = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -40465,22 +41361,22 @@ function createDashboardServer(opts) {
|
|
|
40465
41361
|
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
41362
|
return;
|
|
40467
41363
|
}
|
|
40468
|
-
let filePath =
|
|
41364
|
+
let filePath = path50.join(publicDir, pathname === "/" ? "index.html" : pathname);
|
|
40469
41365
|
if (!filePath.startsWith(publicDir)) {
|
|
40470
41366
|
notFound(res);
|
|
40471
41367
|
return;
|
|
40472
41368
|
}
|
|
40473
|
-
if (
|
|
40474
|
-
const ext =
|
|
41369
|
+
if (fs49.existsSync(filePath) && fs49.statSync(filePath).isFile()) {
|
|
41370
|
+
const ext = path50.extname(filePath);
|
|
40475
41371
|
const contentType = MIME[ext] ?? "application/octet-stream";
|
|
40476
41372
|
res.writeHead(200, { "Content-Type": contentType });
|
|
40477
|
-
|
|
41373
|
+
fs49.createReadStream(filePath).pipe(res);
|
|
40478
41374
|
return;
|
|
40479
41375
|
}
|
|
40480
|
-
filePath =
|
|
40481
|
-
if (
|
|
41376
|
+
filePath = path50.join(publicDir, "index.html");
|
|
41377
|
+
if (fs49.existsSync(filePath)) {
|
|
40482
41378
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
40483
|
-
|
|
41379
|
+
fs49.createReadStream(filePath).pipe(res);
|
|
40484
41380
|
return;
|
|
40485
41381
|
}
|
|
40486
41382
|
notFound(res);
|
|
@@ -40490,17 +41386,17 @@ function createDashboardServer(opts) {
|
|
|
40490
41386
|
}
|
|
40491
41387
|
|
|
40492
41388
|
// ../core/dist/dashboard/state.js
|
|
40493
|
-
import * as
|
|
40494
|
-
import * as
|
|
40495
|
-
import * as
|
|
40496
|
-
var STATE_PATH =
|
|
41389
|
+
import * as fs50 from "node:fs";
|
|
41390
|
+
import * as os30 from "node:os";
|
|
41391
|
+
import * as path51 from "node:path";
|
|
41392
|
+
var STATE_PATH = path51.join(os30.homedir(), ".olam", "dashboard.json");
|
|
40497
41393
|
function saveDashboardState(state) {
|
|
40498
|
-
|
|
40499
|
-
|
|
41394
|
+
fs50.mkdirSync(path51.dirname(STATE_PATH), { recursive: true });
|
|
41395
|
+
fs50.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
|
|
40500
41396
|
}
|
|
40501
41397
|
function loadDashboardState() {
|
|
40502
41398
|
try {
|
|
40503
|
-
const raw =
|
|
41399
|
+
const raw = fs50.readFileSync(STATE_PATH, "utf-8");
|
|
40504
41400
|
return JSON.parse(raw);
|
|
40505
41401
|
} catch {
|
|
40506
41402
|
return null;
|
|
@@ -40508,7 +41404,7 @@ function loadDashboardState() {
|
|
|
40508
41404
|
}
|
|
40509
41405
|
function clearDashboardState() {
|
|
40510
41406
|
try {
|
|
40511
|
-
|
|
41407
|
+
fs50.unlinkSync(STATE_PATH);
|
|
40512
41408
|
} catch {
|
|
40513
41409
|
}
|
|
40514
41410
|
}
|
|
@@ -40788,8 +41684,8 @@ var PleriClient = class {
|
|
|
40788
41684
|
};
|
|
40789
41685
|
|
|
40790
41686
|
// ../mcp-server/src/env-loader.ts
|
|
40791
|
-
import { readFileSync as
|
|
40792
|
-
import { join as
|
|
41687
|
+
import { readFileSync as readFileSync39, existsSync as existsSync47, statSync as statSync14 } from "node:fs";
|
|
41688
|
+
import { join as join52, dirname as dirname29, resolve as resolve13 } from "node:path";
|
|
40793
41689
|
var PROJECT_MARKERS = [
|
|
40794
41690
|
".olam/config.yaml",
|
|
40795
41691
|
".olam/config.yml",
|
|
@@ -40801,26 +41697,26 @@ function findProjectRoot2(startDir) {
|
|
|
40801
41697
|
const root = resolve13("/");
|
|
40802
41698
|
while (true) {
|
|
40803
41699
|
for (const marker of PROJECT_MARKERS) {
|
|
40804
|
-
if (
|
|
41700
|
+
if (existsSync47(join52(dir, marker))) return dir;
|
|
40805
41701
|
}
|
|
40806
|
-
const pkg =
|
|
40807
|
-
if (
|
|
41702
|
+
const pkg = join52(dir, "package.json");
|
|
41703
|
+
if (existsSync47(pkg)) {
|
|
40808
41704
|
try {
|
|
40809
|
-
const json = JSON.parse(
|
|
41705
|
+
const json = JSON.parse(readFileSync39(pkg, "utf8"));
|
|
40810
41706
|
const isOlamWorkspace = typeof json.name === "string" && json.name.startsWith("@olam/");
|
|
40811
41707
|
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
41708
|
if (isOlamWorkspace || hasOlamDep) return dir;
|
|
40813
41709
|
} catch {
|
|
40814
41710
|
}
|
|
40815
41711
|
}
|
|
40816
|
-
const parent =
|
|
41712
|
+
const parent = dirname29(dir);
|
|
40817
41713
|
if (parent === dir || parent === root) return null;
|
|
40818
41714
|
dir = parent;
|
|
40819
41715
|
}
|
|
40820
41716
|
}
|
|
40821
|
-
function parseEnvFile(
|
|
41717
|
+
function parseEnvFile(path52) {
|
|
40822
41718
|
const out = {};
|
|
40823
|
-
const raw =
|
|
41719
|
+
const raw = readFileSync39(path52, "utf8");
|
|
40824
41720
|
for (const line of raw.split(/\r?\n/)) {
|
|
40825
41721
|
const trimmed = line.trim();
|
|
40826
41722
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -40843,8 +41739,8 @@ function loadProjectEnv(startDir = process.cwd()) {
|
|
|
40843
41739
|
const filesRead = [];
|
|
40844
41740
|
const merged = {};
|
|
40845
41741
|
for (const name of [".env", ".env.local"]) {
|
|
40846
|
-
const p =
|
|
40847
|
-
if (
|
|
41742
|
+
const p = join52(root, name);
|
|
41743
|
+
if (existsSync47(p) && statSync14(p).isFile()) {
|
|
40848
41744
|
Object.assign(merged, parseEnvFile(p));
|
|
40849
41745
|
filesRead.push(p);
|
|
40850
41746
|
}
|
|
@@ -40880,12 +41776,12 @@ async function main() {
|
|
|
40880
41776
|
maxDailyUsd: config2.cost.max_daily_usd,
|
|
40881
41777
|
warningThreshold: config2.cost.warning_threshold
|
|
40882
41778
|
});
|
|
40883
|
-
const
|
|
41779
|
+
const WORLD_ID_RE3 = /^[a-z0-9-]+$/;
|
|
40884
41780
|
const callerWorldIdRaw = (process.env.OLAM_CALLER_WORLD_ID ?? "").trim();
|
|
40885
41781
|
let callerWorldId;
|
|
40886
41782
|
if (callerWorldIdRaw.length === 0) {
|
|
40887
41783
|
callerWorldId = void 0;
|
|
40888
|
-
} else if (
|
|
41784
|
+
} else if (WORLD_ID_RE3.test(callerWorldIdRaw)) {
|
|
40889
41785
|
callerWorldId = callerWorldIdRaw;
|
|
40890
41786
|
} else {
|
|
40891
41787
|
logger.warn(
|