happy-coder 0.9.0 → 0.10.0-0

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/lib.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var types = require('./types-CyOnnZ8M.cjs');
3
+ var types = require('./types-fU2E-jQl.cjs');
4
4
  require('axios');
5
5
  require('chalk');
6
6
  require('fs');
package/dist/lib.d.cts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { z } from 'zod';
2
2
  import { EventEmitter } from 'node:events';
3
- import { ChildProcess } from 'child_process';
4
3
  import { ExpoPushMessage } from 'expo-server-sdk';
5
4
 
6
5
  /**
@@ -379,6 +378,12 @@ declare const SessionSchema: z.ZodObject<{
379
378
  metadataVersion: z.ZodNumber;
380
379
  agentState: z.ZodNullable<z.ZodAny>;
381
380
  agentStateVersion: z.ZodNumber;
381
+ connectivityStatus: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["neverConnected", "online", "offline"]>, z.ZodString]>>;
382
+ connectivityStatusSince: z.ZodOptional<z.ZodNumber>;
383
+ connectivityStatusReason: z.ZodOptional<z.ZodString>;
384
+ state: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["running", "archiveRequested", "archived"]>, z.ZodString]>>;
385
+ stateSince: z.ZodOptional<z.ZodNumber>;
386
+ stateReason: z.ZodOptional<z.ZodString>;
382
387
  }, "strip", z.ZodTypeAny, {
383
388
  id: string;
384
389
  seq: number;
@@ -388,6 +393,12 @@ declare const SessionSchema: z.ZodObject<{
388
393
  agentStateVersion: number;
389
394
  metadata?: any;
390
395
  agentState?: any;
396
+ connectivityStatus?: string | undefined;
397
+ connectivityStatusSince?: number | undefined;
398
+ connectivityStatusReason?: string | undefined;
399
+ state?: string | undefined;
400
+ stateSince?: number | undefined;
401
+ stateReason?: string | undefined;
391
402
  }, {
392
403
  id: string;
393
404
  seq: number;
@@ -397,6 +408,12 @@ declare const SessionSchema: z.ZodObject<{
397
408
  agentStateVersion: number;
398
409
  metadata?: any;
399
410
  agentState?: any;
411
+ connectivityStatus?: string | undefined;
412
+ connectivityStatusSince?: number | undefined;
413
+ connectivityStatusReason?: string | undefined;
414
+ state?: string | undefined;
415
+ stateSince?: number | undefined;
416
+ stateReason?: string | undefined;
400
417
  }>;
401
418
  type Session = z.infer<typeof SessionSchema>;
402
419
  /**
@@ -461,6 +478,12 @@ declare const MachineSchema: z.ZodObject<{
461
478
  activeAt: z.ZodNumber;
462
479
  createdAt: z.ZodNumber;
463
480
  updatedAt: z.ZodNumber;
481
+ connectivityStatus: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["neverConnected", "online", "offline"]>, z.ZodString]>>;
482
+ connectivityStatusSince: z.ZodOptional<z.ZodNumber>;
483
+ connectivityStatusReason: z.ZodOptional<z.ZodString>;
484
+ state: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["running", "archiveRequested", "archived"]>, z.ZodString]>>;
485
+ stateSince: z.ZodOptional<z.ZodNumber>;
486
+ stateReason: z.ZodOptional<z.ZodString>;
464
487
  }, "strip", z.ZodTypeAny, {
465
488
  id: string;
466
489
  createdAt: number;
@@ -471,6 +494,12 @@ declare const MachineSchema: z.ZodObject<{
471
494
  activeAt: number;
472
495
  metadata?: any;
473
496
  daemonState?: any;
497
+ connectivityStatus?: string | undefined;
498
+ connectivityStatusSince?: number | undefined;
499
+ connectivityStatusReason?: string | undefined;
500
+ state?: string | undefined;
501
+ stateSince?: number | undefined;
502
+ stateReason?: string | undefined;
474
503
  }, {
475
504
  id: string;
476
505
  createdAt: number;
@@ -481,6 +510,12 @@ declare const MachineSchema: z.ZodObject<{
481
510
  activeAt: number;
482
511
  metadata?: any;
483
512
  daemonState?: any;
513
+ connectivityStatus?: string | undefined;
514
+ connectivityStatusSince?: number | undefined;
515
+ connectivityStatusReason?: string | undefined;
516
+ state?: string | undefined;
517
+ stateSince?: number | undefined;
518
+ stateReason?: string | undefined;
484
519
  }>;
485
520
  type Machine = z.infer<typeof MachineSchema>;
486
521
  declare const UserMessageSchema: z.ZodObject<{
@@ -571,6 +606,7 @@ type Metadata = {
571
606
  updatedAt: number;
572
607
  };
573
608
  machineId?: string;
609
+ claudeSessionId?: string;
574
610
  tools?: string[];
575
611
  slashCommands?: string[];
576
612
  homeDir?: string;
@@ -578,6 +614,10 @@ type Metadata = {
578
614
  startedFromDaemon?: boolean;
579
615
  hostPid?: number;
580
616
  startedBy?: 'daemon' | 'terminal';
617
+ lifecycleState?: 'running' | 'archiveRequested' | 'archived' | string;
618
+ lifecycleStateSince?: number;
619
+ archivedBy?: string;
620
+ archiveReason?: string;
581
621
  };
582
622
  type AgentState = {
583
623
  controlledByUser?: boolean | null | undefined;
@@ -603,22 +643,26 @@ type AgentState = {
603
643
  };
604
644
 
605
645
  /**
606
- * Daemon-specific types (not related to API/server communication)
646
+ * RPC handlers for API session communication
647
+ * Handles remote procedure calls from mobile clients
607
648
  */
