@pleri/olam-cli 0.1.36 → 0.1.37
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/__tests__/diagnose.test.d.ts +9 -0
- package/dist/commands/__tests__/diagnose.test.d.ts.map +1 -0
- package/dist/commands/__tests__/diagnose.test.js +108 -0
- package/dist/commands/__tests__/diagnose.test.js.map +1 -0
- package/dist/commands/__tests__/update.test.d.ts +7 -0
- package/dist/commands/__tests__/update.test.d.ts.map +1 -0
- package/dist/commands/__tests__/update.test.js +224 -0
- package/dist/commands/__tests__/update.test.js.map +1 -0
- package/dist/commands/diagnose.d.ts +20 -0
- package/dist/commands/diagnose.d.ts.map +1 -0
- package/dist/commands/diagnose.js +161 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/update.d.ts +65 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +278 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/image-digests.json +3 -3
- package/dist/index.js +629 -115
- package/dist/index.js.map +1 -1
- package/dist/lib/__tests__/symlink-reconcile.test.d.ts +2 -0
- package/dist/lib/__tests__/symlink-reconcile.test.d.ts.map +1 -0
- package/dist/lib/__tests__/symlink-reconcile.test.js +106 -0
- package/dist/lib/__tests__/symlink-reconcile.test.js.map +1 -0
- package/dist/lib/symlink-reconcile.d.ts +32 -0
- package/dist/lib/symlink-reconcile.d.ts.map +1 -0
- package/dist/lib/symlink-reconcile.js +80 -0
- package/dist/lib/symlink-reconcile.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -421,8 +421,8 @@ var init_parseUtil = __esm({
|
|
|
421
421
|
init_errors();
|
|
422
422
|
init_en();
|
|
423
423
|
makeIssue = (params) => {
|
|
424
|
-
const { data, path:
|
|
425
|
-
const fullPath = [...
|
|
424
|
+
const { data, path: path40, errorMaps, issueData } = params;
|
|
425
|
+
const fullPath = [...path40, ...issueData.path || []];
|
|
426
426
|
const fullIssue = {
|
|
427
427
|
...issueData,
|
|
428
428
|
path: fullPath
|
|
@@ -730,11 +730,11 @@ var init_types = __esm({
|
|
|
730
730
|
init_parseUtil();
|
|
731
731
|
init_util();
|
|
732
732
|
ParseInputLazyPath = class {
|
|
733
|
-
constructor(parent, value,
|
|
733
|
+
constructor(parent, value, path40, key) {
|
|
734
734
|
this._cachedPath = [];
|
|
735
735
|
this.parent = parent;
|
|
736
736
|
this.data = value;
|
|
737
|
-
this._path =
|
|
737
|
+
this._path = path40;
|
|
738
738
|
this._key = key;
|
|
739
739
|
}
|
|
740
740
|
get path() {
|
|
@@ -2812,33 +2812,33 @@ var init_types = __esm({
|
|
|
2812
2812
|
...processCreateParams(params)
|
|
2813
2813
|
});
|
|
2814
2814
|
};
|
|
2815
|
-
getDiscriminator = (
|
|
2816
|
-
if (
|
|
2817
|
-
return getDiscriminator(
|
|
2818
|
-
} else if (
|
|
2819
|
-
return getDiscriminator(
|
|
2820
|
-
} else if (
|
|
2821
|
-
return [
|
|
2822
|
-
} else if (
|
|
2823
|
-
return
|
|
2824
|
-
} else if (
|
|
2825
|
-
return util.objectValues(
|
|
2826
|
-
} else if (
|
|
2827
|
-
return getDiscriminator(
|
|
2828
|
-
} else if (
|
|
2815
|
+
getDiscriminator = (type2) => {
|
|
2816
|
+
if (type2 instanceof ZodLazy) {
|
|
2817
|
+
return getDiscriminator(type2.schema);
|
|
2818
|
+
} else if (type2 instanceof ZodEffects) {
|
|
2819
|
+
return getDiscriminator(type2.innerType());
|
|
2820
|
+
} else if (type2 instanceof ZodLiteral) {
|
|
2821
|
+
return [type2.value];
|
|
2822
|
+
} else if (type2 instanceof ZodEnum) {
|
|
2823
|
+
return type2.options;
|
|
2824
|
+
} else if (type2 instanceof ZodNativeEnum) {
|
|
2825
|
+
return util.objectValues(type2.enum);
|
|
2826
|
+
} else if (type2 instanceof ZodDefault) {
|
|
2827
|
+
return getDiscriminator(type2._def.innerType);
|
|
2828
|
+
} else if (type2 instanceof ZodUndefined) {
|
|
2829
2829
|
return [void 0];
|
|
2830
|
-
} else if (
|
|
2830
|
+
} else if (type2 instanceof ZodNull) {
|
|
2831
2831
|
return [null];
|
|
2832
|
-
} else if (
|
|
2833
|
-
return [void 0, ...getDiscriminator(
|
|
2834
|
-
} else if (
|
|
2835
|
-
return [null, ...getDiscriminator(
|
|
2836
|
-
} else if (
|
|
2837
|
-
return getDiscriminator(
|
|
2838
|
-
} else if (
|
|
2839
|
-
return getDiscriminator(
|
|
2840
|
-
} else if (
|
|
2841
|
-
return getDiscriminator(
|
|
2832
|
+
} else if (type2 instanceof ZodOptional) {
|
|
2833
|
+
return [void 0, ...getDiscriminator(type2.unwrap())];
|
|
2834
|
+
} else if (type2 instanceof ZodNullable) {
|
|
2835
|
+
return [null, ...getDiscriminator(type2.unwrap())];
|
|
2836
|
+
} else if (type2 instanceof ZodBranded) {
|
|
2837
|
+
return getDiscriminator(type2.unwrap());
|
|
2838
|
+
} else if (type2 instanceof ZodReadonly) {
|
|
2839
|
+
return getDiscriminator(type2.unwrap());
|
|
2840
|
+
} else if (type2 instanceof ZodCatch) {
|
|
2841
|
+
return getDiscriminator(type2._def.innerType);
|
|
2842
2842
|
} else {
|
|
2843
2843
|
return [];
|
|
2844
2844
|
}
|
|
@@ -2898,8 +2898,8 @@ var init_types = __esm({
|
|
|
2898
2898
|
*/
|
|
2899
2899
|
static create(discriminator, options, params) {
|
|
2900
2900
|
const optionsMap = /* @__PURE__ */ new Map();
|
|
2901
|
-
for (const
|
|
2902
|
-
const discriminatorValues = getDiscriminator(
|
|
2901
|
+
for (const type2 of options) {
|
|
2902
|
+
const discriminatorValues = getDiscriminator(type2.shape[discriminator]);
|
|
2903
2903
|
if (!discriminatorValues.length) {
|
|
2904
2904
|
throw new Error(`A discriminator value for key \`${discriminator}\` could not be extracted from all schema options`);
|
|
2905
2905
|
}
|
|
@@ -2907,7 +2907,7 @@ var init_types = __esm({
|
|
|
2907
2907
|
if (optionsMap.has(value)) {
|
|
2908
2908
|
throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`);
|
|
2909
2909
|
}
|
|
2910
|
-
optionsMap.set(value,
|
|
2910
|
+
optionsMap.set(value, type2);
|
|
2911
2911
|
}
|
|
2912
2912
|
}
|
|
2913
2913
|
return new _ZodDiscriminatedUnion({
|
|
@@ -3673,9 +3673,9 @@ var init_types = __esm({
|
|
|
3673
3673
|
return this._def.innerType;
|
|
3674
3674
|
}
|
|
3675
3675
|
};
|
|
3676
|
-
ZodOptional.create = (
|
|
3676
|
+
ZodOptional.create = (type2, params) => {
|
|
3677
3677
|
return new ZodOptional({
|
|
3678
|
-
innerType:
|
|
3678
|
+
innerType: type2,
|
|
3679
3679
|
typeName: ZodFirstPartyTypeKind.ZodOptional,
|
|
3680
3680
|
...processCreateParams(params)
|
|
3681
3681
|
});
|
|
@@ -3692,9 +3692,9 @@ var init_types = __esm({
|
|
|
3692
3692
|
return this._def.innerType;
|
|
3693
3693
|
}
|
|
3694
3694
|
};
|
|
3695
|
-
ZodNullable.create = (
|
|
3695
|
+
ZodNullable.create = (type2, params) => {
|
|
3696
3696
|
return new ZodNullable({
|
|
3697
|
-
innerType:
|
|
3697
|
+
innerType: type2,
|
|
3698
3698
|
typeName: ZodFirstPartyTypeKind.ZodNullable,
|
|
3699
3699
|
...processCreateParams(params)
|
|
3700
3700
|
});
|
|
@@ -3716,9 +3716,9 @@ var init_types = __esm({
|
|
|
3716
3716
|
return this._def.innerType;
|
|
3717
3717
|
}
|
|
3718
3718
|
};
|
|
3719
|
-
ZodDefault.create = (
|
|
3719
|
+
ZodDefault.create = (type2, params) => {
|
|
3720
3720
|
return new ZodDefault({
|
|
3721
|
-
innerType:
|
|
3721
|
+
innerType: type2,
|
|
3722
3722
|
typeName: ZodFirstPartyTypeKind.ZodDefault,
|
|
3723
3723
|
defaultValue: typeof params.default === "function" ? params.default : () => params.default,
|
|
3724
3724
|
...processCreateParams(params)
|
|
@@ -3769,9 +3769,9 @@ var init_types = __esm({
|
|
|
3769
3769
|
return this._def.innerType;
|
|
3770
3770
|
}
|
|
3771
3771
|
};
|
|
3772
|
-
ZodCatch.create = (
|
|
3772
|
+
ZodCatch.create = (type2, params) => {
|
|
3773
3773
|
return new ZodCatch({
|
|
3774
|
-
innerType:
|
|
3774
|
+
innerType: type2,
|
|
3775
3775
|
typeName: ZodFirstPartyTypeKind.ZodCatch,
|
|
3776
3776
|
catchValue: typeof params.catch === "function" ? params.catch : () => params.catch,
|
|
3777
3777
|
...processCreateParams(params)
|
|
@@ -3883,9 +3883,9 @@ var init_types = __esm({
|
|
|
3883
3883
|
return this._def.innerType;
|
|
3884
3884
|
}
|
|
3885
3885
|
};
|
|
3886
|
-
ZodReadonly.create = (
|
|
3886
|
+
ZodReadonly.create = (type2, params) => {
|
|
3887
3887
|
return new ZodReadonly({
|
|
3888
|
-
innerType:
|
|
3888
|
+
innerType: type2,
|
|
3889
3889
|
typeName: ZodFirstPartyTypeKind.ZodReadonly,
|
|
3890
3890
|
...processCreateParams(params)
|
|
3891
3891
|
});
|
|
@@ -4221,7 +4221,7 @@ import YAML from "yaml";
|
|
|
4221
4221
|
function bootstrapStepCmd(entry) {
|
|
4222
4222
|
return typeof entry === "string" ? entry : entry.cmd;
|
|
4223
4223
|
}
|
|
4224
|
-
function refineForbiddenKeys(value,
|
|
4224
|
+
function refineForbiddenKeys(value, path40, ctx, rejectSource) {
|
|
4225
4225
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4226
4226
|
return;
|
|
4227
4227
|
}
|
|
@@ -4229,12 +4229,12 @@ function refineForbiddenKeys(value, path36, ctx, rejectSource) {
|
|
|
4229
4229
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4230
4230
|
ctx.addIssue({
|
|
4231
4231
|
code: external_exports.ZodIssueCode.custom,
|
|
4232
|
-
path: [...
|
|
4232
|
+
path: [...path40, key],
|
|
4233
4233
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
4234
4234
|
});
|
|
4235
4235
|
continue;
|
|
4236
4236
|
}
|
|
4237
|
-
if (rejectSource &&
|
|
4237
|
+
if (rejectSource && path40.length === 0 && key === "source") {
|
|
4238
4238
|
ctx.addIssue({
|
|
4239
4239
|
code: external_exports.ZodIssueCode.custom,
|
|
4240
4240
|
path: ["source"],
|
|
@@ -4244,30 +4244,30 @@ function refineForbiddenKeys(value, path36, ctx, rejectSource) {
|
|
|
4244
4244
|
}
|
|
4245
4245
|
refineForbiddenKeys(
|
|
4246
4246
|
value[key],
|
|
4247
|
-
[...
|
|
4247
|
+
[...path40, key],
|
|
4248
4248
|
ctx,
|
|
4249
4249
|
false
|
|
4250
4250
|
);
|
|
4251
4251
|
}
|
|
4252
4252
|
}
|
|
4253
|
-
function rejectForbiddenKeys(value,
|
|
4253
|
+
function rejectForbiddenKeys(value, path40, rejectSource) {
|
|
4254
4254
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4255
4255
|
return;
|
|
4256
4256
|
}
|
|
4257
4257
|
for (const key of Object.keys(value)) {
|
|
4258
4258
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4259
4259
|
throw new Error(
|
|
4260
|
-
`[manifest] ${
|
|
4260
|
+
`[manifest] ${path40}: forbidden key "${key}" (prototype-pollution surface)`
|
|
4261
4261
|
);
|
|
4262
4262
|
}
|
|
4263
4263
|
if (rejectSource && key === "source") {
|
|
4264
4264
|
throw new Error(
|
|
4265
|
-
`[manifest] ${
|
|
4265
|
+
`[manifest] ${path40}: top-level "source" is loader-stamped \u2014 manifests must not author it`
|
|
4266
4266
|
);
|
|
4267
4267
|
}
|
|
4268
4268
|
rejectForbiddenKeys(
|
|
4269
4269
|
value[key],
|
|
4270
|
-
`${
|
|
4270
|
+
`${path40}.${key}`,
|
|
4271
4271
|
false
|
|
4272
4272
|
);
|
|
4273
4273
|
}
|
|
@@ -5208,8 +5208,8 @@ var init_client = __esm({
|
|
|
5208
5208
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
5209
5209
|
}
|
|
5210
5210
|
}
|
|
5211
|
-
async request(method,
|
|
5212
|
-
const url = `${this.baseUrl}${
|
|
5211
|
+
async request(method, path40, body, attempt = 0) {
|
|
5212
|
+
const url = `${this.baseUrl}${path40}`;
|
|
5213
5213
|
const controller = new AbortController();
|
|
5214
5214
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
5215
5215
|
const headers = {};
|
|
@@ -5225,7 +5225,7 @@ var init_client = __esm({
|
|
|
5225
5225
|
} catch (err) {
|
|
5226
5226
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
5227
5227
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
5228
|
-
return this.request(method,
|
|
5228
|
+
return this.request(method, path40, body, attempt + 1);
|
|
5229
5229
|
}
|
|
5230
5230
|
throw err;
|
|
5231
5231
|
} finally {
|
|
@@ -5644,7 +5644,7 @@ var init_container2 = __esm({
|
|
|
5644
5644
|
init_volume();
|
|
5645
5645
|
serviceContainerName = (worldId, serviceName) => `olam-${sanitizeContainerName(worldId)}-${sanitizeContainerName(serviceName)}`;
|
|
5646
5646
|
worldContainerName = (worldId) => `olam-${sanitizeContainerName(worldId)}-devbox`;
|
|
5647
|
-
miseCacheVolumeName = (
|
|
5647
|
+
miseCacheVolumeName = (arch2 = process.arch) => `olam-mise-cache-${arch2}`;
|
|
5648
5648
|
PACKAGE_MANAGER_CACHE_DIRS = [
|
|
5649
5649
|
{ name: "bundle", hostSubpath: ".olam/cache/bundle", containerPath: "/home/olam/.bundle/cache" },
|
|
5650
5650
|
{ name: "npm", hostSubpath: ".olam/cache/npm", containerPath: "/home/olam/.npm" },
|
|
@@ -6715,8 +6715,8 @@ var init_provider3 = __esm({
|
|
|
6715
6715
|
// -----------------------------------------------------------------------
|
|
6716
6716
|
// Internal fetch helper
|
|
6717
6717
|
// -----------------------------------------------------------------------
|
|
6718
|
-
async request(
|
|
6719
|
-
const url = `${this.config.workerUrl}${
|
|
6718
|
+
async request(path40, method, body) {
|
|
6719
|
+
const url = `${this.config.workerUrl}${path40}`;
|
|
6720
6720
|
const bearer = await this.config.mintToken();
|
|
6721
6721
|
const headers = {
|
|
6722
6722
|
Authorization: `Bearer ${bearer}`
|
|
@@ -6817,8 +6817,8 @@ var init_provider3 = __esm({
|
|
|
6817
6817
|
/**
|
|
6818
6818
|
* Submit thumbs-up / thumbs-down feedback for a session.
|
|
6819
6819
|
*/
|
|
6820
|
-
async submitFeedback(sessionId,
|
|
6821
|
-
const body = { sessionId, type, comment };
|
|
6820
|
+
async submitFeedback(sessionId, type2, comment) {
|
|
6821
|
+
const body = { sessionId, type: type2, comment };
|
|
6822
6822
|
const res = await this.request("/feedback", "POST", body);
|
|
6823
6823
|
await assertOk(res, `submitFeedback ${sessionId}`);
|
|
6824
6824
|
}
|
|
@@ -7570,8 +7570,8 @@ function copyDirRecursive(src, dest, depth = 0, skipFiles = /* @__PURE__ */ new
|
|
|
7570
7570
|
}
|
|
7571
7571
|
}
|
|
7572
7572
|
async function copyClaudeConfigIntoContainer(containerName) {
|
|
7573
|
-
const { execSync:
|
|
7574
|
-
const dockerExec = (cmd) =>
|
|
7573
|
+
const { execSync: execSync12 } = await import("node:child_process");
|
|
7574
|
+
const dockerExec = (cmd) => execSync12(`docker exec ${containerName} sh -c '${cmd}'`, { stdio: "pipe" });
|
|
7575
7575
|
dockerExec("mkdir -p /home/olam/.claude");
|
|
7576
7576
|
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");
|
|
7577
7577
|
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");
|
|
@@ -7589,7 +7589,7 @@ async function copyClaudeConfigIntoContainer(containerName) {
|
|
|
7589
7589
|
await sanitizeContainerClaudeHooks(containerName);
|
|
7590
7590
|
}
|
|
7591
7591
|
async function sanitizeContainerClaudeHooks(containerName) {
|
|
7592
|
-
const { execSync:
|
|
7592
|
+
const { execSync: execSync12 } = await import("node:child_process");
|
|
7593
7593
|
const script = `
|
|
7594
7594
|
const fs = require('fs');
|
|
7595
7595
|
const p = '/home/olam/.claude/settings.json';
|
|
@@ -7633,7 +7633,7 @@ if (changed) {
|
|
|
7633
7633
|
}
|
|
7634
7634
|
`;
|
|
7635
7635
|
try {
|
|
7636
|
-
|
|
7636
|
+
execSync12(
|
|
7637
7637
|
`docker exec ${containerName} /usr/local/bin/node -e ${shQuote(script)}`,
|
|
7638
7638
|
{ stdio: "pipe" }
|
|
7639
7639
|
);
|
|
@@ -7870,8 +7870,8 @@ import { execFileSync as execFileSync3 } from "node:child_process";
|
|
|
7870
7870
|
import * as fs13 from "node:fs";
|
|
7871
7871
|
import * as os9 from "node:os";
|
|
7872
7872
|
import * as path14 from "node:path";
|
|
7873
|
-
function expandHome(p,
|
|
7874
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
7873
|
+
function expandHome(p, homedir20) {
|
|
7874
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir20());
|
|
7875
7875
|
}
|
|
7876
7876
|
function sanitizeRepoFilename(name) {
|
|
7877
7877
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -7892,7 +7892,7 @@ ${stderr}`;
|
|
|
7892
7892
|
}
|
|
7893
7893
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
7894
7894
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync3(cmd, args, opts));
|
|
7895
|
-
const
|
|
7895
|
+
const homedir20 = deps.homedir ?? (() => os9.homedir());
|
|
7896
7896
|
const baselineDir = path14.join(workspacePath, ".olam", "baseline");
|
|
7897
7897
|
try {
|
|
7898
7898
|
fs13.mkdirSync(baselineDir, { recursive: true });
|
|
@@ -7907,7 +7907,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
7907
7907
|
if (!repo.path) continue;
|
|
7908
7908
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
7909
7909
|
const outPath = path14.join(baselineDir, filename);
|
|
7910
|
-
const repoPath = expandHome(repo.path,
|
|
7910
|
+
const repoPath = expandHome(repo.path, homedir20);
|
|
7911
7911
|
if (!fs13.existsSync(repoPath)) {
|
|
7912
7912
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
7913
7913
|
# (skipped: path ${repoPath} does not exist)
|
|
@@ -9960,7 +9960,7 @@ var init_manager = __esm({
|
|
|
9960
9960
|
console.warn(`[WorldManager] container git setup failed: ${msg}`);
|
|
9961
9961
|
}
|
|
9962
9962
|
try {
|
|
9963
|
-
const
|
|
9963
|
+
const safeExec2 = makeContainerExecFn(containerName);
|
|
9964
9964
|
let stacks;
|
|
9965
9965
|
if (preDetectedStacks.size > 0) {
|
|
9966
9966
|
stacks = preDetectedStacks;
|
|
@@ -9971,12 +9971,12 @@ var init_manager = __esm({
|
|
|
9971
9971
|
if (repo.stack && Object.keys(repo.stack).length > 0) {
|
|
9972
9972
|
stacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
|
|
9973
9973
|
} else {
|
|
9974
|
-
const detected = await detectRepoStack(
|
|
9974
|
+
const detected = await detectRepoStack(safeExec2, repoDir, repo.name);
|
|
9975
9975
|
stacks.set(repo.name, detected);
|
|
9976
9976
|
}
|
|
9977
9977
|
}
|
|
9978
9978
|
}
|
|
9979
|
-
const stackResult = await installStack(
|
|
9979
|
+
const stackResult = await installStack(safeExec2, enrichedRepos, stacks);
|
|
9980
9980
|
if (stackResult.installed.length > 0) {
|
|
9981
9981
|
const summary = stackResult.installed.map((r) => `${r.runtime}@${r.version}`).join(", ");
|
|
9982
9982
|
console.log(`[WorldManager] installed runtimes: ${summary}`);
|
|
@@ -10564,8 +10564,8 @@ var init_local_store = __esm({
|
|
|
10564
10564
|
const rows = this.db.prepare("SELECT * FROM thought_edges").all();
|
|
10565
10565
|
return rows.map(rowToEdge);
|
|
10566
10566
|
}
|
|
10567
|
-
getNodesByType(
|
|
10568
|
-
const rows = this.db.prepare("SELECT * FROM thought_nodes WHERE node_type = ? ORDER BY sequence_num").all(
|
|
10567
|
+
getNodesByType(type2) {
|
|
10568
|
+
const rows = this.db.prepare("SELECT * FROM thought_nodes WHERE node_type = ? ORDER BY sequence_num").all(type2);
|
|
10569
10569
|
return rows.map(rowToNode);
|
|
10570
10570
|
}
|
|
10571
10571
|
getChainToRoot(nodeId) {
|
|
@@ -12118,10 +12118,64 @@ var init_checksum = __esm({
|
|
|
12118
12118
|
}
|
|
12119
12119
|
});
|
|
12120
12120
|
|
|
12121
|
+
// ../core/src/config/machine-schema.ts
|
|
12122
|
+
var machine_schema_exports = {};
|
|
12123
|
+
__export(machine_schema_exports, {
|
|
12124
|
+
MachineConfigSchema: () => MachineConfigSchema,
|
|
12125
|
+
initMachineConfig: () => initMachineConfig,
|
|
12126
|
+
readMachineConfig: () => readMachineConfig,
|
|
12127
|
+
writeMachineConfig: () => writeMachineConfig
|
|
12128
|
+
});
|
|
12129
|
+
import * as fs32 from "node:fs";
|
|
12130
|
+
import * as path36 from "node:path";
|
|
12131
|
+
import * as os19 from "node:os";
|
|
12132
|
+
import { parse as parseYaml4, stringify as stringifyYaml4 } from "yaml";
|
|
12133
|
+
function readMachineConfig(configPath) {
|
|
12134
|
+
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
12135
|
+
if (!fs32.existsSync(p)) return null;
|
|
12136
|
+
try {
|
|
12137
|
+
const raw = fs32.readFileSync(p, "utf-8");
|
|
12138
|
+
const parsed = parseYaml4(raw);
|
|
12139
|
+
return MachineConfigSchema.parse(parsed);
|
|
12140
|
+
} catch {
|
|
12141
|
+
return null;
|
|
12142
|
+
}
|
|
12143
|
+
}
|
|
12144
|
+
function writeMachineConfig(config, configPath) {
|
|
12145
|
+
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
12146
|
+
fs32.mkdirSync(path36.dirname(p), { recursive: true });
|
|
12147
|
+
fs32.writeFileSync(p, stringifyYaml4({ ...config }), { mode: 420 });
|
|
12148
|
+
}
|
|
12149
|
+
function initMachineConfig(opts = {}) {
|
|
12150
|
+
const configPath = opts.configPath ?? DEFAULT_CONFIG_PATH;
|
|
12151
|
+
const existing = readMachineConfig(configPath);
|
|
12152
|
+
if (existing) return existing;
|
|
12153
|
+
const config = MachineConfigSchema.parse({
|
|
12154
|
+
telemetry: opts.telemetry ?? true
|
|
12155
|
+
});
|
|
12156
|
+
writeMachineConfig(config, configPath);
|
|
12157
|
+
return config;
|
|
12158
|
+
}
|
|
12159
|
+
var MachineConfigSchema, DEFAULT_CONFIG_PATH;
|
|
12160
|
+
var init_machine_schema = __esm({
|
|
12161
|
+
"../core/src/config/machine-schema.ts"() {
|
|
12162
|
+
"use strict";
|
|
12163
|
+
init_zod();
|
|
12164
|
+
MachineConfigSchema = external_exports.object({
|
|
12165
|
+
schema_version: external_exports.literal(1).default(1),
|
|
12166
|
+
channel: external_exports.enum(["stable", "beta", "edge"]).default("stable"),
|
|
12167
|
+
auto_update: external_exports.boolean().default(true),
|
|
12168
|
+
telemetry: external_exports.boolean().default(true),
|
|
12169
|
+
worlds_dir: external_exports.string().default(() => path36.join(os19.homedir(), ".olam", "worlds"))
|
|
12170
|
+
});
|
|
12171
|
+
DEFAULT_CONFIG_PATH = path36.join(os19.homedir(), ".olam", "config.yaml");
|
|
12172
|
+
}
|
|
12173
|
+
});
|
|
12174
|
+
|
|
12121
12175
|
// src/index.ts
|
|
12122
12176
|
import { Command } from "commander";
|
|
12123
|
-
import * as
|
|
12124
|
-
import * as
|
|
12177
|
+
import * as fs35 from "node:fs";
|
|
12178
|
+
import * as path39 from "node:path";
|
|
12125
12179
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
12126
12180
|
|
|
12127
12181
|
// src/commands/init.ts
|
|
@@ -12529,11 +12583,11 @@ var UnknownArchetypeError = class extends Error {
|
|
|
12529
12583
|
known;
|
|
12530
12584
|
};
|
|
12531
12585
|
var ArchetypeCycleError = class extends Error {
|
|
12532
|
-
constructor(
|
|
12586
|
+
constructor(path40) {
|
|
12533
12587
|
super(
|
|
12534
|
-
`Archetype inheritance cycle detected: ${
|
|
12588
|
+
`Archetype inheritance cycle detected: ${path40.join(" \u2192 ")} \u2192 ${path40[0] ?? "?"}`
|
|
12535
12589
|
);
|
|
12536
|
-
this.path =
|
|
12590
|
+
this.path = path40;
|
|
12537
12591
|
this.name = "ArchetypeCycleError";
|
|
12538
12592
|
}
|
|
12539
12593
|
path;
|
|
@@ -12547,15 +12601,15 @@ function walk(name, acc, stack) {
|
|
|
12547
12601
|
if (stack.includes(name)) {
|
|
12548
12602
|
throw new ArchetypeCycleError([...stack, name]);
|
|
12549
12603
|
}
|
|
12550
|
-
const
|
|
12551
|
-
if (!
|
|
12604
|
+
const arch2 = getArchetype(name);
|
|
12605
|
+
if (!arch2) {
|
|
12552
12606
|
throw new UnknownArchetypeError(name, listArchetypeNames());
|
|
12553
12607
|
}
|
|
12554
12608
|
const nextStack = [...stack, name];
|
|
12555
|
-
for (const parent of
|
|
12609
|
+
for (const parent of arch2.inherits ?? []) {
|
|
12556
12610
|
walk(parent, acc, nextStack);
|
|
12557
12611
|
}
|
|
12558
|
-
for (const cap of
|
|
12612
|
+
for (const cap of arch2.capabilities) {
|
|
12559
12613
|
acc.add(cap);
|
|
12560
12614
|
}
|
|
12561
12615
|
}
|
|
@@ -12659,8 +12713,8 @@ function registerInstall(program2) {
|
|
|
12659
12713
|
}
|
|
12660
12714
|
if (!opts.as) {
|
|
12661
12715
|
printError("Missing --as <archetype>. Known archetypes:");
|
|
12662
|
-
for (const
|
|
12663
|
-
console.log(` ${pc4.bold(
|
|
12716
|
+
for (const arch2 of ARCHETYPES) {
|
|
12717
|
+
console.log(` ${pc4.bold(arch2.name.padEnd(20))} ${pc4.dim(arch2.description)}`);
|
|
12664
12718
|
}
|
|
12665
12719
|
process.exitCode = 1;
|
|
12666
12720
|
return;
|
|
@@ -13374,10 +13428,10 @@ async function readHostCpToken2() {
|
|
|
13374
13428
|
if (!fs19.existsSync(tp)) return null;
|
|
13375
13429
|
return fs19.readFileSync(tp, "utf-8").trim();
|
|
13376
13430
|
}
|
|
13377
|
-
async function callHostCpProxy(method, worldId,
|
|
13431
|
+
async function callHostCpProxy(method, worldId, path40, body) {
|
|
13378
13432
|
const token = await readHostCpToken2();
|
|
13379
13433
|
if (!token) return { ok: false, status: 0, error: "no token (host CP not started)" };
|
|
13380
|
-
const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${
|
|
13434
|
+
const url = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path40}`;
|
|
13381
13435
|
try {
|
|
13382
13436
|
const headers = {
|
|
13383
13437
|
Authorization: `Bearer ${token}`
|
|
@@ -14450,9 +14504,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
14450
14504
|
"These source files have changed since the image was built; the",
|
|
14451
14505
|
"changes will NOT take effect in fresh worlds until you rebuild:"
|
|
14452
14506
|
];
|
|
14453
|
-
for (const { path:
|
|
14507
|
+
for (const { path: path40, mtimeMs } of result.newerSources) {
|
|
14454
14508
|
const when = new Date(mtimeMs).toISOString();
|
|
14455
|
-
lines.push(` \u2022 ${
|
|
14509
|
+
lines.push(` \u2022 ${path40} (modified ${when})`);
|
|
14456
14510
|
}
|
|
14457
14511
|
lines.push("");
|
|
14458
14512
|
lines.push("Rebuild with:");
|
|
@@ -14612,15 +14666,15 @@ init_context();
|
|
|
14612
14666
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
14613
14667
|
async function readHostCpTokenForCreate() {
|
|
14614
14668
|
try {
|
|
14615
|
-
const { default:
|
|
14616
|
-
const { default:
|
|
14617
|
-
const { default:
|
|
14618
|
-
const tp =
|
|
14619
|
-
process.env.OLAM_HOME ??
|
|
14669
|
+
const { default: fs36 } = await import("node:fs");
|
|
14670
|
+
const { default: os21 } = await import("node:os");
|
|
14671
|
+
const { default: path40 } = await import("node:path");
|
|
14672
|
+
const tp = path40.join(
|
|
14673
|
+
process.env.OLAM_HOME ?? path40.join(os21.homedir(), ".olam"),
|
|
14620
14674
|
"host-cp.token"
|
|
14621
14675
|
);
|
|
14622
|
-
if (!
|
|
14623
|
-
return
|
|
14676
|
+
if (!fs36.existsSync(tp)) return null;
|
|
14677
|
+
return fs36.readFileSync(tp, "utf-8").trim();
|
|
14624
14678
|
} catch {
|
|
14625
14679
|
return null;
|
|
14626
14680
|
}
|
|
@@ -14982,12 +15036,12 @@ function defaultNameFromPrompt(prompt) {
|
|
|
14982
15036
|
}
|
|
14983
15037
|
async function readHostCpToken3() {
|
|
14984
15038
|
try {
|
|
14985
|
-
const { default:
|
|
14986
|
-
const { default:
|
|
14987
|
-
const { default:
|
|
14988
|
-
const tp =
|
|
14989
|
-
if (!
|
|
14990
|
-
const raw =
|
|
15039
|
+
const { default: fs36 } = await import("node:fs");
|
|
15040
|
+
const { default: os21 } = await import("node:os");
|
|
15041
|
+
const { default: path40 } = await import("node:path");
|
|
15042
|
+
const tp = path40.join(os21.homedir(), ".olam", "host-cp.token");
|
|
15043
|
+
if (!fs36.existsSync(tp)) return null;
|
|
15044
|
+
const raw = fs36.readFileSync(tp, "utf-8").trim();
|
|
14991
15045
|
return raw.length > 0 ? raw : null;
|
|
14992
15046
|
} catch {
|
|
14993
15047
|
return null;
|
|
@@ -16200,15 +16254,15 @@ var AST = class {
|
|
|
16200
16254
|
parts: this.#parts
|
|
16201
16255
|
};
|
|
16202
16256
|
}
|
|
16203
|
-
constructor(
|
|
16204
|
-
this.type =
|
|
16205
|
-
if (
|
|
16257
|
+
constructor(type2, parent, options = {}) {
|
|
16258
|
+
this.type = type2;
|
|
16259
|
+
if (type2)
|
|
16206
16260
|
this.#hasMagic = true;
|
|
16207
16261
|
this.#parent = parent;
|
|
16208
16262
|
this.#root = this.#parent ? this.#parent.#root : this;
|
|
16209
16263
|
this.#options = this.#root === this ? options : this.#root.#options;
|
|
16210
16264
|
this.#negs = this.#root === this ? [] : this.#root.#negs;
|
|
16211
|
-
if (
|
|
16265
|
+
if (type2 === "!" && !this.#root.#filledNegs)
|
|
16212
16266
|
this.#negs.push(this);
|
|
16213
16267
|
this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0;
|
|
16214
16268
|
}
|
|
@@ -16851,8 +16905,8 @@ var defaults = (def) => {
|
|
|
16851
16905
|
},
|
|
16852
16906
|
AST: class AST extends orig.AST {
|
|
16853
16907
|
/* c8 ignore start */
|
|
16854
|
-
constructor(
|
|
16855
|
-
super(
|
|
16908
|
+
constructor(type2, parent, options = {}) {
|
|
16909
|
+
super(type2, parent, ext(def, options));
|
|
16856
16910
|
}
|
|
16857
16911
|
/* c8 ignore stop */
|
|
16858
16912
|
static fromGlob(pattern, options = {}) {
|
|
@@ -19936,19 +19990,477 @@ Run \`olam refresh\` from the olam repo root.`
|
|
|
19936
19990
|
});
|
|
19937
19991
|
}
|
|
19938
19992
|
|
|
19939
|
-
// src/
|
|
19993
|
+
// src/commands/diagnose.ts
|
|
19940
19994
|
import * as fs30 from "node:fs";
|
|
19995
|
+
import * as os18 from "node:os";
|
|
19941
19996
|
import * as path34 from "node:path";
|
|
19997
|
+
import { execFileSync as execFileSync5, execSync as execSync10 } from "node:child_process";
|
|
19998
|
+
import pc20 from "picocolors";
|
|
19999
|
+
|
|
20000
|
+
// ../core/src/diagnose/secret-stripper.ts
|
|
20001
|
+
var SECRET_PATTERNS = [
|
|
20002
|
+
{ name: "anthropic-key", re: /sk-ant-[A-Za-z0-9\-_]{8,}/g },
|
|
20003
|
+
{ name: "github-pat", re: /gh[pourstu]_[A-Za-z0-9]{20,}/g },
|
|
20004
|
+
{ name: "github-pat-fgp", re: /github_pat_[A-Za-z0-9_]{22,}/g },
|
|
20005
|
+
{ name: "aws-access-key", re: /AKIA[A-Z0-9]{16}/g },
|
|
20006
|
+
{ name: "bearer-header", re: /Bearer\s+[A-Za-z0-9._\-+/=]{16,}/g },
|
|
20007
|
+
{ name: "slack-token", re: /xox[bpsa]-[A-Za-z0-9-]{10,}/g },
|
|
20008
|
+
{ name: "host-cp-token", re: /(?:host[-_.]?cp[-_.]?token|"token")\s*[:=]\s*"?([A-Za-z0-9._\-]{16,})"?/gi },
|
|
20009
|
+
{ name: "generic-hex-key", re: /\bkey\s*[:=]\s*[0-9a-f]{32,}/gi },
|
|
20010
|
+
{ name: "db-url", re: /(?:postgres|mysql|redis|mongodb):\/\/[^:]+:[^@]+@[^\s'"]+/gi },
|
|
20011
|
+
{ name: "env-secret", re: /(?:API_KEY|SECRET_KEY|AUTH_TOKEN|ACCESS_TOKEN|PRIVATE_KEY|DATABASE_URL|REDIS_URL)\s*[=:]\s*\S+/gi },
|
|
20012
|
+
{ name: "pem-key", re: /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC )?PRIVATE KEY-----/g }
|
|
20013
|
+
];
|
|
20014
|
+
var REDACTED = "[REDACTED]";
|
|
20015
|
+
function stripSecrets(input) {
|
|
20016
|
+
let out = input;
|
|
20017
|
+
for (const { re } of SECRET_PATTERNS) {
|
|
20018
|
+
re.lastIndex = 0;
|
|
20019
|
+
out = out.replace(re, (match2) => {
|
|
20020
|
+
const colonOrEq = match2.indexOf(":") !== -1 ? match2.indexOf(":") : match2.indexOf("=");
|
|
20021
|
+
if (colonOrEq !== -1 && (match2.includes("token") || match2.includes("key") || match2.includes("KEY"))) {
|
|
20022
|
+
return match2.slice(0, colonOrEq + 1) + " " + REDACTED;
|
|
20023
|
+
}
|
|
20024
|
+
return REDACTED;
|
|
20025
|
+
});
|
|
20026
|
+
}
|
|
20027
|
+
return out;
|
|
20028
|
+
}
|
|
20029
|
+
|
|
20030
|
+
// src/commands/diagnose.ts
|
|
20031
|
+
var DIAGNOSTICS_DIR = path34.join(os18.homedir(), ".olam", "diagnostics");
|
|
20032
|
+
var LOG_DIR = path34.join(os18.homedir(), ".olam", "log");
|
|
20033
|
+
var CACHE_DIR = path34.join(os18.homedir(), ".olam", "cache");
|
|
20034
|
+
var LOG_TAIL_LINES = 200;
|
|
20035
|
+
function safeExec(cmd) {
|
|
20036
|
+
try {
|
|
20037
|
+
return execSync10(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
20038
|
+
} catch {
|
|
20039
|
+
return "";
|
|
20040
|
+
}
|
|
20041
|
+
}
|
|
20042
|
+
function defaultZip(zipPath, files) {
|
|
20043
|
+
execFileSync5("zip", ["-j", zipPath, ...files]);
|
|
20044
|
+
}
|
|
20045
|
+
async function buildDiagnosticsZip(_exec = (cmd) => safeExec(cmd), _outDir = DIAGNOSTICS_DIR, _logDir = LOG_DIR, _zip = defaultZip) {
|
|
20046
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 23);
|
|
20047
|
+
const zipPath = path34.join(_outDir, `olam-diag-${ts}.zip`);
|
|
20048
|
+
const tmpDir = fs30.mkdtempSync(path34.join(os18.tmpdir(), "olam-diag-"));
|
|
20049
|
+
try {
|
|
20050
|
+
fs30.mkdirSync(_outDir, { recursive: true });
|
|
20051
|
+
const entries = [];
|
|
20052
|
+
const version = process.env["OLAM_CLI_VERSION"] ?? "unknown";
|
|
20053
|
+
const nodeVersion = process.version;
|
|
20054
|
+
const platform = `${process.platform}/${process.arch}`;
|
|
20055
|
+
const versionContent = `olam: ${version}
|
|
20056
|
+
node: ${nodeVersion}
|
|
20057
|
+
platform: ${platform}
|
|
20058
|
+
`;
|
|
20059
|
+
_writeEntry(tmpDir, "version.txt", stripSecrets(versionContent), entries);
|
|
20060
|
+
const osContent = [
|
|
20061
|
+
`os: ${os18.type()} ${os18.release()}`,
|
|
20062
|
+
`arch: ${os18.arch()}`,
|
|
20063
|
+
`uptime: ${os18.uptime()}s`
|
|
20064
|
+
].join("\n") + "\n";
|
|
20065
|
+
_writeEntry(tmpDir, "os-info.txt", stripSecrets(osContent), entries);
|
|
20066
|
+
const depsFile = path34.join(CACHE_DIR, "deps.json");
|
|
20067
|
+
if (fs30.existsSync(depsFile)) {
|
|
20068
|
+
const deps = fs30.readFileSync(depsFile, "utf-8");
|
|
20069
|
+
_writeEntry(tmpDir, "deps.json", stripSecrets(deps), entries);
|
|
20070
|
+
}
|
|
20071
|
+
const latestLog = _latestLog(_logDir);
|
|
20072
|
+
if (latestLog) {
|
|
20073
|
+
const lines = fs30.readFileSync(latestLog, "utf-8").split("\n");
|
|
20074
|
+
const tail = lines.slice(-LOG_TAIL_LINES).join("\n");
|
|
20075
|
+
_writeEntry(tmpDir, "log-tail.txt", stripSecrets(tail), entries);
|
|
20076
|
+
}
|
|
20077
|
+
const statusOut = _exec("olam status --json");
|
|
20078
|
+
if (statusOut) {
|
|
20079
|
+
_writeEntry(tmpDir, "status.json", stripSecrets(statusOut), entries);
|
|
20080
|
+
}
|
|
20081
|
+
const authAudit = _exec("npm run audit:auth-callers --if-present 2>&1");
|
|
20082
|
+
if (authAudit) {
|
|
20083
|
+
_writeEntry(tmpDir, "audit-auth-callers.txt", stripSecrets(authAudit), entries);
|
|
20084
|
+
}
|
|
20085
|
+
const fileArgs = entries.map((e) => path34.join(tmpDir, e));
|
|
20086
|
+
try {
|
|
20087
|
+
_zip(zipPath, fileArgs);
|
|
20088
|
+
} catch (err) {
|
|
20089
|
+
throw new Error(`zip command produced no output file. zip stderr: ${err.message}`);
|
|
20090
|
+
}
|
|
20091
|
+
if (!fs30.existsSync(zipPath)) {
|
|
20092
|
+
throw new Error("zip command produced no output file.");
|
|
20093
|
+
}
|
|
20094
|
+
return { zipPath, entries };
|
|
20095
|
+
} finally {
|
|
20096
|
+
try {
|
|
20097
|
+
fs30.rmSync(tmpDir, { recursive: true, force: true });
|
|
20098
|
+
} catch {
|
|
20099
|
+
}
|
|
20100
|
+
}
|
|
20101
|
+
}
|
|
20102
|
+
function _writeEntry(dir, name, content, entries) {
|
|
20103
|
+
fs30.writeFileSync(path34.join(dir, name), content, { mode: 420 });
|
|
20104
|
+
entries.push(name);
|
|
20105
|
+
}
|
|
20106
|
+
function _latestLog(logDir) {
|
|
20107
|
+
if (!fs30.existsSync(logDir)) return null;
|
|
20108
|
+
const files = fs30.readdirSync(logDir).filter((f) => f.startsWith("host-")).sort().reverse();
|
|
20109
|
+
return files.length > 0 ? path34.join(logDir, files[0]) : null;
|
|
20110
|
+
}
|
|
20111
|
+
async function buildTelemetryPayload() {
|
|
20112
|
+
const channel = "stable";
|
|
20113
|
+
const manifestFile = path34.join(CACHE_DIR, "manifest.json");
|
|
20114
|
+
let manifestAgeHours = null;
|
|
20115
|
+
if (fs30.existsSync(manifestFile)) {
|
|
20116
|
+
const mtime = fs30.statSync(manifestFile).mtime.getTime();
|
|
20117
|
+
manifestAgeHours = Math.round((Date.now() - mtime) / 36e5);
|
|
20118
|
+
}
|
|
20119
|
+
return {
|
|
20120
|
+
version: process.env["OLAM_CLI_VERSION"] ?? "unknown",
|
|
20121
|
+
os: process.platform,
|
|
20122
|
+
arch: process.arch,
|
|
20123
|
+
channel,
|
|
20124
|
+
manifest_age_hours: manifestAgeHours
|
|
20125
|
+
// No userid, no project, no path — privacy per design doc
|
|
20126
|
+
};
|
|
20127
|
+
}
|
|
20128
|
+
function registerDiagnose(program2) {
|
|
20129
|
+
program2.command("diagnose").description("Bundle diagnostics into a zip file for sharing with maintainers").option("--show-telemetry", "Print the telemetry payload that would be sent (no endpoint yet)").option("--no-telemetry", "Suppress telemetry payload (future opt-out)").option("--upload", "Share zip with maintainers (endpoint not yet provisioned)").option("--quiet", "Suppress progress output").action(async (opts) => {
|
|
20130
|
+
if (opts.showTelemetry) {
|
|
20131
|
+
const payload = await buildTelemetryPayload();
|
|
20132
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
20133
|
+
return;
|
|
20134
|
+
}
|
|
20135
|
+
if (!opts.quiet) {
|
|
20136
|
+
console.log(pc20.cyan("Building diagnostics zip\u2026"));
|
|
20137
|
+
}
|
|
20138
|
+
try {
|
|
20139
|
+
const { zipPath, entries } = await buildDiagnosticsZip();
|
|
20140
|
+
if (!opts.quiet) {
|
|
20141
|
+
console.log(pc20.green(`Done: ${zipPath}`));
|
|
20142
|
+
console.log(pc20.dim(`Contents: ${entries.join(", ")}`));
|
|
20143
|
+
}
|
|
20144
|
+
if (opts.upload) {
|
|
20145
|
+
console.log(pc20.yellow(
|
|
20146
|
+
`Telemetry endpoint not yet provisioned. Share the zip manually:
|
|
20147
|
+
File: ${zipPath}
|
|
20148
|
+
See docs/runbooks/share-diagnostics.md for instructions.`
|
|
20149
|
+
));
|
|
20150
|
+
}
|
|
20151
|
+
} catch (err) {
|
|
20152
|
+
console.error(pc20.red(`Diagnose failed: ${err.message}`));
|
|
20153
|
+
process.exitCode = 1;
|
|
20154
|
+
}
|
|
20155
|
+
});
|
|
20156
|
+
}
|
|
20157
|
+
|
|
20158
|
+
// src/commands/update.ts
|
|
20159
|
+
import * as fs33 from "node:fs";
|
|
20160
|
+
import * as os20 from "node:os";
|
|
20161
|
+
import * as path37 from "node:path";
|
|
20162
|
+
import { execSync as execSync11 } from "node:child_process";
|
|
20163
|
+
import pc21 from "picocolors";
|
|
20164
|
+
|
|
20165
|
+
// src/lib/symlink-reconcile.ts
|
|
20166
|
+
import * as fs31 from "node:fs";
|
|
20167
|
+
import * as path35 from "node:path";
|
|
20168
|
+
var realFs = {
|
|
20169
|
+
readdirSync: (p) => fs31.readdirSync(p),
|
|
20170
|
+
existsSync: (p) => fs31.existsSync(p),
|
|
20171
|
+
lstatSync: (p) => fs31.lstatSync(p),
|
|
20172
|
+
readlinkSync: (p) => fs31.readlinkSync(p),
|
|
20173
|
+
symlinkSync: (t, l) => fs31.symlinkSync(t, l),
|
|
20174
|
+
unlinkSync: (p) => fs31.unlinkSync(p),
|
|
20175
|
+
mkdirSync: (p, o) => {
|
|
20176
|
+
fs31.mkdirSync(p, o);
|
|
20177
|
+
}
|
|
20178
|
+
};
|
|
20179
|
+
function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir, _fs = realFs) {
|
|
20180
|
+
const added = [];
|
|
20181
|
+
const removed = [];
|
|
20182
|
+
const kept = [];
|
|
20183
|
+
_fs.mkdirSync(claudeSkillsDir, { recursive: true });
|
|
20184
|
+
const sourceSkills = _fs.existsSync(npmSkillsDir) ? _fs.readdirSync(npmSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
20185
|
+
for (const skill of sourceSkills) {
|
|
20186
|
+
const linkPath = path35.join(claudeSkillsDir, skill);
|
|
20187
|
+
const target = path35.join(npmSkillsDir, skill);
|
|
20188
|
+
if (!_fs.existsSync(linkPath)) {
|
|
20189
|
+
try {
|
|
20190
|
+
_fs.symlinkSync(target, linkPath);
|
|
20191
|
+
added.push(skill);
|
|
20192
|
+
} catch (e) {
|
|
20193
|
+
if (e.code !== "EEXIST") throw e;
|
|
20194
|
+
kept.push(skill);
|
|
20195
|
+
}
|
|
20196
|
+
}
|
|
20197
|
+
}
|
|
20198
|
+
const deployedEntries = _fs.existsSync(claudeSkillsDir) ? _fs.readdirSync(claudeSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
20199
|
+
for (const entry of deployedEntries) {
|
|
20200
|
+
const linkPath = path35.join(claudeSkillsDir, entry);
|
|
20201
|
+
let isSymlink = false;
|
|
20202
|
+
try {
|
|
20203
|
+
isSymlink = _fs.lstatSync(linkPath).isSymbolicLink();
|
|
20204
|
+
} catch {
|
|
20205
|
+
continue;
|
|
20206
|
+
}
|
|
20207
|
+
if (!isSymlink) continue;
|
|
20208
|
+
const target = _fs.readlinkSync(linkPath);
|
|
20209
|
+
if (!target.includes("@pleri/olam-cli")) {
|
|
20210
|
+
kept.push(entry);
|
|
20211
|
+
continue;
|
|
20212
|
+
}
|
|
20213
|
+
if (_fs.existsSync(target)) {
|
|
20214
|
+
kept.push(entry);
|
|
20215
|
+
} else {
|
|
20216
|
+
_fs.unlinkSync(linkPath);
|
|
20217
|
+
removed.push(entry);
|
|
20218
|
+
}
|
|
20219
|
+
}
|
|
20220
|
+
return { added, removed, kept };
|
|
20221
|
+
}
|
|
20222
|
+
|
|
20223
|
+
// src/commands/update.ts
|
|
20224
|
+
var PACKAGE_NAME = "@pleri/olam-cli";
|
|
20225
|
+
var CACHE_DIR2 = path37.join(os20.homedir(), ".olam", "cache");
|
|
20226
|
+
var LOG_DIR2 = path37.join(os20.homedir(), ".olam", "log");
|
|
20227
|
+
var LAST_STABLE_FILE = path37.join(CACHE_DIR2, "last-stable.txt");
|
|
20228
|
+
function defaultExec(cmd) {
|
|
20229
|
+
try {
|
|
20230
|
+
const stdout = execSync11(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
20231
|
+
return { exitCode: 0, stdout, stderr: "" };
|
|
20232
|
+
} catch (err) {
|
|
20233
|
+
const e = err;
|
|
20234
|
+
return { exitCode: e.status ?? 1, stdout: e.stdout ?? "", stderr: e.stderr ?? "" };
|
|
20235
|
+
}
|
|
20236
|
+
}
|
|
20237
|
+
function getCurrentVersion(_exec = defaultExec) {
|
|
20238
|
+
const result = _exec(`npm ls -g ${PACKAGE_NAME} --json --depth=0`);
|
|
20239
|
+
if (result.exitCode !== 0) return null;
|
|
20240
|
+
try {
|
|
20241
|
+
const parsed = JSON.parse(result.stdout);
|
|
20242
|
+
return parsed.dependencies?.[PACKAGE_NAME]?.version ?? null;
|
|
20243
|
+
} catch {
|
|
20244
|
+
return null;
|
|
20245
|
+
}
|
|
20246
|
+
}
|
|
20247
|
+
function readLastStable(file = LAST_STABLE_FILE) {
|
|
20248
|
+
try {
|
|
20249
|
+
const v = fs33.readFileSync(file, "utf-8").trim();
|
|
20250
|
+
return v || null;
|
|
20251
|
+
} catch {
|
|
20252
|
+
return null;
|
|
20253
|
+
}
|
|
20254
|
+
}
|
|
20255
|
+
function writeLastStable(version, file = LAST_STABLE_FILE) {
|
|
20256
|
+
fs33.mkdirSync(path37.dirname(file), { recursive: true });
|
|
20257
|
+
fs33.writeFileSync(file, version, { mode: 420 });
|
|
20258
|
+
}
|
|
20259
|
+
function logUpdateFailure(stderr) {
|
|
20260
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
20261
|
+
const logFile = path37.join(LOG_DIR2, `update-${ts}.log`);
|
|
20262
|
+
try {
|
|
20263
|
+
fs33.mkdirSync(LOG_DIR2, { recursive: true });
|
|
20264
|
+
fs33.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
20265
|
+
${stderr}
|
|
20266
|
+
`, "utf-8");
|
|
20267
|
+
} catch {
|
|
20268
|
+
}
|
|
20269
|
+
}
|
|
20270
|
+
var SAFE_VERSION_RE = /^[a-zA-Z0-9._-]{1,64}$/;
|
|
20271
|
+
function isUpgradeBlocked(channelOrVersion, _exec = defaultExec) {
|
|
20272
|
+
if (!SAFE_VERSION_RE.test(channelOrVersion)) return false;
|
|
20273
|
+
const result = _exec(`npm view ${PACKAGE_NAME}@${channelOrVersion} olam.upgrade_blocked --json`);
|
|
20274
|
+
if (result.exitCode !== 0) return false;
|
|
20275
|
+
try {
|
|
20276
|
+
const val = JSON.parse(result.stdout.trim());
|
|
20277
|
+
return val === true;
|
|
20278
|
+
} catch {
|
|
20279
|
+
return false;
|
|
20280
|
+
}
|
|
20281
|
+
}
|
|
20282
|
+
async function doUpdate(opts, _exec = defaultExec, _reconcile = reconcileSkillSymlinks, _readConfig, _getNpmRoot = defaultExec) {
|
|
20283
|
+
const readConfig = _readConfig ?? (async () => {
|
|
20284
|
+
const { readMachineConfig: readMachineConfig2 } = await Promise.resolve().then(() => (init_machine_schema(), machine_schema_exports));
|
|
20285
|
+
return readMachineConfig2();
|
|
20286
|
+
});
|
|
20287
|
+
const config = await readConfig();
|
|
20288
|
+
const channel = opts.channel ?? config?.channel ?? "stable";
|
|
20289
|
+
const quiet = opts.quiet ?? false;
|
|
20290
|
+
const force = opts.force ?? false;
|
|
20291
|
+
if (!SAFE_VERSION_RE.test(channel)) {
|
|
20292
|
+
if (!quiet) console.error(`Invalid channel/version: ${channel}`);
|
|
20293
|
+
return { action: "failed", exitCode: 11 };
|
|
20294
|
+
}
|
|
20295
|
+
if (!force && config && config.auto_update === false) {
|
|
20296
|
+
if (!quiet) {
|
|
20297
|
+
console.log("Updates frozen. Run `olam update --force` to override or `olam update --freeze` to manage.");
|
|
20298
|
+
}
|
|
20299
|
+
return { action: "failed", exitCode: 11 };
|
|
20300
|
+
}
|
|
20301
|
+
if (!force) {
|
|
20302
|
+
const blocked = isUpgradeBlocked(channel, _exec);
|
|
20303
|
+
if (blocked) {
|
|
20304
|
+
if (!quiet) {
|
|
20305
|
+
console.error(`Version @${channel} has upgrade_blocked: true. Run with --force to override.`);
|
|
20306
|
+
}
|
|
20307
|
+
return { action: "failed", exitCode: 11 };
|
|
20308
|
+
}
|
|
20309
|
+
}
|
|
20310
|
+
const prevVersion = getCurrentVersion(_exec);
|
|
20311
|
+
if (prevVersion) {
|
|
20312
|
+
writeLastStable(prevVersion);
|
|
20313
|
+
}
|
|
20314
|
+
if (!quiet) {
|
|
20315
|
+
console.log(pc21.cyan(`Installing ${PACKAGE_NAME}@${channel}\u2026`));
|
|
20316
|
+
}
|
|
20317
|
+
const installResult = _exec(`npm install -g ${PACKAGE_NAME}@${channel}`);
|
|
20318
|
+
if (installResult.exitCode !== 0) {
|
|
20319
|
+
logUpdateFailure(installResult.stderr);
|
|
20320
|
+
if (!quiet) {
|
|
20321
|
+
console.error(pc21.red("Update failed."));
|
|
20322
|
+
}
|
|
20323
|
+
const prev = readLastStable();
|
|
20324
|
+
if (prev) {
|
|
20325
|
+
if (!quiet) {
|
|
20326
|
+
console.log(pc21.yellow(`Restoring to ${prev}\u2026`));
|
|
20327
|
+
}
|
|
20328
|
+
const restoreResult = _exec(`npm install -g ${PACKAGE_NAME}@${prev}`);
|
|
20329
|
+
if (restoreResult.exitCode !== 0) {
|
|
20330
|
+
if (!quiet) {
|
|
20331
|
+
console.error(pc21.red(
|
|
20332
|
+
`Restore also failed. Run: npm install -g ${PACKAGE_NAME}@${prev} manually.`
|
|
20333
|
+
));
|
|
20334
|
+
}
|
|
20335
|
+
} else if (!quiet) {
|
|
20336
|
+
console.log(pc21.yellow(`Restored to ${prev}.`));
|
|
20337
|
+
}
|
|
20338
|
+
} else if (!quiet) {
|
|
20339
|
+
console.error(pc21.red("No previous version cached; cannot auto-restore."));
|
|
20340
|
+
}
|
|
20341
|
+
return { action: "restored", prevVersion: prev ?? void 0, exitCode: 11 };
|
|
20342
|
+
}
|
|
20343
|
+
const newVersion = getCurrentVersion(_exec) ?? void 0;
|
|
20344
|
+
if (!quiet && newVersion) {
|
|
20345
|
+
console.log(pc21.green(`Updated to ${newVersion}.`));
|
|
20346
|
+
}
|
|
20347
|
+
const npmRootResult = _getNpmRoot("npm root -g");
|
|
20348
|
+
let symlinkResult = { added: [], removed: [] };
|
|
20349
|
+
if (npmRootResult.exitCode === 0) {
|
|
20350
|
+
const npmRoot = npmRootResult.stdout.trim();
|
|
20351
|
+
const npmSkillsDir = path37.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
|
|
20352
|
+
const claudeSkillsDir = path37.join(os20.homedir(), ".claude", "skills");
|
|
20353
|
+
const rec = _reconcile(npmSkillsDir, claudeSkillsDir);
|
|
20354
|
+
symlinkResult = { added: rec.added, removed: rec.removed };
|
|
20355
|
+
if (!quiet && (rec.added.length > 0 || rec.removed.length > 0)) {
|
|
20356
|
+
if (rec.added.length > 0) {
|
|
20357
|
+
console.log(pc21.dim(`Skills added: ${rec.added.join(", ")}`));
|
|
20358
|
+
}
|
|
20359
|
+
if (rec.removed.length > 0) {
|
|
20360
|
+
console.log(pc21.dim(`Skills removed (dangling): ${rec.removed.join(", ")}`));
|
|
20361
|
+
}
|
|
20362
|
+
}
|
|
20363
|
+
}
|
|
20364
|
+
return {
|
|
20365
|
+
action: "installed",
|
|
20366
|
+
version: newVersion,
|
|
20367
|
+
prevVersion: prevVersion ?? void 0,
|
|
20368
|
+
exitCode: 0,
|
|
20369
|
+
symlinks: symlinkResult
|
|
20370
|
+
};
|
|
20371
|
+
}
|
|
20372
|
+
async function doCheck(_exec = defaultExec) {
|
|
20373
|
+
const current = getCurrentVersion(_exec);
|
|
20374
|
+
const viewResult = _exec(`npm view ${PACKAGE_NAME} dist-tags.stable`);
|
|
20375
|
+
const latest = viewResult.exitCode === 0 ? viewResult.stdout.trim() || null : null;
|
|
20376
|
+
if (current && latest && current === latest) {
|
|
20377
|
+
return { action: "already-current", current, latest, exitCode: 10 };
|
|
20378
|
+
}
|
|
20379
|
+
return { action: "update-available", current, latest, exitCode: 0 };
|
|
20380
|
+
}
|
|
20381
|
+
async function doRollback(_exec = defaultExec, _reconcile = reconcileSkillSymlinks, _getNpmRoot = defaultExec) {
|
|
20382
|
+
const prev = readLastStable();
|
|
20383
|
+
if (!prev) {
|
|
20384
|
+
return { action: "nothing-to-rollback", exitCode: 14 };
|
|
20385
|
+
}
|
|
20386
|
+
const current = getCurrentVersion(_exec);
|
|
20387
|
+
if (current && current === prev) {
|
|
20388
|
+
return { action: "already-at-cached", restoredVersion: prev, exitCode: 0 };
|
|
20389
|
+
}
|
|
20390
|
+
const result = _exec(`npm install -g ${PACKAGE_NAME}@${prev}`);
|
|
20391
|
+
if (result.exitCode !== 0) {
|
|
20392
|
+
return { action: "failed", restoredVersion: prev, exitCode: 11 };
|
|
20393
|
+
}
|
|
20394
|
+
const npmRootResult = _getNpmRoot("npm root -g");
|
|
20395
|
+
if (npmRootResult.exitCode === 0) {
|
|
20396
|
+
const npmRoot = npmRootResult.stdout.trim();
|
|
20397
|
+
_reconcile(
|
|
20398
|
+
path37.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
|
|
20399
|
+
path37.join(os20.homedir(), ".claude", "skills")
|
|
20400
|
+
);
|
|
20401
|
+
}
|
|
20402
|
+
return { action: "rolled-back", restoredVersion: prev, exitCode: 0 };
|
|
20403
|
+
}
|
|
20404
|
+
function registerUpdate(program2) {
|
|
20405
|
+
program2.command("update").description("Update @pleri/olam-cli to the latest version on the configured channel").option("--to <version>", "Install a specific version").option("--rollback", "Restore the previously installed version").option("--check", "Check if a newer version is available (read-only)").option("--channel <channel>", "Switch to channel and install (stable|beta|edge)").option("--freeze", "Disable automatic updates (sets auto_update: false)").option("--force", "Override freeze and upgrade_blocked checks").option("--quiet", "Suppress output").action(async (opts) => {
|
|
20406
|
+
if (opts.freeze) {
|
|
20407
|
+
const { readMachineConfig: readMachineConfig2, writeMachineConfig: writeMachineConfig2, MachineConfigSchema: MachineConfigSchema2 } = await Promise.resolve().then(() => (init_machine_schema(), machine_schema_exports));
|
|
20408
|
+
const cfg = readMachineConfig2() ?? MachineConfigSchema2.parse({});
|
|
20409
|
+
writeMachineConfig2({ ...cfg, auto_update: false });
|
|
20410
|
+
if (!opts.quiet) console.log("Updates frozen. Run `olam update --force` to override.");
|
|
20411
|
+
return;
|
|
20412
|
+
}
|
|
20413
|
+
if (opts.check) {
|
|
20414
|
+
const r = await doCheck();
|
|
20415
|
+
if (!opts.quiet) {
|
|
20416
|
+
if (r.action === "already-current") {
|
|
20417
|
+
console.log(`Already on latest: ${r.current}`);
|
|
20418
|
+
} else {
|
|
20419
|
+
console.log(`Current: ${r.current ?? "unknown"}, Latest: ${r.latest ?? "unknown"}`);
|
|
20420
|
+
}
|
|
20421
|
+
}
|
|
20422
|
+
process.exitCode = r.exitCode;
|
|
20423
|
+
return;
|
|
20424
|
+
}
|
|
20425
|
+
if (opts.rollback) {
|
|
20426
|
+
const r = await doRollback();
|
|
20427
|
+
if (!opts.quiet) {
|
|
20428
|
+
if (r.action === "nothing-to-rollback") {
|
|
20429
|
+
console.error("Nothing to roll back. Use --to=<version> for a specific target.");
|
|
20430
|
+
} else if (r.action === "already-at-cached") {
|
|
20431
|
+
console.log(`Already at cached version ${r.restoredVersion}. Use --to=<v> for older targets.`);
|
|
20432
|
+
} else if (r.action === "rolled-back") {
|
|
20433
|
+
console.log(`Rolled back to ${r.restoredVersion}.`);
|
|
20434
|
+
} else {
|
|
20435
|
+
console.error(`Rollback failed.`);
|
|
20436
|
+
}
|
|
20437
|
+
}
|
|
20438
|
+
process.exitCode = r.exitCode;
|
|
20439
|
+
return;
|
|
20440
|
+
}
|
|
20441
|
+
if (opts.channel) {
|
|
20442
|
+
const { readMachineConfig: readMachineConfig2, writeMachineConfig: writeMachineConfig2, MachineConfigSchema: MachineConfigSchema2 } = await Promise.resolve().then(() => (init_machine_schema(), machine_schema_exports));
|
|
20443
|
+
const cfg = readMachineConfig2() ?? MachineConfigSchema2.parse({});
|
|
20444
|
+
writeMachineConfig2({ ...cfg, channel: opts.channel });
|
|
20445
|
+
}
|
|
20446
|
+
const result = await doUpdate({ channel: opts.to ?? opts.channel, quiet: opts.quiet, force: opts.force });
|
|
20447
|
+
process.exitCode = result.exitCode;
|
|
20448
|
+
});
|
|
20449
|
+
}
|
|
20450
|
+
|
|
20451
|
+
// src/pleri-config.ts
|
|
20452
|
+
import * as fs34 from "node:fs";
|
|
20453
|
+
import * as path38 from "node:path";
|
|
19942
20454
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
19943
20455
|
if (process.env.PLERI_BASE_URL) {
|
|
19944
20456
|
return true;
|
|
19945
20457
|
}
|
|
19946
|
-
const configPath =
|
|
19947
|
-
if (!
|
|
20458
|
+
const configPath = path38.join(configDir, "config.yaml");
|
|
20459
|
+
if (!fs34.existsSync(configPath)) {
|
|
19948
20460
|
return false;
|
|
19949
20461
|
}
|
|
19950
20462
|
try {
|
|
19951
|
-
const contents =
|
|
20463
|
+
const contents = fs34.readFileSync(configPath, "utf8");
|
|
19952
20464
|
return /^[^#\n]*\bpleri:/m.test(contents);
|
|
19953
20465
|
} catch {
|
|
19954
20466
|
return false;
|
|
@@ -19959,14 +20471,14 @@ function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
|
19959
20471
|
var program = new Command();
|
|
19960
20472
|
function readCliVersion() {
|
|
19961
20473
|
try {
|
|
19962
|
-
const here =
|
|
20474
|
+
const here = path39.dirname(fileURLToPath4(import.meta.url));
|
|
19963
20475
|
for (const candidate of [
|
|
19964
|
-
|
|
19965
|
-
|
|
19966
|
-
|
|
20476
|
+
path39.join(here, "package.json"),
|
|
20477
|
+
path39.join(here, "..", "package.json"),
|
|
20478
|
+
path39.join(here, "..", "..", "package.json")
|
|
19967
20479
|
]) {
|
|
19968
|
-
if (
|
|
19969
|
-
const pkg = JSON.parse(
|
|
20480
|
+
if (fs35.existsSync(candidate)) {
|
|
20481
|
+
const pkg = JSON.parse(fs35.readFileSync(candidate, "utf-8"));
|
|
19970
20482
|
if (typeof pkg.version === "string" && pkg.version.length > 0) return pkg.version;
|
|
19971
20483
|
}
|
|
19972
20484
|
}
|
|
@@ -19998,4 +20510,6 @@ registerKeys(program);
|
|
|
19998
20510
|
registerWorldSnapshot(program);
|
|
19999
20511
|
registerRefresh(program);
|
|
20000
20512
|
registerBootstrap(program);
|
|
20513
|
+
registerDiagnose(program);
|
|
20514
|
+
registerUpdate(program);
|
|
20001
20515
|
program.parse();
|