@chipschat/hermes 1.0.16 → 1.0.18
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 +10 -3
- package/dist/THIRD-PARTY-NOTICES.md +1 -1
- package/dist/main.js +271 -104
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -152,11 +152,18 @@ point (the one the `hermes` wrapper runs) directly, with the wrapper's variables
|
|
|
152
152
|
`DYLD_LIBRARY_PATH=/opt/homebrew/opt/expat/lib`, which macOS would drop at the wrapper, and its log
|
|
153
153
|
says so.
|
|
154
154
|
|
|
155
|
-
**Folders.** Each agent gets a folder of its own, `~/
|
|
155
|
+
**Folders.** Each agent gets a folder of its own, `~/Chips/Agents/hermes/<its name>`, made the
|
|
156
156
|
first time it is spoken to and kept by its Chips agent after a rename. Each run tells the agent it
|
|
157
157
|
is its folder, in the run's `instructions`. The files an answer sends go to the room from there and
|
|
158
158
|
from nowhere else.
|
|
159
159
|
|
|
160
|
+
Everything the bridge keeps is under `~/Chips` (Chips ADR 0283): its config, sessions and state in
|
|
161
|
+
`~/Chips/.bridges/hermes`, the agents' folders in `~/Chips/Agents/hermes`. Until 1.0.17 they were
|
|
162
|
+
`~/.chips-hermes` and `~/chips-hermes/agents`. The first start of 1.0.17 moves them, and the folder
|
|
163
|
+
paths its sessions saved. It renames and never copies; where something is at the new place already
|
|
164
|
+
it moves in what isn't there yet and says in its log what it left. A file in `~/chips-hermes` it
|
|
165
|
+
didn't make stays there.
|
|
166
|
+
|
|
160
167
|
**Each new agent, a profile of its own.** An agent made in Chips (Add, then a new one, or a
|
|
161
168
|
space from the +) gets a Hermes profile, made by Hermes with
|
|
162
169
|
`hermes profile create <name> --clone-from <the Main agent's> --no-alias`:
|
|
@@ -172,7 +179,7 @@ space from the +) gets a Hermes profile, made by Hermes with
|
|
|
172
179
|
The profile is named after the agent when it is made, in lowercase letters, digits and `-`
|
|
173
180
|
(`nova`, `nova-2` when Hermes has a `nova` already), and keeps that name after a rename, as the
|
|
174
181
|
agent's folder does. Deleting the agent in Chips leaves its profile in Hermes: what it learned is
|
|
175
|
-
yours to delete, with `hermes profile delete <name>`.
|
|
182
|
+
yours to delete, with `hermes profile delete <name>`. `~/Chips/.bridges/hermes/sessions.json` remembers
|
|
176
183
|
which profile is whose.
|
|
177
184
|
|
|
178
185
|
The one gateway serves every profile under `/p/<name>`, and takes a new one at once when the bridge
|
|
@@ -183,7 +190,7 @@ on it serves every profile. Hermes's gateway also keeps sending a new profile's
|
|
|
183
190
|
Main agent's address until it starts again, which the bridge drops. Where Hermes doesn't make a
|
|
184
191
|
profile, the agent runs on the first profile, in a session of its own, and the log says why.
|
|
185
192
|
|
|
186
|
-
**More than one agent.** Name them in
|
|
193
|
+
**More than one agent.** Name them in `~/Chips/.bridges/hermes/config.json` (see `config.example.json`).
|
|
187
194
|
Each agent is one of three:
|
|
188
195
|
- the default profile;
|
|
189
196
|
- a profile under `/p/<profile>`, with `gateway.multiplex_profiles` on and that profile's own key;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Third-party notices
|
|
2
2
|
|
|
3
|
-
`dist/main.js` in @chipschat/hermes 1.0.
|
|
3
|
+
`dist/main.js` in @chipschat/hermes 1.0.18 carries these packages, bundled in. Each one's
|
|
4
4
|
licence follows.
|
|
5
5
|
|
|
6
6
|
## @chipschat/harness 1.0.2 (Apache-2.0)
|
package/dist/main.js
CHANGED
|
@@ -9,10 +9,9 @@ var __export = (target, all) => {
|
|
|
9
9
|
|
|
10
10
|
// src/main.ts
|
|
11
11
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
12
|
-
import { existsSync as
|
|
12
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync6 } from "node:fs";
|
|
13
13
|
import { createServer as createServer2 } from "node:net";
|
|
14
|
-
import {
|
|
15
|
-
import { dirname as dirname6, join as join13, resolve as resolve6 } from "node:path";
|
|
14
|
+
import { dirname as dirname7, join as join14 } from "node:path";
|
|
16
15
|
|
|
17
16
|
// node_modules/zod/v4/classic/external.js
|
|
18
17
|
var external_exports = {};
|
|
@@ -5108,7 +5107,7 @@ function isRecursive(inst, stack, resolve7) {
|
|
|
5108
5107
|
}
|
|
5109
5108
|
return answer;
|
|
5110
5109
|
};
|
|
5111
|
-
const
|
|
5110
|
+
const merge3 = (answer) => {
|
|
5112
5111
|
if (answer > result)
|
|
5113
5112
|
result = answer;
|
|
5114
5113
|
};
|
|
@@ -5117,7 +5116,7 @@ function isRecursive(inst, stack, resolve7) {
|
|
|
5117
5116
|
switch (kind) {
|
|
5118
5117
|
case "object": {
|
|
5119
5118
|
const raw = rawShape(def);
|
|
5120
|
-
|
|
5119
|
+
merge3(raw ? shape(raw, true) : ASSUMED);
|
|
5121
5120
|
check2(def.catchall);
|
|
5122
5121
|
break;
|
|
5123
5122
|
}
|
|
@@ -5167,7 +5166,7 @@ function isRecursive(inst, stack, resolve7) {
|
|
|
5167
5166
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
5168
5167
|
case "lazy": {
|
|
5169
5168
|
const inner = def._cachedInner ?? (resolve7 ? inst._zod.innerType : void 0);
|
|
5170
|
-
|
|
5169
|
+
merge3(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
5171
5170
|
break;
|
|
5172
5171
|
}
|
|
5173
5172
|
// a leaf by choice: `parts` are regex fragments, not data positions
|
|
@@ -23400,8 +23399,8 @@ var Project = class {
|
|
|
23400
23399
|
const end2 = all.findIndex((line2, at) => at > start && line2.startsWith(">>>>>>> "));
|
|
23401
23400
|
if (start < 0 || end2 < 0)
|
|
23402
23401
|
return void 0;
|
|
23403
|
-
const
|
|
23404
|
-
return
|
|
23402
|
+
const shown3 = all.slice(Math.max(0, start - 1), end2 + 2);
|
|
23403
|
+
return shown3.length <= MARKED_LINES ? shown3.join("\n") : [...shown3.slice(0, MARKED_LINES - 1), "\u2026"].join("\n");
|
|
23405
23404
|
} catch {
|
|
23406
23405
|
return void 0;
|
|
23407
23406
|
}
|
|
@@ -25325,7 +25324,7 @@ async function ask(url2, options, send, machine) {
|
|
|
25325
25324
|
if (asked.status !== 201)
|
|
25326
25325
|
throw await refused(asked);
|
|
25327
25326
|
const { request_id, secret, code, interval } = await asked.json();
|
|
25328
|
-
const show = options.onCode ?? ((
|
|
25327
|
+
const show = options.onCode ?? ((shown3, where) => process.stderr.write(`Allow ${options.name} in Chips at ${where}. Its code is ${shown3}.
|
|
25329
25328
|
`));
|
|
25330
25329
|
show(code, url2);
|
|
25331
25330
|
for (; ; ) {
|
|
@@ -25902,8 +25901,8 @@ function profileName(profile) {
|
|
|
25902
25901
|
const name2 = (profile ?? "default").trim().toLowerCase();
|
|
25903
25902
|
return name2 === "" ? "default" : name2;
|
|
25904
25903
|
}
|
|
25905
|
-
function envValue(
|
|
25906
|
-
const path = join5(
|
|
25904
|
+
function envValue(home, name2) {
|
|
25905
|
+
const path = join5(home, ".env");
|
|
25907
25906
|
if (!existsSync5(path)) return void 0;
|
|
25908
25907
|
let found;
|
|
25909
25908
|
for (const line2 of readFileSync5(path, "utf8").split("\n")) {
|
|
@@ -25915,16 +25914,16 @@ function envValue(home2, name2) {
|
|
|
25915
25914
|
}
|
|
25916
25915
|
return found;
|
|
25917
25916
|
}
|
|
25918
|
-
function appendEnv(
|
|
25919
|
-
const path = join5(
|
|
25917
|
+
function appendEnv(home, name2, value) {
|
|
25918
|
+
const path = join5(home, ".env");
|
|
25920
25919
|
const text = readFileSync5(path, "utf8");
|
|
25921
25920
|
const mode = statSync(path).mode & 511;
|
|
25922
25921
|
appendFileSync(path, `${text === "" || text.endsWith("\n") ? "" : "\n"}${name2}=${value}
|
|
25923
25922
|
`);
|
|
25924
25923
|
chmodSync3(path, mode);
|
|
25925
25924
|
}
|
|
25926
|
-
function configText(
|
|
25927
|
-
const path = join5(
|
|
25925
|
+
function configText(home) {
|
|
25926
|
+
const path = join5(home, "config.yaml");
|
|
25928
25927
|
try {
|
|
25929
25928
|
return existsSync5(path) ? readFileSync5(path, "utf8") : "";
|
|
25930
25929
|
} catch {
|
|
@@ -26006,30 +26005,30 @@ function isFolder(path) {
|
|
|
26006
26005
|
return false;
|
|
26007
26006
|
}
|
|
26008
26007
|
}
|
|
26009
|
-
function workFolder(
|
|
26010
|
-
const configured = yamlValue(configText(
|
|
26008
|
+
function workFolder(home, env = process.env) {
|
|
26009
|
+
const configured = yamlValue(configText(home), "terminal", "cwd");
|
|
26011
26010
|
if (configured !== void 0 && configured !== "" && configured !== ".") {
|
|
26012
26011
|
const folder2 = expanded(configured);
|
|
26013
26012
|
if (isFolder(folder2)) return folder2;
|
|
26014
26013
|
}
|
|
26015
26014
|
for (const name2 of ["TERMINAL_CWD", "MESSAGING_CWD"]) {
|
|
26016
|
-
const said2 = envValue(
|
|
26015
|
+
const said2 = envValue(home, name2) ?? env[name2];
|
|
26017
26016
|
if (said2 !== void 0 && said2 !== "" && isFolder(expanded(said2))) return expanded(said2);
|
|
26018
26017
|
}
|
|
26019
|
-
return gatewayFolder(
|
|
26018
|
+
return gatewayFolder(home);
|
|
26020
26019
|
}
|
|
26021
26020
|
var gateways = /* @__PURE__ */ new Map();
|
|
26022
|
-
function gatewayFolder(
|
|
26021
|
+
function gatewayFolder(home) {
|
|
26023
26022
|
let raw;
|
|
26024
26023
|
try {
|
|
26025
|
-
raw = readFileSync5(join5(
|
|
26024
|
+
raw = readFileSync5(join5(home, "gateway.pid"), "utf8").trim();
|
|
26026
26025
|
} catch {
|
|
26027
26026
|
return void 0;
|
|
26028
26027
|
}
|
|
26029
|
-
const known = gateways.get(
|
|
26028
|
+
const known = gateways.get(home);
|
|
26030
26029
|
if (known?.pidFile === raw) return known.folder;
|
|
26031
26030
|
const folder2 = folderOfPid(raw);
|
|
26032
|
-
gateways.set(
|
|
26031
|
+
gateways.set(home, { pidFile: raw, folder: folder2 });
|
|
26033
26032
|
return folder2;
|
|
26034
26033
|
}
|
|
26035
26034
|
function folderOfPid(raw) {
|
|
@@ -26107,8 +26106,8 @@ function memoryProblem(text, limit, what) {
|
|
|
26107
26106
|
}
|
|
26108
26107
|
return void 0;
|
|
26109
26108
|
}
|
|
26110
|
-
function memorySettings(
|
|
26111
|
-
const text = configText(
|
|
26109
|
+
function memorySettings(home) {
|
|
26110
|
+
const text = configText(home);
|
|
26112
26111
|
const value = (key) => yamlValue(text, "memory", key);
|
|
26113
26112
|
return {
|
|
26114
26113
|
...yamlBool(value("memory_enabled")) === false ? {} : { memory: yamlNumber(value("memory_char_limit")) ?? MEMORY_LIMIT },
|
|
@@ -26116,21 +26115,21 @@ function memorySettings(home2) {
|
|
|
26116
26115
|
};
|
|
26117
26116
|
}
|
|
26118
26117
|
function sourcesOf(profile, env = process.env) {
|
|
26119
|
-
const { name: name2, home
|
|
26118
|
+
const { name: name2, home } = profile;
|
|
26120
26119
|
const found = [];
|
|
26121
|
-
const soul = join6(
|
|
26120
|
+
const soul = join6(home, "SOUL.md");
|
|
26122
26121
|
if (existsSync6(soul)) found.push({ path: soul, kind: "soul", file: "SOUL.md", profile: name2 });
|
|
26123
|
-
const folder2 = workFolder(
|
|
26122
|
+
const folder2 = workFolder(home, env);
|
|
26124
26123
|
const project = folder2 === void 0 ? void 0 : PROJECT_FILES.find((file3) => readText(join6(folder2, file3)).trim() !== "");
|
|
26125
26124
|
if (folder2 !== void 0 && project !== void 0) {
|
|
26126
26125
|
found.push({ path: join6(folder2, project), kind: "project", file: project, profile: name2 });
|
|
26127
26126
|
}
|
|
26128
|
-
const memory = memorySettings(
|
|
26127
|
+
const memory = memorySettings(home);
|
|
26129
26128
|
if (memory.user !== void 0) {
|
|
26130
|
-
found.push({ path: join6(
|
|
26129
|
+
found.push({ path: join6(home, "memories", "USER.md"), kind: "user", file: "USER.md", profile: name2, limit: memory.user });
|
|
26131
26130
|
}
|
|
26132
26131
|
if (memory.memory !== void 0) {
|
|
26133
|
-
found.push({ path: join6(
|
|
26132
|
+
found.push({ path: join6(home, "memories", "MEMORY.md"), kind: "memory", file: "MEMORY.md", profile: name2, limit: memory.memory });
|
|
26134
26133
|
}
|
|
26135
26134
|
return found;
|
|
26136
26135
|
}
|
|
@@ -26209,18 +26208,18 @@ var Picture = class {
|
|
|
26209
26208
|
}
|
|
26210
26209
|
/** The harness's own set, as `PUT /v1/harnesses/:id/context` takes it. */
|
|
26211
26210
|
harnessCopy() {
|
|
26212
|
-
const
|
|
26211
|
+
const shown3 = [];
|
|
26213
26212
|
const notShown = [];
|
|
26214
26213
|
for (const [path, { id: id2, name: name2 }] of this.shared) {
|
|
26215
26214
|
const entry = this.readers.get(path);
|
|
26216
26215
|
if (entry === void 0) continue;
|
|
26217
26216
|
const { source: source2, agents } = entry;
|
|
26218
26217
|
const { file: file3, tooLarge } = fileOf(source2, name2);
|
|
26219
|
-
if (tooLarge ||
|
|
26218
|
+
if (tooLarge || shown3.length >= FILES_SHOWN) {
|
|
26220
26219
|
notShown.push({ name: name2, title: ROWS[source2.kind].title, reason: tooLarge ? "too_large" : "count" });
|
|
26221
26220
|
continue;
|
|
26222
26221
|
}
|
|
26223
|
-
|
|
26222
|
+
shown3.push({
|
|
26224
26223
|
...file3,
|
|
26225
26224
|
id: id2,
|
|
26226
26225
|
used_by: agents.length,
|
|
@@ -26228,7 +26227,7 @@ var Picture = class {
|
|
|
26228
26227
|
});
|
|
26229
26228
|
}
|
|
26230
26229
|
return {
|
|
26231
|
-
shared:
|
|
26230
|
+
shared: shown3,
|
|
26232
26231
|
...notShown.length === 0 ? {} : { not_shown: notShown }
|
|
26233
26232
|
};
|
|
26234
26233
|
}
|
|
@@ -26268,9 +26267,9 @@ var Picture = class {
|
|
|
26268
26267
|
/** The file an edit names: an agent's own, or one of the harness's set; with whether it is shared. */
|
|
26269
26268
|
find(agentId2, name2) {
|
|
26270
26269
|
if (agentId2 === void 0) {
|
|
26271
|
-
for (const [path, { name:
|
|
26270
|
+
for (const [path, { name: shown3 }] of this.shared) {
|
|
26272
26271
|
const source2 = this.readers.get(path)?.source;
|
|
26273
|
-
if (
|
|
26272
|
+
if (shown3 === name2 && source2 !== void 0) return { source: source2, shared: true };
|
|
26274
26273
|
}
|
|
26275
26274
|
return void 0;
|
|
26276
26275
|
}
|
|
@@ -26457,8 +26456,8 @@ var SMALL_THRESHOLD = 0.75;
|
|
|
26457
26456
|
var WHY_NOT = "Hermes can't be asked to compact from Chips.";
|
|
26458
26457
|
var whyReadOnly = (profile) => `Hermes sets this for every agent on its ${profile} profile.`;
|
|
26459
26458
|
var num = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
26460
|
-
function limitOf(
|
|
26461
|
-
const text = configText(
|
|
26459
|
+
function limitOf(home, window) {
|
|
26460
|
+
const text = configText(home);
|
|
26462
26461
|
const enabled = yamlBool(yamlValue(text, "compression", "enabled")) ?? true;
|
|
26463
26462
|
const threshold = yamlNumber(yamlValue(text, "compression", "threshold")) ?? THRESHOLD;
|
|
26464
26463
|
let ratio = window < SMALL_WINDOW ? Math.max(threshold, SMALL_THRESHOLD) : threshold;
|
|
@@ -26911,8 +26910,8 @@ function linesOf2(text) {
|
|
|
26911
26910
|
return { indent, words: words4 };
|
|
26912
26911
|
});
|
|
26913
26912
|
}
|
|
26914
|
-
function hookPortIn(
|
|
26915
|
-
const path = join7(
|
|
26913
|
+
function hookPortIn(home) {
|
|
26914
|
+
const path = join7(home, "config.yaml");
|
|
26916
26915
|
if (!existsSync7(path)) return void 0;
|
|
26917
26916
|
const escaped = HOOK_PATH.replace(/[/]/g, "\\/");
|
|
26918
26917
|
const match = new RegExp(`^\\s*(?:-\\s*)?url:\\s*["']?http:\\/\\/127\\.0\\.0\\.1:(\\d+)${escaped}`, "m").exec(
|
|
@@ -26931,15 +26930,15 @@ function entryLines(indent, url2, secret) {
|
|
|
26931
26930
|
`${indent} timeout: 5`
|
|
26932
26931
|
];
|
|
26933
26932
|
}
|
|
26934
|
-
function secretInEnv(
|
|
26935
|
-
const path = join7(
|
|
26933
|
+
function secretInEnv(home, secret) {
|
|
26934
|
+
const path = join7(home, ".env");
|
|
26936
26935
|
if (!existsSync7(path)) return false;
|
|
26937
|
-
if (envValue(
|
|
26936
|
+
if (envValue(home, SECRET_ENV) === void 0) appendEnv(home, SECRET_ENV, secret);
|
|
26938
26937
|
return true;
|
|
26939
26938
|
}
|
|
26940
|
-
function addHook(
|
|
26941
|
-
const path = join7(
|
|
26942
|
-
if (!existsSync7(
|
|
26939
|
+
function addHook(home, port, profile, secret) {
|
|
26940
|
+
const path = join7(home, "config.yaml");
|
|
26941
|
+
if (!existsSync7(home)) return { state: "no_home", path };
|
|
26943
26942
|
const url2 = hookUrl(port, profile);
|
|
26944
26943
|
const text = existsSync7(path) ? readFileSync7(path, "utf8") : "";
|
|
26945
26944
|
const lines2 = linesOf2(text);
|
|
@@ -26947,16 +26946,16 @@ function addHook(home2, port, profile, secret) {
|
|
|
26947
26946
|
if (lines2.some((line2) => ours2.test(line2.words))) return { state: "there", path };
|
|
26948
26947
|
const where = lines2.findIndex((line2) => line2.indent === 0 && /^["']?hooks["']?\s*:/.test(line2.words));
|
|
26949
26948
|
const byHand = (why) => {
|
|
26950
|
-
const inEnv2 = secretInEnv(
|
|
26951
|
-
const
|
|
26952
|
-
return { state: "by_hand", path, why, lines: ["hooks:", ...
|
|
26949
|
+
const inEnv2 = secretInEnv(home, secret);
|
|
26950
|
+
const shown3 = entryLines(" ", url2, inEnv2 ? { env: SECRET_ENV } : { inline: secret });
|
|
26951
|
+
return { state: "by_hand", path, why, lines: ["hooks:", ...shown3].join("\n") };
|
|
26953
26952
|
};
|
|
26954
26953
|
const plain = /^(?:"[^"]+"|'[^']+'|[A-Za-z_][\w.-]*)\s*:(?:\s|$)/;
|
|
26955
26954
|
if (lines2.some((line2) => line2.indent === 0 && line2.words !== "" && !plain.test(line2.words))) {
|
|
26956
26955
|
return byHand("its top level isn't laid out as this bridge expects");
|
|
26957
26956
|
}
|
|
26958
26957
|
if (where === -1) {
|
|
26959
|
-
const inEnv2 = secretInEnv(
|
|
26958
|
+
const inEnv2 = secretInEnv(home, secret);
|
|
26960
26959
|
const block = [
|
|
26961
26960
|
"# Chips: how full each agent's context is, sent to the chips-hermes bridge after each model call.",
|
|
26962
26961
|
"hooks:",
|
|
@@ -26988,7 +26987,7 @@ function addHook(home2, port, profile, secret) {
|
|
|
26988
26987
|
if (children.some((line2) => line2.indent !== indent && line2.indent < indent) || children[0]?.words.startsWith("-")) {
|
|
26989
26988
|
return byHand("its hooks: isn't laid out as this bridge expects");
|
|
26990
26989
|
}
|
|
26991
|
-
const inEnv = secretInEnv(
|
|
26990
|
+
const inEnv = secretInEnv(home, secret);
|
|
26992
26991
|
const raw = text.split("\n");
|
|
26993
26992
|
raw.splice(where + 1, 0, ...entryLines(" ".repeat(indent), url2, inEnv ? { env: SECRET_ENV } : { inline: secret }));
|
|
26994
26993
|
writeWhole(path, raw.join("\n"));
|
|
@@ -27115,9 +27114,9 @@ function gatewayRunArgs(command) {
|
|
|
27115
27114
|
return plain[0] === "gateway" && plain[1] === "run" ? args : void 0;
|
|
27116
27115
|
}
|
|
27117
27116
|
function serviceOf(system, root2, env = {}) {
|
|
27118
|
-
const
|
|
27117
|
+
const home = resolve3(root2);
|
|
27119
27118
|
const native = resolve3(system.home, ".hermes");
|
|
27120
|
-
const suffix =
|
|
27119
|
+
const suffix = home === native ? "" : dirname5(home) === join8(native, "profiles") ? basename4(home) : createHash3("sha256").update(home).digest("hex").slice(0, 8);
|
|
27121
27120
|
if (system.platform === "darwin") {
|
|
27122
27121
|
const path = join8(system.home, "Library", "LaunchAgents", `ai.hermes.gateway${suffix ? `-${suffix}` : ""}.plist`);
|
|
27123
27122
|
return system.exists(path) ? { kind: "launchd", path } : void 0;
|
|
@@ -27549,18 +27548,18 @@ function freeProfile(root2, name2, taken) {
|
|
|
27549
27548
|
if (!taken.includes(profile) && !existsSync9(join9(root2, "profiles", profile))) return profile;
|
|
27550
27549
|
}
|
|
27551
27550
|
}
|
|
27552
|
-
function readyProfile(
|
|
27553
|
-
for (const file3 of ["MEMORY.md", "USER.md"]) rmSync4(join9(
|
|
27554
|
-
if (envValue(
|
|
27551
|
+
function readyProfile(home, names, hook) {
|
|
27552
|
+
for (const file3 of ["MEMORY.md", "USER.md"]) rmSync4(join9(home, "memories", file3), { force: true });
|
|
27553
|
+
if (envValue(home, KEY_ENV) === void 0) appendEnv(home, KEY_ENV, randomBytes2(32).toString("hex"));
|
|
27555
27554
|
if (hook === void 0) return void 0;
|
|
27556
|
-
const path = join9(
|
|
27555
|
+
const path = join9(home, "config.yaml");
|
|
27557
27556
|
if (existsSync9(path)) {
|
|
27558
27557
|
const theirs = hookUrl(hook.port, names.from).replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
|
|
27559
27558
|
const entry = new RegExp(`^(\\s*(?:-\\s*)?url:\\s*["']?)${theirs}(["']?\\s*(?:#.*)?)$`, "m");
|
|
27560
27559
|
const text = readFileSync9(path, "utf8");
|
|
27561
27560
|
if (entry.test(text)) writeWhole(path, text.replace(entry, `$1${hookUrl(hook.port, names.profile)}$2`));
|
|
27562
27561
|
}
|
|
27563
|
-
return addHook(
|
|
27562
|
+
return addHook(home, hook.port, names.profile, hook.secret);
|
|
27564
27563
|
}
|
|
27565
27564
|
function hermesProfiles(options) {
|
|
27566
27565
|
return {
|
|
@@ -27633,9 +27632,9 @@ var WANTS = [
|
|
|
27633
27632
|
];
|
|
27634
27633
|
function settingsFor(active) {
|
|
27635
27634
|
const bridge2 = () => {
|
|
27636
|
-
const
|
|
27637
|
-
if (
|
|
27638
|
-
return
|
|
27635
|
+
const there2 = active();
|
|
27636
|
+
if (there2 === void 0) throw new Refuse("The bridge is starting. Try again in a moment.");
|
|
27637
|
+
return there2;
|
|
27639
27638
|
};
|
|
27640
27639
|
return {
|
|
27641
27640
|
context: (edit) => bridge2().onContextEdit(edit),
|
|
@@ -28026,10 +28025,10 @@ var Bridge = class {
|
|
|
28026
28025
|
}
|
|
28027
28026
|
/** The Main agent into the harness's own room, in the place of whichever of ours is there. */
|
|
28028
28027
|
async goHome(main2, known) {
|
|
28029
|
-
const { chips: chips2, home
|
|
28030
|
-
if (
|
|
28031
|
-
const
|
|
28032
|
-
await chips2.agents.attach(main2.agentId, { spaceId:
|
|
28028
|
+
const { chips: chips2, home } = this.options;
|
|
28029
|
+
if (home === void 0 || main2.spaces.includes(home)) return;
|
|
28030
|
+
const there2 = known.find((agent) => agent.agentId !== main2.agentId && agent.spaces.includes(home));
|
|
28031
|
+
await chips2.agents.attach(main2.agentId, { spaceId: home, replacing: there2?.agentId ?? chips2.harnessId }).catch((error62) => this.log(`${main2.name} stays out of its home: ${String(error62)}`));
|
|
28033
28032
|
}
|
|
28034
28033
|
/**
|
|
28035
28034
|
* A person asked for a new agent in a room (Chips ADR 0108): one of the harness's, keyed by the
|
|
@@ -28065,12 +28064,12 @@ var Bridge = class {
|
|
|
28065
28064
|
if (profiles === void 0 || root2 === void 0 || main2 === void 0 || this.own.has(agentId2)) return;
|
|
28066
28065
|
const from = profileName(main2.config.address.profile);
|
|
28067
28066
|
const profile = freeProfile(root2, name2, Object.values(state2.made ?? {}));
|
|
28068
|
-
const
|
|
28067
|
+
const home = profileHome(root2, profile);
|
|
28069
28068
|
const secret = state2.fills?.secret ?? this.options.fills?.secret;
|
|
28070
28069
|
try {
|
|
28071
28070
|
await profiles.create(profile, from);
|
|
28072
28071
|
const port = this.fillsPort;
|
|
28073
|
-
const hook = readyProfile(
|
|
28072
|
+
const hook = readyProfile(home, { from, profile }, port === void 0 || secret === void 0 ? void 0 : { port, secret });
|
|
28074
28073
|
if (hook?.state === "by_hand") this.log(`context window: ${hook.path} was left as it is: ${hook.why}. Add these lines to it:
|
|
28075
28074
|
${hook.lines}`);
|
|
28076
28075
|
} catch (error62) {
|
|
@@ -28098,12 +28097,12 @@ ${hook.lines}`);
|
|
|
28098
28097
|
const main2 = this.agents[0];
|
|
28099
28098
|
const root2 = this.options.hermesRoot;
|
|
28100
28099
|
if (main2 === void 0 || root2 === void 0) return void 0;
|
|
28101
|
-
const
|
|
28100
|
+
const home = profileHome(root2, profile);
|
|
28102
28101
|
const config3 = {
|
|
28103
28102
|
name: name2,
|
|
28104
|
-
address: { url: main2.config.address.url, profile, key: envValue(
|
|
28103
|
+
address: { url: main2.config.address.url, profile, key: envValue(home, KEY_ENV) ?? "" },
|
|
28105
28104
|
keyEnv: KEY_ENV,
|
|
28106
|
-
keyFrom: join10(
|
|
28105
|
+
keyFrom: join10(home, ".env")
|
|
28107
28106
|
};
|
|
28108
28107
|
const client = this.options.clientFor?.(config3) ?? new HermesClient(config3.address);
|
|
28109
28108
|
return { config: config3, key: agentId2, client, agentId: agentId2, up: true };
|
|
@@ -28850,12 +28849,60 @@ function lowerFirst(text) {
|
|
|
28850
28849
|
}
|
|
28851
28850
|
|
|
28852
28851
|
// src/keep.ts
|
|
28853
|
-
import {
|
|
28854
|
-
import { basename as basename5, join as join11, resolve as resolve4 } from "node:path";
|
|
28852
|
+
import { basename as basename5 } from "node:path";
|
|
28855
28853
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
28854
|
+
|
|
28855
|
+
// src/places.ts
|
|
28856
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
28857
|
+
import { homedir as homedir6 } from "node:os";
|
|
28858
|
+
import { isAbsolute as isAbsolute2, join as join11, relative, resolve as resolve4, sep as sep2 } from "node:path";
|
|
28859
|
+
function placesOf(home = homedir6()) {
|
|
28860
|
+
return {
|
|
28861
|
+
settings: join11(home, "Chips", ".bridges", "hermes"),
|
|
28862
|
+
agents: join11(home, "Chips", "Agents", "hermes"),
|
|
28863
|
+
oldSettings: join11(home, ".chips-hermes"),
|
|
28864
|
+
oldAgents: join11(home, "chips-hermes", "agents")
|
|
28865
|
+
};
|
|
28866
|
+
}
|
|
28867
|
+
var fromHome = (path, home = homedir6()) => path === "~" ? home : path.startsWith("~/") ? join11(home, path.slice(2)) : path;
|
|
28868
|
+
function inside2(root2, path) {
|
|
28869
|
+
const under = relative(root2, path);
|
|
28870
|
+
return under === ".." || under.startsWith(`..${sep2}`) || isAbsolute2(under) ? void 0 : under;
|
|
28871
|
+
}
|
|
28872
|
+
function nowAt(path, before, after) {
|
|
28873
|
+
const under = inside2(before, path);
|
|
28874
|
+
if (under === void 0) return path;
|
|
28875
|
+
const moved = join11(after, under);
|
|
28876
|
+
return existsSync10(path) && !existsSync10(moved) ? path : moved;
|
|
28877
|
+
}
|
|
28878
|
+
var configOf = (word, places, home) => resolve4(fromHome(word ?? join11(places.settings, "config.json"), home));
|
|
28879
|
+
function configTargetOf(word, home = homedir6()) {
|
|
28880
|
+
const places = placesOf(home);
|
|
28881
|
+
const path = configOf(word, places, home);
|
|
28882
|
+
const under = inside2(places.oldSettings, path);
|
|
28883
|
+
return under === void 0 ? path : join11(places.settings, under);
|
|
28884
|
+
}
|
|
28885
|
+
function configPathOf(word, home = homedir6()) {
|
|
28886
|
+
const places = placesOf(home);
|
|
28887
|
+
const target = configTargetOf(word, home);
|
|
28888
|
+
const under = inside2(places.settings, target);
|
|
28889
|
+
const old = under === void 0 ? void 0 : join11(places.oldSettings, under);
|
|
28890
|
+
return old !== void 0 && existsSync10(old) && !existsSync10(target) ? old : target;
|
|
28891
|
+
}
|
|
28892
|
+
function folderPathOf(path, home = homedir6()) {
|
|
28893
|
+
const places = placesOf(home);
|
|
28894
|
+
const whole2 = resolve4(fromHome(path, home));
|
|
28895
|
+
const under = inside2(places.agents, whole2);
|
|
28896
|
+
const old = under === void 0 ? void 0 : join11(places.oldAgents, under);
|
|
28897
|
+
if (old !== void 0 && existsSync10(old) && !existsSync10(whole2)) return old;
|
|
28898
|
+
return nowAt(whole2, places.oldAgents, places.agents);
|
|
28899
|
+
}
|
|
28900
|
+
|
|
28901
|
+
// src/keep.ts
|
|
28856
28902
|
var flags = process.argv.slice(2);
|
|
28857
28903
|
var words3 = flags.filter((word) => !word.startsWith("--"));
|
|
28858
|
-
var
|
|
28904
|
+
var handsOver = flags.includes("--keep");
|
|
28905
|
+
var whole = (word) => configTargetOf(word);
|
|
28859
28906
|
var here = fileURLToPath2(new URL("..", import.meta.url)).replace(/\/$/, "");
|
|
28860
28907
|
var self = fileURLToPath2(import.meta.url);
|
|
28861
28908
|
var run = self.endsWith(".js") ? [self] : ["--import", "tsx", "src/main.ts"];
|
|
@@ -28900,10 +28947,130 @@ function keepIfAsked(label2, url2, names, log2, before = () => void 0) {
|
|
|
28900
28947
|
);
|
|
28901
28948
|
}
|
|
28902
28949
|
|
|
28903
|
-
// src/
|
|
28904
|
-
import {
|
|
28950
|
+
// src/move.ts
|
|
28951
|
+
import { lstatSync as lstatSync2, mkdirSync as mkdirSync6, readdirSync, readFileSync as readFileSync10, renameSync as renameSync3, rmdirSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
28905
28952
|
import { homedir as homedir7 } from "node:os";
|
|
28906
|
-
import { join as join12, resolve as resolve5 } from "node:path";
|
|
28953
|
+
import { dirname as dirname6, join as join12, resolve as resolve5 } from "node:path";
|
|
28954
|
+
var there = (path) => {
|
|
28955
|
+
try {
|
|
28956
|
+
lstatSync2(path);
|
|
28957
|
+
return true;
|
|
28958
|
+
} catch {
|
|
28959
|
+
return false;
|
|
28960
|
+
}
|
|
28961
|
+
};
|
|
28962
|
+
var isFolder2 = (path) => lstatSync2(path).isDirectory();
|
|
28963
|
+
var shown = (path, home) => path.startsWith(`${home}/`) ? `~${path.slice(home.length)}` : path;
|
|
28964
|
+
function merge2(from, to, log2, home = homedir7(), quiet = false) {
|
|
28965
|
+
if (!there(from)) return;
|
|
28966
|
+
try {
|
|
28967
|
+
if (!there(to)) {
|
|
28968
|
+
mkdirSync6(dirname6(to), { recursive: true });
|
|
28969
|
+
renameSync3(from, to);
|
|
28970
|
+
if (!quiet) log2(`moved ${shown(from, home)} to ${shown(to, home)}`);
|
|
28971
|
+
return;
|
|
28972
|
+
}
|
|
28973
|
+
if (!isFolder2(from) || !isFolder2(to)) {
|
|
28974
|
+
log2(`${shown(from, home)} was left where it is: ${shown(to, home)} is there already`);
|
|
28975
|
+
return;
|
|
28976
|
+
}
|
|
28977
|
+
for (const entry of readdirSync(from)) merge2(join12(from, entry), join12(to, entry), log2, home, true);
|
|
28978
|
+
if (readdirSync(from).length === 0) rmdirSync(from);
|
|
28979
|
+
if (!quiet) log2(`moved what was in ${shown(from, home)} into ${shown(to, home)}`);
|
|
28980
|
+
} catch (error62) {
|
|
28981
|
+
log2(`${shown(from, home)} couldn't be moved to ${shown(to, home)}, so it is used where it is: ${error62.message}`);
|
|
28982
|
+
}
|
|
28983
|
+
}
|
|
28984
|
+
function removeIfEmpty(path) {
|
|
28985
|
+
try {
|
|
28986
|
+
if (readdirSync(path).length === 0) rmdirSync(path);
|
|
28987
|
+
} catch {
|
|
28988
|
+
}
|
|
28989
|
+
}
|
|
28990
|
+
function pairOf(path, places) {
|
|
28991
|
+
const old = inside2(places.oldAgents, path);
|
|
28992
|
+
if (old !== void 0) return { old: path, now: join12(places.agents, old) };
|
|
28993
|
+
const now = inside2(places.agents, path);
|
|
28994
|
+
return now === void 0 ? void 0 : { old: join12(places.oldAgents, now), now: path };
|
|
28995
|
+
}
|
|
28996
|
+
function writeJson(path, value) {
|
|
28997
|
+
const next = `${path}.next`;
|
|
28998
|
+
writeFileSync5(next, `${JSON.stringify(value, null, 2)}
|
|
28999
|
+
`, { mode: 384 });
|
|
29000
|
+
renameSync3(next, path);
|
|
29001
|
+
}
|
|
29002
|
+
var readJson = (path) => {
|
|
29003
|
+
try {
|
|
29004
|
+
const read = JSON.parse(readFileSync10(path, "utf8"));
|
|
29005
|
+
return typeof read === "object" && read !== null ? read : void 0;
|
|
29006
|
+
} catch {
|
|
29007
|
+
return void 0;
|
|
29008
|
+
}
|
|
29009
|
+
};
|
|
29010
|
+
function movedWords(said2, places, home) {
|
|
29011
|
+
if (typeof said2 !== "string" || said2 === "") return void 0;
|
|
29012
|
+
const path = resolve5(fromHome(said2, home));
|
|
29013
|
+
const moved = nowAt(path, places.oldAgents, places.agents);
|
|
29014
|
+
return moved === path ? void 0 : `~/${moved.slice(home.length + 1)}`;
|
|
29015
|
+
}
|
|
29016
|
+
function moveOld(configPath2, log2, home = homedir7()) {
|
|
29017
|
+
const places = placesOf(home);
|
|
29018
|
+
const settings = dirname6(configPath2);
|
|
29019
|
+
const under = inside2(places.settings, settings);
|
|
29020
|
+
if (under !== void 0) {
|
|
29021
|
+
mkdirSync6(dirname6(dirname6(places.settings)), { recursive: true });
|
|
29022
|
+
mkdirSync6(dirname6(places.settings), { recursive: true, mode: 448 });
|
|
29023
|
+
merge2(join12(places.oldSettings, under), settings, log2, home);
|
|
29024
|
+
}
|
|
29025
|
+
const config3 = readJson(configPath2);
|
|
29026
|
+
const agents = Array.isArray(config3?.["agents"]) ? config3["agents"] : [];
|
|
29027
|
+
const roots = [config3?.["folders"] ?? places.agents, config3?.["folder"], ...agents.map((agent) => agent["folder"])].filter((root2) => typeof root2 === "string" && root2 !== "").map((root2) => resolve5(fromHome(root2, home)));
|
|
29028
|
+
const pairs = roots.map((root2) => pairOf(root2, places)).filter((pair) => pair !== void 0);
|
|
29029
|
+
for (const { old, now } of pairs) merge2(old, now, log2, home);
|
|
29030
|
+
if (config3 !== void 0) {
|
|
29031
|
+
let changed = false;
|
|
29032
|
+
const folders = movedWords(config3["folders"], places, home);
|
|
29033
|
+
if (folders !== void 0) {
|
|
29034
|
+
config3["folders"] = folders;
|
|
29035
|
+
changed = true;
|
|
29036
|
+
}
|
|
29037
|
+
const folder2 = movedWords(config3["folder"], places, home);
|
|
29038
|
+
if (folder2 !== void 0) {
|
|
29039
|
+
config3["folder"] = folder2;
|
|
29040
|
+
changed = true;
|
|
29041
|
+
}
|
|
29042
|
+
for (const agent of agents) {
|
|
29043
|
+
const folder3 = movedWords(agent["folder"], places, home);
|
|
29044
|
+
if (folder3 === void 0) continue;
|
|
29045
|
+
agent["folder"] = folder3;
|
|
29046
|
+
changed = true;
|
|
29047
|
+
}
|
|
29048
|
+
if (changed) writeJson(configPath2, config3);
|
|
29049
|
+
}
|
|
29050
|
+
const statePath2 = join12(settings, "sessions.json");
|
|
29051
|
+
const state2 = readJson(statePath2);
|
|
29052
|
+
const saved = state2?.["folders"];
|
|
29053
|
+
if (state2 !== void 0 && typeof saved === "object" && saved !== null) {
|
|
29054
|
+
const folders = saved;
|
|
29055
|
+
let changed = false;
|
|
29056
|
+
for (const [agentId2, folder2] of Object.entries(folders)) {
|
|
29057
|
+
if (typeof folder2 !== "string") continue;
|
|
29058
|
+
const moved = nowAt(folder2, places.oldAgents, places.agents);
|
|
29059
|
+
if (moved === folder2) continue;
|
|
29060
|
+
folders[agentId2] = moved;
|
|
29061
|
+
changed = true;
|
|
29062
|
+
}
|
|
29063
|
+
if (changed) writeJson(statePath2, state2);
|
|
29064
|
+
}
|
|
29065
|
+
removeIfEmpty(places.oldSettings);
|
|
29066
|
+
removeIfEmpty(places.oldAgents);
|
|
29067
|
+
removeIfEmpty(dirname6(places.oldAgents));
|
|
29068
|
+
}
|
|
29069
|
+
|
|
29070
|
+
// src/setup.ts
|
|
29071
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11 } from "node:fs";
|
|
29072
|
+
import { homedir as homedir8 } from "node:os";
|
|
29073
|
+
import { join as join13, resolve as resolve6 } from "node:path";
|
|
28907
29074
|
var SetupError = class extends Error {
|
|
28908
29075
|
constructor(message, words4 = {}) {
|
|
28909
29076
|
super(message);
|
|
@@ -28912,7 +29079,7 @@ var SetupError = class extends Error {
|
|
|
28912
29079
|
words;
|
|
28913
29080
|
name = "SetupError";
|
|
28914
29081
|
};
|
|
28915
|
-
var
|
|
29082
|
+
var shown2 = (path) => path.startsWith(`${homedir8()}/`) ? `~${path.slice(homedir8().length)}` : path;
|
|
28916
29083
|
var portOf2 = (url2) => {
|
|
28917
29084
|
const parsed = new URL(url2);
|
|
28918
29085
|
return parsed.port || (parsed.protocol === "https:" ? "443" : "80");
|
|
@@ -28932,24 +29099,24 @@ function readyHooks(config3, options) {
|
|
|
28932
29099
|
const profile = profileName(named);
|
|
28933
29100
|
if (done.has(profile)) continue;
|
|
28934
29101
|
done.add(profile);
|
|
28935
|
-
const
|
|
29102
|
+
const home = profileHome(options.root, named);
|
|
28936
29103
|
let outcome;
|
|
28937
29104
|
try {
|
|
28938
|
-
outcome = addHook(
|
|
29105
|
+
outcome = addHook(home, options.port, profile, options.secret);
|
|
28939
29106
|
} catch (error62) {
|
|
28940
|
-
lines2.push(`Chips's webhook wasn't added to ${
|
|
29107
|
+
lines2.push(`Chips's webhook wasn't added to ${shown2(join13(home, "config.yaml"))}: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
28941
29108
|
continue;
|
|
28942
29109
|
}
|
|
28943
29110
|
if (outcome.state === "added") {
|
|
28944
|
-
lines2.push(`Added Chips's webhook to ${
|
|
29111
|
+
lines2.push(`Added Chips's webhook to ${shown2(outcome.path)}, so Hermes tells Chips how full each agent's context is.`);
|
|
28945
29112
|
restart2 ||= options.gatewayUp;
|
|
28946
29113
|
} else if (outcome.state === "by_hand") {
|
|
28947
29114
|
lines2.push(
|
|
28948
|
-
`${
|
|
29115
|
+
`${shown2(outcome.path)} was left as it is: ${outcome.why}. For Chips to show how full each agent's context is, add these lines to it, then start hermes gateway again:
|
|
28949
29116
|
${outcome.lines}`
|
|
28950
29117
|
);
|
|
28951
29118
|
} else if (outcome.state === "no_home") {
|
|
28952
|
-
lines2.push(`Hermes has no ${profile} profile at ${
|
|
29119
|
+
lines2.push(`Hermes has no ${profile} profile at ${shown2(home)}, so no webhook was added for it.`);
|
|
28953
29120
|
}
|
|
28954
29121
|
}
|
|
28955
29122
|
if (restart2) lines2.push(RESTART);
|
|
@@ -28959,12 +29126,12 @@ var STILL_GOOD = "The link is still good: run the same command again once that's
|
|
|
28959
29126
|
var EXAMPLE = '{ "agents": [{ "name": "Hermes", "profile": "default", "keyEnv": "API_SERVER_KEY" }] }';
|
|
28960
29127
|
var PLAIN = { agents: [{ name: "Hermes", profile: "default", keyEnv: "API_SERVER_KEY" }] };
|
|
28961
29128
|
function hermesEnvPath(env = process.env) {
|
|
28962
|
-
return
|
|
29129
|
+
return resolve6(env["HERMES_HOME"] ?? resolve6(homedir8(), ".hermes"), ".env");
|
|
28963
29130
|
}
|
|
28964
29131
|
function fromHermes(name2, env) {
|
|
28965
29132
|
const path = hermesEnvPath(env);
|
|
28966
|
-
if (!
|
|
28967
|
-
for (const line2 of
|
|
29133
|
+
if (!existsSync11(path)) return void 0;
|
|
29134
|
+
for (const line2 of readFileSync11(path, "utf8").split("\n")) {
|
|
28968
29135
|
const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/.exec(line2);
|
|
28969
29136
|
if (match?.[1] === name2) return match[2]?.replace(/^(["'])(.*)\1$/, "$2");
|
|
28970
29137
|
}
|
|
@@ -28972,10 +29139,10 @@ function fromHermes(name2, env) {
|
|
|
28972
29139
|
}
|
|
28973
29140
|
function folderOf(said2) {
|
|
28974
29141
|
if (typeof said2 !== "string" || said2 === "") return void 0;
|
|
28975
|
-
return
|
|
29142
|
+
return folderPathOf(said2);
|
|
28976
29143
|
}
|
|
28977
29144
|
function readConfig(path, env = process.env) {
|
|
28978
|
-
const raw =
|
|
29145
|
+
const raw = existsSync11(path) ? JSON.parse(readFileSync11(path, "utf8")) : PLAIN;
|
|
28979
29146
|
const url2 = typeof raw.url === "string" ? raw.url : "http://127.0.0.1:8642";
|
|
28980
29147
|
const folder2 = folderOf(raw.folder);
|
|
28981
29148
|
if (!Array.isArray(raw.agents) || raw.agents.length === 0) {
|
|
@@ -28993,7 +29160,7 @@ function readConfig(path, env = process.env) {
|
|
|
28993
29160
|
{
|
|
28994
29161
|
detail: "No key for its API server",
|
|
28995
29162
|
says: "Hermes's API server isn't set up.",
|
|
28996
|
-
doing: `Add API_SERVER_ENABLED=true and an API_SERVER_KEY, a long random key, to ${
|
|
29163
|
+
doing: `Add API_SERVER_ENABLED=true and an API_SERVER_KEY, a long random key, to ${shown2(hermesEnvPath(env))}. Then start Hermes with hermes gateway.`
|
|
28997
29164
|
}
|
|
28998
29165
|
);
|
|
28999
29166
|
}
|
|
@@ -29014,7 +29181,7 @@ function readConfig(path, env = process.env) {
|
|
|
29014
29181
|
return {
|
|
29015
29182
|
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
29016
29183
|
agents,
|
|
29017
|
-
folders: folderOf(raw.folders) ??
|
|
29184
|
+
folders: folderOf(raw.folders) ?? folderPathOf(placesOf().agents),
|
|
29018
29185
|
...typeof hookPort === "number" && Number.isInteger(hookPort) && hookPort > 0 && hookPort < 65536 ? { hookPort } : {}
|
|
29019
29186
|
};
|
|
29020
29187
|
}
|
|
@@ -29027,7 +29194,7 @@ async function checkHermes(config3, clientFor = (agent) => new HermesClient(agen
|
|
|
29027
29194
|
{
|
|
29028
29195
|
detail: `Nothing answers on port ${portOf2(agent.address.url)}`,
|
|
29029
29196
|
says: "Hermes's API server is off.",
|
|
29030
|
-
doing: `Add this line to ${
|
|
29197
|
+
doing: `Add this line to ${shown2(hermesEnvPath())}, then start Hermes with hermes gateway.`,
|
|
29031
29198
|
copy: "API_SERVER_ENABLED=true"
|
|
29032
29199
|
}
|
|
29033
29200
|
);
|
|
@@ -29046,25 +29213,25 @@ async function checkHermes(config3, clientFor = (agent) => new HermesClient(agen
|
|
|
29046
29213
|
}
|
|
29047
29214
|
|
|
29048
29215
|
// src/version.ts
|
|
29049
|
-
import { readFileSync as
|
|
29050
|
-
var VERSION = JSON.parse(
|
|
29216
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
29217
|
+
var VERSION = JSON.parse(readFileSync12(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
29051
29218
|
|
|
29052
29219
|
// src/main.ts
|
|
29053
|
-
var home = (path) => path.startsWith("~/") ? join13(homedir8(), path.slice(2)) : path;
|
|
29054
29220
|
var link = process.env["CHIPS_JOIN_LINK"] || void 0;
|
|
29055
29221
|
var LABEL = "chat.chips.hermes";
|
|
29056
29222
|
stopIfAsked(LABEL);
|
|
29057
|
-
var
|
|
29058
|
-
|
|
29059
|
-
|
|
29060
|
-
var
|
|
29223
|
+
var log = (line2) => process.stdout.write(`${(/* @__PURE__ */ new Date()).toISOString()} ${line2}
|
|
29224
|
+
`);
|
|
29225
|
+
if (!handsOver) moveOld(configTargetOf(words3[0]), log);
|
|
29226
|
+
var configPath = configPathOf(words3[0]);
|
|
29227
|
+
var folder = dirname7(configPath);
|
|
29228
|
+
var statePath = join14(folder, "sessions.json");
|
|
29229
|
+
var state = existsSync12(statePath) ? JSON.parse(readFileSync13(statePath, "utf8")) : { sessions: {} };
|
|
29061
29230
|
var saveState = (next) => {
|
|
29062
|
-
|
|
29063
|
-
|
|
29231
|
+
mkdirSync7(folder, { recursive: true, mode: 448 });
|
|
29232
|
+
writeFileSync6(statePath, `${JSON.stringify(next, null, 2)}
|
|
29064
29233
|
`, { mode: 384 });
|
|
29065
29234
|
};
|
|
29066
|
-
var log = (line2) => process.stdout.write(`${(/* @__PURE__ */ new Date()).toISOString()} ${line2}
|
|
29067
|
-
`);
|
|
29068
29235
|
var freePort = () => new Promise((done, failed) => {
|
|
29069
29236
|
const server = createServer2();
|
|
29070
29237
|
server.once("error", failed);
|
|
@@ -29137,7 +29304,7 @@ var chips = await connect({
|
|
|
29137
29304
|
url: joined.url,
|
|
29138
29305
|
token: joined.token,
|
|
29139
29306
|
client: { name: "chips-hermes", version: VERSION },
|
|
29140
|
-
store: fileStore(
|
|
29307
|
+
store: fileStore(join14(folder, "chips-state.json")),
|
|
29141
29308
|
onRestart: restart,
|
|
29142
29309
|
settings: settingsFor(() => bridge)
|
|
29143
29310
|
});
|
package/package.json
CHANGED