@pleri/olam-cli 0.1.70 → 0.1.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +2 -0
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/runbooks.d.ts +13 -0
- package/dist/commands/runbooks.d.ts.map +1 -0
- package/dist/commands/runbooks.js +189 -0
- package/dist/commands/runbooks.js.map +1 -0
- package/dist/commands/world-snapshot.d.ts +1 -0
- package/dist/commands/world-snapshot.d.ts.map +1 -1
- package/dist/commands/world-snapshot.js +126 -1
- package/dist/commands/world-snapshot.js.map +1 -1
- package/dist/commands/worldspec/compile.d.ts +20 -0
- package/dist/commands/worldspec/compile.d.ts.map +1 -0
- package/dist/commands/worldspec/compile.js +130 -0
- package/dist/commands/worldspec/compile.js.map +1 -0
- package/dist/commands/worldspec/index.d.ts +12 -0
- package/dist/commands/worldspec/index.d.ts.map +1 -0
- package/dist/commands/worldspec/index.js +23 -0
- package/dist/commands/worldspec/index.js.map +1 -0
- package/dist/commands/worldspec/init.d.ts +15 -0
- package/dist/commands/worldspec/init.d.ts.map +1 -0
- package/dist/commands/worldspec/init.js +166 -0
- package/dist/commands/worldspec/init.js.map +1 -0
- package/dist/commands/worldspec/schema.d.ts +11 -0
- package/dist/commands/worldspec/schema.d.ts.map +1 -0
- package/dist/commands/worldspec/schema.js +55 -0
- package/dist/commands/worldspec/schema.js.map +1 -0
- package/dist/commands/worldspec/validate.d.ts +15 -0
- package/dist/commands/worldspec/validate.d.ts.map +1 -0
- package/dist/commands/worldspec/validate.js +66 -0
- package/dist/commands/worldspec/validate.js.map +1 -0
- package/dist/exit-codes.d.ts +32 -0
- package/dist/exit-codes.d.ts.map +1 -1
- package/dist/exit-codes.js +32 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/image-digests.json +5 -5
- package/dist/index.js +4379 -897
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.js +1252 -286
- package/host-cp/src/global-config-source.mjs +71 -0
- package/host-cp/src/listening-server-poller.mjs +1 -1
- package/host-cp/src/plan-orchestrator.mjs +21 -2
- package/host-cp/src/port-bridge-manager.mjs +1 -1
- package/host-cp/src/server.mjs +46 -7
- package/package.json +4 -2
- package/dist/__tests__/audit-publish-deps-contract.test.d.ts +0 -26
- package/dist/__tests__/audit-publish-deps-contract.test.d.ts.map +0 -1
- package/dist/__tests__/audit-publish-deps-contract.test.js +0 -86
- package/dist/__tests__/audit-publish-deps-contract.test.js.map +0 -1
- package/dist/__tests__/auth-status.test.d.ts +0 -2
- package/dist/__tests__/auth-status.test.d.ts.map +0 -1
- package/dist/__tests__/auth-status.test.js +0 -291
- package/dist/__tests__/auth-status.test.js.map +0 -1
- package/dist/__tests__/auth-upgrade.test.d.ts +0 -9
- package/dist/__tests__/auth-upgrade.test.d.ts.map +0 -1
- package/dist/__tests__/auth-upgrade.test.js +0 -397
- package/dist/__tests__/auth-upgrade.test.js.map +0 -1
- package/dist/__tests__/bootstrap-tag-mcp-auth.test.d.ts +0 -22
- package/dist/__tests__/bootstrap-tag-mcp-auth.test.d.ts.map +0 -1
- package/dist/__tests__/bootstrap-tag-mcp-auth.test.js +0 -63
- package/dist/__tests__/bootstrap-tag-mcp-auth.test.js.map +0 -1
- package/dist/__tests__/cli-mcp-revoke.test.d.ts +0 -8
- package/dist/__tests__/cli-mcp-revoke.test.d.ts.map +0 -1
- package/dist/__tests__/cli-mcp-revoke.test.js +0 -124
- package/dist/__tests__/cli-mcp-revoke.test.js.map +0 -1
- package/dist/__tests__/config.test.d.ts +0 -2
- package/dist/__tests__/config.test.d.ts.map +0 -1
- package/dist/__tests__/config.test.js +0 -95
- package/dist/__tests__/config.test.js.map +0 -1
- package/dist/__tests__/create-app-urls.test.d.ts +0 -2
- package/dist/__tests__/create-app-urls.test.d.ts.map +0 -1
- package/dist/__tests__/create-app-urls.test.js +0 -102
- package/dist/__tests__/create-app-urls.test.js.map +0 -1
- package/dist/__tests__/docker-host.test.d.ts +0 -14
- package/dist/__tests__/docker-host.test.d.ts.map +0 -1
- package/dist/__tests__/docker-host.test.js +0 -109
- package/dist/__tests__/docker-host.test.js.map +0 -1
- package/dist/__tests__/enter.test.d.ts +0 -2
- package/dist/__tests__/enter.test.d.ts.map +0 -1
- package/dist/__tests__/enter.test.js +0 -90
- package/dist/__tests__/enter.test.js.map +0 -1
- package/dist/__tests__/help-output.test.d.ts +0 -2
- package/dist/__tests__/help-output.test.d.ts.map +0 -1
- package/dist/__tests__/help-output.test.js +0 -74
- package/dist/__tests__/help-output.test.js.map +0 -1
- package/dist/__tests__/host-cp-gh-token.test.d.ts +0 -9
- package/dist/__tests__/host-cp-gh-token.test.d.ts.map +0 -1
- package/dist/__tests__/host-cp-gh-token.test.js +0 -129
- package/dist/__tests__/host-cp-gh-token.test.js.map +0 -1
- package/dist/__tests__/host-cp.test.d.ts +0 -9
- package/dist/__tests__/host-cp.test.d.ts.map +0 -1
- package/dist/__tests__/host-cp.test.js +0 -335
- package/dist/__tests__/host-cp.test.js.map +0 -1
- package/dist/__tests__/image-presence.test.d.ts +0 -2
- package/dist/__tests__/image-presence.test.d.ts.map +0 -1
- package/dist/__tests__/image-presence.test.js +0 -44
- package/dist/__tests__/image-presence.test.js.map +0 -1
- package/dist/__tests__/install-root.test.d.ts +0 -2
- package/dist/__tests__/install-root.test.d.ts.map +0 -1
- package/dist/__tests__/install-root.test.js +0 -119
- package/dist/__tests__/install-root.test.js.map +0 -1
- package/dist/__tests__/keys.test.d.ts +0 -9
- package/dist/__tests__/keys.test.d.ts.map +0 -1
- package/dist/__tests__/keys.test.js +0 -145
- package/dist/__tests__/keys.test.js.map +0 -1
- package/dist/__tests__/logs.test.d.ts +0 -9
- package/dist/__tests__/logs.test.d.ts.map +0 -1
- package/dist/__tests__/logs.test.js +0 -124
- package/dist/__tests__/logs.test.js.map +0 -1
- package/dist/__tests__/mcp-import.test.d.ts +0 -11
- package/dist/__tests__/mcp-import.test.d.ts.map +0 -1
- package/dist/__tests__/mcp-import.test.js +0 -134
- package/dist/__tests__/mcp-import.test.js.map +0 -1
- package/dist/__tests__/protocol-version.test.d.ts +0 -2
- package/dist/__tests__/protocol-version.test.d.ts.map +0 -1
- package/dist/__tests__/protocol-version.test.js +0 -170
- package/dist/__tests__/protocol-version.test.js.map +0 -1
- package/dist/__tests__/ps.test.d.ts +0 -2
- package/dist/__tests__/ps.test.d.ts.map +0 -1
- package/dist/__tests__/ps.test.js +0 -172
- package/dist/__tests__/ps.test.js.map +0 -1
- package/dist/__tests__/registry-allowlist.test.d.ts +0 -2
- package/dist/__tests__/registry-allowlist.test.d.ts.map +0 -1
- package/dist/__tests__/registry-allowlist.test.js +0 -129
- package/dist/__tests__/registry-allowlist.test.js.map +0 -1
- package/dist/__tests__/services.test.d.ts +0 -8
- package/dist/__tests__/services.test.d.ts.map +0 -1
- package/dist/__tests__/services.test.js +0 -185
- package/dist/__tests__/services.test.js.map +0 -1
- package/dist/__tests__/status-app-urls.test.d.ts +0 -2
- package/dist/__tests__/status-app-urls.test.d.ts.map +0 -1
- package/dist/__tests__/status-app-urls.test.js +0 -125
- package/dist/__tests__/status-app-urls.test.js.map +0 -1
- package/dist/__tests__/upgrade-gh-token-contract.test.d.ts +0 -19
- package/dist/__tests__/upgrade-gh-token-contract.test.d.ts.map +0 -1
- package/dist/__tests__/upgrade-gh-token-contract.test.js +0 -63
- package/dist/__tests__/upgrade-gh-token-contract.test.js.map +0 -1
- package/dist/__tests__/upgrade.test.d.ts +0 -9
- package/dist/__tests__/upgrade.test.d.ts.map +0 -1
- package/dist/__tests__/upgrade.test.js +0 -586
- package/dist/__tests__/upgrade.test.js.map +0 -1
- package/dist/commands/__tests__/__fixtures__/upgrade-helpers.d.ts +0 -6
- package/dist/commands/__tests__/__fixtures__/upgrade-helpers.d.ts.map +0 -1
- package/dist/commands/__tests__/__fixtures__/upgrade-helpers.js +0 -26
- package/dist/commands/__tests__/__fixtures__/upgrade-helpers.js.map +0 -1
- package/dist/commands/__tests__/begin.test.d.ts +0 -7
- package/dist/commands/__tests__/begin.test.d.ts.map +0 -1
- package/dist/commands/__tests__/begin.test.js +0 -72
- package/dist/commands/__tests__/begin.test.js.map +0 -1
- package/dist/commands/__tests__/bootstrap.test.d.ts +0 -2
- package/dist/commands/__tests__/bootstrap.test.d.ts.map +0 -1
- package/dist/commands/__tests__/bootstrap.test.js +0 -370
- package/dist/commands/__tests__/bootstrap.test.js.map +0 -1
- package/dist/commands/__tests__/carry-uncommitted.test.d.ts +0 -14
- package/dist/commands/__tests__/carry-uncommitted.test.d.ts.map +0 -1
- package/dist/commands/__tests__/carry-uncommitted.test.js +0 -83
- package/dist/commands/__tests__/carry-uncommitted.test.js.map +0 -1
- package/dist/commands/__tests__/clean.test.d.ts +0 -9
- package/dist/commands/__tests__/clean.test.d.ts.map +0 -1
- package/dist/commands/__tests__/clean.test.js +0 -105
- package/dist/commands/__tests__/clean.test.js.map +0 -1
- package/dist/commands/__tests__/crystallize.test.d.ts +0 -2
- package/dist/commands/__tests__/crystallize.test.d.ts.map +0 -1
- package/dist/commands/__tests__/crystallize.test.js +0 -133
- package/dist/commands/__tests__/crystallize.test.js.map +0 -1
- package/dist/commands/__tests__/diagnose.test.d.ts +0 -9
- package/dist/commands/__tests__/diagnose.test.d.ts.map +0 -1
- package/dist/commands/__tests__/diagnose.test.js +0 -108
- package/dist/commands/__tests__/diagnose.test.js.map +0 -1
- package/dist/commands/__tests__/openHostCpUrl.test.d.ts +0 -2
- package/dist/commands/__tests__/openHostCpUrl.test.d.ts.map +0 -1
- package/dist/commands/__tests__/openHostCpUrl.test.js +0 -63
- package/dist/commands/__tests__/openHostCpUrl.test.js.map +0 -1
- package/dist/commands/__tests__/refresh.test.d.ts +0 -13
- package/dist/commands/__tests__/refresh.test.d.ts.map +0 -1
- package/dist/commands/__tests__/refresh.test.js +0 -170
- package/dist/commands/__tests__/refresh.test.js.map +0 -1
- package/dist/commands/__tests__/status.test.d.ts +0 -8
- package/dist/commands/__tests__/status.test.d.ts.map +0 -1
- package/dist/commands/__tests__/status.test.js +0 -62
- package/dist/commands/__tests__/status.test.js.map +0 -1
- package/dist/commands/__tests__/stop.test.d.ts +0 -5
- package/dist/commands/__tests__/stop.test.d.ts.map +0 -1
- package/dist/commands/__tests__/stop.test.js +0 -30
- package/dist/commands/__tests__/stop.test.js.map +0 -1
- package/dist/commands/__tests__/update.test.d.ts +0 -7
- package/dist/commands/__tests__/update.test.d.ts.map +0 -1
- package/dist/commands/__tests__/update.test.js +0 -224
- package/dist/commands/__tests__/update.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.all-three.test.d.ts +0 -19
- package/dist/commands/__tests__/upgrade.all-three.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.all-three.test.js +0 -80
- package/dist/commands/__tests__/upgrade.all-three.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.compose-path.test.d.ts +0 -20
- package/dist/commands/__tests__/upgrade.compose-path.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.compose-path.test.js +0 -140
- package/dist/commands/__tests__/upgrade.compose-path.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.history.test.d.ts +0 -15
- package/dist/commands/__tests__/upgrade.history.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.history.test.js +0 -199
- package/dist/commands/__tests__/upgrade.history.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.lock.test.d.ts +0 -15
- package/dist/commands/__tests__/upgrade.lock.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.lock.test.js +0 -253
- package/dist/commands/__tests__/upgrade.lock.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.olam-tag.test.d.ts +0 -21
- package/dist/commands/__tests__/upgrade.olam-tag.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.olam-tag.test.js +0 -114
- package/dist/commands/__tests__/upgrade.olam-tag.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.poll.test.d.ts +0 -14
- package/dist/commands/__tests__/upgrade.poll.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.poll.test.js +0 -136
- package/dist/commands/__tests__/upgrade.poll.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.recreate.test.d.ts +0 -17
- package/dist/commands/__tests__/upgrade.recreate.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.recreate.test.js +0 -83
- package/dist/commands/__tests__/upgrade.recreate.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.rollback.test.d.ts +0 -12
- package/dist/commands/__tests__/upgrade.rollback.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.rollback.test.js +0 -255
- package/dist/commands/__tests__/upgrade.rollback.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.sha-capture.test.d.ts +0 -12
- package/dist/commands/__tests__/upgrade.sha-capture.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.sha-capture.test.js +0 -63
- package/dist/commands/__tests__/upgrade.sha-capture.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.smoke.test.d.ts +0 -19
- package/dist/commands/__tests__/upgrade.smoke.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.smoke.test.js +0 -87
- package/dist/commands/__tests__/upgrade.smoke.test.js.map +0 -1
- package/dist/commands/__tests__/upgrade.swap.test.d.ts +0 -19
- package/dist/commands/__tests__/upgrade.swap.test.d.ts.map +0 -1
- package/dist/commands/__tests__/upgrade.swap.test.js +0 -312
- package/dist/commands/__tests__/upgrade.swap.test.js.map +0 -1
- package/dist/commands/__tests__/world-upgrade.test.d.ts +0 -8
- package/dist/commands/__tests__/world-upgrade.test.d.ts.map +0 -1
- package/dist/commands/__tests__/world-upgrade.test.js +0 -73
- package/dist/commands/__tests__/world-upgrade.test.js.map +0 -1
- package/dist/lib/__tests__/symlink-reconcile.test.d.ts +0 -2
- package/dist/lib/__tests__/symlink-reconcile.test.d.ts.map +0 -1
- package/dist/lib/__tests__/symlink-reconcile.test.js +0 -106
- package/dist/lib/__tests__/symlink-reconcile.test.js.map +0 -1
package/dist/mcp-server.js
CHANGED
|
@@ -412,11 +412,11 @@ var require_codegen = __commonJS({
|
|
|
412
412
|
const rhs = this.rhs === void 0 ? "" : ` = ${this.rhs}`;
|
|
413
413
|
return `${varKind} ${this.name}${rhs};` + _n;
|
|
414
414
|
}
|
|
415
|
-
optimizeNames(names,
|
|
415
|
+
optimizeNames(names, constants2) {
|
|
416
416
|
if (!names[this.name.str])
|
|
417
417
|
return;
|
|
418
418
|
if (this.rhs)
|
|
419
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
419
|
+
this.rhs = optimizeExpr(this.rhs, names, constants2);
|
|
420
420
|
return this;
|
|
421
421
|
}
|
|
422
422
|
get names() {
|
|
@@ -433,10 +433,10 @@ var require_codegen = __commonJS({
|
|
|
433
433
|
render({ _n }) {
|
|
434
434
|
return `${this.lhs} = ${this.rhs};` + _n;
|
|
435
435
|
}
|
|
436
|
-
optimizeNames(names,
|
|
436
|
+
optimizeNames(names, constants2) {
|
|
437
437
|
if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
|
|
438
438
|
return;
|
|
439
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
439
|
+
this.rhs = optimizeExpr(this.rhs, names, constants2);
|
|
440
440
|
return this;
|
|
441
441
|
}
|
|
442
442
|
get names() {
|
|
@@ -497,8 +497,8 @@ var require_codegen = __commonJS({
|
|
|
497
497
|
optimizeNodes() {
|
|
498
498
|
return `${this.code}` ? this : void 0;
|
|
499
499
|
}
|
|
500
|
-
optimizeNames(names,
|
|
501
|
-
this.code = optimizeExpr(this.code, names,
|
|
500
|
+
optimizeNames(names, constants2) {
|
|
501
|
+
this.code = optimizeExpr(this.code, names, constants2);
|
|
502
502
|
return this;
|
|
503
503
|
}
|
|
504
504
|
get names() {
|
|
@@ -527,12 +527,12 @@ var require_codegen = __commonJS({
|
|
|
527
527
|
}
|
|
528
528
|
return nodes.length > 0 ? this : void 0;
|
|
529
529
|
}
|
|
530
|
-
optimizeNames(names,
|
|
530
|
+
optimizeNames(names, constants2) {
|
|
531
531
|
const { nodes } = this;
|
|
532
532
|
let i = nodes.length;
|
|
533
533
|
while (i--) {
|
|
534
534
|
const n = nodes[i];
|
|
535
|
-
if (n.optimizeNames(names,
|
|
535
|
+
if (n.optimizeNames(names, constants2))
|
|
536
536
|
continue;
|
|
537
537
|
subtractNames(names, n.names);
|
|
538
538
|
nodes.splice(i, 1);
|
|
@@ -585,12 +585,12 @@ var require_codegen = __commonJS({
|
|
|
585
585
|
return void 0;
|
|
586
586
|
return this;
|
|
587
587
|
}
|
|
588
|
-
optimizeNames(names,
|
|
588
|
+
optimizeNames(names, constants2) {
|
|
589
589
|
var _a;
|
|
590
|
-
this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names,
|
|
591
|
-
if (!(super.optimizeNames(names,
|
|
590
|
+
this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants2);
|
|
591
|
+
if (!(super.optimizeNames(names, constants2) || this.else))
|
|
592
592
|
return;
|
|
593
|
-
this.condition = optimizeExpr(this.condition, names,
|
|
593
|
+
this.condition = optimizeExpr(this.condition, names, constants2);
|
|
594
594
|
return this;
|
|
595
595
|
}
|
|
596
596
|
get names() {
|
|
@@ -613,10 +613,10 @@ var require_codegen = __commonJS({
|
|
|
613
613
|
render(opts) {
|
|
614
614
|
return `for(${this.iteration})` + super.render(opts);
|
|
615
615
|
}
|
|
616
|
-
optimizeNames(names,
|
|
617
|
-
if (!super.optimizeNames(names,
|
|
616
|
+
optimizeNames(names, constants2) {
|
|
617
|
+
if (!super.optimizeNames(names, constants2))
|
|
618
618
|
return;
|
|
619
|
-
this.iteration = optimizeExpr(this.iteration, names,
|
|
619
|
+
this.iteration = optimizeExpr(this.iteration, names, constants2);
|
|
620
620
|
return this;
|
|
621
621
|
}
|
|
622
622
|
get names() {
|
|
@@ -652,10 +652,10 @@ var require_codegen = __commonJS({
|
|
|
652
652
|
render(opts) {
|
|
653
653
|
return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
|
|
654
654
|
}
|
|
655
|
-
optimizeNames(names,
|
|
656
|
-
if (!super.optimizeNames(names,
|
|
655
|
+
optimizeNames(names, constants2) {
|
|
656
|
+
if (!super.optimizeNames(names, constants2))
|
|
657
657
|
return;
|
|
658
|
-
this.iterable = optimizeExpr(this.iterable, names,
|
|
658
|
+
this.iterable = optimizeExpr(this.iterable, names, constants2);
|
|
659
659
|
return this;
|
|
660
660
|
}
|
|
661
661
|
get names() {
|
|
@@ -697,11 +697,11 @@ var require_codegen = __commonJS({
|
|
|
697
697
|
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
|
|
698
698
|
return this;
|
|
699
699
|
}
|
|
700
|
-
optimizeNames(names,
|
|
700
|
+
optimizeNames(names, constants2) {
|
|
701
701
|
var _a, _b;
|
|
702
|
-
super.optimizeNames(names,
|
|
703
|
-
(_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names,
|
|
704
|
-
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names,
|
|
702
|
+
super.optimizeNames(names, constants2);
|
|
703
|
+
(_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants2);
|
|
704
|
+
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants2);
|
|
705
705
|
return this;
|
|
706
706
|
}
|
|
707
707
|
get names() {
|
|
@@ -1002,7 +1002,7 @@ var require_codegen = __commonJS({
|
|
|
1002
1002
|
function addExprNames(names, from) {
|
|
1003
1003
|
return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
|
|
1004
1004
|
}
|
|
1005
|
-
function optimizeExpr(expr, names,
|
|
1005
|
+
function optimizeExpr(expr, names, constants2) {
|
|
1006
1006
|
if (expr instanceof code_1.Name)
|
|
1007
1007
|
return replaceName(expr);
|
|
1008
1008
|
if (!canOptimize(expr))
|
|
@@ -1017,14 +1017,14 @@ var require_codegen = __commonJS({
|
|
|
1017
1017
|
return items;
|
|
1018
1018
|
}, []));
|
|
1019
1019
|
function replaceName(n) {
|
|
1020
|
-
const c =
|
|
1020
|
+
const c = constants2[n.str];
|
|
1021
1021
|
if (c === void 0 || names[n.str] !== 1)
|
|
1022
1022
|
return n;
|
|
1023
1023
|
delete names[n.str];
|
|
1024
1024
|
return c;
|
|
1025
1025
|
}
|
|
1026
1026
|
function canOptimize(e) {
|
|
1027
|
-
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 &&
|
|
1027
|
+
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants2[c.str] !== void 0);
|
|
1028
1028
|
}
|
|
1029
1029
|
}
|
|
1030
1030
|
function subtractNames(names, from) {
|
|
@@ -2986,7 +2986,7 @@ var require_compile = __commonJS({
|
|
|
2986
2986
|
const schOrFunc = root.refs[ref];
|
|
2987
2987
|
if (schOrFunc)
|
|
2988
2988
|
return schOrFunc;
|
|
2989
|
-
let _sch =
|
|
2989
|
+
let _sch = resolve8.call(this, root, ref);
|
|
2990
2990
|
if (_sch === void 0) {
|
|
2991
2991
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2992
2992
|
const { schemaId } = this.opts;
|
|
@@ -3013,7 +3013,7 @@ var require_compile = __commonJS({
|
|
|
3013
3013
|
function sameSchemaEnv(s1, s2) {
|
|
3014
3014
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3015
3015
|
}
|
|
3016
|
-
function
|
|
3016
|
+
function resolve8(root, ref) {
|
|
3017
3017
|
let sch;
|
|
3018
3018
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3019
3019
|
ref = sch;
|
|
@@ -3228,8 +3228,8 @@ var require_utils = __commonJS({
|
|
|
3228
3228
|
}
|
|
3229
3229
|
return ind;
|
|
3230
3230
|
}
|
|
3231
|
-
function removeDotSegments(
|
|
3232
|
-
let input =
|
|
3231
|
+
function removeDotSegments(path27) {
|
|
3232
|
+
let input = path27;
|
|
3233
3233
|
const output = [];
|
|
3234
3234
|
let nextSlash = -1;
|
|
3235
3235
|
let len = 0;
|
|
@@ -3428,8 +3428,8 @@ var require_schemes = __commonJS({
|
|
|
3428
3428
|
wsComponent.secure = void 0;
|
|
3429
3429
|
}
|
|
3430
3430
|
if (wsComponent.resourceName) {
|
|
3431
|
-
const [
|
|
3432
|
-
wsComponent.path =
|
|
3431
|
+
const [path27, query] = wsComponent.resourceName.split("?");
|
|
3432
|
+
wsComponent.path = path27 && path27 !== "/" ? path27 : void 0;
|
|
3433
3433
|
wsComponent.query = query;
|
|
3434
3434
|
wsComponent.resourceName = void 0;
|
|
3435
3435
|
}
|
|
@@ -3588,55 +3588,55 @@ var require_fast_uri = __commonJS({
|
|
|
3588
3588
|
}
|
|
3589
3589
|
return uri;
|
|
3590
3590
|
}
|
|
3591
|
-
function
|
|
3591
|
+
function resolve8(baseURI, relativeURI, options) {
|
|
3592
3592
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3593
3593
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3594
3594
|
schemelessOptions.skipEscape = true;
|
|
3595
3595
|
return serialize(resolved, schemelessOptions);
|
|
3596
3596
|
}
|
|
3597
|
-
function resolveComponent(base,
|
|
3597
|
+
function resolveComponent(base, relative3, options, skipNormalization) {
|
|
3598
3598
|
const target = {};
|
|
3599
3599
|
if (!skipNormalization) {
|
|
3600
3600
|
base = parse3(serialize(base, options), options);
|
|
3601
|
-
|
|
3601
|
+
relative3 = parse3(serialize(relative3, options), options);
|
|
3602
3602
|
}
|
|
3603
3603
|
options = options || {};
|
|
3604
|
-
if (!options.tolerant &&
|
|
3605
|
-
target.scheme =
|
|
3606
|
-
target.userinfo =
|
|
3607
|
-
target.host =
|
|
3608
|
-
target.port =
|
|
3609
|
-
target.path = removeDotSegments(
|
|
3610
|
-
target.query =
|
|
3604
|
+
if (!options.tolerant && relative3.scheme) {
|
|
3605
|
+
target.scheme = relative3.scheme;
|
|
3606
|
+
target.userinfo = relative3.userinfo;
|
|
3607
|
+
target.host = relative3.host;
|
|
3608
|
+
target.port = relative3.port;
|
|
3609
|
+
target.path = removeDotSegments(relative3.path || "");
|
|
3610
|
+
target.query = relative3.query;
|
|
3611
3611
|
} else {
|
|
3612
|
-
if (
|
|
3613
|
-
target.userinfo =
|
|
3614
|
-
target.host =
|
|
3615
|
-
target.port =
|
|
3616
|
-
target.path = removeDotSegments(
|
|
3617
|
-
target.query =
|
|
3612
|
+
if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
|
|
3613
|
+
target.userinfo = relative3.userinfo;
|
|
3614
|
+
target.host = relative3.host;
|
|
3615
|
+
target.port = relative3.port;
|
|
3616
|
+
target.path = removeDotSegments(relative3.path || "");
|
|
3617
|
+
target.query = relative3.query;
|
|
3618
3618
|
} else {
|
|
3619
|
-
if (!
|
|
3619
|
+
if (!relative3.path) {
|
|
3620
3620
|
target.path = base.path;
|
|
3621
|
-
if (
|
|
3622
|
-
target.query =
|
|
3621
|
+
if (relative3.query !== void 0) {
|
|
3622
|
+
target.query = relative3.query;
|
|
3623
3623
|
} else {
|
|
3624
3624
|
target.query = base.query;
|
|
3625
3625
|
}
|
|
3626
3626
|
} else {
|
|
3627
|
-
if (
|
|
3628
|
-
target.path = removeDotSegments(
|
|
3627
|
+
if (relative3.path[0] === "/") {
|
|
3628
|
+
target.path = removeDotSegments(relative3.path);
|
|
3629
3629
|
} else {
|
|
3630
3630
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
3631
|
-
target.path = "/" +
|
|
3631
|
+
target.path = "/" + relative3.path;
|
|
3632
3632
|
} else if (!base.path) {
|
|
3633
|
-
target.path =
|
|
3633
|
+
target.path = relative3.path;
|
|
3634
3634
|
} else {
|
|
3635
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
3635
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
|
|
3636
3636
|
}
|
|
3637
3637
|
target.path = removeDotSegments(target.path);
|
|
3638
3638
|
}
|
|
3639
|
-
target.query =
|
|
3639
|
+
target.query = relative3.query;
|
|
3640
3640
|
}
|
|
3641
3641
|
target.userinfo = base.userinfo;
|
|
3642
3642
|
target.host = base.host;
|
|
@@ -3644,7 +3644,7 @@ var require_fast_uri = __commonJS({
|
|
|
3644
3644
|
}
|
|
3645
3645
|
target.scheme = base.scheme;
|
|
3646
3646
|
}
|
|
3647
|
-
target.fragment =
|
|
3647
|
+
target.fragment = relative3.fragment;
|
|
3648
3648
|
return target;
|
|
3649
3649
|
}
|
|
3650
3650
|
function equal(uriA, uriB, options) {
|
|
@@ -3815,7 +3815,7 @@ var require_fast_uri = __commonJS({
|
|
|
3815
3815
|
var fastUri = {
|
|
3816
3816
|
SCHEMES,
|
|
3817
3817
|
normalize,
|
|
3818
|
-
resolve:
|
|
3818
|
+
resolve: resolve8,
|
|
3819
3819
|
resolveComponent,
|
|
3820
3820
|
equal,
|
|
3821
3821
|
serialize,
|
|
@@ -6791,12 +6791,12 @@ var require_dist = __commonJS({
|
|
|
6791
6791
|
throw new Error(`Unknown format "${name}"`);
|
|
6792
6792
|
return f;
|
|
6793
6793
|
};
|
|
6794
|
-
function addFormats(ajv, list,
|
|
6794
|
+
function addFormats(ajv, list, fs23, exportName) {
|
|
6795
6795
|
var _a;
|
|
6796
6796
|
var _b;
|
|
6797
6797
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6798
6798
|
for (const f of list)
|
|
6799
|
-
ajv.addFormat(f,
|
|
6799
|
+
ajv.addFormat(f, fs23[f]);
|
|
6800
6800
|
}
|
|
6801
6801
|
module.exports = exports = formatsPlugin;
|
|
6802
6802
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -7002,10 +7002,10 @@ function assignProp(target, prop, value) {
|
|
|
7002
7002
|
configurable: true
|
|
7003
7003
|
});
|
|
7004
7004
|
}
|
|
7005
|
-
function getElementAtPath(obj,
|
|
7006
|
-
if (!
|
|
7005
|
+
function getElementAtPath(obj, path27) {
|
|
7006
|
+
if (!path27)
|
|
7007
7007
|
return obj;
|
|
7008
|
-
return
|
|
7008
|
+
return path27.reduce((acc, key) => acc?.[key], obj);
|
|
7009
7009
|
}
|
|
7010
7010
|
function promiseAllObject(promisesObj) {
|
|
7011
7011
|
const keys = Object.keys(promisesObj);
|
|
@@ -7325,11 +7325,11 @@ function aborted(x, startIndex = 0) {
|
|
|
7325
7325
|
}
|
|
7326
7326
|
return false;
|
|
7327
7327
|
}
|
|
7328
|
-
function prefixIssues(
|
|
7328
|
+
function prefixIssues(path27, issues) {
|
|
7329
7329
|
return issues.map((iss) => {
|
|
7330
7330
|
var _a;
|
|
7331
7331
|
(_a = iss).path ?? (_a.path = []);
|
|
7332
|
-
iss.path.unshift(
|
|
7332
|
+
iss.path.unshift(path27);
|
|
7333
7333
|
return iss;
|
|
7334
7334
|
});
|
|
7335
7335
|
}
|
|
@@ -12914,12 +12914,12 @@ var StdioServerTransport = class {
|
|
|
12914
12914
|
this.onclose?.();
|
|
12915
12915
|
}
|
|
12916
12916
|
send(message) {
|
|
12917
|
-
return new Promise((
|
|
12917
|
+
return new Promise((resolve8) => {
|
|
12918
12918
|
const json = serializeMessage(message);
|
|
12919
12919
|
if (this._stdout.write(json)) {
|
|
12920
|
-
|
|
12920
|
+
resolve8();
|
|
12921
12921
|
} else {
|
|
12922
|
-
this._stdout.once("drain",
|
|
12922
|
+
this._stdout.once("drain", resolve8);
|
|
12923
12923
|
}
|
|
12924
12924
|
});
|
|
12925
12925
|
}
|
|
@@ -13403,8 +13403,8 @@ function getErrorMap() {
|
|
|
13403
13403
|
|
|
13404
13404
|
// ../../node_modules/zod/v3/helpers/parseUtil.js
|
|
13405
13405
|
var makeIssue = (params) => {
|
|
13406
|
-
const { data, path:
|
|
13407
|
-
const fullPath = [...
|
|
13406
|
+
const { data, path: path27, errorMaps, issueData } = params;
|
|
13407
|
+
const fullPath = [...path27, ...issueData.path || []];
|
|
13408
13408
|
const fullIssue = {
|
|
13409
13409
|
...issueData,
|
|
13410
13410
|
path: fullPath
|
|
@@ -13520,11 +13520,11 @@ var errorUtil;
|
|
|
13520
13520
|
|
|
13521
13521
|
// ../../node_modules/zod/v3/types.js
|
|
13522
13522
|
var ParseInputLazyPath = class {
|
|
13523
|
-
constructor(parent, value,
|
|
13523
|
+
constructor(parent, value, path27, key) {
|
|
13524
13524
|
this._cachedPath = [];
|
|
13525
13525
|
this.parent = parent;
|
|
13526
13526
|
this.data = value;
|
|
13527
|
-
this._path =
|
|
13527
|
+
this._path = path27;
|
|
13528
13528
|
this._key = key;
|
|
13529
13529
|
}
|
|
13530
13530
|
get path() {
|
|
@@ -18987,7 +18987,7 @@ var Protocol = class {
|
|
|
18987
18987
|
return;
|
|
18988
18988
|
}
|
|
18989
18989
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
18990
|
-
await new Promise((
|
|
18990
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
18991
18991
|
options?.signal?.throwIfAborted();
|
|
18992
18992
|
}
|
|
18993
18993
|
} catch (error2) {
|
|
@@ -19004,7 +19004,7 @@ var Protocol = class {
|
|
|
19004
19004
|
*/
|
|
19005
19005
|
request(request2, resultSchema, options) {
|
|
19006
19006
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
19007
|
-
return new Promise((
|
|
19007
|
+
return new Promise((resolve8, reject2) => {
|
|
19008
19008
|
const earlyReject = (error2) => {
|
|
19009
19009
|
reject2(error2);
|
|
19010
19010
|
};
|
|
@@ -19082,7 +19082,7 @@ var Protocol = class {
|
|
|
19082
19082
|
if (!parseResult.success) {
|
|
19083
19083
|
reject2(parseResult.error);
|
|
19084
19084
|
} else {
|
|
19085
|
-
|
|
19085
|
+
resolve8(parseResult.data);
|
|
19086
19086
|
}
|
|
19087
19087
|
} catch (error2) {
|
|
19088
19088
|
reject2(error2);
|
|
@@ -19343,12 +19343,12 @@ var Protocol = class {
|
|
|
19343
19343
|
}
|
|
19344
19344
|
} catch {
|
|
19345
19345
|
}
|
|
19346
|
-
return new Promise((
|
|
19346
|
+
return new Promise((resolve8, reject2) => {
|
|
19347
19347
|
if (signal.aborted) {
|
|
19348
19348
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
19349
19349
|
return;
|
|
19350
19350
|
}
|
|
19351
|
-
const timeoutId = setTimeout(
|
|
19351
|
+
const timeoutId = setTimeout(resolve8, interval);
|
|
19352
19352
|
signal.addEventListener("abort", () => {
|
|
19353
19353
|
clearTimeout(timeoutId);
|
|
19354
19354
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -20448,7 +20448,7 @@ var McpServer = class {
|
|
|
20448
20448
|
let task = createTaskResult.task;
|
|
20449
20449
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
20450
20450
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
20451
|
-
await new Promise((
|
|
20451
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
20452
20452
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
20453
20453
|
if (!updatedTask) {
|
|
20454
20454
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -21365,8 +21365,8 @@ var AuthClient = class {
|
|
|
21365
21365
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
21366
21366
|
}
|
|
21367
21367
|
}
|
|
21368
|
-
async request(method,
|
|
21369
|
-
const url = `${this.baseUrl}${
|
|
21368
|
+
async request(method, path27, body, attempt = 0) {
|
|
21369
|
+
const url = `${this.baseUrl}${path27}`;
|
|
21370
21370
|
const controller = new AbortController();
|
|
21371
21371
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
21372
21372
|
const headers = {};
|
|
@@ -21384,7 +21384,7 @@ var AuthClient = class {
|
|
|
21384
21384
|
} catch (err) {
|
|
21385
21385
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
21386
21386
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
21387
|
-
return this.request(method,
|
|
21387
|
+
return this.request(method, path27, body, attempt + 1);
|
|
21388
21388
|
}
|
|
21389
21389
|
throw err;
|
|
21390
21390
|
} finally {
|
|
@@ -21411,7 +21411,7 @@ async function safeText(res) {
|
|
|
21411
21411
|
}
|
|
21412
21412
|
}
|
|
21413
21413
|
function sleep(ms) {
|
|
21414
|
-
return new Promise((
|
|
21414
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
21415
21415
|
}
|
|
21416
21416
|
|
|
21417
21417
|
// ../core/dist/auth/container.js
|
|
@@ -21543,7 +21543,7 @@ function resolveAuthServicePath() {
|
|
|
21543
21543
|
return path3.join(pkgsDir, "auth-service");
|
|
21544
21544
|
}
|
|
21545
21545
|
function sleep2(ms) {
|
|
21546
|
-
return new Promise((
|
|
21546
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
21547
21547
|
}
|
|
21548
21548
|
|
|
21549
21549
|
// ../core/dist/auth/preflight.js
|
|
@@ -22191,12 +22191,12 @@ function register3(server, _ctx, _initError) {
|
|
|
22191
22191
|
registry2.close();
|
|
22192
22192
|
}
|
|
22193
22193
|
try {
|
|
22194
|
-
const { default:
|
|
22195
|
-
const { default:
|
|
22196
|
-
const { default:
|
|
22197
|
-
const tokenPath =
|
|
22198
|
-
if (
|
|
22199
|
-
const token =
|
|
22194
|
+
const { default: fs23 } = await import("node:fs");
|
|
22195
|
+
const { default: os15 } = await import("node:os");
|
|
22196
|
+
const { default: path27 } = await import("node:path");
|
|
22197
|
+
const tokenPath = path27.join(os15.homedir(), ".olam", "host-cp.token");
|
|
22198
|
+
if (fs23.existsSync(tokenPath)) {
|
|
22199
|
+
const token = fs23.readFileSync(tokenPath, "utf-8").trim();
|
|
22200
22200
|
await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
|
|
22201
22201
|
method: "POST",
|
|
22202
22202
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
@@ -22338,11 +22338,13 @@ var serviceSchema = external_exports.object({
|
|
|
22338
22338
|
var deploySchema = external_exports.object({
|
|
22339
22339
|
tags: external_exports.array(external_exports.string()).optional()
|
|
22340
22340
|
}).passthrough();
|
|
22341
|
+
var BootstrapKindSchema = external_exports.enum(["gems", "node", "pg"]);
|
|
22341
22342
|
var BootstrapStepSchema = external_exports.union([
|
|
22342
22343
|
external_exports.string(),
|
|
22343
22344
|
external_exports.object({
|
|
22344
22345
|
cmd: external_exports.string().min(1),
|
|
22345
|
-
idempotent_check: external_exports.string().min(1).optional()
|
|
22346
|
+
idempotent_check: external_exports.string().min(1).optional(),
|
|
22347
|
+
produces: BootstrapKindSchema.nullable().optional()
|
|
22346
22348
|
}).passthrough()
|
|
22347
22349
|
]);
|
|
22348
22350
|
function bootstrapStepCmd(entry) {
|
|
@@ -22389,7 +22391,7 @@ var KNOWN_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
22389
22391
|
"deploy"
|
|
22390
22392
|
]);
|
|
22391
22393
|
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
22392
|
-
function refineForbiddenKeys(value,
|
|
22394
|
+
function refineForbiddenKeys(value, path27, ctx, rejectSource) {
|
|
22393
22395
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
22394
22396
|
return;
|
|
22395
22397
|
}
|
|
@@ -22397,12 +22399,12 @@ function refineForbiddenKeys(value, path24, ctx, rejectSource) {
|
|
|
22397
22399
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
22398
22400
|
ctx.addIssue({
|
|
22399
22401
|
code: external_exports.ZodIssueCode.custom,
|
|
22400
|
-
path: [...
|
|
22402
|
+
path: [...path27, key],
|
|
22401
22403
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
22402
22404
|
});
|
|
22403
22405
|
continue;
|
|
22404
22406
|
}
|
|
22405
|
-
if (rejectSource &&
|
|
22407
|
+
if (rejectSource && path27.length === 0 && key === "source") {
|
|
22406
22408
|
ctx.addIssue({
|
|
22407
22409
|
code: external_exports.ZodIssueCode.custom,
|
|
22408
22410
|
path: ["source"],
|
|
@@ -22410,21 +22412,21 @@ function refineForbiddenKeys(value, path24, ctx, rejectSource) {
|
|
|
22410
22412
|
});
|
|
22411
22413
|
continue;
|
|
22412
22414
|
}
|
|
22413
|
-
refineForbiddenKeys(value[key], [...
|
|
22415
|
+
refineForbiddenKeys(value[key], [...path27, key], ctx, false);
|
|
22414
22416
|
}
|
|
22415
22417
|
}
|
|
22416
|
-
function rejectForbiddenKeys(value,
|
|
22418
|
+
function rejectForbiddenKeys(value, path27, rejectSource) {
|
|
22417
22419
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
22418
22420
|
return;
|
|
22419
22421
|
}
|
|
22420
22422
|
for (const key of Object.keys(value)) {
|
|
22421
22423
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
22422
|
-
throw new Error(`[manifest] ${
|
|
22424
|
+
throw new Error(`[manifest] ${path27}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
22423
22425
|
}
|
|
22424
22426
|
if (rejectSource && key === "source") {
|
|
22425
|
-
throw new Error(`[manifest] ${
|
|
22427
|
+
throw new Error(`[manifest] ${path27}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
22426
22428
|
}
|
|
22427
|
-
rejectForbiddenKeys(value[key], `${
|
|
22429
|
+
rejectForbiddenKeys(value[key], `${path27}.${key}`, false);
|
|
22428
22430
|
}
|
|
22429
22431
|
}
|
|
22430
22432
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -22433,40 +22435,40 @@ function unknownTopLevelKeys(parsed) {
|
|
|
22433
22435
|
function loadRepoManifest(repoDir) {
|
|
22434
22436
|
const olamPath = join5(repoDir, ".olam.yaml");
|
|
22435
22437
|
const adbPath = join5(repoDir, ".adb.yaml");
|
|
22436
|
-
let
|
|
22438
|
+
let manifestPath2;
|
|
22437
22439
|
let source;
|
|
22438
22440
|
if (existsSync4(olamPath)) {
|
|
22439
|
-
|
|
22441
|
+
manifestPath2 = olamPath;
|
|
22440
22442
|
source = "olam";
|
|
22441
22443
|
} else if (existsSync4(adbPath)) {
|
|
22442
|
-
|
|
22444
|
+
manifestPath2 = adbPath;
|
|
22443
22445
|
source = "adb";
|
|
22444
22446
|
} else {
|
|
22445
22447
|
return null;
|
|
22446
22448
|
}
|
|
22447
|
-
const stat = lstatSync(
|
|
22449
|
+
const stat = lstatSync(manifestPath2);
|
|
22448
22450
|
if (stat.isSymbolicLink()) {
|
|
22449
|
-
throw new Error(`[manifest] ${
|
|
22451
|
+
throw new Error(`[manifest] ${manifestPath2}: symbolic links are not permitted`);
|
|
22450
22452
|
}
|
|
22451
|
-
const raw = readFileSync3(
|
|
22453
|
+
const raw = readFileSync3(manifestPath2, "utf-8");
|
|
22452
22454
|
const parsed = YAML.parse(raw, { maxAliasCount: 100 });
|
|
22453
22455
|
if (parsed === null || parsed === void 0) {
|
|
22454
22456
|
if (source === "olam" && existsSync4(adbPath)) {
|
|
22455
|
-
console.warn(`[manifest] ${
|
|
22457
|
+
console.warn(`[manifest] ${manifestPath2}: file is empty; .adb.yaml is NOT consulted (delete .olam.yaml to fall back)`);
|
|
22456
22458
|
}
|
|
22457
22459
|
return null;
|
|
22458
22460
|
}
|
|
22459
22461
|
if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
22460
|
-
throw new Error(`[manifest] ${
|
|
22462
|
+
throw new Error(`[manifest] ${manifestPath2}: expected a YAML mapping at the top level`);
|
|
22461
22463
|
}
|
|
22462
|
-
rejectForbiddenKeys(parsed,
|
|
22464
|
+
rejectForbiddenKeys(parsed, manifestPath2, true);
|
|
22463
22465
|
const body = RepoManifestSchema.parse(parsed);
|
|
22464
22466
|
if (parsed["version"] === void 0) {
|
|
22465
|
-
console.warn(`[manifest] ${
|
|
22467
|
+
console.warn(`[manifest] ${manifestPath2}: missing "version: ${MANIFEST_VERSION}" field \u2014 add it to suppress this warning (backward-compat: file still parses)`);
|
|
22466
22468
|
}
|
|
22467
22469
|
const unknown2 = unknownTopLevelKeys(parsed);
|
|
22468
22470
|
if (unknown2.length > 0) {
|
|
22469
|
-
console.warn(`[manifest] ${
|
|
22471
|
+
console.warn(`[manifest] ${manifestPath2}: unknown top-level fields preserved (passthrough): ${unknown2.join(", ")}`);
|
|
22470
22472
|
}
|
|
22471
22473
|
return { ...body, source };
|
|
22472
22474
|
}
|
|
@@ -22862,10 +22864,10 @@ function extractMcpConfig(claudeJsonPath) {
|
|
|
22862
22864
|
}
|
|
22863
22865
|
return { mcpServers, secrets };
|
|
22864
22866
|
}
|
|
22865
|
-
function readOptional(
|
|
22866
|
-
if (!existsSync6(
|
|
22867
|
+
function readOptional(path27) {
|
|
22868
|
+
if (!existsSync6(path27)) return null;
|
|
22867
22869
|
try {
|
|
22868
|
-
return readFileSync5(
|
|
22870
|
+
return readFileSync5(path27, "utf8");
|
|
22869
22871
|
} catch {
|
|
22870
22872
|
return null;
|
|
22871
22873
|
}
|
|
@@ -23163,6 +23165,7 @@ var createWorldContainer = async (docker, worldId, worldName, image, env, resour
|
|
|
23163
23165
|
}
|
|
23164
23166
|
const hostControlPlanePort = HOST_CONTROL_PLANE_BASE2 + (portOffset ?? 0);
|
|
23165
23167
|
const hostTtydPort = 17681 + (portOffset ?? 0);
|
|
23168
|
+
const hostTtydShellPort = 17682 + (portOffset ?? 0);
|
|
23166
23169
|
const appPortBindings = {};
|
|
23167
23170
|
const appExposedPorts = {};
|
|
23168
23171
|
const appHostPorts = [];
|
|
@@ -23177,6 +23180,7 @@ var createWorldContainer = async (docker, worldId, worldName, image, env, resour
|
|
|
23177
23180
|
await auditPortsForZombies(docker, [
|
|
23178
23181
|
hostControlPlanePort,
|
|
23179
23182
|
hostTtydPort,
|
|
23183
|
+
hostTtydShellPort,
|
|
23180
23184
|
...appHostPorts
|
|
23181
23185
|
]);
|
|
23182
23186
|
const container = await docker.createContainer({
|
|
@@ -23190,6 +23194,7 @@ var createWorldContainer = async (docker, worldId, worldName, image, env, resour
|
|
|
23190
23194
|
ExposedPorts: {
|
|
23191
23195
|
[`${CONTROL_PLANE_PORT}/tcp`]: {},
|
|
23192
23196
|
"7681/tcp": {},
|
|
23197
|
+
"7682/tcp": {},
|
|
23193
23198
|
...appExposedPorts
|
|
23194
23199
|
},
|
|
23195
23200
|
HostConfig: {
|
|
@@ -23202,6 +23207,7 @@ var createWorldContainer = async (docker, worldId, worldName, image, env, resour
|
|
|
23202
23207
|
PortBindings: {
|
|
23203
23208
|
[`${CONTROL_PLANE_PORT}/tcp`]: [{ HostPort: String(hostControlPlanePort), HostIp: "127.0.0.1" }],
|
|
23204
23209
|
"7681/tcp": [{ HostPort: String(hostTtydPort), HostIp: "127.0.0.1" }],
|
|
23210
|
+
"7682/tcp": [{ HostPort: String(hostTtydShellPort), HostIp: "127.0.0.1" }],
|
|
23205
23211
|
...appPortBindings
|
|
23206
23212
|
},
|
|
23207
23213
|
NanoCpus: resources?.cpuCores ? resources.cpuCores * 1e9 : void 0,
|
|
@@ -23235,7 +23241,7 @@ var stopAndRemove = async (container) => {
|
|
|
23235
23241
|
|
|
23236
23242
|
// ../adapters/dist/docker/exec.js
|
|
23237
23243
|
import { PassThrough } from "node:stream";
|
|
23238
|
-
var demuxStream = (stream) => new Promise((
|
|
23244
|
+
var demuxStream = (stream) => new Promise((resolve8, reject2) => {
|
|
23239
23245
|
const stdoutChunks = [];
|
|
23240
23246
|
const stderrChunks = [];
|
|
23241
23247
|
const stdout = new PassThrough();
|
|
@@ -23249,7 +23255,7 @@ var demuxStream = (stream) => new Promise((resolve6, reject2) => {
|
|
|
23249
23255
|
stream.pipe(stdout);
|
|
23250
23256
|
}
|
|
23251
23257
|
stream.on("end", () => {
|
|
23252
|
-
|
|
23258
|
+
resolve8({
|
|
23253
23259
|
stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
|
|
23254
23260
|
stderr: Buffer.concat(stderrChunks).toString("utf-8")
|
|
23255
23261
|
});
|
|
@@ -23542,7 +23548,7 @@ var SSHConnectionPool = class {
|
|
|
23542
23548
|
// -----------------------------------------------------------------------
|
|
23543
23549
|
async exec(host, command) {
|
|
23544
23550
|
const client = await this.getConnection(host);
|
|
23545
|
-
return new Promise((
|
|
23551
|
+
return new Promise((resolve8, reject2) => {
|
|
23546
23552
|
client.exec(command, (err, stream) => {
|
|
23547
23553
|
if (err) {
|
|
23548
23554
|
reject2(new Error(`SSH exec failed on ${host}: ${err.message}`));
|
|
@@ -23557,7 +23563,7 @@ var SSHConnectionPool = class {
|
|
|
23557
23563
|
stderr += data.toString();
|
|
23558
23564
|
});
|
|
23559
23565
|
stream.on("close", (code) => {
|
|
23560
|
-
|
|
23566
|
+
resolve8({
|
|
23561
23567
|
exitCode: code ?? 0,
|
|
23562
23568
|
stdout: stdout.trimEnd(),
|
|
23563
23569
|
stderr: stderr.trimEnd()
|
|
@@ -23588,10 +23594,10 @@ var SSHConnectionPool = class {
|
|
|
23588
23594
|
throw new Error(`No SSH configuration found for host: ${host}`);
|
|
23589
23595
|
}
|
|
23590
23596
|
const client = new SSHClient();
|
|
23591
|
-
return new Promise((
|
|
23597
|
+
return new Promise((resolve8, reject2) => {
|
|
23592
23598
|
client.on("ready", () => {
|
|
23593
23599
|
this.connections.set(host, client);
|
|
23594
|
-
|
|
23600
|
+
resolve8(client);
|
|
23595
23601
|
}).on("error", (err) => {
|
|
23596
23602
|
this.connections.delete(host);
|
|
23597
23603
|
reject2(new Error(`SSH connection to ${host} failed: ${err.message}`));
|
|
@@ -24008,8 +24014,8 @@ var CloudflareProvider = class extends ComputeProvider {
|
|
|
24008
24014
|
// -----------------------------------------------------------------------
|
|
24009
24015
|
// Internal fetch helper
|
|
24010
24016
|
// -----------------------------------------------------------------------
|
|
24011
|
-
async request(
|
|
24012
|
-
const url = `${this.config.workerUrl}${
|
|
24017
|
+
async request(path27, method, body) {
|
|
24018
|
+
const url = `${this.config.workerUrl}${path27}`;
|
|
24013
24019
|
const bearer = await this.config.mintToken();
|
|
24014
24020
|
const headers = {
|
|
24015
24021
|
Authorization: `Bearer ${bearer}`
|
|
@@ -24446,7 +24452,8 @@ function register6(server, ctx, initError) {
|
|
|
24446
24452
|
// strip step so any operator-side uncommitted edits survive into
|
|
24447
24453
|
// the world's worktree. The baseline-diff snapshot still runs
|
|
24448
24454
|
// unconditionally (Phase C reaper still needs it).
|
|
24449
|
-
carryUncommitted: external_exports.boolean().optional().describe("Preserve operator's uncommitted edits in the world's worktree (B3); default false")
|
|
24455
|
+
carryUncommitted: external_exports.boolean().optional().describe("Preserve operator's uncommitted edits in the world's worktree (B3); default false"),
|
|
24456
|
+
runbookName: external_exports.string().optional().describe("Named runbook profile from ~/.olam/config.json \u2014 seeds ports, env overrides, and fixture-copy steps")
|
|
24450
24457
|
},
|
|
24451
24458
|
async (params) => {
|
|
24452
24459
|
if (!ctx) {
|
|
@@ -24510,7 +24517,8 @@ function register6(server, ctx, initError) {
|
|
|
24510
24517
|
branchName: params.branchName,
|
|
24511
24518
|
planFile: params.planFile,
|
|
24512
24519
|
taskContext: params.taskContext,
|
|
24513
|
-
carryUncommitted: params.carryUncommitted ?? false
|
|
24520
|
+
carryUncommitted: params.carryUncommitted ?? false,
|
|
24521
|
+
...params.runbookName ? { runbookName: params.runbookName } : {}
|
|
24514
24522
|
});
|
|
24515
24523
|
const lines = [
|
|
24516
24524
|
`World created successfully.`,
|
|
@@ -24569,7 +24577,7 @@ function register6(server, ctx, initError) {
|
|
|
24569
24577
|
}
|
|
24570
24578
|
} catch {
|
|
24571
24579
|
}
|
|
24572
|
-
await new Promise((
|
|
24580
|
+
await new Promise((resolve8) => setTimeout(resolve8, POLL_INTERVAL_MS));
|
|
24573
24581
|
}
|
|
24574
24582
|
}
|
|
24575
24583
|
if (authenticated) {
|
|
@@ -25301,8 +25309,8 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
|
|
|
25301
25309
|
}
|
|
25302
25310
|
}
|
|
25303
25311
|
async function copyClaudeConfigIntoContainer(containerName) {
|
|
25304
|
-
const { execSync:
|
|
25305
|
-
const dockerExec = (cmd) =>
|
|
25312
|
+
const { execSync: execSync7 } = await import("node:child_process");
|
|
25313
|
+
const dockerExec = (cmd) => execSync7(`docker exec ${containerName} sh -c '${cmd}'`, { stdio: "pipe" });
|
|
25306
25314
|
dockerExec("mkdir -p /home/olam/.claude");
|
|
25307
25315
|
dockerExec("test -f /home/olam/workspace/.claude-host-config/settings.json && cp /home/olam/workspace/.claude-host-config/settings.json /home/olam/.claude/settings.json || true");
|
|
25308
25316
|
dockerExec("test -f /home/olam/workspace/.claude-host-config/CLAUDE.md && cp /home/olam/workspace/.claude-host-config/CLAUDE.md /home/olam/.claude/CLAUDE.md || true");
|
|
@@ -25318,7 +25326,7 @@ async function copyClaudeConfigIntoContainer(containerName) {
|
|
|
25318
25326
|
await sanitizeContainerClaudeHooks(containerName);
|
|
25319
25327
|
}
|
|
25320
25328
|
async function sanitizeContainerClaudeHooks(containerName) {
|
|
25321
|
-
const { execSync:
|
|
25329
|
+
const { execSync: execSync7 } = await import("node:child_process");
|
|
25322
25330
|
const script = `
|
|
25323
25331
|
const fs = require('fs');
|
|
25324
25332
|
const p = '/home/olam/.claude/settings.json';
|
|
@@ -25362,7 +25370,7 @@ if (changed) {
|
|
|
25362
25370
|
}
|
|
25363
25371
|
`;
|
|
25364
25372
|
try {
|
|
25365
|
-
|
|
25373
|
+
execSync7(`docker exec ${containerName} /usr/local/bin/node -e ${shQuote(script)}`, { stdio: "pipe" });
|
|
25366
25374
|
} catch {
|
|
25367
25375
|
}
|
|
25368
25376
|
}
|
|
@@ -25499,8 +25507,8 @@ function copyMatchingFiles(sourcePath, destPath, pattern) {
|
|
|
25499
25507
|
try {
|
|
25500
25508
|
const matches2 = globSync(fullPattern);
|
|
25501
25509
|
for (const match of matches2) {
|
|
25502
|
-
const
|
|
25503
|
-
const dest = path9.join(destPath,
|
|
25510
|
+
const relative3 = path9.relative(sourcePath, match);
|
|
25511
|
+
const dest = path9.join(destPath, relative3);
|
|
25504
25512
|
fs6.mkdirSync(path9.dirname(dest), { recursive: true });
|
|
25505
25513
|
fs6.copyFileSync(match, dest);
|
|
25506
25514
|
}
|
|
@@ -26442,10 +26450,10 @@ async function writeManifest(args) {
|
|
|
26442
26450
|
capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
26443
26451
|
shots: entries
|
|
26444
26452
|
};
|
|
26445
|
-
const
|
|
26446
|
-
await writeFile(
|
|
26453
|
+
const path27 = join12(args.outDir, "manifest.json");
|
|
26454
|
+
await writeFile(path27, `${JSON.stringify(manifest, null, 2)}
|
|
26447
26455
|
`, "utf8");
|
|
26448
|
-
return { path:
|
|
26456
|
+
return { path: path27, manifest };
|
|
26449
26457
|
}
|
|
26450
26458
|
|
|
26451
26459
|
// ../mcp-server/src/tools/_capture/proxy.ts
|
|
@@ -26699,9 +26707,9 @@ async function startProxy(opts) {
|
|
|
26699
26707
|
const liveCompiled = verified.allowedPaths.map(compileGlob);
|
|
26700
26708
|
const target = parseRequestTarget(req);
|
|
26701
26709
|
if (!target) return httpReject(400, "invalid_target");
|
|
26702
|
-
const
|
|
26703
|
-
if (!liveCompiled.some((re) => re.test(
|
|
26704
|
-
return httpReject(403, "outside_allow_list", { path:
|
|
26710
|
+
const path27 = target.pathname;
|
|
26711
|
+
if (!liveCompiled.some((re) => re.test(path27))) {
|
|
26712
|
+
return httpReject(403, "outside_allow_list", { path: path27 });
|
|
26705
26713
|
}
|
|
26706
26714
|
const headerWorld = req.headers[WORLD_ASSERT_HEADER];
|
|
26707
26715
|
const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
|
|
@@ -26805,15 +26813,15 @@ ${JSON.stringify({ error: reason })}`
|
|
|
26805
26813
|
unlinkSync2(udsPath);
|
|
26806
26814
|
} catch {
|
|
26807
26815
|
}
|
|
26808
|
-
await new Promise((
|
|
26809
|
-
server.listen(udsPath, () =>
|
|
26816
|
+
await new Promise((resolve8, reject2) => {
|
|
26817
|
+
server.listen(udsPath, () => resolve8());
|
|
26810
26818
|
server.once("error", reject2);
|
|
26811
26819
|
});
|
|
26812
26820
|
chmodSync3(udsPath, 384);
|
|
26813
26821
|
port = 0;
|
|
26814
26822
|
} else {
|
|
26815
|
-
await new Promise((
|
|
26816
|
-
server.listen(opts.port ?? 0, "127.0.0.1", () =>
|
|
26823
|
+
await new Promise((resolve8, reject2) => {
|
|
26824
|
+
server.listen(opts.port ?? 0, "127.0.0.1", () => resolve8());
|
|
26817
26825
|
server.once("error", reject2);
|
|
26818
26826
|
});
|
|
26819
26827
|
const addr = server.address();
|
|
@@ -26829,10 +26837,10 @@ ${JSON.stringify({ error: reason })}`
|
|
|
26829
26837
|
} catch {
|
|
26830
26838
|
}
|
|
26831
26839
|
await Promise.race([
|
|
26832
|
-
new Promise((
|
|
26833
|
-
server.close((err) => err ? reject2(err) :
|
|
26840
|
+
new Promise((resolve8, reject2) => {
|
|
26841
|
+
server.close((err) => err ? reject2(err) : resolve8());
|
|
26834
26842
|
}),
|
|
26835
|
-
new Promise((
|
|
26843
|
+
new Promise((resolve8) => setTimeout(resolve8, 5e3))
|
|
26836
26844
|
]);
|
|
26837
26845
|
if (udsPath) {
|
|
26838
26846
|
try {
|
|
@@ -27164,10 +27172,10 @@ async function acquireLaunchSlot() {
|
|
|
27164
27172
|
_inFlightLaunches++;
|
|
27165
27173
|
return releaseLaunchSlot;
|
|
27166
27174
|
}
|
|
27167
|
-
return new Promise((
|
|
27175
|
+
return new Promise((resolve8) => {
|
|
27168
27176
|
_launchQueue.push(() => {
|
|
27169
27177
|
_inFlightLaunches++;
|
|
27170
|
-
|
|
27178
|
+
resolve8(releaseLaunchSlot);
|
|
27171
27179
|
});
|
|
27172
27180
|
});
|
|
27173
27181
|
}
|
|
@@ -27480,14 +27488,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
|
|
|
27480
27488
|
await page.waitForTimeout(shot.afterLoadMs);
|
|
27481
27489
|
}
|
|
27482
27490
|
const ext = format === "jpeg" ? "jpg" : "png";
|
|
27483
|
-
const
|
|
27491
|
+
const path27 = join13(outDir, `${shot.name}.${ext}`);
|
|
27484
27492
|
await page.screenshot({
|
|
27485
|
-
path:
|
|
27493
|
+
path: path27,
|
|
27486
27494
|
type: format,
|
|
27487
27495
|
...format === "jpeg" ? { quality: jpegQuality } : {},
|
|
27488
27496
|
fullPage: false
|
|
27489
27497
|
});
|
|
27490
|
-
return { name: shot.name, path:
|
|
27498
|
+
return { name: shot.name, path: path27, urlRedacted: redactUrl(shot.url), viewport };
|
|
27491
27499
|
} finally {
|
|
27492
27500
|
await context.close();
|
|
27493
27501
|
}
|
|
@@ -27708,7 +27716,7 @@ function register20(server, ctx, initError) {
|
|
|
27708
27716
|
shot.url === navigableShot.url ? result : { ...result, urlRedacted: redactUrl(shot.url) }
|
|
27709
27717
|
);
|
|
27710
27718
|
}
|
|
27711
|
-
const { path:
|
|
27719
|
+
const { path: manifestPath2 } = await writeManifest({
|
|
27712
27720
|
outDir: absOutDir,
|
|
27713
27721
|
correlationId,
|
|
27714
27722
|
shots: results
|
|
@@ -27720,7 +27728,7 @@ function register20(server, ctx, initError) {
|
|
|
27720
27728
|
type: "text",
|
|
27721
27729
|
text: `Captured ${results.length} shot(s) to ${absOutDir} (correlationId=${correlationId}):
|
|
27722
27730
|
${lines.join("\n")}
|
|
27723
|
-
manifest \u2192 ${
|
|
27731
|
+
manifest \u2192 ${manifestPath2}`
|
|
27724
27732
|
}
|
|
27725
27733
|
]
|
|
27726
27734
|
};
|
|
@@ -27930,12 +27938,12 @@ function openUrl(url) {
|
|
|
27930
27938
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
27931
27939
|
async function readHostCpToken2() {
|
|
27932
27940
|
try {
|
|
27933
|
-
const { default:
|
|
27934
|
-
const { default:
|
|
27935
|
-
const { default:
|
|
27936
|
-
const tp =
|
|
27937
|
-
if (!
|
|
27938
|
-
return { token:
|
|
27941
|
+
const { default: fs23 } = await import("node:fs");
|
|
27942
|
+
const { default: os15 } = await import("node:os");
|
|
27943
|
+
const { default: path27 } = await import("node:path");
|
|
27944
|
+
const tp = path27.join(os15.homedir(), ".olam", "host-cp.token");
|
|
27945
|
+
if (!fs23.existsSync(tp)) return { token: null };
|
|
27946
|
+
return { token: fs23.readFileSync(tp, "utf-8").trim() };
|
|
27939
27947
|
} catch {
|
|
27940
27948
|
return { token: null };
|
|
27941
27949
|
}
|
|
@@ -28354,6 +28362,168 @@ function updateRepo(name, updates) {
|
|
|
28354
28362
|
return updated;
|
|
28355
28363
|
}
|
|
28356
28364
|
|
|
28365
|
+
// ../core/dist/global-config/runbooks.js
|
|
28366
|
+
function validateRunbookIntegrity(rb, registeredRepoNames) {
|
|
28367
|
+
const runbookRepoSet = new Set(rb.repos);
|
|
28368
|
+
for (const repoName of rb.repos) {
|
|
28369
|
+
if (!registeredRepoNames.has(repoName)) {
|
|
28370
|
+
throw new Error(`repo "${repoName}" is not registered. Add it with "olam repos add".`);
|
|
28371
|
+
}
|
|
28372
|
+
}
|
|
28373
|
+
if (rb.seeds) {
|
|
28374
|
+
for (const seed of rb.seeds) {
|
|
28375
|
+
if (seed.repo && !runbookRepoSet.has(seed.repo)) {
|
|
28376
|
+
throw new Error(`seed references repo "${seed.repo}" which is not in runbook repos [${rb.repos.join(", ")}].`);
|
|
28377
|
+
}
|
|
28378
|
+
}
|
|
28379
|
+
}
|
|
28380
|
+
if (rb.portMap) {
|
|
28381
|
+
for (const repoKey of Object.keys(rb.portMap)) {
|
|
28382
|
+
if (!runbookRepoSet.has(repoKey)) {
|
|
28383
|
+
throw new Error(`portMap references repo "${repoKey}" which is not in runbook repos [${rb.repos.join(", ")}].`);
|
|
28384
|
+
}
|
|
28385
|
+
}
|
|
28386
|
+
}
|
|
28387
|
+
if (rb.env) {
|
|
28388
|
+
for (const repoKey of Object.keys(rb.env)) {
|
|
28389
|
+
if (!runbookRepoSet.has(repoKey)) {
|
|
28390
|
+
throw new Error(`env references repo "${repoKey}" which is not in runbook repos [${rb.repos.join(", ")}].`);
|
|
28391
|
+
}
|
|
28392
|
+
}
|
|
28393
|
+
}
|
|
28394
|
+
if (rb.portMap) {
|
|
28395
|
+
const seen = /* @__PURE__ */ new Map();
|
|
28396
|
+
for (const [repoName, svcMap] of Object.entries(rb.portMap)) {
|
|
28397
|
+
for (const [svcName, port] of Object.entries(svcMap)) {
|
|
28398
|
+
if (port < 1024 || port > 65535) {
|
|
28399
|
+
throw new Error(`port ${port} for ${repoName}.${svcName} is out of range. Ports must be 1024\u201365535.`);
|
|
28400
|
+
}
|
|
28401
|
+
const label = `${repoName}.${svcName}`;
|
|
28402
|
+
const previous = seen.get(port);
|
|
28403
|
+
if (previous !== void 0) {
|
|
28404
|
+
throw new Error(`port ${port} declared twice in runbook "${rb.name}" (${previous} and ${label}). Each port must be unique within a runbook.`);
|
|
28405
|
+
}
|
|
28406
|
+
seen.set(port, label);
|
|
28407
|
+
}
|
|
28408
|
+
}
|
|
28409
|
+
}
|
|
28410
|
+
}
|
|
28411
|
+
function listRunbooks() {
|
|
28412
|
+
return readGlobalConfig().runbooks;
|
|
28413
|
+
}
|
|
28414
|
+
function addRunbook(entry) {
|
|
28415
|
+
const config2 = readGlobalConfig();
|
|
28416
|
+
if (config2.runbooks.some((r) => r.name === entry.name)) {
|
|
28417
|
+
throw new Error(`runbook "${entry.name}" already exists. Use "olam runbooks update" to modify it.`);
|
|
28418
|
+
}
|
|
28419
|
+
const registeredRepoNames = new Set(config2.repos.map((r) => r.name));
|
|
28420
|
+
validateRunbookIntegrity({ ...entry, seeds: entry.seeds }, registeredRepoNames);
|
|
28421
|
+
const now = Date.now();
|
|
28422
|
+
const newRunbook = {
|
|
28423
|
+
name: entry.name,
|
|
28424
|
+
repos: entry.repos,
|
|
28425
|
+
updatedAt: now,
|
|
28426
|
+
...entry.description !== void 0 ? { description: entry.description } : {},
|
|
28427
|
+
...entry.portMap !== void 0 ? { portMap: entry.portMap } : {},
|
|
28428
|
+
...entry.seeds !== void 0 ? { seeds: entry.seeds } : {},
|
|
28429
|
+
...entry.env !== void 0 ? { env: entry.env } : {}
|
|
28430
|
+
};
|
|
28431
|
+
writeGlobalConfig({ ...config2, runbooks: [...config2.runbooks, newRunbook] });
|
|
28432
|
+
return newRunbook;
|
|
28433
|
+
}
|
|
28434
|
+
function removeRunbook(name) {
|
|
28435
|
+
const config2 = readGlobalConfig();
|
|
28436
|
+
if (!config2.runbooks.some((r) => r.name === name)) {
|
|
28437
|
+
throw new Error(`runbook "${name}" not found. Run "olam runbooks list" to see available runbooks.`);
|
|
28438
|
+
}
|
|
28439
|
+
writeGlobalConfig({ ...config2, runbooks: config2.runbooks.filter((r) => r.name !== name) });
|
|
28440
|
+
}
|
|
28441
|
+
function getRunbook(name) {
|
|
28442
|
+
const config2 = readGlobalConfig();
|
|
28443
|
+
const found = config2.runbooks.find((r) => r.name === name);
|
|
28444
|
+
if (!found) {
|
|
28445
|
+
throw new Error(`runbook "${name}" not found. Run "olam runbooks list" to see available runbooks.`);
|
|
28446
|
+
}
|
|
28447
|
+
return found;
|
|
28448
|
+
}
|
|
28449
|
+
|
|
28450
|
+
// ../core/dist/global-config/port-validator.js
|
|
28451
|
+
import * as net2 from "node:net";
|
|
28452
|
+
import * as childProcess from "node:child_process";
|
|
28453
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
28454
|
+
var _require3;
|
|
28455
|
+
function getRequire() {
|
|
28456
|
+
if (!_require3) {
|
|
28457
|
+
_require3 = createRequire3(import.meta.url);
|
|
28458
|
+
}
|
|
28459
|
+
return _require3;
|
|
28460
|
+
}
|
|
28461
|
+
function checkPortInUse(port) {
|
|
28462
|
+
try {
|
|
28463
|
+
const server = net2.createServer();
|
|
28464
|
+
server.unref();
|
|
28465
|
+
let inUse = false;
|
|
28466
|
+
try {
|
|
28467
|
+
server.listen({ port, host: "0.0.0.0" });
|
|
28468
|
+
server.close();
|
|
28469
|
+
} catch {
|
|
28470
|
+
inUse = true;
|
|
28471
|
+
}
|
|
28472
|
+
return inUse;
|
|
28473
|
+
} catch {
|
|
28474
|
+
return false;
|
|
28475
|
+
}
|
|
28476
|
+
}
|
|
28477
|
+
function getPidForPort(port) {
|
|
28478
|
+
try {
|
|
28479
|
+
const out = childProcess.execSync(`lsof -ti :${port}`, {
|
|
28480
|
+
encoding: "utf8",
|
|
28481
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
28482
|
+
timeout: 2e3
|
|
28483
|
+
});
|
|
28484
|
+
const pid = parseInt(out.trim().split("\n")[0] ?? "", 10);
|
|
28485
|
+
return Number.isNaN(pid) ? void 0 : pid;
|
|
28486
|
+
} catch {
|
|
28487
|
+
return void 0;
|
|
28488
|
+
}
|
|
28489
|
+
}
|
|
28490
|
+
function getOlamWorldForPortDefault(port) {
|
|
28491
|
+
try {
|
|
28492
|
+
const { WorldRegistry: WorldRegistry2 } = getRequire()("../world/registry.js");
|
|
28493
|
+
const registry2 = new WorldRegistry2();
|
|
28494
|
+
try {
|
|
28495
|
+
const worlds = registry2.list();
|
|
28496
|
+
for (const world of worlds) {
|
|
28497
|
+
if (world.appPortUrls?.some((apu) => apu.hostPort === port)) {
|
|
28498
|
+
return world.id;
|
|
28499
|
+
}
|
|
28500
|
+
}
|
|
28501
|
+
} finally {
|
|
28502
|
+
registry2.close();
|
|
28503
|
+
}
|
|
28504
|
+
} catch {
|
|
28505
|
+
}
|
|
28506
|
+
return void 0;
|
|
28507
|
+
}
|
|
28508
|
+
function validateRunbookPorts(runbook, deps) {
|
|
28509
|
+
if (!runbook.portMap || Object.keys(runbook.portMap).length === 0) {
|
|
28510
|
+
return { conflicts: [] };
|
|
28511
|
+
}
|
|
28512
|
+
const isInUse = deps?.isPortInUse ?? checkPortInUse;
|
|
28513
|
+
const getWorldId = deps?.getOlamWorldForPort ?? getOlamWorldForPortDefault;
|
|
28514
|
+
const conflicts = [];
|
|
28515
|
+
for (const [repoName, svcMap] of Object.entries(runbook.portMap)) {
|
|
28516
|
+
for (const [serviceName, port] of Object.entries(svcMap)) {
|
|
28517
|
+
if (!isInUse(port))
|
|
28518
|
+
continue;
|
|
28519
|
+
const worldId = getWorldId(port);
|
|
28520
|
+
const occupant = worldId ? { type: "olam-world", worldId } : { type: "non-olam", pid: getPidForPort(port) };
|
|
28521
|
+
conflicts.push({ port, repoName, serviceName, occupant });
|
|
28522
|
+
}
|
|
28523
|
+
}
|
|
28524
|
+
return { conflicts };
|
|
28525
|
+
}
|
|
28526
|
+
|
|
28357
28527
|
// ../mcp-server/src/tools/repo.ts
|
|
28358
28528
|
function asMessage4(err) {
|
|
28359
28529
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -28382,9 +28552,9 @@ function register22(server, _ctx, _initError) {
|
|
|
28382
28552
|
description: external_exports.string().optional().describe("Optional human-readable description."),
|
|
28383
28553
|
defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
|
|
28384
28554
|
},
|
|
28385
|
-
async ({ name, path:
|
|
28555
|
+
async ({ name, path: path27, description, defaultBranch }) => {
|
|
28386
28556
|
try {
|
|
28387
|
-
const entry = addRepo({ name, path:
|
|
28557
|
+
const entry = addRepo({ name, path: path27, description, defaultBranch });
|
|
28388
28558
|
return {
|
|
28389
28559
|
content: [{
|
|
28390
28560
|
type: "text",
|
|
@@ -28425,9 +28595,9 @@ function register22(server, _ctx, _initError) {
|
|
|
28425
28595
|
description: external_exports.string().optional().describe("New description."),
|
|
28426
28596
|
defaultBranch: external_exports.string().optional().describe("New default branch.")
|
|
28427
28597
|
},
|
|
28428
|
-
async ({ name, path:
|
|
28598
|
+
async ({ name, path: path27, description, defaultBranch }) => {
|
|
28429
28599
|
try {
|
|
28430
|
-
const entry = updateRepo(name, { path:
|
|
28600
|
+
const entry = updateRepo(name, { path: path27, description, defaultBranch });
|
|
28431
28601
|
return {
|
|
28432
28602
|
content: [{
|
|
28433
28603
|
type: "text",
|
|
@@ -28577,6 +28747,163 @@ function register23(server, _ctx, _initError) {
|
|
|
28577
28747
|
);
|
|
28578
28748
|
}
|
|
28579
28749
|
|
|
28750
|
+
// ../mcp-server/src/tools/runbook.ts
|
|
28751
|
+
var runbook_exports = {};
|
|
28752
|
+
__export(runbook_exports, {
|
|
28753
|
+
register: () => register24
|
|
28754
|
+
});
|
|
28755
|
+
function asMessage6(err) {
|
|
28756
|
+
return err instanceof Error ? err.message : String(err);
|
|
28757
|
+
}
|
|
28758
|
+
function formatConflicts(conflicts) {
|
|
28759
|
+
const lines = conflicts.map((c) => {
|
|
28760
|
+
const occupant = c.occupant.type === "olam-world" ? `in use by world "${c.occupant.worldId}" (olam)` : `in use by PID ${c.occupant.pid ?? "unknown"} (non-olam)`;
|
|
28761
|
+
return ` \u2717 ${c.repoName}.${c.serviceName}:${c.port} \u2014 ${occupant}`;
|
|
28762
|
+
});
|
|
28763
|
+
return lines.join("\n");
|
|
28764
|
+
}
|
|
28765
|
+
function register24(server, ctx, _initError) {
|
|
28766
|
+
server.tool(
|
|
28767
|
+
"olam_runbook_list",
|
|
28768
|
+
"List all runbooks in ~/.olam/config.json. Returns { runbooks: Runbook[] }.",
|
|
28769
|
+
{},
|
|
28770
|
+
async () => {
|
|
28771
|
+
const runbooks = listRunbooks();
|
|
28772
|
+
return {
|
|
28773
|
+
content: [{ type: "text", text: JSON.stringify({ runbooks }, null, 2) }]
|
|
28774
|
+
};
|
|
28775
|
+
}
|
|
28776
|
+
);
|
|
28777
|
+
server.tool(
|
|
28778
|
+
"olam_runbook_show",
|
|
28779
|
+
"Show a single runbook by name. Returns { runbook: Runbook }.",
|
|
28780
|
+
{
|
|
28781
|
+
name: external_exports.string().min(1).describe("Runbook name.")
|
|
28782
|
+
},
|
|
28783
|
+
async ({ name }) => {
|
|
28784
|
+
try {
|
|
28785
|
+
const runbook = getRunbook(name);
|
|
28786
|
+
return {
|
|
28787
|
+
content: [{ type: "text", text: JSON.stringify({ runbook }, null, 2) }]
|
|
28788
|
+
};
|
|
28789
|
+
} catch (err) {
|
|
28790
|
+
return { content: [{ type: "text", text: asMessage6(err) }], isError: true };
|
|
28791
|
+
}
|
|
28792
|
+
}
|
|
28793
|
+
);
|
|
28794
|
+
server.tool(
|
|
28795
|
+
"olam_runbook_add",
|
|
28796
|
+
"Create a new runbook. Validates that all referenced repos exist in the global registry and that portMap has no duplicates.",
|
|
28797
|
+
{
|
|
28798
|
+
name: external_exports.string().min(1).describe("Runbook name (lowercase, digits, dash; 1\u201364 chars)."),
|
|
28799
|
+
repos: external_exports.array(external_exports.string().min(1)).min(1).describe("Repo names (must exist in registry)."),
|
|
28800
|
+
description: external_exports.string().optional().describe("Optional human-readable description."),
|
|
28801
|
+
portMap: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.number().int())).optional().describe("Port mappings: { repoName: { serviceName: hostPort } }."),
|
|
28802
|
+
seeds: external_exports.array(
|
|
28803
|
+
external_exports.union([
|
|
28804
|
+
external_exports.object({ type: external_exports.literal("sql-file"), repo: external_exports.string(), service: external_exports.string(), path: external_exports.string() }),
|
|
28805
|
+
external_exports.object({ type: external_exports.literal("command"), repo: external_exports.string(), run: external_exports.string() }),
|
|
28806
|
+
external_exports.object({ type: external_exports.literal("fixture-copy"), repo: external_exports.string(), src: external_exports.string(), dest: external_exports.string() })
|
|
28807
|
+
])
|
|
28808
|
+
).optional().describe("Optional seed operations to run when applying the runbook."),
|
|
28809
|
+
env: external_exports.record(external_exports.string().min(1), external_exports.record(external_exports.string().min(1), external_exports.string())).optional().describe("Per-repo environment variable overrides.")
|
|
28810
|
+
},
|
|
28811
|
+
async ({ name, repos, description, portMap, seeds, env }) => {
|
|
28812
|
+
try {
|
|
28813
|
+
const runbook = addRunbook({ name, repos, description, portMap, seeds, env });
|
|
28814
|
+
return {
|
|
28815
|
+
content: [{
|
|
28816
|
+
type: "text",
|
|
28817
|
+
text: JSON.stringify({ name: runbook.name, message: `Created runbook "${runbook.name}".` }, null, 2)
|
|
28818
|
+
}]
|
|
28819
|
+
};
|
|
28820
|
+
} catch (err) {
|
|
28821
|
+
return { content: [{ type: "text", text: asMessage6(err) }], isError: true };
|
|
28822
|
+
}
|
|
28823
|
+
}
|
|
28824
|
+
);
|
|
28825
|
+
server.tool(
|
|
28826
|
+
"olam_runbook_remove",
|
|
28827
|
+
"Remove a runbook from the global config. Does not affect any running worlds.",
|
|
28828
|
+
{
|
|
28829
|
+
name: external_exports.string().min(1).describe("Runbook name to remove.")
|
|
28830
|
+
},
|
|
28831
|
+
async ({ name }) => {
|
|
28832
|
+
try {
|
|
28833
|
+
removeRunbook(name);
|
|
28834
|
+
return {
|
|
28835
|
+
content: [{
|
|
28836
|
+
type: "text",
|
|
28837
|
+
text: JSON.stringify({ name, message: `Removed runbook "${name}".` }, null, 2)
|
|
28838
|
+
}]
|
|
28839
|
+
};
|
|
28840
|
+
} catch (err) {
|
|
28841
|
+
return { content: [{ type: "text", text: asMessage6(err) }], isError: true };
|
|
28842
|
+
}
|
|
28843
|
+
}
|
|
28844
|
+
);
|
|
28845
|
+
server.tool(
|
|
28846
|
+
"olam_runbook_apply",
|
|
28847
|
+
"Validate ports then create a world from a runbook. Errors (isError: true) on port conflicts. Returns world metadata on success.",
|
|
28848
|
+
{
|
|
28849
|
+
name: external_exports.string().min(1).describe("Runbook name."),
|
|
28850
|
+
worldName: external_exports.string().optional().describe("Override the world name."),
|
|
28851
|
+
task: external_exports.string().optional().describe("Initial task to dispatch into the world."),
|
|
28852
|
+
branchName: external_exports.string().optional().describe("Override the default branch name.")
|
|
28853
|
+
},
|
|
28854
|
+
async ({ name, worldName, task, branchName }) => {
|
|
28855
|
+
if (!ctx) {
|
|
28856
|
+
return {
|
|
28857
|
+
content: [{ type: "text", text: "Olam is not configured. Run /olam:init to set up." }],
|
|
28858
|
+
isError: true
|
|
28859
|
+
};
|
|
28860
|
+
}
|
|
28861
|
+
let runbook;
|
|
28862
|
+
try {
|
|
28863
|
+
runbook = getRunbook(name);
|
|
28864
|
+
} catch (err) {
|
|
28865
|
+
return { content: [{ type: "text", text: asMessage6(err) }], isError: true };
|
|
28866
|
+
}
|
|
28867
|
+
const { conflicts } = validateRunbookPorts(runbook);
|
|
28868
|
+
if (conflicts.length > 0) {
|
|
28869
|
+
const detail = formatConflicts(conflicts);
|
|
28870
|
+
const msg = `Port conflicts detected for runbook "${name}":
|
|
28871
|
+
${detail}
|
|
28872
|
+
|
|
28873
|
+
${conflicts.length} port conflict(s). Stop the conflicting processes or update portMap in runbook "${name}".`;
|
|
28874
|
+
return {
|
|
28875
|
+
content: [{ type: "text", text: msg }],
|
|
28876
|
+
isError: true
|
|
28877
|
+
};
|
|
28878
|
+
}
|
|
28879
|
+
try {
|
|
28880
|
+
const worldOpts = {
|
|
28881
|
+
name: worldName ?? name,
|
|
28882
|
+
repos: runbook.repos,
|
|
28883
|
+
task: task ?? `Apply runbook "${name}"`,
|
|
28884
|
+
...branchName ? { branchName } : {}
|
|
28885
|
+
};
|
|
28886
|
+
const world = await ctx.worldManager.createWorld(worldOpts);
|
|
28887
|
+
const result = {
|
|
28888
|
+
worldId: world.id,
|
|
28889
|
+
name: world.name,
|
|
28890
|
+
branch: world.branch,
|
|
28891
|
+
status: world.status,
|
|
28892
|
+
repos: world.repos,
|
|
28893
|
+
portOffset: world.portOffset,
|
|
28894
|
+
...world.appPortUrls ? { appPortUrls: world.appPortUrls } : {},
|
|
28895
|
+
message: `World "${world.name}" created from runbook "${name}".`
|
|
28896
|
+
};
|
|
28897
|
+
return {
|
|
28898
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
28899
|
+
};
|
|
28900
|
+
} catch (err) {
|
|
28901
|
+
return { content: [{ type: "text", text: asMessage6(err) }], isError: true };
|
|
28902
|
+
}
|
|
28903
|
+
}
|
|
28904
|
+
);
|
|
28905
|
+
}
|
|
28906
|
+
|
|
28580
28907
|
// ../mcp-server/src/tools/index.ts
|
|
28581
28908
|
var toolModules = [
|
|
28582
28909
|
init_exports,
|
|
@@ -28601,7 +28928,8 @@ var toolModules = [
|
|
|
28601
28928
|
capture_view_exports,
|
|
28602
28929
|
create_from_prompt_exports,
|
|
28603
28930
|
repo_exports,
|
|
28604
|
-
process_port_exports
|
|
28931
|
+
process_port_exports,
|
|
28932
|
+
runbook_exports
|
|
28605
28933
|
];
|
|
28606
28934
|
function registerAllTools(server, ctx, initError) {
|
|
28607
28935
|
for (const mod of toolModules) {
|
|
@@ -28618,7 +28946,7 @@ var SERVER_INSTRUCTIONS = [
|
|
|
28618
28946
|
"Use olam_observe to watch a world's reasoning. Use olam_crystallize to save thoughts.",
|
|
28619
28947
|
"Always olam_destroy_world when done to clean up resources."
|
|
28620
28948
|
].join("\n");
|
|
28621
|
-
function
|
|
28949
|
+
function createServer4(ctx, initError) {
|
|
28622
28950
|
const server = new McpServer(
|
|
28623
28951
|
{ name: SERVER_NAME, version: SERVER_VERSION },
|
|
28624
28952
|
{ instructions: SERVER_INSTRUCTIONS }
|
|
@@ -29098,11 +29426,11 @@ function loadConfig(startDir) {
|
|
|
29098
29426
|
}
|
|
29099
29427
|
|
|
29100
29428
|
// ../core/dist/world/manager.js
|
|
29101
|
-
import * as
|
|
29102
|
-
import { execSync as
|
|
29103
|
-
import * as
|
|
29104
|
-
import * as
|
|
29105
|
-
import * as
|
|
29429
|
+
import * as crypto5 from "node:crypto";
|
|
29430
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
29431
|
+
import * as fs20 from "node:fs";
|
|
29432
|
+
import * as os13 from "node:os";
|
|
29433
|
+
import * as path24 from "node:path";
|
|
29106
29434
|
|
|
29107
29435
|
// ../core/dist/world/state.js
|
|
29108
29436
|
var VALID_TRANSITIONS = {
|
|
@@ -29136,6 +29464,7 @@ var WorldStateMachine = class {
|
|
|
29136
29464
|
};
|
|
29137
29465
|
|
|
29138
29466
|
// ../core/dist/world/devbox-image.js
|
|
29467
|
+
var WORLDSPEC_OVERRIDE_TAG = "worldspec-override";
|
|
29139
29468
|
function selectDevboxImage(config2, repos) {
|
|
29140
29469
|
const selectors = config2.devbox?.image_selectors;
|
|
29141
29470
|
if (!selectors || selectors.length === 0)
|
|
@@ -29147,7 +29476,8 @@ function selectDevboxImage(config2, repos) {
|
|
|
29147
29476
|
return {
|
|
29148
29477
|
image: resolveDevboxImage(config2, sel.tag),
|
|
29149
29478
|
cacheArch: sel.cache_arch,
|
|
29150
|
-
tag: sel.tag
|
|
29479
|
+
tag: sel.tag,
|
|
29480
|
+
source: "image_selector"
|
|
29151
29481
|
};
|
|
29152
29482
|
}
|
|
29153
29483
|
}
|
|
@@ -29168,6 +29498,18 @@ function matches(sel, repoNames, repoTypes) {
|
|
|
29168
29498
|
}
|
|
29169
29499
|
return true;
|
|
29170
29500
|
}
|
|
29501
|
+
function selectDevboxImageForWorld(args) {
|
|
29502
|
+
if (args.worldspec) {
|
|
29503
|
+
return {
|
|
29504
|
+
image: args.worldspec.images.devbox,
|
|
29505
|
+
cacheArch: void 0,
|
|
29506
|
+
// v1 worldspec schema doesn't carry cache_arch
|
|
29507
|
+
tag: WORLDSPEC_OVERRIDE_TAG,
|
|
29508
|
+
source: "worldspec"
|
|
29509
|
+
};
|
|
29510
|
+
}
|
|
29511
|
+
return selectDevboxImage(args.config, args.repos);
|
|
29512
|
+
}
|
|
29171
29513
|
function resolveDevboxImage(config2, tag) {
|
|
29172
29514
|
const registry2 = config2.devbox?.registry;
|
|
29173
29515
|
if (!registry2)
|
|
@@ -29311,8 +29653,8 @@ import * as fs14 from "node:fs";
|
|
|
29311
29653
|
import * as os10 from "node:os";
|
|
29312
29654
|
import * as path17 from "node:path";
|
|
29313
29655
|
var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
29314
|
-
function expandHome(p,
|
|
29315
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
29656
|
+
function expandHome(p, homedir15) {
|
|
29657
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir15());
|
|
29316
29658
|
}
|
|
29317
29659
|
function sanitizeRepoFilename(name) {
|
|
29318
29660
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -29335,7 +29677,7 @@ ${stderr}`;
|
|
|
29335
29677
|
}
|
|
29336
29678
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
29337
29679
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync3(cmd, args, opts));
|
|
29338
|
-
const
|
|
29680
|
+
const homedir15 = deps.homedir ?? (() => os10.homedir());
|
|
29339
29681
|
const baselineDir = path17.join(workspacePath, ".olam", "baseline");
|
|
29340
29682
|
try {
|
|
29341
29683
|
fs14.mkdirSync(baselineDir, { recursive: true });
|
|
@@ -29351,7 +29693,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
29351
29693
|
continue;
|
|
29352
29694
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
29353
29695
|
const outPath = path17.join(baselineDir, filename);
|
|
29354
|
-
const repoPath = expandHome(repo.path,
|
|
29696
|
+
const repoPath = expandHome(repo.path, homedir15);
|
|
29355
29697
|
if (!fs14.existsSync(repoPath)) {
|
|
29356
29698
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
29357
29699
|
# (skipped: path ${repoPath} does not exist)
|
|
@@ -29866,7 +30208,7 @@ async function installStack(exec, repos, stacks) {
|
|
|
29866
30208
|
}
|
|
29867
30209
|
|
|
29868
30210
|
// ../core/dist/world/stack-image.js
|
|
29869
|
-
import { execSync as
|
|
30211
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
29870
30212
|
import * as crypto3 from "node:crypto";
|
|
29871
30213
|
var BASE_IMAGE = "olam-devbox";
|
|
29872
30214
|
var LABEL_PREFIX = "olam.stack-image";
|
|
@@ -29898,7 +30240,7 @@ function lookupCachedImage(runtimes) {
|
|
|
29898
30240
|
const tag = computeImageTag(runtimes);
|
|
29899
30241
|
const imageName = `${BASE_IMAGE}:${tag}`;
|
|
29900
30242
|
try {
|
|
29901
|
-
|
|
30243
|
+
execSync3(`docker image inspect ${imageName} > /dev/null 2>&1`, {
|
|
29902
30244
|
stdio: "pipe",
|
|
29903
30245
|
timeout: 5e3
|
|
29904
30246
|
});
|
|
@@ -29910,14 +30252,14 @@ function lookupCachedImage(runtimes) {
|
|
|
29910
30252
|
function commitAsImage(containerName, imageName) {
|
|
29911
30253
|
const baseDigest = getBaseImageDigest();
|
|
29912
30254
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
29913
|
-
|
|
30255
|
+
execSync3(`docker commit --change 'LABEL ${LABEL_PREFIX}=true' --change 'LABEL ${LABEL_PREFIX}.created-at=${now}' --change 'LABEL ${LABEL_PREFIX}.base-digest=${baseDigest}' ${containerName} ${imageName}`, { stdio: "pipe", timeout: 12e4 });
|
|
29914
30256
|
}
|
|
29915
30257
|
var cachedBaseDigest;
|
|
29916
30258
|
function getBaseImageDigest() {
|
|
29917
30259
|
if (cachedBaseDigest)
|
|
29918
30260
|
return cachedBaseDigest;
|
|
29919
30261
|
try {
|
|
29920
|
-
const digest =
|
|
30262
|
+
const digest = execSync3(`docker inspect ${BASE_IMAGE}:latest --format '{{.Id}}'`, { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
29921
30263
|
cachedBaseDigest = digest.replace("sha256:", "").slice(0, 16);
|
|
29922
30264
|
return cachedBaseDigest;
|
|
29923
30265
|
} catch {
|
|
@@ -30142,6 +30484,9 @@ var SENTINEL_SUFFIX = "-done";
|
|
|
30142
30484
|
function sentinelPath(workdir, index) {
|
|
30143
30485
|
return `${workdir}/${SENTINEL_PREFIX}${index}${SENTINEL_SUFFIX}`;
|
|
30144
30486
|
}
|
|
30487
|
+
function bootstrapStepSentinelPath(workdir, index) {
|
|
30488
|
+
return sentinelPath(workdir, index);
|
|
30489
|
+
}
|
|
30145
30490
|
async function runBootstrap(containerName, workdir, steps, exec, options = {}) {
|
|
30146
30491
|
if (!SAFE_IDENT.test(containerName)) {
|
|
30147
30492
|
throw new Error(`containerName "${containerName}" must match ${SAFE_IDENT} (defensive guard)`);
|
|
@@ -30197,8 +30542,430 @@ function shellQuote(s) {
|
|
|
30197
30542
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
30198
30543
|
}
|
|
30199
30544
|
|
|
30545
|
+
// ../core/dist/world/snapshot.js
|
|
30546
|
+
import * as crypto4 from "node:crypto";
|
|
30547
|
+
import * as fs16 from "node:fs";
|
|
30548
|
+
import * as os11 from "node:os";
|
|
30549
|
+
import * as path19 from "node:path";
|
|
30550
|
+
import { execFileSync as execFileSync4, spawn } from "node:child_process";
|
|
30551
|
+
import { gunzipSync } from "node:zlib";
|
|
30552
|
+
function snapshotsDir() {
|
|
30553
|
+
return process.env["OLAM_SNAPSHOTS_DIR"] ?? path19.join(os11.homedir(), ".olam", "snapshots");
|
|
30554
|
+
}
|
|
30555
|
+
function snapshotKindDirByWorkspace(workspace, arch, kind) {
|
|
30556
|
+
return path19.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
|
|
30557
|
+
}
|
|
30558
|
+
function cleanupLegacyByWorldDir(worldId) {
|
|
30559
|
+
const legacyDir = path19.join(snapshotsDir(), worldId);
|
|
30560
|
+
if (worldId === "by-workspace")
|
|
30561
|
+
return;
|
|
30562
|
+
if (!fs16.existsSync(legacyDir))
|
|
30563
|
+
return;
|
|
30564
|
+
try {
|
|
30565
|
+
fs16.rmSync(legacyDir, { recursive: true, force: true });
|
|
30566
|
+
} catch {
|
|
30567
|
+
}
|
|
30568
|
+
}
|
|
30569
|
+
function manifestPath(tarPath) {
|
|
30570
|
+
return tarPath.replace(/\.tar\.gz$/, ".manifest.json");
|
|
30571
|
+
}
|
|
30572
|
+
function hashBuffers(entries) {
|
|
30573
|
+
const sorted = [...entries].sort((a, b) => a.path.localeCompare(b.path));
|
|
30574
|
+
const hash = crypto4.createHash("sha256");
|
|
30575
|
+
for (const entry of sorted) {
|
|
30576
|
+
hash.update(entry.path);
|
|
30577
|
+
hash.update("\0");
|
|
30578
|
+
hash.update(entry.content);
|
|
30579
|
+
hash.update("\0");
|
|
30580
|
+
}
|
|
30581
|
+
return hash.digest("hex").slice(0, 12);
|
|
30582
|
+
}
|
|
30583
|
+
function computeGemsFingerprint(repoDir, imageDigest) {
|
|
30584
|
+
const lockfile = path19.join(repoDir, "Gemfile.lock");
|
|
30585
|
+
if (!fs16.existsSync(lockfile))
|
|
30586
|
+
return null;
|
|
30587
|
+
const entries = [
|
|
30588
|
+
{ path: "Gemfile.lock", content: fs16.readFileSync(lockfile) }
|
|
30589
|
+
];
|
|
30590
|
+
if (imageDigest) {
|
|
30591
|
+
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
30592
|
+
}
|
|
30593
|
+
return hashBuffers(entries);
|
|
30594
|
+
}
|
|
30595
|
+
function computeNodeFingerprint(repoDir, imageDigest) {
|
|
30596
|
+
const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
|
|
30597
|
+
for (const name of candidates) {
|
|
30598
|
+
const lockfile = path19.join(repoDir, name);
|
|
30599
|
+
if (fs16.existsSync(lockfile)) {
|
|
30600
|
+
const entries = [
|
|
30601
|
+
{ path: name, content: fs16.readFileSync(lockfile) }
|
|
30602
|
+
];
|
|
30603
|
+
if (imageDigest) {
|
|
30604
|
+
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
30605
|
+
}
|
|
30606
|
+
return hashBuffers(entries);
|
|
30607
|
+
}
|
|
30608
|
+
}
|
|
30609
|
+
return null;
|
|
30610
|
+
}
|
|
30611
|
+
function unpackTarballAtomic(srcPath, destDir) {
|
|
30612
|
+
const validation = enumerateAndValidateTarballEntries(srcPath, destDir);
|
|
30613
|
+
if (!validation.valid) {
|
|
30614
|
+
return {
|
|
30615
|
+
ok: false,
|
|
30616
|
+
reason: validation.reason,
|
|
30617
|
+
detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
|
|
30618
|
+
};
|
|
30619
|
+
}
|
|
30620
|
+
const parent = path19.dirname(destDir);
|
|
30621
|
+
fs16.mkdirSync(parent, { recursive: true });
|
|
30622
|
+
const tmpSuffix = `.tmp-${process.pid}-${crypto4.randomBytes(4).toString("hex")}`;
|
|
30623
|
+
const tmpDir = `${destDir}${tmpSuffix}`;
|
|
30624
|
+
try {
|
|
30625
|
+
fs16.mkdirSync(tmpDir, { recursive: true });
|
|
30626
|
+
execFileSync4("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
|
|
30627
|
+
fs16.renameSync(tmpDir, destDir);
|
|
30628
|
+
return { ok: true, entryCount: validation.entries.length };
|
|
30629
|
+
} catch (err) {
|
|
30630
|
+
try {
|
|
30631
|
+
fs16.rmSync(tmpDir, { recursive: true, force: true });
|
|
30632
|
+
} catch {
|
|
30633
|
+
}
|
|
30634
|
+
return {
|
|
30635
|
+
ok: false,
|
|
30636
|
+
reason: "extract-error",
|
|
30637
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
30638
|
+
};
|
|
30639
|
+
}
|
|
30640
|
+
}
|
|
30641
|
+
function resolvesWithin(base, target) {
|
|
30642
|
+
const resolved = path19.resolve(base, target);
|
|
30643
|
+
const baseResolved = path19.resolve(base);
|
|
30644
|
+
const rel = path19.relative(baseResolved, resolved);
|
|
30645
|
+
if (rel === "")
|
|
30646
|
+
return true;
|
|
30647
|
+
return !rel.startsWith("..") && !path19.isAbsolute(rel);
|
|
30648
|
+
}
|
|
30649
|
+
var TYPE_CHAR_TO_TYPE = {
|
|
30650
|
+
"-": "file",
|
|
30651
|
+
"d": "dir",
|
|
30652
|
+
"l": "symlink",
|
|
30653
|
+
"h": "hardlink"
|
|
30654
|
+
};
|
|
30655
|
+
var DATE_MARKER_RE = /(?:\d{1,2}:\d{2}|(?:19|20)\d{2})\s+(.+)$/;
|
|
30656
|
+
function parseTarListLine(line) {
|
|
30657
|
+
const trimmed = line.trimEnd();
|
|
30658
|
+
if (trimmed.length === 0)
|
|
30659
|
+
return null;
|
|
30660
|
+
const typeChar = trimmed[0];
|
|
30661
|
+
if (typeChar === void 0)
|
|
30662
|
+
return null;
|
|
30663
|
+
const type = TYPE_CHAR_TO_TYPE[typeChar];
|
|
30664
|
+
if (!type)
|
|
30665
|
+
return null;
|
|
30666
|
+
const match = trimmed.match(DATE_MARKER_RE);
|
|
30667
|
+
if (!match)
|
|
30668
|
+
return null;
|
|
30669
|
+
const remainderRaw = match[1];
|
|
30670
|
+
if (remainderRaw === void 0)
|
|
30671
|
+
return null;
|
|
30672
|
+
let remainder = remainderRaw;
|
|
30673
|
+
if (remainder.startsWith("./"))
|
|
30674
|
+
remainder = remainder.slice(2);
|
|
30675
|
+
const symlinkSplit = remainder.indexOf(" -> ");
|
|
30676
|
+
if (type === "symlink" && symlinkSplit !== -1) {
|
|
30677
|
+
return {
|
|
30678
|
+
type: "symlink",
|
|
30679
|
+
name: remainder.slice(0, symlinkSplit),
|
|
30680
|
+
linkname: remainder.slice(symlinkSplit + 4)
|
|
30681
|
+
};
|
|
30682
|
+
}
|
|
30683
|
+
const hardlinkMarker = " link to ";
|
|
30684
|
+
const hardlinkSplit = remainder.indexOf(hardlinkMarker);
|
|
30685
|
+
if (type === "hardlink" && hardlinkSplit !== -1) {
|
|
30686
|
+
return {
|
|
30687
|
+
type: "hardlink",
|
|
30688
|
+
name: remainder.slice(0, hardlinkSplit),
|
|
30689
|
+
linkname: remainder.slice(hardlinkSplit + hardlinkMarker.length)
|
|
30690
|
+
};
|
|
30691
|
+
}
|
|
30692
|
+
return { type, name: remainder };
|
|
30693
|
+
}
|
|
30694
|
+
function validateHardlinksBinary(tarPath, targetDir) {
|
|
30695
|
+
let raw;
|
|
30696
|
+
try {
|
|
30697
|
+
raw = gunzipSync(fs16.readFileSync(tarPath));
|
|
30698
|
+
} catch {
|
|
30699
|
+
return null;
|
|
30700
|
+
}
|
|
30701
|
+
let offset = 0;
|
|
30702
|
+
while (offset + 512 <= raw.length) {
|
|
30703
|
+
const block = raw.subarray(offset, offset + 512);
|
|
30704
|
+
if (!block.some((b) => b !== 0))
|
|
30705
|
+
break;
|
|
30706
|
+
const typeflag = block[156] !== void 0 ? String.fromCharCode(block[156]) : "";
|
|
30707
|
+
if (typeflag === "1") {
|
|
30708
|
+
const nameNull = block.indexOf(0, 0);
|
|
30709
|
+
const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
|
|
30710
|
+
const linkNull = block.indexOf(0, 157);
|
|
30711
|
+
const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
|
|
30712
|
+
if (linkname && (path19.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
|
|
30713
|
+
return {
|
|
30714
|
+
valid: false,
|
|
30715
|
+
reason: "hardlink-escape",
|
|
30716
|
+
unsafePath: name || tarPath,
|
|
30717
|
+
detail: `linkname=${linkname} resolves outside targetDir`
|
|
30718
|
+
};
|
|
30719
|
+
}
|
|
30720
|
+
}
|
|
30721
|
+
const sizeRaw = block.subarray(124, 136).toString("utf-8").replace(/[\0 ]/g, "");
|
|
30722
|
+
const size = sizeRaw ? parseInt(sizeRaw, 8) : 0;
|
|
30723
|
+
offset += (1 + Math.ceil((isNaN(size) ? 0 : size) / 512)) * 512;
|
|
30724
|
+
}
|
|
30725
|
+
return null;
|
|
30726
|
+
}
|
|
30727
|
+
function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
30728
|
+
let raw;
|
|
30729
|
+
try {
|
|
30730
|
+
raw = execFileSync4("tar", ["-tvf", tarPath], {
|
|
30731
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
30732
|
+
env: { ...process.env, LC_ALL: "C", TZ: "UTC" },
|
|
30733
|
+
encoding: "utf-8",
|
|
30734
|
+
maxBuffer: 64 * 1024 * 1024
|
|
30735
|
+
// 64 MiB ceiling for very large tarballs
|
|
30736
|
+
});
|
|
30737
|
+
} catch (err) {
|
|
30738
|
+
return {
|
|
30739
|
+
valid: false,
|
|
30740
|
+
reason: "parse-error",
|
|
30741
|
+
unsafePath: tarPath,
|
|
30742
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
30743
|
+
};
|
|
30744
|
+
}
|
|
30745
|
+
const entries = [];
|
|
30746
|
+
for (const line of raw.split("\n")) {
|
|
30747
|
+
const entry = parseTarListLine(line);
|
|
30748
|
+
if (!entry)
|
|
30749
|
+
continue;
|
|
30750
|
+
if (path19.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
|
|
30751
|
+
return {
|
|
30752
|
+
valid: false,
|
|
30753
|
+
reason: "path-traversal",
|
|
30754
|
+
unsafePath: entry.name
|
|
30755
|
+
};
|
|
30756
|
+
}
|
|
30757
|
+
if (entry.type === "symlink" && entry.linkname !== void 0) {
|
|
30758
|
+
const symlinkParent = path19.join(targetDir, path19.dirname(entry.name));
|
|
30759
|
+
if (path19.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path19.join(path19.dirname(entry.name), entry.linkname))) {
|
|
30760
|
+
return {
|
|
30761
|
+
valid: false,
|
|
30762
|
+
reason: "symlink-escape",
|
|
30763
|
+
unsafePath: entry.name,
|
|
30764
|
+
detail: `linkname=${entry.linkname} resolves outside ${symlinkParent}`
|
|
30765
|
+
};
|
|
30766
|
+
}
|
|
30767
|
+
}
|
|
30768
|
+
if (entry.type === "hardlink" && entry.linkname !== void 0) {
|
|
30769
|
+
if (path19.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
|
|
30770
|
+
return {
|
|
30771
|
+
valid: false,
|
|
30772
|
+
reason: "hardlink-escape",
|
|
30773
|
+
unsafePath: entry.name,
|
|
30774
|
+
detail: `linkname=${entry.linkname} resolves outside targetDir`
|
|
30775
|
+
};
|
|
30776
|
+
}
|
|
30777
|
+
}
|
|
30778
|
+
entries.push(entry);
|
|
30779
|
+
}
|
|
30780
|
+
const hardlinkResult = validateHardlinksBinary(tarPath, targetDir);
|
|
30781
|
+
if (hardlinkResult !== null)
|
|
30782
|
+
return hardlinkResult;
|
|
30783
|
+
return { valid: true, entries };
|
|
30784
|
+
}
|
|
30785
|
+
var KINDS_BY_REPO = [
|
|
30786
|
+
{ kind: "gems", targetSubpath: "vendor/bundle", computeFp: computeGemsFingerprint },
|
|
30787
|
+
{ kind: "node", targetSubpath: "node_modules", computeFp: computeNodeFingerprint }
|
|
30788
|
+
];
|
|
30789
|
+
function restoreSnapshotsForRepos(input) {
|
|
30790
|
+
const restored = /* @__PURE__ */ new Map();
|
|
30791
|
+
const outcomes = [];
|
|
30792
|
+
for (const repo of input.repos) {
|
|
30793
|
+
const repoRestored = [];
|
|
30794
|
+
for (const { kind, targetSubpath, computeFp } of KINDS_BY_REPO) {
|
|
30795
|
+
const fingerprint = computeFp(repo.worktreeDir, input.imageDigest);
|
|
30796
|
+
if (!fingerprint) {
|
|
30797
|
+
outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-lockfile" });
|
|
30798
|
+
continue;
|
|
30799
|
+
}
|
|
30800
|
+
const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
|
|
30801
|
+
const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
|
|
30802
|
+
const tarPath = path19.join(archDir, tarFilename);
|
|
30803
|
+
if (!fs16.existsSync(tarPath)) {
|
|
30804
|
+
outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
|
|
30805
|
+
continue;
|
|
30806
|
+
}
|
|
30807
|
+
const manifest = readManifest(tarPath);
|
|
30808
|
+
if (!manifest || manifest.arch !== input.arch) {
|
|
30809
|
+
outcomes.push({
|
|
30810
|
+
repo: repo.name,
|
|
30811
|
+
kind,
|
|
30812
|
+
outcome: "refused",
|
|
30813
|
+
reason: "arch-mismatch",
|
|
30814
|
+
fingerprint
|
|
30815
|
+
});
|
|
30816
|
+
continue;
|
|
30817
|
+
}
|
|
30818
|
+
const targetDir = path19.join(repo.worktreeDir, targetSubpath);
|
|
30819
|
+
try {
|
|
30820
|
+
fs16.rmSync(targetDir, { recursive: true, force: true });
|
|
30821
|
+
} catch {
|
|
30822
|
+
}
|
|
30823
|
+
const result = unpackTarballAtomic(tarPath, targetDir);
|
|
30824
|
+
if (!result.ok) {
|
|
30825
|
+
outcomes.push({
|
|
30826
|
+
repo: repo.name,
|
|
30827
|
+
kind,
|
|
30828
|
+
outcome: "refused",
|
|
30829
|
+
reason: result.reason,
|
|
30830
|
+
fingerprint
|
|
30831
|
+
});
|
|
30832
|
+
try {
|
|
30833
|
+
fs16.rmSync(tarPath, { force: true });
|
|
30834
|
+
fs16.rmSync(manifestPath(tarPath), { force: true });
|
|
30835
|
+
} catch {
|
|
30836
|
+
}
|
|
30837
|
+
continue;
|
|
30838
|
+
}
|
|
30839
|
+
outcomes.push({ repo: repo.name, kind, outcome: "hit", fingerprint });
|
|
30840
|
+
repoRestored.push(kind);
|
|
30841
|
+
}
|
|
30842
|
+
if (repoRestored.length > 0) {
|
|
30843
|
+
restored.set(repo.name, repoRestored);
|
|
30844
|
+
}
|
|
30845
|
+
}
|
|
30846
|
+
return { restored, outcomes };
|
|
30847
|
+
}
|
|
30848
|
+
function readManifest(tarPath) {
|
|
30849
|
+
const mPath = manifestPath(tarPath);
|
|
30850
|
+
if (!fs16.existsSync(mPath))
|
|
30851
|
+
return null;
|
|
30852
|
+
try {
|
|
30853
|
+
return JSON.parse(fs16.readFileSync(mPath, "utf-8"));
|
|
30854
|
+
} catch {
|
|
30855
|
+
return null;
|
|
30856
|
+
}
|
|
30857
|
+
}
|
|
30858
|
+
var EVICT_LOCK_FILENAME = ".evict.lock";
|
|
30859
|
+
function isPidAlive(pid) {
|
|
30860
|
+
try {
|
|
30861
|
+
process.kill(pid, 0);
|
|
30862
|
+
return true;
|
|
30863
|
+
} catch {
|
|
30864
|
+
return false;
|
|
30865
|
+
}
|
|
30866
|
+
}
|
|
30867
|
+
function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
30868
|
+
fs16.mkdirSync(dir, { recursive: true });
|
|
30869
|
+
const lockPath = path19.join(dir, EVICT_LOCK_FILENAME);
|
|
30870
|
+
let fd;
|
|
30871
|
+
try {
|
|
30872
|
+
fd = fs16.openSync(lockPath, fs16.constants.O_WRONLY | fs16.constants.O_CREAT | fs16.constants.O_EXCL, 384);
|
|
30873
|
+
} catch (err) {
|
|
30874
|
+
if (err.code !== "EEXIST")
|
|
30875
|
+
return 0;
|
|
30876
|
+
let holderPid = null;
|
|
30877
|
+
try {
|
|
30878
|
+
holderPid = parseInt(fs16.readFileSync(lockPath, "utf-8").trim(), 10);
|
|
30879
|
+
} catch {
|
|
30880
|
+
holderPid = null;
|
|
30881
|
+
}
|
|
30882
|
+
if (holderPid && Number.isInteger(holderPid) && isPidAlive(holderPid)) {
|
|
30883
|
+
return 0;
|
|
30884
|
+
}
|
|
30885
|
+
try {
|
|
30886
|
+
fs16.unlinkSync(lockPath);
|
|
30887
|
+
fd = fs16.openSync(lockPath, fs16.constants.O_WRONLY | fs16.constants.O_CREAT | fs16.constants.O_EXCL, 384);
|
|
30888
|
+
} catch {
|
|
30889
|
+
return 0;
|
|
30890
|
+
}
|
|
30891
|
+
}
|
|
30892
|
+
try {
|
|
30893
|
+
fs16.writeSync(fd, `${process.pid}
|
|
30894
|
+
`);
|
|
30895
|
+
} finally {
|
|
30896
|
+
fs16.closeSync(fd);
|
|
30897
|
+
}
|
|
30898
|
+
try {
|
|
30899
|
+
return evictOldSnapshots(maxBytes, dir);
|
|
30900
|
+
} finally {
|
|
30901
|
+
try {
|
|
30902
|
+
fs16.unlinkSync(lockPath);
|
|
30903
|
+
} catch {
|
|
30904
|
+
}
|
|
30905
|
+
}
|
|
30906
|
+
}
|
|
30907
|
+
function spawnAutoCapture(worldId, olamBin = "olam") {
|
|
30908
|
+
if (process.env["OLAM_SNAPSHOT_AUTO_CAPTURE"] === "0")
|
|
30909
|
+
return null;
|
|
30910
|
+
if (!/^[a-zA-Z0-9_\-.]+$/.test(worldId))
|
|
30911
|
+
return null;
|
|
30912
|
+
try {
|
|
30913
|
+
const child = spawn(olamBin, ["world", "snapshot", "create", worldId, "--kind", "all"], {
|
|
30914
|
+
detached: true,
|
|
30915
|
+
stdio: "ignore",
|
|
30916
|
+
// OLAM_INTERNAL_SNAPSHOT=1 sentinel — Phase D D1's deprecation
|
|
30917
|
+
// counter (in packages/cli/src/commands/world-snapshot.ts) skips
|
|
30918
|
+
// the bump when this env var is set. Preserves D22 signal
|
|
30919
|
+
// integrity: the counter measures operator-driven invocations
|
|
30920
|
+
// only, not auto-capture-triggered ones. See CP3 review HIGH
|
|
30921
|
+
// finding for context.
|
|
30922
|
+
env: {
|
|
30923
|
+
...process.env,
|
|
30924
|
+
OLAM_INTERNAL_SNAPSHOT: "1",
|
|
30925
|
+
NODE_OPTIONS: process.env["NODE_OPTIONS"] ?? ""
|
|
30926
|
+
}
|
|
30927
|
+
});
|
|
30928
|
+
child.unref();
|
|
30929
|
+
return child.pid ?? null;
|
|
30930
|
+
} catch {
|
|
30931
|
+
return null;
|
|
30932
|
+
}
|
|
30933
|
+
}
|
|
30934
|
+
function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
30935
|
+
if (!fs16.existsSync(dir))
|
|
30936
|
+
return 0;
|
|
30937
|
+
const allTars = [];
|
|
30938
|
+
const walk = (d) => {
|
|
30939
|
+
for (const entry of fs16.readdirSync(d, { withFileTypes: true })) {
|
|
30940
|
+
const full = path19.join(d, entry.name);
|
|
30941
|
+
if (entry.isDirectory()) {
|
|
30942
|
+
walk(full);
|
|
30943
|
+
} else if (entry.name.endsWith(".tar.gz")) {
|
|
30944
|
+
const stat = fs16.statSync(full);
|
|
30945
|
+
allTars.push({ path: full, size: stat.size, mtime: stat.mtimeMs });
|
|
30946
|
+
}
|
|
30947
|
+
}
|
|
30948
|
+
};
|
|
30949
|
+
walk(dir);
|
|
30950
|
+
const total = allTars.reduce((acc, t) => acc + t.size, 0);
|
|
30951
|
+
if (total <= maxBytes)
|
|
30952
|
+
return 0;
|
|
30953
|
+
allTars.sort((a, b) => a.mtime - b.mtime);
|
|
30954
|
+
let freed = 0;
|
|
30955
|
+
let remaining = total;
|
|
30956
|
+
for (const tar of allTars) {
|
|
30957
|
+
if (remaining <= maxBytes)
|
|
30958
|
+
break;
|
|
30959
|
+
fs16.rmSync(tar.path, { force: true });
|
|
30960
|
+
fs16.rmSync(manifestPath(tar.path), { force: true });
|
|
30961
|
+
freed += tar.size;
|
|
30962
|
+
remaining -= tar.size;
|
|
30963
|
+
}
|
|
30964
|
+
return freed;
|
|
30965
|
+
}
|
|
30966
|
+
|
|
30200
30967
|
// ../core/dist/world/secrets-fetcher.js
|
|
30201
|
-
import { execSync as
|
|
30968
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
30202
30969
|
function parseGcpSecretUrl(url) {
|
|
30203
30970
|
if (!url.startsWith("gcp://"))
|
|
30204
30971
|
return null;
|
|
@@ -30213,7 +30980,7 @@ function parseGcpSecretUrl(url) {
|
|
|
30213
30980
|
return { project, secretName };
|
|
30214
30981
|
}
|
|
30215
30982
|
function defaultExecFn(cmd, opts) {
|
|
30216
|
-
return
|
|
30983
|
+
return execSync4(cmd, { encoding: "utf-8", timeout: opts?.timeout ?? 15e3 });
|
|
30217
30984
|
}
|
|
30218
30985
|
function fetchGcpSecret(ref, execFn = defaultExecFn) {
|
|
30219
30986
|
const { project, secretName } = ref;
|
|
@@ -30306,14 +31073,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
|
|
|
30306
31073
|
}
|
|
30307
31074
|
|
|
30308
31075
|
// ../core/dist/world/olam-yaml.js
|
|
30309
|
-
import * as
|
|
31076
|
+
import * as path20 from "node:path";
|
|
30310
31077
|
import YAML2 from "yaml";
|
|
30311
31078
|
function enrichReposWithManifests(repos, workspacePath) {
|
|
30312
31079
|
return repos.map((repo) => {
|
|
30313
31080
|
if (repo.manifest !== void 0 && repo.manifest !== null) {
|
|
30314
31081
|
return repo;
|
|
30315
31082
|
}
|
|
30316
|
-
const repoDir =
|
|
31083
|
+
const repoDir = path20.join(workspacePath, repo.name);
|
|
30317
31084
|
let manifest = null;
|
|
30318
31085
|
try {
|
|
30319
31086
|
manifest = loadRepoManifest(repoDir);
|
|
@@ -30328,8 +31095,8 @@ function enrichReposWithManifests(repos, workspacePath) {
|
|
|
30328
31095
|
}
|
|
30329
31096
|
|
|
30330
31097
|
// ../core/dist/policies/loader.js
|
|
30331
|
-
import * as
|
|
30332
|
-
import * as
|
|
31098
|
+
import * as fs17 from "node:fs";
|
|
31099
|
+
import * as path21 from "node:path";
|
|
30333
31100
|
import { parse as parseYaml3 } from "yaml";
|
|
30334
31101
|
function parseFrontmatter(content) {
|
|
30335
31102
|
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
|
|
@@ -30349,20 +31116,20 @@ function toStringArray(v) {
|
|
|
30349
31116
|
return v.filter((x) => typeof x === "string");
|
|
30350
31117
|
}
|
|
30351
31118
|
function loadPolicies(workspaceRoot) {
|
|
30352
|
-
const policiesDir =
|
|
30353
|
-
if (!
|
|
31119
|
+
const policiesDir = path21.join(workspaceRoot, ".olam", "policies");
|
|
31120
|
+
if (!fs17.existsSync(policiesDir))
|
|
30354
31121
|
return [];
|
|
30355
31122
|
let files;
|
|
30356
31123
|
try {
|
|
30357
|
-
files =
|
|
31124
|
+
files = fs17.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
|
|
30358
31125
|
} catch {
|
|
30359
31126
|
return [];
|
|
30360
31127
|
}
|
|
30361
31128
|
const policies = [];
|
|
30362
31129
|
for (const file of files) {
|
|
30363
|
-
const filePath =
|
|
31130
|
+
const filePath = path21.join(policiesDir, file);
|
|
30364
31131
|
try {
|
|
30365
|
-
const content =
|
|
31132
|
+
const content = fs17.readFileSync(filePath, "utf8");
|
|
30366
31133
|
const parsed = parseFrontmatter(content);
|
|
30367
31134
|
if (!parsed) {
|
|
30368
31135
|
console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
|
|
@@ -30412,17 +31179,93 @@ function formatPoliciesBrief(policies) {
|
|
|
30412
31179
|
return lines.join("\n");
|
|
30413
31180
|
}
|
|
30414
31181
|
|
|
31182
|
+
// ../core/dist/global-config/runbook-resolver.js
|
|
31183
|
+
import * as fs18 from "node:fs";
|
|
31184
|
+
import * as os12 from "node:os";
|
|
31185
|
+
import * as path22 from "node:path";
|
|
31186
|
+
function expandTilde(p) {
|
|
31187
|
+
if (p === "~" || p.startsWith("~/")) {
|
|
31188
|
+
return path22.join(os12.homedir(), p.slice(1));
|
|
31189
|
+
}
|
|
31190
|
+
return p;
|
|
31191
|
+
}
|
|
31192
|
+
function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
31193
|
+
const registryMap = new Map(repoRegistry.map((r) => [r.name, r]));
|
|
31194
|
+
for (const repoName of runbook.repos) {
|
|
31195
|
+
const entry = registryMap.get(repoName);
|
|
31196
|
+
if (!entry) {
|
|
31197
|
+
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.`);
|
|
31198
|
+
}
|
|
31199
|
+
const resolvedPath = expandTilde(entry.path);
|
|
31200
|
+
if (!fs18.existsSync(resolvedPath)) {
|
|
31201
|
+
throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
|
|
31202
|
+
}
|
|
31203
|
+
}
|
|
31204
|
+
return {
|
|
31205
|
+
repoNames: [...runbook.repos],
|
|
31206
|
+
portOverrides: runbook.portMap ?? {},
|
|
31207
|
+
envOverrides: runbook.env ?? {},
|
|
31208
|
+
seeds: runbook.seeds
|
|
31209
|
+
};
|
|
31210
|
+
}
|
|
31211
|
+
|
|
31212
|
+
// ../core/dist/world/bootstrap-hooks.js
|
|
31213
|
+
import * as fs19 from "node:fs";
|
|
31214
|
+
import * as path23 from "node:path";
|
|
31215
|
+
function runFixtureCopySeeds(seeds, workspacePath) {
|
|
31216
|
+
if (!seeds)
|
|
31217
|
+
return;
|
|
31218
|
+
for (const seed of seeds) {
|
|
31219
|
+
if (seed.type !== "fixture-copy")
|
|
31220
|
+
continue;
|
|
31221
|
+
const srcAbs = path23.resolve(workspacePath, seed.repo, seed.src);
|
|
31222
|
+
const destAbs = path23.resolve(workspacePath, seed.repo, seed.dest);
|
|
31223
|
+
const destDir = path23.dirname(destAbs);
|
|
31224
|
+
fs19.mkdirSync(destDir, { recursive: true });
|
|
31225
|
+
fs19.cpSync(srcAbs, destAbs, { recursive: true, force: true });
|
|
31226
|
+
}
|
|
31227
|
+
}
|
|
31228
|
+
async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
|
|
31229
|
+
if (!seeds)
|
|
31230
|
+
return;
|
|
31231
|
+
for (const seed of seeds) {
|
|
31232
|
+
if (seed.type === "fixture-copy")
|
|
31233
|
+
continue;
|
|
31234
|
+
if (seed.type === "sql-file") {
|
|
31235
|
+
const servicePorts = servicePortMap[seed.repo] ?? {};
|
|
31236
|
+
const port = servicePorts[seed.service] ?? 5432;
|
|
31237
|
+
const waitCmd = `until pg_isready -h localhost -p ${port} -t 1 2>/dev/null; do sleep 2; done`;
|
|
31238
|
+
const psqlCmd = `psql -h localhost -p ${port} -f /home/olam/workspace/${seed.repo}/${seed.path}`;
|
|
31239
|
+
const combined = `${waitCmd} && ${psqlCmd}`;
|
|
31240
|
+
try {
|
|
31241
|
+
exec(containerName, combined);
|
|
31242
|
+
} catch (err) {
|
|
31243
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
31244
|
+
throw new Error(`seed failed for repo "${seed.repo}" (type: sql-file, service: "${seed.service}", path: "${seed.path}"): ${msg}`);
|
|
31245
|
+
}
|
|
31246
|
+
} else if (seed.type === "command") {
|
|
31247
|
+
const workdir = `/home/olam/workspace/${seed.repo}`;
|
|
31248
|
+
try {
|
|
31249
|
+
exec(containerName, `cd ${workdir} && ${seed.run}`);
|
|
31250
|
+
} catch (err) {
|
|
31251
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
31252
|
+
throw new Error(`seed failed for repo "${seed.repo}" (type: command, run: "${seed.run}"): ${msg}`);
|
|
31253
|
+
}
|
|
31254
|
+
}
|
|
31255
|
+
}
|
|
31256
|
+
}
|
|
31257
|
+
|
|
30415
31258
|
// ../core/dist/world/tmux-supervisor.js
|
|
30416
31259
|
var PortInUseError = class extends Error {
|
|
30417
31260
|
port;
|
|
30418
31261
|
repo;
|
|
30419
31262
|
manifestPath;
|
|
30420
|
-
constructor(port, repo,
|
|
30421
|
-
super(`Port ${port} already in use on host (claimed by repo "${repo}"). Free the port or change \`app_port\` in ${
|
|
31263
|
+
constructor(port, repo, manifestPath2) {
|
|
31264
|
+
super(`Port ${port} already in use on host (claimed by repo "${repo}"). Free the port or change \`app_port\` in ${manifestPath2}.`);
|
|
30422
31265
|
this.name = "PortInUseError";
|
|
30423
31266
|
this.port = port;
|
|
30424
31267
|
this.repo = repo;
|
|
30425
|
-
this.manifestPath =
|
|
31268
|
+
this.manifestPath = manifestPath2;
|
|
30426
31269
|
}
|
|
30427
31270
|
};
|
|
30428
31271
|
var SAFE_IDENT2 = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
@@ -30517,7 +31360,7 @@ var BotIdentityError = class extends Error {
|
|
|
30517
31360
|
this.name = "BotIdentityError";
|
|
30518
31361
|
}
|
|
30519
31362
|
};
|
|
30520
|
-
function getTokenScopes(ghToken, _exec =
|
|
31363
|
+
function getTokenScopes(ghToken, _exec = execSync5) {
|
|
30521
31364
|
try {
|
|
30522
31365
|
const out = _exec("gh auth status 2>&1", {
|
|
30523
31366
|
encoding: "utf-8",
|
|
@@ -30534,13 +31377,13 @@ function getTokenScopes(ghToken, _exec = execSync4) {
|
|
|
30534
31377
|
}
|
|
30535
31378
|
}
|
|
30536
31379
|
async function setupContainerGit(containerName, repos, branch) {
|
|
30537
|
-
const dockerExec = (cmd) =>
|
|
31380
|
+
const dockerExec = (cmd) => execSync5(`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`, {
|
|
30538
31381
|
stdio: "pipe",
|
|
30539
31382
|
timeout: 6e4
|
|
30540
31383
|
}).toString();
|
|
30541
31384
|
let ghToken = "";
|
|
30542
31385
|
try {
|
|
30543
|
-
ghToken =
|
|
31386
|
+
ghToken = execSync5("gh auth token 2>/dev/null", { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
30544
31387
|
} catch {
|
|
30545
31388
|
}
|
|
30546
31389
|
const actorName = process.env.OLAM_BOT_NAME ?? "Claude Code (olam)";
|
|
@@ -30560,7 +31403,7 @@ async function setupContainerGit(containerName, repos, branch) {
|
|
|
30560
31403
|
continue;
|
|
30561
31404
|
const ownerRepo = ghMatch[1];
|
|
30562
31405
|
try {
|
|
30563
|
-
|
|
31406
|
+
execSync5(`gh api repos/${ownerRepo} --silent`, {
|
|
30564
31407
|
stdio: "pipe",
|
|
30565
31408
|
timeout: 5e3,
|
|
30566
31409
|
env: { ...process.env, GH_TOKEN: ghToken }
|
|
@@ -30608,8 +31451,8 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
|
|
|
30608
31451
|
if (!olamUserPresent) {
|
|
30609
31452
|
const imageName = (() => {
|
|
30610
31453
|
try {
|
|
30611
|
-
const { execSync:
|
|
30612
|
-
return
|
|
31454
|
+
const { execSync: execSync7 } = __require("node:child_process");
|
|
31455
|
+
return execSync7(`docker inspect ${containerName} --format '{{.Config.Image}}'`, {
|
|
30613
31456
|
encoding: "utf8",
|
|
30614
31457
|
timeout: 5e3
|
|
30615
31458
|
}).trim() || "(unknown)";
|
|
@@ -30652,7 +31495,7 @@ ${stderr.split("\n").slice(0, 3).join(" ")}`);
|
|
|
30652
31495
|
function makeHostExecFn() {
|
|
30653
31496
|
return async (cmd) => {
|
|
30654
31497
|
try {
|
|
30655
|
-
const stdout =
|
|
31498
|
+
const stdout = execSync5(cmd, { encoding: "utf-8", timeout: 5e3 });
|
|
30656
31499
|
return { stdout, stderr: "", exitCode: 0 };
|
|
30657
31500
|
} catch {
|
|
30658
31501
|
return { stdout: "", stderr: "", exitCode: 1 };
|
|
@@ -30662,7 +31505,7 @@ function makeHostExecFn() {
|
|
|
30662
31505
|
function makeContainerExecFn(containerName) {
|
|
30663
31506
|
return async (cmd) => {
|
|
30664
31507
|
try {
|
|
30665
|
-
const result =
|
|
31508
|
+
const result = execSync5(`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
|
|
30666
31509
|
return { stdout: result.toString(), stderr: "", exitCode: 0 };
|
|
30667
31510
|
} catch (err) {
|
|
30668
31511
|
const execErr = err;
|
|
@@ -30676,7 +31519,7 @@ function makeContainerExecFn(containerName) {
|
|
|
30676
31519
|
}
|
|
30677
31520
|
function defaultDockerExec() {
|
|
30678
31521
|
return (containerName, cmd) => {
|
|
30679
|
-
const result =
|
|
31522
|
+
const result = execSync5(
|
|
30680
31523
|
`docker exec ${containerName} sh -c '${cmd.replace(/'/g, "'\\''")}'`,
|
|
30681
31524
|
// Phase E E5 raise: 10min was too tight on cold-boot for atlas-core's
|
|
30682
31525
|
// `rails db:create` chain (Rails 7 boot + initializer load + first
|
|
@@ -30900,8 +31743,28 @@ var WorldManager = class {
|
|
|
30900
31743
|
throw new AuthPreflightError(preflight.verdict, preflight.message, preflight.remedy);
|
|
30901
31744
|
}
|
|
30902
31745
|
}
|
|
31746
|
+
let runbookPortOverrides = {};
|
|
31747
|
+
let runbookEnvOverrides = {};
|
|
31748
|
+
let runbookSeeds;
|
|
31749
|
+
if (opts.runbookName) {
|
|
31750
|
+
const runbook = getRunbook(opts.runbookName);
|
|
31751
|
+
const globalConfig2 = readGlobalConfig();
|
|
31752
|
+
const resolved = resolveRunbookToWorldParams(runbook, globalConfig2.repos);
|
|
31753
|
+
const { conflicts } = validateRunbookPorts(runbook);
|
|
31754
|
+
if (conflicts.length > 0) {
|
|
31755
|
+
const detail = conflicts.map((c) => {
|
|
31756
|
+
const occ = c.occupant.type === "olam-world" ? `in use by world "${c.occupant.worldId}" (olam)` : `in use by PID ${c.occupant.pid ?? "unknown"} (non-olam)`;
|
|
31757
|
+
return ` ${c.repoName}.${c.serviceName}:${c.port} \u2014 ${occ}`;
|
|
31758
|
+
}).join("\n");
|
|
31759
|
+
throw new Error(`Port conflicts detected for runbook "${opts.runbookName}":
|
|
31760
|
+
${detail}`);
|
|
31761
|
+
}
|
|
31762
|
+
runbookPortOverrides = resolved.portOverrides;
|
|
31763
|
+
runbookEnvOverrides = resolved.envOverrides;
|
|
31764
|
+
runbookSeeds = resolved.seeds;
|
|
31765
|
+
}
|
|
30903
31766
|
const worldId = generateWorldId();
|
|
30904
|
-
const workspacePath =
|
|
31767
|
+
const workspacePath = path24.join(os13.homedir(), ".olam", "worlds", worldId);
|
|
30905
31768
|
const portOffset = this.registry.getNextPortOffset();
|
|
30906
31769
|
const branch = opts.branchName ?? `olam/${worldId}`;
|
|
30907
31770
|
const repos = this.resolveReposWithWorkspace(opts);
|
|
@@ -30933,6 +31796,19 @@ var WorldManager = class {
|
|
|
30933
31796
|
this.registry.update(worldId, { status: "error" });
|
|
30934
31797
|
throw err;
|
|
30935
31798
|
}
|
|
31799
|
+
if (opts.runbookName && runbookSeeds) {
|
|
31800
|
+
try {
|
|
31801
|
+
runFixtureCopySeeds(runbookSeeds, workspacePath);
|
|
31802
|
+
} catch (err) {
|
|
31803
|
+
sm.transition("error");
|
|
31804
|
+
this.registry.update(worldId, { status: "error" });
|
|
31805
|
+
try {
|
|
31806
|
+
await removeWorktrees(repos, workspacePath);
|
|
31807
|
+
} catch {
|
|
31808
|
+
}
|
|
31809
|
+
throw err;
|
|
31810
|
+
}
|
|
31811
|
+
}
|
|
30936
31812
|
try {
|
|
30937
31813
|
const baseline = snapshotBaselineDiff(repos, workspacePath);
|
|
30938
31814
|
console.log(formatBaselineSummary(baseline));
|
|
@@ -30957,38 +31833,38 @@ var WorldManager = class {
|
|
|
30957
31833
|
for (const repo of repos) {
|
|
30958
31834
|
if (!repo.path)
|
|
30959
31835
|
continue;
|
|
30960
|
-
const sourceRoot = repo.path.replace(/^~/,
|
|
30961
|
-
const worktreeRoot =
|
|
30962
|
-
if (!
|
|
31836
|
+
const sourceRoot = repo.path.replace(/^~/, os13.homedir());
|
|
31837
|
+
const worktreeRoot = path24.join(workspacePath, repo.name);
|
|
31838
|
+
if (!fs20.existsSync(sourceRoot) || !fs20.existsSync(worktreeRoot))
|
|
30963
31839
|
continue;
|
|
30964
31840
|
let copied = 0;
|
|
30965
31841
|
for (const pattern of RUNTIME_FILE_PATTERNS) {
|
|
30966
31842
|
const matches2 = [];
|
|
30967
31843
|
if (pattern.includes("*")) {
|
|
30968
|
-
const [dir, glob] = [
|
|
30969
|
-
const sourceDir =
|
|
30970
|
-
if (
|
|
31844
|
+
const [dir, glob] = [path24.dirname(pattern), path24.basename(pattern)];
|
|
31845
|
+
const sourceDir = path24.join(sourceRoot, dir);
|
|
31846
|
+
if (fs20.existsSync(sourceDir)) {
|
|
30971
31847
|
const ext = glob.replace(/^\*+/, "");
|
|
30972
31848
|
try {
|
|
30973
|
-
for (const entry of
|
|
31849
|
+
for (const entry of fs20.readdirSync(sourceDir)) {
|
|
30974
31850
|
if (ext === "" || entry.endsWith(ext))
|
|
30975
|
-
matches2.push(
|
|
31851
|
+
matches2.push(path24.join(dir, entry));
|
|
30976
31852
|
}
|
|
30977
31853
|
} catch {
|
|
30978
31854
|
}
|
|
30979
31855
|
}
|
|
30980
|
-
} else if (
|
|
31856
|
+
} else if (fs20.existsSync(path24.join(sourceRoot, pattern))) {
|
|
30981
31857
|
matches2.push(pattern);
|
|
30982
31858
|
}
|
|
30983
31859
|
for (const rel of matches2) {
|
|
30984
|
-
const src =
|
|
30985
|
-
const dst =
|
|
31860
|
+
const src = path24.join(sourceRoot, rel);
|
|
31861
|
+
const dst = path24.join(worktreeRoot, rel);
|
|
30986
31862
|
try {
|
|
30987
|
-
const st =
|
|
31863
|
+
const st = fs20.statSync(src);
|
|
30988
31864
|
if (!st.isFile())
|
|
30989
31865
|
continue;
|
|
30990
|
-
|
|
30991
|
-
|
|
31866
|
+
fs20.mkdirSync(path24.dirname(dst), { recursive: true });
|
|
31867
|
+
fs20.copyFileSync(src, dst);
|
|
30992
31868
|
copied++;
|
|
30993
31869
|
} catch {
|
|
30994
31870
|
}
|
|
@@ -31088,7 +31964,7 @@ var WorldManager = class {
|
|
|
31088
31964
|
try {
|
|
31089
31965
|
const hostExec = makeHostExecFn();
|
|
31090
31966
|
for (const repo of repos) {
|
|
31091
|
-
const repoDir =
|
|
31967
|
+
const repoDir = path24.join(workspacePath, repo.name);
|
|
31092
31968
|
if (repo.stack && Object.keys(repo.stack).length > 0) {
|
|
31093
31969
|
preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
|
|
31094
31970
|
} else {
|
|
@@ -31114,11 +31990,19 @@ var WorldManager = class {
|
|
|
31114
31990
|
}
|
|
31115
31991
|
let cacheArchOverride;
|
|
31116
31992
|
if (!stackCacheHit) {
|
|
31117
|
-
const selected =
|
|
31993
|
+
const selected = selectDevboxImageForWorld({
|
|
31994
|
+
config: this.config,
|
|
31995
|
+
repos,
|
|
31996
|
+
worldspec: opts.worldspec
|
|
31997
|
+
});
|
|
31118
31998
|
if (selected) {
|
|
31119
31999
|
selectedImage = selected.image;
|
|
31120
32000
|
cacheArchOverride = selected.cacheArch;
|
|
31121
|
-
|
|
32001
|
+
if (selected.source === "worldspec") {
|
|
32002
|
+
console.log(`[WorldManager] worldspec override \u2014 using ${selected.image} (tag=${selected.tag})`);
|
|
32003
|
+
} else {
|
|
32004
|
+
console.log(`[WorldManager] image_selector matched \u2014 using ${selected.image} (tag=${selected.tag}${selected.cacheArch ? `, cache_arch=${selected.cacheArch}` : ""})`);
|
|
32005
|
+
}
|
|
31122
32006
|
} else {
|
|
31123
32007
|
const hasRailsRepo = repos.some((r) => r.type === "rails");
|
|
31124
32008
|
if (hasRailsRepo) {
|
|
@@ -31138,17 +32022,18 @@ var WorldManager = class {
|
|
|
31138
32022
|
}
|
|
31139
32023
|
}
|
|
31140
32024
|
const appPortUrls = appPorts.map((ap) => {
|
|
31141
|
-
const
|
|
32025
|
+
const override = runbookPortOverrides[ap.name]?.["app"];
|
|
32026
|
+
const hostPort = override !== void 0 ? override : ap.port + 1e4 + portOffset;
|
|
31142
32027
|
return { repoName: ap.name, internalPort: ap.port, hostPort, url: `http://localhost:${hostPort}` };
|
|
31143
32028
|
});
|
|
31144
32029
|
try {
|
|
31145
32030
|
const worldEnv = {};
|
|
31146
32031
|
if (opts.task)
|
|
31147
32032
|
worldEnv.OLAM_TASK = opts.task;
|
|
31148
|
-
const r2CredsPath =
|
|
31149
|
-
if (
|
|
32033
|
+
const r2CredsPath = path24.join(os13.homedir(), ".olam", "r2-credentials.json");
|
|
32034
|
+
if (fs20.existsSync(r2CredsPath)) {
|
|
31150
32035
|
try {
|
|
31151
|
-
const r2Raw =
|
|
32036
|
+
const r2Raw = fs20.readFileSync(r2CredsPath, "utf-8").trim();
|
|
31152
32037
|
if (r2Raw.length > 0) {
|
|
31153
32038
|
const r2 = JSON.parse(r2Raw);
|
|
31154
32039
|
if (typeof r2.account_id === "string")
|
|
@@ -31165,10 +32050,10 @@ var WorldManager = class {
|
|
|
31165
32050
|
} catch {
|
|
31166
32051
|
}
|
|
31167
32052
|
}
|
|
31168
|
-
const keysYamlPath =
|
|
31169
|
-
if (
|
|
32053
|
+
const keysYamlPath = path24.join(os13.homedir(), ".olam", "keys.yaml");
|
|
32054
|
+
if (fs20.existsSync(keysYamlPath)) {
|
|
31170
32055
|
try {
|
|
31171
|
-
const keysRaw =
|
|
32056
|
+
const keysRaw = fs20.readFileSync(keysYamlPath, "utf-8").trim();
|
|
31172
32057
|
if (keysRaw.length > 0) {
|
|
31173
32058
|
const parsed = YAML3.parse(keysRaw);
|
|
31174
32059
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
@@ -31204,6 +32089,18 @@ var WorldManager = class {
|
|
|
31204
32089
|
seenFromRepo.set(k, repo.name);
|
|
31205
32090
|
}
|
|
31206
32091
|
}
|
|
32092
|
+
if (opts.runbookName) {
|
|
32093
|
+
for (const [repoName, repoEnv] of Object.entries(runbookEnvOverrides)) {
|
|
32094
|
+
for (const [k, v] of Object.entries(repoEnv)) {
|
|
32095
|
+
if (PROTECTED_ENV_KEY_SET.has(k))
|
|
32096
|
+
continue;
|
|
32097
|
+
if (k.startsWith("OLAM_"))
|
|
32098
|
+
continue;
|
|
32099
|
+
worldEnv[k] = v;
|
|
32100
|
+
}
|
|
32101
|
+
void repoName;
|
|
32102
|
+
}
|
|
32103
|
+
}
|
|
31207
32104
|
if (repoSecretUrls.length > 0) {
|
|
31208
32105
|
const { env: gcpSecrets, fileWrites } = fetchSecretsForRepos(repoSecretUrls);
|
|
31209
32106
|
for (const [k, v] of Object.entries(gcpSecrets)) {
|
|
@@ -31215,10 +32112,10 @@ var WorldManager = class {
|
|
|
31215
32112
|
worldEnv[k] = v;
|
|
31216
32113
|
}
|
|
31217
32114
|
for (const { repoName, relativePath, content } of fileWrites) {
|
|
31218
|
-
const absPath =
|
|
32115
|
+
const absPath = path24.join(workspacePath, repoName, relativePath);
|
|
31219
32116
|
try {
|
|
31220
|
-
|
|
31221
|
-
|
|
32117
|
+
fs20.mkdirSync(path24.dirname(absPath), { recursive: true });
|
|
32118
|
+
fs20.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
|
|
31222
32119
|
mode: 384
|
|
31223
32120
|
});
|
|
31224
32121
|
console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
|
|
@@ -31324,6 +32221,44 @@ var WorldManager = class {
|
|
|
31324
32221
|
const msg = err instanceof Error ? err.message : String(err);
|
|
31325
32222
|
console.warn(`[WorldManager] stack installation failed: ${msg}`);
|
|
31326
32223
|
}
|
|
32224
|
+
try {
|
|
32225
|
+
cleanupLegacyByWorldDir(worldId);
|
|
32226
|
+
const restoreResult = restoreSnapshotsForRepos({
|
|
32227
|
+
workspace: opts.workspace ?? "default",
|
|
32228
|
+
arch: process.arch,
|
|
32229
|
+
imageDigest: void 0,
|
|
32230
|
+
repos: enrichedRepos.map((r) => ({
|
|
32231
|
+
name: r.name,
|
|
32232
|
+
worktreeDir: path24.join(workspacePath, r.name)
|
|
32233
|
+
}))
|
|
32234
|
+
});
|
|
32235
|
+
for (const out of restoreResult.outcomes) {
|
|
32236
|
+
if (out.outcome === "hit") {
|
|
32237
|
+
console.log(`[snapshot] Restored ${out.kind} for ${out.repo} (${out.fingerprint?.slice(0, 12)})`);
|
|
32238
|
+
} else if (out.outcome === "refused") {
|
|
32239
|
+
console.warn(`[snapshot] Skipped ${out.repo} ${out.kind}: ${out.reason ?? "unknown"}`);
|
|
32240
|
+
}
|
|
32241
|
+
}
|
|
32242
|
+
for (const [repoName, restoredKinds] of restoreResult.restored) {
|
|
32243
|
+
const repo = enrichedRepos.find((r) => r.name === repoName);
|
|
32244
|
+
if (!repo?.manifest?.bootstrap)
|
|
32245
|
+
continue;
|
|
32246
|
+
const containerWorkdir = `/home/olam/workspace/${repoName}`;
|
|
32247
|
+
repo.manifest.bootstrap.forEach((step, idx) => {
|
|
32248
|
+
const produces = typeof step === "object" && step !== null ? step.produces : void 0;
|
|
32249
|
+
if (produces && restoredKinds.includes(produces)) {
|
|
32250
|
+
const sentinel = bootstrapStepSentinelPath(containerWorkdir, idx);
|
|
32251
|
+
try {
|
|
32252
|
+
this.dockerExec(containerName, `touch ${sentinel}`);
|
|
32253
|
+
} catch {
|
|
32254
|
+
}
|
|
32255
|
+
}
|
|
32256
|
+
});
|
|
32257
|
+
}
|
|
32258
|
+
} catch (err) {
|
|
32259
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
32260
|
+
console.warn(`[snapshot] restore failed (cold path): ${msg}`);
|
|
32261
|
+
}
|
|
31327
32262
|
try {
|
|
31328
32263
|
await runManifestRuntime(containerName, worldId, enrichedRepos, this.dockerExec);
|
|
31329
32264
|
} catch (err) {
|
|
@@ -31348,12 +32283,30 @@ var WorldManager = class {
|
|
|
31348
32283
|
console.warn(`[manifest] step 4e/4f/4g non-fatal failure: ${msg}`);
|
|
31349
32284
|
}
|
|
31350
32285
|
}
|
|
32286
|
+
if (opts.runbookName && runbookSeeds) {
|
|
32287
|
+
const servicePortMap = {};
|
|
32288
|
+
for (const repo of enrichedRepos) {
|
|
32289
|
+
if (!repo.manifest?.services)
|
|
32290
|
+
continue;
|
|
32291
|
+
const svcPorts = {};
|
|
32292
|
+
for (const [svcName, svc] of Object.entries(repo.manifest.services)) {
|
|
32293
|
+
svcPorts[svcName] = svc.port ?? 5432;
|
|
32294
|
+
}
|
|
32295
|
+
servicePortMap[repo.name] = svcPorts;
|
|
32296
|
+
}
|
|
32297
|
+
try {
|
|
32298
|
+
await runSeedHooks(runbookSeeds, containerName, servicePortMap, this.dockerExec);
|
|
32299
|
+
} catch (err) {
|
|
32300
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
32301
|
+
console.warn(`[runbook] seed hook failed: ${msg}`);
|
|
32302
|
+
}
|
|
32303
|
+
}
|
|
31351
32304
|
for (const repo of repos) {
|
|
31352
32305
|
if (repo.setup_commands.length > 0) {
|
|
31353
32306
|
const escapedDir = `/home/olam/workspace/${repo.name.replace(/["$`\\]/g, "\\$&")}`;
|
|
31354
32307
|
for (const cmd of repo.setup_commands) {
|
|
31355
32308
|
try {
|
|
31356
|
-
|
|
32309
|
+
execSync5(`docker exec ${containerName} sh -c 'cd "${escapedDir}" && ${cmd.replace(/'/g, "'\\''")}'`, { stdio: "pipe", timeout: 6e5 });
|
|
31357
32310
|
} catch (err) {
|
|
31358
32311
|
const msg = err instanceof Error ? err.message : String(err);
|
|
31359
32312
|
console.warn(`[WorldManager] setup command failed for ${repo.name}: ${msg}`);
|
|
@@ -31363,14 +32316,14 @@ var WorldManager = class {
|
|
|
31363
32316
|
}
|
|
31364
32317
|
if (credentialsInjected.claude) {
|
|
31365
32318
|
try {
|
|
31366
|
-
|
|
32319
|
+
execSync5(`docker exec ${containerName} curl -sf -X POST http://localhost:8080/session/start-agent 2>/dev/null || true`, { stdio: "pipe", timeout: 45e3 });
|
|
31367
32320
|
} catch {
|
|
31368
32321
|
}
|
|
31369
32322
|
if (opts.task) {
|
|
31370
32323
|
let taskWithPolicies = opts.task;
|
|
31371
32324
|
try {
|
|
31372
32325
|
const allPolicies = repos.flatMap((repo) => {
|
|
31373
|
-
const repoWorktree =
|
|
32326
|
+
const repoWorktree = path24.join(workspacePath, repo.name);
|
|
31374
32327
|
return loadPolicies(repoWorktree);
|
|
31375
32328
|
});
|
|
31376
32329
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -31384,11 +32337,11 @@ var WorldManager = class {
|
|
|
31384
32337
|
const brief = formatPoliciesBrief(uniquePolicies);
|
|
31385
32338
|
taskWithPolicies = `${brief}## Your task
|
|
31386
32339
|
${opts.task}`;
|
|
31387
|
-
|
|
32340
|
+
execSync5(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
31388
32341
|
for (const repo of repos) {
|
|
31389
|
-
const policiesDir =
|
|
31390
|
-
if (
|
|
31391
|
-
|
|
32342
|
+
const policiesDir = path24.join(workspacePath, repo.name, ".olam", "policies");
|
|
32343
|
+
if (fs20.existsSync(policiesDir)) {
|
|
32344
|
+
execSync5(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
31392
32345
|
}
|
|
31393
32346
|
}
|
|
31394
32347
|
}
|
|
@@ -31398,7 +32351,7 @@ ${opts.task}`;
|
|
|
31398
32351
|
}
|
|
31399
32352
|
try {
|
|
31400
32353
|
const payload = JSON.stringify({ prompt: taskWithPolicies }).replace(/'/g, "'\\''");
|
|
31401
|
-
|
|
32354
|
+
execSync5(`docker exec ${containerName} curl -sf -X POST -H 'Content-Type: application/json' -d '${payload}' http://localhost:8080/dispatch 2>/dev/null || true`, { stdio: "pipe", timeout: 3e4 });
|
|
31402
32355
|
console.log("[world] Task auto-dispatched");
|
|
31403
32356
|
} catch {
|
|
31404
32357
|
}
|
|
@@ -31409,6 +32362,19 @@ ${opts.task}`;
|
|
|
31409
32362
|
const terminalPort = 17681 + portOffset;
|
|
31410
32363
|
const dashboardUrl = `http://localhost:${dashboardPort}`;
|
|
31411
32364
|
const terminalUrl = `http://localhost:${terminalPort}`;
|
|
32365
|
+
try {
|
|
32366
|
+
spawnAutoCapture(worldId);
|
|
32367
|
+
} catch {
|
|
32368
|
+
}
|
|
32369
|
+
try {
|
|
32370
|
+
const cap = parseInt(process.env["OLAM_SNAPSHOT_MAX_BYTES"] ?? "", 10);
|
|
32371
|
+
const maxBytes = Number.isInteger(cap) && cap > 0 ? cap : 5 * 1024 * 1024 * 1024;
|
|
32372
|
+
const freed = evictOldSnapshotsWithFlock(maxBytes);
|
|
32373
|
+
if (freed > 0) {
|
|
32374
|
+
console.log(`[snapshot] evicted ${(freed / 1024 / 1024).toFixed(0)}MB to stay under ${(maxBytes / 1024 / 1024 / 1024).toFixed(1)}GB cap`);
|
|
32375
|
+
}
|
|
32376
|
+
} catch {
|
|
32377
|
+
}
|
|
31412
32378
|
return {
|
|
31413
32379
|
...metadata,
|
|
31414
32380
|
status: "running",
|
|
@@ -31466,8 +32432,8 @@ ${opts.task}`;
|
|
|
31466
32432
|
} catch {
|
|
31467
32433
|
}
|
|
31468
32434
|
try {
|
|
31469
|
-
|
|
31470
|
-
if (
|
|
32435
|
+
fs20.rmSync(world.workspacePath, { recursive: true, force: true });
|
|
32436
|
+
if (fs20.existsSync(world.workspacePath)) {
|
|
31471
32437
|
console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
|
|
31472
32438
|
}
|
|
31473
32439
|
} catch (err) {
|
|
@@ -31552,14 +32518,14 @@ ${opts.task}`;
|
|
|
31552
32518
|
return names.map((name) => this.config.repos.find((r) => r.name === name)).filter((r) => r !== void 0);
|
|
31553
32519
|
}
|
|
31554
32520
|
transportPlanFile(planFilePath, workspacePath, repoNames) {
|
|
31555
|
-
const planContent =
|
|
31556
|
-
const planFileName =
|
|
32521
|
+
const planContent = fs20.readFileSync(planFilePath, "utf-8");
|
|
32522
|
+
const planFileName = path24.basename(planFilePath);
|
|
31557
32523
|
const targetRepo = repoNames[0];
|
|
31558
32524
|
if (!targetRepo)
|
|
31559
32525
|
return;
|
|
31560
|
-
const plansDir =
|
|
31561
|
-
|
|
31562
|
-
|
|
32526
|
+
const plansDir = path24.join(workspacePath, targetRepo, "docs", "plans");
|
|
32527
|
+
fs20.mkdirSync(plansDir, { recursive: true });
|
|
32528
|
+
fs20.writeFileSync(path24.join(plansDir, planFileName), planContent);
|
|
31563
32529
|
}
|
|
31564
32530
|
resolveServices(repos) {
|
|
31565
32531
|
const services = [];
|
|
@@ -31644,8 +32610,8 @@ import * as http2 from "node:http";
|
|
|
31644
32610
|
|
|
31645
32611
|
// ../core/dist/dashboard/server.js
|
|
31646
32612
|
import * as http from "node:http";
|
|
31647
|
-
import * as
|
|
31648
|
-
import * as
|
|
32613
|
+
import * as fs21 from "node:fs";
|
|
32614
|
+
import * as path25 from "node:path";
|
|
31649
32615
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
31650
32616
|
|
|
31651
32617
|
// ../core/dist/dashboard/serialize.js
|
|
@@ -31980,7 +32946,7 @@ function notFound(res) {
|
|
|
31980
32946
|
}
|
|
31981
32947
|
function openThoughtStore(workspacePath) {
|
|
31982
32948
|
const dbPath = getWorldDbPath(workspacePath);
|
|
31983
|
-
if (!
|
|
32949
|
+
if (!fs21.existsSync(dbPath))
|
|
31984
32950
|
return null;
|
|
31985
32951
|
return new ThoughtLocalStore(dbPath);
|
|
31986
32952
|
}
|
|
@@ -32151,13 +33117,13 @@ function findSessionInWorld(registry2, sessionId) {
|
|
|
32151
33117
|
}
|
|
32152
33118
|
function createDashboardServer(opts) {
|
|
32153
33119
|
const { port, registry: registry2 } = opts;
|
|
32154
|
-
const thisDir =
|
|
32155
|
-
const defaultPublicDir =
|
|
33120
|
+
const thisDir = path25.dirname(fileURLToPath2(import.meta.url));
|
|
33121
|
+
const defaultPublicDir = path25.resolve(thisDir, "../../../control-plane/public");
|
|
32156
33122
|
const publicDir = opts.publicDir ?? defaultPublicDir;
|
|
32157
|
-
let hasPublicDir =
|
|
33123
|
+
let hasPublicDir = fs21.existsSync(publicDir);
|
|
32158
33124
|
const server = http.createServer((req, res) => {
|
|
32159
33125
|
if (!hasPublicDir) {
|
|
32160
|
-
hasPublicDir =
|
|
33126
|
+
hasPublicDir = fs21.existsSync(publicDir);
|
|
32161
33127
|
}
|
|
32162
33128
|
const host = req.headers.host ?? `localhost:${port}`;
|
|
32163
33129
|
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -32431,22 +33397,22 @@ function createDashboardServer(opts) {
|
|
|
32431
33397
|
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>`);
|
|
32432
33398
|
return;
|
|
32433
33399
|
}
|
|
32434
|
-
let filePath =
|
|
33400
|
+
let filePath = path25.join(publicDir, pathname === "/" ? "index.html" : pathname);
|
|
32435
33401
|
if (!filePath.startsWith(publicDir)) {
|
|
32436
33402
|
notFound(res);
|
|
32437
33403
|
return;
|
|
32438
33404
|
}
|
|
32439
|
-
if (
|
|
32440
|
-
const ext =
|
|
33405
|
+
if (fs21.existsSync(filePath) && fs21.statSync(filePath).isFile()) {
|
|
33406
|
+
const ext = path25.extname(filePath);
|
|
32441
33407
|
const contentType = MIME[ext] ?? "application/octet-stream";
|
|
32442
33408
|
res.writeHead(200, { "Content-Type": contentType });
|
|
32443
|
-
|
|
33409
|
+
fs21.createReadStream(filePath).pipe(res);
|
|
32444
33410
|
return;
|
|
32445
33411
|
}
|
|
32446
|
-
filePath =
|
|
32447
|
-
if (
|
|
33412
|
+
filePath = path25.join(publicDir, "index.html");
|
|
33413
|
+
if (fs21.existsSync(filePath)) {
|
|
32448
33414
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
32449
|
-
|
|
33415
|
+
fs21.createReadStream(filePath).pipe(res);
|
|
32450
33416
|
return;
|
|
32451
33417
|
}
|
|
32452
33418
|
notFound(res);
|
|
@@ -32456,17 +33422,17 @@ function createDashboardServer(opts) {
|
|
|
32456
33422
|
}
|
|
32457
33423
|
|
|
32458
33424
|
// ../core/dist/dashboard/state.js
|
|
32459
|
-
import * as
|
|
32460
|
-
import * as
|
|
32461
|
-
import * as
|
|
32462
|
-
var STATE_PATH =
|
|
33425
|
+
import * as fs22 from "node:fs";
|
|
33426
|
+
import * as os14 from "node:os";
|
|
33427
|
+
import * as path26 from "node:path";
|
|
33428
|
+
var STATE_PATH = path26.join(os14.homedir(), ".olam", "dashboard.json");
|
|
32463
33429
|
function saveDashboardState(state) {
|
|
32464
|
-
|
|
32465
|
-
|
|
33430
|
+
fs22.mkdirSync(path26.dirname(STATE_PATH), { recursive: true });
|
|
33431
|
+
fs22.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
|
|
32466
33432
|
}
|
|
32467
33433
|
function loadDashboardState() {
|
|
32468
33434
|
try {
|
|
32469
|
-
const raw =
|
|
33435
|
+
const raw = fs22.readFileSync(STATE_PATH, "utf-8");
|
|
32470
33436
|
return JSON.parse(raw);
|
|
32471
33437
|
} catch {
|
|
32472
33438
|
return null;
|
|
@@ -32474,7 +33440,7 @@ function loadDashboardState() {
|
|
|
32474
33440
|
}
|
|
32475
33441
|
function clearDashboardState() {
|
|
32476
33442
|
try {
|
|
32477
|
-
|
|
33443
|
+
fs22.unlinkSync(STATE_PATH);
|
|
32478
33444
|
} catch {
|
|
32479
33445
|
}
|
|
32480
33446
|
}
|
|
@@ -32492,19 +33458,19 @@ function isDashboardRunning() {
|
|
|
32492
33458
|
}
|
|
32493
33459
|
|
|
32494
33460
|
// ../core/dist/dashboard/tunnel.js
|
|
32495
|
-
import { spawn, execSync as
|
|
33461
|
+
import { spawn as spawn2, execSync as execSync6 } from "node:child_process";
|
|
32496
33462
|
var tunnelProcess = null;
|
|
32497
33463
|
function isCloudflaredAvailable() {
|
|
32498
33464
|
try {
|
|
32499
|
-
|
|
33465
|
+
execSync6("which cloudflared", { stdio: "ignore" });
|
|
32500
33466
|
return true;
|
|
32501
33467
|
} catch {
|
|
32502
33468
|
return false;
|
|
32503
33469
|
}
|
|
32504
33470
|
}
|
|
32505
33471
|
function startTunnel(port) {
|
|
32506
|
-
return new Promise((
|
|
32507
|
-
const child =
|
|
33472
|
+
return new Promise((resolve8, reject2) => {
|
|
33473
|
+
const child = spawn2("cloudflared", ["tunnel", "--url", `http://localhost:${port}`], {
|
|
32508
33474
|
stdio: ["ignore", "pipe", "pipe"],
|
|
32509
33475
|
detached: false
|
|
32510
33476
|
});
|
|
@@ -32525,7 +33491,7 @@ function startTunnel(port) {
|
|
|
32525
33491
|
if (match) {
|
|
32526
33492
|
resolved = true;
|
|
32527
33493
|
clearTimeout(timeout);
|
|
32528
|
-
|
|
33494
|
+
resolve8(match[0]);
|
|
32529
33495
|
}
|
|
32530
33496
|
}
|
|
32531
33497
|
child.stdout?.on("data", scan);
|
|
@@ -32593,8 +33559,8 @@ var DashboardManager = class {
|
|
|
32593
33559
|
}
|
|
32594
33560
|
throw err;
|
|
32595
33561
|
}
|
|
32596
|
-
await new Promise((
|
|
32597
|
-
this.server.on("listening",
|
|
33562
|
+
await new Promise((resolve8, reject2) => {
|
|
33563
|
+
this.server.on("listening", resolve8);
|
|
32598
33564
|
this.server.on("error", reject2);
|
|
32599
33565
|
});
|
|
32600
33566
|
this.info = { localUrl: `http://localhost:${port}` };
|
|
@@ -32640,8 +33606,8 @@ var DashboardManager = class {
|
|
|
32640
33606
|
async stop() {
|
|
32641
33607
|
stopTunnel();
|
|
32642
33608
|
if (this.server) {
|
|
32643
|
-
await new Promise((
|
|
32644
|
-
this.server.close(() =>
|
|
33609
|
+
await new Promise((resolve8) => {
|
|
33610
|
+
this.server.close(() => resolve8());
|
|
32645
33611
|
});
|
|
32646
33612
|
this.server = null;
|
|
32647
33613
|
}
|
|
@@ -32754,8 +33720,8 @@ var PleriClient = class {
|
|
|
32754
33720
|
};
|
|
32755
33721
|
|
|
32756
33722
|
// ../mcp-server/src/env-loader.ts
|
|
32757
|
-
import { readFileSync as
|
|
32758
|
-
import { join as
|
|
33723
|
+
import { readFileSync as readFileSync16, existsSync as existsSync21, statSync as statSync7 } from "node:fs";
|
|
33724
|
+
import { join as join27, dirname as dirname15, resolve as resolve7 } from "node:path";
|
|
32759
33725
|
var PROJECT_MARKERS = [
|
|
32760
33726
|
".olam/config.yaml",
|
|
32761
33727
|
".olam/config.yml",
|
|
@@ -32763,30 +33729,30 @@ var PROJECT_MARKERS = [
|
|
|
32763
33729
|
"olam.yml"
|
|
32764
33730
|
];
|
|
32765
33731
|
function findProjectRoot2(startDir) {
|
|
32766
|
-
let dir =
|
|
32767
|
-
const root =
|
|
33732
|
+
let dir = resolve7(startDir);
|
|
33733
|
+
const root = resolve7("/");
|
|
32768
33734
|
while (true) {
|
|
32769
33735
|
for (const marker of PROJECT_MARKERS) {
|
|
32770
|
-
if (
|
|
33736
|
+
if (existsSync21(join27(dir, marker))) return dir;
|
|
32771
33737
|
}
|
|
32772
|
-
const pkg =
|
|
32773
|
-
if (
|
|
33738
|
+
const pkg = join27(dir, "package.json");
|
|
33739
|
+
if (existsSync21(pkg)) {
|
|
32774
33740
|
try {
|
|
32775
|
-
const json = JSON.parse(
|
|
33741
|
+
const json = JSON.parse(readFileSync16(pkg, "utf8"));
|
|
32776
33742
|
const isOlamWorkspace = typeof json.name === "string" && json.name.startsWith("@olam/");
|
|
32777
33743
|
const hasOlamDep = json.dependencies && Object.keys(json.dependencies).some((k) => k.startsWith("@olam/")) || json.devDependencies && Object.keys(json.devDependencies).some((k) => k.startsWith("@olam/"));
|
|
32778
33744
|
if (isOlamWorkspace || hasOlamDep) return dir;
|
|
32779
33745
|
} catch {
|
|
32780
33746
|
}
|
|
32781
33747
|
}
|
|
32782
|
-
const parent =
|
|
33748
|
+
const parent = dirname15(dir);
|
|
32783
33749
|
if (parent === dir || parent === root) return null;
|
|
32784
33750
|
dir = parent;
|
|
32785
33751
|
}
|
|
32786
33752
|
}
|
|
32787
|
-
function parseEnvFile(
|
|
33753
|
+
function parseEnvFile(path27) {
|
|
32788
33754
|
const out = {};
|
|
32789
|
-
const raw =
|
|
33755
|
+
const raw = readFileSync16(path27, "utf8");
|
|
32790
33756
|
for (const line of raw.split(/\r?\n/)) {
|
|
32791
33757
|
const trimmed = line.trim();
|
|
32792
33758
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -32809,8 +33775,8 @@ function loadProjectEnv(startDir = process.cwd()) {
|
|
|
32809
33775
|
const filesRead = [];
|
|
32810
33776
|
const merged = {};
|
|
32811
33777
|
for (const name of [".env", ".env.local"]) {
|
|
32812
|
-
const p =
|
|
32813
|
-
if (
|
|
33778
|
+
const p = join27(root, name);
|
|
33779
|
+
if (existsSync21(p) && statSync7(p).isFile()) {
|
|
32814
33780
|
Object.assign(merged, parseEnvFile(p));
|
|
32815
33781
|
filesRead.push(p);
|
|
32816
33782
|
}
|
|
@@ -32880,7 +33846,7 @@ async function main() {
|
|
|
32880
33846
|
initError = err instanceof Error ? err : new Error(String(err));
|
|
32881
33847
|
logger.error("Failed to initialize Olam", { error: initError.message });
|
|
32882
33848
|
}
|
|
32883
|
-
const server =
|
|
33849
|
+
const server = createServer4(ctx, initError);
|
|
32884
33850
|
const transport = new StdioServerTransport();
|
|
32885
33851
|
await server.connect(transport);
|
|
32886
33852
|
logger.info("Olam MCP server running on stdio transport");
|