@hermespilot/link 0.3.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ ConversationService,
3
4
  LINK_COMMAND,
4
5
  LINK_VERSION,
5
6
  LinkHttpError,
6
7
  clearPairingClaim,
8
+ createFileLogger,
7
9
  currentCliScriptPath,
8
10
  daemonLogFile,
9
11
  detectRuntimeEnvironment,
@@ -30,7 +32,7 @@ import {
30
32
  startDaemonProcess,
31
33
  startLinkService,
32
34
  stopDaemonProcess
33
- } from "../chunk-IJTQ6YVR.js";
35
+ } from "../chunk-ZQO7TU7G.js";
34
36
 
35
37
  // src/cli/index.ts
36
38
  import { Command } from "commander";
@@ -242,6 +244,9 @@ var messages = {
242
244
  "stop.stopped": "Hermes Link stopped.",
243
245
  "stop.notRunning": "Hermes Link is not running.",
244
246
  "restart.description": "Restart the background Hermes Link daemon",
247
+ "deliver.description": "Import files from a Hermes Link delivery staging directory",
248
+ "deliver.imported": "Delivered {count} file(s) to conversation {conversationId}.",
249
+ "deliver.none": "No new files were delivered for conversation {conversationId}.",
245
250
  "config.description": "Manage local Hermes Link configuration",
246
251
  "config.set.description": "Set a configuration value",
247
252
  "config.unset.description": "Unset a configuration value",
@@ -329,6 +334,9 @@ var messages = {
329
334
  "stop.stopped": "Hermes Link \u5DF2\u505C\u6B62\u3002",
330
335
  "stop.notRunning": "Hermes Link \u6CA1\u6709\u5728\u8FD0\u884C\u3002",
331
336
  "restart.description": "\u91CD\u542F\u540E\u53F0 Hermes Link \u670D\u52A1",
337
+ "deliver.description": "\u5BFC\u5165 Hermes Link \u4EA4\u4ED8\u4E2D\u8F6C\u76EE\u5F55\u4E2D\u7684\u6587\u4EF6",
338
+ "deliver.imported": "\u5DF2\u5411\u4F1A\u8BDD {conversationId} \u4EA4\u4ED8 {count} \u4E2A\u6587\u4EF6\u3002",
339
+ "deliver.none": "\u4F1A\u8BDD {conversationId} \u6CA1\u6709\u65B0\u7684\u53EF\u4EA4\u4ED8\u6587\u4EF6\u3002",
332
340
  "config.description": "\u7BA1\u7406\u672C\u673A Hermes Link \u914D\u7F6E",
333
341
  "config.set.description": "\u8BBE\u7F6E\u914D\u7F6E\u9879",
334
342
  "config.unset.description": "\u6E05\u9664\u914D\u7F6E\u9879",
@@ -736,6 +744,20 @@ program.command("restart").description(helpText("restart.description")).action(a
736
744
  const status = await startDaemonProcess();
737
745
  console.log(t("start.backgroundStarted", { pid: status.pid ?? "unknown" }));
738
746
  });
747
+ program.command("deliver").argument("<staging-dir>").description(helpText("deliver.description")).action(async (stagingDir) => {
748
+ const paths = resolveRuntimePaths();
749
+ const config = await loadConfig(paths);
750
+ const language = resolveLanguage(config.language);
751
+ const t = translate.bind(null, language);
752
+ const result = await deliverStagedFilesFromCli(stagingDir, paths, config);
753
+ const key = result.imported_count > 0 ? "deliver.imported" : "deliver.none";
754
+ console.log(
755
+ t(key, {
756
+ count: result.imported_count,
757
+ conversationId: result.conversation_id
758
+ })
759
+ );
760
+ });
739
761
  program.command("daemon").option("--foreground", "run in foreground").description(helpText("daemon.description")).action(async () => {
740
762
  const config = await loadConfig();
741
763
  const language = resolveLanguage(config.language);
@@ -917,6 +939,44 @@ async function loadCliLanguage() {
917
939
  const config = await loadConfig();
918
940
  return resolveLanguage(config.language);
919
941
  }
942
+ async function deliverStagedFilesFromCli(stagingDir, paths, config) {
943
+ try {
944
+ return await deliverStagedFilesThroughDaemon(stagingDir, config.port);
945
+ } catch (error) {
946
+ if (!isFetchNetworkError(error)) {
947
+ throw error;
948
+ }
949
+ }
950
+ const logger = createFileLogger({ paths });
951
+ try {
952
+ const conversations = new ConversationService(paths, logger);
953
+ return await conversations.deliverStagedFiles(stagingDir);
954
+ } finally {
955
+ await logger.flush();
956
+ }
957
+ }
958
+ async function deliverStagedFilesThroughDaemon(stagingDir, port) {
959
+ const response = await fetch(`http://127.0.0.1:${port}/internal/deliver`, {
960
+ method: "POST",
961
+ headers: { "content-type": "application/json" },
962
+ body: JSON.stringify({ staging_dir: stagingDir })
963
+ });
964
+ if (!response.ok) {
965
+ throw new Error(await readResponseError(response));
966
+ }
967
+ const body = await response.json();
968
+ if (body.ok !== true) {
969
+ throw new Error("Hermes Link delivery import failed");
970
+ }
971
+ return body;
972
+ }
973
+ async function readResponseError(response) {
974
+ const body = await response.json().catch(() => null);
975
+ return body?.error?.message ?? body?.message ?? `Hermes Link delivery import failed with HTTP ${response.status}`;
976
+ }
977
+ function isFetchNetworkError(error) {
978
+ return error instanceof TypeError;
979
+ }
920
980
  async function resolvePairingLanguage(paths, config) {
921
981
  if (config.language !== "auto") {
922
982
  return { config, language: resolveLanguage(config.language) };
@@ -321,6 +321,34 @@ interface CancelRunResult {
321
321
  }
322
322
  type ConversationEventListener = (event: ConversationEvent) => void;
323
323
 
324
+ interface HermesSessionSyncResult {
325
+ scanned_profiles: number;
326
+ scanned_sessions: number;
327
+ eligible_sessions: number;
328
+ imported_count: number;
329
+ reprojected_count: number;
330
+ skipped_existing: number;
331
+ skipped_hidden: number;
332
+ skipped_deleted: number;
333
+ skipped_over_limit: number;
334
+ errors: Array<{
335
+ profile: string;
336
+ message: string;
337
+ }>;
338
+ }
339
+
340
+ interface ImportMediaReferencesResult {
341
+ conversation_id: string;
342
+ run_id: string;
343
+ message_id: string;
344
+ discovered_count: number;
345
+ imported_count: number;
346
+ skipped_count: number;
347
+ failed_count: number;
348
+ parts: LinkMessagePart[];
349
+ last_event_seq?: number;
350
+ }
351
+
324
352
  declare class ConversationService {
325
353
  private readonly paths;
326
354
  private readonly logger;
@@ -334,6 +362,7 @@ declare class ConversationService {
334
362
  private readonly orchestration;
335
363
  private readonly queries;
336
364
  private readonly runLifecycle;
365
+ private hermesSessionSyncPromise;
337
366
  constructor(paths: RuntimePaths, logger: FileLogger);
338
367
  private withConversationLock;
339
368
  listConversations(): Promise<ConversationSummary[]>;
@@ -356,6 +385,8 @@ declare class ConversationService {
356
385
  runAt?: string;
357
386
  }): Promise<void>;
358
387
  syncCronDeliveries(): Promise<void>;
388
+ syncHermesSessions(): Promise<HermesSessionSyncResult>;
389
+ deliverStagedFiles(stagingDir: string): Promise<ImportMediaReferencesResult>;
359
390
  getMessages(conversationId: string, options?: ConversationMessagesPageOptions): Promise<{
360
391
  messages: LinkMessage[];
361
392
  last_event_seq: number;
package/dist/http/app.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createApp
3
- } from "../chunk-IJTQ6YVR.js";
3
+ } from "../chunk-ZQO7TU7G.js";
4
4
  export {
5
5
  createApp
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hermespilot/link",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "private": false,
5
5
  "description": "Hermes Link companion service and CLI for connecting hermes-agent through HermesPilot",
6
6
  "license": "MIT",