@saleso.innovations/bridge 0.1.42 → 0.1.44

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.
Files changed (58) hide show
  1. package/dist/client.d.ts +2 -0
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +5 -1
  4. package/dist/constants.d.ts +2 -0
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/constants.js +3 -0
  7. package/dist/cronList.d.ts +2 -0
  8. package/dist/cronList.d.ts.map +1 -1
  9. package/dist/cronList.js +11 -8
  10. package/dist/cronWatcher.d.ts +1 -1
  11. package/dist/cronWatcher.d.ts.map +1 -1
  12. package/dist/cronWatcher.js +70 -29
  13. package/dist/ensureHermesApi.d.ts +1 -1
  14. package/dist/ensureHermesApi.d.ts.map +1 -1
  15. package/dist/ensureHermesApi.js +14 -10
  16. package/dist/gatewayControl.d.ts +3 -3
  17. package/dist/gatewayControl.d.ts.map +1 -1
  18. package/dist/gatewayControl.js +58 -24
  19. package/dist/hermesCommands.d.ts +1 -1
  20. package/dist/hermesCommands.d.ts.map +1 -1
  21. package/dist/hermesCommands.js +64 -29
  22. package/dist/hermesFileCommands.d.ts +5 -5
  23. package/dist/hermesFileCommands.d.ts.map +1 -1
  24. package/dist/hermesFileCommands.js +10 -10
  25. package/dist/hermesFiles.d.ts +7 -6
  26. package/dist/hermesFiles.d.ts.map +1 -1
  27. package/dist/hermesFiles.js +11 -14
  28. package/dist/hermesForwarder.d.ts +2 -0
  29. package/dist/hermesForwarder.d.ts.map +1 -1
  30. package/dist/hermesForwarder.js +27 -20
  31. package/dist/hermesSessionDb.d.ts +10 -6
  32. package/dist/hermesSessionDb.d.ts.map +1 -1
  33. package/dist/hermesSessionDb.js +44 -24
  34. package/dist/index.d.ts +3 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +2 -1
  37. package/dist/mcpList.d.ts +3 -2
  38. package/dist/mcpList.d.ts.map +1 -1
  39. package/dist/mcpList.js +5 -5
  40. package/dist/models.d.ts +19 -0
  41. package/dist/models.d.ts.map +1 -0
  42. package/dist/models.js +37 -0
  43. package/dist/profiles.d.ts +70 -0
  44. package/dist/profiles.d.ts.map +1 -0
  45. package/dist/profiles.js +442 -0
  46. package/dist/renameHermesSession.d.ts +1 -1
  47. package/dist/renameHermesSession.d.ts.map +1 -1
  48. package/dist/renameHermesSession.js +2 -2
  49. package/dist/skillLearnedDetector.d.ts +1 -1
  50. package/dist/skillLearnedDetector.d.ts.map +1 -1
  51. package/dist/skillLearnedDetector.js +2 -3
  52. package/dist/skillsList.d.ts +5 -2
  53. package/dist/skillsList.d.ts.map +1 -1
  54. package/dist/skillsList.js +14 -14
  55. package/dist/toolsList.d.ts +2 -2
  56. package/dist/toolsList.d.ts.map +1 -1
  57. package/dist/toolsList.js +4 -4
  58. package/package.json +1 -1
@@ -12,6 +12,8 @@ import { executeShellExec, resetShellSession } from "./shellSession.js";
12
12
  import { fetchHermesRuntimeVersion } from "./runtimeVersion.js";
13
13
  import { fetchBridgeRuntimeVersion, fetchInstalledBridgeVersion } from "./bridgeVersion.js";
14
14
  import { runBridgeUpdate } from "./update.js";
15
+ import { createHermesProfile, deleteHermesProfile, listHermesProfiles, renameHermesProfile, resolveProfileContext, setHermesProfileModel, } from "./profiles.js";
16
+ import { normalizeModelOptions } from "./models.js";
15
17
  import { spawn } from "node:child_process";
