@pleri/olam-cli 0.1.209 → 0.1.211
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 +794 -437
- package/dist/mcp-server.js +193 -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 +25 -6
- 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) {
|
|
@@ -53845,8 +54016,9 @@ function registerMcpServe(cmd) {
|
|
|
53845
54016
|
init_output();
|
|
53846
54017
|
init_install_shared();
|
|
53847
54018
|
var NPM_PACKAGE_NAME2 = "@pleri/olam-cli";
|
|
54019
|
+
var NPM_PACKAGE_SPEC = `${NPM_PACKAGE_NAME2}@latest`;
|
|
53848
54020
|
function buildClaudeMcpAddArgs2(scope, useGlobal) {
|
|
53849
|
-
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"] };
|
|
53850
54022
|
return {
|
|
53851
54023
|
command: "claude",
|
|
53852
54024
|
args: ["mcp", "add", "olam", "--scope", scope, "--", target.cmd, ...target.args]
|
|
@@ -53956,8 +54128,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
|
|
|
53956
54128
|
function authHeaders() {
|
|
53957
54129
|
return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
|
|
53958
54130
|
}
|
|
53959
|
-
async function apiFetch(
|
|
53960
|
-
const res = await fetch(`${BASE_URL}${
|
|
54131
|
+
async function apiFetch(path122, init = {}) {
|
|
54132
|
+
const res = await fetch(`${BASE_URL}${path122}`, {
|
|
53961
54133
|
...init,
|
|
53962
54134
|
headers: {
|
|
53963
54135
|
"Content-Type": "application/json",
|
|
@@ -54974,18 +55146,29 @@ import { existsSync as existsSync121 } from "node:fs";
|
|
|
54974
55146
|
// ../core/dist/memory/gate.js
|
|
54975
55147
|
init_olam_paths();
|
|
54976
55148
|
import { readFileSync as readFileSync108 } from "node:fs";
|
|
54977
|
-
var
|
|
54978
|
-
|
|
54979
|
-
|
|
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() {
|
|
54980
55163
|
const envVal = process.env["OLAM_AGENT_MEMORY"];
|
|
54981
55164
|
if (envVal !== void 0 && envVal.length > 0) {
|
|
54982
|
-
return
|
|
55165
|
+
return ENV_MODE.get(envVal.trim().toLowerCase()) ?? "off";
|
|
54983
55166
|
}
|
|
54984
55167
|
try {
|
|
54985
55168
|
const raw = readFileSync108(agentMemoryEnabledPath(), "utf8").trim().toLowerCase();
|
|
54986
|
-
return
|
|
55169
|
+
return FILE_MODE.get(raw) ?? "off";
|
|
54987
55170
|
} catch {
|
|
54988
|
-
return
|
|
55171
|
+
return "off";
|
|
54989
55172
|
}
|
|
54990
55173
|
}
|
|
54991
55174
|
|
|
@@ -55039,18 +55222,18 @@ async function runMemoryStatus(opts = {}) {
|
|
|
55039
55222
|
printInfo("livez", s.livez);
|
|
55040
55223
|
printInfo("secret", s.secretSet ? "~/.olam/memory-secret (set)" : "(missing)");
|
|
55041
55224
|
printInfo("port", `${s.port}`);
|
|
55042
|
-
const
|
|
55225
|
+
const mode = agentMemoryMode();
|
|
55043
55226
|
const envVal = process.env["OLAM_AGENT_MEMORY"];
|
|
55044
55227
|
const envActive = envVal !== void 0 && envVal.length > 0;
|
|
55045
|
-
|
|
55046
|
-
|
|
55047
|
-
|
|
55048
|
-
|
|
55049
|
-
);
|
|
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})`);
|
|
55050
55233
|
} else {
|
|
55051
55234
|
printInfo(
|
|
55052
55235
|
"agent-memory",
|
|
55053
|
-
envActive ? `
|
|
55236
|
+
envActive ? `OFF (${source})` : `OFF \u2014 enable with \`olam memory enable\` (--editor for capture)`
|
|
55054
55237
|
);
|
|
55055
55238
|
}
|
|
55056
55239
|
if (s.legacyPidfilePresent) {
|
|
@@ -55196,27 +55379,34 @@ init_olam_paths();
|
|
|
55196
55379
|
import { mkdirSync as mkdirSync73, writeFileSync as writeFileSync66 } from "node:fs";
|
|
55197
55380
|
import { dirname as dirname69 } from "node:path";
|
|
55198
55381
|
init_output();
|
|
55199
|
-
function writeGateFlag(
|
|
55382
|
+
function writeGateFlag(value) {
|
|
55200
55383
|
const flagPath = agentMemoryEnabledPath();
|
|
55201
55384
|
mkdirSync73(dirname69(flagPath), { recursive: true });
|
|
55202
|
-
writeFileSync66(flagPath,
|
|
55385
|
+
writeFileSync66(flagPath, `${value}
|
|
55386
|
+
`, { mode: 420 });
|
|
55203
55387
|
}
|
|
55204
55388
|
function registerMemoryEnable(parent) {
|
|
55205
|
-
parent.command("enable").description(
|
|
55206
|
-
|
|
55207
|
-
|
|
55208
|
-
|
|
55209
|
-
|
|
55210
|
-
|
|
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());
|
|
55211
55402
|
});
|
|
55212
55403
|
}
|
|
55213
55404
|
function registerMemoryDisable(parent) {
|
|
55214
55405
|
parent.command("disable").description("Disable agent-memory recall and capture (writes FALSE to the gate flag file)").action(() => {
|
|
55215
|
-
writeGateFlag(
|
|
55216
|
-
const flagPath = agentMemoryEnabledPath();
|
|
55406
|
+
writeGateFlag("FALSE");
|
|
55217
55407
|
printSuccess(`agent-memory disabled`);
|
|
55218
|
-
printInfo("flag file",
|
|
55219
|
-
printInfo("
|
|
55408
|
+
printInfo("flag file", agentMemoryEnabledPath());
|
|
55409
|
+
printInfo("mode", agentMemoryMode());
|
|
55220
55410
|
});
|
|
55221
55411
|
}
|
|
55222
55412
|
|
|
@@ -55581,13 +55771,13 @@ function resolveMemoryServiceDir() {
|
|
|
55581
55771
|
);
|
|
55582
55772
|
}
|
|
55583
55773
|
function resolveLocalBridgeScript(serviceDir) {
|
|
55584
|
-
const
|
|
55585
|
-
if (!existsSync123(
|
|
55774
|
+
const path122 = join126(serviceDir, "scripts", "local-bridge-server.mjs");
|
|
55775
|
+
if (!existsSync123(path122)) {
|
|
55586
55776
|
throw new Error(
|
|
55587
|
-
`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.`
|
|
55588
55778
|
);
|
|
55589
55779
|
}
|
|
55590
|
-
return
|
|
55780
|
+
return path122;
|
|
55591
55781
|
}
|
|
55592
55782
|
function validateBridgeOpts(opts) {
|
|
55593
55783
|
const local = opts.local ?? true;
|
|
@@ -56446,18 +56636,179 @@ function registerInboxInstallHookCommand(inbox) {
|
|
|
56446
56636
|
});
|
|
56447
56637
|
}
|
|
56448
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
|
+
|
|
56449
56799
|
// src/commands/inbox/index.ts
|
|
56450
56800
|
function registerInbox(program2) {
|
|
56451
56801
|
const inbox = program2.command("inbox").description("Mobile question-inbox operations (route AskUserQuestion to phone)");
|
|
56452
56802
|
registerInboxInstallHookCommand(inbox);
|
|
56803
|
+
registerInboxToggleCommands(inbox);
|
|
56453
56804
|
}
|
|
56454
56805
|
|
|
56455
56806
|
// src/commands/kg-build.ts
|
|
56456
56807
|
init_storage_paths();
|
|
56457
56808
|
init_workspace_name();
|
|
56458
|
-
import * as
|
|
56459
|
-
import * as
|
|
56460
|
-
import * as
|
|
56809
|
+
import * as fs118 from "node:fs";
|
|
56810
|
+
import * as os64 from "node:os";
|
|
56811
|
+
import * as path118 from "node:path";
|
|
56461
56812
|
|
|
56462
56813
|
// ../core/dist/kg/kg-service-client.js
|
|
56463
56814
|
var KG_SERVICE_PORT_DEFAULT = 9997;
|
|
@@ -56468,8 +56819,8 @@ function port() {
|
|
|
56468
56819
|
const n = Number.parseInt(env, 10);
|
|
56469
56820
|
return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
|
|
56470
56821
|
}
|
|
56471
|
-
function url(
|
|
56472
|
-
return `http://127.0.0.1:${port()}${
|
|
56822
|
+
function url(path122) {
|
|
56823
|
+
return `http://127.0.0.1:${port()}${path122}`;
|
|
56473
56824
|
}
|
|
56474
56825
|
function kgServiceHealthUrl() {
|
|
56475
56826
|
return url("/health");
|
|
@@ -56549,39 +56900,39 @@ init_storage_paths();
|
|
|
56549
56900
|
init_workspace_name();
|
|
56550
56901
|
init_kg_caps();
|
|
56551
56902
|
init_output();
|
|
56552
|
-
import
|
|
56553
|
-
import { homedir as
|
|
56554
|
-
import
|
|
56903
|
+
import fs113 from "node:fs";
|
|
56904
|
+
import { homedir as homedir76 } from "node:os";
|
|
56905
|
+
import path113 from "node:path";
|
|
56555
56906
|
function olamHome6() {
|
|
56556
|
-
return process.env.OLAM_HOME ??
|
|
56907
|
+
return process.env.OLAM_HOME ?? path113.join(homedir76(), ".olam");
|
|
56557
56908
|
}
|
|
56558
56909
|
function kgRoot2() {
|
|
56559
|
-
return
|
|
56910
|
+
return path113.join(olamHome6(), "kg");
|
|
56560
56911
|
}
|
|
56561
56912
|
function worldsRoot2() {
|
|
56562
|
-
return
|
|
56913
|
+
return path113.join(olamHome6(), "worlds");
|
|
56563
56914
|
}
|
|
56564
56915
|
function dirSizeBytes2(dir) {
|
|
56565
|
-
if (!
|
|
56916
|
+
if (!fs113.existsSync(dir)) return 0;
|
|
56566
56917
|
let total = 0;
|
|
56567
56918
|
const stack = [dir];
|
|
56568
56919
|
while (stack.length > 0) {
|
|
56569
56920
|
const cur = stack.pop();
|
|
56570
56921
|
let entries;
|
|
56571
56922
|
try {
|
|
56572
|
-
entries =
|
|
56923
|
+
entries = fs113.readdirSync(cur, { withFileTypes: true });
|
|
56573
56924
|
} catch {
|
|
56574
56925
|
continue;
|
|
56575
56926
|
}
|
|
56576
56927
|
for (const entry of entries) {
|
|
56577
|
-
const full =
|
|
56928
|
+
const full = path113.join(cur, entry.name);
|
|
56578
56929
|
if (entry.isSymbolicLink()) continue;
|
|
56579
56930
|
if (entry.isDirectory()) {
|
|
56580
56931
|
stack.push(full);
|
|
56581
56932
|
continue;
|
|
56582
56933
|
}
|
|
56583
56934
|
try {
|
|
56584
|
-
total +=
|
|
56935
|
+
total += fs113.statSync(full).size;
|
|
56585
56936
|
} catch {
|
|
56586
56937
|
}
|
|
56587
56938
|
}
|
|
@@ -56595,10 +56946,10 @@ function formatBytes5(n) {
|
|
|
56595
56946
|
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
56596
56947
|
}
|
|
56597
56948
|
function readFreshness(workspace) {
|
|
56598
|
-
const file =
|
|
56599
|
-
if (!
|
|
56949
|
+
const file = path113.join(kgPristinePath(workspace), "freshness.json");
|
|
56950
|
+
if (!fs113.existsSync(file)) return null;
|
|
56600
56951
|
try {
|
|
56601
|
-
const raw = JSON.parse(
|
|
56952
|
+
const raw = JSON.parse(fs113.readFileSync(file, "utf-8"));
|
|
56602
56953
|
if (raw && typeof raw === "object") return raw;
|
|
56603
56954
|
return null;
|
|
56604
56955
|
} catch {
|
|
@@ -56606,10 +56957,10 @@ function readFreshness(workspace) {
|
|
|
56606
56957
|
}
|
|
56607
56958
|
}
|
|
56608
56959
|
function readOverlayNodeCount(graphifyOutDir) {
|
|
56609
|
-
const graphPath =
|
|
56610
|
-
if (!
|
|
56960
|
+
const graphPath = path113.join(graphifyOutDir, "graph.json");
|
|
56961
|
+
if (!fs113.existsSync(graphPath)) return null;
|
|
56611
56962
|
try {
|
|
56612
|
-
const raw = JSON.parse(
|
|
56963
|
+
const raw = JSON.parse(fs113.readFileSync(graphPath, "utf-8"));
|
|
56613
56964
|
if (raw && typeof raw === "object") {
|
|
56614
56965
|
const nodes = raw.nodes;
|
|
56615
56966
|
if (Array.isArray(nodes)) return nodes.length;
|
|
@@ -56621,28 +56972,28 @@ function readOverlayNodeCount(graphifyOutDir) {
|
|
|
56621
56972
|
}
|
|
56622
56973
|
function listOverlays() {
|
|
56623
56974
|
const root = worldsRoot2();
|
|
56624
|
-
if (!
|
|
56975
|
+
if (!fs113.existsSync(root)) return [];
|
|
56625
56976
|
const records = [];
|
|
56626
56977
|
let worldDirs;
|
|
56627
56978
|
try {
|
|
56628
|
-
worldDirs =
|
|
56979
|
+
worldDirs = fs113.readdirSync(root, { withFileTypes: true });
|
|
56629
56980
|
} catch {
|
|
56630
56981
|
return [];
|
|
56631
56982
|
}
|
|
56632
56983
|
for (const worldEntry of worldDirs) {
|
|
56633
56984
|
if (!worldEntry.isDirectory()) continue;
|
|
56634
56985
|
const worldId = worldEntry.name;
|
|
56635
|
-
const worldDir =
|
|
56986
|
+
const worldDir = path113.join(root, worldId);
|
|
56636
56987
|
let cloneDirs;
|
|
56637
56988
|
try {
|
|
56638
|
-
cloneDirs =
|
|
56989
|
+
cloneDirs = fs113.readdirSync(worldDir, { withFileTypes: true });
|
|
56639
56990
|
} catch {
|
|
56640
56991
|
continue;
|
|
56641
56992
|
}
|
|
56642
56993
|
for (const cloneEntry of cloneDirs) {
|
|
56643
56994
|
if (!cloneEntry.isDirectory()) continue;
|
|
56644
|
-
const graphifyOut =
|
|
56645
|
-
if (!
|
|
56995
|
+
const graphifyOut = path113.join(worldDir, cloneEntry.name, "graphify-out");
|
|
56996
|
+
if (!fs113.existsSync(graphifyOut)) continue;
|
|
56646
56997
|
records.push({
|
|
56647
56998
|
world_id: worldId,
|
|
56648
56999
|
clone_dir: cloneEntry.name,
|
|
@@ -56656,11 +57007,11 @@ function listOverlays() {
|
|
|
56656
57007
|
}
|
|
56657
57008
|
function listPristines(overlays) {
|
|
56658
57009
|
const root = kgRoot2();
|
|
56659
|
-
if (!
|
|
57010
|
+
if (!fs113.existsSync(root)) return [];
|
|
56660
57011
|
const records = [];
|
|
56661
57012
|
let entries;
|
|
56662
57013
|
try {
|
|
56663
|
-
entries =
|
|
57014
|
+
entries = fs113.readdirSync(root, { withFileTypes: true });
|
|
56664
57015
|
} catch {
|
|
56665
57016
|
return [];
|
|
56666
57017
|
}
|
|
@@ -56673,7 +57024,7 @@ function listPristines(overlays) {
|
|
|
56673
57024
|
continue;
|
|
56674
57025
|
}
|
|
56675
57026
|
const fresh = readFreshness(workspace);
|
|
56676
|
-
const graphifyOut =
|
|
57027
|
+
const graphifyOut = path113.join(kgPristinePath(workspace), "graphify-out");
|
|
56677
57028
|
const size = dirSizeBytes2(graphifyOut);
|
|
56678
57029
|
const worldCount = overlays.filter((o) => o.clone_dir === workspace).length;
|
|
56679
57030
|
records.push({
|
|
@@ -56809,10 +57160,10 @@ init_storage_paths();
|
|
|
56809
57160
|
init_workspace_name();
|
|
56810
57161
|
init_output();
|
|
56811
57162
|
import { spawn as spawn13 } from "node:child_process";
|
|
56812
|
-
import
|
|
56813
|
-
import
|
|
57163
|
+
import fs114 from "node:fs";
|
|
57164
|
+
import path114 from "node:path";
|
|
56814
57165
|
function pidFilePath2(workspace) {
|
|
56815
|
-
return
|
|
57166
|
+
return path114.join(kgPristinePath(workspace), ".watch.pid");
|
|
56816
57167
|
}
|
|
56817
57168
|
function isPidAlive3(pid) {
|
|
56818
57169
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -56827,39 +57178,39 @@ function isPidAlive3(pid) {
|
|
|
56827
57178
|
}
|
|
56828
57179
|
function readAndClassifyPid(workspace) {
|
|
56829
57180
|
const file = pidFilePath2(workspace);
|
|
56830
|
-
if (!
|
|
57181
|
+
if (!fs114.existsSync(file)) return { status: "no-pidfile", pid: null };
|
|
56831
57182
|
let pid;
|
|
56832
57183
|
try {
|
|
56833
|
-
const raw =
|
|
57184
|
+
const raw = fs114.readFileSync(file, "utf-8").trim();
|
|
56834
57185
|
pid = Number.parseInt(raw, 10);
|
|
56835
57186
|
} catch {
|
|
56836
|
-
|
|
57187
|
+
fs114.rmSync(file, { force: true });
|
|
56837
57188
|
return { status: "stale-reclaimed", pid: null };
|
|
56838
57189
|
}
|
|
56839
57190
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
56840
|
-
|
|
57191
|
+
fs114.rmSync(file, { force: true });
|
|
56841
57192
|
return { status: "stale-reclaimed", pid: null };
|
|
56842
57193
|
}
|
|
56843
57194
|
if (isPidAlive3(pid)) return { status: "active", pid };
|
|
56844
|
-
|
|
57195
|
+
fs114.rmSync(file, { force: true });
|
|
56845
57196
|
return { status: "stale-reclaimed", pid: null };
|
|
56846
57197
|
}
|
|
56847
57198
|
function writePidFile2(workspace, pid) {
|
|
56848
57199
|
const file = pidFilePath2(workspace);
|
|
56849
|
-
const dir =
|
|
56850
|
-
|
|
56851
|
-
|
|
57200
|
+
const dir = path114.dirname(file);
|
|
57201
|
+
fs114.mkdirSync(dir, { recursive: true });
|
|
57202
|
+
fs114.writeFileSync(file, String(pid), { encoding: "utf-8" });
|
|
56852
57203
|
}
|
|
56853
57204
|
function removePidFile(workspace) {
|
|
56854
57205
|
const file = pidFilePath2(workspace);
|
|
56855
57206
|
try {
|
|
56856
|
-
|
|
57207
|
+
fs114.rmSync(file, { force: true });
|
|
56857
57208
|
} catch {
|
|
56858
57209
|
}
|
|
56859
57210
|
}
|
|
56860
57211
|
async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
56861
57212
|
const cwd = deps.cwd ?? opts.cwd ?? process.cwd();
|
|
56862
|
-
const name = workspaceArg ??
|
|
57213
|
+
const name = workspaceArg ?? path114.basename(cwd).toLowerCase();
|
|
56863
57214
|
try {
|
|
56864
57215
|
validateWorkspaceName(name);
|
|
56865
57216
|
} catch (err) {
|
|
@@ -56867,7 +57218,7 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
|
56867
57218
|
return { exitCode: 1, pidWritten: false };
|
|
56868
57219
|
}
|
|
56869
57220
|
const pristinePath = kgPristinePath(name);
|
|
56870
|
-
const graphPath =
|
|
57221
|
+
const graphPath = path114.join(pristinePath, "graphify-out", "graph.json");
|
|
56871
57222
|
const pidState = readAndClassifyPid(name);
|
|
56872
57223
|
if (pidState.status === "active") {
|
|
56873
57224
|
printError(
|
|
@@ -57180,33 +57531,33 @@ function registerKgDoctorCommand(kg) {
|
|
|
57180
57531
|
init_merge_settings();
|
|
57181
57532
|
init_hook_template2();
|
|
57182
57533
|
init_output();
|
|
57183
|
-
import * as
|
|
57184
|
-
import * as
|
|
57185
|
-
import * as
|
|
57534
|
+
import * as fs115 from "node:fs";
|
|
57535
|
+
import * as path115 from "node:path";
|
|
57536
|
+
import * as os61 from "node:os";
|
|
57186
57537
|
import { parse as yamlParse3, stringify as yamlStringify4 } from "yaml";
|
|
57187
57538
|
function settingsPathFor4(scope) {
|
|
57188
57539
|
if (scope === "user") {
|
|
57189
|
-
return
|
|
57540
|
+
return path115.join(os61.homedir(), ".claude", "settings.json");
|
|
57190
57541
|
}
|
|
57191
|
-
return
|
|
57542
|
+
return path115.join(process.cwd(), ".claude", "settings.json");
|
|
57192
57543
|
}
|
|
57193
57544
|
function backup3(filePath) {
|
|
57194
|
-
if (!
|
|
57545
|
+
if (!fs115.existsSync(filePath)) return null;
|
|
57195
57546
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
57196
57547
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
57197
|
-
|
|
57548
|
+
fs115.copyFileSync(filePath, backupPath);
|
|
57198
57549
|
return backupPath;
|
|
57199
57550
|
}
|
|
57200
57551
|
var HERMES_HOOK_MATCHERS = ["terminal", "bash", "shell", "search_files", "grep", "ripgrep"];
|
|
57201
57552
|
function hermesConfigPath2() {
|
|
57202
|
-
return
|
|
57553
|
+
return path115.join(os61.homedir(), ".hermes", "config.yaml");
|
|
57203
57554
|
}
|
|
57204
57555
|
function hermesHooksDir() {
|
|
57205
|
-
return
|
|
57556
|
+
return path115.join(os61.homedir(), ".hermes", "hooks");
|
|
57206
57557
|
}
|
|
57207
57558
|
function patchHermesConfigForHook(action) {
|
|
57208
57559
|
const configPath = hermesConfigPath2();
|
|
57209
|
-
const raw =
|
|
57560
|
+
const raw = fs115.readFileSync(configPath, "utf-8");
|
|
57210
57561
|
const config = yamlParse3(raw);
|
|
57211
57562
|
const hooks = config["hooks"] ?? {};
|
|
57212
57563
|
const preToolCall = Array.isArray(hooks["pre_tool_call"]) ? hooks["pre_tool_call"] : [];
|
|
@@ -57215,7 +57566,7 @@ function patchHermesConfigForHook(action) {
|
|
|
57215
57566
|
(e) => typeof e["command"] === "string" && e["command"].includes(HERMES_KG_HOOK_SENTINEL)
|
|
57216
57567
|
);
|
|
57217
57568
|
if (alreadyPresent) return "already-present";
|
|
57218
|
-
const hookScriptPath =
|
|
57569
|
+
const hookScriptPath = path115.join(hermesHooksDir(), "kg-first.sh");
|
|
57219
57570
|
const entry = {
|
|
57220
57571
|
matcher: HERMES_HOOK_MATCHERS.join("|"),
|
|
57221
57572
|
command: `${hookScriptPath} # ${HERMES_KG_HOOK_SENTINEL}`
|
|
@@ -57225,7 +57576,7 @@ function patchHermesConfigForHook(action) {
|
|
|
57225
57576
|
hooks: { ...hooks, pre_tool_call: [...preToolCall, entry] },
|
|
57226
57577
|
hooks_auto_accept: true
|
|
57227
57578
|
};
|
|
57228
|
-
|
|
57579
|
+
fs115.writeFileSync(configPath, yamlStringify4(updated2), "utf-8");
|
|
57229
57580
|
return "patched";
|
|
57230
57581
|
}
|
|
57231
57582
|
const filtered = preToolCall.filter(
|
|
@@ -57236,12 +57587,12 @@ function patchHermesConfigForHook(action) {
|
|
|
57236
57587
|
...config,
|
|
57237
57588
|
hooks: { ...hooks, pre_tool_call: filtered }
|
|
57238
57589
|
};
|
|
57239
|
-
|
|
57590
|
+
fs115.writeFileSync(configPath, yamlStringify4(updated), "utf-8");
|
|
57240
57591
|
return "patched";
|
|
57241
57592
|
}
|
|
57242
57593
|
function doInstallForHermes() {
|
|
57243
57594
|
const configPath = hermesConfigPath2();
|
|
57244
|
-
if (!
|
|
57595
|
+
if (!fs115.existsSync(configPath)) {
|
|
57245
57596
|
printError(`~/.hermes/config.yaml not found at ${configPath}`);
|
|
57246
57597
|
printInfo("remedy", "Install Hermes first, then re-run `olam kg install-hook --for hermes`");
|
|
57247
57598
|
process.exitCode = 1;
|
|
@@ -57269,17 +57620,17 @@ function doInstallForHermes() {
|
|
|
57269
57620
|
function doUninstallForHermes() {
|
|
57270
57621
|
const configPath = hermesConfigPath2();
|
|
57271
57622
|
const hooksDir = hermesHooksDir();
|
|
57272
|
-
const hookScriptPath =
|
|
57623
|
+
const hookScriptPath = path115.join(hooksDir, "kg-first.sh");
|
|
57273
57624
|
let scriptRemoved = false;
|
|
57274
|
-
if (
|
|
57275
|
-
const content =
|
|
57625
|
+
if (fs115.existsSync(hookScriptPath)) {
|
|
57626
|
+
const content = fs115.readFileSync(hookScriptPath, "utf-8");
|
|
57276
57627
|
if (content.includes(HERMES_KG_HOOK_SENTINEL)) {
|
|
57277
|
-
|
|
57628
|
+
fs115.unlinkSync(hookScriptPath);
|
|
57278
57629
|
scriptRemoved = true;
|
|
57279
57630
|
}
|
|
57280
57631
|
}
|
|
57281
57632
|
let configPatched = false;
|
|
57282
|
-
if (
|
|
57633
|
+
if (fs115.existsSync(configPath)) {
|
|
57283
57634
|
const result = patchHermesConfigForHook("uninstall");
|
|
57284
57635
|
configPatched = result === "patched";
|
|
57285
57636
|
}
|
|
@@ -57304,9 +57655,9 @@ function registerKgInstallHookCommand(kg) {
|
|
|
57304
57655
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
57305
57656
|
const filePath = settingsPathFor4(scope);
|
|
57306
57657
|
try {
|
|
57307
|
-
|
|
57658
|
+
fs115.mkdirSync(path115.dirname(filePath), { recursive: true });
|
|
57308
57659
|
} catch (err) {
|
|
57309
|
-
printError(`could not create ${
|
|
57660
|
+
printError(`could not create ${path115.dirname(filePath)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
57310
57661
|
process.exitCode = 1;
|
|
57311
57662
|
return;
|
|
57312
57663
|
}
|
|
@@ -57320,6 +57671,14 @@ function registerKgInstallHookCommand(kg) {
|
|
|
57320
57671
|
entry: buildHookMatcherEntry({ flavor: "host" })
|
|
57321
57672
|
}
|
|
57322
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
|
+
});
|
|
57323
57682
|
switch (result.status) {
|
|
57324
57683
|
case "installed":
|
|
57325
57684
|
printSuccess(`kg-service hook installed (${scope} scope)`);
|
|
@@ -57331,7 +57690,7 @@ function registerKgInstallHookCommand(kg) {
|
|
|
57331
57690
|
printInfo("kg-service hook", `already installed at ${filePath}`);
|
|
57332
57691
|
if (backupPath) {
|
|
57333
57692
|
try {
|
|
57334
|
-
|
|
57693
|
+
fs115.unlinkSync(backupPath);
|
|
57335
57694
|
} catch {
|
|
57336
57695
|
}
|
|
57337
57696
|
}
|
|
@@ -57351,22 +57710,22 @@ function registerKgInstallHookCommand(kg) {
|
|
|
57351
57710
|
// src/commands/kg-uninstall-hook.ts
|
|
57352
57711
|
init_hook_template2();
|
|
57353
57712
|
init_output();
|
|
57354
|
-
import * as
|
|
57355
|
-
import * as
|
|
57356
|
-
import * as
|
|
57713
|
+
import * as fs116 from "node:fs";
|
|
57714
|
+
import * as path116 from "node:path";
|
|
57715
|
+
import * as os62 from "node:os";
|
|
57357
57716
|
function settingsPathFor5(scope) {
|
|
57358
57717
|
if (scope === "user") {
|
|
57359
|
-
return
|
|
57718
|
+
return path116.join(os62.homedir(), ".claude", "settings.json");
|
|
57360
57719
|
}
|
|
57361
|
-
return
|
|
57720
|
+
return path116.join(process.cwd(), ".claude", "settings.json");
|
|
57362
57721
|
}
|
|
57363
|
-
function dropSentinel(matchers) {
|
|
57722
|
+
function dropSentinel(matchers, sentinelPrefix) {
|
|
57364
57723
|
let changed = false;
|
|
57365
57724
|
const out = [];
|
|
57366
57725
|
for (const matcher of matchers) {
|
|
57367
57726
|
const innerHooks = matcher.hooks ?? [];
|
|
57368
57727
|
const keptInner = innerHooks.filter((h) => {
|
|
57369
|
-
if (typeof h.command === "string" && h.command.includes(
|
|
57728
|
+
if (typeof h.command === "string" && h.command.includes(sentinelPrefix)) {
|
|
57370
57729
|
changed = true;
|
|
57371
57730
|
return false;
|
|
57372
57731
|
}
|
|
@@ -57388,13 +57747,13 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
57388
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) => {
|
|
57389
57748
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
57390
57749
|
const filePath = settingsPathFor5(scope);
|
|
57391
|
-
if (!
|
|
57750
|
+
if (!fs116.existsSync(filePath)) {
|
|
57392
57751
|
printInfo("kg-service hook", `no settings.json at ${filePath} \u2014 nothing to remove`);
|
|
57393
57752
|
return;
|
|
57394
57753
|
}
|
|
57395
57754
|
let settings;
|
|
57396
57755
|
try {
|
|
57397
|
-
const raw =
|
|
57756
|
+
const raw = fs116.readFileSync(filePath, "utf-8");
|
|
57398
57757
|
settings = raw.trim() ? JSON.parse(raw) : {};
|
|
57399
57758
|
} catch (err) {
|
|
57400
57759
|
printError(`could not parse ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -57402,38 +57761,36 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
57402
57761
|
return;
|
|
57403
57762
|
}
|
|
57404
57763
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
57405
|
-
|
|
57406
|
-
|
|
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`);
|
|
57407
57769
|
return;
|
|
57408
57770
|
}
|
|
57409
|
-
const { matchers, changed }
|
|
57410
|
-
|
|
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) {
|
|
57411
57774
|
printInfo("kg-service hook", `not found in ${filePath} \u2014 already uninstalled`);
|
|
57412
57775
|
return;
|
|
57413
57776
|
}
|
|
57414
57777
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
57415
57778
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
57416
57779
|
try {
|
|
57417
|
-
|
|
57780
|
+
fs116.copyFileSync(filePath, backupPath);
|
|
57418
57781
|
} catch {
|
|
57419
57782
|
}
|
|
57420
|
-
const
|
|
57421
|
-
|
|
57422
|
-
|
|
57423
|
-
|
|
57424
|
-
|
|
57425
|
-
|
|
57426
|
-
|
|
57427
|
-
|
|
57428
|
-
const otherStages = Object.keys(next.hooks ?? {}).filter((k) => k !== "PreToolUse");
|
|
57429
|
-
if (otherStages.length === 0) {
|
|
57430
|
-
delete next.hooks;
|
|
57431
|
-
} else {
|
|
57432
|
-
delete next.hooks.PreToolUse;
|
|
57433
|
-
}
|
|
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;
|
|
57434
57791
|
}
|
|
57435
57792
|
try {
|
|
57436
|
-
|
|
57793
|
+
fs116.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
57437
57794
|
printSuccess(`kg-service hook removed from ${filePath}`);
|
|
57438
57795
|
printInfo("backup", backupPath);
|
|
57439
57796
|
} catch (err) {
|
|
@@ -57506,15 +57863,15 @@ function registerKgSavingsCommand(kg) {
|
|
|
57506
57863
|
|
|
57507
57864
|
// src/commands/kg-mirror.ts
|
|
57508
57865
|
init_output();
|
|
57509
|
-
import * as
|
|
57510
|
-
import * as
|
|
57511
|
-
import * as
|
|
57866
|
+
import * as fs117 from "node:fs";
|
|
57867
|
+
import * as os63 from "node:os";
|
|
57868
|
+
import * as path117 from "node:path";
|
|
57512
57869
|
function readEnvOrFile(envVar, fileName) {
|
|
57513
57870
|
const fromEnv = process.env[envVar];
|
|
57514
57871
|
if (fromEnv && fromEnv.length > 0) return fromEnv.trim();
|
|
57515
57872
|
try {
|
|
57516
|
-
const file =
|
|
57517
|
-
const content =
|
|
57873
|
+
const file = path117.join(os63.homedir(), ".olam", fileName);
|
|
57874
|
+
const content = fs117.readFileSync(file, "utf-8").trim();
|
|
57518
57875
|
if (content.length > 0) return content;
|
|
57519
57876
|
} catch {
|
|
57520
57877
|
}
|
|
@@ -57776,14 +58133,14 @@ async function runKgMirrorGraph(symbol, options = {}) {
|
|
|
57776
58133
|
function guessGitUrl(workspace) {
|
|
57777
58134
|
try {
|
|
57778
58135
|
const { spawnSync: spawnSync36 } = __require("node:child_process");
|
|
57779
|
-
const cwd =
|
|
58136
|
+
const cwd = path117.resolve(process.cwd());
|
|
57780
58137
|
const candidates2 = [
|
|
57781
58138
|
cwd,
|
|
57782
|
-
|
|
57783
|
-
|
|
58139
|
+
path117.join(path117.dirname(cwd), workspace),
|
|
58140
|
+
path117.join(os63.homedir(), "Projects", workspace)
|
|
57784
58141
|
];
|
|
57785
58142
|
for (const dir of candidates2) {
|
|
57786
|
-
if (!
|
|
58143
|
+
if (!fs117.existsSync(path117.join(dir, ".git"))) continue;
|
|
57787
58144
|
const r = spawnSync36("git", ["-C", dir, "remote", "get-url", "origin"], {
|
|
57788
58145
|
encoding: "utf-8"
|
|
57789
58146
|
});
|
|
@@ -57821,12 +58178,12 @@ function registerKgMirrorCommand(kg) {
|
|
|
57821
58178
|
// src/commands/kg-connect.ts
|
|
57822
58179
|
init_memory_secret();
|
|
57823
58180
|
init_connect_url();
|
|
57824
|
-
import { existsSync as
|
|
57825
|
-
import { homedir as
|
|
57826
|
-
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";
|
|
57827
58184
|
init_output();
|
|
57828
58185
|
function olamFile(name) {
|
|
57829
|
-
return
|
|
58186
|
+
return join134(homedir80(), ".olam", name);
|
|
57830
58187
|
}
|
|
57831
58188
|
function safeUrl3(url2) {
|
|
57832
58189
|
try {
|
|
@@ -57847,7 +58204,7 @@ function registerKgConnectCommand(kg) {
|
|
|
57847
58204
|
return;
|
|
57848
58205
|
}
|
|
57849
58206
|
const urlPath = olamFile("kg-proxy-url");
|
|
57850
|
-
const previous =
|
|
58207
|
+
const previous = existsSync130(urlPath) ? readFileSync116(urlPath, "utf8").trim() : "";
|
|
57851
58208
|
writeSecretAtPath(urlPath, classifierUrl);
|
|
57852
58209
|
if (opts.bearer) writeSecretAtPath(olamFile("kg-proxy-bearer"), opts.bearer);
|
|
57853
58210
|
if (opts.builderUrl) {
|
|
@@ -57882,8 +58239,8 @@ function registerKgConnectCommand(kg) {
|
|
|
57882
58239
|
|
|
57883
58240
|
// src/commands/kg-build.ts
|
|
57884
58241
|
function readQueueFromDisk(queuePath) {
|
|
57885
|
-
if (!
|
|
57886
|
-
const raw =
|
|
58242
|
+
if (!fs118.existsSync(queuePath)) return [];
|
|
58243
|
+
const raw = fs118.readFileSync(queuePath, "utf-8");
|
|
57887
58244
|
const entries = [];
|
|
57888
58245
|
for (const line of raw.split("\n")) {
|
|
57889
58246
|
const t = line.trim();
|
|
@@ -57896,14 +58253,14 @@ function readQueueFromDisk(queuePath) {
|
|
|
57896
58253
|
return entries;
|
|
57897
58254
|
}
|
|
57898
58255
|
function writeQueueToDisk(queuePath, entries) {
|
|
57899
|
-
|
|
58256
|
+
fs118.mkdirSync(path118.dirname(queuePath), { recursive: true });
|
|
57900
58257
|
const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
|
|
57901
|
-
|
|
58258
|
+
fs118.writeFileSync(queuePath, content, "utf-8");
|
|
57902
58259
|
}
|
|
57903
58260
|
async function runKgBuildPending(opts = {}) {
|
|
57904
58261
|
const queuePath = opts.queuePath ?? (() => {
|
|
57905
|
-
const stateDir2 = process.env["OLAM_STATE_DIR"] ??
|
|
57906
|
-
return
|
|
58262
|
+
const stateDir2 = process.env["OLAM_STATE_DIR"] ?? path118.join(os64.homedir(), ".olam", "state");
|
|
58263
|
+
return path118.join(stateDir2, "kg-pending.jsonl");
|
|
57907
58264
|
})();
|
|
57908
58265
|
const readQueue2 = opts.readQueueFn ?? readQueueFromDisk;
|
|
57909
58266
|
const writeQueue2 = opts.writeQueueFn ?? writeQueueToDisk;
|
|
@@ -57919,7 +58276,7 @@ async function runKgBuildPending(opts = {}) {
|
|
|
57919
58276
|
const remaining = [];
|
|
57920
58277
|
for (const entry of deduped) {
|
|
57921
58278
|
const repoPath = entry.path;
|
|
57922
|
-
const workspaceName =
|
|
58279
|
+
const workspaceName = path118.basename(repoPath).toLowerCase();
|
|
57923
58280
|
printInfo("kg build --pending", `building ${repoPath} (workspace=${workspaceName})`);
|
|
57924
58281
|
let containerPath;
|
|
57925
58282
|
try {
|
|
@@ -57957,20 +58314,20 @@ async function runKgBuildPending(opts = {}) {
|
|
|
57957
58314
|
}
|
|
57958
58315
|
function resolveWorkspace(arg) {
|
|
57959
58316
|
const cwd = process.cwd();
|
|
57960
|
-
const name = arg ??
|
|
58317
|
+
const name = arg ?? path118.basename(cwd).toLowerCase();
|
|
57961
58318
|
validateWorkspaceName(name);
|
|
57962
58319
|
return { name, sourcePath: cwd };
|
|
57963
58320
|
}
|
|
57964
58321
|
function toContainerPath(hostPath) {
|
|
57965
|
-
const home =
|
|
57966
|
-
const resolved =
|
|
57967
|
-
if (!resolved.startsWith(home +
|
|
58322
|
+
const home = os64.homedir();
|
|
58323
|
+
const resolved = path118.resolve(hostPath);
|
|
58324
|
+
if (!resolved.startsWith(home + path118.sep) && resolved !== home) {
|
|
57968
58325
|
throw new Error(
|
|
57969
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.`
|
|
57970
58327
|
);
|
|
57971
58328
|
}
|
|
57972
|
-
const rel =
|
|
57973
|
-
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("/"));
|
|
57974
58331
|
}
|
|
57975
58332
|
async function runKgBuild(workspaceArg, options = {}) {
|
|
57976
58333
|
let workspace;
|
|
@@ -57988,7 +58345,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
57988
58345
|
return { exitCode: 2 };
|
|
57989
58346
|
}
|
|
57990
58347
|
const outDir = kgPristinePath(workspace.name);
|
|
57991
|
-
|
|
58348
|
+
fs118.mkdirSync(outDir, { recursive: true });
|
|
57992
58349
|
const human = !options.json;
|
|
57993
58350
|
if (human) {
|
|
57994
58351
|
printInfo("kg build", `workspace=${workspace.name} source=${workspace.sourcePath}`);
|
|
@@ -58021,12 +58378,12 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
58021
58378
|
workspace: workspace.name,
|
|
58022
58379
|
graphify_path: "container"
|
|
58023
58380
|
};
|
|
58024
|
-
|
|
58025
|
-
|
|
58381
|
+
fs118.writeFileSync(
|
|
58382
|
+
path118.join(outDir, "freshness.json"),
|
|
58026
58383
|
JSON.stringify(freshness, null, 2) + "\n",
|
|
58027
58384
|
"utf-8"
|
|
58028
58385
|
);
|
|
58029
|
-
const finalOut =
|
|
58386
|
+
const finalOut = path118.join(outDir, "graphify-out");
|
|
58030
58387
|
if (options.json) {
|
|
58031
58388
|
process.stdout.write(JSON.stringify(freshness) + "\n");
|
|
58032
58389
|
} else {
|
|
@@ -58070,12 +58427,12 @@ function registerKg(program2) {
|
|
|
58070
58427
|
// src/commands/flywheel/emit-breadcrumb.ts
|
|
58071
58428
|
init_file_lock();
|
|
58072
58429
|
import { mkdirSync as mkdirSync77, appendFileSync as appendFileSync6 } from "node:fs";
|
|
58073
|
-
import { homedir as
|
|
58074
|
-
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";
|
|
58075
58432
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
58076
58433
|
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info", "warn"]);
|
|
58077
58434
|
var PROMPT_FEEDING_FIELDS = ["extracted_pattern", "severity", "affected_persona", "proposed_edit"];
|
|
58078
|
-
var BREADCRUMBS_BASE =
|
|
58435
|
+
var BREADCRUMBS_BASE = join136(homedir82(), ".local", "share", "claude", "breadcrumbs");
|
|
58079
58436
|
var LOCK_FILENAME = ".flywheel-emit.lock";
|
|
58080
58437
|
function buildRecord(opts) {
|
|
58081
58438
|
const rec = {
|
|
@@ -58122,7 +58479,7 @@ function validatePromptFeeding(rec) {
|
|
|
58122
58479
|
}
|
|
58123
58480
|
function destPath(projectSlug) {
|
|
58124
58481
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
58125
|
-
return
|
|
58482
|
+
return join136(BREADCRUMBS_BASE, projectSlug, `${today}.jsonl`);
|
|
58126
58483
|
}
|
|
58127
58484
|
async function emitBreadcrumb(opts) {
|
|
58128
58485
|
if (!VALID_SEVERITIES.has(opts.severity)) {
|
|
@@ -58141,14 +58498,14 @@ async function emitBreadcrumb(opts) {
|
|
|
58141
58498
|
);
|
|
58142
58499
|
process.exit(2);
|
|
58143
58500
|
}
|
|
58144
|
-
const
|
|
58145
|
-
const lockDir = dirname74(
|
|
58501
|
+
const path122 = destPath(rec.project_slug);
|
|
58502
|
+
const lockDir = dirname74(path122);
|
|
58146
58503
|
mkdirSync77(lockDir, { recursive: true });
|
|
58147
58504
|
const line = JSON.stringify(rec) + "\n";
|
|
58148
58505
|
await withFileLock(
|
|
58149
58506
|
lockDir,
|
|
58150
58507
|
() => {
|
|
58151
|
-
appendFileSync6(
|
|
58508
|
+
appendFileSync6(path122, line, "utf8");
|
|
58152
58509
|
},
|
|
58153
58510
|
{
|
|
58154
58511
|
lockFilename: LOCK_FILENAME,
|
|
@@ -58164,7 +58521,7 @@ async function emitBreadcrumb(opts) {
|
|
|
58164
58521
|
acquireTimeoutMs: 2e4
|
|
58165
58522
|
}
|
|
58166
58523
|
);
|
|
58167
|
-
process.stdout.write(`[K7-emit] ${
|
|
58524
|
+
process.stdout.write(`[K7-emit] ${path122}: ${rec.extracted_pattern} (${rec.severity})
|
|
58168
58525
|
`);
|
|
58169
58526
|
}
|
|
58170
58527
|
function registerFlywheelEmitBreadcrumb(parent) {
|
|
@@ -58229,7 +58586,7 @@ function registerFlywheelK5Score(parent) {
|
|
|
58229
58586
|
}
|
|
58230
58587
|
|
|
58231
58588
|
// src/commands/flywheel/k5-validate.ts
|
|
58232
|
-
import { readFileSync as
|
|
58589
|
+
import { readFileSync as readFileSync118, statSync as statSync33 } from "node:fs";
|
|
58233
58590
|
import { parse as parseYAML } from "yaml";
|
|
58234
58591
|
var K5_DIMS = ["direction", "approach", "open_questions", "constraints", "reuse"];
|
|
58235
58592
|
var MAX_PLAN_BYTES = 1048576;
|
|
@@ -58287,9 +58644,9 @@ function validateK5ScoredAt(scoredAt) {
|
|
|
58287
58644
|
}
|
|
58288
58645
|
return null;
|
|
58289
58646
|
}
|
|
58290
|
-
function validatePlan(
|
|
58647
|
+
function validatePlan(path122) {
|
|
58291
58648
|
const emptyJson = (status2, errors2) => ({
|
|
58292
|
-
path:
|
|
58649
|
+
path: path122,
|
|
58293
58650
|
status: status2,
|
|
58294
58651
|
errors: errors2,
|
|
58295
58652
|
k5_scores: null,
|
|
@@ -58300,33 +58657,33 @@ function validatePlan(path121) {
|
|
|
58300
58657
|
});
|
|
58301
58658
|
let stat;
|
|
58302
58659
|
try {
|
|
58303
|
-
stat = statSync33(
|
|
58660
|
+
stat = statSync33(path122);
|
|
58304
58661
|
} catch (err) {
|
|
58305
|
-
const m = `FAIL cannot stat ${
|
|
58662
|
+
const m = `FAIL cannot stat ${path122}: ${err instanceof Error ? err.message : "unknown"}`;
|
|
58306
58663
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58307
58664
|
}
|
|
58308
58665
|
if (stat.size > MAX_PLAN_BYTES) {
|
|
58309
|
-
const m = `FAIL ${
|
|
58666
|
+
const m = `FAIL ${path122}: plan file exceeds 1MB (${stat.size} bytes); refusing to parse`;
|
|
58310
58667
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58311
58668
|
}
|
|
58312
58669
|
let text;
|
|
58313
58670
|
try {
|
|
58314
|
-
text =
|
|
58671
|
+
text = readFileSync118(path122, "utf8");
|
|
58315
58672
|
} catch (err) {
|
|
58316
|
-
const m = `FAIL cannot read ${
|
|
58673
|
+
const m = `FAIL cannot read ${path122}: ${err instanceof Error ? err.message : "unknown"}`;
|
|
58317
58674
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58318
58675
|
}
|
|
58319
58676
|
if (!text.replace(/^/, "").startsWith("---")) {
|
|
58320
|
-
const m = `FAIL ${
|
|
58677
|
+
const m = `FAIL ${path122}: no YAML frontmatter (missing opening --- marker)`;
|
|
58321
58678
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58322
58679
|
}
|
|
58323
58680
|
if (!text.includes("\n---", 3)) {
|
|
58324
|
-
const m = `FAIL ${
|
|
58681
|
+
const m = `FAIL ${path122}: frontmatter block never closed (missing closing --- marker)`;
|
|
58325
58682
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58326
58683
|
}
|
|
58327
58684
|
const fm = extractFrontmatter(text);
|
|
58328
58685
|
if (fm === null) {
|
|
58329
|
-
const m = `FAIL ${
|
|
58686
|
+
const m = `FAIL ${path122}: frontmatter could not be parsed as YAML`;
|
|
58330
58687
|
return { ok: false, message: m, json: emptyJson("error", [m]) };
|
|
58331
58688
|
}
|
|
58332
58689
|
const hasScores = "k5_scores" in fm;
|
|
@@ -58336,7 +58693,7 @@ function validatePlan(path121) {
|
|
|
58336
58693
|
if (!hasScores && !hasBoost && !hasComposite && !hasScoredAt) {
|
|
58337
58694
|
return {
|
|
58338
58695
|
ok: true,
|
|
58339
|
-
message: `PASS ${
|
|
58696
|
+
message: `PASS ${path122}: k5_scores absent (acceptable \u2014 legacy plan)`,
|
|
58340
58697
|
json: emptyJson("absent", [])
|
|
58341
58698
|
};
|
|
58342
58699
|
}
|
|
@@ -58360,12 +58717,12 @@ function validatePlan(path121) {
|
|
|
58360
58717
|
if (errors.length > 0) {
|
|
58361
58718
|
return {
|
|
58362
58719
|
ok: false,
|
|
58363
|
-
message: `FAIL ${
|
|
58720
|
+
message: `FAIL ${path122}: ${errors.join("; ")}`,
|
|
58364
58721
|
json: emptyJson("fail", errors)
|
|
58365
58722
|
};
|
|
58366
58723
|
}
|
|
58367
58724
|
const json = emptyJson("pass", []);
|
|
58368
|
-
const lines = [`PASS ${
|
|
58725
|
+
const lines = [`PASS ${path122}: k5_scores valid`];
|
|
58369
58726
|
if (hasScores && typeof fm.k5_scores === "object" && fm.k5_scores !== null) {
|
|
58370
58727
|
const scoresObj = fm.k5_scores;
|
|
58371
58728
|
const parsed = {};
|
|
@@ -58435,7 +58792,7 @@ function registerFlywheelK5Validate(parent) {
|
|
|
58435
58792
|
}
|
|
58436
58793
|
|
|
58437
58794
|
// src/commands/flywheel/k10-measure.ts
|
|
58438
|
-
import { readFileSync as
|
|
58795
|
+
import { readFileSync as readFileSync119 } from "node:fs";
|
|
58439
58796
|
|
|
58440
58797
|
// ../core/dist/lib/k10-budget.js
|
|
58441
58798
|
var K10_TOKEN_CAP = 5500;
|
|
@@ -58492,7 +58849,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
58492
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) => {
|
|
58493
58850
|
let upstreamText;
|
|
58494
58851
|
try {
|
|
58495
|
-
upstreamText =
|
|
58852
|
+
upstreamText = readFileSync119(opts.upstream, "utf8");
|
|
58496
58853
|
} catch (err) {
|
|
58497
58854
|
process.stderr.write(
|
|
58498
58855
|
`[k10-measure-error] cannot read upstream ${opts.upstream}: ${err instanceof Error ? err.message : "unknown"}
|
|
@@ -58504,7 +58861,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
58504
58861
|
let overlayTokens = null;
|
|
58505
58862
|
if (opts.overlay !== void 0) {
|
|
58506
58863
|
try {
|
|
58507
|
-
const overlayText =
|
|
58864
|
+
const overlayText = readFileSync119(opts.overlay, "utf8");
|
|
58508
58865
|
overlayTokens = tokensFromText(overlayText);
|
|
58509
58866
|
} catch (err) {
|
|
58510
58867
|
process.stderr.write(
|
|
@@ -58538,13 +58895,13 @@ function registerFlywheelK10Measure(parent) {
|
|
|
58538
58895
|
}
|
|
58539
58896
|
|
|
58540
58897
|
// src/commands/flywheel/check-persona-skeleton.ts
|
|
58541
|
-
import { existsSync as
|
|
58542
|
-
import { homedir as
|
|
58543
|
-
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";
|
|
58544
58901
|
import { parse as parseYAML2 } from "yaml";
|
|
58545
58902
|
var CHARS_PER_TOKEN3 = 4;
|
|
58546
58903
|
var K10_TOKEN_CAP2 = 6e3;
|
|
58547
|
-
var AGENTS_DIR =
|
|
58904
|
+
var AGENTS_DIR = join137(homedir83(), ".claude", "agents");
|
|
58548
58905
|
var REQUIRED_FRONTMATTER_KEYS = ["name", "description", "allowed-tools"];
|
|
58549
58906
|
var REQUIRED_SECTIONS = [
|
|
58550
58907
|
"## Role",
|
|
@@ -58584,10 +58941,10 @@ function countNamedPatterns(sectionText) {
|
|
|
58584
58941
|
return Math.max(h3Count, bulletCount);
|
|
58585
58942
|
}
|
|
58586
58943
|
function checkFile(filepath) {
|
|
58587
|
-
if (!
|
|
58944
|
+
if (!existsSync132(filepath) || !statSync34(filepath).isFile()) {
|
|
58588
58945
|
return { passed: false, failures: [`file not found: ${filepath}`], tokens: 0, mergedSkipped: false };
|
|
58589
58946
|
}
|
|
58590
|
-
const text =
|
|
58947
|
+
const text = readFileSync120(filepath, "utf8");
|
|
58591
58948
|
const { fm, body } = parseFile(text);
|
|
58592
58949
|
const failures = [];
|
|
58593
58950
|
for (const key of REQUIRED_FRONTMATTER_KEYS) {
|
|
@@ -58600,8 +58957,8 @@ function checkFile(filepath) {
|
|
|
58600
58957
|
const agentName = typeof fm.name === "string" ? fm.name : "";
|
|
58601
58958
|
let mergedSkipped = false;
|
|
58602
58959
|
if (!isNewAgent && agentName !== "") {
|
|
58603
|
-
const upstreamPath =
|
|
58604
|
-
if (
|
|
58960
|
+
const upstreamPath = join137(AGENTS_DIR, `${agentName}.md`);
|
|
58961
|
+
if (existsSync132(upstreamPath)) {
|
|
58605
58962
|
mergedSkipped = true;
|
|
58606
58963
|
}
|
|
58607
58964
|
}
|
|
@@ -58653,7 +59010,7 @@ Results: ${passCount} passed, ${failCount} failed
|
|
|
58653
59010
|
}
|
|
58654
59011
|
|
|
58655
59012
|
// src/commands/flywheel/diversity-check.ts
|
|
58656
|
-
import { readFileSync as
|
|
59013
|
+
import { readFileSync as readFileSync121 } from "node:fs";
|
|
58657
59014
|
import { basename as basename15 } from "node:path";
|
|
58658
59015
|
import { globSync as globSync2 } from "node:fs";
|
|
58659
59016
|
|
|
@@ -58763,7 +59120,7 @@ function registerFlywheelDiversityCheck(parent) {
|
|
|
58763
59120
|
const personas = /* @__PURE__ */ new Map();
|
|
58764
59121
|
for (const filepath of files) {
|
|
58765
59122
|
try {
|
|
58766
|
-
const body =
|
|
59123
|
+
const body = readFileSync121(filepath, "utf8");
|
|
58767
59124
|
if (body.trim().length > 0) {
|
|
58768
59125
|
personas.set(basename15(filepath, ".md"), body);
|
|
58769
59126
|
}
|
|
@@ -58794,9 +59151,9 @@ ${formatRedivergencePrompt(persona_a, persona_b, score, void 0, void 0, threshol
|
|
|
58794
59151
|
}
|
|
58795
59152
|
|
|
58796
59153
|
// src/commands/flywheel/ping.ts
|
|
58797
|
-
import { mkdirSync as mkdirSync78, writeFileSync as
|
|
58798
|
-
import { homedir as
|
|
58799
|
-
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";
|
|
58800
59157
|
var COLD_START_BUDGET_GOOD_MS = 200;
|
|
58801
59158
|
var COLD_START_BUDGET_FAIR_MS = 500;
|
|
58802
59159
|
function classifyColdStart(coldStartMs) {
|
|
@@ -58812,9 +59169,9 @@ function readOlamVersion() {
|
|
|
58812
59169
|
}
|
|
58813
59170
|
}
|
|
58814
59171
|
function writeBaseline(record) {
|
|
58815
|
-
const baselinePath =
|
|
59172
|
+
const baselinePath = join138(homedir84(), ".local", "share", "olam", "flywheel-baseline.json");
|
|
58816
59173
|
mkdirSync78(dirname75(baselinePath), { recursive: true });
|
|
58817
|
-
|
|
59174
|
+
writeFileSync74(baselinePath, JSON.stringify(record, null, 2) + "\n", "utf8");
|
|
58818
59175
|
return baselinePath;
|
|
58819
59176
|
}
|
|
58820
59177
|
function registerFlywheelPing(parent) {
|
|
@@ -58849,30 +59206,30 @@ function registerFlywheelPing(parent) {
|
|
|
58849
59206
|
}
|
|
58850
59207
|
|
|
58851
59208
|
// src/commands/flywheel/session-start.ts
|
|
58852
|
-
import { readFileSync as
|
|
58853
|
-
import { homedir as
|
|
58854
|
-
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";
|
|
58855
59212
|
var SESSIONSTART_HOOK_SENTINEL = "olam-sessionstart-context-hook-v1";
|
|
58856
59213
|
var MAX_WAKE_BRIEF_BYTES = 8 * 1024;
|
|
58857
59214
|
var MAX_ACTIVE_WORLD_BYTES = 4 * 1024;
|
|
58858
59215
|
var MAX_CONFIG_BYTES = 8 * 1024;
|
|
58859
|
-
function tryReadCapped(
|
|
59216
|
+
function tryReadCapped(path122, maxBytes) {
|
|
58860
59217
|
try {
|
|
58861
|
-
const stat = statSync35(
|
|
59218
|
+
const stat = statSync35(path122);
|
|
58862
59219
|
if (!stat.isFile() || stat.size === 0) return null;
|
|
58863
59220
|
if (stat.size > maxBytes) {
|
|
58864
59221
|
process.stderr.write(
|
|
58865
|
-
`[${SESSIONSTART_HOOK_SENTINEL}] skipping ${
|
|
59222
|
+
`[${SESSIONSTART_HOOK_SENTINEL}] skipping ${path122}: ${stat.size} bytes > ${maxBytes} cap
|
|
58866
59223
|
`
|
|
58867
59224
|
);
|
|
58868
59225
|
return null;
|
|
58869
59226
|
}
|
|
58870
|
-
return
|
|
59227
|
+
return readFileSync122(path122, "utf-8");
|
|
58871
59228
|
} catch (err) {
|
|
58872
59229
|
const code = err?.code;
|
|
58873
59230
|
if (code === "ENOENT") return null;
|
|
58874
59231
|
process.stderr.write(
|
|
58875
|
-
`[${SESSIONSTART_HOOK_SENTINEL}] read failed for ${
|
|
59232
|
+
`[${SESSIONSTART_HOOK_SENTINEL}] read failed for ${path122}: ${err?.message ?? err}
|
|
58876
59233
|
`
|
|
58877
59234
|
);
|
|
58878
59235
|
return null;
|
|
@@ -58892,15 +59249,15 @@ function tryParseJson(raw, label) {
|
|
|
58892
59249
|
}
|
|
58893
59250
|
function buildContextBlock(olamHome7) {
|
|
58894
59251
|
const config = tryParseJson(
|
|
58895
|
-
tryReadCapped(
|
|
59252
|
+
tryReadCapped(join139(olamHome7, "config.json"), MAX_CONFIG_BYTES),
|
|
58896
59253
|
"config.json"
|
|
58897
59254
|
);
|
|
58898
59255
|
const activeWorld = tryParseJson(
|
|
58899
|
-
tryReadCapped(
|
|
59256
|
+
tryReadCapped(join139(olamHome7, "state", "active-world.json"), MAX_ACTIVE_WORLD_BYTES),
|
|
58900
59257
|
"active-world.json"
|
|
58901
59258
|
);
|
|
58902
59259
|
const wakeBrief = tryReadCapped(
|
|
58903
|
-
|
|
59260
|
+
join139(olamHome7, "state", "wake-brief.md"),
|
|
58904
59261
|
MAX_WAKE_BRIEF_BYTES
|
|
58905
59262
|
);
|
|
58906
59263
|
const sections = [];
|
|
@@ -58952,7 +59309,7 @@ function registerFlywheelSessionStart(parent) {
|
|
|
58952
59309
|
parent.command("session-start").description(
|
|
58953
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."
|
|
58954
59311
|
).action(() => {
|
|
58955
|
-
const olamHome7 = process.env.OLAM_HOME ??
|
|
59312
|
+
const olamHome7 = process.env.OLAM_HOME ?? join139(homedir85(), ".olam");
|
|
58956
59313
|
emitSessionStartContext(olamHome7);
|
|
58957
59314
|
process.exit(0);
|
|
58958
59315
|
});
|
|
@@ -58961,9 +59318,9 @@ function registerFlywheelSessionStart(parent) {
|
|
|
58961
59318
|
// src/commands/flywheel/install-sessionstart-hook.ts
|
|
58962
59319
|
init_merge_settings();
|
|
58963
59320
|
init_output();
|
|
58964
|
-
import { existsSync as
|
|
58965
|
-
import { homedir as
|
|
58966
|
-
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";
|
|
58967
59324
|
var SESSIONSTART_HOOK_STAGE = "SessionStart";
|
|
58968
59325
|
var SESSIONSTART_HOOK_TIMEOUT_MS = 5e3;
|
|
58969
59326
|
var NOOP_GUARD = "command -v olam >/dev/null 2>&1 || exit 0;";
|
|
@@ -58980,11 +59337,11 @@ function buildSessionStartHookEntry() {
|
|
|
58980
59337
|
};
|
|
58981
59338
|
}
|
|
58982
59339
|
function settingsPathFor6(scope, cwd) {
|
|
58983
|
-
if (scope === "user") return
|
|
58984
|
-
return
|
|
59340
|
+
if (scope === "user") return join140(homedir86(), ".claude", "settings.json");
|
|
59341
|
+
return join140(cwd ?? process.cwd(), ".claude", "settings.json");
|
|
58985
59342
|
}
|
|
58986
59343
|
function backup4(filePath) {
|
|
58987
|
-
if (!
|
|
59344
|
+
if (!existsSync133(filePath)) return null;
|
|
58988
59345
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
58989
59346
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
58990
59347
|
copyFileSync19(filePath, backupPath);
|
|
@@ -59010,8 +59367,8 @@ function installSessionStartHook(filePath) {
|
|
|
59010
59367
|
return { status: result.status, filePath, backupPath };
|
|
59011
59368
|
}
|
|
59012
59369
|
function uninstallSessionStartHook(filePath) {
|
|
59013
|
-
if (!
|
|
59014
|
-
const raw =
|
|
59370
|
+
if (!existsSync133(filePath)) return { status: "no-settings", filePath };
|
|
59371
|
+
const raw = readFileSync123(filePath, "utf-8");
|
|
59015
59372
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
59016
59373
|
const matchers = settings.hooks?.SessionStart;
|
|
59017
59374
|
if (!Array.isArray(matchers) || matchers.length === 0) {
|
|
@@ -59051,7 +59408,7 @@ function uninstallSessionStartHook(filePath) {
|
|
|
59051
59408
|
delete next.hooks.SessionStart;
|
|
59052
59409
|
}
|
|
59053
59410
|
}
|
|
59054
|
-
|
|
59411
|
+
writeFileSync75(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
59055
59412
|
return { status: "removed", filePath };
|
|
59056
59413
|
}
|
|
59057
59414
|
function registerFlywheelInstallSessionStartHook(parent) {
|
|
@@ -59379,14 +59736,14 @@ init_manager();
|
|
|
59379
59736
|
init_context();
|
|
59380
59737
|
init_output();
|
|
59381
59738
|
import { spawnSync as defaultSpawnSync } from "node:child_process";
|
|
59382
|
-
import * as
|
|
59383
|
-
import * as
|
|
59384
|
-
import * as
|
|
59739
|
+
import * as fs119 from "node:fs";
|
|
59740
|
+
import * as os65 from "node:os";
|
|
59741
|
+
import * as path119 from "node:path";
|
|
59385
59742
|
function devboxContainerName(worldId) {
|
|
59386
59743
|
return `olam-${worldId}-devbox`;
|
|
59387
59744
|
}
|
|
59388
59745
|
function olamHomeDir() {
|
|
59389
|
-
return process.env["OLAM_HOME"] ??
|
|
59746
|
+
return process.env["OLAM_HOME"] ?? path119.join(os65.homedir(), ".olam");
|
|
59390
59747
|
}
|
|
59391
59748
|
function defaultRestartContainer(name, spawn14 = defaultSpawnSync) {
|
|
59392
59749
|
const r = spawn14("docker", ["restart", "--time", "30", name], {
|
|
@@ -59399,8 +59756,8 @@ function defaultRestartContainer(name, spawn14 = defaultSpawnSync) {
|
|
|
59399
59756
|
};
|
|
59400
59757
|
}
|
|
59401
59758
|
function defaultAppendAuditLog(homeDir, line) {
|
|
59402
|
-
|
|
59403
|
-
|
|
59759
|
+
fs119.mkdirSync(homeDir, { recursive: true });
|
|
59760
|
+
fs119.appendFileSync(path119.join(homeDir, "usage.log"), line.endsWith("\n") ? line : line + "\n", {
|
|
59404
59761
|
encoding: "utf-8"
|
|
59405
59762
|
});
|
|
59406
59763
|
}
|
|
@@ -59445,19 +59802,19 @@ async function doRekey(worldId, deps) {
|
|
|
59445
59802
|
);
|
|
59446
59803
|
const rotatedAt = deps.now().toISOString();
|
|
59447
59804
|
const homeDir = deps.olamHomeDir();
|
|
59448
|
-
const worldDir =
|
|
59449
|
-
|
|
59450
|
-
const credentialsPath =
|
|
59805
|
+
const worldDir = path119.join(homeDir, "worlds", worldId);
|
|
59806
|
+
fs119.mkdirSync(worldDir, { recursive: true });
|
|
59807
|
+
const credentialsPath = path119.join(worldDir, "credentials.json");
|
|
59451
59808
|
const payload = {
|
|
59452
59809
|
worldRoleName,
|
|
59453
59810
|
password,
|
|
59454
59811
|
rotatedAt
|
|
59455
59812
|
};
|
|
59456
|
-
|
|
59813
|
+
fs119.writeFileSync(credentialsPath, JSON.stringify(payload, null, 2) + "\n", {
|
|
59457
59814
|
encoding: "utf-8",
|
|
59458
59815
|
mode: 384
|
|
59459
59816
|
});
|
|
59460
|
-
|
|
59817
|
+
fs119.chmodSync(credentialsPath, 384);
|
|
59461
59818
|
const restart = deps.restartContainer(devboxContainerName(worldId));
|
|
59462
59819
|
deps.appendAuditLog(`${rotatedAt} ${worldId} rekey`);
|
|
59463
59820
|
if (!restart.ok) {
|
|
@@ -59523,9 +59880,9 @@ function registerRekey(program2) {
|
|
|
59523
59880
|
// src/commands/yolo.ts
|
|
59524
59881
|
init_output();
|
|
59525
59882
|
import * as childProcess2 from "node:child_process";
|
|
59526
|
-
import * as
|
|
59527
|
-
import * as
|
|
59528
|
-
import * as
|
|
59883
|
+
import * as fs120 from "node:fs";
|
|
59884
|
+
import * as os66 from "node:os";
|
|
59885
|
+
import * as path120 from "node:path";
|
|
59529
59886
|
import pc51 from "picocolors";
|
|
59530
59887
|
var YOLO_BOOT_DELAY_MS = 8e3;
|
|
59531
59888
|
var CAPTURE_DELAY_MS = 4e3;
|
|
@@ -59553,7 +59910,7 @@ function defaultSleeper(ms) {
|
|
|
59553
59910
|
function detectTmuxBinary(runner = defaultRunner) {
|
|
59554
59911
|
for (const p of TMUX_PROBE_PATHS) {
|
|
59555
59912
|
if (TMUX_SHIM_MARKERS.some((m) => p.includes(m))) continue;
|
|
59556
|
-
if (
|
|
59913
|
+
if (fs120.existsSync(p)) return p;
|
|
59557
59914
|
}
|
|
59558
59915
|
const result = runner("which", ["tmux"]);
|
|
59559
59916
|
if (result.status === 0 && result.stdout) {
|
|
@@ -59567,17 +59924,17 @@ function resolveWorktreeRoot(runner = defaultRunner, cwd = process.cwd()) {
|
|
|
59567
59924
|
if (process.env["OLAM_TMUX_YOLO_ROOT"]) {
|
|
59568
59925
|
return process.env["OLAM_TMUX_YOLO_ROOT"];
|
|
59569
59926
|
}
|
|
59570
|
-
const rootFile =
|
|
59571
|
-
if (
|
|
59572
|
-
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();
|
|
59573
59930
|
if (line) return line;
|
|
59574
59931
|
}
|
|
59575
59932
|
const gitResult = runner("git", ["rev-parse", "--show-toplevel"], { cwd });
|
|
59576
59933
|
if (gitResult.status !== 0 || !gitResult.stdout) {
|
|
59577
|
-
return
|
|
59934
|
+
return path120.join(cwd, "..", path120.basename(cwd) + "-wt");
|
|
59578
59935
|
}
|
|
59579
59936
|
const repoRoot = gitResult.stdout.trim();
|
|
59580
|
-
return
|
|
59937
|
+
return path120.join(path120.dirname(repoRoot), path120.basename(repoRoot) + "-wt");
|
|
59581
59938
|
}
|
|
59582
59939
|
function resolveYoloCommand(runner = defaultRunner) {
|
|
59583
59940
|
const result = runner("bash", ["-lc", "command -v yolo"]);
|
|
@@ -59603,7 +59960,7 @@ async function spawnYolo(opts) {
|
|
|
59603
59960
|
);
|
|
59604
59961
|
}
|
|
59605
59962
|
try {
|
|
59606
|
-
|
|
59963
|
+
fs120.accessSync(opts.promptFile, fs120.constants.R_OK);
|
|
59607
59964
|
} catch {
|
|
59608
59965
|
throw new Error(
|
|
59609
59966
|
`Prompt file not found or not readable: ${opts.promptFile}
|
|
@@ -59611,7 +59968,7 @@ Create the file with your task description and try again.`
|
|
|
59611
59968
|
);
|
|
59612
59969
|
}
|
|
59613
59970
|
const worktreeRoot = resolveWorktreeRoot(runner, cwd);
|
|
59614
|
-
const worktreePath =
|
|
59971
|
+
const worktreePath = path120.join(worktreeRoot, opts.name);
|
|
59615
59972
|
const branchCheck = runner("git", ["show-ref", "--verify", "--quiet", `refs/heads/${opts.branch}`], { cwd });
|
|
59616
59973
|
if (branchCheck.status === 0) {
|
|
59617
59974
|
throw new Error(
|
|
@@ -59619,7 +59976,7 @@ Create the file with your task description and try again.`
|
|
|
59619
59976
|
Run: olam yolo --cleanup ${opts.name} (or use --force to bypass the merged check)`
|
|
59620
59977
|
);
|
|
59621
59978
|
}
|
|
59622
|
-
if (
|
|
59979
|
+
if (fs120.existsSync(worktreePath)) {
|
|
59623
59980
|
throw new Error(
|
|
59624
59981
|
`Worktree directory already exists: ${worktreePath}
|
|
59625
59982
|
Run: olam yolo --cleanup ${opts.name} to remove it first.`
|
|
@@ -59684,10 +60041,10 @@ function listYoloWindows(opts = {}) {
|
|
|
59684
60041
|
const windowNames = listResult.stdout.split("\n").map((n) => n.trim()).filter(Boolean);
|
|
59685
60042
|
const worktreeRoot = resolveWorktreeRoot(runner, cwd);
|
|
59686
60043
|
return windowNames.map((name) => {
|
|
59687
|
-
const worktreePath =
|
|
60044
|
+
const worktreePath = path120.join(worktreeRoot, name);
|
|
59688
60045
|
return {
|
|
59689
60046
|
name,
|
|
59690
|
-
worktreePath:
|
|
60047
|
+
worktreePath: fs120.existsSync(worktreePath) ? worktreePath : void 0
|
|
59691
60048
|
};
|
|
59692
60049
|
});
|
|
59693
60050
|
}
|
|
@@ -59696,7 +60053,7 @@ async function cleanupYolo(opts) {
|
|
|
59696
60053
|
const cwd = opts.cwd ?? process.cwd();
|
|
59697
60054
|
const mainBranch = opts.mainBranch ?? "main";
|
|
59698
60055
|
const worktreeRoot = resolveWorktreeRoot(runner, cwd);
|
|
59699
|
-
const worktreePath =
|
|
60056
|
+
const worktreePath = path120.join(worktreeRoot, opts.name);
|
|
59700
60057
|
const worktreeList = runner("git", ["worktree", "list", "--porcelain"], { cwd });
|
|
59701
60058
|
let branch;
|
|
59702
60059
|
if (worktreeList.status === 0) {
|
|
@@ -59821,18 +60178,18 @@ function registerYolo(program2) {
|
|
|
59821
60178
|
}
|
|
59822
60179
|
|
|
59823
60180
|
// src/pleri-config.ts
|
|
59824
|
-
import * as
|
|
59825
|
-
import * as
|
|
60181
|
+
import * as fs121 from "node:fs";
|
|
60182
|
+
import * as path121 from "node:path";
|
|
59826
60183
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
59827
60184
|
if (process.env.PLERI_BASE_URL) {
|
|
59828
60185
|
return true;
|
|
59829
60186
|
}
|
|
59830
|
-
const configPath =
|
|
59831
|
-
if (!
|
|
60187
|
+
const configPath = path121.join(configDir, "config.yaml");
|
|
60188
|
+
if (!fs121.existsSync(configPath)) {
|
|
59832
60189
|
return false;
|
|
59833
60190
|
}
|
|
59834
60191
|
try {
|
|
59835
|
-
const contents =
|
|
60192
|
+
const contents = fs121.readFileSync(configPath, "utf8");
|
|
59836
60193
|
return /^[^#\n]*\bpleri:/m.test(contents);
|
|
59837
60194
|
} catch {
|
|
59838
60195
|
return false;
|
|
@@ -59909,7 +60266,7 @@ var HELP_GROUPS = [
|
|
|
59909
60266
|
// crystallize is conditionally hidden (requires Pleri); kept here so it
|
|
59910
60267
|
// lands in the right group when Pleri IS configured.
|
|
59911
60268
|
title: "Dev tools",
|
|
59912
|
-
names: ["begin", "completion", "crystallize", "hermes", "lanes", "policy-check", "pr", "stop", "yolo"]
|
|
60269
|
+
names: ["begin", "completion", "crystallize", "hermes", "inbox", "lanes", "policy-check", "pr", "stop", "yolo"]
|
|
59913
60270
|
},
|
|
59914
60271
|
{
|
|
59915
60272
|
// Alphabetical within group. `config` lives in 'Cloud setup' above.
|
|
@@ -60131,7 +60488,7 @@ try {
|
|
|
60131
60488
|
}
|
|
60132
60489
|
}
|
|
60133
60490
|
void scheduleUpgradeCheck(cliVersion);
|
|
60134
|
-
if (process.argv.length <= 2 && !
|
|
60491
|
+
if (process.argv.length <= 2 && !existsSync136(join144(homedir89(), ".olam", "config.json"))) {
|
|
60135
60492
|
process.stdout.write("No olam config found yet.\n");
|
|
60136
60493
|
process.stdout.write("Get started: olam setup\n\n");
|
|
60137
60494
|
}
|