@pleri/olam-cli 0.1.208 → 0.1.210
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/image-digests.json +8 -8
- package/dist/index.js +796 -437
- package/dist/mcp-server.js +200 -32
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
- package/host-cp/src/server.mjs +18 -5
- package/memory-hooks/agent-memory-gate.mjs +103 -0
- package/memory-hooks/agentmemory-save.mjs +4 -0
- package/memory-hooks/agentmemory-session-recall.js +8 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -535,8 +535,8 @@ var init_parseUtil = __esm({
|
|
|
535
535
|
init_errors();
|
|
536
536
|
init_en();
|
|
537
537
|
makeIssue = (params) => {
|
|
538
|
-
const { data, path:
|
|
539
|
-
const fullPath = [...
|
|
538
|
+
const { data, path: path122, errorMaps, issueData } = params;
|
|
539
|
+
const fullPath = [...path122, ...issueData.path || []];
|
|
540
540
|
const fullIssue = {
|
|
541
541
|
...issueData,
|
|
542
542
|
path: fullPath
|
|
@@ -844,11 +844,11 @@ var init_types = __esm({
|
|
|
844
844
|
init_parseUtil();
|
|
845
845
|
init_util();
|
|
846
846
|
ParseInputLazyPath = class {
|
|
847
|
-
constructor(parent, value,
|
|
847
|
+
constructor(parent, value, path122, key) {
|
|
848
848
|
this._cachedPath = [];
|
|
849
849
|
this.parent = parent;
|
|
850
850
|
this.data = value;
|
|
851
|
-
this._path =
|
|
851
|
+
this._path = path122;
|
|
852
852
|
this._key = key;
|
|
853
853
|
}
|
|
854
854
|
get path() {
|
|
@@ -4336,7 +4336,7 @@ import YAML from "yaml";
|
|
|
4336
4336
|
function bootstrapStepCmd(entry) {
|
|
4337
4337
|
return typeof entry === "string" ? entry : entry.cmd;
|
|
4338
4338
|
}
|
|
4339
|
-
function refineForbiddenKeys(value,
|
|
4339
|
+
function refineForbiddenKeys(value, path122, ctx, rejectSource) {
|
|
4340
4340
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4341
4341
|
return;
|
|
4342
4342
|
}
|
|
@@ -4344,12 +4344,12 @@ function refineForbiddenKeys(value, path121, ctx, rejectSource) {
|
|
|
4344
4344
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4345
4345
|
ctx.addIssue({
|
|
4346
4346
|
code: external_exports.ZodIssueCode.custom,
|
|
4347
|
-
path: [...
|
|
4347
|
+
path: [...path122, key],
|
|
4348
4348
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
4349
4349
|
});
|
|
4350
4350
|
continue;
|
|
4351
4351
|
}
|
|
4352
|
-
if (rejectSource &&
|
|
4352
|
+
if (rejectSource && path122.length === 0 && key === "source") {
|
|
4353
4353
|
ctx.addIssue({
|
|
4354
4354
|
code: external_exports.ZodIssueCode.custom,
|
|
4355
4355
|
path: ["source"],
|
|
@@ -4357,21 +4357,21 @@ function refineForbiddenKeys(value, path121, ctx, rejectSource) {
|
|
|
4357
4357
|
});
|
|
4358
4358
|
continue;
|
|
4359
4359
|
}
|
|
4360
|
-
refineForbiddenKeys(value[key], [...
|
|
4360
|
+
refineForbiddenKeys(value[key], [...path122, key], ctx, false);
|
|
4361
4361
|
}
|
|
4362
4362
|
}
|
|
4363
|
-
function rejectForbiddenKeys(value,
|
|
4363
|
+
function rejectForbiddenKeys(value, path122, rejectSource) {
|
|
4364
4364
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4365
4365
|
return;
|
|
4366
4366
|
}
|
|
4367
4367
|
for (const key of Object.keys(value)) {
|
|
4368
4368
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4369
|
-
throw new Error(`[manifest] ${
|
|
4369
|
+
throw new Error(`[manifest] ${path122}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
4370
4370
|
}
|
|
4371
4371
|
if (rejectSource && key === "source") {
|
|
4372
|
-
throw new Error(`[manifest] ${
|
|
4372
|
+
throw new Error(`[manifest] ${path122}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
4373
4373
|
}
|
|
4374
|
-
rejectForbiddenKeys(value[key], `${
|
|
4374
|
+
rejectForbiddenKeys(value[key], `${path122}.${key}`, false);
|
|
4375
4375
|
}
|
|
4376
4376
|
}
|
|
4377
4377
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -5645,16 +5645,16 @@ function isValidConfig(value) {
|
|
|
5645
5645
|
if (typeof v.install_id !== "string" || v.install_id.length === 0) return false;
|
|
5646
5646
|
return true;
|
|
5647
5647
|
}
|
|
5648
|
-
function atomicWriteJSON(
|
|
5648
|
+
function atomicWriteJSON(path122, value, stderr = process.stderr) {
|
|
5649
5649
|
ensureStateDir();
|
|
5650
|
-
const dir = dirname3(
|
|
5650
|
+
const dir = dirname3(path122);
|
|
5651
5651
|
if (!existsSync6(dir)) {
|
|
5652
5652
|
mkdirSync2(dir, { recursive: true });
|
|
5653
5653
|
}
|
|
5654
|
-
const tmp = `${
|
|
5654
|
+
const tmp = `${path122}.tmp.${process.pid}`;
|
|
5655
5655
|
try {
|
|
5656
5656
|
writeFileSync2(tmp, JSON.stringify(value, null, 2) + "\n", { encoding: "utf8" });
|
|
5657
|
-
renameSync2(tmp,
|
|
5657
|
+
renameSync2(tmp, path122);
|
|
5658
5658
|
} catch (err) {
|
|
5659
5659
|
if (existsSync6(tmp)) {
|
|
5660
5660
|
try {
|
|
@@ -5669,16 +5669,16 @@ function atomicWriteJSON(path121, value, stderr = process.stderr) {
|
|
|
5669
5669
|
throw err;
|
|
5670
5670
|
}
|
|
5671
5671
|
}
|
|
5672
|
-
function atomicWriteYaml(
|
|
5672
|
+
function atomicWriteYaml(path122, value, stderr = process.stderr) {
|
|
5673
5673
|
ensureStateDir();
|
|
5674
|
-
const dir = dirname3(
|
|
5674
|
+
const dir = dirname3(path122);
|
|
5675
5675
|
if (!existsSync6(dir)) {
|
|
5676
5676
|
mkdirSync2(dir, { recursive: true });
|
|
5677
5677
|
}
|
|
5678
|
-
const tmp = `${
|
|
5678
|
+
const tmp = `${path122}.tmp.${process.pid}`;
|
|
5679
5679
|
try {
|
|
5680
5680
|
writeFileSync2(tmp, stringifyYaml3(value), { encoding: "utf8" });
|
|
5681
|
-
renameSync2(tmp,
|
|
5681
|
+
renameSync2(tmp, path122);
|
|
5682
5682
|
} catch (err) {
|
|
5683
5683
|
if (existsSync6(tmp)) {
|
|
5684
5684
|
try {
|
|
@@ -5693,11 +5693,11 @@ function atomicWriteYaml(path121, value, stderr = process.stderr) {
|
|
|
5693
5693
|
throw err;
|
|
5694
5694
|
}
|
|
5695
5695
|
}
|
|
5696
|
-
function atomicWrite(
|
|
5697
|
-
if (isYamlPath(
|
|
5698
|
-
atomicWriteYaml(
|
|
5696
|
+
function atomicWrite(path122, value, stderr = process.stderr) {
|
|
5697
|
+
if (isYamlPath(path122)) {
|
|
5698
|
+
atomicWriteYaml(path122, value, stderr);
|
|
5699
5699
|
} else {
|
|
5700
|
-
atomicWriteJSON(
|
|
5700
|
+
atomicWriteJSON(path122, value, stderr);
|
|
5701
5701
|
}
|
|
5702
5702
|
}
|
|
5703
5703
|
function readConfig(opts = {}) {
|
|
@@ -6006,8 +6006,8 @@ var init_client = __esm({
|
|
|
6006
6006
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
6007
6007
|
}
|
|
6008
6008
|
}
|
|
6009
|
-
async request(method,
|
|
6010
|
-
const url2 = `${this.baseUrl}${
|
|
6009
|
+
async request(method, path122, body, attempt = 0) {
|
|
6010
|
+
const url2 = `${this.baseUrl}${path122}`;
|
|
6011
6011
|
const controller = new AbortController();
|
|
6012
6012
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
6013
6013
|
const headers = {};
|
|
@@ -6025,7 +6025,7 @@ var init_client = __esm({
|
|
|
6025
6025
|
} catch (err) {
|
|
6026
6026
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
6027
6027
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
6028
|
-
return this.request(method,
|
|
6028
|
+
return this.request(method, path122, body, attempt + 1);
|
|
6029
6029
|
}
|
|
6030
6030
|
throw err;
|
|
6031
6031
|
} finally {
|
|
@@ -7903,8 +7903,8 @@ var init_provider3 = __esm({
|
|
|
7903
7903
|
// -----------------------------------------------------------------------
|
|
7904
7904
|
// Internal fetch helper
|
|
7905
7905
|
// -----------------------------------------------------------------------
|
|
7906
|
-
async request(
|
|
7907
|
-
const url2 = `${this.config.workerUrl}${
|
|
7906
|
+
async request(path122, method, body) {
|
|
7907
|
+
const url2 = `${this.config.workerUrl}${path122}`;
|
|
7908
7908
|
const bearer = await this.config.mintToken();
|
|
7909
7909
|
const headers = {
|
|
7910
7910
|
Authorization: `Bearer ${bearer}`
|
|
@@ -9740,17 +9740,17 @@ function kgRoot() {
|
|
|
9740
9740
|
function worldsRoot() {
|
|
9741
9741
|
return join19(olamHome3(), "worlds");
|
|
9742
9742
|
}
|
|
9743
|
-
function assertWithinPrefix(
|
|
9744
|
-
if (!
|
|
9745
|
-
throw new Error(`${label} escape: ${
|
|
9743
|
+
function assertWithinPrefix(path122, prefix, label) {
|
|
9744
|
+
if (!path122.startsWith(prefix + "/")) {
|
|
9745
|
+
throw new Error(`${label} escape: ${path122} not under ${prefix}/`);
|
|
9746
9746
|
}
|
|
9747
9747
|
}
|
|
9748
9748
|
function kgPristinePath(workspace) {
|
|
9749
9749
|
validateWorkspaceName(workspace);
|
|
9750
9750
|
const root = kgRoot();
|
|
9751
|
-
const
|
|
9752
|
-
assertWithinPrefix(
|
|
9753
|
-
return
|
|
9751
|
+
const path122 = resolve6(join19(root, workspace));
|
|
9752
|
+
assertWithinPrefix(path122, root, "kgPristinePath");
|
|
9753
|
+
return path122;
|
|
9754
9754
|
}
|
|
9755
9755
|
var KG_PATHS_INTERNALS;
|
|
9756
9756
|
var init_storage_paths = __esm({
|
|
@@ -9865,8 +9865,8 @@ import { execFileSync as execFileSync4 } from "node:child_process";
|
|
|
9865
9865
|
import * as fs17 from "node:fs";
|
|
9866
9866
|
import * as os10 from "node:os";
|
|
9867
9867
|
import * as path19 from "node:path";
|
|
9868
|
-
function expandHome2(p,
|
|
9869
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
9868
|
+
function expandHome2(p, homedir90) {
|
|
9869
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir90());
|
|
9870
9870
|
}
|
|
9871
9871
|
function sanitizeRepoFilename(name) {
|
|
9872
9872
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -9889,7 +9889,7 @@ ${stderr}`;
|
|
|
9889
9889
|
}
|
|
9890
9890
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
9891
9891
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
|
|
9892
|
-
const
|
|
9892
|
+
const homedir90 = deps.homedir ?? (() => os10.homedir());
|
|
9893
9893
|
const baselineDir = path19.join(workspacePath, ".olam", "baseline");
|
|
9894
9894
|
try {
|
|
9895
9895
|
fs17.mkdirSync(baselineDir, { recursive: true });
|
|
@@ -9905,7 +9905,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
9905
9905
|
continue;
|
|
9906
9906
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
9907
9907
|
const outPath = path19.join(baselineDir, filename);
|
|
9908
|
-
const repoPath = expandHome2(repo.path,
|
|
9908
|
+
const repoPath = expandHome2(repo.path, homedir90);
|
|
9909
9909
|
if (!fs17.existsSync(repoPath)) {
|
|
9910
9910
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
9911
9911
|
# (skipped: path ${repoPath} does not exist)
|
|
@@ -10025,8 +10025,8 @@ function extractStderr(err) {
|
|
|
10025
10025
|
}
|
|
10026
10026
|
function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
10027
10027
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
|
|
10028
|
-
const
|
|
10029
|
-
const
|
|
10028
|
+
const homedir90 = deps.homedir ?? (() => os10.homedir());
|
|
10029
|
+
const existsSync137 = deps.existsSync ?? ((p) => fs17.existsSync(p));
|
|
10030
10030
|
const copyFileSync20 = deps.copyFileSync ?? ((src, dest) => fs17.copyFileSync(src, dest));
|
|
10031
10031
|
const mkdirSync81 = deps.mkdirSync ?? ((dirPath, opts) => {
|
|
10032
10032
|
fs17.mkdirSync(dirPath, opts);
|
|
@@ -10035,11 +10035,11 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
10035
10035
|
for (const repo of repos) {
|
|
10036
10036
|
if (!repo.path)
|
|
10037
10037
|
continue;
|
|
10038
|
-
const repoPath = expandHome2(repo.path,
|
|
10038
|
+
const repoPath = expandHome2(repo.path, homedir90);
|
|
10039
10039
|
const worktreePath = path19.join(workspacePath, repo.name);
|
|
10040
|
-
if (!
|
|
10040
|
+
if (!existsSync137(repoPath))
|
|
10041
10041
|
continue;
|
|
10042
|
-
if (!
|
|
10042
|
+
if (!existsSync137(worktreePath)) {
|
|
10043
10043
|
console.warn(`[carry] ${repo.name}: world worktree ${worktreePath} missing; skipping carry for this repo`);
|
|
10044
10044
|
continue;
|
|
10045
10045
|
}
|
|
@@ -10099,7 +10099,7 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
10099
10099
|
for (const rel of plan.diff.untracked) {
|
|
10100
10100
|
const src = path19.join(plan.repoPath, rel);
|
|
10101
10101
|
const dest = path19.join(plan.worktreePath, rel);
|
|
10102
|
-
if (!
|
|
10102
|
+
if (!existsSync137(src))
|
|
10103
10103
|
continue;
|
|
10104
10104
|
try {
|
|
10105
10105
|
mkdirSync81(path19.dirname(dest), { recursive: true });
|
|
@@ -16708,10 +16708,10 @@ async function readHostCpToken2() {
|
|
|
16708
16708
|
if (!fs29.existsSync(tp)) return null;
|
|
16709
16709
|
return fs29.readFileSync(tp, "utf-8").trim();
|
|
16710
16710
|
}
|
|
16711
|
-
async function callHostCpProxy(method, worldId,
|
|
16711
|
+
async function callHostCpProxy(method, worldId, path122, body) {
|
|
16712
16712
|
const token = await readHostCpToken2();
|
|
16713
16713
|
if (!token) return { ok: false, status: 0, error: "no token (host CP not started)" };
|
|
16714
|
-
const url2 = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${
|
|
16714
|
+
const url2 = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path122}`;
|
|
16715
16715
|
try {
|
|
16716
16716
|
const headers = {
|
|
16717
16717
|
Authorization: `Bearer ${token}`
|
|
@@ -17132,57 +17132,57 @@ import { randomBytes as randomBytes8 } from "node:crypto";
|
|
|
17132
17132
|
function generateSecret() {
|
|
17133
17133
|
return randomBytes8(SECRET_LEN_BYTES).toString("hex");
|
|
17134
17134
|
}
|
|
17135
|
-
function writeSecretAtPath(
|
|
17136
|
-
mkdirSync23(dirname23(
|
|
17137
|
-
const tmp = `${
|
|
17135
|
+
function writeSecretAtPath(path122, value) {
|
|
17136
|
+
mkdirSync23(dirname23(path122), { recursive: true, mode: 448 });
|
|
17137
|
+
const tmp = `${path122}.tmp.${process.pid}`;
|
|
17138
17138
|
writeFileSync18(tmp, value, { mode: 384 });
|
|
17139
17139
|
chmodSync8(tmp, 384);
|
|
17140
|
-
renameSync7(tmp,
|
|
17140
|
+
renameSync7(tmp, path122);
|
|
17141
17141
|
}
|
|
17142
|
-
function readSecretAtPathOrNull(
|
|
17143
|
-
if (!existsSync34(
|
|
17144
|
-
const mode = statSync9(
|
|
17142
|
+
function readSecretAtPathOrNull(path122) {
|
|
17143
|
+
if (!existsSync34(path122)) return null;
|
|
17144
|
+
const mode = statSync9(path122).mode & 511;
|
|
17145
17145
|
if (mode !== 384) {
|
|
17146
17146
|
process.stderr.write(
|
|
17147
|
-
`warn: ${
|
|
17147
|
+
`warn: ${path122} has mode 0${mode.toString(8)}; expected 0600. Run 'olam memory secret rotate' to regenerate.
|
|
17148
17148
|
`
|
|
17149
17149
|
);
|
|
17150
17150
|
}
|
|
17151
|
-
return readFileSync28(
|
|
17151
|
+
return readFileSync28(path122, "utf8").trim();
|
|
17152
17152
|
}
|
|
17153
|
-
function readSecretAtPath(
|
|
17154
|
-
const v = readSecretAtPathOrNull(
|
|
17153
|
+
function readSecretAtPath(path122) {
|
|
17154
|
+
const v = readSecretAtPathOrNull(path122);
|
|
17155
17155
|
if (v === null) {
|
|
17156
17156
|
throw new Error(
|
|
17157
|
-
`Secret not found at ${
|
|
17157
|
+
`Secret not found at ${path122}. Run 'olam memory start' to generate it.`
|
|
17158
17158
|
);
|
|
17159
17159
|
}
|
|
17160
17160
|
return v;
|
|
17161
17161
|
}
|
|
17162
|
-
function ensureMemorySecret(
|
|
17163
|
-
const existing = readSecretAtPathOrNull(
|
|
17162
|
+
function ensureMemorySecret(path122 = MEMORY_SECRET_PATH) {
|
|
17163
|
+
const existing = readSecretAtPathOrNull(path122);
|
|
17164
17164
|
if (existing) return existing;
|
|
17165
17165
|
const fresh = generateSecret();
|
|
17166
|
-
const writePath =
|
|
17166
|
+
const writePath = path122 === MEMORY_SECRET_PATH ? MEMORY_SECRET_CANONICAL_PATH : path122;
|
|
17167
17167
|
writeSecretAtPath(writePath, fresh);
|
|
17168
17168
|
return fresh;
|
|
17169
17169
|
}
|
|
17170
|
-
function readMemorySecretOrNull(
|
|
17171
|
-
return readSecretAtPathOrNull(
|
|
17170
|
+
function readMemorySecretOrNull(path122 = MEMORY_SECRET_PATH) {
|
|
17171
|
+
return readSecretAtPathOrNull(path122);
|
|
17172
17172
|
}
|
|
17173
|
-
function readMemorySecret(
|
|
17174
|
-
return readSecretAtPath(
|
|
17173
|
+
function readMemorySecret(path122 = MEMORY_SECRET_PATH) {
|
|
17174
|
+
return readSecretAtPath(path122);
|
|
17175
17175
|
}
|
|
17176
|
-
function rotateMemorySecret(
|
|
17176
|
+
function rotateMemorySecret(path122 = MEMORY_SECRET_CANONICAL_PATH) {
|
|
17177
17177
|
const fresh = generateSecret();
|
|
17178
|
-
writeSecretAtPath(
|
|
17178
|
+
writeSecretAtPath(path122, fresh);
|
|
17179
17179
|
return fresh;
|
|
17180
17180
|
}
|
|
17181
|
-
function hasMemorySecret(
|
|
17182
|
-
return existsSync34(
|
|
17181
|
+
function hasMemorySecret(path122 = MEMORY_SECRET_PATH) {
|
|
17182
|
+
return existsSync34(path122);
|
|
17183
17183
|
}
|
|
17184
|
-
function writeCloudMemorySecret(value,
|
|
17185
|
-
writeSecretAtPath(
|
|
17184
|
+
function writeCloudMemorySecret(value, path122 = CLOUD_MEMORY_SECRET_CANONICAL_PATH) {
|
|
17185
|
+
writeSecretAtPath(path122, value);
|
|
17186
17186
|
}
|
|
17187
17187
|
var MEMORY_SECRET_PATH, CLOUD_MEMORY_SECRET_PATH, MEMORY_SECRET_CANONICAL_PATH, CLOUD_MEMORY_SECRET_CANONICAL_PATH, SECRET_LEN_BYTES;
|
|
17188
17188
|
var init_memory_secret = __esm({
|
|
@@ -17260,31 +17260,31 @@ __export(from_manifest_exports, {
|
|
|
17260
17260
|
provenanceLine: () => provenanceLine
|
|
17261
17261
|
});
|
|
17262
17262
|
import { readFileSync as readFileSync37 } from "node:fs";
|
|
17263
|
-
function parseForkManifest(
|
|
17263
|
+
function parseForkManifest(path122) {
|
|
17264
17264
|
let raw;
|
|
17265
17265
|
try {
|
|
17266
|
-
raw = readFileSync37(
|
|
17266
|
+
raw = readFileSync37(path122, "utf8");
|
|
17267
17267
|
} catch (err) {
|
|
17268
17268
|
const reason = err?.code === "ENOENT" ? "file does not exist" : err.message;
|
|
17269
|
-
throw new Error(`--from-manifest: cannot read ${
|
|
17269
|
+
throw new Error(`--from-manifest: cannot read ${path122} (${reason})`);
|
|
17270
17270
|
}
|
|
17271
17271
|
let json;
|
|
17272
17272
|
try {
|
|
17273
17273
|
json = JSON.parse(raw);
|
|
17274
17274
|
} catch (err) {
|
|
17275
|
-
throw new Error(`--from-manifest: ${
|
|
17275
|
+
throw new Error(`--from-manifest: ${path122} is not valid JSON (${err.message})`);
|
|
17276
17276
|
}
|
|
17277
17277
|
if (!isPlainObject2(json)) {
|
|
17278
|
-
throw new Error(`--from-manifest: ${
|
|
17278
|
+
throw new Error(`--from-manifest: ${path122} root must be a JSON object`);
|
|
17279
17279
|
}
|
|
17280
17280
|
const originalWorldId = json.originalWorldId;
|
|
17281
17281
|
if (typeof originalWorldId !== "string" || originalWorldId.trim().length === 0) {
|
|
17282
|
-
throw new Error(`--from-manifest: ${
|
|
17282
|
+
throw new Error(`--from-manifest: ${path122} missing required string "originalWorldId"`);
|
|
17283
17283
|
}
|
|
17284
17284
|
const newPrompt = json.newPrompt;
|
|
17285
17285
|
if (typeof newPrompt !== "string" || newPrompt.trim().length === 0) {
|
|
17286
17286
|
throw new Error(
|
|
17287
|
-
`--from-manifest: ${
|
|
17287
|
+
`--from-manifest: ${path122} has no "newPrompt" \u2014 re-run trace-replay with --with-prompt "<alternate dispatch>"`
|
|
17288
17288
|
);
|
|
17289
17289
|
}
|
|
17290
17290
|
const fp = isPlainObject2(json.forkPoint) ? json.forkPoint : {};
|
|
@@ -17295,7 +17295,7 @@ function parseForkManifest(path121) {
|
|
|
17295
17295
|
originalWorldId: originalWorldId.trim(),
|
|
17296
17296
|
forkPoint: { resolvedPhase, resolvedSpanId, resolvedAt },
|
|
17297
17297
|
newPrompt,
|
|
17298
|
-
manifestPath:
|
|
17298
|
+
manifestPath: path122
|
|
17299
17299
|
};
|
|
17300
17300
|
}
|
|
17301
17301
|
function defaultNameFromManifest(manifest) {
|
|
@@ -17390,10 +17390,10 @@ function legacySecretPath(home = homedir27()) {
|
|
|
17390
17390
|
return join53(home, ".olam", "secrets", "plan-agent-secret");
|
|
17391
17391
|
}
|
|
17392
17392
|
function readRemoteConnection() {
|
|
17393
|
-
for (const
|
|
17393
|
+
for (const path122 of [planChatConnectionPath(), legacyConnectionPath()]) {
|
|
17394
17394
|
try {
|
|
17395
|
-
if (!existsSync45(
|
|
17396
|
-
const parsed = JSON.parse(readFileSync38(
|
|
17395
|
+
if (!existsSync45(path122)) continue;
|
|
17396
|
+
const parsed = JSON.parse(readFileSync38(path122, "utf8"));
|
|
17397
17397
|
if (typeof parsed.url !== "string" || parsed.url.length === 0) continue;
|
|
17398
17398
|
return {
|
|
17399
17399
|
url: parsed.url,
|
|
@@ -17407,12 +17407,12 @@ function readRemoteConnection() {
|
|
|
17407
17407
|
return null;
|
|
17408
17408
|
}
|
|
17409
17409
|
function writeRemoteConnection(input2) {
|
|
17410
|
-
const
|
|
17411
|
-
mkdirSync29(dirname30(
|
|
17410
|
+
const path122 = planChatConnectionPath();
|
|
17411
|
+
mkdirSync29(dirname30(path122), { recursive: true, mode: 448 });
|
|
17412
17412
|
const payload = { url: input2.url, connectedAt: input2.connectedAt };
|
|
17413
17413
|
if (input2.password) payload["password"] = input2.password;
|
|
17414
17414
|
if (input2.bearer) payload["bearer"] = input2.bearer;
|
|
17415
|
-
writeSecretAtPath(
|
|
17415
|
+
writeSecretAtPath(path122, JSON.stringify(payload, null, 2) + "\n");
|
|
17416
17416
|
}
|
|
17417
17417
|
function resolveRemoteUrl2() {
|
|
17418
17418
|
const env = process.env["OLAM_CLOUD_URL"];
|
|
@@ -17726,9 +17726,9 @@ function memoryConnectionPath() {
|
|
|
17726
17726
|
}
|
|
17727
17727
|
function readMemoryConnection() {
|
|
17728
17728
|
try {
|
|
17729
|
-
const
|
|
17730
|
-
if (!existsSync63(
|
|
17731
|
-
const parsed = JSON.parse(readFileSync55(
|
|
17729
|
+
const path122 = memoryConnectionPath();
|
|
17730
|
+
if (!existsSync63(path122)) return null;
|
|
17731
|
+
const parsed = JSON.parse(readFileSync55(path122, "utf8"));
|
|
17732
17732
|
if (typeof parsed.url !== "string" || parsed.url.length === 0) return null;
|
|
17733
17733
|
return { url: parsed.url, connectedAt: parsed.connectedAt ?? "" };
|
|
17734
17734
|
} catch {
|
|
@@ -17736,9 +17736,9 @@ function readMemoryConnection() {
|
|
|
17736
17736
|
}
|
|
17737
17737
|
}
|
|
17738
17738
|
function writeMemoryConnection(url2, connectedAt) {
|
|
17739
|
-
const
|
|
17740
|
-
mkdirSync39(dirname36(
|
|
17741
|
-
writeSecretAtPath(
|
|
17739
|
+
const path122 = memoryConnectionPath();
|
|
17740
|
+
mkdirSync39(dirname36(path122), { recursive: true, mode: 448 });
|
|
17741
|
+
writeSecretAtPath(path122, JSON.stringify({ url: url2, connectedAt }, null, 2) + "\n");
|
|
17742
17742
|
}
|
|
17743
17743
|
var init_memory_connection = __esm({
|
|
17744
17744
|
"src/lib/memory-connection.ts"() {
|
|
@@ -19407,16 +19407,25 @@ function settingsBackupDir() {
|
|
|
19407
19407
|
return override;
|
|
19408
19408
|
return path73.join(os38.homedir(), ".olam", "state", "settings-backups");
|
|
19409
19409
|
}
|
|
19410
|
+
function entryKey(entry) {
|
|
19411
|
+
const cmds = commandsInEntry(entry);
|
|
19412
|
+
const cmdKey = cmds.length > 0 ? cmds[0] : "";
|
|
19413
|
+
return `${entry.matcher ?? ""}\0${cmdKey}`;
|
|
19414
|
+
}
|
|
19410
19415
|
function dedupeByMatcher(entries) {
|
|
19411
19416
|
const map = /* @__PURE__ */ new Map();
|
|
19412
19417
|
for (const e of entries) {
|
|
19413
|
-
|
|
19414
|
-
const cmdKey = cmds.length > 0 ? cmds[0] : "";
|
|
19415
|
-
const key = `${e.matcher ?? ""}\0${cmdKey}`;
|
|
19416
|
-
map.set(key, e);
|
|
19418
|
+
map.set(entryKey(e), e);
|
|
19417
19419
|
}
|
|
19418
19420
|
return [...map.values()];
|
|
19419
19421
|
}
|
|
19422
|
+
function reclaimLegacyDuplicates(preserved, olamFinal) {
|
|
19423
|
+
if (olamFinal.length === 0)
|
|
19424
|
+
return { kept: preserved, reclaimedCount: 0 };
|
|
19425
|
+
const olamKeys = new Set(olamFinal.map(entryKey));
|
|
19426
|
+
const kept = preserved.filter((e) => !olamKeys.has(entryKey(e)));
|
|
19427
|
+
return { kept, reclaimedCount: preserved.length - kept.length };
|
|
19428
|
+
}
|
|
19420
19429
|
function commandsInEntry(entry) {
|
|
19421
19430
|
const cmds = [];
|
|
19422
19431
|
const direct = entry["command"];
|
|
@@ -19517,6 +19526,7 @@ function mergeSettings(input2) {
|
|
|
19517
19526
|
]);
|
|
19518
19527
|
let hooksAdded = 0;
|
|
19519
19528
|
let dualWriteDeduped = 0;
|
|
19529
|
+
let legacyReclaimed = 0;
|
|
19520
19530
|
const dualWriteDroppedCommands = [];
|
|
19521
19531
|
for (const cat of categories) {
|
|
19522
19532
|
const existing = Array.isArray(existingHooks[cat]) ? existingHooks[cat] : [];
|
|
@@ -19526,7 +19536,9 @@ function mergeSettings(input2) {
|
|
|
19526
19536
|
const { kept: olamFinal, droppedCount, droppedCommands } = applyDualWriteDedup(olamDeduped, preserved);
|
|
19527
19537
|
dualWriteDeduped += droppedCount;
|
|
19528
19538
|
dualWriteDroppedCommands.push(...droppedCommands);
|
|
19529
|
-
|
|
19539
|
+
const { kept: preservedFinal, reclaimedCount } = reclaimLegacyDuplicates(preserved, olamFinal);
|
|
19540
|
+
legacyReclaimed += reclaimedCount;
|
|
19541
|
+
mergedHooks[cat] = [...preservedFinal, ...olamFinal];
|
|
19530
19542
|
hooksAdded += olamFinal.length;
|
|
19531
19543
|
}
|
|
19532
19544
|
const permSet = /* @__PURE__ */ new Set();
|
|
@@ -19556,7 +19568,14 @@ function mergeSettings(input2) {
|
|
|
19556
19568
|
const tmp = `${settingsPath}.tmp-${process.pid}`;
|
|
19557
19569
|
fs75.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
|
|
19558
19570
|
fs75.renameSync(tmp, settingsPath);
|
|
19559
|
-
return {
|
|
19571
|
+
return {
|
|
19572
|
+
backupPath,
|
|
19573
|
+
hooksAdded,
|
|
19574
|
+
permissionsCount: permSet.size,
|
|
19575
|
+
dualWriteDeduped,
|
|
19576
|
+
dualWriteDroppedCommands,
|
|
19577
|
+
legacyReclaimed
|
|
19578
|
+
};
|
|
19560
19579
|
}
|
|
19561
19580
|
var OLAM_SKILLS_MARKER, BACKUP_RETENTION, DUAL_WRITE_DEDUP_RULES;
|
|
19562
19581
|
var init_settings_merger = __esm({
|
|
@@ -21013,12 +21032,12 @@ function sourceConfigPath(clonePath) {
|
|
|
21013
21032
|
return join91(clonePath, "shared", "source-config.yaml");
|
|
21014
21033
|
}
|
|
21015
21034
|
function readSourceConfig(clonePath, sourceId) {
|
|
21016
|
-
const
|
|
21017
|
-
if (!existsSync88(
|
|
21035
|
+
const path122 = sourceConfigPath(clonePath);
|
|
21036
|
+
if (!existsSync88(path122))
|
|
21018
21037
|
return void 0;
|
|
21019
21038
|
let raw;
|
|
21020
21039
|
try {
|
|
21021
|
-
raw = readFileSync82(
|
|
21040
|
+
raw = readFileSync82(path122, "utf-8");
|
|
21022
21041
|
} catch (err) {
|
|
21023
21042
|
emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
|
|
21024
21043
|
return void 0;
|
|
@@ -22744,10 +22763,16 @@ var init_kg_eager = __esm({
|
|
|
22744
22763
|
// ../core/dist/kg/hook-template.js
|
|
22745
22764
|
var hook_template_exports = {};
|
|
22746
22765
|
__export(hook_template_exports, {
|
|
22766
|
+
KG_HOOK_PROMPT_SENTINEL: () => KG_HOOK_PROMPT_SENTINEL,
|
|
22767
|
+
KG_HOOK_PROMPT_SENTINEL_PREFIX: () => KG_HOOK_PROMPT_SENTINEL_PREFIX,
|
|
22747
22768
|
KG_HOOK_SENTINEL: () => KG_HOOK_SENTINEL,
|
|
22748
22769
|
KG_HOOK_SENTINEL_PREFIX: () => KG_HOOK_SENTINEL_PREFIX,
|
|
22770
|
+
PROMPT_TERM_EXTRACT_PY: () => PROMPT_TERM_EXTRACT_PY,
|
|
22771
|
+
TERM_EXTRACT_PY: () => TERM_EXTRACT_PY,
|
|
22749
22772
|
buildHookCommand: () => buildHookCommand,
|
|
22750
|
-
buildHookMatcherEntry: () => buildHookMatcherEntry
|
|
22773
|
+
buildHookMatcherEntry: () => buildHookMatcherEntry,
|
|
22774
|
+
buildPromptHookCommand: () => buildPromptHookCommand,
|
|
22775
|
+
buildPromptHookMatcherEntry: () => buildPromptHookMatcherEntry
|
|
22751
22776
|
});
|
|
22752
22777
|
function defaultUrl(flavor) {
|
|
22753
22778
|
if (flavor === "host")
|
|
@@ -22763,20 +22788,26 @@ function buildHookCommand(opts) {
|
|
|
22763
22788
|
try:
|
|
22764
22789
|
d=json.loads(sys.stdin.read())
|
|
22765
22790
|
route=d.get("route","")
|
|
22791
|
+
qnodes=[]
|
|
22792
|
+
try:
|
|
22793
|
+
qd=json.loads(os.environ.get("KG_QUERY_NODES","") or "{}")
|
|
22794
|
+
if isinstance(qd,dict) and qd.get("ok") and isinstance(qd.get("nodes"),list):
|
|
22795
|
+
qnodes=qd["nodes"]
|
|
22796
|
+
except Exception: qnodes=[]
|
|
22797
|
+
real_n=len(qnodes)
|
|
22766
22798
|
if route:
|
|
22767
22799
|
if route in ("kg","both"):
|
|
22768
22800
|
label=d.get("top_match") or d.get("reason","")
|
|
22769
22801
|
layer=d.get("layer","?")
|
|
22770
|
-
nodes=d.get("nodes_matched",0)
|
|
22802
|
+
nodes=real_n if real_n else d.get("nodes_matched",0)
|
|
22771
22803
|
saved=(d.get("savings") or {}).get("saved_tokens_est",0)
|
|
22772
22804
|
saved_k=round(saved/1000)
|
|
22773
22805
|
sys.stderr.write(f"\\x1b[32m\\u29bf\\u29bf\\x1b[0m KG hit \\u2713 {label} \\u2192 L{layer}/{route} \\u00b7 {nodes} nodes \\u00b7 \\x1b[32m~{saved_k}k tokens saved\\x1b[0m\\n")
|
|
22774
|
-
|
|
22806
|
+
elif route=="grep":
|
|
22775
22807
|
sys.stderr.write("\\U0001f50d Grep used\\n")
|
|
22776
|
-
if route
|
|
22808
|
+
if route in ("kg","both"):
|
|
22777
22809
|
label=d.get("top_match") or d.get("reason","")
|
|
22778
22810
|
layer=d.get("layer","?")
|
|
22779
|
-
nodes=d.get("nodes_matched",0)
|
|
22780
22811
|
saved=(d.get("savings") or {}).get("saved_tokens_est",0)
|
|
22781
22812
|
saved_k=round(saved/1000)
|
|
22782
22813
|
q=os.environ.get("KG_QUERY","")[:60]
|
|
@@ -22786,20 +22817,44 @@ try:
|
|
|
22786
22817
|
rel=any(k in ql for k in ("call","caller","import","uses","used","reference","who "))
|
|
22787
22818
|
g="olam kg mirror graph \\"" + sym + "\\" --workspace <ws>"
|
|
22788
22819
|
hint=g + (" --relates" if rel else "") + " (where X is defined; add --relates for what calls/imports it; --repo <name> to browse a repo)"
|
|
22789
|
-
|
|
22820
|
+
if qnodes:
|
|
22821
|
+
lines=[]
|
|
22822
|
+
for n in qnodes[:5]:
|
|
22823
|
+
s=str(n.get("symbol") or n.get("label") or "?")
|
|
22824
|
+
f=str(n.get("file") or "")
|
|
22825
|
+
loc=str(n.get("loc") or "")
|
|
22826
|
+
lines.append(f" {s} {f}:{loc}" if loc else f" {s} {f}")
|
|
22827
|
+
body="[kg-classifier L"+str(layer)+"|"+route+"] "+label[:140]+"\\n\\u21b3 nodes ("+str(real_n)+"):\\n"+"\\n".join(lines)+"\\n\\u21b3 graph: "+hint
|
|
22828
|
+
else:
|
|
22829
|
+
body="[kg-classifier L"+str(layer)+"|"+route+"] "+label[:140]+"\\n\\u21b3 graph: "+hint
|
|
22830
|
+
print(json.dumps({"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":body}}))
|
|
22790
22831
|
except Exception: pass' 2>/dev/null`;
|
|
22791
22832
|
const isCloud = opts.flavor === "cloud-sandbox";
|
|
22792
22833
|
const resolvedUrl = isCloud ? '"${OLAM_KG_PROXY_URL:-}/v1/classify"' : url2;
|
|
22793
22834
|
const authHeader = isCloud ? `-H "Authorization: Bearer \${OLAM_KG_PROXY_BEARER:-}"` : "";
|
|
22794
22835
|
const cloudGuard = isCloud ? `if [ -z "\${OLAM_KG_PROXY_URL:-}" ] || [ -z "\${OLAM_KG_PROXY_BEARER:-}" ]; then exit 0; fi; ` : "";
|
|
22795
|
-
const
|
|
22796
|
-
const
|
|
22797
|
-
const
|
|
22836
|
+
const isHostOrWorld = opts.flavor === "host" || opts.flavor === "world";
|
|
22837
|
+
const wsResolve = isHostOrWorld ? `KG_WS="\${OLAM_KG_WORKSPACE:-$(cat "\${OLAM_HOME:-$HOME/.olam}/kg-default-workspace" 2>/dev/null || echo atlas-one)}"; ` : "";
|
|
22838
|
+
const wsField = isCloud ? `,\\"workspace\\":\\"\${OLAM_KG_PROXY_WORKSPACE:-}\\"` : `,\\"workspace\\":\\"$KG_WS\\"`;
|
|
22839
|
+
const termExtract = TERM_EXTRACT_PY;
|
|
22840
|
+
const qTermLocal = `$(echo \\"$KG_TERM\\" | head -c 200 | tr '\\"' ' ')`;
|
|
22841
|
+
const setTerm = `KG_TERM=$(echo "$CMD" | ${termExtract}); `;
|
|
22842
|
+
const curlPost = `${wsResolve}${setTerm}RESP=$(curl -s --max-time 1 -X POST -H 'Content-Type: application/json' ${authHeader} -d "{\\"q\\":\\"${qTermLocal}\\"${wsField}}" ${resolvedUrl} 2>/dev/null)`;
|
|
22843
|
+
const hostRemoteFallback = opts.flavor === "host" ? `; if [ -r "$HOME/.olam/kg-proxy-url" ] && [ -r "$HOME/.olam/kg-proxy-bearer" ]; then KG_ORIGIN=$(sed 's|\\(https*://[^/]*\\).*|\\1|' "$HOME/.olam/kg-proxy-url" 2>/dev/null); if [ -z "$RESP" ]; then RESP=$(curl -s --max-time 3 -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer $(cat "$HOME/.olam/kg-proxy-bearer")" -d "{\\"q\\":\\"${qTermLocal}\\"${wsField}}" "$KG_ORIGIN/v1/classify" 2>/dev/null); fi; fi` : "";
|
|
22844
|
+
const routeIsKg = `echo "$RESP" | grep -Eq '"route"[[:space:]]*:[[:space:]]*"(kg|both)"'`;
|
|
22845
|
+
const queryBody = `-d "{\\"q\\":\\"${qTermLocal}\\",\\"limit\\":5${wsField}}"`;
|
|
22846
|
+
let queryFollowup = "";
|
|
22847
|
+
if (opts.flavor === "host") {
|
|
22848
|
+
queryFollowup = `; KG_QUERY_NODES=""; if [ -n "$RESP" ] && ${routeIsKg} && [ -n "$KG_ORIGIN" ] && [ -r "$HOME/.olam/kg-proxy-bearer" ]; then KG_QUERY_NODES=$(curl -s --max-time 3 -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer $(cat "$HOME/.olam/kg-proxy-bearer")" ${queryBody} "$KG_ORIGIN/v1/query" 2>/dev/null); fi`;
|
|
22849
|
+
} else if (isCloud) {
|
|
22850
|
+
queryFollowup = `; KG_QUERY_NODES=""; if [ -n "$RESP" ] && ${routeIsKg}; then KG_QUERY_NODES=$(curl -s --max-time 3 -X POST -H 'Content-Type: application/json' ${authHeader} ${queryBody} "\${OLAM_KG_PROXY_URL:-}/v1/query" 2>/dev/null); fi`;
|
|
22851
|
+
}
|
|
22852
|
+
const emitLine = `export KG_QUERY="$(echo \\"$CMD\\" | head -c 60 | tr '\\"' ' ')"; export KG_QUERY_NODES="\${KG_QUERY_NODES:-}"; echo "$RESP" | ${emitContext}`;
|
|
22798
22853
|
return [
|
|
22799
22854
|
`KG_SENTINEL=${KG_HOOK_SENTINEL}`,
|
|
22800
22855
|
`CMD=$(${extractCmd})`,
|
|
22801
|
-
`case "$CMD" in grep\\ *|grep|git\\ grep\\ *|rg\\ *|ripgrep\\ *|find\\ *|fd\\ *|ack\\ *|ag\\ *) ${cloudGuard}${curlPost}${hostRemoteFallback}`,
|
|
22802
|
-
|
|
22856
|
+
`case "$CMD" in grep\\ *|grep|git\\ grep\\ *|rg\\ *|ripgrep\\ *|find\\ *|fd\\ *|ack\\ *|ag\\ *) ${cloudGuard}${curlPost}${hostRemoteFallback}${queryFollowup}`,
|
|
22857
|
+
emitLine,
|
|
22803
22858
|
`;; esac`
|
|
22804
22859
|
].join("; ");
|
|
22805
22860
|
}
|
|
@@ -22814,12 +22869,112 @@ function buildHookMatcherEntry(opts) {
|
|
|
22814
22869
|
]
|
|
22815
22870
|
};
|
|
22816
22871
|
}
|
|
22817
|
-
|
|
22872
|
+
function buildPromptHookCommand(opts) {
|
|
22873
|
+
const url2 = opts.url ?? defaultUrl(opts.flavor);
|
|
22874
|
+
const isCloud = opts.flavor === "cloud-sandbox";
|
|
22875
|
+
const isHostOrWorld = opts.flavor === "host" || opts.flavor === "world";
|
|
22876
|
+
const extractCmd = `python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('prompt',''))" 2>/dev/null`;
|
|
22877
|
+
const resolvedUrl = isCloud ? '"${OLAM_KG_PROXY_URL:-}/v1/classify"' : url2;
|
|
22878
|
+
const authHeader = isCloud ? `-H "Authorization: Bearer \${OLAM_KG_PROXY_BEARER:-}"` : "";
|
|
22879
|
+
const cloudGuard = isCloud ? `if [ -z "\${OLAM_KG_PROXY_URL:-}" ] || [ -z "\${OLAM_KG_PROXY_BEARER:-}" ]; then exit 0; fi; ` : "";
|
|
22880
|
+
const wsResolve = isHostOrWorld ? `KG_WS="\${OLAM_KG_WORKSPACE:-$(cat "\${OLAM_HOME:-$HOME/.olam}/kg-default-workspace" 2>/dev/null || echo atlas-one)}"; ` : "";
|
|
22881
|
+
const wsField = isCloud ? `,\\"workspace\\":\\"\${OLAM_KG_PROXY_WORKSPACE:-}\\"` : `,\\"workspace\\":\\"$KG_WS\\"`;
|
|
22882
|
+
const classifyPost = `${wsResolve}RESP=$(curl -s --max-time 1 -X POST -H 'Content-Type: application/json' ${authHeader} -d "{\\"q\\":\\"$(echo \\"$PROMPT\\" | head -c 200 | tr '\\"' ' ')\\"${wsField}}" ${resolvedUrl} 2>/dev/null)`;
|
|
22883
|
+
const hostRemoteFallback = opts.flavor === "host" ? `; if [ -r "$HOME/.olam/kg-proxy-url" ] && [ -r "$HOME/.olam/kg-proxy-bearer" ]; then KG_ORIGIN=$(sed 's|\\(https*://[^/]*\\).*|\\1|' "$HOME/.olam/kg-proxy-url" 2>/dev/null); if [ -z "$RESP" ]; then RESP=$(curl -s --max-time 3 -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer $(cat "$HOME/.olam/kg-proxy-bearer")" -d "{\\"q\\":\\"$(echo \\"$PROMPT\\" | head -c 200 | tr '\\"' ' ')\\"${wsField}}" "$KG_ORIGIN/v1/classify" 2>/dev/null); fi; fi` : "";
|
|
22884
|
+
const setTerm = `KG_TERM=$(echo "$PROMPT" | ${PROMPT_TERM_EXTRACT_PY}); `;
|
|
22885
|
+
const qTerm = `$(echo \\"$KG_TERM\\" | head -c 200 | tr '\\"' ' ')`;
|
|
22886
|
+
const routeIsKg = `echo "$RESP" | grep -Eq '"route"[[:space:]]*:[[:space:]]*"(kg|both)"'`;
|
|
22887
|
+
const queryBody = `-d "{\\"q\\":\\"${qTerm}\\",\\"limit\\":5${wsField}}"`;
|
|
22888
|
+
let queryFollowup = "";
|
|
22889
|
+
if (opts.flavor === "host") {
|
|
22890
|
+
queryFollowup = `; KG_QUERY_NODES=""; if [ -n "$RESP" ] && ${routeIsKg} && [ -n "$KG_ORIGIN" ] && [ -r "$HOME/.olam/kg-proxy-bearer" ]; then ${setTerm}KG_QUERY_NODES=$(curl -s --max-time 3 -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer $(cat "$HOME/.olam/kg-proxy-bearer")" ${queryBody} "$KG_ORIGIN/v1/query" 2>/dev/null); fi`;
|
|
22891
|
+
} else if (isCloud) {
|
|
22892
|
+
queryFollowup = `; KG_QUERY_NODES=""; if [ -n "$RESP" ] && ${routeIsKg}; then ${setTerm}KG_QUERY_NODES=$(curl -s --max-time 3 -X POST -H 'Content-Type: application/json' ${authHeader} ${queryBody} "\${OLAM_KG_PROXY_URL:-}/v1/query" 2>/dev/null); fi`;
|
|
22893
|
+
}
|
|
22894
|
+
const emitContext = `python3 -c 'import json,sys,os
|
|
22895
|
+
try:
|
|
22896
|
+
d=json.loads(sys.stdin.read())
|
|
22897
|
+
route=d.get("route","")
|
|
22898
|
+
if route not in ("kg","both"): sys.exit(0)
|
|
22899
|
+
qnodes=[]
|
|
22900
|
+
try:
|
|
22901
|
+
qd=json.loads(os.environ.get("KG_QUERY_NODES","") or "{}")
|
|
22902
|
+
if isinstance(qd,dict) and qd.get("ok") and isinstance(qd.get("nodes"),list):
|
|
22903
|
+
qnodes=qd["nodes"]
|
|
22904
|
+
except Exception: qnodes=[]
|
|
22905
|
+
layer=d.get("layer","?")
|
|
22906
|
+
cands=d.get("candidate_symbols") or []
|
|
22907
|
+
sym=(cands[0] if cands else "") or "<symbol>"
|
|
22908
|
+
q=os.environ.get("KG_QUERY","")[:60]
|
|
22909
|
+
ql=q.lower()
|
|
22910
|
+
rel=any(k in ql for k in ("call","caller","import","uses","used","reference","who "))
|
|
22911
|
+
g="olam kg mirror graph \\"" + sym + "\\" --workspace <ws>"
|
|
22912
|
+
hint=g + (" --relates" if rel else "") + " (where X is defined; add --relates for what calls/imports it; --repo <name> to browse a repo)"
|
|
22913
|
+
if qnodes:
|
|
22914
|
+
lines=[]
|
|
22915
|
+
for n in qnodes[:5]:
|
|
22916
|
+
s=str(n.get("symbol") or n.get("label") or "?")
|
|
22917
|
+
f=str(n.get("file") or "")
|
|
22918
|
+
loc=str(n.get("loc") or "")
|
|
22919
|
+
lines.append(f" {s} {f}:{loc}" if loc else f" {s} {f}")
|
|
22920
|
+
body="[kg L"+str(layer)+"|"+route+"] this looks symbol-shaped \u2014 the KG already has:\\n\\u21b3 nodes ("+str(len(qnodes))+"):\\n"+"\\n".join(lines)+"\\n\\u21b3 graph: "+hint
|
|
22921
|
+
else:
|
|
22922
|
+
body="[kg L"+str(layer)+"|"+route+"] this looks symbol-shaped \u2014 prefer the KG over grep.\\n\\u21b3 graph: "+hint
|
|
22923
|
+
print(json.dumps({"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":body}}))
|
|
22924
|
+
except Exception: pass' 2>/dev/null`;
|
|
22925
|
+
const emitLine = `export KG_QUERY="$(echo \\"$PROMPT\\" | head -c 60 | tr '\\"' ' ')"; export KG_QUERY_NODES="\${KG_QUERY_NODES:-}"; echo "$RESP" | ${emitContext}`;
|
|
22926
|
+
return [
|
|
22927
|
+
`KG_SENTINEL=${KG_HOOK_PROMPT_SENTINEL}`,
|
|
22928
|
+
`PROMPT=$(${extractCmd})`,
|
|
22929
|
+
// No search-tool gate: classify every non-empty prompt. Empty prompt → no-op.
|
|
22930
|
+
`if [ -n "$PROMPT" ]; then ${cloudGuard}${classifyPost}${hostRemoteFallback}${queryFollowup}; ${emitLine}; fi`
|
|
22931
|
+
].join("; ");
|
|
22932
|
+
}
|
|
22933
|
+
function buildPromptHookMatcherEntry(opts) {
|
|
22934
|
+
return {
|
|
22935
|
+
hooks: [
|
|
22936
|
+
{
|
|
22937
|
+
type: "command",
|
|
22938
|
+
command: buildPromptHookCommand(opts)
|
|
22939
|
+
}
|
|
22940
|
+
]
|
|
22941
|
+
};
|
|
22942
|
+
}
|
|
22943
|
+
var KG_HOOK_SENTINEL, KG_HOOK_SENTINEL_PREFIX, KG_HOOK_PROMPT_SENTINEL, KG_HOOK_PROMPT_SENTINEL_PREFIX, TERM_EXTRACT_PY, PROMPT_TERM_EXTRACT_PY;
|
|
22818
22944
|
var init_hook_template2 = __esm({
|
|
22819
22945
|
"../core/dist/kg/hook-template.js"() {
|
|
22820
22946
|
"use strict";
|
|
22821
|
-
KG_HOOK_SENTINEL = "kg-service-
|
|
22947
|
+
KG_HOOK_SENTINEL = "kg-service-v4-classifier-hook";
|
|
22822
22948
|
KG_HOOK_SENTINEL_PREFIX = "kg-service-v";
|
|
22949
|
+
KG_HOOK_PROMPT_SENTINEL = "kg-service-prompt-v4-classifier-hook";
|
|
22950
|
+
KG_HOOK_PROMPT_SENTINEL_PREFIX = "kg-service-prompt-v";
|
|
22951
|
+
TERM_EXTRACT_PY = `python3 -c 'import sys
|
|
22952
|
+
cmd=sys.stdin.read().strip()
|
|
22953
|
+
toks=cmd.split()
|
|
22954
|
+
TOOLS=("grep","rg","ripgrep","find","fd","ack","ag")
|
|
22955
|
+
DIRS=("src","lib","app","test","spec","packages")
|
|
22956
|
+
QUOTES=chr(34)+chr(39)+chr(96)
|
|
22957
|
+
i=0
|
|
22958
|
+
if toks and toks[0]=="git" and len(toks)>1 and toks[1]=="grep": i=2
|
|
22959
|
+
elif toks and toks[0] in TOOLS: i=1
|
|
22960
|
+
term=""
|
|
22961
|
+
for t in toks[i:]:
|
|
22962
|
+
if t.startswith("-"): continue
|
|
22963
|
+
s=t.strip(QUOTES)
|
|
22964
|
+
if not s: continue
|
|
22965
|
+
if "/" in s or s.endswith("/") or s in DIRS or s in (".",".."): continue
|
|
22966
|
+
term=s; break
|
|
22967
|
+
print(term if term else cmd)' 2>/dev/null`;
|
|
22968
|
+
PROMPT_TERM_EXTRACT_PY = `python3 -c 'import sys,re
|
|
22969
|
+
p=sys.stdin.read().strip()
|
|
22970
|
+
Q=chr(34); B=chr(96); A=chr(39)
|
|
22971
|
+
pats=[B+"([^"+B+"]{3,})"+B, Q+"([^"+Q+"]{3,})"+Q, A+"([^"+A+"]{3,})"+A, "\\\\b[A-Za-z_$][\\\\w$]*(?:\\\\.[A-Za-z_$][\\\\w$]*)+\\\\b", "\\\\b[a-zA-Z_$][\\\\w$]*[A-Z][\\\\w$]*\\\\b", "\\\\b[a-z_][a-z0-9_]*_[a-z0-9_]+\\\\b"]
|
|
22972
|
+
term=""
|
|
22973
|
+
for pat in pats:
|
|
22974
|
+
m=re.search(pat,p)
|
|
22975
|
+
if m:
|
|
22976
|
+
term=(m.group(1) if m.groups() else m.group(0)).strip(); break
|
|
22977
|
+
print(term if term else p)' 2>/dev/null`;
|
|
22823
22978
|
}
|
|
22824
22979
|
});
|
|
22825
22980
|
|
|
@@ -23383,8 +23538,8 @@ function olamDir(deps) {
|
|
|
23383
23538
|
return join104(deps.home ?? homedir56(), ".olam");
|
|
23384
23539
|
}
|
|
23385
23540
|
function resolveLocalSecretValue(obj, deps = {}) {
|
|
23386
|
-
const
|
|
23387
|
-
const direct = readSecretAtPathOrNull(
|
|
23541
|
+
const path122 = join104(olamDir(deps), obj.local);
|
|
23542
|
+
const direct = readSecretAtPathOrNull(path122);
|
|
23388
23543
|
if (direct) return direct;
|
|
23389
23544
|
if (obj.object === "plan-chat-secret") {
|
|
23390
23545
|
const conn = readRemoteConnection();
|
|
@@ -23696,9 +23851,9 @@ var init_machine_schema = __esm({
|
|
|
23696
23851
|
init_cli_version();
|
|
23697
23852
|
init_output();
|
|
23698
23853
|
init_exit_codes();
|
|
23699
|
-
import { existsSync as
|
|
23700
|
-
import { homedir as
|
|
23701
|
-
import { join as
|
|
23854
|
+
import { existsSync as existsSync136 } from "node:fs";
|
|
23855
|
+
import { homedir as homedir89 } from "node:os";
|
|
23856
|
+
import { join as join144 } from "node:path";
|
|
23702
23857
|
import { Command } from "commander";
|
|
23703
23858
|
|
|
23704
23859
|
// src/commands/init.ts
|
|
@@ -24254,9 +24409,9 @@ var UnknownArchetypeError = class extends Error {
|
|
|
24254
24409
|
};
|
|
24255
24410
|
var ArchetypeCycleError = class extends Error {
|
|
24256
24411
|
path;
|
|
24257
|
-
constructor(
|
|
24258
|
-
super(`Archetype inheritance cycle detected: ${
|
|
24259
|
-
this.path =
|
|
24412
|
+
constructor(path122) {
|
|
24413
|
+
super(`Archetype inheritance cycle detected: ${path122.join(" \u2192 ")} \u2192 ${path122[0] ?? "?"}`);
|
|
24414
|
+
this.path = path122;
|
|
24260
24415
|
this.name = "ArchetypeCycleError";
|
|
24261
24416
|
}
|
|
24262
24417
|
};
|
|
@@ -25606,8 +25761,8 @@ async function installObservability(opts) {
|
|
|
25606
25761
|
}
|
|
25607
25762
|
const outcomes = [];
|
|
25608
25763
|
for (const script of OBSERVABILITY_SCRIPTS) {
|
|
25609
|
-
const
|
|
25610
|
-
if (!existsSync31(
|
|
25764
|
+
const path122 = join37(observabilityDir, script);
|
|
25765
|
+
if (!existsSync31(path122)) {
|
|
25611
25766
|
outcomes.push({ script, state: "missing" });
|
|
25612
25767
|
continue;
|
|
25613
25768
|
}
|
|
@@ -25619,7 +25774,7 @@ async function installObservability(opts) {
|
|
|
25619
25774
|
}
|
|
25620
25775
|
}
|
|
25621
25776
|
const runResult = await runObservabilityScript(
|
|
25622
|
-
|
|
25777
|
+
path122,
|
|
25623
25778
|
script,
|
|
25624
25779
|
scriptEnv,
|
|
25625
25780
|
opts.verbose
|
|
@@ -27291,8 +27446,8 @@ function locateMkcert(deps) {
|
|
|
27291
27446
|
const spawn14 = deps.spawnImpl ?? defaultSpawn;
|
|
27292
27447
|
const which = spawn14("which", ["mkcert"]);
|
|
27293
27448
|
if (which.status === 0) {
|
|
27294
|
-
const
|
|
27295
|
-
if (
|
|
27449
|
+
const path122 = which.stdout.trim();
|
|
27450
|
+
if (path122.length > 0) return path122;
|
|
27296
27451
|
}
|
|
27297
27452
|
const brewPath = "/opt/homebrew/bin/mkcert";
|
|
27298
27453
|
const exists = spawn14("test", ["-x", brewPath]);
|
|
@@ -28622,12 +28777,12 @@ function appendAuditEntry(entry, auditLogPath, writeFileSyncImpl) {
|
|
|
28622
28777
|
async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, peripheral) {
|
|
28623
28778
|
const auditLogPath = deps.auditLogPath ?? MANIFEST_REFRESH_AUDIT_LOG;
|
|
28624
28779
|
const readdirSync37 = deps.readdirSync ?? fs35.readdirSync;
|
|
28625
|
-
const
|
|
28780
|
+
const readFileSync126 = deps.readFileSync ?? fs35.readFileSync;
|
|
28626
28781
|
const writeFileSyncImpl = deps.writeFileSync ?? fs35.writeFileSync;
|
|
28627
|
-
const
|
|
28782
|
+
const existsSync137 = deps.existsSync ?? fs35.existsSync;
|
|
28628
28783
|
const now = deps.now ? deps.now() : /* @__PURE__ */ new Date();
|
|
28629
28784
|
const targetDir = peripheral ? path36.join(manifestsDir, peripheral) : manifestsDir;
|
|
28630
|
-
if (!
|
|
28785
|
+
if (!existsSync137(targetDir)) {
|
|
28631
28786
|
return {
|
|
28632
28787
|
ok: false,
|
|
28633
28788
|
message: peripheral ? `peripheral manifests directory not found: ${targetDir}` : `manifests directory not found: ${targetDir}`
|
|
@@ -28648,7 +28803,7 @@ async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, per
|
|
|
28648
28803
|
const filePath = path36.join(targetDir, file);
|
|
28649
28804
|
let content;
|
|
28650
28805
|
try {
|
|
28651
|
-
content =
|
|
28806
|
+
content = readFileSync126(filePath, "utf8");
|
|
28652
28807
|
} catch {
|
|
28653
28808
|
continue;
|
|
28654
28809
|
}
|
|
@@ -28907,11 +29062,11 @@ async function checkSecretPreCondition(context, deps) {
|
|
|
28907
29062
|
}
|
|
28908
29063
|
async function applyConfigMapSubstitution(context, manifestsDir, deps) {
|
|
28909
29064
|
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
28910
|
-
const
|
|
29065
|
+
const readFileSync126 = deps.readFileSyncImpl ?? fs36.readFileSync;
|
|
28911
29066
|
const configMapPath = path37.join(manifestsDir, "30-configmap.yaml");
|
|
28912
29067
|
let rawYaml;
|
|
28913
29068
|
try {
|
|
28914
|
-
rawYaml =
|
|
29069
|
+
rawYaml = readFileSync126(configMapPath, "utf8");
|
|
28915
29070
|
} catch (err) {
|
|
28916
29071
|
return `Failed to read ConfigMap at ${configMapPath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
28917
29072
|
}
|
|
@@ -30205,10 +30360,10 @@ function emptyMigrationState() {
|
|
|
30205
30360
|
return { version: 1, migrated: {} };
|
|
30206
30361
|
}
|
|
30207
30362
|
function readMigrationState(statePath, deps) {
|
|
30208
|
-
const
|
|
30209
|
-
const
|
|
30210
|
-
if (!
|
|
30211
|
-
const raw =
|
|
30363
|
+
const existsSync137 = deps.existsSync ?? fs40.existsSync;
|
|
30364
|
+
const readFileSync126 = deps.readFileSync ?? ((p) => fs40.readFileSync(p, "utf-8"));
|
|
30365
|
+
if (!existsSync137(statePath)) return emptyMigrationState();
|
|
30366
|
+
const raw = readFileSync126(statePath);
|
|
30212
30367
|
let parsed;
|
|
30213
30368
|
try {
|
|
30214
30369
|
parsed = JSON.parse(raw);
|
|
@@ -30225,17 +30380,17 @@ function readMigrationState(statePath, deps) {
|
|
|
30225
30380
|
return parsed;
|
|
30226
30381
|
}
|
|
30227
30382
|
function writeMigrationStateAtomic(statePath, state, deps) {
|
|
30228
|
-
const
|
|
30383
|
+
const writeFileSync77 = deps.writeFileSync ?? ((p, d) => fs40.writeFileSync(p, d, "utf-8"));
|
|
30229
30384
|
const renameSync23 = deps.renameSync ?? fs40.renameSync;
|
|
30230
30385
|
const tmpPath = `${statePath}.tmp`;
|
|
30231
|
-
|
|
30386
|
+
writeFileSync77(tmpPath, JSON.stringify(state, null, 2) + "\n");
|
|
30232
30387
|
renameSync23(tmpPath, statePath);
|
|
30233
30388
|
}
|
|
30234
30389
|
function readLocalAccounts(accountsPath, deps) {
|
|
30235
|
-
const
|
|
30236
|
-
const
|
|
30237
|
-
if (!
|
|
30238
|
-
const raw =
|
|
30390
|
+
const existsSync137 = deps.existsSync ?? fs40.existsSync;
|
|
30391
|
+
const readFileSync126 = deps.readFileSync ?? ((p) => fs40.readFileSync(p, "utf-8"));
|
|
30392
|
+
if (!existsSync137(accountsPath)) return null;
|
|
30393
|
+
const raw = readFileSync126(accountsPath);
|
|
30239
30394
|
let parsed;
|
|
30240
30395
|
try {
|
|
30241
30396
|
parsed = JSON.parse(raw);
|
|
@@ -33877,9 +34032,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
33877
34032
|
"These source files have changed since the image was built; the",
|
|
33878
34033
|
"changes will NOT take effect in fresh worlds until you rebuild:"
|
|
33879
34034
|
];
|
|
33880
|
-
for (const { path:
|
|
34035
|
+
for (const { path: path122, mtimeMs } of result.newerSources) {
|
|
33881
34036
|
const when = new Date(mtimeMs).toISOString();
|
|
33882
|
-
lines.push(` \u2022 ${
|
|
34037
|
+
lines.push(` \u2022 ${path122} (modified ${when})`);
|
|
33883
34038
|
}
|
|
33884
34039
|
lines.push("");
|
|
33885
34040
|
lines.push("Rebuild with:");
|
|
@@ -34259,15 +34414,15 @@ var AGENTMEMORY_LOCAL_URL = "http://host.docker.internal:3111";
|
|
|
34259
34414
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
34260
34415
|
async function readHostCpTokenForCreate() {
|
|
34261
34416
|
try {
|
|
34262
|
-
const { default:
|
|
34263
|
-
const { default:
|
|
34264
|
-
const { default:
|
|
34265
|
-
const tp =
|
|
34266
|
-
process.env.OLAM_HOME ??
|
|
34417
|
+
const { default: fs122 } = await import("node:fs");
|
|
34418
|
+
const { default: os67 } = await import("node:os");
|
|
34419
|
+
const { default: path122 } = await import("node:path");
|
|
34420
|
+
const tp = path122.join(
|
|
34421
|
+
process.env.OLAM_HOME ?? path122.join(os67.homedir(), ".olam"),
|
|
34267
34422
|
"host-cp.token"
|
|
34268
34423
|
);
|
|
34269
|
-
if (!
|
|
34270
|
-
return
|
|
34424
|
+
if (!fs122.existsSync(tp)) return null;
|
|
34425
|
+
return fs122.readFileSync(tp, "utf-8").trim();
|
|
34271
34426
|
} catch {
|
|
34272
34427
|
return null;
|
|
34273
34428
|
}
|
|
@@ -34767,12 +34922,12 @@ function defaultNameFromPrompt(prompt) {
|
|
|
34767
34922
|
}
|
|
34768
34923
|
async function readHostCpToken3() {
|
|
34769
34924
|
try {
|
|
34770
|
-
const { default:
|
|
34771
|
-
const { default:
|
|
34772
|
-
const { default:
|
|
34773
|
-
const tp =
|
|
34774
|
-
if (!
|
|
34775
|
-
const raw =
|
|
34925
|
+
const { default: fs122 } = await import("node:fs");
|
|
34926
|
+
const { default: os67 } = await import("node:os");
|
|
34927
|
+
const { default: path122 } = await import("node:path");
|
|
34928
|
+
const tp = path122.join(os67.homedir(), ".olam", "host-cp.token");
|
|
34929
|
+
if (!fs122.existsSync(tp)) return null;
|
|
34930
|
+
const raw = fs122.readFileSync(tp, "utf-8").trim();
|
|
34776
34931
|
return raw.length > 0 ? raw : null;
|
|
34777
34932
|
} catch {
|
|
34778
34933
|
return null;
|
|
@@ -36853,13 +37008,13 @@ var PlansClient = class {
|
|
|
36853
37008
|
const credentials = Buffer.from(`operator:${this.cfg.bearer}`).toString("base64");
|
|
36854
37009
|
return `Basic ${credentials}`;
|
|
36855
37010
|
}
|
|
36856
|
-
async request(
|
|
37011
|
+
async request(path122, init) {
|
|
36857
37012
|
const headers = {
|
|
36858
37013
|
Authorization: this.authHeader()
|
|
36859
37014
|
};
|
|
36860
37015
|
if (init.body) headers["content-type"] = "application/json";
|
|
36861
37016
|
if (init.adminSecret) headers["X-Admin-Secret"] = init.adminSecret;
|
|
36862
|
-
return fetch(`${this.cfg.cloudUrl}${
|
|
37017
|
+
return fetch(`${this.cfg.cloudUrl}${path122}`, {
|
|
36863
37018
|
method: init.method,
|
|
36864
37019
|
headers,
|
|
36865
37020
|
body: init.body ? JSON.stringify(init.body) : void 0
|
|
@@ -39410,11 +39565,11 @@ function zodIssueToError(issue, doc, lineCounter) {
|
|
|
39410
39565
|
suggestion: deriveSuggestion(issue)
|
|
39411
39566
|
};
|
|
39412
39567
|
}
|
|
39413
|
-
function formatJsonPath(
|
|
39414
|
-
if (
|
|
39568
|
+
function formatJsonPath(path122) {
|
|
39569
|
+
if (path122.length === 0)
|
|
39415
39570
|
return "<root>";
|
|
39416
39571
|
let out = "";
|
|
39417
|
-
for (const seg of
|
|
39572
|
+
for (const seg of path122) {
|
|
39418
39573
|
if (typeof seg === "number") {
|
|
39419
39574
|
out += `[${seg}]`;
|
|
39420
39575
|
} else {
|
|
@@ -39423,11 +39578,11 @@ function formatJsonPath(path121) {
|
|
|
39423
39578
|
}
|
|
39424
39579
|
return out;
|
|
39425
39580
|
}
|
|
39426
|
-
function resolveYamlLocation(
|
|
39581
|
+
function resolveYamlLocation(path122, doc, lineCounter) {
|
|
39427
39582
|
let bestLine = 0;
|
|
39428
39583
|
let bestColumn = 0;
|
|
39429
|
-
for (let depth =
|
|
39430
|
-
const segment =
|
|
39584
|
+
for (let depth = path122.length; depth >= 0; depth -= 1) {
|
|
39585
|
+
const segment = path122.slice(0, depth);
|
|
39431
39586
|
try {
|
|
39432
39587
|
const node = doc.getIn(segment, true);
|
|
39433
39588
|
if (node && typeof node === "object" && "range" in node) {
|
|
@@ -39645,11 +39800,11 @@ function topoSort(nodes) {
|
|
|
39645
39800
|
}
|
|
39646
39801
|
function traceCycle(start, byId) {
|
|
39647
39802
|
const seen = /* @__PURE__ */ new Set();
|
|
39648
|
-
const
|
|
39803
|
+
const path122 = [];
|
|
39649
39804
|
let current = start;
|
|
39650
39805
|
while (current && !seen.has(current)) {
|
|
39651
39806
|
seen.add(current);
|
|
39652
|
-
|
|
39807
|
+
path122.push(current);
|
|
39653
39808
|
const node = byId.get(current);
|
|
39654
39809
|
const next = node?.dependsOn[0];
|
|
39655
39810
|
if (next === void 0)
|
|
@@ -39657,10 +39812,10 @@ function traceCycle(start, byId) {
|
|
|
39657
39812
|
current = next;
|
|
39658
39813
|
}
|
|
39659
39814
|
if (current && seen.has(current)) {
|
|
39660
|
-
const idx =
|
|
39661
|
-
return [...
|
|
39815
|
+
const idx = path122.indexOf(current);
|
|
39816
|
+
return [...path122.slice(idx), current];
|
|
39662
39817
|
}
|
|
39663
|
-
return
|
|
39818
|
+
return path122;
|
|
39664
39819
|
}
|
|
39665
39820
|
|
|
39666
39821
|
// ../core/dist/executor/types.js
|
|
@@ -44546,8 +44701,8 @@ function checkWorld(container, hostShas, dockerExec) {
|
|
|
44546
44701
|
const m = shaLine.match(/^([a-f0-9]{64})\s+(.+)$/);
|
|
44547
44702
|
if (!m) continue;
|
|
44548
44703
|
const sha = m[1];
|
|
44549
|
-
const
|
|
44550
|
-
const filename =
|
|
44704
|
+
const path122 = m[2];
|
|
44705
|
+
const filename = path122?.split("/").pop();
|
|
44551
44706
|
if (!filename) continue;
|
|
44552
44707
|
const mtimeSecs = parseInt(mtimeLine.trim(), 10);
|
|
44553
44708
|
if (Number.isNaN(mtimeSecs) || !sha) continue;
|
|
@@ -45665,9 +45820,9 @@ var TasksClient = class {
|
|
|
45665
45820
|
this.olamNodeId = opts.olamNodeId;
|
|
45666
45821
|
this.sessionId = opts.sessionId;
|
|
45667
45822
|
}
|
|
45668
|
-
async call(method,
|
|
45823
|
+
async call(method, path122, scopes, body, query) {
|
|
45669
45824
|
const qs = query ? "?" + new URLSearchParams(Object.entries(query).filter(([, v]) => v !== void 0)).toString() : "";
|
|
45670
|
-
const url2 = `${this.baseUrl}${
|
|
45825
|
+
const url2 = `${this.baseUrl}${path122}${qs}`;
|
|
45671
45826
|
const res = await fetch(url2, {
|
|
45672
45827
|
method,
|
|
45673
45828
|
headers: {
|
|
@@ -45718,8 +45873,8 @@ function parseFrontmatter2(raw) {
|
|
|
45718
45873
|
}
|
|
45719
45874
|
return { frontmatter: fm, body };
|
|
45720
45875
|
}
|
|
45721
|
-
function parseTracker(
|
|
45722
|
-
const raw = readFileSync60(
|
|
45876
|
+
function parseTracker(path122) {
|
|
45877
|
+
const raw = readFileSync60(path122, "utf8");
|
|
45723
45878
|
const { frontmatter, body } = parseFrontmatter2(raw);
|
|
45724
45879
|
const lines = body.split("\n");
|
|
45725
45880
|
const tasks = [];
|
|
@@ -45956,8 +46111,8 @@ function registerTasks(program2) {
|
|
|
45956
46111
|
`);
|
|
45957
46112
|
}
|
|
45958
46113
|
});
|
|
45959
|
-
tasks.command("sync-tracker <path>").description("Parse /10x:commit-plan tracker.md + upsert each task via POST /api/tasks (B2.4; dual-emit pattern, olam-side per cross-ownership decoupling)").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--dry-run", "Parse + print task records; do not POST").option("--json", "Output raw JSON envelope").action(async (
|
|
45960
|
-
const parsed = parseTracker(
|
|
46114
|
+
tasks.command("sync-tracker <path>").description("Parse /10x:commit-plan tracker.md + upsert each task via POST /api/tasks (B2.4; dual-emit pattern, olam-side per cross-ownership decoupling)").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--dry-run", "Parse + print task records; do not POST").option("--json", "Output raw JSON envelope").action(async (path122, opts) => {
|
|
46115
|
+
const parsed = parseTracker(path122);
|
|
45961
46116
|
if (opts.dryRun) {
|
|
45962
46117
|
process.stdout.write(JSON.stringify(parsed, null, 2) + "\n");
|
|
45963
46118
|
return;
|
|
@@ -47520,7 +47675,7 @@ function registerSetup(program2) {
|
|
|
47520
47675
|
const hasCloudArg = Boolean(
|
|
47521
47676
|
rawOpts.skillsSource || rawOpts.memoryUrl || rawOpts.remoteMemoryUrl || rawOpts.kgUrl || rawOpts.remoteKgUrl || rawOpts.remoteUrl || rawOpts.remoteDispatchUrl || rawOpts.credentials
|
|
47522
47677
|
);
|
|
47523
|
-
let
|
|
47678
|
+
let path122 = resolveSetupPath2(
|
|
47524
47679
|
{
|
|
47525
47680
|
localMode: rawOpts.localMode,
|
|
47526
47681
|
cloudFirst: rawOpts.cloudFirst || hasCloudArg,
|
|
@@ -47530,7 +47685,7 @@ function registerSetup(program2) {
|
|
|
47530
47685
|
},
|
|
47531
47686
|
isTty
|
|
47532
47687
|
);
|
|
47533
|
-
if (
|
|
47688
|
+
if (path122 === "prompt") {
|
|
47534
47689
|
const { select: select2 } = await import("@inquirer/prompts");
|
|
47535
47690
|
const choice = await select2({
|
|
47536
47691
|
message: "How do you want to set up olam?",
|
|
@@ -47540,9 +47695,9 @@ function registerSetup(program2) {
|
|
|
47540
47695
|
],
|
|
47541
47696
|
default: "cloud"
|
|
47542
47697
|
});
|
|
47543
|
-
|
|
47698
|
+
path122 = choice === "local" ? "local" : "cloud";
|
|
47544
47699
|
}
|
|
47545
|
-
if (
|
|
47700
|
+
if (path122 === "cloud") {
|
|
47546
47701
|
const credentials = rawOpts.credentials === "gcp" ? "gcp" : rawOpts.credentials === "prompt" ? "prompt" : void 0;
|
|
47547
47702
|
if (rawOpts.credentials !== void 0 && credentials === void 0) {
|
|
47548
47703
|
process.stderr.write(`[olam setup] invalid --credentials "${rawOpts.credentials}" (expected: gcp | prompt)
|
|
@@ -49786,7 +49941,10 @@ var HOOK_BASENAMES = [
|
|
|
49786
49941
|
"agentmemory-recall-trigger.mjs",
|
|
49787
49942
|
"agentmemory-classify-queue.mjs",
|
|
49788
49943
|
"agentmemory-reflect-cite.mjs",
|
|
49789
|
-
"recall-log.mjs"
|
|
49944
|
+
"recall-log.mjs",
|
|
49945
|
+
// Shared dependency module imported by recall-trigger, classify-queue, and
|
|
49946
|
+
// agentmemory-save. Copied (not registered) — sibling of its importers.
|
|
49947
|
+
"agent-memory-gate.mjs"
|
|
49790
49948
|
];
|
|
49791
49949
|
var SOURCE_ANCHOR = "agentmemory-session-recall.js";
|
|
49792
49950
|
function resolveSourceDir(here3) {
|
|
@@ -49908,9 +50066,19 @@ function installHooks(opts = {}) {
|
|
|
49908
50066
|
}
|
|
49909
50067
|
});
|
|
49910
50068
|
settings.push(`kg-hook (PreToolUse): ${describeMerge(kgResult.status)}`);
|
|
50069
|
+
const kgPromptResult = mergeHomeSettingsJson(settingsPath, {
|
|
50070
|
+
ensureHook: {
|
|
50071
|
+
stage: "UserPromptSubmit",
|
|
50072
|
+
sentinel: KG_HOOK_PROMPT_SENTINEL,
|
|
50073
|
+
staleSentinelPrefix: KG_HOOK_PROMPT_SENTINEL_PREFIX,
|
|
50074
|
+
entry: buildPromptHookMatcherEntry({ flavor: "host" })
|
|
50075
|
+
}
|
|
50076
|
+
});
|
|
50077
|
+
settings.push(`kg-hook (UserPromptSubmit): ${describeMerge(kgPromptResult.status)}`);
|
|
49911
50078
|
} else {
|
|
49912
50079
|
settings.push("save-hook (PostToolUse): dry-run");
|
|
49913
50080
|
settings.push("kg-hook (PreToolUse): dry-run");
|
|
50081
|
+
settings.push("kg-hook (UserPromptSubmit): dry-run");
|
|
49914
50082
|
}
|
|
49915
50083
|
return { filesWritten, filesReplaced, filesUnchanged, backups, settings };
|
|
49916
50084
|
}
|
|
@@ -50558,6 +50726,9 @@ function printSyncSummary(summary2, dryRun, verbose = false) {
|
|
|
50558
50726
|
console.log(` ${pc38.dim("(dropped)")} ${cmd.slice(0, 120)}${cmd.length > 120 ? "\u2026" : ""}`);
|
|
50559
50727
|
}
|
|
50560
50728
|
}
|
|
50729
|
+
if (summary2.merge.legacyReclaimed > 0) {
|
|
50730
|
+
console.log(` ${pc38.dim(`legacy duplicates reclaimed: ${summary2.merge.legacyReclaimed} (pre-marker hook copies collapsed; each olam hook now fires once)`)}`);
|
|
50731
|
+
}
|
|
50561
50732
|
}
|
|
50562
50733
|
if (summary2.metaHooks) {
|
|
50563
50734
|
const mh = summary2.metaHooks;
|
|
@@ -53827,7 +53998,7 @@ function resolveBundlePath(candidates2 = BUNDLE_PATH_CANDIDATES, exists = exists
|
|
|
53827
53998
|
var MISSING_BUNDLE_REMEDY = "olam mcp server bundle missing. Searched: " + BUNDLE_PATH_CANDIDATES.join(", ") + ". For local dev, run: node packages/cli/scripts/bundle-mcp-server.mjs. A fresh `npm install -g @pleri/olam-cli@latest` should always include the bundle (see prepublishOnly in packages/cli/package.json); file an issue if it does not.";
|
|
53828
53999
|
function registerMcpServe(cmd) {
|
|
53829
54000
|
cmd.command("serve").description(
|
|
53830
|
-
"Run the olam MCP server (stdio transport). Claude Code wires this via `claude mcp add olam --scope user -- npx -y @pleri/olam-cli mcp serve`."
|
|
54001
|
+
"Run the olam MCP server (stdio transport). Claude Code wires this via `claude mcp add olam --scope user -- npx -y @pleri/olam-cli@latest mcp serve`."
|
|
53831
54002
|
).action(async () => {
|
|
53832
54003
|
const bundlePath = resolveBundlePath();
|
|
53833
54004
|
if (bundlePath === null) {
|
|
@@ -53836,6 +54007,8 @@ function registerMcpServe(cmd) {
|
|
|
53836
54007
|
return;
|
|
53837
54008
|
}
|
|
53838
54009
|
await import(bundlePath);
|
|
54010
|
+
await new Promise(() => {
|
|
54011
|
+
});
|
|
53839
54012
|
});
|
|
53840
54013
|
}
|
|
53841
54014
|
|
|
@@ -53843,8 +54016,9 @@ function registerMcpServe(cmd) {
|
|
|
53843
54016
|
init_output();
|
|
53844
54017
|
init_install_shared();
|
|
53845
54018
|
var NPM_PACKAGE_NAME2 = "@pleri/olam-cli";
|
|
54019
|
+
var NPM_PACKAGE_SPEC = `${NPM_PACKAGE_NAME2}@latest`;
|
|
53846
54020
|
function buildClaudeMcpAddArgs2(scope, useGlobal) {
|
|
53847
|
-
const target = useGlobal ? { cmd: "olam", args: ["mcp", "serve"] } : { cmd: "npx", args: ["-y",
|
|
54021
|
+
const target = useGlobal ? { cmd: "olam", args: ["mcp", "serve"] } : { cmd: "npx", args: ["-y", NPM_PACKAGE_SPEC, "mcp", "serve"] };
|
|
53848
54022
|
return {
|
|
53849
54023
|
command: "claude",
|
|
53850
54024
|
args: ["mcp", "add", "olam", "--scope", scope, "--", target.cmd, ...target.args]
|
|
@@ -53954,8 +54128,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
|
|
|
53954
54128
|
function authHeaders() {
|
|
53955
54129
|
return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
|
|
53956
54130
|
}
|
|
53957
|
-
async function apiFetch(
|
|
53958
|
-
const res = await fetch(`${BASE_URL}${
|
|
54131
|
+
async function apiFetch(path122, init = {}) {
|
|
54132
|
+
const res = await fetch(`${BASE_URL}${path122}`, {
|
|
53959
54133
|
...init,
|
|
53960
54134
|
headers: {
|
|
53961
54135
|
"Content-Type": "application/json",
|
|
@@ -54972,18 +55146,29 @@ import { existsSync as existsSync121 } from "node:fs";
|
|
|
54972
55146
|
// ../core/dist/memory/gate.js
|
|
54973
55147
|
init_olam_paths();
|
|
54974
55148
|
import { readFileSync as readFileSync108 } from "node:fs";
|
|
54975
|
-
var
|
|
54976
|
-
|
|
54977
|
-
|
|
55149
|
+
var ENV_MODE = /* @__PURE__ */ new Map([
|
|
55150
|
+
["readonly", "readonly"],
|
|
55151
|
+
["editor", "editor"],
|
|
55152
|
+
["1", "readonly"],
|
|
55153
|
+
["true", "readonly"],
|
|
55154
|
+
["on", "readonly"]
|
|
55155
|
+
]);
|
|
55156
|
+
var FILE_MODE = /* @__PURE__ */ new Map([
|
|
55157
|
+
["readonly", "readonly"],
|
|
55158
|
+
["editor", "editor"],
|
|
55159
|
+
["true", "readonly"],
|
|
55160
|
+
["1", "readonly"]
|
|
55161
|
+
]);
|
|
55162
|
+
function agentMemoryMode() {
|
|
54978
55163
|
const envVal = process.env["OLAM_AGENT_MEMORY"];
|
|
54979
55164
|
if (envVal !== void 0 && envVal.length > 0) {
|
|
54980
|
-
return
|
|
55165
|
+
return ENV_MODE.get(envVal.trim().toLowerCase()) ?? "off";
|
|
54981
55166
|
}
|
|
54982
55167
|
try {
|
|
54983
55168
|
const raw = readFileSync108(agentMemoryEnabledPath(), "utf8").trim().toLowerCase();
|
|
54984
|
-
return
|
|
55169
|
+
return FILE_MODE.get(raw) ?? "off";
|
|
54985
55170
|
} catch {
|
|
54986
|
-
return
|
|
55171
|
+
return "off";
|
|
54987
55172
|
}
|
|
54988
55173
|
}
|
|
54989
55174
|
|
|
@@ -55037,18 +55222,18 @@ async function runMemoryStatus(opts = {}) {
|
|
|
55037
55222
|
printInfo("livez", s.livez);
|
|
55038
55223
|
printInfo("secret", s.secretSet ? "~/.olam/memory-secret (set)" : "(missing)");
|
|
55039
55224
|
printInfo("port", `${s.port}`);
|
|
55040
|
-
const
|
|
55225
|
+
const mode = agentMemoryMode();
|
|
55041
55226
|
const envVal = process.env["OLAM_AGENT_MEMORY"];
|
|
55042
55227
|
const envActive = envVal !== void 0 && envVal.length > 0;
|
|
55043
|
-
|
|
55044
|
-
|
|
55045
|
-
|
|
55046
|
-
|
|
55047
|
-
);
|
|
55228
|
+
const source = envActive ? `OLAM_AGENT_MEMORY=${envVal} env override` : `flag file: ${agentMemoryEnabledPath()}`;
|
|
55229
|
+
if (mode === "editor") {
|
|
55230
|
+
printInfo("agent-memory", `EDITOR \u2014 recall + capture (${source})`);
|
|
55231
|
+
} else if (mode === "readonly") {
|
|
55232
|
+
printInfo("agent-memory", `READONLY \u2014 recall only, no capture (${source})`);
|
|
55048
55233
|
} else {
|
|
55049
55234
|
printInfo(
|
|
55050
55235
|
"agent-memory",
|
|
55051
|
-
envActive ? `
|
|
55236
|
+
envActive ? `OFF (${source})` : `OFF \u2014 enable with \`olam memory enable\` (--editor for capture)`
|
|
55052
55237
|
);
|
|
55053
55238
|
}
|
|
55054
55239
|
if (s.legacyPidfilePresent) {
|
|
@@ -55194,27 +55379,34 @@ init_olam_paths();
|
|
|
55194
55379
|
import { mkdirSync as mkdirSync73, writeFileSync as writeFileSync66 } from "node:fs";
|
|
55195
55380
|
import { dirname as dirname69 } from "node:path";
|
|
55196
55381
|
init_output();
|
|
55197
|
-
function writeGateFlag(
|
|
55382
|
+
function writeGateFlag(value) {
|
|
55198
55383
|
const flagPath = agentMemoryEnabledPath();
|
|
55199
55384
|
mkdirSync73(dirname69(flagPath), { recursive: true });
|
|
55200
|
-
writeFileSync66(flagPath,
|
|
55385
|
+
writeFileSync66(flagPath, `${value}
|
|
55386
|
+
`, { mode: 420 });
|
|
55201
55387
|
}
|
|
55202
55388
|
function registerMemoryEnable(parent) {
|
|
55203
|
-
parent.command("enable").description(
|
|
55204
|
-
|
|
55205
|
-
|
|
55206
|
-
|
|
55207
|
-
|
|
55208
|
-
|
|
55389
|
+
parent.command("enable").description(
|
|
55390
|
+
"Enable agent-memory. Default READONLY (recall only); pass --editor for recall + capture."
|
|
55391
|
+
).option("--editor", "Grant capture (write) access \u2014 fully agentic mode (EDITOR)").option("--readonly", "Recall only, no capture (READONLY) \u2014 the default").action((opts) => {
|
|
55392
|
+
if (opts.editor && opts.readonly) {
|
|
55393
|
+
printInfo("gate", "pass only one of --editor / --readonly");
|
|
55394
|
+
process.exitCode = 1;
|
|
55395
|
+
return;
|
|
55396
|
+
}
|
|
55397
|
+
const value = opts.editor ? "EDITOR" : "READONLY";
|
|
55398
|
+
writeGateFlag(value);
|
|
55399
|
+
printSuccess(`agent-memory enabled (${value})`);
|
|
55400
|
+
printInfo("flag file", agentMemoryEnabledPath());
|
|
55401
|
+
printInfo("mode", agentMemoryMode());
|
|
55209
55402
|
});
|
|
55210
55403
|
}
|
|
55211
55404
|
function registerMemoryDisable(parent) {
|
|
55212
55405
|
parent.command("disable").description("Disable agent-memory recall and capture (writes FALSE to the gate flag file)").action(() => {
|
|
55213
|
-
writeGateFlag(
|
|
55214
|
-
const flagPath = agentMemoryEnabledPath();
|
|
55406
|
+
writeGateFlag("FALSE");
|
|
55215
55407
|
printSuccess(`agent-memory disabled`);
|
|
55216
|
-
printInfo("flag file",
|
|
55217
|
-
printInfo("
|
|
55408
|
+
printInfo("flag file", agentMemoryEnabledPath());
|
|
55409
|
+
printInfo("mode", agentMemoryMode());
|
|
55218
55410
|
});
|
|
55219
55411
|
}
|
|
55220
55412
|
|
|
@@ -55579,13 +55771,13 @@ function resolveMemoryServiceDir() {
|
|
|
55579
55771
|
);
|
|
55580
55772
|
}
|
|
55581
55773
|
function resolveLocalBridgeScript(serviceDir) {
|
|
55582
|
-
const
|
|
55583
|
-
if (!existsSync123(
|
|
55774
|
+
const path122 = join126(serviceDir, "scripts", "local-bridge-server.mjs");
|
|
55775
|
+
if (!existsSync123(path122)) {
|
|
55584
55776
|
throw new Error(
|
|
55585
|
-
`Could not find local-bridge-server.mjs at ${
|
|
55777
|
+
`Could not find local-bridge-server.mjs at ${path122}. Verify packages/memory-service ships the scripts/ directory.`
|
|
55586
55778
|
);
|
|
55587
55779
|
}
|
|
55588
|
-
return
|
|
55780
|
+
return path122;
|
|
55589
55781
|
}
|
|
55590
55782
|
function validateBridgeOpts(opts) {
|
|
55591
55783
|
const local = opts.local ?? true;
|
|
@@ -56444,18 +56636,179 @@ function registerInboxInstallHookCommand(inbox) {
|
|
|
56444
56636
|
});
|
|
56445
56637
|
}
|
|
56446
56638
|
|
|
56639
|
+
// src/commands/inbox-toggle.ts
|
|
56640
|
+
init_merge_settings();
|
|
56641
|
+
import * as fs112 from "node:fs";
|
|
56642
|
+
import * as os60 from "node:os";
|
|
56643
|
+
import * as path112 from "node:path";
|
|
56644
|
+
init_output();
|
|
56645
|
+
var INBOX_ENV_KEY = "OLAM_QUESTION_INBOX";
|
|
56646
|
+
var OPT_OUT_VALUE = "0";
|
|
56647
|
+
function isOptOutValue(v) {
|
|
56648
|
+
const s = (v ?? "").toLowerCase();
|
|
56649
|
+
return s === "0" || s === "false" || s === "off" || s === "no";
|
|
56650
|
+
}
|
|
56651
|
+
function resolveScope(opts) {
|
|
56652
|
+
return opts.scope === "project" ? "project" : "user";
|
|
56653
|
+
}
|
|
56654
|
+
function localBrokerBasePresent() {
|
|
56655
|
+
return fs112.existsSync(path112.join(os60.homedir(), ".olam", "anthropic-base-url"));
|
|
56656
|
+
}
|
|
56657
|
+
function readPersistedOptOut(filePath) {
|
|
56658
|
+
if (!fs112.existsSync(filePath)) return void 0;
|
|
56659
|
+
const raw = fs112.readFileSync(filePath, "utf-8");
|
|
56660
|
+
if (!raw.trim()) return void 0;
|
|
56661
|
+
let settings;
|
|
56662
|
+
try {
|
|
56663
|
+
settings = JSON.parse(raw);
|
|
56664
|
+
} catch {
|
|
56665
|
+
return void 0;
|
|
56666
|
+
}
|
|
56667
|
+
const env = settings["env"];
|
|
56668
|
+
if (!env || typeof env !== "object") return void 0;
|
|
56669
|
+
const val = env[INBOX_ENV_KEY];
|
|
56670
|
+
return typeof val === "string" ? val : void 0;
|
|
56671
|
+
}
|
|
56672
|
+
function doDisable(scope) {
|
|
56673
|
+
const filePath = settingsPathFor3(scope);
|
|
56674
|
+
let result;
|
|
56675
|
+
try {
|
|
56676
|
+
result = mergeHomeSettingsJson(filePath, { env: { [INBOX_ENV_KEY]: OPT_OUT_VALUE } });
|
|
56677
|
+
} catch (err) {
|
|
56678
|
+
printError(
|
|
56679
|
+
`could not update ${filePath}: ${err instanceof Error ? err.message : String(err)}`
|
|
56680
|
+
);
|
|
56681
|
+
process.exitCode = 1;
|
|
56682
|
+
return;
|
|
56683
|
+
}
|
|
56684
|
+
if (result.status === "installed") {
|
|
56685
|
+
printSuccess(`question inbox DISABLED (${scope} scope)`);
|
|
56686
|
+
} else {
|
|
56687
|
+
printInfo("inbox", `already disabled (${scope} scope)`);
|
|
56688
|
+
}
|
|
56689
|
+
printInfo("settings", filePath);
|
|
56690
|
+
printInfo("effect", "new Claude Code sessions answer AskUserQuestion in the terminal");
|
|
56691
|
+
printInfo("re-enable", `olam inbox enable --scope ${scope}`);
|
|
56692
|
+
}
|
|
56693
|
+
function doEnable(scope) {
|
|
56694
|
+
const filePath = settingsPathFor3(scope);
|
|
56695
|
+
if (!fs112.existsSync(filePath)) {
|
|
56696
|
+
printInfo("inbox", `no settings at ${filePath} \u2014 already at default (ON for local)`);
|
|
56697
|
+
return;
|
|
56698
|
+
}
|
|
56699
|
+
const raw = fs112.readFileSync(filePath, "utf-8");
|
|
56700
|
+
if (!raw.trim()) {
|
|
56701
|
+
printInfo("inbox", `settings empty at ${filePath} \u2014 already at default (ON for local)`);
|
|
56702
|
+
return;
|
|
56703
|
+
}
|
|
56704
|
+
let settings;
|
|
56705
|
+
try {
|
|
56706
|
+
settings = JSON.parse(raw);
|
|
56707
|
+
} catch {
|
|
56708
|
+
printError(`could not parse ${filePath} \u2014 no changes made`);
|
|
56709
|
+
process.exitCode = 1;
|
|
56710
|
+
return;
|
|
56711
|
+
}
|
|
56712
|
+
const env = settings["env"];
|
|
56713
|
+
if (!env || typeof env !== "object" || !(INBOX_ENV_KEY in env)) {
|
|
56714
|
+
printInfo("inbox", `not disabled at this scope (${scope}) \u2014 nothing to enable`);
|
|
56715
|
+
return;
|
|
56716
|
+
}
|
|
56717
|
+
const nextEnv = { ...env };
|
|
56718
|
+
delete nextEnv[INBOX_ENV_KEY];
|
|
56719
|
+
const updated = { ...settings, env: nextEnv };
|
|
56720
|
+
const backupPath = backup2(filePath);
|
|
56721
|
+
try {
|
|
56722
|
+
fs112.writeFileSync(filePath, JSON.stringify(updated, null, 2) + "\n", { mode: 420 });
|
|
56723
|
+
} catch (err) {
|
|
56724
|
+
printError(
|
|
56725
|
+
`could not write ${filePath}: ${err instanceof Error ? err.message : String(err)}`
|
|
56726
|
+
);
|
|
56727
|
+
if (backupPath) printInfo("backup", `settings.json preserved at ${backupPath}`);
|
|
56728
|
+
process.exitCode = 1;
|
|
56729
|
+
return;
|
|
56730
|
+
}
|
|
56731
|
+
printSuccess(`question inbox ENABLED (${scope} scope) \u2014 default-ON restored`);
|
|
56732
|
+
printInfo("settings", filePath);
|
|
56733
|
+
if (backupPath) printInfo("backup", backupPath);
|
|
56734
|
+
if (!localBrokerBasePresent()) {
|
|
56735
|
+
printInfo(
|
|
56736
|
+
"note",
|
|
56737
|
+
"no ~/.olam/anthropic-base-url found \u2014 inbox stays inactive until cloud auth is set up (olam auth issue-anthropic-token)"
|
|
56738
|
+
);
|
|
56739
|
+
}
|
|
56740
|
+
}
|
|
56741
|
+
function doStatus(scope) {
|
|
56742
|
+
const filePath = settingsPathFor3(scope);
|
|
56743
|
+
const persisted = readPersistedOptOut(filePath);
|
|
56744
|
+
const brokerUrl = process.env.OLAM_QUESTION_BROKER_URL;
|
|
56745
|
+
const runtimeOptOut = process.env[INBOX_ENV_KEY];
|
|
56746
|
+
const basePresent = localBrokerBasePresent();
|
|
56747
|
+
printInfo("scope", `${scope} (${filePath})`);
|
|
56748
|
+
printInfo(
|
|
56749
|
+
`${INBOX_ENV_KEY} (persisted)`,
|
|
56750
|
+
persisted === void 0 ? "(unset)" : JSON.stringify(persisted)
|
|
56751
|
+
);
|
|
56752
|
+
if (runtimeOptOut !== void 0) {
|
|
56753
|
+
printInfo(`${INBOX_ENV_KEY} (current env)`, JSON.stringify(runtimeOptOut));
|
|
56754
|
+
}
|
|
56755
|
+
printInfo("~/.olam/anthropic-base-url", basePresent ? "present" : "absent");
|
|
56756
|
+
if (brokerUrl) printInfo("OLAM_QUESTION_BROKER_URL", "set (forces inbox ON)");
|
|
56757
|
+
let on;
|
|
56758
|
+
let reason;
|
|
56759
|
+
if (brokerUrl) {
|
|
56760
|
+
on = true;
|
|
56761
|
+
reason = "OLAM_QUESTION_BROKER_URL is set (explicit/CF override)";
|
|
56762
|
+
} else if (isOptOutValue(persisted)) {
|
|
56763
|
+
on = false;
|
|
56764
|
+
reason = `${INBOX_ENV_KEY}=${JSON.stringify(persisted)} opts out`;
|
|
56765
|
+
} else if (basePresent) {
|
|
56766
|
+
on = true;
|
|
56767
|
+
reason = "default-ON (anthropic-base-url present, not opted out)";
|
|
56768
|
+
} else {
|
|
56769
|
+
on = false;
|
|
56770
|
+
reason = "no broker base (~/.olam/anthropic-base-url absent) \u2192 passthrough";
|
|
56771
|
+
}
|
|
56772
|
+
if (on) {
|
|
56773
|
+
printInfo("inbox interception", `ON \u2014 ${reason}`);
|
|
56774
|
+
} else {
|
|
56775
|
+
printSuccess(`inbox interception: OFF \u2014 ${reason}`);
|
|
56776
|
+
}
|
|
56777
|
+
}
|
|
56778
|
+
function scopeOption(cmd) {
|
|
56779
|
+
return cmd.option(
|
|
56780
|
+
"--scope <scope>",
|
|
56781
|
+
"user (default; ~/.claude/settings.json) or project (<cwd>/.claude/settings.json)",
|
|
56782
|
+
"user"
|
|
56783
|
+
);
|
|
56784
|
+
}
|
|
56785
|
+
function registerInboxToggleCommands(inbox) {
|
|
56786
|
+
scopeOption(
|
|
56787
|
+
inbox.command("disable").description(
|
|
56788
|
+
"Stop routing AskUserQuestion to the mobile inbox; answer in the terminal instead"
|
|
56789
|
+
)
|
|
56790
|
+
).action((opts) => doDisable(resolveScope(opts)));
|
|
56791
|
+
scopeOption(
|
|
56792
|
+
inbox.command("enable").description("Re-enable inbox routing for AskUserQuestion (restore default-ON)")
|
|
56793
|
+
).action((opts) => doEnable(resolveScope(opts)));
|
|
56794
|
+
scopeOption(
|
|
56795
|
+
inbox.command("status").description("Show whether AskUserQuestion is routed to the inbox in this scope")
|
|
56796
|
+
).action((opts) => doStatus(resolveScope(opts)));
|
|
56797
|
+
}
|
|
56798
|
+
|
|
56447
56799
|
// src/commands/inbox/index.ts
|
|
56448
56800
|
function registerInbox(program2) {
|
|
56449
56801
|
const inbox = program2.command("inbox").description("Mobile question-inbox operations (route AskUserQuestion to phone)");
|
|
56450
56802
|
registerInboxInstallHookCommand(inbox);
|
|
56803
|
+
registerInboxToggleCommands(inbox);
|
|
56451
56804
|
}
|
|
56452
56805
|
|
|
56453
56806
|
// src/commands/kg-build.ts
|
|
56454
56807
|
init_storage_paths();
|
|
56455
56808
|
init_workspace_name();
|
|
56456
|
-
import * as
|
|
56457
|
-
import * as
|
|
56458
|
-
import * as
|
|
56809
|
+
import * as fs118 from "node:fs";
|
|
56810
|
+
import * as os64 from "node:os";
|
|
56811
|
+
import * as path118 from "node:path";
|
|
56459
56812
|
|
|
56460
56813
|
// ../core/dist/kg/kg-service-client.js
|
|
56461
56814
|
var KG_SERVICE_PORT_DEFAULT = 9997;
|
|
@@ -56466,8 +56819,8 @@ function port() {
|
|
|
56466
56819
|
const n = Number.parseInt(env, 10);
|
|
56467
56820
|
return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
|
|
56468
56821
|
}
|
|
56469
|
-
function url(
|
|
56470
|
-
return `http://127.0.0.1:${port()}${
|
|
56822
|
+
function url(path122) {
|
|
56823
|
+
return `http://127.0.0.1:${port()}${path122}`;
|
|
56471
56824
|
}
|
|
56472
56825
|
function kgServiceHealthUrl() {
|
|
56473
56826
|
return url("/health");
|
|
@@ -56547,39 +56900,39 @@ init_storage_paths();
|
|
|
56547
56900
|
init_workspace_name();
|
|
56548
56901
|
init_kg_caps();
|
|
56549
56902
|
init_output();
|
|
56550
|
-
import
|
|
56551
|
-
import { homedir as
|
|
56552
|
-
import
|
|
56903
|
+
import fs113 from "node:fs";
|
|
56904
|
+
import { homedir as homedir76 } from "node:os";
|
|
56905
|
+
import path113 from "node:path";
|
|
56553
56906
|
function olamHome6() {
|
|
56554
|
-
return process.env.OLAM_HOME ??
|
|
56907
|
+
return process.env.OLAM_HOME ?? path113.join(homedir76(), ".olam");
|
|
56555
56908
|
}
|
|
56556
56909
|
function kgRoot2() {
|
|
56557
|
-
return
|
|
56910
|
+
return path113.join(olamHome6(), "kg");
|
|
56558
56911
|
}
|
|
56559
56912
|
function worldsRoot2() {
|
|
56560
|
-
return
|
|
56913
|
+
return path113.join(olamHome6(), "worlds");
|
|
56561
56914
|
}
|
|
56562
56915
|
function dirSizeBytes2(dir) {
|
|
56563
|
-
if (!
|
|
56916
|
+
if (!fs113.existsSync(dir)) return 0;
|
|
56564
56917
|
let total = 0;
|
|
56565
56918
|
const stack = [dir];
|
|
56566
56919
|
while (stack.length > 0) {
|
|
56567
56920
|
const cur = stack.pop();
|
|
56568
56921
|
let entries;
|
|
56569
56922
|
try {
|
|
56570
|
-
entries =
|
|
56923
|
+
entries = fs113.readdirSync(cur, { withFileTypes: true });
|
|
56571
56924
|
} catch {
|
|
56572
56925
|
continue;
|
|
56573
56926
|
}
|
|
56574
56927
|
for (const entry of entries) {
|
|
56575
|
-
const full =
|
|
56928
|
+
const full = path113.join(cur, entry.name);
|
|
56576
56929
|
if (entry.isSymbolicLink()) continue;
|
|
56577
56930
|
if (entry.isDirectory()) {
|
|
56578
56931
|
stack.push(full);
|
|
56579
56932
|
continue;
|
|
56580
56933
|
}
|
|
56581
56934
|
try {
|
|
56582
|
-
total +=
|
|
56935
|
+
total += fs113.statSync(full).size;
|
|
56583
56936
|
} catch {
|
|
56584
56937
|
}
|
|
56585
56938
|
}
|
|
@@ -56593,10 +56946,10 @@ function formatBytes5(n) {
|
|
|
56593
56946
|
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
56594
56947
|
}
|
|
56595
56948
|
function readFreshness(workspace) {
|
|
56596
|
-
const file =
|
|
56597
|
-
if (!
|
|
56949
|
+
const file = path113.join(kgPristinePath(workspace), "freshness.json");
|
|
56950
|
+
if (!fs113.existsSync(file)) return null;
|
|
56598
56951
|
try {
|
|
56599
|
-
const raw = JSON.parse(
|
|
56952
|
+
const raw = JSON.parse(fs113.readFileSync(file, "utf-8"));
|
|
56600
56953
|
if (raw && typeof raw === "object") return raw;
|
|
56601
56954
|
return null;
|
|
56602
56955
|
} catch {
|
|
@@ -56604,10 +56957,10 @@ function readFreshness(workspace) {
|
|
|
56604
56957
|
}
|
|
56605
56958
|
}
|
|
56606
56959
|
function readOverlayNodeCount(graphifyOutDir) {
|
|
56607
|
-
const graphPath =
|
|
56608
|
-
if (!
|
|
56960
|
+
const graphPath = path113.join(graphifyOutDir, "graph.json");
|
|
56961
|
+
if (!fs113.existsSync(graphPath)) return null;
|
|
56609
56962
|
try {
|
|
56610
|
-
const raw = JSON.parse(
|
|
56963
|
+
const raw = JSON.parse(fs113.readFileSync(graphPath, "utf-8"));
|
|
56611
56964
|
if (raw && typeof raw === "object") {
|
|
56612
56965
|
const nodes = raw.nodes;
|
|
56613
56966
|
if (Array.isArray(nodes)) return nodes.length;
|
|
@@ -56619,28 +56972,28 @@ function readOverlayNodeCount(graphifyOutDir) {
|
|
|
56619
56972
|
}
|
|
56620
56973
|
function listOverlays() {
|
|
56621
56974
|
const root = worldsRoot2();
|
|
56622
|
-
if (!
|
|
56975
|
+
if (!fs113.existsSync(root)) return [];
|
|
56623
56976
|
const records = [];
|
|
56624
56977
|
let worldDirs;
|
|
56625
56978
|
try {
|
|
56626
|
-
worldDirs =
|
|
56979
|
+
worldDirs = fs113.readdirSync(root, { withFileTypes: true });
|
|
56627
56980
|
} catch {
|
|
56628
56981
|
return [];
|
|
56629
56982
|
}
|
|
56630
56983
|
for (const worldEntry of worldDirs) {
|
|
56631
56984
|
if (!worldEntry.isDirectory()) continue;
|
|
56632
56985
|
const worldId = worldEntry.name;
|
|
56633
|
-
const worldDir =
|
|
56986
|
+
const worldDir = path113.join(root, worldId);
|
|
56634
56987
|
let cloneDirs;
|
|
56635
56988
|
try {
|
|
56636
|
-
cloneDirs =
|
|
56989
|
+
cloneDirs = fs113.readdirSync(worldDir, { withFileTypes: true });
|
|
56637
56990
|
} catch {
|
|
56638
56991
|
continue;
|
|
56639
56992
|
}
|
|
56640
56993
|
for (const cloneEntry of cloneDirs) {
|
|
56641
56994
|
if (!cloneEntry.isDirectory()) continue;
|
|
56642
|
-
const graphifyOut =
|
|
56643
|
-
if (!
|
|
56995
|
+
const graphifyOut = path113.join(worldDir, cloneEntry.name, "graphify-out");
|
|
56996
|
+
if (!fs113.existsSync(graphifyOut)) continue;
|
|
56644
56997
|
records.push({
|
|
56645
56998
|
world_id: worldId,
|
|
56646
56999
|
clone_dir: cloneEntry.name,
|
|
@@ -56654,11 +57007,11 @@ function listOverlays() {
|
|
|
56654
57007
|
}
|
|
56655
57008
|
function listPristines(overlays) {
|
|
56656
57009
|
const root = kgRoot2();
|
|
56657
|
-
if (!
|
|
57010
|
+
if (!fs113.existsSync(root)) return [];
|
|
56658
57011
|
const records = [];
|
|
56659
57012
|
let entries;
|
|
56660
57013
|
try {
|
|
56661
|
-
entries =
|
|
57014
|
+
entries = fs113.readdirSync(root, { withFileTypes: true });
|
|
56662
57015
|
} catch {
|
|
56663
57016
|
return [];
|
|
56664
57017
|
}
|
|
@@ -56671,7 +57024,7 @@ function listPristines(overlays) {
|
|
|
56671
57024
|
continue;
|
|
56672
57025
|
}
|
|
56673
57026
|
const fresh = readFreshness(workspace);
|
|
56674
|
-
const graphifyOut =
|
|
57027
|
+
const graphifyOut = path113.join(kgPristinePath(workspace), "graphify-out");
|
|
56675
57028
|
const size = dirSizeBytes2(graphifyOut);
|
|
56676
57029
|
const worldCount = overlays.filter((o) => o.clone_dir === workspace).length;
|
|
56677
57030
|
records.push({
|
|
@@ -56807,10 +57160,10 @@ init_storage_paths();
|
|
|
56807
57160
|
init_workspace_name();
|
|
56808
57161
|
init_output();
|
|
56809
57162
|
import { spawn as spawn13 } from "node:child_process";
|
|
56810
|
-
import
|
|
56811
|
-
import
|
|
57163
|
+
import fs114 from "node:fs";
|
|
57164
|
+
import path114 from "node:path";
|
|
56812
57165
|
function pidFilePath2(workspace) {
|
|
56813
|
-
return
|
|
57166
|
+
return path114.join(kgPristinePath(workspace), ".watch.pid");
|
|
56814
57167
|
}
|
|
56815
57168
|
function isPidAlive3(pid) {
|
|
56816
57169
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -56825,39 +57178,39 @@ function isPidAlive3(pid) {
|
|
|
56825
57178
|
}
|
|
56826
57179
|
function readAndClassifyPid(workspace) {
|
|
56827
57180
|
const file = pidFilePath2(workspace);
|
|
56828
|
-
if (!
|
|
57181
|
+
if (!fs114.existsSync(file)) return { status: "no-pidfile", pid: null };
|
|
56829
57182
|
let pid;
|
|
56830
57183
|
try {
|
|
56831
|
-
const raw =
|
|
57184
|
+
const raw = fs114.readFileSync(file, "utf-8").trim();
|
|
56832
57185
|
pid = Number.parseInt(raw, 10);
|
|
56833
57186
|
} catch {
|
|
56834
|
-
|
|
57187
|
+
fs114.rmSync(file, { force: true });
|
|
56835
57188
|
return { status: "stale-reclaimed", pid: null };
|
|
56836
57189
|
}
|
|
56837
57190
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
56838
|
-
|
|
57191
|
+
fs114.rmSync(file, { force: true });
|
|
56839
57192
|
return { status: "stale-reclaimed", pid: null };
|
|
56840
57193
|
}
|
|
56841
57194
|
if (isPidAlive3(pid)) return { status: "active", pid };
|
|
56842
|
-
|
|
57195
|
+
fs114.rmSync(file, { force: true });
|
|
56843
57196
|
return { status: "stale-reclaimed", pid: null };
|
|
56844
57197
|
}
|
|
56845
57198
|
function writePidFile2(workspace, pid) {
|
|
56846
57199
|
const file = pidFilePath2(workspace);
|
|
56847
|
-
const dir =
|
|
56848
|
-
|
|
56849
|
-
|
|
57200
|
+
const dir = path114.dirname(file);
|
|
57201
|
+
fs114.mkdirSync(dir, { recursive: true });
|
|
57202
|
+
fs114.writeFileSync(file, String(pid), { encoding: "utf-8" });
|
|
56850
57203
|
}
|
|
56851
57204
|
function removePidFile(workspace) {
|
|
56852
57205
|
const file = pidFilePath2(workspace);
|
|
56853
57206
|
try {
|
|
56854
|
-
|
|
57207
|
+
fs114.rmSync(file, { force: true });
|
|
56855
57208
|
} catch {
|
|
56856
57209
|
}
|
|
56857
57210
|
}
|
|
56858
57211
|
async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
56859
57212
|
const cwd = deps.cwd ?? opts.cwd ?? process.cwd();
|
|
56860
|
-
const name = workspaceArg ??
|
|
57213
|
+
const name = workspaceArg ?? path114.basename(cwd).toLowerCase();
|
|
56861
57214
|
try {
|
|
56862
57215
|
validateWorkspaceName(name);
|
|
56863
57216
|
} catch (err) {
|
|
@@ -56865,7 +57218,7 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
|
56865
57218
|
return { exitCode: 1, pidWritten: false };
|
|
56866
57219
|
}
|
|
56867
57220
|
const pristinePath = kgPristinePath(name);
|
|
56868
|
-
const graphPath =
|
|
57221
|
+
const graphPath = path114.join(pristinePath, "graphify-out", "graph.json");
|
|
56869
57222
|
const pidState = readAndClassifyPid(name);
|
|
56870
57223
|
if (pidState.status === "active") {
|
|
56871
57224
|
printError(
|
|
@@ -57178,33 +57531,33 @@ function registerKgDoctorCommand(kg) {
|
|
|
57178
57531
|
init_merge_settings();
|
|
57179
57532
|
init_hook_template2();
|
|
57180
57533
|
init_output();
|
|
57181
|
-
import * as
|
|
57182
|
-
import * as
|
|
57183
|
-
import * as
|
|
57534
|
+
import * as fs115 from "node:fs";
|
|
57535
|
+
import * as path115 from "node:path";
|
|
57536
|
+
import * as os61 from "node:os";
|
|
57184
57537
|
import { parse as yamlParse3, stringify as yamlStringify4 } from "yaml";
|
|
57185
57538
|
function settingsPathFor4(scope) {
|
|
57186
57539
|
if (scope === "user") {
|
|
57187
|
-
return
|
|
57540
|
+
return path115.join(os61.homedir(), ".claude", "settings.json");
|
|
57188
57541
|
}
|
|
57189
|
-
return
|
|
57542
|
+
return path115.join(process.cwd(), ".claude", "settings.json");
|
|
57190
57543
|
}
|
|
57191
57544
|
function backup3(filePath) {
|
|
57192
|
-
if (!
|
|
57545
|
+
if (!fs115.existsSync(filePath)) return null;
|
|
57193
57546
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
57194
57547
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
57195
|
-
|
|
57548
|
+
fs115.copyFileSync(filePath, backupPath);
|
|
57196
57549
|
return backupPath;
|
|
57197
57550
|
}
|
|
57198
57551
|
var HERMES_HOOK_MATCHERS = ["terminal", "bash", "shell", "search_files", "grep", "ripgrep"];
|
|
57199
57552
|
function hermesConfigPath2() {
|
|
57200
|
-
return
|
|
57553
|
+
return path115.join(os61.homedir(), ".hermes", "config.yaml");
|
|
57201
57554
|
}
|
|
57202
57555
|
function hermesHooksDir() {
|
|
57203
|
-
return
|
|
57556
|
+
return path115.join(os61.homedir(), ".hermes", "hooks");
|
|
57204
57557
|
}
|
|
57205
57558
|
function patchHermesConfigForHook(action) {
|
|
57206
57559
|
const configPath = hermesConfigPath2();
|
|
57207
|
-
const raw =
|
|
57560
|
+
const raw = fs115.readFileSync(configPath, "utf-8");
|
|
57208
57561
|
const config = yamlParse3(raw);
|
|
57209
57562
|
const hooks = config["hooks"] ?? {};
|
|
57210
57563
|
const preToolCall = Array.isArray(hooks["pre_tool_call"]) ? hooks["pre_tool_call"] : [];
|
|
@@ -57213,7 +57566,7 @@ function patchHermesConfigForHook(action) {
|
|
|
57213
57566
|
(e) => typeof e["command"] === "string" && e["command"].includes(HERMES_KG_HOOK_SENTINEL)
|
|
57214
57567
|
);
|
|
57215
57568
|
if (alreadyPresent) return "already-present";
|
|
57216
|
-
const hookScriptPath =
|
|
57569
|
+
const hookScriptPath = path115.join(hermesHooksDir(), "kg-first.sh");
|
|
57217
57570
|
const entry = {
|
|
57218
57571
|
matcher: HERMES_HOOK_MATCHERS.join("|"),
|
|
57219
57572
|
command: `${hookScriptPath} # ${HERMES_KG_HOOK_SENTINEL}`
|
|
@@ -57223,7 +57576,7 @@ function patchHermesConfigForHook(action) {
|
|
|
57223
57576
|
hooks: { ...hooks, pre_tool_call: [...preToolCall, entry] },
|
|
57224
57577
|
hooks_auto_accept: true
|
|
57225
57578
|
};
|
|
57226
|
-
|
|
57579
|
+
fs115.writeFileSync(configPath, yamlStringify4(updated2), "utf-8");
|
|
57227
57580
|
return "patched";
|
|
57228
57581
|
}
|
|
57229
57582
|
const filtered = preToolCall.filter(
|
|
@@ -57234,12 +57587,12 @@ function patchHermesConfigForHook(action) {
|
|
|
57234
57587
|
...config,
|
|
57235
57588
|
hooks: { ...hooks, pre_tool_call: filtered }
|
|
57236
57589
|
};
|
|
57237
|
-
|
|
57590
|
+
fs115.writeFileSync(configPath, yamlStringify4(updated), "utf-8");
|
|
57238
57591
|
return "patched";
|
|
57239
57592
|
}
|
|
57240
57593
|
function doInstallForHermes() {
|
|
57241
57594
|
const configPath = hermesConfigPath2();
|
|
57242
|
-
if (!
|
|
57595
|
+
if (!fs115.existsSync(configPath)) {
|
|
57243
57596
|
printError(`~/.hermes/config.yaml not found at ${configPath}`);
|
|
57244
57597
|
printInfo("remedy", "Install Hermes first, then re-run `olam kg install-hook --for hermes`");
|
|
57245
57598
|
process.exitCode = 1;
|
|
@@ -57267,17 +57620,17 @@ function doInstallForHermes() {
|
|
|
57267
57620
|
function doUninstallForHermes() {
|
|
57268
57621
|
const configPath = hermesConfigPath2();
|
|
57269
57622
|
const hooksDir = hermesHooksDir();
|
|
57270
|
-
const hookScriptPath =
|
|
57623
|
+
const hookScriptPath = path115.join(hooksDir, "kg-first.sh");
|
|
57271
57624
|
let scriptRemoved = false;
|
|
57272
|
-
if (
|
|
57273
|
-
const content =
|
|
57625
|
+
if (fs115.existsSync(hookScriptPath)) {
|
|
57626
|
+
const content = fs115.readFileSync(hookScriptPath, "utf-8");
|
|
57274
57627
|
if (content.includes(HERMES_KG_HOOK_SENTINEL)) {
|
|
57275
|
-
|
|
57628
|
+
fs115.unlinkSync(hookScriptPath);
|
|
57276
57629
|
scriptRemoved = true;
|
|
57277
57630
|
}
|
|
57278
57631
|
}
|
|
57279
57632
|
let configPatched = false;
|
|
57280
|
-
if (
|
|
57633
|
+
if (fs115.existsSync(configPath)) {
|
|
57281
57634
|
const result = patchHermesConfigForHook("uninstall");
|
|
57282
57635
|
configPatched = result === "patched";
|
|
57283
57636
|
}
|
|
@@ -57302,9 +57655,9 @@ function registerKgInstallHookCommand(kg) {
|
|
|
57302
57655
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
57303
57656
|
const filePath = settingsPathFor4(scope);
|
|
57304
57657
|
try {
|
|
57305
|
-
|
|
57658
|
+
fs115.mkdirSync(path115.dirname(filePath), { recursive: true });
|
|
57306
57659
|
} catch (err) {
|
|
57307
|
-
printError(`could not create ${
|
|
57660
|
+
printError(`could not create ${path115.dirname(filePath)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
57308
57661
|
process.exitCode = 1;
|
|
57309
57662
|
return;
|
|
57310
57663
|
}
|
|
@@ -57318,6 +57671,14 @@ function registerKgInstallHookCommand(kg) {
|
|
|
57318
57671
|
entry: buildHookMatcherEntry({ flavor: "host" })
|
|
57319
57672
|
}
|
|
57320
57673
|
});
|
|
57674
|
+
mergeHomeSettingsJson(filePath, {
|
|
57675
|
+
ensureHook: {
|
|
57676
|
+
stage: "UserPromptSubmit",
|
|
57677
|
+
sentinel: KG_HOOK_PROMPT_SENTINEL,
|
|
57678
|
+
staleSentinelPrefix: KG_HOOK_PROMPT_SENTINEL_PREFIX,
|
|
57679
|
+
entry: buildPromptHookMatcherEntry({ flavor: "host" })
|
|
57680
|
+
}
|
|
57681
|
+
});
|
|
57321
57682
|
switch (result.status) {
|
|
57322
57683
|
case "installed":
|
|
57323
57684
|
printSuccess(`kg-service hook installed (${scope} scope)`);
|
|
@@ -57329,7 +57690,7 @@ function registerKgInstallHookCommand(kg) {
|
|
|
57329
57690
|
printInfo("kg-service hook", `already installed at ${filePath}`);
|
|
57330
57691
|
if (backupPath) {
|
|
57331
57692
|
try {
|
|
57332
|
-
|
|
57693
|
+
fs115.unlinkSync(backupPath);
|
|
57333
57694
|
} catch {
|
|
57334
57695
|
}
|
|
57335
57696
|
}
|
|
@@ -57349,22 +57710,22 @@ function registerKgInstallHookCommand(kg) {
|
|
|
57349
57710
|
// src/commands/kg-uninstall-hook.ts
|
|
57350
57711
|
init_hook_template2();
|
|
57351
57712
|
init_output();
|
|
57352
|
-
import * as
|
|
57353
|
-
import * as
|
|
57354
|
-
import * as
|
|
57713
|
+
import * as fs116 from "node:fs";
|
|
57714
|
+
import * as path116 from "node:path";
|
|
57715
|
+
import * as os62 from "node:os";
|
|
57355
57716
|
function settingsPathFor5(scope) {
|
|
57356
57717
|
if (scope === "user") {
|
|
57357
|
-
return
|
|
57718
|
+
return path116.join(os62.homedir(), ".claude", "settings.json");
|
|
57358
57719
|
}
|
|
57359
|
-
return
|
|
57720
|
+
return path116.join(process.cwd(), ".claude", "settings.json");
|
|
57360
57721
|
}
|
|
57361
|
-
function dropSentinel(matchers) {
|
|
57722
|
+
function dropSentinel(matchers, sentinelPrefix) {
|
|
57362
57723
|
let changed = false;
|
|
57363
57724
|
const out = [];
|
|
57364
57725
|
for (const matcher of matchers) {
|
|
57365
57726
|
const innerHooks = matcher.hooks ?? [];
|
|
57366
57727
|
const keptInner = innerHooks.filter((h) => {
|
|
57367
|
-
if (typeof h.command === "string" && h.command.includes(
|
|
57728
|
+
if (typeof h.command === "string" && h.command.includes(sentinelPrefix)) {
|
|
57368
57729
|
changed = true;
|
|
57369
57730
|
return false;
|
|
57370
57731
|
}
|
|
@@ -57386,13 +57747,13 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
57386
57747
|
kg.command("uninstall-hook").description("Remove kg-service PreToolUse hook from .claude/settings.json (sentinel-matched; surgical)").option("--scope <scope>", "project (default) or user", "project").action((opts) => {
|
|
57387
57748
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
57388
57749
|
const filePath = settingsPathFor5(scope);
|
|
57389
|
-
if (!
|
|
57750
|
+
if (!fs116.existsSync(filePath)) {
|
|
57390
57751
|
printInfo("kg-service hook", `no settings.json at ${filePath} \u2014 nothing to remove`);
|
|
57391
57752
|
return;
|
|
57392
57753
|
}
|
|
57393
57754
|
let settings;
|
|
57394
57755
|
try {
|
|
57395
|
-
const raw =
|
|
57756
|
+
const raw = fs116.readFileSync(filePath, "utf-8");
|
|
57396
57757
|
settings = raw.trim() ? JSON.parse(raw) : {};
|
|
57397
57758
|
} catch (err) {
|
|
57398
57759
|
printError(`could not parse ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -57400,38 +57761,36 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
57400
57761
|
return;
|
|
57401
57762
|
}
|
|
57402
57763
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
57403
|
-
|
|
57404
|
-
|
|
57764
|
+
const promptSubmit = settings.hooks?.UserPromptSubmit;
|
|
57765
|
+
const hasPre = Array.isArray(preToolUse) && preToolUse.length > 0;
|
|
57766
|
+
const hasPrompt = Array.isArray(promptSubmit) && promptSubmit.length > 0;
|
|
57767
|
+
if (!hasPre && !hasPrompt) {
|
|
57768
|
+
printInfo("kg-service hook", `no kg hooks at ${filePath} \u2014 nothing to remove`);
|
|
57405
57769
|
return;
|
|
57406
57770
|
}
|
|
57407
|
-
const { matchers, changed }
|
|
57408
|
-
|
|
57771
|
+
const preResult = hasPre ? dropSentinel(preToolUse, KG_HOOK_SENTINEL_PREFIX) : { matchers: [], changed: false };
|
|
57772
|
+
const promptResult = hasPrompt ? dropSentinel(promptSubmit, KG_HOOK_PROMPT_SENTINEL_PREFIX) : { matchers: [], changed: false };
|
|
57773
|
+
if (!preResult.changed && !promptResult.changed) {
|
|
57409
57774
|
printInfo("kg-service hook", `not found in ${filePath} \u2014 already uninstalled`);
|
|
57410
57775
|
return;
|
|
57411
57776
|
}
|
|
57412
57777
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
57413
57778
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
57414
57779
|
try {
|
|
57415
|
-
|
|
57780
|
+
fs116.copyFileSync(filePath, backupPath);
|
|
57416
57781
|
} catch {
|
|
57417
57782
|
}
|
|
57418
|
-
const
|
|
57419
|
-
|
|
57420
|
-
|
|
57421
|
-
|
|
57422
|
-
|
|
57423
|
-
|
|
57424
|
-
|
|
57425
|
-
|
|
57426
|
-
const otherStages = Object.keys(next.hooks ?? {}).filter((k) => k !== "PreToolUse");
|
|
57427
|
-
if (otherStages.length === 0) {
|
|
57428
|
-
delete next.hooks;
|
|
57429
|
-
} else {
|
|
57430
|
-
delete next.hooks.PreToolUse;
|
|
57431
|
-
}
|
|
57783
|
+
const nextHooks = { ...settings.hooks };
|
|
57784
|
+
if (hasPre) nextHooks.PreToolUse = preResult.matchers;
|
|
57785
|
+
if (hasPrompt) nextHooks.UserPromptSubmit = promptResult.matchers;
|
|
57786
|
+
if (hasPre && preResult.matchers.length === 0) delete nextHooks.PreToolUse;
|
|
57787
|
+
if (hasPrompt && promptResult.matchers.length === 0) delete nextHooks.UserPromptSubmit;
|
|
57788
|
+
const next = { ...settings, hooks: nextHooks };
|
|
57789
|
+
if (Object.keys(nextHooks).length === 0) {
|
|
57790
|
+
delete next.hooks;
|
|
57432
57791
|
}
|
|
57433
57792
|
try {
|
|
57434
|
-
|
|
57793
|
+
fs116.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
57435
57794
|
printSuccess(`kg-service hook removed from ${filePath}`);
|
|
57436
57795
|
printInfo("backup", backupPath);
|
|
57437
57796
|
} catch (err) {
|
|
@@ -57504,15 +57863,15 @@ function registerKgSavingsCommand(kg) {
|
|
|
57504
57863
|
|
|
57505
57864
|
// src/commands/kg-mirror.ts
|
|
57506
57865
|
init_output();
|
|
57507
|
-
import * as
|
|
57508
|
-
import * as
|
|
57509
|
-
import * as
|
|
57866
|
+
import * as fs117 from "node:fs";
|
|
57867
|
+
import * as os63 from "node:os";
|
|
57868
|
+
import * as path117 from "node:path";
|
|
57510
57869
|
function readEnvOrFile(envVar, fileName) {
|
|
57511
57870
|
const fromEnv = process.env[envVar];
|
|
57512
57871
|
if (fromEnv && fromEnv.length > 0) return fromEnv.trim();
|
|
57513
57872
|
try {
|
|
57514
|
-
const file =
|
|
57515
|
-
const content =
|
|
57873
|
+
const file = path117.join(os63.homedir(), ".olam", fileName);
|
|
57874
|
+
const content = fs117.readFileSync(file, "utf-8").trim();
|
|
57516
57875
|
if (content.length > 0) return content;
|
|
57517
57876
|
} catch {
|
|
57518
57877
|
}
|
|
@@ -57774,14 +58133,14 @@ async function runKgMirrorGraph(symbol, options = {}) {
|
|
|
57774
58133
|
function guessGitUrl(workspace) {
|
|
57775
58134
|
try {
|
|
57776
58135
|
const { spawnSync: spawnSync36 } = __require("node:child_process");
|
|
57777
|
-
const cwd =
|
|
58136
|
+
const cwd = path117.resolve(process.cwd());
|
|
57778
58137
|
const candidates2 = [
|
|
57779
58138
|
cwd,
|
|
57780
|
-
|
|
57781
|
-
|
|
58139
|
+
path117.join(path117.dirname(cwd), workspace),
|
|
58140
|
+
path117.join(os63.homedir(), "Projects", workspace)
|
|
57782
58141
|
];
|
|
57783
58142
|
for (const dir of candidates2) {
|
|
57784
|
-
if (!
|
|
58143
|
+
if (!fs117.existsSync(path117.join(dir, ".git"))) continue;
|
|
57785
58144
|
const r = spawnSync36("git", ["-C", dir, "remote", "get-url", "origin"], {
|
|
57786
58145
|
encoding: "utf-8"
|
|
57787
58146
|
});
|
|
@@ -57819,12 +58178,12 @@ function registerKgMirrorCommand(kg) {
|
|
|
57819
58178
|
// src/commands/kg-connect.ts
|
|
57820
58179
|
init_memory_secret();
|
|
57821
58180
|
init_connect_url();
|
|
57822
|
-
import { existsSync as
|
|
57823
|
-
import { homedir as
|
|
57824
|
-
import { join as
|
|
58181
|
+
import { existsSync as existsSync130, readFileSync as readFileSync116 } from "node:fs";
|
|
58182
|
+
import { homedir as homedir80 } from "node:os";
|
|
58183
|
+
import { join as join134 } from "node:path";
|
|
57825
58184
|
init_output();
|
|
57826
58185
|
function olamFile(name) {
|
|
57827
|
-
return
|
|
58186
|
+
return join134(homedir80(), ".olam", name);
|
|
57828
58187
|
}
|
|
57829
58188
|
function safeUrl3(url2) {
|
|
57830
58189
|
try {
|
|
@@ -57845,7 +58204,7 @@ function registerKgConnectCommand(kg) {
|
|
|
57845
58204
|
return;
|
|
57846
58205
|
}
|
|
57847
58206
|
const urlPath = olamFile("kg-proxy-url");
|
|
57848
|
-
const previous =
|
|
58207
|
+
const previous = existsSync130(urlPath) ? readFileSync116(urlPath, "utf8").trim() : "";
|
|
57849
58208
|
writeSecretAtPath(urlPath, classifierUrl);
|
|
57850
58209
|
if (opts.bearer) writeSecretAtPath(olamFile("kg-proxy-bearer"), opts.bearer);
|
|
57851
58210
|
if (opts.builderUrl) {
|
|
@@ -57880,8 +58239,8 @@ function registerKgConnectCommand(kg) {
|
|
|
57880
58239
|
|
|
57881
58240
|
// src/commands/kg-build.ts
|
|
57882
58241
|
function readQueueFromDisk(queuePath) {
|
|
57883
|
-
if (!
|
|
57884
|
-
const raw =
|
|
58242
|
+
if (!fs118.existsSync(queuePath)) return [];
|
|
58243
|
+
const raw = fs118.readFileSync(queuePath, "utf-8");
|
|
57885
58244
|
const entries = [];
|
|
57886
58245
|
for (const line of raw.split("\n")) {
|
|
57887
58246
|
const t = line.trim();
|
|
@@ -57894,14 +58253,14 @@ function readQueueFromDisk(queuePath) {
|
|
|
57894
58253
|
return entries;
|
|
57895
58254
|
}
|
|
57896
58255
|
function writeQueueToDisk(queuePath, entries) {
|
|
57897
|
-
|
|
58256
|
+
fs118.mkdirSync(path118.dirname(queuePath), { recursive: true });
|
|
57898
58257
|
const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
|
|
57899
|
-
|
|
58258
|
+
fs118.writeFileSync(queuePath, content, "utf-8");
|
|
57900
58259
|
}
|
|
57901
58260
|
async function runKgBuildPending(opts = {}) {
|
|
57902
58261
|
const queuePath = opts.queuePath ?? (() => {
|
|
57903
|
-
const stateDir2 = process.env["OLAM_STATE_DIR"] ??
|
|
57904
|
-
return
|
|
58262
|
+
const stateDir2 = process.env["OLAM_STATE_DIR"] ?? path118.join(os64.homedir(), ".olam", "state");
|
|
58263
|
+
return path118.join(stateDir2, "kg-pending.jsonl");
|
|
57905
58264
|
})();
|
|
57906
58265
|
const readQueue2 = opts.readQueueFn ?? readQueueFromDisk;
|
|
57907
58266
|
const writeQueue2 = opts.writeQueueFn ?? writeQueueToDisk;
|
|
@@ -57917,7 +58276,7 @@ async function runKgBuildPending(opts = {}) {
|
|
|
57917
58276
|
const remaining = [];
|
|
57918
58277
|
for (const entry of deduped) {
|
|
57919
58278
|
const repoPath = entry.path;
|
|
57920
|
-
const workspaceName =
|
|
58279
|
+
const workspaceName = path118.basename(repoPath).toLowerCase();
|
|
57921
58280
|
printInfo("kg build --pending", `building ${repoPath} (workspace=${workspaceName})`);
|
|
57922
58281
|
let containerPath;
|
|
57923
58282
|
try {
|
|
@@ -57955,20 +58314,20 @@ async function runKgBuildPending(opts = {}) {
|
|
|
57955
58314
|
}
|
|
57956
58315
|
function resolveWorkspace(arg) {
|
|
57957
58316
|
const cwd = process.cwd();
|
|
57958
|
-
const name = arg ??
|
|
58317
|
+
const name = arg ?? path118.basename(cwd).toLowerCase();
|
|
57959
58318
|
validateWorkspaceName(name);
|
|
57960
58319
|
return { name, sourcePath: cwd };
|
|
57961
58320
|
}
|
|
57962
58321
|
function toContainerPath(hostPath) {
|
|
57963
|
-
const home =
|
|
57964
|
-
const resolved =
|
|
57965
|
-
if (!resolved.startsWith(home +
|
|
58322
|
+
const home = os64.homedir();
|
|
58323
|
+
const resolved = path118.resolve(hostPath);
|
|
58324
|
+
if (!resolved.startsWith(home + path118.sep) && resolved !== home) {
|
|
57966
58325
|
throw new Error(
|
|
57967
58326
|
`source path "${resolved}" is not under $HOME (${home}). kg-service can only build repos that live under your home dir (it bind-mounts $HOME:/host-home:ro at start). Move the repo or set OLAM_HOME if you need a different root.`
|
|
57968
58327
|
);
|
|
57969
58328
|
}
|
|
57970
|
-
const rel =
|
|
57971
|
-
return rel === "" ? "/host-home" :
|
|
58329
|
+
const rel = path118.relative(home, resolved);
|
|
58330
|
+
return rel === "" ? "/host-home" : path118.posix.join("/host-home", rel.split(path118.sep).join("/"));
|
|
57972
58331
|
}
|
|
57973
58332
|
async function runKgBuild(workspaceArg, options = {}) {
|
|
57974
58333
|
let workspace;
|
|
@@ -57986,7 +58345,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
57986
58345
|
return { exitCode: 2 };
|
|
57987
58346
|
}
|
|
57988
58347
|
const outDir = kgPristinePath(workspace.name);
|
|
57989
|
-
|
|
58348
|
+
fs118.mkdirSync(outDir, { recursive: true });
|
|
57990
58349
|
const human = !options.json;
|
|
57991
58350
|
if (human) {
|
|
57992
58351
|
printInfo("kg build", `workspace=${workspace.name} source=${workspace.sourcePath}`);
|
|
@@ -58019,12 +58378,12 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
58019
58378
|
workspace: workspace.name,
|
|
58020
58379
|
graphify_path: "container"
|
|
58021
58380
|
};
|
|
58022
|
-
|
|
58023
|
-
|
|
58381
|
+
fs118.writeFileSync(
|
|
58382
|
+
path118.join(outDir, "freshness.json"),
|
|
58024
58383
|
JSON.stringify(freshness, null, 2) + "\n",
|
|
58025
58384
|
"utf-8"
|
|
58026
58385
|
);
|
|
58027
|
-
const finalOut =
|
|
58386
|
+
const finalOut = path118.join(outDir, "graphify-out");
|
|
58028
58387
|
if (options.json) {
|
|
58029
58388
|
process.stdout.write(JSON.stringify(freshness) + "\n");
|
|
58030
58389
|
} else {
|
|
@@ -58068,12 +58427,12 @@ function registerKg(program2) {
|
|
|
58068
58427
|
// src/commands/flywheel/emit-breadcrumb.ts
|
|
58069
58428
|
init_file_lock();
|
|
58070
58429
|
import { mkdirSync as mkdirSync77, appendFileSync as appendFileSync6 } from "node:fs";
|
|
58071
|
-
import { homedir as
|
|
58072
|
-
import { dirname as dirname74, join as
|
|
58430
|
+
import { homedir as homedir82 } from "node:os";
|
|
58431
|
+
import { dirname as dirname74, join as join136 } from "node:path";
|
|
58073
58432
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
58074
58433
|
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info", "warn"]);
|
|
58075
58434
|
var PROMPT_FEEDING_FIELDS = ["extracted_pattern", "severity", "affected_persona", "proposed_edit"];
|
|
58076
|
-
var BREADCRUMBS_BASE =
|
|
58435
|
+
var BREADCRUMBS_BASE = join136(homedir82(), ".local", "share", "claude", "breadcrumbs");
|
|
58077
58436
|
var LOCK_FILENAME = ".flywheel-emit.lock";
|
|
58078
58437
|
function buildRecord(opts) {
|
|
58079
58438
|
const rec = {
|
|
@@ -58120,7 +58479,7 @@ function validatePromptFeeding(rec) {
|
|
|
58120
58479
|
}
|
|
58121
58480
|
function destPath(projectSlug) {
|
|
58122
58481
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
58123
|
-
return
|
|
58482
|
+
return join136(BREADCRUMBS_BASE, projectSlug, `${today}.jsonl`);
|
|
58124
58483
|
}
|
|
58125
58484
|
async function emitBreadcrumb(opts) {
|
|
58126
58485
|
if (!VALID_SEVERITIES.has(opts.severity)) {
|
|
@@ -58139,14 +58498,14 @@ async function emitBreadcrumb(opts) {
|
|
|
58139
58498
|
);
|
|
58140
58499
|
process.exit(2);
|
|
58141
58500
|
}
|
|
58142
|
-
const
|
|
58143
|
-
const lockDir = dirname74(
|
|
58501
|
+
const path122 = destPath(rec.project_slug);
|
|
58502
|
+
const lockDir = dirname74(path122);
|
|
58144
58503
|
mkdirSync77(lockDir, { recursive: true });
|
|
58145
58504
|
const line = JSON.stringify(rec) + "\n";
|
|
58146
58505
|
await withFileLock(
|
|
58147
58506
|
lockDir,
|
|
58148
58507
|
() => {
|
|
58149
|
-
appendFileSync6(
|
|
58508
|
+
appendFileSync6(path122, line, "utf8");
|
|
58150
58509
|
},
|
|
58151
58510
|
{
|
|
58152
58511
|
lockFilename: LOCK_FILENAME,
|
|
@@ -58162,7 +58521,7 @@ async function emitBreadcrumb(opts) {
|
|
|
58162
58521
|
acquireTimeoutMs: 2e4
|
|
58163
58522
|
}
|
|
58164
58523
|
);
|
|
58165
|
-
process.stdout.write(`[K7-emit] ${
|
|
58524
|
+
process.stdout.write(`[K7-emit] ${path122}: ${rec.extracted_pattern} (${rec.severity})
|
|
58166
58525
|
`);
|
|
58167
58526
|
}
|
|
58168
58527
|
function registerFlywheelEmitBreadcrumb(parent) {
|
|
@@ -58227,7 +58586,7 @@ function registerFlywheelK5Score(parent) {
|
|
|
58227
58586
|
}
|
|
58228
58587
|
|
|
58229
58588
|
// src/commands/flywheel/k5-validate.ts
|
|
58230
|
-
import { readFileSync as
|
|
58589
|
+
import { readFileSync as readFileSync118, statSync as statSync33 } from "node:fs";
|
|
58231
58590
|
import { parse as parseYAML } from "yaml";
|
|
58232
58591
|
var K5_DIMS = ["direction", "approach", "open_questions", "constraints", "reuse"];
|
|
58233
58592
|
var MAX_PLAN_BYTES = 1048576;
|
|
@@ -58285,9 +58644,9 @@ function validateK5ScoredAt(scoredAt) {
|
|
|
58285
58644
|
}
|
|
58286
58645
|
return null;
|
|
58287
58646
|
}
|
|
58288
|
-
function validatePlan(
|
|
58647
|
+
function validatePlan(path122) {
|
|
58289
58648
|
const emptyJson = (status2, errors2) => ({
|
|
58290
|
-
path:
|
|
58649
|
+
path: path122,
|
|
58291
58650
|
status: status2,
|
|
58292
58651
|
errors: errors2,
|
|
58293
58652
|
k5_scores: null,
|
|
@@ -58298,33 +58657,33 @@ function validatePlan(path121) {
|
|
|
58298
58657
|
});
|
|
58299
58658
|
let stat;
|
|
58300
58659
|
try {
|
|
58301
|
-
stat = statSync33(
|
|
58660
|
+
stat = statSync33(path122);
|
|
58302
58661
|
} catch (err) {
|
|
58303
|
-
const m = `FAIL cannot stat ${
|
|
58662
|
+
const m = `FAIL cannot stat ${path122}: ${err instanceof Error ? err.message : "unknown"}`;
|
|
58304
58663
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58305
58664
|
}
|
|
58306
58665
|
if (stat.size > MAX_PLAN_BYTES) {
|
|
58307
|
-
const m = `FAIL ${
|
|
58666
|
+
const m = `FAIL ${path122}: plan file exceeds 1MB (${stat.size} bytes); refusing to parse`;
|
|
58308
58667
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58309
58668
|
}
|
|
58310
58669
|
let text;
|
|
58311
58670
|
try {
|
|
58312
|
-
text =
|
|
58671
|
+
text = readFileSync118(path122, "utf8");
|
|
58313
58672
|
} catch (err) {
|
|
58314
|
-
const m = `FAIL cannot read ${
|
|
58673
|
+
const m = `FAIL cannot read ${path122}: ${err instanceof Error ? err.message : "unknown"}`;
|
|
58315
58674
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58316
58675
|
}
|
|
58317
58676
|
if (!text.replace(/^/, "").startsWith("---")) {
|
|
58318
|
-
const m = `FAIL ${
|
|
58677
|
+
const m = `FAIL ${path122}: no YAML frontmatter (missing opening --- marker)`;
|
|
58319
58678
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58320
58679
|
}
|
|
58321
58680
|
if (!text.includes("\n---", 3)) {
|
|
58322
|
-
const m = `FAIL ${
|
|
58681
|
+
const m = `FAIL ${path122}: frontmatter block never closed (missing closing --- marker)`;
|
|
58323
58682
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58324
58683
|
}
|
|
58325
58684
|
const fm = extractFrontmatter(text);
|
|
58326
58685
|
if (fm === null) {
|
|
58327
|
-
const m = `FAIL ${
|
|
58686
|
+
const m = `FAIL ${path122}: frontmatter could not be parsed as YAML`;
|
|
58328
58687
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58329
58688
|
}
|
|
58330
58689
|
const hasScores = "k5_scores" in fm;
|
|
@@ -58334,7 +58693,7 @@ function validatePlan(path121) {
|
|
|
58334
58693
|
if (!hasScores && !hasBoost && !hasComposite && !hasScoredAt) {
|
|
58335
58694
|
return {
|
|
58336
58695
|
ok: true,
|
|
58337
|
-
message: `PASS ${
|
|
58696
|
+
message: `PASS ${path122}: k5_scores absent (acceptable \u2014 legacy plan)`,
|
|
58338
58697
|
json: emptyJson("absent", [])
|
|
58339
58698
|
};
|
|
58340
58699
|
}
|
|
@@ -58358,12 +58717,12 @@ function validatePlan(path121) {
|
|
|
58358
58717
|
if (errors.length > 0) {
|
|
58359
58718
|
return {
|
|
58360
58719
|
ok: false,
|
|
58361
|
-
message: `FAIL ${
|
|
58720
|
+
message: `FAIL ${path122}: ${errors.join("; ")}`,
|
|
58362
58721
|
json: emptyJson("fail", errors)
|
|
58363
58722
|
};
|
|
58364
58723
|
}
|
|
58365
58724
|
const json = emptyJson("pass", []);
|
|
58366
|
-
const lines = [`PASS ${
|
|
58725
|
+
const lines = [`PASS ${path122}: k5_scores valid`];
|
|
58367
58726
|
if (hasScores && typeof fm.k5_scores === "object" && fm.k5_scores !== null) {
|
|
58368
58727
|
const scoresObj = fm.k5_scores;
|
|
58369
58728
|
const parsed = {};
|
|
@@ -58433,7 +58792,7 @@ function registerFlywheelK5Validate(parent) {
|
|
|
58433
58792
|
}
|
|
58434
58793
|
|
|
58435
58794
|
// src/commands/flywheel/k10-measure.ts
|
|
58436
|
-
import { readFileSync as
|
|
58795
|
+
import { readFileSync as readFileSync119 } from "node:fs";
|
|
58437
58796
|
|
|
58438
58797
|
// ../core/dist/lib/k10-budget.js
|
|
58439
58798
|
var K10_TOKEN_CAP = 5500;
|
|
@@ -58490,7 +58849,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
58490
58849
|
parent.command("k10-measure").description("Measure K10 token budget for upstream + optional overlay; emit PASS/REJECT verdict").requiredOption("--upstream <path>", "path to upstream file (e.g. persona prompt)").option("--overlay <path>", "path to overlay file (omit if none \u2014 PASS without enforcement)").option("--json", "emit verdict as JSON instead of human-readable").action((opts) => {
|
|
58491
58850
|
let upstreamText;
|
|
58492
58851
|
try {
|
|
58493
|
-
upstreamText =
|
|
58852
|
+
upstreamText = readFileSync119(opts.upstream, "utf8");
|
|
58494
58853
|
} catch (err) {
|
|
58495
58854
|
process.stderr.write(
|
|
58496
58855
|
`[k10-measure-error] cannot read upstream ${opts.upstream}: ${err instanceof Error ? err.message : "unknown"}
|
|
@@ -58502,7 +58861,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
58502
58861
|
let overlayTokens = null;
|
|
58503
58862
|
if (opts.overlay !== void 0) {
|
|
58504
58863
|
try {
|
|
58505
|
-
const overlayText =
|
|
58864
|
+
const overlayText = readFileSync119(opts.overlay, "utf8");
|
|
58506
58865
|
overlayTokens = tokensFromText(overlayText);
|
|
58507
58866
|
} catch (err) {
|
|
58508
58867
|
process.stderr.write(
|
|
@@ -58536,13 +58895,13 @@ function registerFlywheelK10Measure(parent) {
|
|
|
58536
58895
|
}
|
|
58537
58896
|
|
|
58538
58897
|
// src/commands/flywheel/check-persona-skeleton.ts
|
|
58539
|
-
import { existsSync as
|
|
58540
|
-
import { homedir as
|
|
58541
|
-
import { basename as basename14, join as
|
|
58898
|
+
import { existsSync as existsSync132, readFileSync as readFileSync120, statSync as statSync34 } from "node:fs";
|
|
58899
|
+
import { homedir as homedir83 } from "node:os";
|
|
58900
|
+
import { basename as basename14, join as join137 } from "node:path";
|
|
58542
58901
|
import { parse as parseYAML2 } from "yaml";
|
|
58543
58902
|
var CHARS_PER_TOKEN3 = 4;
|
|
58544
58903
|
var K10_TOKEN_CAP2 = 6e3;
|
|
58545
|
-
var AGENTS_DIR =
|
|
58904
|
+
var AGENTS_DIR = join137(homedir83(), ".claude", "agents");
|
|
58546
58905
|
var REQUIRED_FRONTMATTER_KEYS = ["name", "description", "allowed-tools"];
|
|
58547
58906
|
var REQUIRED_SECTIONS = [
|
|
58548
58907
|
"## Role",
|
|
@@ -58582,10 +58941,10 @@ function countNamedPatterns(sectionText) {
|
|
|
58582
58941
|
return Math.max(h3Count, bulletCount);
|
|
58583
58942
|
}
|
|
58584
58943
|
function checkFile(filepath) {
|
|
58585
|
-
if (!
|
|
58944
|
+
if (!existsSync132(filepath) || !statSync34(filepath).isFile()) {
|
|
58586
58945
|
return { passed: false, failures: [`file not found: ${filepath}`], tokens: 0, mergedSkipped: false };
|
|
58587
58946
|
}
|
|
58588
|
-
const text =
|
|
58947
|
+
const text = readFileSync120(filepath, "utf8");
|
|
58589
58948
|
const { fm, body } = parseFile(text);
|
|
58590
58949
|
const failures = [];
|
|
58591
58950
|
for (const key of REQUIRED_FRONTMATTER_KEYS) {
|
|
@@ -58598,8 +58957,8 @@ function checkFile(filepath) {
|
|
|
58598
58957
|
const agentName = typeof fm.name === "string" ? fm.name : "";
|
|
58599
58958
|
let mergedSkipped = false;
|
|
58600
58959
|
if (!isNewAgent && agentName !== "") {
|
|
58601
|
-
const upstreamPath =
|
|
58602
|
-
if (
|
|
58960
|
+
const upstreamPath = join137(AGENTS_DIR, `${agentName}.md`);
|
|
58961
|
+
if (existsSync132(upstreamPath)) {
|
|
58603
58962
|
mergedSkipped = true;
|
|
58604
58963
|
}
|
|
58605
58964
|
}
|
|
@@ -58651,7 +59010,7 @@ Results: ${passCount} passed, ${failCount} failed
|
|
|
58651
59010
|
}
|
|
58652
59011
|
|
|
58653
59012
|
// src/commands/flywheel/diversity-check.ts
|
|
58654
|
-
import { readFileSync as
|
|
59013
|
+
import { readFileSync as readFileSync121 } from "node:fs";
|
|
58655
59014
|
import { basename as basename15 } from "node:path";
|
|
58656
59015
|
import { globSync as globSync2 } from "node:fs";
|
|
58657
59016
|
|
|
@@ -58761,7 +59120,7 @@ function registerFlywheelDiversityCheck(parent) {
|
|
|
58761
59120
|
const personas = /* @__PURE__ */ new Map();
|
|
58762
59121
|
for (const filepath of files) {
|
|
58763
59122
|
try {
|
|
58764
|
-
const body =
|
|
59123
|
+
const body = readFileSync121(filepath, "utf8");
|
|
58765
59124
|
if (body.trim().length > 0) {
|
|
58766
59125
|
personas.set(basename15(filepath, ".md"), body);
|
|
58767
59126
|
}
|
|
@@ -58792,9 +59151,9 @@ ${formatRedivergencePrompt(persona_a, persona_b, score, void 0, void 0, threshol
|
|
|
58792
59151
|
}
|
|
58793
59152
|
|
|
58794
59153
|
// src/commands/flywheel/ping.ts
|
|
58795
|
-
import { mkdirSync as mkdirSync78, writeFileSync as
|
|
58796
|
-
import { homedir as
|
|
58797
|
-
import { dirname as dirname75, join as
|
|
59154
|
+
import { mkdirSync as mkdirSync78, writeFileSync as writeFileSync74 } from "node:fs";
|
|
59155
|
+
import { homedir as homedir84 } from "node:os";
|
|
59156
|
+
import { dirname as dirname75, join as join138 } from "node:path";
|
|
58798
59157
|
var COLD_START_BUDGET_GOOD_MS = 200;
|
|
58799
59158
|
var COLD_START_BUDGET_FAIR_MS = 500;
|
|
58800
59159
|
function classifyColdStart(coldStartMs) {
|
|
@@ -58810,9 +59169,9 @@ function readOlamVersion() {
|
|
|
58810
59169
|
}
|
|
58811
59170
|
}
|
|
58812
59171
|
function writeBaseline(record) {
|
|
58813
|
-
const baselinePath =
|
|
59172
|
+
const baselinePath = join138(homedir84(), ".local", "share", "olam", "flywheel-baseline.json");
|
|
58814
59173
|
mkdirSync78(dirname75(baselinePath), { recursive: true });
|
|
58815
|
-
|
|
59174
|
+
writeFileSync74(baselinePath, JSON.stringify(record, null, 2) + "\n", "utf8");
|
|
58816
59175
|
return baselinePath;
|
|
58817
59176
|
}
|
|
58818
59177
|
function registerFlywheelPing(parent) {
|
|
@@ -58847,30 +59206,30 @@ function registerFlywheelPing(parent) {
|
|
|
58847
59206
|
}
|
|
58848
59207
|
|
|
58849
59208
|
// src/commands/flywheel/session-start.ts
|
|
58850
|
-
import { readFileSync as
|
|
58851
|
-
import { homedir as
|
|
58852
|
-
import { join as
|
|
59209
|
+
import { readFileSync as readFileSync122, statSync as statSync35 } from "node:fs";
|
|
59210
|
+
import { homedir as homedir85 } from "node:os";
|
|
59211
|
+
import { join as join139 } from "node:path";
|
|
58853
59212
|
var SESSIONSTART_HOOK_SENTINEL = "olam-sessionstart-context-hook-v1";
|
|
58854
59213
|
var MAX_WAKE_BRIEF_BYTES = 8 * 1024;
|
|
58855
59214
|
var MAX_ACTIVE_WORLD_BYTES = 4 * 1024;
|
|
58856
59215
|
var MAX_CONFIG_BYTES = 8 * 1024;
|
|
58857
|
-
function tryReadCapped(
|
|
59216
|
+
function tryReadCapped(path122, maxBytes) {
|
|
58858
59217
|
try {
|
|
58859
|
-
const stat = statSync35(
|
|
59218
|
+
const stat = statSync35(path122);
|
|
58860
59219
|
if (!stat.isFile() || stat.size === 0) return null;
|
|
58861
59220
|
if (stat.size > maxBytes) {
|
|
58862
59221
|
process.stderr.write(
|
|
58863
|
-
`[${SESSIONSTART_HOOK_SENTINEL}] skipping ${
|
|
59222
|
+
`[${SESSIONSTART_HOOK_SENTINEL}] skipping ${path122}: ${stat.size} bytes > ${maxBytes} cap
|
|
58864
59223
|
`
|
|
58865
59224
|
);
|
|
58866
59225
|
return null;
|
|
58867
59226
|
}
|
|
58868
|
-
return
|
|
59227
|
+
return readFileSync122(path122, "utf-8");
|
|
58869
59228
|
} catch (err) {
|
|
58870
59229
|
const code = err?.code;
|
|
58871
59230
|
if (code === "ENOENT") return null;
|
|
58872
59231
|
process.stderr.write(
|
|
58873
|
-
`[${SESSIONSTART_HOOK_SENTINEL}] read failed for ${
|
|
59232
|
+
`[${SESSIONSTART_HOOK_SENTINEL}] read failed for ${path122}: ${err?.message ?? err}
|
|
58874
59233
|
`
|
|
58875
59234
|
);
|
|
58876
59235
|
return null;
|
|
@@ -58890,15 +59249,15 @@ function tryParseJson(raw, label) {
|
|
|
58890
59249
|
}
|
|
58891
59250
|
function buildContextBlock(olamHome7) {
|
|
58892
59251
|
const config = tryParseJson(
|
|
58893
|
-
tryReadCapped(
|
|
59252
|
+
tryReadCapped(join139(olamHome7, "config.json"), MAX_CONFIG_BYTES),
|
|
58894
59253
|
"config.json"
|
|
58895
59254
|
);
|
|
58896
59255
|
const activeWorld = tryParseJson(
|
|
58897
|
-
tryReadCapped(
|
|
59256
|
+
tryReadCapped(join139(olamHome7, "state", "active-world.json"), MAX_ACTIVE_WORLD_BYTES),
|
|
58898
59257
|
"active-world.json"
|
|
58899
59258
|
);
|
|
58900
59259
|
const wakeBrief = tryReadCapped(
|
|
58901
|
-
|
|
59260
|
+
join139(olamHome7, "state", "wake-brief.md"),
|
|
58902
59261
|
MAX_WAKE_BRIEF_BYTES
|
|
58903
59262
|
);
|
|
58904
59263
|
const sections = [];
|
|
@@ -58950,7 +59309,7 @@ function registerFlywheelSessionStart(parent) {
|
|
|
58950
59309
|
parent.command("session-start").description(
|
|
58951
59310
|
"Emit operator-state context for the SessionStart hook (4th defense layer). Reads ~/.olam/state/* and writes the additionalContext JSON to stdout. Fail-soft: always exits 0."
|
|
58952
59311
|
).action(() => {
|
|
58953
|
-
const olamHome7 = process.env.OLAM_HOME ??
|
|
59312
|
+
const olamHome7 = process.env.OLAM_HOME ?? join139(homedir85(), ".olam");
|
|
58954
59313
|
emitSessionStartContext(olamHome7);
|
|
58955
59314
|
process.exit(0);
|
|
58956
59315
|
});
|
|
@@ -58959,9 +59318,9 @@ function registerFlywheelSessionStart(parent) {
|
|
|
58959
59318
|
// src/commands/flywheel/install-sessionstart-hook.ts
|
|
58960
59319
|
init_merge_settings();
|
|
58961
59320
|
init_output();
|
|
58962
|
-
import { existsSync as
|
|
58963
|
-
import { homedir as
|
|
58964
|
-
import { dirname as dirname76, join as
|
|
59321
|
+
import { existsSync as existsSync133, copyFileSync as copyFileSync19, mkdirSync as mkdirSync79, readFileSync as readFileSync123, unlinkSync as unlinkSync26, writeFileSync as writeFileSync75 } from "node:fs";
|
|
59322
|
+
import { homedir as homedir86 } from "node:os";
|
|
59323
|
+
import { dirname as dirname76, join as join140 } from "node:path";
|
|
58965
59324
|
var SESSIONSTART_HOOK_STAGE = "SessionStart";
|
|
58966
59325
|
var SESSIONSTART_HOOK_TIMEOUT_MS = 5e3;
|
|
58967
59326
|
var NOOP_GUARD = "command -v olam >/dev/null 2>&1 || exit 0;";
|
|
@@ -58978,11 +59337,11 @@ function buildSessionStartHookEntry() {
|
|
|
58978
59337
|
};
|
|
58979
59338
|
}
|
|
58980
59339
|
function settingsPathFor6(scope, cwd) {
|
|
58981
|
-
if (scope === "user") return
|
|
58982
|
-
return
|
|
59340
|
+
if (scope === "user") return join140(homedir86(), ".claude", "settings.json");
|
|
59341
|
+
return join140(cwd ?? process.cwd(), ".claude", "settings.json");
|
|
58983
59342
|
}
|
|
58984
59343
|
function backup4(filePath) {
|
|
58985
|
-
if (!
|
|
59344
|
+
if (!existsSync133(filePath)) return null;
|
|
58986
59345
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
58987
59346
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
58988
59347
|
copyFileSync19(filePath, backupPath);
|
|
@@ -59008,8 +59367,8 @@ function installSessionStartHook(filePath) {
|
|
|
59008
59367
|
return { status: result.status, filePath, backupPath };
|
|
59009
59368
|
}
|
|
59010
59369
|
function uninstallSessionStartHook(filePath) {
|
|
59011
|
-
if (!
|
|
59012
|
-
const raw =
|
|
59370
|
+
if (!existsSync133(filePath)) return { status: "no-settings", filePath };
|
|
59371
|
+
const raw = readFileSync123(filePath, "utf-8");
|
|
59013
59372
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
59014
59373
|
const matchers = settings.hooks?.SessionStart;
|
|
59015
59374
|
if (!Array.isArray(matchers) || matchers.length === 0) {
|
|
@@ -59049,7 +59408,7 @@ function uninstallSessionStartHook(filePath) {
|
|
|
59049
59408
|
delete next.hooks.SessionStart;
|
|
59050
59409
|
}
|
|
59051
59410
|
}
|
|
59052
|
-
|
|
59411
|
+
writeFileSync75(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
59053
59412
|
return { status: "removed", filePath };
|
|
59054
59413
|
}
|
|
59055
59414
|
function registerFlywheelInstallSessionStartHook(parent) {
|
|
@@ -59377,14 +59736,14 @@ init_manager();
|
|
|
59377
59736
|
init_context();
|
|
59378
59737
|
init_output();
|
|
59379
59738
|
import { spawnSync as defaultSpawnSync } from "node:child_process";
|
|
59380
|
-
import * as
|
|
59381
|
-
import * as
|
|
59382
|
-
import * as
|
|
59739
|
+
import * as fs119 from "node:fs";
|
|
59740
|
+
import * as os65 from "node:os";
|
|
59741
|
+
import * as path119 from "node:path";
|
|
59383
59742
|
function devboxContainerName(worldId) {
|
|
59384
59743
|
return `olam-${worldId}-devbox`;
|
|
59385
59744
|
}
|
|
59386
59745
|
function olamHomeDir() {
|
|
59387
|
-
return process.env["OLAM_HOME"] ??
|
|
59746
|
+
return process.env["OLAM_HOME"] ?? path119.join(os65.homedir(), ".olam");
|
|
59388
59747
|
}
|
|
59389
59748
|
function defaultRestartContainer(name, spawn14 = defaultSpawnSync) {
|
|
59390
59749
|
const r = spawn14("docker", ["restart", "--time", "30", name], {
|
|
@@ -59397,8 +59756,8 @@ function defaultRestartContainer(name, spawn14 = defaultSpawnSync) {
|
|
|
59397
59756
|
};
|
|
59398
59757
|
}
|
|
59399
59758
|
function defaultAppendAuditLog(homeDir, line) {
|
|
59400
|
-
|
|
59401
|
-
|
|
59759
|
+
fs119.mkdirSync(homeDir, { recursive: true });
|
|
59760
|
+
fs119.appendFileSync(path119.join(homeDir, "usage.log"), line.endsWith("\n") ? line : line + "\n", {
|
|
59402
59761
|
encoding: "utf-8"
|
|
59403
59762
|
});
|
|
59404
59763
|
}
|
|
@@ -59443,19 +59802,19 @@ async function doRekey(worldId, deps) {
|
|
|
59443
59802
|
);
|
|
59444
59803
|
const rotatedAt = deps.now().toISOString();
|
|
59445
59804
|
const homeDir = deps.olamHomeDir();
|
|
59446
|
-
const worldDir =
|
|
59447
|
-
|
|
59448
|
-
const credentialsPath =
|
|
59805
|
+
const worldDir = path119.join(homeDir, "worlds", worldId);
|
|
59806
|
+
fs119.mkdirSync(worldDir, { recursive: true });
|
|
59807
|
+
const credentialsPath = path119.join(worldDir, "credentials.json");
|
|
59449
59808
|
const payload = {
|
|
59450
59809
|
worldRoleName,
|
|
59451
59810
|
password,
|
|
59452
59811
|
rotatedAt
|
|
59453
59812
|
};
|
|
59454
|
-
|
|
59813
|
+
fs119.writeFileSync(credentialsPath, JSON.stringify(payload, null, 2) + "\n", {
|
|
59455
59814
|
encoding: "utf-8",
|
|
59456
59815
|
mode: 384
|
|
59457
59816
|
});
|
|
59458
|
-
|
|
59817
|
+
fs119.chmodSync(credentialsPath, 384);
|
|
59459
59818
|
const restart = deps.restartContainer(devboxContainerName(worldId));
|
|
59460
59819
|
deps.appendAuditLog(`${rotatedAt} ${worldId} rekey`);
|
|
59461
59820
|
if (!restart.ok) {
|
|
@@ -59521,9 +59880,9 @@ function registerRekey(program2) {
|
|
|
59521
59880
|
// src/commands/yolo.ts
|
|
59522
59881
|
init_output();
|
|
59523
59882
|
import * as childProcess2 from "node:child_process";
|
|
59524
|
-
import * as
|
|
59525
|
-
import * as
|
|
59526
|
-
import * as
|
|
59883
|
+
import * as fs120 from "node:fs";
|
|
59884
|
+
import * as os66 from "node:os";
|
|
59885
|
+
import * as path120 from "node:path";
|
|
59527
59886
|
import pc51 from "picocolors";
|
|
59528
59887
|
var YOLO_BOOT_DELAY_MS = 8e3;
|
|
59529
59888
|
var CAPTURE_DELAY_MS = 4e3;
|
|
@@ -59551,7 +59910,7 @@ function defaultSleeper(ms) {
|
|
|
59551
59910
|
function detectTmuxBinary(runner = defaultRunner) {
|
|
59552
59911
|
for (const p of TMUX_PROBE_PATHS) {
|
|
59553
59912
|
if (TMUX_SHIM_MARKERS.some((m) => p.includes(m))) continue;
|
|
59554
|
-
if (
|
|
59913
|
+
if (fs120.existsSync(p)) return p;
|
|
59555
59914
|
}
|
|
59556
59915
|
const result = runner("which", ["tmux"]);
|
|
59557
59916
|
if (result.status === 0 && result.stdout) {
|
|
@@ -59565,17 +59924,17 @@ function resolveWorktreeRoot(runner = defaultRunner, cwd = process.cwd()) {
|
|
|
59565
59924
|
if (process.env["OLAM_TMUX_YOLO_ROOT"]) {
|
|
59566
59925
|
return process.env["OLAM_TMUX_YOLO_ROOT"];
|
|
59567
59926
|
}
|
|
59568
|
-
const rootFile =
|
|
59569
|
-
if (
|
|
59570
|
-
const line =
|
|
59927
|
+
const rootFile = path120.join(os66.homedir(), ".olam-tmux-yolo-root");
|
|
59928
|
+
if (fs120.existsSync(rootFile)) {
|
|
59929
|
+
const line = fs120.readFileSync(rootFile, "utf-8").trim();
|
|
59571
59930
|
if (line) return line;
|
|
59572
59931
|
}
|
|
59573
59932
|
const gitResult = runner("git", ["rev-parse", "--show-toplevel"], { cwd });
|
|
59574
59933
|
if (gitResult.status !== 0 || !gitResult.stdout) {
|
|
59575
|
-
return
|
|
59934
|
+
return path120.join(cwd, "..", path120.basename(cwd) + "-wt");
|
|
59576
59935
|
}
|
|
59577
59936
|
const repoRoot = gitResult.stdout.trim();
|
|
59578
|
-
return
|
|
59937
|
+
return path120.join(path120.dirname(repoRoot), path120.basename(repoRoot) + "-wt");
|
|
59579
59938
|
}
|
|
59580
59939
|
function resolveYoloCommand(runner = defaultRunner) {
|
|
59581
59940
|
const result = runner("bash", ["-lc", "command -v yolo"]);
|
|
@@ -59601,7 +59960,7 @@ async function spawnYolo(opts) {
|
|
|
59601
59960
|
);
|
|
59602
59961
|
}
|
|
59603
59962
|
try {
|
|
59604
|
-
|
|
59963
|
+
fs120.accessSync(opts.promptFile, fs120.constants.R_OK);
|
|
59605
59964
|
} catch {
|
|
59606
59965
|
throw new Error(
|
|
59607
59966
|
`Prompt file not found or not readable: ${opts.promptFile}
|
|
@@ -59609,7 +59968,7 @@ Create the file with your task description and try again.`
|
|
|
59609
59968
|
);
|
|
59610
59969
|
}
|
|
59611
59970
|
const worktreeRoot = resolveWorktreeRoot(runner, cwd);
|
|
59612
|
-
const worktreePath =
|
|
59971
|
+
const worktreePath = path120.join(worktreeRoot, opts.name);
|
|
59613
59972
|
const branchCheck = runner("git", ["show-ref", "--verify", "--quiet", `refs/heads/${opts.branch}`], { cwd });
|
|
59614
59973
|
if (branchCheck.status === 0) {
|
|
59615
59974
|
throw new Error(
|
|
@@ -59617,7 +59976,7 @@ Create the file with your task description and try again.`
|
|
|
59617
59976
|
Run: olam yolo --cleanup ${opts.name} (or use --force to bypass the merged check)`
|
|
59618
59977
|
);
|
|
59619
59978
|
}
|
|
59620
|
-
if (
|
|
59979
|
+
if (fs120.existsSync(worktreePath)) {
|
|
59621
59980
|
throw new Error(
|
|
59622
59981
|
`Worktree directory already exists: ${worktreePath}
|
|
59623
59982
|
Run: olam yolo --cleanup ${opts.name} to remove it first.`
|
|
@@ -59682,10 +60041,10 @@ function listYoloWindows(opts = {}) {
|
|
|
59682
60041
|
const windowNames = listResult.stdout.split("\n").map((n) => n.trim()).filter(Boolean);
|
|
59683
60042
|
const worktreeRoot = resolveWorktreeRoot(runner, cwd);
|
|
59684
60043
|
return windowNames.map((name) => {
|
|
59685
|
-
const worktreePath =
|
|
60044
|
+
const worktreePath = path120.join(worktreeRoot, name);
|
|
59686
60045
|
return {
|
|
59687
60046
|
name,
|
|
59688
|
-
worktreePath:
|
|
60047
|
+
worktreePath: fs120.existsSync(worktreePath) ? worktreePath : void 0
|
|
59689
60048
|
};
|
|
59690
60049
|
});
|
|
59691
60050
|
}
|
|
@@ -59694,7 +60053,7 @@ async function cleanupYolo(opts) {
|
|
|
59694
60053
|
const cwd = opts.cwd ?? process.cwd();
|
|
59695
60054
|
const mainBranch = opts.mainBranch ?? "main";
|
|
59696
60055
|
const worktreeRoot = resolveWorktreeRoot(runner, cwd);
|
|
59697
|
-
const worktreePath =
|
|
60056
|
+
const worktreePath = path120.join(worktreeRoot, opts.name);
|
|
59698
60057
|
const worktreeList = runner("git", ["worktree", "list", "--porcelain"], { cwd });
|
|
59699
60058
|
let branch;
|
|
59700
60059
|
if (worktreeList.status === 0) {
|
|
@@ -59819,18 +60178,18 @@ function registerYolo(program2) {
|
|
|
59819
60178
|
}
|
|
59820
60179
|
|
|
59821
60180
|
// src/pleri-config.ts
|
|
59822
|
-
import * as
|
|
59823
|
-
import * as
|
|
60181
|
+
import * as fs121 from "node:fs";
|
|
60182
|
+
import * as path121 from "node:path";
|
|
59824
60183
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
59825
60184
|
if (process.env.PLERI_BASE_URL) {
|
|
59826
60185
|
return true;
|
|
59827
60186
|
}
|
|
59828
|
-
const configPath =
|
|
59829
|
-
if (!
|
|
60187
|
+
const configPath = path121.join(configDir, "config.yaml");
|
|
60188
|
+
if (!fs121.existsSync(configPath)) {
|
|
59830
60189
|
return false;
|
|
59831
60190
|
}
|
|
59832
60191
|
try {
|
|
59833
|
-
const contents =
|
|
60192
|
+
const contents = fs121.readFileSync(configPath, "utf8");
|
|
59834
60193
|
return /^[^#\n]*\bpleri:/m.test(contents);
|
|
59835
60194
|
} catch {
|
|
59836
60195
|
return false;
|
|
@@ -59907,7 +60266,7 @@ var HELP_GROUPS = [
|
|
|
59907
60266
|
// crystallize is conditionally hidden (requires Pleri); kept here so it
|
|
59908
60267
|
// lands in the right group when Pleri IS configured.
|
|
59909
60268
|
title: "Dev tools",
|
|
59910
|
-
names: ["begin", "completion", "crystallize", "hermes", "lanes", "policy-check", "pr", "stop", "yolo"]
|
|
60269
|
+
names: ["begin", "completion", "crystallize", "hermes", "inbox", "lanes", "policy-check", "pr", "stop", "yolo"]
|
|
59911
60270
|
},
|
|
59912
60271
|
{
|
|
59913
60272
|
// Alphabetical within group. `config` lives in 'Cloud setup' above.
|
|
@@ -60129,7 +60488,7 @@ try {
|
|
|
60129
60488
|
}
|
|
60130
60489
|
}
|
|
60131
60490
|
void scheduleUpgradeCheck(cliVersion);
|
|
60132
|
-
if (process.argv.length <= 2 && !
|
|
60491
|
+
if (process.argv.length <= 2 && !existsSync136(join144(homedir89(), ".olam", "config.json"))) {
|
|
60133
60492
|
process.stdout.write("No olam config found yet.\n");
|
|
60134
60493
|
process.stdout.write("Get started: olam setup\n\n");
|
|
60135
60494
|
}
|