16
18
  export const HERMES_COMMAND_NAMES = [
17
19
  "runtime.health",
@@ -34,6 +36,8 @@ export const HERMES_COMMAND_NAMES = [
34
36
  "jobs.delete",
35
37
  "profiles.list",
36
38
  "profiles.create",
39
+ "profiles.rename",
40
+ "profiles.delete",
37
41
  "gateway.start",
38
42
  "gateway.stop",
39
43
  "gateway.restart",
@@ -175,7 +179,11 @@ function scheduleDetachedBridgeRestart() {
175
179
  }
176
180
  }
177
181
  export async function executeHermesCommand(command, args, options = {}) {
178
- const config = resolveHermesApiConfig(options);
182
+ const profileName = optionalString(args, "profile");
183
+ const profileCtx = resolveProfileContext(profileName);
184
+ const config = resolveHermesApiConfig({ ...options, profile: profileCtx.profile });
185
+ const home = profileCtx.home;
186
+ const env = profileCtx.env;
179
187
  const { onDelta } = options;
180
188
  switch (command) {
181
189
  case "runtime.health":
@@ -186,10 +194,25 @@ export async function executeHermesCommand(command, args, options = {}) {
186
194
  return await fetchHermesRuntimeVersion();
187
195
  case "runtime.capabilities":
188
196
  return await hermesFetchJson(config, "/v1/capabilities");
189
- case "models.list":
190
- return await hermesFetchJson(config, "/v1/models");
191
- case "model.set":
192
- throw new HermesCommandError("unsupported_by_http", "Changing the active Hermes model is not exposed over the HTTP API. Update Hermes config on the agent machine.");
197
+ case "models.list": {
198
+ const payload = await hermesFetchJson(config, "/api/model/options");
199
+ return normalizeModelOptions(payload);
200
+ }
201
+ case "model.set": {
202
+ const model = requireString(args, "model");
203
+ const provider = requireString(args, "provider");
204
+ try {
205
+ await hermesFetchJson(config, "/api/model/set", {
206
+ method: "POST",
207
+ headers: { "content-type": "application/json" },
208
+ body: JSON.stringify({ scope: "main", provider, model }),
209
+ });
210
+ return { ok: true, provider, model };
211
+ }
212
+ catch {
213
+ return await setHermesProfileModel(profileCtx.profile, model, provider);
214
+ }
215
+ }
193
216
  case "responses.create": {
194
217
  const input = args.input ?? args.prompt;
195
218
  if (typeof input !== "string" || input.trim().length === 0) {
@@ -256,7 +279,7 @@ export async function executeHermesCommand(command, args, options = {}) {
256
279
  case "jobs.list": {
257
280
  const includeAll = args.all === true || args.includeInactive === true;
258
281
  if (includeAll) {
259
- return await listHermesCronJobs({ all: true });
282
+ return await listHermesCronJobs({ all: true, home, env });
260
283
  }
261
284
  return await hermesFetchJson(config, "/api/jobs");
262
285
  }
@@ -318,15 +341,27 @@ export async function executeHermesCommand(command, args, options = {}) {
318
341
  });
319
342
  }
320
343
  case "profiles.list":
321
- throw new HermesCommandError("unsupported_by_http", "Listing Hermes profiles is not exposed over the HTTP API.");
322
- case "profiles.create":
323
- throw new HermesCommandError("unsupported_by_http", "Creating Hermes profiles is not exposed over the HTTP API. Run `hermes profile create` on the agent machine.");
344
+ return await listHermesProfiles();
345
+ case "profiles.create": {
346
+ const name = requireString(args, "name");
347
+ const clone = args.clone === true;
348
+ return await createHermesProfile(name, { clone });
349
+ }
350
+ case "profiles.rename": {
351
+ const oldName = requireString(args, "oldName");
352
+ const newName = requireString(args, "newName");
353
+ return await renameHermesProfile(oldName, newName);
354
+ }
355
+ case "profiles.delete": {
356
+ const name = requireString(args, "name");
357
+ return await deleteHermesProfile(name);
358
+ }
324
359
  case "gateway.start":
325
- return await startHermesGateway();
360
+ return await startHermesGateway(profileCtx.profile);
326
361
  case "gateway.stop":
327
- return await stopHermesGateway();
362
+ return await stopHermesGateway(profileCtx.profile);
328
363
  case "gateway.restart":
329
- return await restartHermesGateway();
364
+ return await restartHermesGateway(profileCtx.profile);
330
365
  case "hermes.update": {
331
366
  const restartGateway = args.restartGateway === true || args.restart_gateway === true;
332
367
  return await runHermesUpdate({ restartGateway });
@@ -349,57 +384,57 @@ export async function executeHermesCommand(command, args, options = {}) {
349
384
  const limit = optionalNumber(args, "limit");
350
385
  const offset = optionalNumber(args, "offset");
351
386
  const offsetFromEnd = optionalNumber(args, "offsetFromEnd");
352
- return listSessionMessages(sessionId, { limit, offset, offsetFromEnd });
387
+ return listSessionMessages(sessionId, { limit, offset, offsetFromEnd, home });
353
388
  }
354
389
  case "sessions.messages.countSent":
355
- return countUserMessagesSent();
390
+ return countUserMessagesSent(home);
356
391
  case "sessions.titles.resolve": {
357
392
  const sessionIds = optionalStringArray(args, "sessionIds") ?? [];
358
- return { titles: resolveSessionTitles(sessionIds) };
393
+ return { titles: resolveSessionTitles(sessionIds, home) };
359
394
  }
360
395
  case "sessions.rename": {
361
396
  const sessionId = requireString(args, "sessionId");
362
397
  const title = requireString(args, "title");
363
- return await renameHermesSession(sessionId, title);
398
+ return await renameHermesSession(sessionId, title, env);
364
399
  }
365
400
  case "sessions.usage.get": {
366
401
  const sessionId = requireString(args, "sessionId");
367
- return getSessionUsage(sessionId);
402
+ return getSessionUsage(sessionId, home);
368
403
  }
369
404
  case "sessions.list": {
370
405
  const limit = optionalNumber(args, "limit");
371
- return { sessions: listHermesSessions({ limit: limit ?? 200 }) };
406
+ return { sessions: listHermesSessions({ limit: limit ?? 200, home }) };
372
407
  }
373
408
  case "skills.list":
374
- return await listHermesSkills();
409
+ return await listHermesSkills({ home, env });
375
410
  case "tools.list": {
376
411
  const platform = optionalString(args, "platform");
377
- return await listHermesTools(platform);
412
+ return await listHermesTools(platform, env);
378
413
  }
379
414
  case "tools.set": {
380
415
  const name = requireString(args, "name");
381
416
  const enabled = args.enabled === true;
382
- return await setHermesToolEnabled(name, enabled);
417
+ return await setHermesToolEnabled(name, enabled, env);
383
418
  }
384
419
  case "mcp.list":
385
- return await listHermesMcpServers();
420
+ return await listHermesMcpServers(env);
386
421
  case "mcp.add": {
387
422
  const name = optionalString(args, "name");
388
423
  const json = requireString(args, "json");
389
- return await addHermesMcpServer({ name, json });
424
+ return await addHermesMcpServer({ name, json, env });
390
425
  }
391
426
  case "mcp.remove": {
392
427
  const name = requireString(args, "name");
393
- return await removeHermesMcpServer(name);
428
+ return await removeHermesMcpServer(name, env);
394
429
  }
395
430
  case "files.list":
396
- return await executeFilesList(args);
431
+ return await executeFilesList(args, home);
397
432
  case "files.read": {
398
433
  const path = optionalString(args, "path");
399
434
  if (!path) {
400
435
  throw new HermesCommandError("invalid_command_args", 'Missing "path"');
401
436
  }
402
- return await executeFilesRead({ ...args, path });
437
+ return await executeFilesRead({ ...args, path }, home);
403
438
  }
404
439
  case "files.write": {
405
440
  const path = optionalString(args, "path");
@@ -410,17 +445,17 @@ export async function executeHermesCommand(command, args, options = {}) {
410
445
  if (typeof content !== "string") {
411
446
  throw new HermesCommandError("invalid_command_args", 'Missing "content"');
412
447
  }
413
- return await executeFilesWrite({ path, content });
448
+ return await executeFilesWrite({ path, content }, home);
414
449
  }
415
450
  case "files.delete": {
416
451
  const path = optionalString(args, "path");
417
452
  if (!path) {
418
453
  throw new HermesCommandError("invalid_command_args", 'Missing "path"');
419
454
  }
420
- return await executeFilesDelete({ path });
455
+ return await executeFilesDelete({ path }, home);
421
456
  }
422
457
  case "memories.list":
423
- return await executeMemoriesList();
458
+ return await executeMemoriesList(home);
424
459
  case "shell.exec": {
425
460
  if (!onDelta) {
426
461
  throw new HermesCommandError("invalid_command_args", "shell.exec requires streaming support");
@@ -1,19 +1,19 @@
1
- export declare function executeFilesList(args: Record<string, unknown>): Promise<{
1
+ export declare function executeFilesList(args: Record<string, unknown>, home?: string): Promise<{
2
2
  files: import("./hermesFiles.js").HermesFileEntry[];
3
3
  }>;
4
- export declare function executeFilesWrite(args: Record<string, unknown>): Promise<{
4
+ export declare function executeFilesWrite(args: Record<string, unknown>, home?: string): Promise<{
5
5
  ok: true;
6
6
  relativePath: string;
7
7
  size: number;
8
8
  }>;
9
- export declare function executeFilesDelete(args: Record<string, unknown>): Promise<{
9
+ export declare function executeFilesDelete(args: Record<string, unknown>, home?: string): Promise<{
10
10
  ok: true;
11
11
  deletedPath: string;
12
12
  }>;
13
- export declare function executeMemoriesList(): Promise<{
13
+ export declare function executeMemoriesList(home?: string): Promise<{
14
14
  files: import("./hermesFiles.js").HermesFileEntry[];
15
15
  }>;
16
- export declare function executeFilesRead(args: Record<string, unknown>): Promise<{
16
+ export declare function executeFilesRead(args: Record<string, unknown>, home?: string): Promise<{
17
17
  fileName: string;
18
18
  mimeType: string;
19
19
  size: number;
@@ -1 +1 @@
1
- {"version":3,"file":"hermesFileCommands.d.ts","sourceRoot":"","sources":["../src/hermesFileCommands.ts"],"names":[],"mappings":"AAgCA,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;GAKnE;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;GAUpE;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;GAMrE;AAED,wBAAsB,mBAAmB;;GAExC;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;;;GAkCnE"}
1
+ {"version":3,"file":"hermesFileCommands.d.ts","sourceRoot":"","sources":["../src/hermesFileCommands.ts"],"names":[],"mappings":"AAgCA,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM;;GAKlF;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM;;;;GAUnF;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM;;;GAMpF;AAED,wBAAsB,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM;;GAEtD;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM;;;;;;;;;;;;;;GAkClF"}
@@ -22,13 +22,13 @@ function optionalCategory(args) {
22
22
  }
23
23
  return "all";
24
24
  }
25
- export async function executeFilesList(args) {
25
+ export async function executeFilesList(args, home) {
26
26
  const limit = optionalNumber(args, "limit");
27
27
  const offset = optionalNumber(args, "offset");
28
28
  const category = optionalCategory(args);
29
- return listHermesFiles({ limit, offset, category });
29
+ return listHermesFiles({ limit, offset, category, home });
30
30
  }
31
- export async function executeFilesWrite(args) {
31
+ export async function executeFilesWrite(args, home) {
32
32
  const path = typeof args.path === "string" ? args.path.trim() : "";
33
33
  if (!path) {
34
34
  throw new Error('Missing "path"');
@@ -37,22 +37,22 @@ export async function executeFilesWrite(args) {
37
37
  if (content === undefined) {
38
38
  throw new Error('Missing "content"');
39
39
  }
40
- return writeHermesFile(path, content);
40
+ return writeHermesFile(path, content, home);
41
41
  }
42
- export async function executeFilesDelete(args) {
42
+ export async function executeFilesDelete(args, home) {
43
43
  const path = typeof args.path === "string" ? args.path.trim() : "";
44
44
  if (!path) {
45
45
  throw new Error('Missing "path"');
46
46
  }
47
- return deleteHermesFile(path);
47
+ return deleteHermesFile(path, home);
48
48
  }
49
- export async function executeMemoriesList() {
50
- return listHermesMemoryFiles();
49
+ export async function executeMemoriesList(home) {
50
+ return listHermesMemoryFiles(home);
51
51
  }
52
- export async function executeFilesRead(args) {
52
+ export async function executeFilesRead(args, home) {
53
53
  const path = typeof args.path === "string" ? args.path.trim() : "";
54
54
  const maxBytes = optionalNumber(args, "maxBytes") ?? DEFAULT_FILES_READ_MAX_BYTES;
55
- const { bytes, mimeType, fileName, size } = readHermesFileBytes(path);
55
+ const { bytes, mimeType, fileName, size } = readHermesFileBytes(path, home);
56
56
  if (size <= maxBytes) {
57
57
  return {
58
58
  fileName,
@@ -43,30 +43,31 @@ export type MediaReference = {
43
43
  export declare function resolveHermesHome(): string;
44
44
  export declare function inferMimeType(fileName: string): string;
45
45
  export declare function inferCategory(fileName: string): HermesFileCategory;
46
- export declare function resolveSandboxedPath(inputPath: string): string;
46
+ export declare function resolveSandboxedPath(inputPath: string, home?: string): string;
47
47
  export declare function listHermesFiles(options?: {
48
48
  limit?: number;
49
49
  offset?: number;
50
50
  category?: HermesFileCategory | "all";
51
+ home?: string;
51
52
  }): {
52
53
  files: HermesFileEntry[];
53
54
  };
54
55
  export declare function normalizeHermesRelativePath(inputPath: string): string;
55
56
  export declare function isWritableSkillPath(relativePath: string): boolean;
56
57
  export declare function assertWritableHermesPath(inputPath: string): string;
57
- export declare function writeHermesFile(inputPath: string, content: string): {
58
+ export declare function writeHermesFile(inputPath: string, content: string, home?: string): {
58
59
  ok: true;
59
60
  relativePath: string;
60
61
  size: number;
61
62
  };
62
- export declare function deleteHermesFile(inputPath: string): {
63
+ export declare function deleteHermesFile(inputPath: string, home?: string): {
63
64
  ok: true;
64
65
  deletedPath: string;
65
66
  };
66
- export declare function listHermesMemoryFiles(): {
67
+ export declare function listHermesMemoryFiles(home?: string): {
67
68
  files: HermesFileEntry[];
68
69
  };
69
- export declare function readHermesFileBytes(inputPath: string): {
70
+ export declare function readHermesFileBytes(inputPath: string, home?: string): {
70
71
  bytes: Buffer;
71
72
  mimeType: string;
72
73
  fileName: string;
@@ -80,7 +81,7 @@ export declare function downloadUrlToBytes(url: string, timeoutMs?: number): Pro
80
81
  fileName: string;
81
82
  size: number;
82
83
  }>;
83
- export declare function resolveMediaReferenceBytes(ref: MediaReference): Promise<{
84
+ export declare function resolveMediaReferenceBytes(ref: MediaReference, home?: string): Promise<{
84
85
  bytes: Buffer;
85
86
  mimeType: string;
86
87
  fileName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"hermesFiles.d.ts","sourceRoot":"","sources":["../src/hermesFiles.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,sBAAsB,QAAmB,CAAC;AACvD,eAAO,MAAM,4BAA4B,QAAa,CAAC;AAEvD,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAC5C,eAAO,MAAM,YAAY,aAAa,CAAC;AACvC,eAAO,MAAM,UAAU,WAAW,CAAC;AACnC,eAAO,MAAM,eAAe,aAAa,CAAC;AAC1C,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AAC5D,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD,eAAO,MAAM,oBAAoB,OAAO,CAAC;AACzC,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAkCvC,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;AAC1E,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEnD,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAIF,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI5E;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiCtD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAMlE;AAqCD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAc9D;AA4FD,wBAAgB,eAAe,CAAC,OAAO,GAAE;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,kBAAkB,GAAG,KAAK,CAAC;CAClC,GAAG;IAAE,KAAK,EAAE,eAAe,EAAE,CAAA;CAAE,CAgBpC;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAQjE;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA4BlE;AAQD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAoBlD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAerF;AA6BD,wBAAgB,qBAAqB,IAAI;IAAE,KAAK,EAAE,eAAe,EAAE,CAAA;CAAE,CAqBpE;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAe1H;AAMD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CA6BnE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,MAAM,CAMjF;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAqBtJ;AAED,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CASzJ"}
1
+ {"version":3,"file":"hermesFiles.d.ts","sourceRoot":"","sources":["../src/hermesFiles.ts"],"names":[],"mappings":"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"}
@@ -131,8 +131,7 @@ function isPathInsideRoot(root, candidate) {
131
131
  const { root: normalizedRoot, candidate: normalizedCandidate } = normalizePathForSandbox(root, candidate);
132
132
  return normalizedCandidate === normalizedRoot || normalizedCandidate.startsWith(`${normalizedRoot}${sep}`);
133
133
  }
134
- export function resolveSandboxedPath(inputPath) {
135
- const home = resolveHermesHome();
134
+ export function resolveSandboxedPath(inputPath, home = resolveHermesHome()) {
136
135
  const candidate = inputPath.startsWith("/") ? resolve(inputPath) : resolve(home, inputPath);
137
136
  if (!isPathInsideRoot(home, candidate)) {
138
137
  throw new Error(`Path is outside Hermes home: ${inputPath}`);
@@ -227,7 +226,7 @@ function walkFiles(rootDir, home, files, jobNames) {
227
226
  }
228
227
  }
229
228
  export function listHermesFiles(options = {}) {
230
- const home = resolveHermesHome();
229
+ const home = options.home ?? resolveHermesHome();
231
230
  const limit = options.limit ?? 200;
232
231
  const offset = options.offset ?? 0;
233
232
  const category = options.category ?? "all";
@@ -283,14 +282,13 @@ function memoryCharLimitForPath(relativePath) {
283
282
  return USER_MD_CHAR_LIMIT;
284
283
  return undefined;
285
284
  }
286
- export function writeHermesFile(inputPath, content) {
285
+ export function writeHermesFile(inputPath, content, home = resolveHermesHome()) {
287
286
  const relativePath = assertWritableHermesPath(inputPath);
288
287
  const charLimit = memoryCharLimitForPath(relativePath);
289
288
  if (charLimit !== undefined && content.length > charLimit) {
290
289
  throw new Error(`Content exceeds ${charLimit} character limit for ${relativePath} (${content.length} chars)`);
291
290
  }
292
- const home = resolveHermesHome();
293
- const resolved = resolveSandboxedPath(relativePath);
291
+ const resolved = resolveSandboxedPath(relativePath, home);
294
292
  if (relativePath.startsWith(`${SKILLS_DIR}/`)) {
295
293
  mkdirSync(dirname(resolved), { recursive: true });
296
294
  }
@@ -301,12 +299,12 @@ export function writeHermesFile(inputPath, content) {
301
299
  writeFileSync(resolved, bytes);
302
300
  return { ok: true, relativePath, size: bytes.length };
303
301
  }
304
- export function deleteHermesFile(inputPath) {
302
+ export function deleteHermesFile(inputPath, home = resolveHermesHome()) {
305
303
  const relativePath = normalizeHermesRelativePath(inputPath);
306
304
  if (!isWritableSkillPath(relativePath)) {
307
305
  throw new Error(`Path is not deletable: ${inputPath}`);
308
306
  }
309
- const resolved = resolveSandboxedPath(relativePath);
307
+ const resolved = resolveSandboxedPath(relativePath, home);
310
308
  if (!existsSync(resolved)) {
311
309
  throw new Error(`File not found: ${inputPath}`);
312
310
  }
@@ -342,8 +340,7 @@ function memoryFileEntry(home, fileName) {
342
340
  source: "artifact",
343
341
  };
344
342
  }
345
- export function listHermesMemoryFiles() {
346
- const home = resolveHermesHome();
343
+ export function listHermesMemoryFiles(home = resolveHermesHome()) {
347
344
  const memoriesRoot = join(home, MEMORIES_DIR);
348
345
  const discovered = new Set(KNOWN_MEMORY_FILES);
349
346
  if (existsSync(memoriesRoot)) {
@@ -363,8 +360,8 @@ export function listHermesMemoryFiles() {
363
360
  .map((fileName) => memoryFileEntry(home, fileName));
364
361
  return { files };
365
362
  }
366
- export function readHermesFileBytes(inputPath) {
367
- const resolved = resolveSandboxedPath(inputPath);
363
+ export function readHermesFileBytes(inputPath, home = resolveHermesHome()) {
364
+ const resolved = resolveSandboxedPath(inputPath, home);
368
365
  if (!existsSync(resolved)) {
369
366
  throw new Error(`File not found: ${inputPath}`);
370
367
  }
@@ -441,10 +438,10 @@ export async function downloadUrlToBytes(url, timeoutMs = 30_000) {
441
438
  clearTimeout(timer);
442
439
  }
443
440
  }
444
- export async function resolveMediaReferenceBytes(ref) {
441
+ export async function resolveMediaReferenceBytes(ref, home = resolveHermesHome()) {
445
442
  try {
446
443
  if (ref.kind === "local") {
447
- return readHermesFileBytes(ref.absolutePath);
444
+ return readHermesFileBytes(ref.absolutePath, home);
448
445
  }
449
446
  return await downloadUrlToBytes(ref.url);
450
447
  }
@@ -4,6 +4,7 @@ export type HermesForwarderOptions = {
4
4
  apiKey?: string;
5
5
  model?: string;
6
6
  conversationId?: string;
7
+ profile?: string;
7
8
  };
8
9
  export type HermesForwardResult = {
9
10
  sessionId: string;
@@ -12,6 +13,7 @@ export declare function resolveHermesApiConfig(options?: HermesForwarderOptions)
12
13
  apiUrl: string;
13
14
  apiKey: string | undefined;
14
15
  model: string;
16
+ home: string;
15
17
  };
16
18
  export declare function forwardToHermes(content: string, meta: UserMessageMeta, reply: AgentReply, options?: HermesForwarderOptions): Promise<HermesForwardResult>;
17
19
  export declare function createHermesMessageHandler(options?: HermesForwarderOptions): (content: string, meta: UserMessageMeta, reply: AgentReply) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"hermesForwarder.d.ts","sourceRoot":"","sources":["../src/hermesForwarder.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAyB,eAAe,EAAE,MAAM,aAAa,CAAC;AAuBtF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAkBF,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,sBAA2B,GAAG;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf,CAUA;AAgID,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,CA0G9B;AA2BD,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,sBAA2B,IAC/D,SAAS,MAAM,EAAE,MAAM,eAAe,EAAE,OAAO,UAAU,KAAG,OAAO,CAAC,IAAI,CAAC,CAMxF"}
1
+ {"version":3,"file":"hermesForwarder.d.ts","sourceRoot":"","sources":["../src/hermesForwarder.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAyB,eAAe,EAAE,MAAM,aAAa,CAAC;AAuBtF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAkBF,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,sBAA2B,GAAG;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAaA;AAiID,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,CA6G9B;AA4BD,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,sBAA2B,IAC/D,SAAS,MAAM,EAAE,MAAM,eAAe,EAAE,OAAO,UAAU,KAAG,OAAO,CAAC,IAAI,CAAC,CAOxF"}
@@ -2,14 +2,14 @@ import { readFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { linkHermesMessageIds, uploadFileToConvex } from "./convexRelay.js";
5
- import { DEFAULT_HERMES_API_URL } from "./constants.js";
6
5
  import { getLatestTurnMessageIds, getSessionUsage, hermesStateDbExists } from "./hermesSessionDb.js";
7
6
  import { diffSkillsLearned, snapshotSkills } from "./skillLearnedDetector.js";
8
7
  import { buildTurnActivity, createTurnActivityAccumulator, parseSseDataLines, processSseEventBlock, } from "./turnActivity.js";
9
8
  import { parseMediaReferences, resolveMediaReferenceBytes, stripMediaReferences, } from "./hermesFiles.js";
10
9
  import { looksLikeHermesStructuredStream, unwrapHermesStructuredContent, } from "./hermesStructuredContent.js";
11
- function readHermesApiKeyFromEnvFile() {
12
- const envPath = join(homedir(), ".hermes", ".env");
10
+ import { resolveProfileContext } from "./profiles.js";
11
+ function readHermesApiKeyFromEnvFile(home) {
12
+ const envPath = join(home?.trim() || join(homedir(), ".hermes"), ".env");
13
13
  try {
14
14
  const contents = readFileSync(envPath, "utf8");
15
15
  for (const line of contents.split("\n")) {
@@ -27,13 +27,16 @@ function readHermesApiKeyFromEnvFile() {
27
27
  return undefined;
28
28
  }
29
29
  export function resolveHermesApiConfig(options = {}) {
30
+ const ctx = resolveProfileContext(options.profile);
30
31
  return {
31
- apiUrl: options.apiUrl?.trim() || process.env.HERMES_API_URL?.trim() || DEFAULT_HERMES_API_URL,
32
+ apiUrl: options.apiUrl?.trim() || ctx.apiUrl,
32
33
  apiKey: options.apiKey?.trim() ||
34
+ ctx.apiKey ||
33
35
  process.env.HERMES_API_KEY?.trim() ||
34
36
  process.env.API_SERVER_KEY?.trim() ||
35
- readHermesApiKeyFromEnvFile(),
37
+ readHermesApiKeyFromEnvFile(ctx.home),
36
38
  model: options.model?.trim() || process.env.HERMES_MODEL?.trim() || "hermes-agent",
39
+ home: ctx.home,
37
40
  };
38
41
  }
39
42
  async function ensureHermesReachable(apiUrl, apiKey) {
@@ -78,10 +81,10 @@ function buildHermesUserContent(text, attachments) {
78
81
  parts.push(...imageParts);
79
82
  return parts;
80
83
  }
81
- async function uploadMediaAttachments(agentId, refs) {
84
+ async function uploadMediaAttachments(agentId, refs, home) {
82
85
  const attachments = [];
83
86
  for (const ref of refs) {
84
- const resolved = await resolveMediaReferenceBytes(ref);
87
+ const resolved = await resolveMediaReferenceBytes(ref, home);
85
88
  if (!resolved)
86
89
  continue;
87
90
  try {
@@ -106,10 +109,10 @@ async function uploadMediaAttachments(agentId, refs) {
106
109
  }
107
110
  return attachments;
108
111
  }
109
- async function linkTurnToConvex(meta, sessionId) {
110
- if (!hermesStateDbExists())
112
+ async function linkTurnToConvex(meta, sessionId, home) {
113
+ if (!hermesStateDbExists(home))
111
114
  return;
112
- const { userMessageId, assistantMessageId } = getLatestTurnMessageIds(sessionId);
115
+ const { userMessageId, assistantMessageId } = getLatestTurnMessageIds(sessionId, home);
113
116
  const links = [];
114
117
  if (userMessageId !== undefined) {
115
118
  links.push({
@@ -145,7 +148,10 @@ async function linkTurnToConvex(meta, sessionId) {
145
148
  }
146
149
  }
147
150
  export async function forwardToHermes(content, meta, reply, options = {}) {
148
- const { apiUrl, apiKey, model } = resolveHermesApiConfig(options);
151
+ const { apiUrl, apiKey, model, home } = resolveHermesApiConfig({
152
+ ...options,
153
+ profile: options.profile ?? meta.profile,
154
+ });
149
155
  await ensureHermesReachable(apiUrl, apiKey);
150
156
  const sessionId = options.conversationId ?? meta.conversationId;
151
157
  const headers = {
@@ -163,7 +169,7 @@ export async function forwardToHermes(content, meta, reply, options = {}) {
163
169
  user: sessionId,
164
170
  };
165
171
  const turnStartedAt = Date.now();
166
- const skillsBefore = snapshotSkills();
172
+ const skillsBefore = snapshotSkills(home);
167
173
  const response = await fetch(apiUrl, {
168
174
  method: "POST",
169
175
  headers,
@@ -219,18 +225,18 @@ export async function forwardToHermes(content, meta, reply, options = {}) {
219
225
  }
220
226
  }
221
227
  const mediaRefs = parseMediaReferences(fullText);
222
- const attachments = mediaRefs.length > 0 ? await uploadMediaAttachments(meta.agentId, mediaRefs) : [];
228
+ const attachments = mediaRefs.length > 0 ? await uploadMediaAttachments(meta.agentId, mediaRefs, home) : [];
223
229
  const rawDisplayText = attachments.length > 0 ? stripMediaReferences(fullText, mediaRefs) : fullText.trim() || fullText;
224
230
  const displayText = unwrapHermesStructuredContent(rawDisplayText);
225
- const { assistantMessageId } = getLatestTurnMessageIds(resolvedSessionId);
226
- const replyModel = resolveReplyModel(modelFromHeader, resolvedSessionId, model);
231
+ const { assistantMessageId } = getLatestTurnMessageIds(resolvedSessionId, home);
232
+ const replyModel = resolveReplyModel(modelFromHeader, resolvedSessionId, model, home);
227
233
  const turnActivity = buildTurnActivity(accumulator, replyModel);
228
- const skillsLearned = diffSkillsLearned(skillsBefore, snapshotSkills(), { turnStartedAt });
234
+ const skillsLearned = diffSkillsLearned(skillsBefore, snapshotSkills(home), { turnStartedAt });
229
235
  if (skillsLearned.length > 0) {
230
236
  turnActivity.skillsLearned = skillsLearned;
231
237
  }
232
238
  reply.complete(displayText, counters.textSequence, attachments.length > 0 ? attachments : undefined, assistantMessageId !== undefined ? String(assistantMessageId) : undefined, turnActivity);
233
- await linkTurnToConvex(meta, resolvedSessionId);
239
+ await linkTurnToConvex(meta, resolvedSessionId, home);
234
240
  return { sessionId: resolvedSessionId };
235
241
  }
236
242
  /**
@@ -239,12 +245,12 @@ export async function forwardToHermes(content, meta, reply, options = {}) {
239
245
  * 2. The session's recorded model in Hermes `state.db`.
240
246
  * 3. The model from the outbound request (skipping the generic placeholder alias).
241
247
  */
242
- function resolveReplyModel(modelFromHeader, resolvedSessionId, requestModel) {
248
+ function resolveReplyModel(modelFromHeader, resolvedSessionId, requestModel, home) {
243
249
  if (modelFromHeader)
244
250
  return modelFromHeader;
245
- if (hermesStateDbExists()) {
251
+ if (hermesStateDbExists(home)) {
246
252
  try {
247
- const usage = getSessionUsage(resolvedSessionId);
253
+ const usage = getSessionUsage(resolvedSessionId, home);
248
254
  if (usage.model)
249
255
  return usage.model;
250
256
  }
@@ -259,6 +265,7 @@ export function createHermesMessageHandler(options = {}) {
259
265
  await forwardToHermes(content, meta, reply, {
260
266
  ...options,
261
267
  conversationId: meta.conversationId,
268
+ profile: options.profile ?? meta.profile,
262
269
  });
263
270
  };
264
271
  }
@@ -5,14 +5,15 @@ export type HermesSessionMessage = {
5
5
  content: string;
6
6
  timestamp: number;
7
7
  };
8
- export declare function resolveSessionTitle(sessionId: string): string | null;
9
- export declare function resolveSessionTitles(sessionIds: string[]): Record<string, string | null>;
8
+ export declare function resolveSessionTitle(sessionId: string, home?: string): string | null;
9
+ export declare function resolveSessionTitles(sessionIds: string[], home?: string): Record<string, string | null>;
10
10
  export declare function listSessionMessages(sessionId: string, options?: {
11
11
  limit?: number;
12
12
  offset?: number;
13
13
  offsetFromEnd?: number;
14
+ home?: string;
14
15
  }): HermesSessionMessage[];
15
- export declare function getLatestTurnMessageIds(sessionId: string): {
16
+ export declare function getLatestTurnMessageIds(sessionId: string, home?: string): {
16
17
  userMessageId?: number;
17
18
  assistantMessageId?: number;
18
19
  };
@@ -28,6 +29,7 @@ export type HermesSessionListEntry = {
28
29
  export declare function isAutomatedHermesSessionPrompt(content: string): boolean;
29
30
  export declare function listHermesSessions(options?: {
30
31
  limit?: number;
32
+ home?: string;
31
33
  }): HermesSessionListEntry[];
32
34
  export type HermesSessionUsage = {
33
35
  sessionId: string;
@@ -41,9 +43,11 @@ export type HermesSessionUsage = {
41
43
  estimatedCostUsd: number | null;
42
44
  messageCount: number;
43
45
  };
44
- export declare function getSessionUsage(sessionId: string): HermesSessionUsage;
45
- export declare function hermesStateDbExists(): boolean;
46
- export declare function countUserMessagesSent(): {
46
+ export declare function getSessionUsage(sessionId: string, home?: string): HermesSessionUsage;
47
+ export declare function hermesStateDbExists(home?: string): boolean;
48
+ export declare function countUserMessagesSent(home?: string): {
47
49
  count: number;
48
50
  };
51
+ /** Total number of sessions in a profile's state.db (best-effort). */
52
+ export declare function countSessions(home?: string): number;
49
53
  //# sourceMappingURL=hermesSessionDb.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hermesSessionDb.d.ts","sourceRoot":"","sources":["../src/hermesSessionDb.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AA4IF,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAapE;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAuBxF;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACxE,oBAAoB,EAAE,CAwCxB;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,GAChB;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,CAmCzD;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAMF,mFAAmF;AACnF,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAqBvE;AAcD,wBAAgB,kBAAkB,CAAC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,sBAAsB,EAAE,CAsE7F;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAiBF,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,CAkErE;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C;AAED,wBAAgB,qBAAqB,IAAI;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAgBzD"}
1
+ {"version":3,"file":"hermesSessionDb.d.ts","sourceRoot":"","sources":["../src/hermesSessionDb.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAgJF,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAanF;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAuBvG;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GACvF,oBAAoB,EAAE,CAwCxB;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,CAmCzD;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAMF,mFAAmF;AACnF,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAqBvE;AAcD,wBAAgB,kBAAkB,CAAC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,sBAAsB,EAAE,CAsE5G;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAiBF,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAkEpF;AAED,wBAAgB,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAO1D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAgBtE;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAgBnD"}