@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/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
- process.stderr.write(`[${opts.agentId}] ${chunk}`);
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 (!this.killed) {
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 spawner = (opts) => AgentInstance.spawn({ ...opts, stderrTailBytes: config.daemon.agentStderrTailBytes });
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydra-acp/cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Multi-client ACP session daemon: spawn agents, attach over WSS, multiplex sessions across editors.",
5
5
  "license": "MIT",
6
6
  "type": "module",