608
649
 
609
- /**
610
- * Session tracking for daemon
611
- */
612
- interface TrackedSession {
613
- startedBy: 'daemon' | string;
614
- happySessionId?: string;
615
- happySessionMetadataFromLocalWebhook?: Metadata;
616
- pid: number;
617
- childProcess?: ChildProcess;
618
- error?: string;
619
- directoryCreated?: boolean;
620
- message?: string;
650
+ interface SpawnSessionOptions {
651
+ machineId?: string;
652
+ directory: string;
653
+ sessionId?: string;
654
+ approvedNewDirectoryCreation?: boolean;
621
655
  }
656
+ type SpawnSessionResult = {
657
+ type: 'success';
658
+ sessionId: string;
659
+ } | {
660
+ type: 'requestToApproveDirectoryCreation';
661
+ directory: string;
662
+ } | {
663
+ type: 'error';
664
+ errorMessage: string;
665
+ };
622
666
 
623
667
  /**
624
668
  * WebSocket client for machine/daemon communication with Happy server
@@ -626,7 +670,7 @@ interface TrackedSession {
626
670
  */
627
671
 
628
672
  type MachineRpcHandlers = {
629
- spawnSession: (directory: string, sessionId?: string) => Promise<TrackedSession | null>;
673
+ spawnSession: (options: SpawnSessionOptions) => Promise<SpawnSessionResult>;
630
674
  stopSession: (sessionId: string) => boolean;
631
675
  requestShutdown: () => void;
632
676
  };
@@ -717,6 +761,11 @@ declare class ApiClient {
717
761
  sessionSyncClient(session: Session): ApiSessionClient;
718
762
  machineSyncClient(machine: Machine): ApiMachineClient;
719
763
  push(): PushNotificationClient;
764
+ /**
765
+ * Register a vendor API token with the server
766
+ * The token is sent as a JSON string - server handles encryption
767
+ */
768
+ registerVendorToken(vendor: 'openai' | 'anthropic' | 'gemini', apiKey: any): Promise<void>;
720
769
  }
721
770
 
722
771
  /**
package/dist/lib.d.mts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { z } from 'zod';
2
2
  import { EventEmitter } from 'node:events';
3
- import { ChildProcess } from 'child_process';
4
3
  import { ExpoPushMessage } from 'expo-server-sdk';
5
4
 
6
5
  /**
@@ -379,6 +378,12 @@ declare const SessionSchema: z.ZodObject<{
379
378
  metadataVersion: z.ZodNumber;
380
379
  agentState: z.ZodNullable<z.ZodAny>;
381
380
  agentStateVersion: z.ZodNumber;
381
+ connectivityStatus: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["neverConnected", "online", "offline"]>, z.ZodString]>>;
382
+ connectivityStatusSince: z.ZodOptional<z.ZodNumber>;
383
+ connectivityStatusReason: z.ZodOptional<z.ZodString>;
384
+ state: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["running", "archiveRequested", "archived"]>, z.ZodString]>>;
385
+ stateSince: z.ZodOptional<z.ZodNumber>;
386
+ stateReason: z.ZodOptional<z.ZodString>;
382
387
  }, "strip", z.ZodTypeAny, {
383
388
  id: string;
384
389
  seq: number;
@@ -388,6 +393,12 @@ declare const SessionSchema: z.ZodObject<{
388
393
  agentStateVersion: number;
389
394
  metadata?: any;
390
395
  agentState?: any;
396
+ connectivityStatus?: string | undefined;
397
+ connectivityStatusSince?: number | undefined;
398
+ connectivityStatusReason?: string | undefined;
399
+ state?: string | undefined;
400
+ stateSince?: number | undefined;
401
+ stateReason?: string | undefined;
391
402
  }, {
392
403
  id: string;
393
404
  seq: number;
@@ -397,6 +408,12 @@ declare const SessionSchema: z.ZodObject<{
397
408
  agentStateVersion: number;
398
409
  metadata?: any;
399
410
  agentState?: any;
411
+ connectivityStatus?: string | undefined;
412
+ connectivityStatusSince?: number | undefined;
413
+ connectivityStatusReason?: string | undefined;
414
+ state?: string | undefined;
415
+ stateSince?: number | undefined;
416
+ stateReason?: string | undefined;
400
417
  }>;
401
418
  type Session = z.infer<typeof SessionSchema>;
402
419
  /**
@@ -461,6 +478,12 @@ declare const MachineSchema: z.ZodObject<{
461
478
  activeAt: z.ZodNumber;
462
479
  createdAt: z.ZodNumber;
463
480
  updatedAt: z.ZodNumber;
481
+ connectivityStatus: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["neverConnected", "online", "offline"]>, z.ZodString]>>;
482
+ connectivityStatusSince: z.ZodOptional<z.ZodNumber>;
483
+ connectivityStatusReason: z.ZodOptional<z.ZodString>;
484
+ state: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["running", "archiveRequested", "archived"]>, z.ZodString]>>;
485
+ stateSince: z.ZodOptional<z.ZodNumber>;
486
+ stateReason: z.ZodOptional<z.ZodString>;
464
487
  }, "strip", z.ZodTypeAny, {
465
488
  id: string;
466
489
  createdAt: number;
@@ -471,6 +494,12 @@ declare const MachineSchema: z.ZodObject<{
471
494
  activeAt: number;
472
495
  metadata?: any;
473
496
  daemonState?: any;
497
+ connectivityStatus?: string | undefined;
498
+ connectivityStatusSince?: number | undefined;
499
+ connectivityStatusReason?: string | undefined;
500
+ state?: string | undefined;
501
+ stateSince?: number | undefined;
502
+ stateReason?: string | undefined;
474
503
  }, {
475
504
  id: string;
476
505
  createdAt: number;
@@ -481,6 +510,12 @@ declare const MachineSchema: z.ZodObject<{
481
510
  activeAt: number;
482
511
  metadata?: any;
483
512
  daemonState?: any;
513
+ connectivityStatus?: string | undefined;
514
+ connectivityStatusSince?: number | undefined;
515
+ connectivityStatusReason?: string | undefined;
516
+ state?: string | undefined;
517
+ stateSince?: number | undefined;
518
+ stateReason?: string | undefined;
484
519
  }>;
485
520
  type Machine = z.infer<typeof MachineSchema>;
486
521
  declare const UserMessageSchema: z.ZodObject<{
@@ -571,6 +606,7 @@ type Metadata = {
571
606
  updatedAt: number;
572
607
  };
573
608
  machineId?: string;
609
+ claudeSessionId?: string;
574
610
  tools?: string[];
575
611
  slashCommands?: string[];
576
612
  homeDir?: string;
@@ -578,6 +614,10 @@ type Metadata = {
578
614
  startedFromDaemon?: boolean;
579
615
  hostPid?: number;
580
616
  startedBy?: 'daemon' | 'terminal';
617
+ lifecycleState?: 'running' | 'archiveRequested' | 'archived' | string;
618
+ lifecycleStateSince?: number;
619
+ archivedBy?: string;
620
+ archiveReason?: string;
581
621
  };
582
622
  type AgentState = {
583
623
  controlledByUser?: boolean | null | undefined;
@@ -603,22 +643,26 @@ type AgentState = {
603
643
  };
604
644
 
605
645
  /**
606
- * Daemon-specific types (not related to API/server communication)
646
+ * RPC handlers for API session communication
647
+ * Handles remote procedure calls from mobile clients
607
648
  */
608
649
 
609
- /**
610
- * Session tracking for daemon
611
- */
612
- interface TrackedSession {
613
- startedBy: 'daemon' | string;
614
- happySessionId?: string;
615
- happySessionMetadataFromLocalWebhook?: Metadata;
616
- pid: number;
617
- childProcess?: ChildProcess;
618
- error?: string;
619
- directoryCreated?: boolean;
620
- message?: string;
650
+ interface SpawnSessionOptions {
651
+ machineId?: string;
652
+ directory: string;
653
+ sessionId?: string;
654
+ approvedNewDirectoryCreation?: boolean;
621
655
  }
656
+ type SpawnSessionResult = {
657
+ type: 'success';
658
+ sessionId: string;
659
+ } | {
660
+ type: 'requestToApproveDirectoryCreation';
661
+ directory: string;
662
+ } | {
663
+ type: 'error';
664
+ errorMessage: string;
665
+ };
622
666
 
623
667
  /**
624
668
  * WebSocket client for machine/daemon communication with Happy server
@@ -626,7 +670,7 @@ interface TrackedSession {
626
670
  */
627
671
 
628
672
  type MachineRpcHandlers = {
629
- spawnSession: (directory: string, sessionId?: string) => Promise<TrackedSession | null>;
673
+ spawnSession: (options: SpawnSessionOptions) => Promise<SpawnSessionResult>;
630
674
  stopSession: (sessionId: string) => boolean;
631
675
  requestShutdown: () => void;
632
676
  };
@@ -717,6 +761,11 @@ declare class ApiClient {
717
761
  sessionSyncClient(session: Session): ApiSessionClient;
718
762
  machineSyncClient(machine: Machine): ApiMachineClient;
719
763
  push(): PushNotificationClient;
764
+ /**
765
+ * Register a vendor API token with the server
766
+ * The token is sent as a JSON string - server handles encryption
767
+ */
768
+ registerVendorToken(vendor: 'openai' | 'anthropic' | 'gemini', apiKey: any): Promise<void>;
720
769
  }
721
770
 
722
771
  /**
package/dist/lib.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-Cezp_n6O.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-CGbH1LGX.mjs';
2
2
  import 'axios';
3
3
  import 'chalk';
4
4
  import 'fs';
@@ -14,7 +14,7 @@ import { io } from 'socket.io-client';
14
14
  import { Expo } from 'expo-server-sdk';
15
15
 
16
16
  var name = "happy-coder";
17
- var version = "0.9.0";
17
+ var version = "0.10.0-0";
18
18
  var description = "Claude Code session sharing CLI";
19
19
  var author = "Kirill Dubovitskiy";
20
20
  var license = "MIT";
@@ -79,6 +79,7 @@ var dependencies = {
79
79
  "@types/react": "^19.1.9",
80
80
  axios: "^1.10.0",
81
81
  chalk: "^5.4.1",
82
+ "cross-spawn": "^7.0.6",
82
83
  "expo-server-sdk": "^3.15.0",
83
84
  fastify: "^5.5.0",
84
85
  "fastify-type-provider-zod": "4.0.2",
@@ -86,6 +87,7 @@ var dependencies = {
86
87
  "http-proxy-middleware": "^3.0.5",
87
88
  ink: "^6.1.0",
88
89
  open: "^10.2.0",
90
+ "ps-list": "^8.1.1",
89
91
  "qrcode-terminal": "^0.12.0",
90
92
  react: "^19.1.1",
91
93
  "socket.io-client": "^4.8.1",
@@ -94,7 +96,9 @@ var dependencies = {
94
96
  };
95
97
  var devDependencies = {
96
98
  "@eslint/compat": "^1",
99
+ "@types/cross-spawn": "^6.0.6",
97
100
  "@types/node": ">=20",
101
+ "@types/ps-list": "^6.2.1",
98
102
  "cross-env": "^10.0.0",
99
103
  dotenv: "^16.6.1",
100
104
  eslint: "^9",
@@ -153,7 +157,7 @@ class Configuration {
153
157
  currentCliVersion;
154
158
  isExperimentalEnabled;
155
159
  constructor() {
156
- this.serverUrl = process.env.HAPPY_SERVER_URL || "https://handy-api.korshakov.org";
160
+ this.serverUrl = process.env.HAPPY_SERVER_URL || "https://api.cluster-fluster.com";
157
161
  const args = process.argv.slice(2);
158
162
  this.isDaemonProcess = args.length >= 2 && args[0] === "daemon" && args[1] === "start-sync";
159
163
  if (process.env.HAPPY_HOME_DIR) {
@@ -533,7 +537,7 @@ class Logger {
533
537
  appendFileSync(this.logFilePath, logLine);
534
538
  } catch (appendError) {
535
539
  if (process.env.DEBUG) {
536
- console.error("Failed to append to log file:", appendError);
540
+ console.error("[DEV MODE ONLY THROWING] Failed to append to log file:", appendError);
537
541
  throw appendError;
538
542
  }
539
543
  }
@@ -640,7 +644,23 @@ z$1.object({
640
644
  metadata: z$1.any(),
641
645
  metadataVersion: z$1.number(),
642
646
  agentState: z$1.any().nullable(),
643
- agentStateVersion: z$1.number()
647
+ agentStateVersion: z$1.number(),
648
+ // Connectivity tracking (from server)
649
+ connectivityStatus: z$1.union([
650
+ z$1.enum(["neverConnected", "online", "offline"]),
651
+ z$1.string()
652
+ // Forward compatibility
653
+ ]).optional(),
654
+ connectivityStatusSince: z$1.number().optional(),
655
+ connectivityStatusReason: z$1.string().optional(),
656
+ // State tracking (from server)
657
+ state: z$1.union([
658
+ z$1.enum(["running", "archiveRequested", "archived"]),
659
+ z$1.string()
660
+ // Forward compatibility
661
+ ]).optional(),
662
+ stateSince: z$1.number().optional(),
663
+ stateReason: z$1.string().optional()
644
664
  });
645
665
  z$1.object({
646
666
  host: z$1.string(),
@@ -678,7 +698,23 @@ z$1.object({
678
698
  active: z$1.boolean(),
679
699
  activeAt: z$1.number(),
680
700
  createdAt: z$1.number(),
681
- updatedAt: z$1.number()
701
+ updatedAt: z$1.number(),
702
+ // Connectivity tracking (from server)
703
+ connectivityStatus: z$1.union([
704
+ z$1.enum(["neverConnected", "online", "offline"]),
705
+ z$1.string()
706
+ // Forward compatibility
707
+ ]).optional(),
708
+ connectivityStatusSince: z$1.number().optional(),
709
+ connectivityStatusReason: z$1.string().optional(),
710
+ // State tracking (from server)
711
+ state: z$1.union([
712
+ z$1.enum(["running", "archiveRequested", "archived"]),
713
+ z$1.string()
714
+ // Forward compatibility
715
+ ]).optional(),
716
+ stateSince: z$1.number().optional(),
717
+ stateReason: z$1.string().optional()
682
718
  });
683
719
  z$1.object({
684
720
  content: SessionMessageContentSchema,
@@ -991,7 +1027,9 @@ class ApiSessionClient extends EventEmitter {
991
1027
  * Send a ping message to keep the connection alive
992
1028
  */
993
1029
  keepAlive(thinking, mode) {
994
- logger.debug(`[API] Sending keep alive message: ${thinking}`);
1030
+ if (process.env.DEBUG) {
1031
+ logger.debug(`[API] Sending keep alive message: ${thinking}`);
1032
+ }
995
1033
  this.socket.volatile.emit("session-alive", {
996
1034
  sid: this.sessionId,
997
1035
  time: Date.now(),
@@ -1229,37 +1267,39 @@ class ApiMachineClient {
1229
1267
  this.socket.on("rpc-request", async (data, callback) => {
1230
1268
  logger.debugLargeJson(`[API MACHINE] Received RPC request:`, data);
1231
1269
  try {
1232
- const spawnMethod2 = `${this.machine.id}:spawn-happy-session`;
1233
- const stopMethod2 = `${this.machine.id}:stop-session`;
1234
- const stopDaemonMethod2 = `${this.machine.id}:stop-daemon`;
1235
- if (data.method === spawnMethod2) {
1270
+ if (data.method === spawnMethod) {
1236
1271
  if (!this.spawnSession) {
1237
1272
  throw new Error("Spawn session handler not set");
1238
1273
  }
1239
- const { directory, sessionId } = decrypt(decodeBase64(data.params), this.secret) || {};
1274
+ const { directory, sessionId, machineId, approvedNewDirectoryCreation } = decrypt(decodeBase64(data.params), this.secret) || {};
1240
1275
  if (!directory) {
1241
1276
  throw new Error("Directory is required");
1242
1277
  }
1243
- const session = await this.spawnSession(directory, sessionId);
1244
- if (!session) {
1245
- throw new Error("Failed to spawn session");
1246
- }
1247
- if (session.error) {
1248
- throw new Error(session.error);
1249
- }
1250
- logger.debug(`[API MACHINE] Spawned session ${session.happySessionId || "WARNING - not session Id recieved in webhook"} with PID ${session.pid}`);
1251
- if (!session.happySessionId) {
1252
- throw new Error(`Session spawned (PID ${session.pid}) but no sessionId received from webhook. The session process may still be initializing.`);
1278
+ const result = await this.spawnSession({ directory, sessionId, machineId, approvedNewDirectoryCreation });
1279
+ switch (result.type) {
1280
+ case "success": {
1281
+ logger.debug(`[API MACHINE] Spawned session ${result.sessionId}`);
1282
+ const response = {
1283
+ type: "success",
1284
+ sessionId: result.sessionId
1285
+ };
1286
+ logger.debug(`[API MACHINE] Sending RPC response:`, response);
1287
+ callback(encodeBase64(encrypt(response, this.secret)));
1288
+ return;
1289
+ }
1290
+ case "requestToApproveDirectoryCreation":
1291
+ const promptResponse = {
1292
+ type: "requestToApproveDirectoryCreation",
1293
+ directory: result.directory
1294
+ };
1295
+ logger.debug(`[API MACHINE] Requesting directory creation approval for: ${result.directory}`);
1296
+ callback(encodeBase64(encrypt(promptResponse, this.secret)));
1297
+ return;
1298
+ case "error":
1299
+ throw new Error(result.errorMessage);
1253
1300
  }
1254
- const response = {
1255
- sessionId: session.happySessionId,
1256
- message: session.message
1257
- };
1258
- logger.debug(`[API MACHINE] Sending RPC response:`, response);
1259
- callback(encodeBase64(encrypt(response, this.secret)));
1260
- return;
1261
1301
  }
1262
- if (data.method === stopMethod2) {
1302
+ if (data.method === stopMethod) {
1263
1303
  logger.debug("[API MACHINE] Received stop-session RPC request");
1264
1304
  const decryptedParams = decrypt(decodeBase64(data.params), this.secret);
1265
1305
  const { sessionId } = decryptedParams || {};
@@ -1279,7 +1319,7 @@ class ApiMachineClient {
1279
1319
  callback(encryptedResponse);
1280
1320
  return;
1281
1321
  }
1282
- if (data.method === stopDaemonMethod2) {
1322
+ if (data.method === stopDaemonMethod) {
1283
1323
  logger.debug("[API MACHINE] Received stop-daemon RPC request");
1284
1324
  callback(encodeBase64(encrypt({
1285
1325
  message: "Daemon stop request acknowledged, starting shutdown sequence..."
@@ -1340,7 +1380,9 @@ class ApiMachineClient {
1340
1380
  machineId: this.machine.id,
1341
1381
  time: Date.now()
1342
1382
  };
1343
- logger.debugLargeJson(`[API MACHINE] Emitting machine-alive`, payload);
1383
+ if (process.env.DEBUG) {
1384
+ logger.debugLargeJson(`[API MACHINE] Emitting machine-alive`, payload);
1385
+ }
1344
1386
  this.socket.emit("machine-alive", payload);
1345
1387
  }, 2e4);
1346
1388
  logger.debug("[API MACHINE] Keep-alive started (20s interval)");
@@ -1366,7 +1408,7 @@ class PushNotificationClient {
1366
1408
  token;
1367
1409
  baseUrl;
1368
1410
  expo;
1369
- constructor(token, baseUrl = "https://handy-api.korshakov.org") {
1411
+ constructor(token, baseUrl = "https://api.cluster-fluster.com") {
1370
1412
  this.token = token;
1371
1413
  this.baseUrl = baseUrl;
1372
1414
  this.expo = new Expo();
@@ -1615,6 +1657,34 @@ class ApiClient {
1615
1657
  push() {
1616
1658
  return this.pushClient;
1617
1659
  }
1660
+ /**
1661
+ * Register a vendor API token with the server
1662
+ * The token is sent as a JSON string - server handles encryption
1663
+ */
1664
+ async registerVendorToken(vendor, apiKey) {
1665
+ try {
1666
+ const response = await axios.post(
1667
+ `${configuration.serverUrl}/v1/connect/${vendor}/register`,
1668
+ {
1669
+ token: JSON.stringify(apiKey)
1670
+ },
1671
+ {
1672
+ headers: {
1673
+ "Authorization": `Bearer ${this.token}`,
1674
+ "Content-Type": "application/json"
1675
+ },
1676
+ timeout: 5e3
1677
+ }
1678
+ );
1679
+ if (response.status !== 200 && response.status !== 201) {
1680
+ throw new Error(`Server returned status ${response.status}`);
1681
+ }
1682
+ logger.debug(`[API] Vendor token for ${vendor} registered successfully`);
1683
+ } catch (error) {
1684
+ logger.debug(`[API] [ERROR] Failed to register vendor token:`, error);
1685
+ throw new Error(`Failed to register vendor token: ${error instanceof Error ? error.message : "Unknown error"}`);
1686
+ }
1687
+ }
1618
1688
  }
1619
1689
 
1620
1690
  const UsageSchema = z$1.object({