happy-coder 0.10.0-3 → 0.10.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/README.md +10 -1
- package/dist/{index-DPVbp4Yx.mjs → index-BI37NnoW.mjs} +93 -87
- package/dist/{index-tqOLc1Il.cjs → index-ettJex_e.cjs} +115 -87
- package/dist/index.cjs +3 -2
- package/dist/index.mjs +3 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +44 -110
- package/dist/lib.d.mts +44 -110
- package/dist/lib.mjs +1 -1
- package/dist/{runCodex-C07HQlsW.mjs → runCodex-HlLNepHI.mjs} +47 -6
- package/dist/{runCodex-BxLD6H6G.cjs → runCodex-QdQBx9HK.cjs} +47 -6
- package/dist/{types-xds_c-JJ.mjs → types-8Ad05p3x.mjs} +213 -166
- package/dist/{types-CsJGQvQ3.cjs → types-CQOz_mPp.cjs} +214 -166
- package/package.json +5 -2
package/dist/lib.d.mts
CHANGED
|
@@ -308,11 +308,9 @@ interface RpcRequest {
|
|
|
308
308
|
* Configuration for RPC handler manager
|
|
309
309
|
*/
|
|
310
310
|
interface RpcHandlerConfig {
|
|
311
|
-
/** Prefix to add to all method names (e.g., sessionId or machineId) */
|
|
312
311
|
scopePrefix: string;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
/** Logger function for debugging */
|
|
312
|
+
encryptionKey: Uint8Array;
|
|
313
|
+
encryptionVariant: 'legacy' | 'dataKey';
|
|
316
314
|
logger?: (message: string, data?: any) => void;
|
|
317
315
|
}
|
|
318
316
|
|
|
@@ -324,7 +322,8 @@ interface RpcHandlerConfig {
|
|
|
324
322
|
declare class RpcHandlerManager {
|
|
325
323
|
private handlers;
|
|
326
324
|
private readonly scopePrefix;
|
|
327
|
-
private readonly
|
|
325
|
+
private readonly encryptionKey;
|
|
326
|
+
private readonly encryptionVariant;
|
|
328
327
|
private readonly logger;
|
|
329
328
|
private socket;
|
|
330
329
|
constructor(config: RpcHandlerConfig);
|
|
@@ -364,7 +363,6 @@ declare class RpcHandlerManager {
|
|
|
364
363
|
|
|
365
364
|
declare class ApiSessionClient extends EventEmitter {
|
|
366
365
|
private readonly token;
|
|
367
|
-
private readonly secret;
|
|
368
366
|
readonly sessionId: string;
|
|
369
367
|
private metadata;
|
|
370
368
|
private metadataVersion;
|
|
@@ -376,7 +374,9 @@ declare class ApiSessionClient extends EventEmitter {
|
|
|
376
374
|
readonly rpcHandlerManager: RpcHandlerManager;
|
|
377
375
|
private agentStateLock;
|
|
378
376
|
private metadataLock;
|
|
379
|
-
|
|
377
|
+
private encryptionKey;
|
|
378
|
+
private encryptionVariant;
|
|
379
|
+
constructor(token: string, session: Session);
|
|
380
380
|
onUserMessage(callback: (data: UserMessage) => void): void;
|
|
381
381
|
/**
|
|
382
382
|
* Send message to session
|
|
@@ -434,53 +434,16 @@ type Usage = z.infer<typeof UsageSchema>;
|
|
|
434
434
|
/**
|
|
435
435
|
* Session information
|
|
436
436
|
*/
|
|
437
|
-
|
|
438
|
-
createdAt: z.ZodNumber;
|
|
439
|
-
id: z.ZodString;
|
|
440
|
-
seq: z.ZodNumber;
|
|
441
|
-
updatedAt: z.ZodNumber;
|
|
442
|
-
metadata: z.ZodAny;
|
|
443
|
-
metadataVersion: z.ZodNumber;
|
|
444
|
-
agentState: z.ZodNullable<z.ZodAny>;
|
|
445
|
-
agentStateVersion: z.ZodNumber;
|
|
446
|
-
connectivityStatus: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["neverConnected", "online", "offline"]>, z.ZodString]>>;
|
|
447
|
-
connectivityStatusSince: z.ZodOptional<z.ZodNumber>;
|
|
448
|
-
connectivityStatusReason: z.ZodOptional<z.ZodString>;
|
|
449
|
-
state: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["running", "archiveRequested", "archived"]>, z.ZodString]>>;
|
|
450
|
-
stateSince: z.ZodOptional<z.ZodNumber>;
|
|
451
|
-
stateReason: z.ZodOptional<z.ZodString>;
|
|
452
|
-
}, "strip", z.ZodTypeAny, {
|
|
453
|
-
id: string;
|
|
454
|
-
seq: number;
|
|
455
|
-
createdAt: number;
|
|
456
|
-
updatedAt: number;
|
|
457
|
-
metadataVersion: number;
|
|
458
|
-
agentStateVersion: number;
|
|
459
|
-
metadata?: any;
|
|
460
|
-
agentState?: any;
|
|
461
|
-
connectivityStatus?: string | undefined;
|
|
462
|
-
connectivityStatusSince?: number | undefined;
|
|
463
|
-
connectivityStatusReason?: string | undefined;
|
|
464
|
-
state?: string | undefined;
|
|
465
|
-
stateSince?: number | undefined;
|
|
466
|
-
stateReason?: string | undefined;
|
|
467
|
-
}, {
|
|
437
|
+
type Session = {
|
|
468
438
|
id: string;
|
|
469
439
|
seq: number;
|
|
470
|
-
|
|
471
|
-
|
|
440
|
+
encryptionKey: Uint8Array;
|
|
441
|
+
encryptionVariant: 'legacy' | 'dataKey';
|
|
442
|
+
metadata: Metadata;
|
|
472
443
|
metadataVersion: number;
|
|
444
|
+
agentState: AgentState | null;
|
|
473
445
|
agentStateVersion: number;
|
|
474
|
-
|
|
475
|
-
agentState?: any;
|
|
476
|
-
connectivityStatus?: string | undefined;
|
|
477
|
-
connectivityStatusSince?: number | undefined;
|
|
478
|
-
connectivityStatusReason?: string | undefined;
|
|
479
|
-
state?: string | undefined;
|
|
480
|
-
stateSince?: number | undefined;
|
|
481
|
-
stateReason?: string | undefined;
|
|
482
|
-
}>;
|
|
483
|
-
type Session = z.infer<typeof SessionSchema>;
|
|
446
|
+
};
|
|
484
447
|
/**
|
|
485
448
|
* Machine metadata - static information (rarely changes)
|
|
486
449
|
*/
|
|
@@ -533,59 +496,15 @@ declare const DaemonStateSchema: z.ZodObject<{
|
|
|
533
496
|
shutdownSource?: string | undefined;
|
|
534
497
|
}>;
|
|
535
498
|
type DaemonState = z.infer<typeof DaemonStateSchema>;
|
|
536
|
-
|
|
537
|
-
* Machine information - similar to Session
|
|
538
|
-
*/
|
|
539
|
-
declare const MachineSchema: z.ZodObject<{
|
|
540
|
-
id: z.ZodString;
|
|
541
|
-
metadata: z.ZodAny;
|
|
542
|
-
metadataVersion: z.ZodNumber;
|
|
543
|
-
daemonState: z.ZodNullable<z.ZodAny>;
|
|
544
|
-
daemonStateVersion: z.ZodNumber;
|
|
545
|
-
active: z.ZodBoolean;
|
|
546
|
-
activeAt: z.ZodNumber;
|
|
547
|
-
createdAt: z.ZodNumber;
|
|
548
|
-
updatedAt: z.ZodNumber;
|
|
549
|
-
connectivityStatus: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["neverConnected", "online", "offline"]>, z.ZodString]>>;
|
|
550
|
-
connectivityStatusSince: z.ZodOptional<z.ZodNumber>;
|
|
551
|
-
connectivityStatusReason: z.ZodOptional<z.ZodString>;
|
|
552
|
-
state: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["running", "archiveRequested", "archived"]>, z.ZodString]>>;
|
|
553
|
-
stateSince: z.ZodOptional<z.ZodNumber>;
|
|
554
|
-
stateReason: z.ZodOptional<z.ZodString>;
|
|
555
|
-
}, "strip", z.ZodTypeAny, {
|
|
556
|
-
id: string;
|
|
557
|
-
createdAt: number;
|
|
558
|
-
updatedAt: number;
|
|
559
|
-
metadataVersion: number;
|
|
560
|
-
daemonStateVersion: number;
|
|
561
|
-
active: boolean;
|
|
562
|
-
activeAt: number;
|
|
563
|
-
metadata?: any;
|
|
564
|
-
daemonState?: any;
|
|
565
|
-
connectivityStatus?: string | undefined;
|
|
566
|
-
connectivityStatusSince?: number | undefined;
|
|
567
|
-
connectivityStatusReason?: string | undefined;
|
|
568
|
-
state?: string | undefined;
|
|
569
|
-
stateSince?: number | undefined;
|
|
570
|
-
stateReason?: string | undefined;
|
|
571
|
-
}, {
|
|
499
|
+
type Machine = {
|
|
572
500
|
id: string;
|
|
573
|
-
|
|
574
|
-
|
|
501
|
+
encryptionKey: Uint8Array;
|
|
502
|
+
encryptionVariant: 'legacy' | 'dataKey';
|
|
503
|
+
metadata: MachineMetadata;
|
|
575
504
|
metadataVersion: number;
|
|
505
|
+
daemonState: DaemonState | null;
|
|
576
506
|
daemonStateVersion: number;
|
|
577
|
-
|
|
578
|
-
activeAt: number;
|
|
579
|
-
metadata?: any;
|
|
580
|
-
daemonState?: any;
|
|
581
|
-
connectivityStatus?: string | undefined;
|
|
582
|
-
connectivityStatusSince?: number | undefined;
|
|
583
|
-
connectivityStatusReason?: string | undefined;
|
|
584
|
-
state?: string | undefined;
|
|
585
|
-
stateSince?: number | undefined;
|
|
586
|
-
stateReason?: string | undefined;
|
|
587
|
-
}>;
|
|
588
|
-
type Machine = z.infer<typeof MachineSchema>;
|
|
507
|
+
};
|
|
589
508
|
declare const UserMessageSchema: z.ZodObject<{
|
|
590
509
|
role: z.ZodLiteral<"user">;
|
|
591
510
|
content: z.ZodObject<{
|
|
@@ -719,6 +638,8 @@ interface SpawnSessionOptions {
|
|
|
719
638
|
directory: string;
|
|
720
639
|
sessionId?: string;
|
|
721
640
|
approvedNewDirectoryCreation?: boolean;
|
|
641
|
+
agent?: 'claude' | 'codex';
|
|
642
|
+
token?: string;
|
|
722
643
|
}
|
|
723
644
|
type SpawnSessionResult = {
|
|
724
645
|
type: 'success';
|
|
@@ -743,12 +664,11 @@ type MachineRpcHandlers = {
|
|
|
743
664
|
};
|
|
744
665
|
declare class ApiMachineClient {
|
|
745
666
|
private token;
|
|
746
|
-
private secret;
|
|
747
667
|
private machine;
|
|
748
668
|
private socket;
|
|
749
669
|
private keepAliveInterval;
|
|
750
670
|
private rpcHandlerManager;
|
|
751
|
-
constructor(token: string,
|
|
671
|
+
constructor(token: string, machine: Machine);
|
|
752
672
|
setRPCHandlers({ spawnSession, stopSession, requestShutdown }: MachineRpcHandlers): void;
|
|
753
673
|
/**
|
|
754
674
|
* Update machine metadata
|
|
@@ -796,11 +716,29 @@ declare class PushNotificationClient {
|
|
|
796
716
|
sendToAllDevices(title: string, body: string, data?: Record<string, any>): void;
|
|
797
717
|
}
|
|
798
718
|
|
|
719
|
+
/**
|
|
720
|
+
* Minimal persistence functions for happy CLI
|
|
721
|
+
*
|
|
722
|
+
* Handles settings and private key storage in ~/.happy/ or local .happy/
|
|
723
|
+
*/
|
|
724
|
+
|
|
725
|
+
type Credentials = {
|
|
726
|
+
token: string;
|
|
727
|
+
encryption: {
|
|
728
|
+
type: 'legacy';
|
|
729
|
+
secret: Uint8Array;
|
|
730
|
+
} | {
|
|
731
|
+
type: 'dataKey';
|
|
732
|
+
publicKey: Uint8Array;
|
|
733
|
+
machineKey: Uint8Array;
|
|
734
|
+
};
|
|
735
|
+
};
|
|
736
|
+
|
|
799
737
|
declare class ApiClient {
|
|
800
|
-
|
|
801
|
-
private readonly
|
|
738
|
+
static create(credential: Credentials): Promise<ApiClient>;
|
|
739
|
+
private readonly credential;
|
|
802
740
|
private readonly pushClient;
|
|
803
|
-
constructor(
|
|
741
|
+
private constructor();
|
|
804
742
|
/**
|
|
805
743
|
* Create a new session or load existing one with the given tag
|
|
806
744
|
*/
|
|
@@ -809,11 +747,6 @@ declare class ApiClient {
|
|
|
809
747
|
metadata: Metadata;
|
|
810
748
|
state: AgentState | null;
|
|
811
749
|
}): Promise<Session>;
|
|
812
|
-
/**
|
|
813
|
-
* Get machine by ID from the server
|
|
814
|
-
* Returns the current machine state from the server with decrypted metadata and daemonState
|
|
815
|
-
*/
|
|
816
|
-
getMachine(machineId: string): Promise<Machine | null>;
|
|
817
750
|
/**
|
|
818
751
|
* Register or update machine with the server
|
|
819
752
|
* Returns the current machine state from the server with decrypted metadata and daemonState
|
|
@@ -864,6 +797,7 @@ declare let logger: Logger;
|
|
|
864
797
|
*/
|
|
865
798
|
declare class Configuration {
|
|
866
799
|
readonly serverUrl: string;
|
|
800
|
+
readonly webappUrl: string;
|
|
867
801
|
readonly isDaemonProcess: boolean;
|
|
868
802
|
readonly happyHomeDir: string;
|
|
869
803
|
readonly logsDir: string;
|
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-
|
|
1
|
+
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-8Ad05p3x.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'fs';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { useStdout, useInput, Box, Text, render } from 'ink';
|
|
2
2
|
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
-
import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, b as packageJson } from './types-
|
|
3
|
+
import { l as logger, A as ApiClient, r as readSettings, p as projectPath, c as configuration, b as packageJson } from './types-8Ad05p3x.mjs';
|
|
4
4
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
5
5
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
|
-
import { i as initialMachineMetadata, M as MessageQueue2, h as hashObject, a as MessageBuffer, s as startHappyServer, t as trimIdent } from './index-
|
|
9
|
+
import { i as initialMachineMetadata, n as notifyDaemonSessionStarted, M as MessageQueue2, h as hashObject, r as registerKillSessionHandler, a as MessageBuffer, s as startHappyServer, t as trimIdent, b as stopCaffeinate } from './index-BI37NnoW.mjs';
|
|
10
10
|
import os from 'node:os';
|
|
11
11
|
import { resolve, join } from 'node:path';
|
|
12
12
|
import fs from 'node:fs';
|
|
@@ -30,6 +30,7 @@ import 'node:readline';
|
|
|
30
30
|
import 'node:url';
|
|
31
31
|
import 'ps-list';
|
|
32
32
|
import 'cross-spawn';
|
|
33
|
+
import 'tmp';
|
|
33
34
|
import 'qrcode-terminal';
|
|
34
35
|
import 'open';
|
|
35
36
|
import 'fastify';
|
|
@@ -678,7 +679,8 @@ const CodexDisplay = ({ messageBuffer, logPath, onExit }) => {
|
|
|
678
679
|
|
|
679
680
|
async function runCodex(opts) {
|
|
680
681
|
const sessionTag = randomUUID();
|
|
681
|
-
const api =
|
|
682
|
+
const api = await ApiClient.create(opts.credentials);
|
|
683
|
+
logger.debug(`[codex] Starting with options: startedBy=${opts.startedBy || "terminal"}`);
|
|
682
684
|
const settings = await readSettings();
|
|
683
685
|
let machineId = settings?.machineId;
|
|
684
686
|
if (!machineId) {
|
|
@@ -703,9 +705,9 @@ async function runCodex(opts) {
|
|
|
703
705
|
happyHomeDir: configuration.happyHomeDir,
|
|
704
706
|
happyLibDir: projectPath(),
|
|
705
707
|
happyToolsDir: resolve(projectPath(), "tools", "unpacked"),
|
|
706
|
-
startedFromDaemon:
|
|
708
|
+
startedFromDaemon: opts.startedBy === "daemon",
|
|
707
709
|
hostPid: process.pid,
|
|
708
|
-
startedBy: "terminal",
|
|
710
|
+
startedBy: opts.startedBy || "terminal",
|
|
709
711
|
// Initialize lifecycle state
|
|
710
712
|
lifecycleState: "running",
|
|
711
713
|
lifecycleStateSince: Date.now(),
|
|
@@ -713,6 +715,17 @@ async function runCodex(opts) {
|
|
|
713
715
|
};
|
|
714
716
|
const response = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
|
|
715
717
|
const session = api.sessionSyncClient(response);
|
|
718
|
+
try {
|
|
719
|
+
logger.debug(`[START] Reporting session ${response.id} to daemon`);
|
|
720
|
+
const result = await notifyDaemonSessionStarted(response.id, metadata);
|
|
721
|
+
if (result.error) {
|
|
722
|
+
logger.debug(`[START] Failed to report to daemon (may not be running):`, result.error);
|
|
723
|
+
} else {
|
|
724
|
+
logger.debug(`[START] Reported session ${response.id} to daemon`);
|
|
725
|
+
}
|
|
726
|
+
} catch (error) {
|
|
727
|
+
logger.debug("[START] Failed to report to daemon (may not be running):", error);
|
|
728
|
+
}
|
|
716
729
|
const messageQueue = new MessageQueue2((mode) => hashObject({
|
|
717
730
|
permissionMode: mode.permissionMode,
|
|
718
731
|
model: mode.model
|
|
@@ -781,7 +794,34 @@ async function runCodex(opts) {
|
|
|
781
794
|
abortController = new AbortController();
|
|
782
795
|
}
|
|
783
796
|
}
|
|
797
|
+
const cleanup = async () => {
|
|
798
|
+
logger.debug("[Codex] Cleanup start");
|
|
799
|
+
await handleAbort();
|
|
800
|
+
logger.debug("[Codex] Cleanup completed");
|
|
801
|
+
try {
|
|
802
|
+
if (session) {
|
|
803
|
+
session.updateMetadata((currentMetadata) => ({
|
|
804
|
+
...currentMetadata,
|
|
805
|
+
lifecycleState: "archived",
|
|
806
|
+
lifecycleStateSince: Date.now(),
|
|
807
|
+
archivedBy: "cli",
|
|
808
|
+
archiveReason: "User terminated"
|
|
809
|
+
}));
|
|
810
|
+
session.sendSessionDeath();
|
|
811
|
+
await session.flush();
|
|
812
|
+
await session.close();
|
|
813
|
+
}
|
|
814
|
+
stopCaffeinate();
|
|
815
|
+
happyServer.stop();
|
|
816
|
+
logger.debug("[Codex] Cleanup complete, exiting");
|
|
817
|
+
process.exit(0);
|
|
818
|
+
} catch (error) {
|
|
819
|
+
logger.debug("[Codex] Error during cleanup:", error);
|
|
820
|
+
process.exit(1);
|
|
821
|
+
}
|
|
822
|
+
};
|
|
784
823
|
session.rpcHandlerManager.registerHandler("abort", handleAbort);
|
|
824
|
+
registerKillSessionHandler(session.rpcHandlerManager, cleanup);
|
|
785
825
|
const messageBuffer = new MessageBuffer();
|
|
786
826
|
const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
|
|
787
827
|
let inkInstance = null;
|
|
@@ -829,7 +869,8 @@ async function runCodex(opts) {
|
|
|
829
869
|
return acc;
|
|
830
870
|
};
|
|
831
871
|
var collectFilesRecursive = collectFilesRecursive2;
|
|
832
|
-
const
|
|
872
|
+
const codexHomeDir = process.env.CODEX_HOME || join(os.homedir(), ".codex");
|
|
873
|
+
const rootDir = join(codexHomeDir, "sessions");
|
|
833
874
|
const candidates = collectFilesRecursive2(rootDir).filter((full) => full.endsWith(`-${sessionId}.jsonl`)).filter((full) => {
|
|
834
875
|
try {
|
|
835
876
|
return fs.statSync(full).isFile();
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
var ink = require('ink');
|
|
4
4
|
var React = require('react');
|
|
5
|
-
var types = require('./types-
|
|
5
|
+
var types = require('./types-CQOz_mPp.cjs');
|
|
6
6
|
var index_js = require('@modelcontextprotocol/sdk/client/index.js');
|
|
7
7
|
var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
8
8
|
var z = require('zod');
|
|
9
9
|
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
10
10
|
var node_crypto = require('node:crypto');
|
|
11
|
-
var index = require('./index-
|
|
11
|
+
var index = require('./index-ettJex_e.cjs');
|
|
12
12
|
var os = require('node:os');
|
|
13
13
|
var node_path = require('node:path');
|
|
14
14
|
var fs = require('node:fs');
|
|
@@ -32,6 +32,7 @@ require('node:readline');
|
|
|
32
32
|
require('node:url');
|
|
33
33
|
require('ps-list');
|
|
34
34
|
require('cross-spawn');
|
|
35
|
+
require('tmp');
|
|
35
36
|
require('qrcode-terminal');
|
|
36
37
|
require('open');
|
|
37
38
|
require('fastify');
|
|
@@ -680,7 +681,8 @@ const CodexDisplay = ({ messageBuffer, logPath, onExit }) => {
|
|
|
680
681
|
|
|
681
682
|
async function runCodex(opts) {
|
|
682
683
|
const sessionTag = node_crypto.randomUUID();
|
|
683
|
-
const api =
|
|
684
|
+
const api = await types.ApiClient.create(opts.credentials);
|
|
685
|
+
types.logger.debug(`[codex] Starting with options: startedBy=${opts.startedBy || "terminal"}`);
|
|
684
686
|
const settings = await types.readSettings();
|
|
685
687
|
let machineId = settings?.machineId;
|
|
686
688
|
if (!machineId) {
|
|
@@ -705,9 +707,9 @@ async function runCodex(opts) {
|
|
|
705
707
|
happyHomeDir: types.configuration.happyHomeDir,
|
|
706
708
|
happyLibDir: types.projectPath(),
|
|
707
709
|
happyToolsDir: node_path.resolve(types.projectPath(), "tools", "unpacked"),
|
|
708
|
-
startedFromDaemon:
|
|
710
|
+
startedFromDaemon: opts.startedBy === "daemon",
|
|
709
711
|
hostPid: process.pid,
|
|
710
|
-
startedBy: "terminal",
|
|
712
|
+
startedBy: opts.startedBy || "terminal",
|
|
711
713
|
// Initialize lifecycle state
|
|
712
714
|
lifecycleState: "running",
|
|
713
715
|
lifecycleStateSince: Date.now(),
|
|
@@ -715,6 +717,17 @@ async function runCodex(opts) {
|
|
|
715
717
|
};
|
|
716
718
|
const response = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
|
|
717
719
|
const session = api.sessionSyncClient(response);
|
|
720
|
+
try {
|
|
721
|
+
types.logger.debug(`[START] Reporting session ${response.id} to daemon`);
|
|
722
|
+
const result = await index.notifyDaemonSessionStarted(response.id, metadata);
|
|
723
|
+
if (result.error) {
|
|
724
|
+
types.logger.debug(`[START] Failed to report to daemon (may not be running):`, result.error);
|
|
725
|
+
} else {
|
|
726
|
+
types.logger.debug(`[START] Reported session ${response.id} to daemon`);
|
|
727
|
+
}
|
|
728
|
+
} catch (error) {
|
|
729
|
+
types.logger.debug("[START] Failed to report to daemon (may not be running):", error);
|
|
730
|
+
}
|
|
718
731
|
const messageQueue = new index.MessageQueue2((mode) => index.hashObject({
|
|
719
732
|
permissionMode: mode.permissionMode,
|
|
720
733
|
model: mode.model
|
|
@@ -783,7 +796,34 @@ async function runCodex(opts) {
|
|
|
783
796
|
abortController = new AbortController();
|
|
784
797
|
}
|
|
785
798
|
}
|
|
799
|
+
const cleanup = async () => {
|
|
800
|
+
types.logger.debug("[Codex] Cleanup start");
|
|
801
|
+
await handleAbort();
|
|
802
|
+
types.logger.debug("[Codex] Cleanup completed");
|
|
803
|
+
try {
|
|
804
|
+
if (session) {
|
|
805
|
+
session.updateMetadata((currentMetadata) => ({
|
|
806
|
+
...currentMetadata,
|
|
807
|
+
lifecycleState: "archived",
|
|
808
|
+
lifecycleStateSince: Date.now(),
|
|
809
|
+
archivedBy: "cli",
|
|
810
|
+
archiveReason: "User terminated"
|
|
811
|
+
}));
|
|
812
|
+
session.sendSessionDeath();
|
|
813
|
+
await session.flush();
|
|
814
|
+
await session.close();
|
|
815
|
+
}
|
|
816
|
+
index.stopCaffeinate();
|
|
817
|
+
happyServer.stop();
|
|
818
|
+
types.logger.debug("[Codex] Cleanup complete, exiting");
|
|
819
|
+
process.exit(0);
|
|
820
|
+
} catch (error) {
|
|
821
|
+
types.logger.debug("[Codex] Error during cleanup:", error);
|
|
822
|
+
process.exit(1);
|
|
823
|
+
}
|
|
824
|
+
};
|
|
786
825
|
session.rpcHandlerManager.registerHandler("abort", handleAbort);
|
|
826
|
+
index.registerKillSessionHandler(session.rpcHandlerManager, cleanup);
|
|
787
827
|
const messageBuffer = new index.MessageBuffer();
|
|
788
828
|
const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
|
|
789
829
|
let inkInstance = null;
|
|
@@ -831,7 +871,8 @@ async function runCodex(opts) {
|
|
|
831
871
|
return acc;
|
|
832
872
|
};
|
|
833
873
|
var collectFilesRecursive = collectFilesRecursive2;
|
|
834
|
-
const
|
|
874
|
+
const codexHomeDir = process.env.CODEX_HOME || node_path.join(os.homedir(), ".codex");
|
|
875
|
+
const rootDir = node_path.join(codexHomeDir, "sessions");
|
|
835
876
|
const candidates = collectFilesRecursive2(rootDir).filter((full) => full.endsWith(`-${sessionId}.jsonl`)).filter((full) => {
|
|
836
877
|
try {
|
|
837
878
|
return fs.statSync(full).isFile();
|