@hydra-acp/cli 0.1.11 → 0.1.13
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.js +816 -45
- package/dist/index.d.ts +46 -0
- package/dist/index.js +113 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -103,18 +103,21 @@ declare const HydraConfig: z.ZodObject<{
|
|
|
103
103
|
mouse: z.ZodDefault<z.ZodBoolean>;
|
|
104
104
|
logMaxBytes: z.ZodDefault<z.ZodNumber>;
|
|
105
105
|
cwdColumnMaxWidth: z.ZodDefault<z.ZodNumber>;
|
|
106
|
+
progressIndicator: z.ZodDefault<z.ZodBoolean>;
|
|
106
107
|
}, "strip", z.ZodTypeAny, {
|
|
107
108
|
repaintThrottleMs: number;
|
|
108
109
|
maxScrollbackLines: number;
|
|
109
110
|
mouse: boolean;
|
|
110
111
|
logMaxBytes: number;
|
|
111
112
|
cwdColumnMaxWidth: number;
|
|
113
|
+
progressIndicator: boolean;
|
|
112
114
|
}, {
|
|
113
115
|
repaintThrottleMs?: number | undefined;
|
|
114
116
|
maxScrollbackLines?: number | undefined;
|
|
115
117
|
mouse?: boolean | undefined;
|
|
116
118
|
logMaxBytes?: number | undefined;
|
|
117
119
|
cwdColumnMaxWidth?: number | undefined;
|
|
120
|
+
progressIndicator?: boolean | undefined;
|
|
118
121
|
}>>;
|
|
119
122
|
}, "strip", z.ZodTypeAny, {
|
|
120
123
|
daemon: {
|
|
@@ -142,6 +145,7 @@ declare const HydraConfig: z.ZodObject<{
|
|
|
142
145
|
mouse: boolean;
|
|
143
146
|
logMaxBytes: number;
|
|
144
147
|
cwdColumnMaxWidth: number;
|
|
148
|
+
progressIndicator: boolean;
|
|
145
149
|
};
|
|
146
150
|
registry: {
|
|
147
151
|
url: string;
|
|
@@ -177,6 +181,7 @@ declare const HydraConfig: z.ZodObject<{
|
|
|
177
181
|
mouse?: boolean | undefined;
|
|
178
182
|
logMaxBytes?: number | undefined;
|
|
179
183
|
cwdColumnMaxWidth?: number | undefined;
|
|
184
|
+
progressIndicator?: boolean | undefined;
|
|
180
185
|
} | undefined;
|
|
181
186
|
registry?: {
|
|
182
187
|
url?: string | undefined;
|
|
@@ -1330,6 +1335,8 @@ declare const SessionListEntry: z.ZodObject<{
|
|
|
1330
1335
|
costAmount?: number | undefined;
|
|
1331
1336
|
costCurrency?: string | undefined;
|
|
1332
1337
|
}>>;
|
|
1338
|
+
importedFromMachine: z.ZodOptional<z.ZodString>;
|
|
1339
|
+
importedFromUpstreamSessionId: z.ZodOptional<z.ZodString>;
|
|
1333
1340
|
updatedAt: z.ZodString;
|
|
1334
1341
|
attachedClients: z.ZodNumber;
|
|
1335
1342
|
status: z.ZodDefault<z.ZodEnum<["live", "cold"]>>;
|
|
@@ -1351,6 +1358,8 @@ declare const SessionListEntry: z.ZodObject<{
|
|
|
1351
1358
|
costAmount?: number | undefined;
|
|
1352
1359
|
costCurrency?: string | undefined;
|
|
1353
1360
|
} | undefined;
|
|
1361
|
+
importedFromMachine?: string | undefined;
|
|
1362
|
+
importedFromUpstreamSessionId?: string | undefined;
|
|
1354
1363
|
}, {
|
|
1355
1364
|
cwd: string;
|
|
1356
1365
|
sessionId: string;
|
|
@@ -1368,6 +1377,8 @@ declare const SessionListEntry: z.ZodObject<{
|
|
|
1368
1377
|
costAmount?: number | undefined;
|
|
1369
1378
|
costCurrency?: string | undefined;
|
|
1370
1379
|
} | undefined;
|
|
1380
|
+
importedFromMachine?: string | undefined;
|
|
1381
|
+
importedFromUpstreamSessionId?: string | undefined;
|
|
1371
1382
|
}>;
|
|
1372
1383
|
type SessionListEntry = z.infer<typeof SessionListEntry>;
|
|
1373
1384
|
declare const SessionListResult: z.ZodObject<{
|
|
@@ -1394,6 +1405,8 @@ declare const SessionListResult: z.ZodObject<{
|
|
|
1394
1405
|
costAmount?: number | undefined;
|
|
1395
1406
|
costCurrency?: string | undefined;
|
|
1396
1407
|
}>>;
|
|
1408
|
+
importedFromMachine: z.ZodOptional<z.ZodString>;
|
|
1409
|
+
importedFromUpstreamSessionId: z.ZodOptional<z.ZodString>;
|
|
1397
1410
|
updatedAt: z.ZodString;
|
|
1398
1411
|
attachedClients: z.ZodNumber;
|
|
1399
1412
|
status: z.ZodDefault<z.ZodEnum<["live", "cold"]>>;
|
|
@@ -1415,6 +1428,8 @@ declare const SessionListResult: z.ZodObject<{
|
|
|
1415
1428
|
costAmount?: number | undefined;
|
|
1416
1429
|
costCurrency?: string | undefined;
|
|
1417
1430
|
} | undefined;
|
|
1431
|
+
importedFromMachine?: string | undefined;
|
|
1432
|
+
importedFromUpstreamSessionId?: string | undefined;
|
|
1418
1433
|
}, {
|
|
1419
1434
|
cwd: string;
|
|
1420
1435
|
sessionId: string;
|
|
@@ -1432,6 +1447,8 @@ declare const SessionListResult: z.ZodObject<{
|
|
|
1432
1447
|
costAmount?: number | undefined;
|
|
1433
1448
|
costCurrency?: string | undefined;
|
|
1434
1449
|
} | undefined;
|
|
1450
|
+
importedFromMachine?: string | undefined;
|
|
1451
|
+
importedFromUpstreamSessionId?: string | undefined;
|
|
1435
1452
|
}>, "many">;
|
|
1436
1453
|
nextCursor: z.ZodOptional<z.ZodString>;
|
|
1437
1454
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -1452,6 +1469,8 @@ declare const SessionListResult: z.ZodObject<{
|
|
|
1452
1469
|
costAmount?: number | undefined;
|
|
1453
1470
|
costCurrency?: string | undefined;
|
|
1454
1471
|
} | undefined;
|
|
1472
|
+
importedFromMachine?: string | undefined;
|
|
1473
|
+
importedFromUpstreamSessionId?: string | undefined;
|
|
1455
1474
|
}[];
|
|
1456
1475
|
nextCursor?: string | undefined;
|
|
1457
1476
|
}, {
|
|
@@ -1472,6 +1491,8 @@ declare const SessionListResult: z.ZodObject<{
|
|
|
1472
1491
|
costAmount?: number | undefined;
|
|
1473
1492
|
costCurrency?: string | undefined;
|
|
1474
1493
|
} | undefined;
|
|
1494
|
+
importedFromMachine?: string | undefined;
|
|
1495
|
+
importedFromUpstreamSessionId?: string | undefined;
|
|
1475
1496
|
}[];
|
|
1476
1497
|
nextCursor?: string | undefined;
|
|
1477
1498
|
}>;
|
|
@@ -1556,6 +1577,11 @@ interface AgentInstanceOptions {
|
|
|
1556
1577
|
plan: SpawnPlan;
|
|
1557
1578
|
extraEnv?: Record<string, string>;
|
|
1558
1579
|
stderrTailBytes?: number;
|
|
1580
|
+
logger?: AgentLogger;
|
|
1581
|
+
}
|
|
1582
|
+
interface AgentLogger {
|
|
1583
|
+
info: (msg: string) => void;
|
|
1584
|
+
warn: (msg: string) => void;
|
|
1559
1585
|
}
|
|
1560
1586
|
declare class AgentInstance {
|
|
1561
1587
|
readonly agentId: string;
|
|
@@ -1566,6 +1592,7 @@ declare class AgentInstance {
|
|
|
1566
1592
|
private killed;
|
|
1567
1593
|
private stderrTail;
|
|
1568
1594
|
private stderrTailBytes;
|
|
1595
|
+
private logger?;
|
|
1569
1596
|
private exitHandlers;
|
|
1570
1597
|
private constructor();
|
|
1571
1598
|
private formatFailure;
|
|
@@ -1636,6 +1663,10 @@ interface SessionInit {
|
|
|
1636
1663
|
agentMeta?: Record<string, unknown>;
|
|
1637
1664
|
agentArgs?: string[];
|
|
1638
1665
|
idleTimeoutMs?: number;
|
|
1666
|
+
logger?: {
|
|
1667
|
+
info: (msg: string) => void;
|
|
1668
|
+
warn: (msg: string) => void;
|
|
1669
|
+
};
|
|
1639
1670
|
spawnReplacementAgent?: SpawnReplacementAgent;
|
|
1640
1671
|
historyStore?: HistoryStore;
|
|
1641
1672
|
historyMaxEntries?: number;
|
|
@@ -1684,6 +1715,7 @@ declare class Session {
|
|
|
1684
1715
|
private idleTimer;
|
|
1685
1716
|
private lastRecordedAt;
|
|
1686
1717
|
private spawnReplacementAgent;
|
|
1718
|
+
private logger;
|
|
1687
1719
|
private agentChangeHandlers;
|
|
1688
1720
|
private agentAdvertisedCommands;
|
|
1689
1721
|
private agentCommandsHandlers;
|
|
@@ -1745,6 +1777,7 @@ declare class Session {
|
|
|
1745
1777
|
private runTitleRegen;
|
|
1746
1778
|
private runInternalPrompt;
|
|
1747
1779
|
private runAgentCommand;
|
|
1780
|
+
private runKillCommand;
|
|
1748
1781
|
private buildSwitchTranscript;
|
|
1749
1782
|
seedFromImport(): Promise<void>;
|
|
1750
1783
|
private broadcastAgentSwitch;
|
|
@@ -1767,6 +1800,8 @@ declare const SessionRecord: z.ZodObject<{
|
|
|
1767
1800
|
lineageId: z.ZodOptional<z.ZodString>;
|
|
1768
1801
|
upstreamSessionId: z.ZodString;
|
|
1769
1802
|
importedFromSessionId: z.ZodOptional<z.ZodString>;
|
|
1803
|
+
importedFromUpstreamSessionId: z.ZodOptional<z.ZodString>;
|
|
1804
|
+
importedFromMachine: z.ZodOptional<z.ZodString>;
|
|
1770
1805
|
agentId: z.ZodString;
|
|
1771
1806
|
cwd: z.ZodString;
|
|
1772
1807
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -1819,6 +1854,8 @@ declare const SessionRecord: z.ZodObject<{
|
|
|
1819
1854
|
costAmount?: number | undefined;
|
|
1820
1855
|
costCurrency?: string | undefined;
|
|
1821
1856
|
} | undefined;
|
|
1857
|
+
importedFromMachine?: string | undefined;
|
|
1858
|
+
importedFromUpstreamSessionId?: string | undefined;
|
|
1822
1859
|
lineageId?: string | undefined;
|
|
1823
1860
|
importedFromSessionId?: string | undefined;
|
|
1824
1861
|
agentCommands?: {
|
|
@@ -1843,6 +1880,8 @@ declare const SessionRecord: z.ZodObject<{
|
|
|
1843
1880
|
costAmount?: number | undefined;
|
|
1844
1881
|
costCurrency?: string | undefined;
|
|
1845
1882
|
} | undefined;
|
|
1883
|
+
importedFromMachine?: string | undefined;
|
|
1884
|
+
importedFromUpstreamSessionId?: string | undefined;
|
|
1846
1885
|
lineageId?: string | undefined;
|
|
1847
1886
|
importedFromSessionId?: string | undefined;
|
|
1848
1887
|
agentCommands?: {
|
|
@@ -1875,6 +1914,7 @@ declare const Bundle: z.ZodObject<{
|
|
|
1875
1914
|
session: z.ZodObject<{
|
|
1876
1915
|
sessionId: z.ZodString;
|
|
1877
1916
|
lineageId: z.ZodString;
|
|
1917
|
+
upstreamSessionId: z.ZodOptional<z.ZodString>;
|
|
1878
1918
|
agentId: z.ZodString;
|
|
1879
1919
|
cwd: z.ZodString;
|
|
1880
1920
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -1915,6 +1955,7 @@ declare const Bundle: z.ZodObject<{
|
|
|
1915
1955
|
updatedAt: string;
|
|
1916
1956
|
lineageId: string;
|
|
1917
1957
|
createdAt: string;
|
|
1958
|
+
upstreamSessionId?: string | undefined;
|
|
1918
1959
|
title?: string | undefined;
|
|
1919
1960
|
currentModel?: string | undefined;
|
|
1920
1961
|
currentMode?: string | undefined;
|
|
@@ -1935,6 +1976,7 @@ declare const Bundle: z.ZodObject<{
|
|
|
1935
1976
|
updatedAt: string;
|
|
1936
1977
|
lineageId: string;
|
|
1937
1978
|
createdAt: string;
|
|
1979
|
+
upstreamSessionId?: string | undefined;
|
|
1938
1980
|
title?: string | undefined;
|
|
1939
1981
|
currentModel?: string | undefined;
|
|
1940
1982
|
currentMode?: string | undefined;
|
|
@@ -1977,6 +2019,7 @@ declare const Bundle: z.ZodObject<{
|
|
|
1977
2019
|
updatedAt: string;
|
|
1978
2020
|
lineageId: string;
|
|
1979
2021
|
createdAt: string;
|
|
2022
|
+
upstreamSessionId?: string | undefined;
|
|
1980
2023
|
title?: string | undefined;
|
|
1981
2024
|
currentModel?: string | undefined;
|
|
1982
2025
|
currentMode?: string | undefined;
|
|
@@ -2011,6 +2054,7 @@ declare const Bundle: z.ZodObject<{
|
|
|
2011
2054
|
updatedAt: string;
|
|
2012
2055
|
lineageId: string;
|
|
2013
2056
|
createdAt: string;
|
|
2057
|
+
upstreamSessionId?: string | undefined;
|
|
2014
2058
|
title?: string | undefined;
|
|
2015
2059
|
currentModel?: string | undefined;
|
|
2016
2060
|
currentMode?: string | undefined;
|
|
@@ -2060,6 +2104,7 @@ interface SessionManagerOptions {
|
|
|
2060
2104
|
idleTimeoutMs?: number;
|
|
2061
2105
|
defaultModels?: Record<string, string>;
|
|
2062
2106
|
sessionHistoryMaxEntries?: number;
|
|
2107
|
+
logger?: AgentLogger;
|
|
2063
2108
|
}
|
|
2064
2109
|
declare class SessionManager {
|
|
2065
2110
|
private registry;
|
|
@@ -2072,6 +2117,7 @@ declare class SessionManager {
|
|
|
2072
2117
|
private defaultModels;
|
|
2073
2118
|
private sessionHistoryMaxEntries;
|
|
2074
2119
|
private metaWriteQueues;
|
|
2120
|
+
private logger?;
|
|
2075
2121
|
constructor(registry: Registry, spawner?: AgentSpawner, store?: SessionStore, options?: SessionManagerOptions);
|
|
2076
2122
|
create(params: CreateSessionParams): Promise<Session>;
|
|
2077
2123
|
resurrect(params: ResurrectParams): Promise<Session>;
|
package/dist/index.js
CHANGED
|
@@ -120,7 +120,13 @@ var TuiConfig = z.object({
|
|
|
120
120
|
// Width cap on the cwd column in the `sessions list` output and the
|
|
121
121
|
// TUI picker. Set higher if you keep deeply-nested working directories
|
|
122
122
|
// and want them visible; the elastic title column shrinks to make room.
|
|
123
|
-
cwdColumnMaxWidth: z.number().int().positive().default(24)
|
|
123
|
+
cwdColumnMaxWidth: z.number().int().positive().default(24),
|
|
124
|
+
// When true (default), emit OSC 9;4 progress-bar control codes so the
|
|
125
|
+
// host terminal can show an indeterminate busy indicator (taskbar pulse
|
|
126
|
+
// on Windows Terminal, dock badge on KDE/Konsole, etc.) while a turn is
|
|
127
|
+
// running. Set false if your terminal renders this obnoxiously or you
|
|
128
|
+
// just don't want it.
|
|
129
|
+
progressIndicator: z.boolean().default(true)
|
|
124
130
|
});
|
|
125
131
|
var ExtensionName = z.string().min(1).regex(/^[A-Za-z0-9._-]+$/, "extension name must be filename-safe");
|
|
126
132
|
var ExtensionBody = z.object({
|
|
@@ -158,7 +164,8 @@ var HydraConfig = z.object({
|
|
|
158
164
|
maxScrollbackLines: 1e4,
|
|
159
165
|
mouse: true,
|
|
160
166
|
logMaxBytes: 5 * 1024 * 1024,
|
|
161
|
-
cwdColumnMaxWidth: 24
|
|
167
|
+
cwdColumnMaxWidth: 24,
|
|
168
|
+
progressIndicator: true
|
|
162
169
|
})
|
|
163
170
|
});
|
|
164
171
|
var HydraConfigReadOnly = HydraConfig.extend({
|
|
@@ -1013,6 +1020,11 @@ var SessionListEntry = z3.object({
|
|
|
1013
1020
|
// Last-known usage snapshot so list views can show per-session cost
|
|
1014
1021
|
// (and tokens, in callers that care) without resurrecting cold sessions.
|
|
1015
1022
|
currentUsage: SessionListUsage.optional(),
|
|
1023
|
+
// Origin host (and origin upstream id) for imported sessions. Picker
|
|
1024
|
+
// uses the host to fill in the UPSTREAM cell pre-first-attach;
|
|
1025
|
+
// future "connect back to origin" callers would dial both.
|
|
1026
|
+
importedFromMachine: z3.string().optional(),
|
|
1027
|
+
importedFromUpstreamSessionId: z3.string().optional(),
|
|
1016
1028
|
updatedAt: z3.string(),
|
|
1017
1029
|
attachedClients: z3.number().int().nonnegative(),
|
|
1018
1030
|
status: z3.enum(["live", "cold"]).default("live"),
|
|
@@ -1323,12 +1335,14 @@ var AgentInstance = class _AgentInstance {
|
|
|
1323
1335
|
killed = false;
|
|
1324
1336
|
stderrTail = "";
|
|
1325
1337
|
stderrTailBytes;
|
|
1338
|
+
logger;
|
|
1326
1339
|
exitHandlers = [];
|
|
1327
1340
|
constructor(opts, child) {
|
|
1328
1341
|
this.agentId = opts.agentId;
|
|
1329
1342
|
this.cwd = opts.cwd;
|
|
1330
1343
|
this.child = child;
|
|
1331
1344
|
this.stderrTailBytes = opts.stderrTailBytes ?? DEFAULT_STDERR_TAIL_BYTES;
|
|
1345
|
+
this.logger = opts.logger;
|
|
1332
1346
|
if (!child.stdout || !child.stdin) {
|
|
1333
1347
|
throw new Error("agent subprocess missing stdio");
|
|
1334
1348
|
}
|
|
@@ -1337,7 +1351,15 @@ var AgentInstance = class _AgentInstance {
|
|
|
1337
1351
|
child.stderr?.setEncoding("utf8");
|
|
1338
1352
|
child.stderr?.on("data", (chunk) => {
|
|
1339
1353
|
this.stderrTail = (this.stderrTail + chunk).slice(-this.stderrTailBytes);
|
|
1340
|
-
|
|
1354
|
+
if (this.logger) {
|
|
1355
|
+
for (const line of chunk.split(/\r?\n/)) {
|
|
1356
|
+
if (line.length > 0) {
|
|
1357
|
+
this.logger.info(`[${opts.agentId}] ${line}`);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
} else {
|
|
1361
|
+
process.stderr.write(`[${opts.agentId}] ${chunk}`);
|
|
1362
|
+
}
|
|
1341
1363
|
});
|
|
1342
1364
|
child.on("error", (err) => {
|
|
1343
1365
|
const msg = this.formatFailure(err.message);
|
|
@@ -1345,9 +1367,16 @@ var AgentInstance = class _AgentInstance {
|
|
|
1345
1367
|
});
|
|
1346
1368
|
child.on("exit", (code, signal) => {
|
|
1347
1369
|
this.exited = true;
|
|
1348
|
-
if (
|
|
1370
|
+
if (this.killed) {
|
|
1371
|
+
this.logger?.info(
|
|
1372
|
+
`agent ${opts.agentId} pid=${child.pid} exited after kill code=${code} signal=${signal}`
|
|
1373
|
+
);
|
|
1374
|
+
} else {
|
|
1349
1375
|
const reason = `agent ${opts.agentId} exited before responding (code=${code} signal=${signal})`;
|
|
1350
1376
|
this.connection.fail(new Error(this.formatFailure(reason)));
|
|
1377
|
+
this.logger?.warn(
|
|
1378
|
+
`agent ${opts.agentId} pid=${child.pid} exited unexpectedly code=${code} signal=${signal}`
|
|
1379
|
+
);
|
|
1351
1380
|
}
|
|
1352
1381
|
for (const handler of this.exitHandlers) {
|
|
1353
1382
|
handler(code, signal);
|
|
@@ -1368,7 +1397,15 @@ stderr: ${tail}` : reason;
|
|
|
1368
1397
|
const child = spawn3(opts.plan.command, opts.plan.args, {
|
|
1369
1398
|
cwd: opts.cwd,
|
|
1370
1399
|
env,
|
|
1371
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
1400
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1401
|
+
// setsid the agent into its own session/process group. The daemon
|
|
1402
|
+
// already runs in its own setsid'd session, but macOS terminals
|
|
1403
|
+
// (iTerm2, Terminal.app) sometimes still reach inherited child
|
|
1404
|
+
// processes when the user closes a window — putting the agent
|
|
1405
|
+
// one more session-boundary away keeps it alive across terminal
|
|
1406
|
+
// restarts. The daemon still owns the pipes, so this.kill()
|
|
1407
|
+
// continues to terminate it cleanly on idle/close.
|
|
1408
|
+
detached: true
|
|
1372
1409
|
});
|
|
1373
1410
|
return new _AgentInstance(opts, child);
|
|
1374
1411
|
}
|
|
@@ -1383,6 +1420,9 @@ stderr: ${tail}` : reason;
|
|
|
1383
1420
|
return;
|
|
1384
1421
|
}
|
|
1385
1422
|
this.killed = true;
|
|
1423
|
+
this.logger?.info(
|
|
1424
|
+
`agent ${this.agentId} pid=${this.child.pid} kill requested signal=${signal}`
|
|
1425
|
+
);
|
|
1386
1426
|
await this.connection.close().catch(() => void 0);
|
|
1387
1427
|
this.child.kill(signal);
|
|
1388
1428
|
}
|
|
@@ -1408,6 +1448,11 @@ var HYDRA_COMMANDS = [
|
|
|
1408
1448
|
name: "hydra agent",
|
|
1409
1449
|
argsHint: "<agent>",
|
|
1410
1450
|
description: "Swap the agent backing this session, preserving context"
|
|
1451
|
+
},
|
|
1452
|
+
{
|
|
1453
|
+
verb: "kill",
|
|
1454
|
+
name: "hydra kill",
|
|
1455
|
+
description: "Close this session (kills the agent; record is kept so it can be resumed later)"
|
|
1411
1456
|
}
|
|
1412
1457
|
];
|
|
1413
1458
|
var VERB_INDEX = new Map(HYDRA_COMMANDS.map((c) => [c.verb, c]));
|
|
@@ -1495,6 +1540,7 @@ var Session = class {
|
|
|
1495
1540
|
// and noisy state churn keep a quiet session alive forever.
|
|
1496
1541
|
lastRecordedAt;
|
|
1497
1542
|
spawnReplacementAgent;
|
|
1543
|
+
logger;
|
|
1498
1544
|
agentChangeHandlers = [];
|
|
1499
1545
|
// Last available_commands_update we observed from the agent. Stored
|
|
1500
1546
|
// so we can re-broadcast a merged (hydra ∪ agent) list whenever
|
|
@@ -1526,6 +1572,7 @@ var Session = class {
|
|
|
1526
1572
|
}
|
|
1527
1573
|
this.idleTimeoutMs = init.idleTimeoutMs ?? 0;
|
|
1528
1574
|
this.spawnReplacementAgent = init.spawnReplacementAgent;
|
|
1575
|
+
this.logger = init.logger;
|
|
1529
1576
|
if (init.firstPromptSeeded) {
|
|
1530
1577
|
this.firstPromptSeeded = true;
|
|
1531
1578
|
}
|
|
@@ -1855,6 +1902,9 @@ var Session = class {
|
|
|
1855
1902
|
if (this.closed) {
|
|
1856
1903
|
return;
|
|
1857
1904
|
}
|
|
1905
|
+
this.logger?.info(
|
|
1906
|
+
`session ${this.sessionId} closing deleteRecord=${opts.deleteRecord ?? false} regenTitle=${opts.regenTitle ?? false}`
|
|
1907
|
+
);
|
|
1858
1908
|
this.cancelIdleTimer();
|
|
1859
1909
|
if (opts.regenTitle && this.firstPromptSeeded) {
|
|
1860
1910
|
const timeoutMs = opts.regenTitleTimeoutMs ?? 5e3;
|
|
@@ -2107,6 +2157,8 @@ var Session = class {
|
|
|
2107
2157
|
return this.runTitleCommand(arg);
|
|
2108
2158
|
case "agent":
|
|
2109
2159
|
return this.runAgentCommand(arg);
|
|
2160
|
+
case "kill":
|
|
2161
|
+
return this.runKillCommand();
|
|
2110
2162
|
default: {
|
|
2111
2163
|
const err = new Error(
|
|
2112
2164
|
`no dispatcher for /hydra verb ${verb}`
|
|
@@ -2218,6 +2270,17 @@ var Session = class {
|
|
|
2218
2270
|
return { stopReason: "end_turn" };
|
|
2219
2271
|
});
|
|
2220
2272
|
}
|
|
2273
|
+
// Close this session in-place. Bypasses enqueuePrompt deliberately so a
|
|
2274
|
+
// mid-turn /hydra kill takes effect immediately — agent.kill() will tear
|
|
2275
|
+
// down any in-flight request as a side effect. The record is kept
|
|
2276
|
+
// (deleteRecord:false) so the session goes cold and can be resurrected.
|
|
2277
|
+
// Returns end_turn so the prompt() caller's response resolves normally,
|
|
2278
|
+
// but every attached client has already received hydra-acp/session_closed
|
|
2279
|
+
// by the time this returns.
|
|
2280
|
+
async runKillCommand() {
|
|
2281
|
+
await this.close({ deleteRecord: false });
|
|
2282
|
+
return { stopReason: "end_turn" };
|
|
2283
|
+
}
|
|
2221
2284
|
// Walk the persisted history and produce a labeled transcript suitable
|
|
2222
2285
|
// for handing to a fresh agent. Includes user prompts, agent replies,
|
|
2223
2286
|
// and tool-call outcomes; skips hydra-synthesized markers (so multi-hop
|
|
@@ -2409,6 +2472,10 @@ _(switched from \`${oldAgentId}\` to \`${newAgentId}\`)_
|
|
|
2409
2472
|
return;
|
|
2410
2473
|
}
|
|
2411
2474
|
const opts = this.firstPromptSeeded ? { deleteRecord: false, regenTitle: true } : { deleteRecord: true };
|
|
2475
|
+
const idleSec = Math.round(idle / 1e3);
|
|
2476
|
+
this.logger?.info(
|
|
2477
|
+
`session ${this.sessionId} idle timeout fired after ${idleSec}s (window=${Math.round(this.idleTimeoutMs / 1e3)}s) \u2014 closing`
|
|
2478
|
+
);
|
|
2412
2479
|
void this.close(opts).catch(() => void 0);
|
|
2413
2480
|
}
|
|
2414
2481
|
cancelIdleTimer() {
|
|
@@ -2777,6 +2844,16 @@ var SessionRecord = z4.object({
|
|
|
2777
2844
|
// origin's local id at export time, kept for debuggability and as a
|
|
2778
2845
|
// breadcrumb in `sessions list` (informational, not used for routing).
|
|
2779
2846
|
importedFromSessionId: z4.string().optional(),
|
|
2847
|
+
// Origin's agent-side session id at export time. Carried as a
|
|
2848
|
+
// breadcrumb and as the handle a future "connect back to origin"
|
|
2849
|
+
// feature would dial. Absent when the origin record had no upstream
|
|
2850
|
+
// bound (re-export of an imported, not-yet-attached session).
|
|
2851
|
+
importedFromUpstreamSessionId: z4.string().optional(),
|
|
2852
|
+
// Hostname of the machine that exported the bundle we imported
|
|
2853
|
+
// (i.e. the most recent hop, not necessarily the true multi-hop
|
|
2854
|
+
// origin). Surfaced in the picker so imported rows don't look like
|
|
2855
|
+
// they materialized from nowhere.
|
|
2856
|
+
importedFromMachine: z4.string().optional(),
|
|
2780
2857
|
agentId: z4.string(),
|
|
2781
2858
|
cwd: z4.string(),
|
|
2782
2859
|
title: z4.string().optional(),
|
|
@@ -2897,6 +2974,8 @@ function recordFromMemorySession(args) {
|
|
|
2897
2974
|
lineageId: args.lineageId,
|
|
2898
2975
|
upstreamSessionId: args.upstreamSessionId,
|
|
2899
2976
|
importedFromSessionId: args.importedFromSessionId,
|
|
2977
|
+
importedFromUpstreamSessionId: args.importedFromUpstreamSessionId,
|
|
2978
|
+
importedFromMachine: args.importedFromMachine,
|
|
2900
2979
|
agentId: args.agentId,
|
|
2901
2980
|
cwd: args.cwd,
|
|
2902
2981
|
title: args.title,
|
|
@@ -3114,6 +3193,7 @@ var SessionManager = class {
|
|
|
3114
3193
|
this.histories = new HistoryStore({ maxEntries: this.sessionHistoryMaxEntries });
|
|
3115
3194
|
this.idleTimeoutMs = options.idleTimeoutMs ?? 0;
|
|
3116
3195
|
this.defaultModels = options.defaultModels ?? {};
|
|
3196
|
+
this.logger = options.logger;
|
|
3117
3197
|
}
|
|
3118
3198
|
registry;
|
|
3119
3199
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -3128,6 +3208,7 @@ var SessionManager = class {
|
|
|
3128
3208
|
// concurrent snapshot updates (e.g. an agent emitting model + mode
|
|
3129
3209
|
// back-to-back) don't lose writes via interleaved reads.
|
|
3130
3210
|
metaWriteQueues = /* @__PURE__ */ new Map();
|
|
3211
|
+
logger;
|
|
3131
3212
|
async create(params) {
|
|
3132
3213
|
const fresh = await this.bootstrapAgent({
|
|
3133
3214
|
agentId: params.agentId,
|
|
@@ -3145,6 +3226,7 @@ var SessionManager = class {
|
|
|
3145
3226
|
title: params.title,
|
|
3146
3227
|
agentArgs: params.agentArgs,
|
|
3147
3228
|
idleTimeoutMs: this.idleTimeoutMs,
|
|
3229
|
+
logger: this.logger,
|
|
3148
3230
|
spawnReplacementAgent: (p) => this.bootstrapAgent({ ...p, mcpServers: [] }),
|
|
3149
3231
|
historyStore: this.histories,
|
|
3150
3232
|
historyMaxEntries: this.sessionHistoryMaxEntries,
|
|
@@ -3238,6 +3320,7 @@ var SessionManager = class {
|
|
|
3238
3320
|
title: params.title,
|
|
3239
3321
|
agentArgs: params.agentArgs,
|
|
3240
3322
|
idleTimeoutMs: this.idleTimeoutMs,
|
|
3323
|
+
logger: this.logger,
|
|
3241
3324
|
spawnReplacementAgent: (p) => this.bootstrapAgent({ ...p, mcpServers: [] }),
|
|
3242
3325
|
historyStore: this.histories,
|
|
3243
3326
|
historyMaxEntries: this.sessionHistoryMaxEntries,
|
|
@@ -3284,6 +3367,7 @@ var SessionManager = class {
|
|
|
3284
3367
|
title: params.title,
|
|
3285
3368
|
agentArgs: params.agentArgs,
|
|
3286
3369
|
idleTimeoutMs: this.idleTimeoutMs,
|
|
3370
|
+
logger: this.logger,
|
|
3287
3371
|
spawnReplacementAgent: (p) => this.bootstrapAgent({ ...p, mcpServers: [] }),
|
|
3288
3372
|
historyStore: this.histories,
|
|
3289
3373
|
historyMaxEntries: this.sessionHistoryMaxEntries,
|
|
@@ -3548,6 +3632,8 @@ var SessionManager = class {
|
|
|
3548
3632
|
agentId: r.agentId,
|
|
3549
3633
|
currentModel: r.currentModel,
|
|
3550
3634
|
currentUsage: r.currentUsage,
|
|
3635
|
+
importedFromMachine: r.importedFromMachine,
|
|
3636
|
+
importedFromUpstreamSessionId: r.importedFromUpstreamSessionId,
|
|
3551
3637
|
updatedAt: used,
|
|
3552
3638
|
attachedClients: 0,
|
|
3553
3639
|
status: "cold"
|
|
@@ -3655,6 +3741,8 @@ var SessionManager = class {
|
|
|
3655
3741
|
lineageId: args.bundle.session.lineageId,
|
|
3656
3742
|
upstreamSessionId: "",
|
|
3657
3743
|
importedFromSessionId: args.bundle.session.sessionId,
|
|
3744
|
+
importedFromUpstreamSessionId: args.bundle.session.upstreamSessionId,
|
|
3745
|
+
importedFromMachine: args.bundle.exportedFrom.machine,
|
|
3658
3746
|
agentId: args.bundle.session.agentId,
|
|
3659
3747
|
cwd: args.cwd ?? args.bundle.session.cwd,
|
|
3660
3748
|
title: args.bundle.session.title,
|
|
@@ -3777,6 +3865,8 @@ function mergeForPersistence(session, existing) {
|
|
|
3777
3865
|
lineageId: existing?.lineageId ?? generateLineageId(),
|
|
3778
3866
|
upstreamSessionId: session.upstreamSessionId,
|
|
3779
3867
|
importedFromSessionId: existing?.importedFromSessionId,
|
|
3868
|
+
importedFromUpstreamSessionId: existing?.importedFromUpstreamSessionId,
|
|
3869
|
+
importedFromMachine: existing?.importedFromMachine,
|
|
3780
3870
|
agentId: session.agentId,
|
|
3781
3871
|
cwd: session.cwd,
|
|
3782
3872
|
title: session.title,
|
|
@@ -4362,6 +4452,12 @@ var BundleSession = z5.object({
|
|
|
4362
4452
|
// Required on bundles — the export path backfills if the source
|
|
4363
4453
|
// record was written before lineageId existed.
|
|
4364
4454
|
lineageId: z5.string(),
|
|
4455
|
+
// The exporter's agent-side session id at export time. Carried so
|
|
4456
|
+
// importers can persist it as a breadcrumb (and, eventually, as the
|
|
4457
|
+
// handle a "connect back to origin" feature would need). Omitted on
|
|
4458
|
+
// bundles whose source record never bound to an agent (e.g. a
|
|
4459
|
+
// re-export of an imported, not-yet-attached session).
|
|
4460
|
+
upstreamSessionId: z5.string().optional(),
|
|
4365
4461
|
agentId: z5.string(),
|
|
4366
4462
|
cwd: z5.string(),
|
|
4367
4463
|
title: z5.string().optional(),
|
|
@@ -4394,6 +4490,7 @@ function encodeBundle(params) {
|
|
|
4394
4490
|
session: {
|
|
4395
4491
|
sessionId: params.record.sessionId,
|
|
4396
4492
|
lineageId: params.record.lineageId,
|
|
4493
|
+
...params.record.upstreamSessionId ? { upstreamSessionId: params.record.upstreamSessionId } : {},
|
|
4397
4494
|
agentId: params.record.agentId,
|
|
4398
4495
|
cwd: params.record.cwd,
|
|
4399
4496
|
...params.record.title !== void 0 ? { title: params.record.title } : {},
|
|
@@ -5185,11 +5282,20 @@ async function startDaemon(config) {
|
|
|
5185
5282
|
await auth(request, reply);
|
|
5186
5283
|
});
|
|
5187
5284
|
const registry = new Registry(config);
|
|
5188
|
-
const
|
|
5285
|
+
const agentLogger = {
|
|
5286
|
+
info: (msg) => app.log.info(msg),
|
|
5287
|
+
warn: (msg) => app.log.warn(msg)
|
|
5288
|
+
};
|
|
5289
|
+
const spawner = (opts) => AgentInstance.spawn({
|
|
5290
|
+
...opts,
|
|
5291
|
+
stderrTailBytes: config.daemon.agentStderrTailBytes,
|
|
5292
|
+
logger: agentLogger
|
|
5293
|
+
});
|
|
5189
5294
|
const manager = new SessionManager(registry, spawner, void 0, {
|
|
5190
5295
|
idleTimeoutMs: config.daemon.sessionIdleTimeoutSeconds * 1e3,
|
|
5191
5296
|
defaultModels: config.defaultModels,
|
|
5192
|
-
sessionHistoryMaxEntries: config.daemon.sessionHistoryMaxEntries
|
|
5297
|
+
sessionHistoryMaxEntries: config.daemon.sessionHistoryMaxEntries,
|
|
5298
|
+
logger: agentLogger
|
|
5193
5299
|
});
|
|
5194
5300
|
const extensions = new ExtensionManager(extensionList(config));
|
|
5195
5301
|
registerHealthRoutes(app, HYDRA_VERSION);
|