handsoff 0.1.2-beta.1 → 0.1.2-beta.2

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.
@@ -2,12 +2,30 @@
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
6
8
  var __typeError = (msg) => {
7
9
  throw TypeError(msg);
8
10
  };
9
11
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
12
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
13
+ var __esm = (fn, res) => function __init() {
14
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
15
+ };
16
+ var __export = (target, all) => {
17
+ for (var name in all)
18
+ __defProp(target, name, { get: all[name], enumerable: true });
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
11
29
  var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
12
30
  var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
13
31
  var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
@@ -47,7 +65,311 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
47
65
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
48
66
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
49
67
 
68
+ // node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js
69
+ import path from "path";
70
+ import { fileURLToPath } from "url";
71
+ var init_esm_shims = __esm({
72
+ "node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js"() {
73
+ "use strict";
74
+ }
75
+ });
76
+
77
+ // src/adapters/channels/feishu/templates/message.ts
78
+ var message_exports = {};
79
+ __export(message_exports, {
80
+ buildMessageCard: () => buildMessageCard
81
+ });
82
+ function buildMessageCard(input) {
83
+ const elements = [];
84
+ elements.push({
85
+ tag: "markdown",
86
+ content: input.content,
87
+ text_align: "left",
88
+ text_size: "normal",
89
+ margin: "0px 0px 0px 0px"
90
+ });
91
+ if (input.meta) {
92
+ elements.push({ tag: "hr", margin: "0px 0px 0px 0px" });
93
+ elements.push({
94
+ tag: "column_set",
95
+ flex_mode: "stretch",
96
+ horizontal_spacing: "8px",
97
+ horizontal_align: "left",
98
+ columns: [
99
+ {
100
+ tag: "column",
101
+ width: "weighted",
102
+ elements: [
103
+ {
104
+ tag: "markdown",
105
+ content: input.meta,
106
+ text_align: "left",
107
+ text_size: "notation",
108
+ margin: "0px 0px 0px 0px",
109
+ icon: {
110
+ tag: "standard_icon",
111
+ token: "ccm-filter_outlined",
112
+ color: "grey"
113
+ }
114
+ }
115
+ ],
116
+ vertical_spacing: "8px",
117
+ horizontal_align: "left",
118
+ vertical_align: "center",
119
+ weight: 1
120
+ }
121
+ ],
122
+ margin: "0px 0px 0px 0px"
123
+ });
124
+ }
125
+ const card = {
126
+ schema: "2.0",
127
+ config: { update_multi: true },
128
+ body: {
129
+ direction: "vertical",
130
+ elements
131
+ },
132
+ header: {
133
+ title: {
134
+ tag: "plain_text",
135
+ content: input.title
136
+ },
137
+ subtitle: {
138
+ tag: "plain_text",
139
+ content: ""
140
+ },
141
+ template: "blue",
142
+ padding: "12px 8px 12px 8px"
143
+ }
144
+ };
145
+ return JSON.stringify(card);
146
+ }
147
+ var init_message = __esm({
148
+ "src/adapters/channels/feishu/templates/message.ts"() {
149
+ "use strict";
150
+ init_esm_shims();
151
+ }
152
+ });
153
+
154
+ // src/adapters/channels/feishu/templates/permission.ts
155
+ var permission_exports = {};
156
+ __export(permission_exports, {
157
+ buildPermissionCard: () => buildPermissionCard
158
+ });
159
+ function buildPermissionCard(input) {
160
+ const columns = input.buttons.map((btn) => {
161
+ const buttonEl = {
162
+ tag: "button",
163
+ text: { tag: "plain_text", content: btn.text },
164
+ type: btn.type,
165
+ width: "default",
166
+ size: "small",
167
+ behaviors: [
168
+ {
169
+ type: "callback",
170
+ value: { action: btn.value }
171
+ }
172
+ ]
173
+ };
174
+ if (btn.confirm) {
175
+ buttonEl.confirm = {
176
+ title: { tag: "plain_text", content: btn.confirm.title },
177
+ text: { tag: "plain_text", content: btn.confirm.text }
178
+ };
179
+ }
180
+ return {
181
+ tag: "column",
182
+ width: "auto",
183
+ elements: [buttonEl],
184
+ padding: "0px 0px 0px 0px",
185
+ direction: "horizontal",
186
+ horizontal_spacing: "4px",
187
+ vertical_spacing: "4px",
188
+ horizontal_align: "center",
189
+ vertical_align: "center",
190
+ margin: "0px 0px 0px 0px"
191
+ };
192
+ });
193
+ const card = {
194
+ schema: "2.0",
195
+ config: { update_multi: true },
196
+ body: {
197
+ direction: "vertical",
198
+ elements: [
199
+ {
200
+ tag: "markdown",
201
+ content: input.content,
202
+ text_align: "left",
203
+ text_size: "normal",
204
+ margin: "0px 0px 0px 0px"
205
+ },
206
+ { tag: "hr", margin: "0px 0px 0px 0px" },
207
+ {
208
+ tag: "column_set",
209
+ horizontal_spacing: "4px",
210
+ horizontal_align: "left",
211
+ columns,
212
+ margin: "0px 0px 0px 0px"
213
+ }
214
+ ]
215
+ },
216
+ header: {
217
+ title: { tag: "plain_text", content: input.title },
218
+ subtitle: { tag: "plain_text", content: "" },
219
+ template: "blue",
220
+ padding: "12px 8px 12px 8px"
221
+ }
222
+ };
223
+ return JSON.stringify(card);
224
+ }
225
+ var init_permission = __esm({
226
+ "src/adapters/channels/feishu/templates/permission.ts"() {
227
+ "use strict";
228
+ init_esm_shims();
229
+ }
230
+ });
231
+
232
+ // src/adapters/channels/feishu/templates/question.ts
233
+ var question_exports = {};
234
+ __export(question_exports, {
235
+ buildQuestionCard: () => buildQuestionCard
236
+ });
237
+ function buildQuestionCard(input) {
238
+ const elements = [
239
+ {
240
+ tag: "markdown",
241
+ content: input.content,
242
+ text_align: "left",
243
+ text_size: "normal",
244
+ margin: "0px 0px 0px 0px"
245
+ },
246
+ { tag: "hr", margin: "0px 0px 0px 0px" }
247
+ ];
248
+ if (input.mode === "single") {
249
+ const columns = input.items.map((item) => ({
250
+ tag: "column",
251
+ width: "auto",
252
+ elements: [
253
+ {
254
+ tag: "button",
255
+ text: { tag: "plain_text", content: item.label },
256
+ type: "primary",
257
+ width: "default",
258
+ size: "small",
259
+ behaviors: [
260
+ {
261
+ type: "callback",
262
+ value: { action: "select", optionId: item.id }
263
+ }
264
+ ]
265
+ }
266
+ ],
267
+ padding: "0px 0px 0px 0px",
268
+ direction: "horizontal",
269
+ horizontal_spacing: "4px",
270
+ vertical_spacing: "4px",
271
+ horizontal_align: "center",
272
+ vertical_align: "center",
273
+ margin: "0px 0px 0px 0px"
274
+ }));
275
+ elements.push({
276
+ tag: "column_set",
277
+ horizontal_spacing: "4px",
278
+ horizontal_align: "left",
279
+ columns,
280
+ margin: "0px 0px 0px 0px"
281
+ });
282
+ } else {
283
+ const checkerElements = input.items.map((item) => ({
284
+ tag: "checker",
285
+ element_id: `checker_${item.id}`,
286
+ name: `checker_${item.id}`,
287
+ checked: false,
288
+ text: { tag: "plain_text", content: item.label },
289
+ behaviors: [
290
+ {
291
+ type: "callback",
292
+ value: { action: "check", optionId: item.id }
293
+ }
294
+ ]
295
+ }));
296
+ elements.push({
297
+ tag: "column_set",
298
+ horizontal_spacing: "4px",
299
+ horizontal_align: "left",
300
+ columns: [
301
+ {
302
+ tag: "column",
303
+ width: "weighted",
304
+ elements: checkerElements,
305
+ padding: "0px 0px 0px 0px",
306
+ direction: "horizontal",
307
+ horizontal_spacing: "4px",
308
+ vertical_spacing: "4px",
309
+ horizontal_align: "left",
310
+ vertical_align: "center",
311
+ margin: "0px 0px 0px 0px",
312
+ weight: 1
313
+ },
314
+ {
315
+ tag: "column",
316
+ width: "auto",
317
+ elements: [
318
+ {
319
+ tag: "button",
320
+ text: { tag: "plain_text", content: "Submit" },
321
+ type: "primary_filled",
322
+ width: "default",
323
+ size: "small",
324
+ margin: "0px 0px 0px 0px",
325
+ behaviors: [
326
+ {
327
+ type: "callback",
328
+ value: { action: "submit" }
329
+ }
330
+ ]
331
+ }
332
+ ],
333
+ padding: "0px 0px 0px 0px",
334
+ direction: "vertical",
335
+ horizontal_spacing: "8px",
336
+ vertical_spacing: "8px",
337
+ horizontal_align: "right",
338
+ vertical_align: "center",
339
+ margin: "0px 0px 0px 0px"
340
+ }
341
+ ],
342
+ margin: "0px 0px 0px 0px"
343
+ });
344
+ }
345
+ const card = {
346
+ schema: "2.0",
347
+ config: { update_multi: true },
348
+ body: {
349
+ direction: "vertical",
350
+ elements
351
+ },
352
+ header: {
353
+ title: { tag: "plain_text", content: input.title },
354
+ subtitle: { tag: "plain_text", content: "" },
355
+ template: "blue",
356
+ padding: "12px 8px 12px 8px"
357
+ }
358
+ };
359
+ return JSON.stringify(card);
360
+ }
361
+ var init_question = __esm({
362
+ "src/adapters/channels/feishu/templates/question.ts"() {
363
+ "use strict";
364
+ init_esm_shims();
365
+ }
366
+ });
367
+
368
+ // src/gateway/process.ts
369
+ init_esm_shims();
370
+
50
371
  // src/shared/pidfile.ts
372
+ init_esm_shims();
51
373
  import { writeFileSync, readFileSync, existsSync, unlinkSync } from "fs";
52
374
  import { dirname } from "path";
53
375
  import { mkdirSync } from "fs";
@@ -68,6 +390,7 @@ function removePidFile(pidFilePath) {
68
390
  }
69
391
 
70
392
  // src/shared/logger.ts
393
+ init_esm_shims();
71
394
  import pino from "pino";
72
395
  import { mkdirSync as mkdirSync2, existsSync as existsSync2, appendFileSync } from "fs";
73
396
  import { dirname as dirname2 } from "path";
@@ -184,6 +507,7 @@ function getLogger(_level) {
184
507
  }
185
508
 
186
509
  // src/shared/session-logger.ts
510
+ init_esm_shims();
187
511
  var SessionLogger = class {
188
512
  bus;
189
513
  unsubscribeFns = [];
@@ -264,7 +588,11 @@ var SessionLogger = class {
264
588
  }
265
589
  };
266
590
 
591
+ // src/gateway/index.ts
592
+ init_esm_shims();
593
+
267
594
  // src/core/agent/AgentRegistry.ts
595
+ init_esm_shims();
268
596
  import { randomBytes } from "crypto";
269
597
  var AgentRegistry = class {
270
598
  registrations = /* @__PURE__ */ new Map();
@@ -294,9 +622,11 @@ var AgentRegistry = class {
294
622
  };
295
623
 
296
624
  // src/core/session/SessionManager.ts
625
+ init_esm_shims();
297
626
  import { randomUUID } from "crypto";
298
627
 
299
628
  // src/core/adapter/AgentAdapterRegistry.ts
629
+ init_esm_shims();
300
630
  var AgentAdapterRegistry = class _AgentAdapterRegistry {
301
631
  static instance = null;
302
632
  adapters = /* @__PURE__ */ new Map();
@@ -366,52 +696,84 @@ var AgentAdapterRegistry = class _AgentAdapterRegistry {
366
696
  };
367
697
 
368
698
  // src/core/session/Session.ts
699
+ init_esm_shims();
369
700
  var Session = class {
370
701
  id;
371
- agentType;
702
+ agent;
372
703
  token;
373
704
  metadata;
374
- adapter;
375
705
  createdAt;
706
+ _status = "active";
707
+ _updatedAt;
708
+ _transportState;
376
709
  cwd;
377
- status = "active";
378
- transportState;
710
+ model;
711
+ permissionMode;
712
+ slashCommands;
379
713
  constructor(options) {
380
714
  this.id = options.id;
381
- this.agentType = options.agentType;
715
+ this.agent = options.adapter;
382
716
  this.token = options.token;
383
717
  this.metadata = options.metadata ?? {};
384
- this.adapter = options.adapter;
385
- this.transportState = options.transportState;
386
- this.createdAt = Date.now();
718
+ this._transportState = options.transportState;
719
+ this.createdAt = options.createdAt ?? Date.now();
720
+ this._updatedAt = this.createdAt;
387
721
  this.cwd = options.cwd;
388
722
  }
723
+ get agentType() {
724
+ return this.agent.agentType;
725
+ }
726
+ get status() {
727
+ return this._status;
728
+ }
729
+ get updatedAt() {
730
+ return this._updatedAt;
731
+ }
732
+ get transportState() {
733
+ return this._transportState;
734
+ }
735
+ updateInfo(partial) {
736
+ if (partial.status !== void 0) this._status = partial.status;
737
+ if (partial.cwd !== void 0) this.cwd = partial.cwd;
738
+ if (partial.model !== void 0) this.model = partial.model;
739
+ if (partial.permissionMode !== void 0) this.permissionMode = partial.permissionMode;
740
+ if (partial.slashCommands !== void 0) this.slashCommands = partial.slashCommands;
741
+ this._updatedAt = Date.now();
742
+ }
389
743
  async sendCommand(command) {
390
- if (this.status !== "active") {
744
+ if (this._status !== "active") {
391
745
  throw new Error(`Cannot send command to closed session: ${this.id}`);
392
746
  }
393
- return this.adapter.sendCommand(this.transportState, command);
747
+ return this.agent.sendCommand(this._transportState, command);
394
748
  }
395
749
  async close() {
396
- if (this.status !== "active") {
750
+ if (this._status !== "active") {
397
751
  return;
398
752
  }
399
- await this.adapter.closeTransportState(this.transportState);
400
- this.status = "closed";
753
+ await this.agent.closeTransportState(this._transportState);
754
+ this._status = "closed";
401
755
  }
756
+ /** @deprecated Use `status` getter instead */
402
757
  getStatus() {
403
- return this.status;
758
+ return this._status;
759
+ }
760
+ /** @deprecated Use `toInfo()` instead */
761
+ toJSON() {
762
+ return this.toInfo();
404
763
  }
405
764
  toInfo() {
406
765
  return {
407
766
  id: this.id,
408
767
  agentType: this.agentType,
409
- status: this.status,
768
+ transportType: this.agent.transportType,
769
+ status: this._status,
410
770
  createdAt: this.createdAt,
411
- updatedAt: Date.now(),
771
+ updatedAt: this._updatedAt,
412
772
  token: this.token,
413
- startedAt: new Date(this.createdAt),
414
- cwd: this.cwd
773
+ cwd: this.cwd,
774
+ model: this.model,
775
+ permissionMode: this.permissionMode,
776
+ slashCommands: this.slashCommands
415
777
  };
416
778
  }
417
779
  };
@@ -434,12 +796,12 @@ var SessionManager = class {
434
796
  this.logger.debug({ sessionId, optionsCwd: options?.cwd, transportCwd, resolvedCwd: cwd }, "[SessionManager] Resolved cwd for session");
435
797
  const session = new Session({
436
798
  id: sessionId,
437
- agentType,
438
799
  adapter,
439
800
  transportState,
440
801
  token: options?.token,
441
802
  metadata: options?.metadata,
442
- cwd
803
+ cwd,
804
+ createdAt: options?.createdAt
443
805
  });
444
806
  this.sessions.set(sessionId, session);
445
807
  this.logger.info({ sessionId, agentType, cwd, token: options?.token?.slice(0, 8) }, "[Session] Created");
@@ -469,13 +831,37 @@ var SessionManager = class {
469
831
  getSessionCount() {
470
832
  return this.sessions.size;
471
833
  }
834
+ updateSessionInfo(sessionId, info) {
835
+ const session = this.sessions.get(sessionId);
836
+ if (!session) {
837
+ this.logger.warn({ sessionId }, "[SessionManager] updateSessionInfo: session not found");
838
+ return false;
839
+ }
840
+ session.updateInfo(info);
841
+ this.logger.debug({ sessionId, ...info }, "[SessionManager] Session info updated");
842
+ return true;
843
+ }
472
844
  };
473
845
 
846
+ // src/gateway/events.ts
847
+ init_esm_shims();
848
+
849
+ // src/gateway/interaction-service.ts
850
+ init_esm_shims();
851
+
474
852
  // src/shared/permissions.ts
853
+ init_esm_shims();
475
854
  import { readFileSync as readFileSync2, existsSync as existsSync3 } from "fs";
476
855
  import { join } from "path";
477
856
 
857
+ // node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/dist/esm/index.js
858
+ init_esm_shims();
859
+
860
+ // node_modules/.pnpm/brace-expansion@5.0.5/node_modules/brace-expansion/dist/esm/index.js
861
+ init_esm_shims();
862
+
478
863
  // node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/dist/esm/index.js
864
+ init_esm_shims();
479
865
  var balanced = (a, b, str) => {
480
866
  const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
481
867
  const mb = b instanceof RegExp ? maybeMatch(b, str) : b;
@@ -689,6 +1075,7 @@ function expand_(str, max, isTop) {
689
1075
  }
690
1076
 
691
1077
  // node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/dist/esm/assert-valid-pattern.js
1078
+ init_esm_shims();
692
1079
  var MAX_PATTERN_LENGTH = 1024 * 64;
693
1080
  var assertValidPattern = (pattern) => {
694
1081
  if (typeof pattern !== "string") {
@@ -699,7 +1086,11 @@ var assertValidPattern = (pattern) => {
699
1086
  }
700
1087
  };
701
1088
 
1089
+ // node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/dist/esm/ast.js
1090
+ init_esm_shims();
1091
+
702
1092
  // node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/dist/esm/brace-expressions.js
1093
+ init_esm_shims();
703
1094
  var posixClasses = {
704
1095
  "[:alnum:]": ["\\p{L}\\p{Nl}\\p{Nd}", true],
705
1096
  "[:alpha:]": ["\\p{L}\\p{Nl}", true],
@@ -809,6 +1200,7 @@ var parseClass = (glob, position) => {
809
1200
  };
810
1201
 
811
1202
  // node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/dist/esm/unescape.js
1203
+ init_esm_shims();
812
1204
  var unescape = (s, { windowsPathsNoEscape = false, magicalBraces = true } = {}) => {
813
1205
  if (magicalBraces) {
814
1206
  return windowsPathsNoEscape ? s.replace(/\[([^/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^/\\])\]/g, "$1$2").replace(/\\([^/])/g, "$1");
@@ -1461,6 +1853,7 @@ var AST = class {
1461
1853
  _a = AST;
1462
1854
 
1463
1855
  // node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/dist/esm/escape.js
1856
+ init_esm_shims();
1464
1857
  var escape = (s, { windowsPathsNoEscape = false, magicalBraces = false } = {}) => {
1465
1858
  if (magicalBraces) {
1466
1859
  return windowsPathsNoEscape ? s.replace(/[?*()[\]{}]/g, "[$&]") : s.replace(/[?*()[\]\\{}]/g, "\\$&");
@@ -1527,11 +1920,11 @@ var qmarksTestNoExtDot = ([$0]) => {
1527
1920
  return (f) => f.length === len && f !== "." && f !== "..";
1528
1921
  };
1529
1922
  var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
1530
- var path = {
1923
+ var path2 = {
1531
1924
  win32: { sep: "\\" },
1532
1925
  posix: { sep: "/" }
1533
1926
  };
1534
- var sep = defaultPlatform === "win32" ? path.win32.sep : path.posix.sep;
1927
+ var sep = defaultPlatform === "win32" ? path2.win32.sep : path2.posix.sep;
1535
1928
  minimatch.sep = sep;
1536
1929
  var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
1537
1930
  minimatch.GLOBSTAR = GLOBSTAR;
@@ -2340,7 +2733,7 @@ function matchesRule(toolName, toolInput, rule) {
2340
2733
  }
2341
2734
  if (toolName === "codex_patch_apply" && toolInput.fileChanges && typeof toolInput.fileChanges === "object") {
2342
2735
  const paths = Object.keys(toolInput.fileChanges);
2343
- return paths.some((path2) => matchesPattern(path2, pattern));
2736
+ return paths.some((path3) => matchesPattern(path3, pattern));
2344
2737
  }
2345
2738
  return false;
2346
2739
  }
@@ -2556,7 +2949,7 @@ var Gateway = class {
2556
2949
  agentType: session.agentType,
2557
2950
  payload: { ...options?.metadata ?? {}, cwd: session.cwd },
2558
2951
  metadata: {
2559
- transportType: session.adapter.transportType
2952
+ transportType: session.agent.transportType
2560
2953
  }
2561
2954
  },
2562
2955
  session
@@ -2577,6 +2970,12 @@ var Gateway = class {
2577
2970
  const session = this.sessionManager.getSession(sessionId);
2578
2971
  return session?.agentType;
2579
2972
  }
2973
+ /**
2974
+ * Get session info snapshot (including model/permissionMode/slashCommands)
2975
+ */
2976
+ getSessionInfo(sessionId) {
2977
+ return this.sessionManager.getSessionInfo(sessionId);
2978
+ }
2580
2979
  /**
2581
2980
  * List all sessions
2582
2981
  */
@@ -2667,13 +3066,17 @@ var Gateway = class {
2667
3066
  toolInput: request.toolInput,
2668
3067
  requestId: request.requestId
2669
3068
  },
2670
- metadata: { transportType: session.adapter.transportType }
3069
+ metadata: { transportType: session.agent.transportType }
2671
3070
  };
2672
3071
  return await this.interactionService.evaluate(envelope);
2673
3072
  }
3073
+ updateSessionInfo(sessionId, info) {
3074
+ this.sessionManager.updateSessionInfo(sessionId, info);
3075
+ }
2674
3076
  };
2675
3077
 
2676
3078
  // src/gateway/publisher.ts
3079
+ init_esm_shims();
2677
3080
  var EventPublisher = class {
2678
3081
  constructor(bus, broadcastFn, persistence) {
2679
3082
  this.bus = bus;
@@ -2779,7 +3182,17 @@ var EventPublisher = class {
2779
3182
  }
2780
3183
  };
2781
3184
 
3185
+ // src/adapters/agent/claude/index.ts
3186
+ init_esm_shims();
3187
+
3188
+ // src/adapters/agent/claude/ClaudeHookAgentAdapter.ts
3189
+ init_esm_shims();
3190
+
3191
+ // src/core/agent/BaseAgentAdapter.ts
3192
+ init_esm_shims();
3193
+
2782
3194
  // src/core/agent/inbound-utils.ts
3195
+ init_esm_shims();
2783
3196
  function escapeRegExp(str) {
2784
3197
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2785
3198
  }
@@ -2805,6 +3218,7 @@ var BaseAgentAdapter = class {
2805
3218
  agentCommands = /* @__PURE__ */ new Map();
2806
3219
  eventHandler = null;
2807
3220
  unsubscribeFns = [];
3221
+ enricher;
2808
3222
  constructor(config) {
2809
3223
  this.bus = config.bus;
2810
3224
  this.bridge = config.bridge;
@@ -2872,6 +3286,30 @@ var BaseAgentAdapter = class {
2872
3286
  }
2873
3287
  this.bridge.emitEvent(envelope);
2874
3288
  }
3289
+ /**
3290
+ * Enrich the event envelope if a {@link TranscriptEnricher} is configured and
3291
+ * capable of handling this event type.
3292
+ *
3293
+ * Subclasses should call this in their async methods **before**
3294
+ * {@link emitEvent}. {@link emitEvent} remains synchronous by design because
3295
+ * downstream consumers (e.g. {@link TurnAggregator} callbacks) expect sync
3296
+ * execution. The async nature of enrichment means there may be an interleaving
3297
+ * gap between the call to this method and the subsequent emit.
3298
+ */
3299
+ async enrichIfNeeded(envelope) {
3300
+ if (!this.enricher?.canEnrich(envelope.type)) {
3301
+ return envelope;
3302
+ }
3303
+ try {
3304
+ return await this.enricher.enrich(envelope);
3305
+ } catch (err) {
3306
+ this.logger.warn(
3307
+ { sessionId: envelope.sessionId, eventType: envelope.type, error: err instanceof Error ? err.message : String(err) },
3308
+ "Transcript enrichment failed, emitting original envelope"
3309
+ );
3310
+ return envelope;
3311
+ }
3312
+ }
2875
3313
  getHelpText() {
2876
3314
  const lines = [
2877
3315
  `${this.agentType} commands:`,
@@ -2973,6 +3411,7 @@ Session ID: ${sessionId}` : `No active ${this.agentType} session for this chat.`
2973
3411
  };
2974
3412
 
2975
3413
  // src/core/agent/EventNormalizer.ts
3414
+ init_esm_shims();
2976
3415
  var EventNormalizer = class {
2977
3416
  static sessionStart(sessionId, agentType, transportType, payload, extraMetadata) {
2978
3417
  return this.build("session:start", sessionId, agentType, transportType, {
@@ -3003,7 +3442,8 @@ var EventNormalizer = class {
3003
3442
  isTimeout: t2.isTimeout
3004
3443
  })),
3005
3444
  durationMs: extra?.durationMs,
3006
- usage: extra?.usage
3445
+ usage: extra?.usage,
3446
+ transcriptPath: extra?.transcriptPath
3007
3447
  });
3008
3448
  }
3009
3449
  static toolExecuted(sessionId, agentType, transportType, tool) {
@@ -3106,7 +3546,8 @@ var EventNormalizer = class {
3106
3546
  ...common,
3107
3547
  reason: payload.reason,
3108
3548
  lastAssistantMessage: payload.last_assistant_message,
3109
- durationMs: typeof payload.duration === "number" ? payload.duration : void 0
3549
+ durationMs: typeof payload.duration === "number" ? payload.duration : void 0,
3550
+ transcriptPath: typeof payload.transcript_path === "string" ? payload.transcript_path : void 0
3110
3551
  }, { rawEventType: eventType });
3111
3552
  default:
3112
3553
  return null;
@@ -3128,6 +3569,7 @@ var EventNormalizer = class {
3128
3569
  };
3129
3570
 
3130
3571
  // src/core/agent/interaction-utils.ts
3572
+ init_esm_shims();
3131
3573
  async function evaluateInteraction(bridge, request) {
3132
3574
  const originalResponse = await bridge.evaluateInteraction(request);
3133
3575
  if (request.toolName === "AskUserQuestion" && (originalResponse.action === "select" || originalResponse.action === "input")) {
@@ -3146,6 +3588,118 @@ async function evaluateInteraction(bridge, request) {
3146
3588
  return originalResponse;
3147
3589
  }
3148
3590
 
3591
+ // src/adapters/agent/claude/jsonl-reader.ts
3592
+ init_esm_shims();
3593
+ import { readFile } from "fs/promises";
3594
+ import { resolve } from "path";
3595
+ async function readClaudeJSONL(transcriptPath) {
3596
+ let lastError;
3597
+ for (let attempt = 1; attempt <= 5; attempt++) {
3598
+ try {
3599
+ const content = await readFile(transcriptPath, "utf-8");
3600
+ const summary = parseTranscript(content);
3601
+ if (summary && (summary.lastAssistantMessage !== void 0 || summary.durationMs !== void 0)) {
3602
+ return summary;
3603
+ }
3604
+ if (summary) {
3605
+ getLogger().debug({ attempt, summary }, "Transcript read but incomplete, retrying...");
3606
+ }
3607
+ } catch (error2) {
3608
+ lastError = error2;
3609
+ }
3610
+ if (attempt < 5) {
3611
+ await new Promise((resolve3) => setTimeout(resolve3, 200));
3612
+ }
3613
+ }
3614
+ getLogger().warn({ error: lastError instanceof Error ? lastError.message : String(lastError), transcriptPath }, "Failed to read transcript or transcript incomplete");
3615
+ return void 0;
3616
+ }
3617
+ function resolveTranscriptPath(cwd, sessionId) {
3618
+ const projectDirName = cwd.replace(/[\\/]/g, "-");
3619
+ return resolve(process.env.HOME || "", ".claude", "projects", projectDirName, `${sessionId}.jsonl`);
3620
+ }
3621
+ function parseTranscript(content) {
3622
+ const lines = content.split("\n").filter((line) => line.trim().length > 0);
3623
+ let lastAssistantMessage;
3624
+ let thinking;
3625
+ let inputTokens;
3626
+ let outputTokens;
3627
+ let lastTextAssistant;
3628
+ let lastAnyAssistant;
3629
+ const userTimestamps = /* @__PURE__ */ new Map();
3630
+ const parentMap = /* @__PURE__ */ new Map();
3631
+ for (const line of lines) {
3632
+ let entry;
3633
+ try {
3634
+ entry = JSON.parse(line);
3635
+ } catch (parseError) {
3636
+ getLogger().warn(
3637
+ { error: parseError instanceof Error ? parseError.message : String(parseError), line: line.slice(0, 200) },
3638
+ "Skipping malformed transcript line"
3639
+ );
3640
+ continue;
3641
+ }
3642
+ const ts = typeof entry.timestamp === "string" ? new Date(entry.timestamp).getTime() : typeof entry.timestamp === "number" ? entry.timestamp : void 0;
3643
+ if (entry.uuid && typeof entry.parentUuid === "string") {
3644
+ parentMap.set(entry.uuid, entry.parentUuid);
3645
+ }
3646
+ if (entry.type === "user" && ts !== void 0 && entry.uuid) {
3647
+ userTimestamps.set(entry.uuid, ts);
3648
+ }
3649
+ if (entry.type === "assistant" && ts !== void 0) {
3650
+ const arr = Array.isArray(entry.message?.content) ? entry.message.content : [];
3651
+ const textBlock = arr.find((c) => c.type === "text");
3652
+ const thinkingBlock = arr.find((c) => c.type === "thinking");
3653
+ const assistantRef = { ts, uuid: entry.uuid, parentUuid: entry.parentUuid };
3654
+ lastAnyAssistant = assistantRef;
3655
+ if (textBlock && typeof textBlock.text === "string") {
3656
+ lastAssistantMessage = textBlock.text;
3657
+ lastTextAssistant = assistantRef;
3658
+ }
3659
+ if (thinkingBlock && typeof thinkingBlock.thinking === "string") {
3660
+ thinking = thinkingBlock.thinking;
3661
+ }
3662
+ if (textBlock) {
3663
+ const usage = entry.message?.usage;
3664
+ if (usage) {
3665
+ if (typeof usage.input_tokens === "number") inputTokens = usage.input_tokens;
3666
+ if (typeof usage.output_tokens === "number") outputTokens = usage.output_tokens;
3667
+ }
3668
+ }
3669
+ }
3670
+ }
3671
+ const durationMs = resolveDuration(lastTextAssistant, userTimestamps, parentMap) ?? resolveDuration(lastAnyAssistant, userTimestamps, parentMap);
3672
+ const summary = {};
3673
+ if (lastAssistantMessage !== void 0) summary.lastAssistantMessage = lastAssistantMessage;
3674
+ if (thinking !== void 0) summary.thinking = thinking;
3675
+ if (inputTokens !== void 0) summary.inputTokens = inputTokens;
3676
+ if (outputTokens !== void 0) summary.outputTokens = outputTokens;
3677
+ if (durationMs !== void 0) summary.durationMs = durationMs;
3678
+ return Object.keys(summary).length > 0 ? summary : void 0;
3679
+ }
3680
+ function resolveDuration(assistantRef, userTimestamps, parentMap) {
3681
+ if (!assistantRef) return void 0;
3682
+ if (assistantRef.parentUuid) {
3683
+ const directParentTs = userTimestamps.get(assistantRef.parentUuid);
3684
+ if (directParentTs !== void 0) {
3685
+ return assistantRef.ts - directParentTs;
3686
+ }
3687
+ }
3688
+ let currentUuid = assistantRef.uuid;
3689
+ const visited = /* @__PURE__ */ new Set();
3690
+ while (currentUuid && !visited.has(currentUuid)) {
3691
+ visited.add(currentUuid);
3692
+ const parentUuid = parentMap.get(currentUuid);
3693
+ if (!parentUuid) break;
3694
+ const parentTs = userTimestamps.get(parentUuid);
3695
+ if (parentTs !== void 0) {
3696
+ return assistantRef.ts - parentTs;
3697
+ }
3698
+ currentUuid = parentUuid;
3699
+ }
3700
+ return void 0;
3701
+ }
3702
+
3149
3703
  // src/adapters/agent/claude/ClaudeHookAgentAdapter.ts
3150
3704
  var ClaudeHookAgentAdapter = class extends BaseAgentAdapter {
3151
3705
  agentType = "claude";
@@ -3159,6 +3713,7 @@ var ClaudeHookAgentAdapter = class extends BaseAgentAdapter {
3159
3713
  constructor(config) {
3160
3714
  super(config);
3161
3715
  this.token = config.token ?? "";
3716
+ this.enricher = this;
3162
3717
  }
3163
3718
  // === Transport Lifecycle ===
3164
3719
  async createTransportState(opts) {
@@ -3182,16 +3737,22 @@ var ClaudeHookAgentAdapter = class extends BaseAgentAdapter {
3182
3737
  return;
3183
3738
  }
3184
3739
  if (eventType === "SessionStart") {
3185
- await this.bridge.ensureSession(sessionId, {
3186
- cwd: payload.cwd,
3187
- chatId: payload.chat_id,
3188
- channel: payload.channel,
3189
- metadata: {
3190
- rawEventType: eventType
3191
- }
3192
- }, this.agentType).catch((err) => {
3740
+ try {
3741
+ await this.bridge.ensureSession(sessionId, {
3742
+ cwd: payload.cwd,
3743
+ chatId: payload.chat_id,
3744
+ channel: payload.channel,
3745
+ metadata: {
3746
+ rawEventType: eventType
3747
+ }
3748
+ }, this.agentType);
3749
+ const model = typeof payload.model === "string" ? payload.model : void 0;
3750
+ if (model) {
3751
+ this.bridge.updateSessionInfo(sessionId, { model });
3752
+ }
3753
+ } catch (err) {
3193
3754
  this.logger.warn({ sessionId, error: err instanceof Error ? err.message : String(err) }, "ensureSession failed during SessionStart");
3194
- });
3755
+ }
3195
3756
  return;
3196
3757
  }
3197
3758
  const envelope = EventNormalizer.fromHookEvent(
@@ -3201,7 +3762,37 @@ var ClaudeHookAgentAdapter = class extends BaseAgentAdapter {
3201
3762
  this.transportType
3202
3763
  );
3203
3764
  if (!envelope) return;
3204
- this.emitEvent(envelope);
3765
+ const enriched = await this.enrichIfNeeded(envelope);
3766
+ this.emitEvent(enriched);
3767
+ }
3768
+ // === TranscriptEnricher implementation ===
3769
+ canEnrich(eventType) {
3770
+ return eventType === "turn:finished";
3771
+ }
3772
+ async enrich(envelope) {
3773
+ const { sessionId, payload } = envelope;
3774
+ const transcriptPath = typeof payload.transcriptPath === "string" ? payload.transcriptPath : typeof payload.cwd === "string" ? resolveTranscriptPath(payload.cwd, sessionId) : void 0;
3775
+ if (!transcriptPath) {
3776
+ return envelope;
3777
+ }
3778
+ const summary = await readClaudeJSONL(transcriptPath);
3779
+ if (!summary) {
3780
+ return envelope;
3781
+ }
3782
+ const enrichedPayload = { ...payload };
3783
+ if (payload.durationMs === void 0 && summary.durationMs !== void 0) {
3784
+ enrichedPayload.durationMs = summary.durationMs;
3785
+ }
3786
+ if (payload.usage === void 0 && summary.inputTokens !== void 0 && summary.outputTokens !== void 0) {
3787
+ enrichedPayload.usage = {
3788
+ inputTokens: summary.inputTokens,
3789
+ outputTokens: summary.outputTokens
3790
+ };
3791
+ }
3792
+ return {
3793
+ ...envelope,
3794
+ payload: enrichedPayload
3795
+ };
3205
3796
  }
3206
3797
  async processPermissionRequest(eventType, payload, requestId) {
3207
3798
  const sessionId = typeof payload.session_id === "string" ? payload.session_id : void 0;
@@ -3245,9 +3836,11 @@ var ClaudeHookAgentAdapter = class extends BaseAgentAdapter {
3245
3836
  };
3246
3837
 
3247
3838
  // src/adapters/agent/claude/ClaudeRemoteAgentAdapter.ts
3839
+ init_esm_shims();
3248
3840
  import { randomUUID as randomUUID2 } from "crypto";
3249
3841
 
3250
3842
  // src/core/agent/TurnAggregator.ts
3843
+ init_esm_shims();
3251
3844
  var TurnAggregator = class {
3252
3845
  constructor(logger5, sessionId) {
3253
3846
  this.logger = logger5;
@@ -3378,7 +3971,14 @@ var TurnAggregator = class {
3378
3971
  }
3379
3972
  };
3380
3973
 
3974
+ // src/core/session-scanner/index.ts
3975
+ init_esm_shims();
3976
+
3977
+ // src/core/session-scanner/types.ts
3978
+ init_esm_shims();
3979
+
3381
3980
  // src/core/session-scanner/registry.ts
3981
+ init_esm_shims();
3382
3982
  var SessionScannerRegistry = class _SessionScannerRegistry {
3383
3983
  scanners = /* @__PURE__ */ new Map();
3384
3984
  /**
@@ -3440,13 +4040,14 @@ var SessionScannerRegistry = class _SessionScannerRegistry {
3440
4040
  };
3441
4041
 
3442
4042
  // src/adapters/agent/claude/scanner.ts
3443
- import { readdir, readFile } from "fs/promises";
3444
- import { join as join2, resolve } from "path";
4043
+ init_esm_shims();
4044
+ import { readdir, readFile as readFile2 } from "fs/promises";
4045
+ import { join as join2, resolve as resolve2 } from "path";
3445
4046
  var ClaudeSessionScanner = class {
3446
4047
  agentType = "claude";
3447
4048
  sessionDir;
3448
4049
  constructor() {
3449
- this.sessionDir = resolve(process.env.HOME || "", ".claude/sessions");
4050
+ this.sessionDir = resolve2(process.env.HOME || "", ".claude/sessions");
3450
4051
  }
3451
4052
  getSessionDir() {
3452
4053
  return this.sessionDir;
@@ -3459,7 +4060,7 @@ var ClaudeSessionScanner = class {
3459
4060
  for (const file of jsonFiles) {
3460
4061
  try {
3461
4062
  const filePath = join2(this.sessionDir, file);
3462
- const content = await readFile(filePath, "utf-8");
4063
+ const content = await readFile2(filePath, "utf-8");
3463
4064
  const meta = JSON.parse(content);
3464
4065
  if (!meta.sessionId) {
3465
4066
  continue;
@@ -3469,8 +4070,9 @@ var ClaudeSessionScanner = class {
3469
4070
  id: meta.sessionId,
3470
4071
  agentType: this.agentType,
3471
4072
  transportType: "hook",
3472
- status: isActive ? "active" : "ended",
3473
- startedAt: meta.startedAt ? new Date(meta.startedAt) : /* @__PURE__ */ new Date(),
4073
+ status: isActive ? "active" : "archived",
4074
+ createdAt: meta.startedAt ?? Date.now(),
4075
+ updatedAt: meta.startedAt ?? Date.now(),
3474
4076
  cwd: meta.cwd
3475
4077
  });
3476
4078
  } catch {
@@ -3481,23 +4083,25 @@ var ClaudeSessionScanner = class {
3481
4083
  return sessions;
3482
4084
  }
3483
4085
  async checkProcessAlive(pid) {
3484
- return new Promise((resolve2) => {
4086
+ return new Promise((resolve3) => {
3485
4087
  try {
3486
4088
  process.kill(pid, 0);
3487
- resolve2(true);
4089
+ resolve3(true);
3488
4090
  } catch {
3489
- resolve2(false);
4091
+ resolve3(false);
3490
4092
  }
3491
4093
  });
3492
4094
  }
3493
4095
  };
3494
4096
 
3495
4097
  // src/adapters/agent/claude/sdk/query.ts
4098
+ init_esm_shims();
3496
4099
  import { spawn } from "child_process";
3497
4100
  import { createInterface } from "readline";
3498
4101
  import { existsSync as existsSync4 } from "fs";
3499
4102
 
3500
4103
  // src/adapters/agent/claude/sdk/stream.ts
4104
+ init_esm_shims();
3501
4105
  var Stream = class {
3502
4106
  constructor(returned) {
3503
4107
  this.returned = returned;
@@ -3526,18 +4130,18 @@ var Stream = class {
3526
4130
  if (this.hasError) {
3527
4131
  return Promise.reject(this.hasError);
3528
4132
  }
3529
- return new Promise((resolve2, reject) => {
3530
- this.readResolve = resolve2;
4133
+ return new Promise((resolve3, reject) => {
4134
+ this.readResolve = resolve3;
3531
4135
  this.readReject = reject;
3532
4136
  });
3533
4137
  }
3534
4138
  enqueue(value) {
3535
4139
  if (this.isDone || this.hasError) return;
3536
4140
  if (this.readResolve) {
3537
- const resolve2 = this.readResolve;
4141
+ const resolve3 = this.readResolve;
3538
4142
  this.readResolve = void 0;
3539
4143
  this.readReject = void 0;
3540
- resolve2({ done: false, value });
4144
+ resolve3({ done: false, value });
3541
4145
  } else {
3542
4146
  this.queue.push(value);
3543
4147
  }
@@ -3546,10 +4150,10 @@ var Stream = class {
3546
4150
  if (this.isDone || this.hasError) return;
3547
4151
  this.isDone = true;
3548
4152
  if (this.readResolve) {
3549
- const resolve2 = this.readResolve;
4153
+ const resolve3 = this.readResolve;
3550
4154
  this.readResolve = void 0;
3551
4155
  this.readReject = void 0;
3552
- resolve2({ done: true, value: void 0 });
4156
+ resolve3({ done: true, value: void 0 });
3553
4157
  }
3554
4158
  }
3555
4159
  error(error2) {
@@ -3572,6 +4176,7 @@ var Stream = class {
3572
4176
  };
3573
4177
 
3574
4178
  // src/adapters/agent/claude/sdk/types.ts
4179
+ init_esm_shims();
3575
4180
  var AbortError = class extends Error {
3576
4181
  constructor(message) {
3577
4182
  super(message);
@@ -3726,10 +4331,10 @@ var Query = class {
3726
4331
  type: "control_request",
3727
4332
  request
3728
4333
  };
3729
- return new Promise((resolve2, reject) => {
4334
+ return new Promise((resolve3, reject) => {
3730
4335
  this.pendingControlResponses.set(requestId, (response) => {
3731
4336
  if (response.subtype === "success") {
3732
- resolve2(response);
4337
+ resolve3(response);
3733
4338
  } else {
3734
4339
  reject(new Error(response.error));
3735
4340
  }
@@ -3880,7 +4485,7 @@ function query(config) {
3880
4485
  if (abort?.aborted) break;
3881
4486
  const data = JSON.stringify(msg) + "\n";
3882
4487
  if (!child.stdin.write(data)) {
3883
- await new Promise((resolve2) => child.stdin.once("drain", resolve2));
4488
+ await new Promise((resolve3) => child.stdin.once("drain", resolve3));
3884
4489
  }
3885
4490
  }
3886
4491
  } finally {
@@ -3893,14 +4498,14 @@ function query(config) {
3893
4498
  if (!child.killed) child.kill("SIGTERM");
3894
4499
  };
3895
4500
  abort?.addEventListener("abort", cleanup);
3896
- const processExitPromise = new Promise((resolve2) => {
4501
+ const processExitPromise = new Promise((resolve3) => {
3897
4502
  child.on("close", (code) => {
3898
4503
  if (abort?.aborted) {
3899
4504
  q.setError(new AbortError("Claude Code process aborted by user"));
3900
4505
  } else if (code !== 0 && code !== null) {
3901
4506
  q.setError(new Error(`Claude Code process exited with code ${code}`));
3902
4507
  } else {
3903
- resolve2();
4508
+ resolve3();
3904
4509
  }
3905
4510
  });
3906
4511
  });
@@ -3928,8 +4533,8 @@ var PushableAsyncIterable = class {
3928
4533
  push(value) {
3929
4534
  if (this.ended) return;
3930
4535
  if (this.resolvers.length > 0) {
3931
- const resolve2 = this.resolvers.shift();
3932
- resolve2({ done: false, value });
4536
+ const resolve3 = this.resolvers.shift();
4537
+ resolve3({ done: false, value });
3933
4538
  } else {
3934
4539
  this.queue.push(value);
3935
4540
  }
@@ -3937,8 +4542,8 @@ var PushableAsyncIterable = class {
3937
4542
  end() {
3938
4543
  this.ended = true;
3939
4544
  while (this.resolvers.length > 0) {
3940
- const resolve2 = this.resolvers.shift();
3941
- resolve2({ done: true, value: void 0 });
4545
+ const resolve3 = this.resolvers.shift();
4546
+ resolve3({ done: true, value: void 0 });
3942
4547
  }
3943
4548
  }
3944
4549
  [Symbol.asyncIterator]() {
@@ -3950,8 +4555,8 @@ var PushableAsyncIterable = class {
3950
4555
  if (this.ended) {
3951
4556
  return Promise.resolve({ done: true, value: void 0 });
3952
4557
  }
3953
- return new Promise((resolve2) => {
3954
- this.resolvers.push(resolve2);
4558
+ return new Promise((resolve3) => {
4559
+ this.resolvers.push(resolve3);
3955
4560
  });
3956
4561
  },
3957
4562
  return: () => {
@@ -4058,7 +4663,8 @@ var ClaudeRemoteAgentAdapter = class _ClaudeRemoteAgentAdapter extends BaseAgent
4058
4663
  turnInProgress: false,
4059
4664
  chatId,
4060
4665
  channel,
4061
- cwd
4666
+ cwd,
4667
+ permissionMode: this.defaultPermissionMode
4062
4668
  };
4063
4669
  this.transports.set(sessionId, state);
4064
4670
  this.emitEvent(EventNormalizer.sessionStart(sessionId, this.agentType, this.transportType, {
@@ -4147,6 +4753,11 @@ var ClaudeRemoteAgentAdapter = class _ClaudeRemoteAgentAdapter extends BaseAgent
4147
4753
  const system = msg;
4148
4754
  if (system.subtype === "init" && system.session_id) {
4149
4755
  this.logger.info({ sessionId, claudeSessionId: system.session_id }, "Claude session initialized");
4756
+ this.bridge.updateSessionInfo(sessionId, {
4757
+ model: system.model,
4758
+ slashCommands: system.slash_commands,
4759
+ permissionMode: state.permissionMode
4760
+ });
4150
4761
  }
4151
4762
  break;
4152
4763
  }
@@ -4234,14 +4845,14 @@ var ClaudeRemoteAgentAdapter = class _ClaudeRemoteAgentAdapter extends BaseAgent
4234
4845
  toolInput: toolInput ?? {},
4235
4846
  timestamp: Date.now()
4236
4847
  };
4237
- return new Promise((resolve2) => {
4848
+ return new Promise((resolve3) => {
4238
4849
  const timeout = setTimeout(() => {
4239
4850
  this.logger.warn({ sessionId, requestId }, "Permission request timeout");
4240
- resolve2({ behavior: "deny", message: "Timeout" });
4851
+ resolve3({ behavior: "deny", message: "Timeout" });
4241
4852
  }, _ClaudeRemoteAgentAdapter.CONTROL_REQUEST_TIMEOUT_MS);
4242
4853
  const onAbort = () => {
4243
4854
  clearTimeout(timeout);
4244
- resolve2({ behavior: "deny", message: "Aborted" });
4855
+ resolve3({ behavior: "deny", message: "Aborted" });
4245
4856
  };
4246
4857
  signal.addEventListener("abort", onAbort, { once: true });
4247
4858
  evaluateInteraction(this.bridge, interactionRequest).then((response) => {
@@ -4249,7 +4860,7 @@ var ClaudeRemoteAgentAdapter = class _ClaudeRemoteAgentAdapter extends BaseAgent
4249
4860
  signal.removeEventListener("abort", onAbort);
4250
4861
  const decision = response.action === "allow" ? "allow" : "deny";
4251
4862
  this.logger.info({ sessionId, requestId, toolName, decision }, "Claude remote permission resolved");
4252
- resolve2({
4863
+ resolve3({
4253
4864
  behavior: decision,
4254
4865
  updatedInput: response.updatedInput,
4255
4866
  ...decision === "deny" ? { message: "User denied this tool call" } : {}
@@ -4258,7 +4869,7 @@ var ClaudeRemoteAgentAdapter = class _ClaudeRemoteAgentAdapter extends BaseAgent
4258
4869
  clearTimeout(timeout);
4259
4870
  signal.removeEventListener("abort", onAbort);
4260
4871
  this.logger.error({ error: err, sessionId, requestId }, "Claude remote permission handler error");
4261
- resolve2({ behavior: "deny", message: "Error" });
4872
+ resolve3({ behavior: "deny", message: "Error" });
4262
4873
  });
4263
4874
  });
4264
4875
  }
@@ -4278,40 +4889,41 @@ var ClaudeRemoteAgentAdapter = class _ClaudeRemoteAgentAdapter extends BaseAgent
4278
4889
  toolInput: { questions: [{ question }] },
4279
4890
  timestamp: Date.now()
4280
4891
  };
4281
- return new Promise((resolve2) => {
4892
+ return new Promise((resolve3) => {
4282
4893
  const timeout = setTimeout(() => {
4283
4894
  this.logger.warn({ sessionId, requestId }, "Question request timeout");
4284
- resolve2({ action: "deny", message: "Timeout" });
4895
+ resolve3({ action: "deny", message: "Timeout" });
4285
4896
  }, _ClaudeRemoteAgentAdapter.CONTROL_REQUEST_TIMEOUT_MS);
4286
4897
  const onAbort = () => {
4287
4898
  clearTimeout(timeout);
4288
- resolve2({ action: "deny", message: "Aborted" });
4899
+ resolve3({ action: "deny", message: "Aborted" });
4289
4900
  };
4290
4901
  signal.addEventListener("abort", onAbort, { once: true });
4291
4902
  evaluateInteraction(this.bridge, interactionRequest).then((response) => {
4292
4903
  clearTimeout(timeout);
4293
4904
  signal.removeEventListener("abort", onAbort);
4294
4905
  if (!response) {
4295
- resolve2({ action: "deny", message: "No response" });
4906
+ resolve3({ action: "deny", message: "No response" });
4296
4907
  return;
4297
4908
  }
4298
4909
  if (response.action === "allow" || response.action === "select") {
4299
4910
  const answer = response.selectedValues?.[0] ?? response.customInput ?? "";
4300
- resolve2({ action: "answer", answer: String(answer) });
4911
+ resolve3({ action: "answer", answer: String(answer) });
4301
4912
  } else {
4302
- resolve2({ action: "deny", message: response.message ?? "User denied" });
4913
+ resolve3({ action: "deny", message: response.message ?? "User denied" });
4303
4914
  }
4304
4915
  }).catch((err) => {
4305
4916
  clearTimeout(timeout);
4306
4917
  signal.removeEventListener("abort", onAbort);
4307
4918
  this.logger.error({ error: err, sessionId, requestId }, "Claude remote question handler error");
4308
- resolve2({ action: "deny", message: "Error" });
4919
+ resolve3({ action: "deny", message: "Error" });
4309
4920
  });
4310
4921
  });
4311
4922
  }
4312
4923
  };
4313
4924
 
4314
4925
  // src/adapters/agent/claude/hook-types.ts
4926
+ init_esm_shims();
4315
4927
  var VALID_CLAUDE_EVENTS = [
4316
4928
  "SessionStart",
4317
4929
  "SessionEnd",
@@ -4325,10 +4937,15 @@ function isClaudeHookEventType(eventType) {
4325
4937
  return VALID_CLAUDE_EVENTS.includes(eventType);
4326
4938
  }
4327
4939
 
4940
+ // src/adapters/agent/codex/index.ts
4941
+ init_esm_shims();
4942
+
4328
4943
  // src/adapters/agent/codex/CodexAppAgentAdapter.ts
4944
+ init_esm_shims();
4329
4945
  import { randomUUID as randomUUID3 } from "crypto";
4330
4946
 
4331
4947
  // src/adapters/agent/codex/codexAppServerClient.ts
4948
+ init_esm_shims();
4332
4949
  import { spawn as spawn2, execFileSync } from "child_process";
4333
4950
  import { createInterface as createInterface2 } from "readline";
4334
4951
  function isAppServerAvailable(command = "codex") {
@@ -4348,8 +4965,8 @@ function normalizeRawFileChangeList(changes) {
4348
4965
  if (!change || typeof change !== "object" || Array.isArray(change)) {
4349
4966
  continue;
4350
4967
  }
4351
- const path2 = typeof change.path === "string" ? change.path : null;
4352
- if (!path2) {
4968
+ const path3 = typeof change.path === "string" ? change.path : null;
4969
+ if (!path3) {
4353
4970
  continue;
4354
4971
  }
4355
4972
  const entry = {};
@@ -4359,7 +4976,7 @@ function normalizeRawFileChangeList(changes) {
4359
4976
  if (change.kind && typeof change.kind === "object" && !Array.isArray(change.kind)) {
4360
4977
  entry.kind = change.kind;
4361
4978
  }
4362
- normalized[path2] = entry;
4979
+ normalized[path3] = entry;
4363
4980
  }
4364
4981
  return Object.keys(normalized).length > 0 ? normalized : void 0;
4365
4982
  }
@@ -4821,7 +5438,7 @@ var CodexAppServerClient = class _CodexAppServerClient {
4821
5438
  if (Date.now() >= deadline) {
4822
5439
  return false;
4823
5440
  }
4824
- await new Promise((resolve2) => setTimeout(resolve2, 25));
5441
+ await new Promise((resolve3) => setTimeout(resolve3, 25));
4825
5442
  }
4826
5443
  return true;
4827
5444
  }
@@ -4894,13 +5511,13 @@ var CodexAppServerClient = class _CodexAppServerClient {
4894
5511
  async sendTurnAndWait(prompt, opts) {
4895
5512
  if (this.pendingInterrupt) {
4896
5513
  await this.pendingInterrupt;
4897
- await new Promise((resolve2) => setTimeout(resolve2, 0));
5514
+ await new Promise((resolve3) => setTimeout(resolve3, 0));
4898
5515
  }
4899
5516
  const timeoutMs = opts?.turnTimeoutMs ?? _CodexAppServerClient.TURN_TIMEOUT_MS;
4900
5517
  let timer = null;
4901
- const completion = new Promise((resolve2) => {
5518
+ const completion = new Promise((resolve3) => {
4902
5519
  this.pendingTurnCompletion = {
4903
- resolve: resolve2,
5520
+ resolve: resolve3,
4904
5521
  started: false,
4905
5522
  turnId: null
4906
5523
  };
@@ -4951,7 +5568,7 @@ var CodexAppServerClient = class _CodexAppServerClient {
4951
5568
  static REQUEST_TIMEOUT_MS = 3e4;
4952
5569
  request(method, params, timeoutMs) {
4953
5570
  const timeout = timeoutMs ?? _CodexAppServerClient.REQUEST_TIMEOUT_MS;
4954
- return new Promise((resolve2, reject) => {
5571
+ return new Promise((resolve3, reject) => {
4955
5572
  if (!this.process?.stdin?.writable) {
4956
5573
  reject(new Error(`Cannot send ${method}: stdin not writable`));
4957
5574
  return;
@@ -4964,7 +5581,7 @@ var CodexAppServerClient = class _CodexAppServerClient {
4964
5581
  this.pending.set(id, {
4965
5582
  resolve: (result) => {
4966
5583
  clearTimeout(timer);
4967
- resolve2(result);
5584
+ resolve3(result);
4968
5585
  },
4969
5586
  reject: (err) => {
4970
5587
  clearTimeout(timer);
@@ -5417,8 +6034,12 @@ var CodexAppAgentAdapter = class extends BaseAgentAdapter {
5417
6034
  }
5418
6035
  };
5419
6036
 
6037
+ // src/adapters/agent/codex/codexAppServerTypes.ts
6038
+ init_esm_shims();
6039
+
5420
6040
  // src/shared/persistence.ts
5421
- import { appendFile, mkdir, readdir as readdir2, readFile as readFile2 } from "fs/promises";
6041
+ init_esm_shims();
6042
+ import { appendFile, mkdir, readdir as readdir2, readFile as readFile3 } from "fs/promises";
5422
6043
  import { readdirSync, statSync } from "fs";
5423
6044
  import { join as join3 } from "path";
5424
6045
  import { existsSync as existsSync5 } from "fs";
@@ -5458,7 +6079,7 @@ var Persistence = class {
5458
6079
  const fileName = files.find((f) => f.endsWith(`-${sessionId}.jsonl`));
5459
6080
  if (fileName) {
5460
6081
  const filePath = join3(dirPath, fileName);
5461
- const content = await readFile2(filePath, "utf-8");
6082
+ const content = await readFile3(filePath, "utf-8");
5462
6083
  const lines = content.trim().split("\n").filter((line) => line.length > 0);
5463
6084
  for (const line of lines) {
5464
6085
  try {
@@ -5509,6 +6130,7 @@ var Persistence = class {
5509
6130
  };
5510
6131
 
5511
6132
  // src/server/http.ts
6133
+ init_esm_shims();
5512
6134
  import { createServer } from "http";
5513
6135
  import { URL } from "url";
5514
6136
  var VERSION = "0.1.0";
@@ -5524,19 +6146,19 @@ var HttpServer = class {
5524
6146
  /**
5525
6147
  * Register a route handler
5526
6148
  */
5527
- registerRoute(method, path2, handler) {
5528
- this.routes.push({ method: method.toUpperCase(), path: path2, handler });
5529
- logger2.debug(`Registered route: ${method} ${path2}`);
6149
+ registerRoute(method, path3, handler) {
6150
+ this.routes.push({ method: method.toUpperCase(), path: path3, handler });
6151
+ logger2.debug(`Registered route: ${method} ${path3}`);
5530
6152
  }
5531
6153
  /**
5532
6154
  * Register a WebSocket upgrade handler for a specific path
5533
6155
  */
5534
- onUpgrade(path2, handler) {
5535
- this.upgradeHandlers.set(path2, handler);
5536
- logger2.debug(`Registered upgrade handler: ${path2}`);
6156
+ onUpgrade(path3, handler) {
6157
+ this.upgradeHandlers.set(path3, handler);
6158
+ logger2.debug(`Registered upgrade handler: ${path3}`);
5537
6159
  return () => {
5538
- this.upgradeHandlers.delete(path2);
5539
- logger2.debug(`Unregistered upgrade handler: ${path2}`);
6160
+ this.upgradeHandlers.delete(path3);
6161
+ logger2.debug(`Unregistered upgrade handler: ${path3}`);
5540
6162
  };
5541
6163
  }
5542
6164
  /**
@@ -5553,10 +6175,10 @@ var HttpServer = class {
5553
6175
  socket.destroy();
5554
6176
  }
5555
6177
  });
5556
- return new Promise((resolve2, reject) => {
6178
+ return new Promise((resolve3, reject) => {
5557
6179
  this.server?.listen(this.port, () => {
5558
6180
  logger2.info(`HTTP server listening on port ${this.port}`);
5559
- resolve2();
6181
+ resolve3();
5560
6182
  });
5561
6183
  this.server?.on("error", reject);
5562
6184
  });
@@ -5565,10 +6187,10 @@ var HttpServer = class {
5565
6187
  * Stop the HTTP server
5566
6188
  */
5567
6189
  async stop() {
5568
- return new Promise((resolve2) => {
6190
+ return new Promise((resolve3) => {
5569
6191
  this.server?.close(() => {
5570
6192
  logger2.info("HTTP server stopped");
5571
- resolve2();
6193
+ resolve3();
5572
6194
  });
5573
6195
  });
5574
6196
  }
@@ -5612,7 +6234,7 @@ var HttpServer = class {
5612
6234
  }
5613
6235
  };
5614
6236
  function parseJsonBody(req) {
5615
- return new Promise((resolve2, reject) => {
6237
+ return new Promise((resolve3, reject) => {
5616
6238
  let body = "";
5617
6239
  req.on("data", (chunk) => {
5618
6240
  body += chunk.toString();
@@ -5620,10 +6242,10 @@ function parseJsonBody(req) {
5620
6242
  req.on("end", () => {
5621
6243
  try {
5622
6244
  if (!body) {
5623
- resolve2({});
6245
+ resolve3({});
5624
6246
  return;
5625
6247
  }
5626
- resolve2(JSON.parse(body));
6248
+ resolve3(JSON.parse(body));
5627
6249
  } catch (error2) {
5628
6250
  reject(error2);
5629
6251
  }
@@ -5702,7 +6324,7 @@ function setupRoutes(httpServer, gateway, getClientCount) {
5702
6324
  sessionId: s.id,
5703
6325
  agentType: s.agentType,
5704
6326
  status: s.status,
5705
- startedAt: s.startedAt?.toISOString(),
6327
+ startedAt: new Date(s.createdAt).toISOString(),
5706
6328
  updatedAt: new Date(s.updatedAt).toISOString()
5707
6329
  })),
5708
6330
  clients: getClientCount()
@@ -5807,6 +6429,7 @@ function setupRoutes(httpServer, gateway, getClientCount) {
5807
6429
  }
5808
6430
 
5809
6431
  // src/server/websocket.ts
6432
+ init_esm_shims();
5810
6433
  import { WebSocketServer as WSWebSocketServer, WebSocket } from "ws";
5811
6434
  import { URL as URL2 } from "url";
5812
6435
  var VERSION2 = "0.1.0";
@@ -5835,13 +6458,13 @@ var WebSocketServer = class {
5835
6458
  this.wss = new WSWebSocketServer({ noServer: true });
5836
6459
  this.setupConnectionHandlers();
5837
6460
  this.startHeartbeat();
5838
- const path2 = this.options.path || "/ws";
5839
- this.httpServer.onUpgrade(path2, (request, socket, head) => {
6461
+ const path3 = this.options.path || "/ws";
6462
+ this.httpServer.onUpgrade(path3, (request, socket, head) => {
5840
6463
  this.wss?.handleUpgrade(request, socket, head, (ws) => {
5841
6464
  this.wss?.emit("connection", ws, request);
5842
6465
  });
5843
6466
  });
5844
- logger3.info(`WebSocket server registered on path: ${path2}`);
6467
+ logger3.info(`WebSocket server registered on path: ${path3}`);
5845
6468
  }
5846
6469
  /**
5847
6470
  * Stop the WebSocket server
@@ -5852,10 +6475,10 @@ var WebSocketServer = class {
5852
6475
  this.heartbeatInterval = null;
5853
6476
  }
5854
6477
  this.closeAll();
5855
- return new Promise((resolve2) => {
6478
+ return new Promise((resolve3) => {
5856
6479
  this.wss?.close(() => {
5857
6480
  logger3.info("WebSocket server stopped");
5858
- resolve2();
6481
+ resolve3();
5859
6482
  });
5860
6483
  });
5861
6484
  }
@@ -6071,7 +6694,7 @@ function setupWebSocketHandlers(wsServer, gateway, options = {}) {
6071
6694
  id: s.id,
6072
6695
  agentType: s.agentType,
6073
6696
  status: s.status,
6074
- startedAt: s.startedAt?.toISOString(),
6697
+ startedAt: new Date(s.createdAt).toISOString(),
6075
6698
  updatedAt: new Date(s.updatedAt).toISOString()
6076
6699
  }))
6077
6700
  }
@@ -6133,6 +6756,7 @@ function broadcastEvent(wsServer, frame) {
6133
6756
  }
6134
6757
 
6135
6758
  // src/shared/credentials.ts
6759
+ init_esm_shims();
6136
6760
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
6137
6761
  import { join as join4, dirname as dirname4 } from "path";
6138
6762
  import { homedir } from "os";
@@ -6140,15 +6764,15 @@ function getCredentialsPath() {
6140
6764
  return join4(homedir(), ".handsoff", "credentials.json");
6141
6765
  }
6142
6766
  function loadCredentials() {
6143
- const path2 = getCredentialsPath();
6144
- if (!existsSync6(path2)) {
6767
+ const path3 = getCredentialsPath();
6768
+ if (!existsSync6(path3)) {
6145
6769
  return null;
6146
6770
  }
6147
6771
  try {
6148
- const content = readFileSync3(path2, "utf-8");
6772
+ const content = readFileSync3(path3, "utf-8");
6149
6773
  return JSON.parse(content);
6150
6774
  } catch (error2) {
6151
- console.error(`Failed to load credentials from ${path2}:`, error2);
6775
+ console.error(`Failed to load credentials from ${path3}:`, error2);
6152
6776
  return null;
6153
6777
  }
6154
6778
  }
@@ -6156,7 +6780,14 @@ function getHookToken() {
6156
6780
  return loadCredentials()?.hookToken ?? null;
6157
6781
  }
6158
6782
 
6783
+ // src/adapters/interaction/index.ts
6784
+ init_esm_shims();
6785
+
6786
+ // src/adapters/interaction/types.ts
6787
+ init_esm_shims();
6788
+
6159
6789
  // src/adapters/interaction/queue.ts
6790
+ init_esm_shims();
6160
6791
  import { randomUUID as randomUUID4 } from "crypto";
6161
6792
  var InteractionQueue = class {
6162
6793
  pending = /* @__PURE__ */ new Map();
@@ -6168,13 +6799,13 @@ var InteractionQueue = class {
6168
6799
  }
6169
6800
  request(request) {
6170
6801
  const requestId = randomUUID4();
6171
- const responsePromise = new Promise((resolve2, reject) => {
6802
+ const responsePromise = new Promise((resolve3, reject) => {
6172
6803
  const timeoutId = setTimeout(() => {
6173
6804
  this.pending.delete(requestId);
6174
6805
  getLogger().info(
6175
6806
  `[Interaction] Timeout: ${request.toolName} | requestId=${requestId} | default=${this.defaultOnTimeout}`
6176
6807
  );
6177
- resolve2({
6808
+ resolve3({
6178
6809
  requestId,
6179
6810
  action: this.defaultOnTimeout,
6180
6811
  message: `Interaction request timed out after ${this.timeoutMs}ms`
@@ -6191,7 +6822,7 @@ var InteractionQueue = class {
6191
6822
  resolve: (response) => {
6192
6823
  clearTimeout(timeoutId);
6193
6824
  this.pending.delete(requestId);
6194
- resolve2(response);
6825
+ resolve3(response);
6195
6826
  },
6196
6827
  reject: (error2) => {
6197
6828
  clearTimeout(timeoutId);
@@ -6260,6 +6891,7 @@ var InteractionQueue = class {
6260
6891
  };
6261
6892
 
6262
6893
  // src/config.ts
6894
+ init_esm_shims();
6263
6895
  import { readFileSync as readFileSync4, existsSync as existsSync7 } from "fs";
6264
6896
  import { join as join5 } from "path";
6265
6897
  import { homedir as homedir2 } from "os";
@@ -6408,7 +7040,16 @@ function loadConfig() {
6408
7040
  }
6409
7041
 
6410
7042
  // src/core/bus/index.ts
7043
+ init_esm_shims();
6411
7044
  import EventEmitter from "events";
7045
+
7046
+ // src/core/bus/types.ts
7047
+ init_esm_shims();
7048
+
7049
+ // src/core/bus/events.ts
7050
+ init_esm_shims();
7051
+
7052
+ // src/core/bus/index.ts
6412
7053
  var EventBus = class {
6413
7054
  emitter;
6414
7055
  logger;
@@ -6686,7 +7327,11 @@ var EventBus = class {
6686
7327
  }
6687
7328
  };
6688
7329
 
7330
+ // src/core/channel/manager.ts
7331
+ init_esm_shims();
7332
+
6689
7333
  // src/core/channel/registry.ts
7334
+ init_esm_shims();
6690
7335
  var ChannelRegistry = class _ChannelRegistry {
6691
7336
  static instance = null;
6692
7337
  registry = /* @__PURE__ */ new Map();
@@ -6853,7 +7498,7 @@ var ChannelManager = class {
6853
7498
  }
6854
7499
  const delay = 1e3 * Math.pow(2, attempt - 1);
6855
7500
  this.logger.debug({ channel: name, delay }, "[Channel] Retrying");
6856
- await new Promise((resolve2) => setTimeout(resolve2, delay));
7501
+ await new Promise((resolve3) => setTimeout(resolve3, delay));
6857
7502
  }
6858
7503
  }
6859
7504
  }
@@ -7126,7 +7771,17 @@ var ChannelManager = class {
7126
7771
  }
7127
7772
  };
7128
7773
 
7774
+ // src/core/routing/index.ts
7775
+ init_esm_shims();
7776
+
7777
+ // src/core/routing/InboundRouter.ts
7778
+ init_esm_shims();
7779
+
7780
+ // src/core/binding/index.ts
7781
+ init_esm_shims();
7782
+
7129
7783
  // src/core/binding/BindingService.ts
7784
+ init_esm_shims();
7130
7785
  import { writeFileSync as writeFileSync3 } from "fs";
7131
7786
  import { join as join6 } from "path";
7132
7787
  import { homedir as homedir3 } from "os";
@@ -7244,6 +7899,7 @@ var BindingService = class {
7244
7899
  };
7245
7900
 
7246
7901
  // src/core/command/routing.ts
7902
+ init_esm_shims();
7247
7903
  var COMMAND_ROOT_SUBCOMMAND = "__root__";
7248
7904
  var SYSTEM_COMMAND_ROOTS = /* @__PURE__ */ new Set([
7249
7905
  "start",
@@ -7366,7 +8022,23 @@ var InboundRouter = class {
7366
8022
  }
7367
8023
  };
7368
8024
 
8025
+ // src/gateway/handlers/index.ts
8026
+ init_esm_shims();
8027
+
8028
+ // src/gateway/handlers/command.ts
8029
+ init_esm_shims();
8030
+
8031
+ // src/core/command/index.ts
8032
+ init_esm_shims();
8033
+
8034
+ // src/core/command/types.ts
8035
+ init_esm_shims();
8036
+
8037
+ // src/core/command/executor.ts
8038
+ init_esm_shims();
8039
+
7369
8040
  // src/core/command/parser.ts
8041
+ init_esm_shims();
7370
8042
  var CommandParser = class {
7371
8043
  /**
7372
8044
  * Check if content is a command (starts with /)
@@ -7512,7 +8184,11 @@ var CommandExecutor = class {
7512
8184
  }
7513
8185
  };
7514
8186
 
8187
+ // src/core/command/builtin/index.ts
8188
+ init_esm_shims();
8189
+
7515
8190
  // src/core/command/builtin/bind.ts
8191
+ init_esm_shims();
7516
8192
  var bindingService = new BindingService();
7517
8193
  var bindCommand = {
7518
8194
  description: "Bind this channel to an agent",
@@ -7567,6 +8243,7 @@ var unbindAgentCommand = {
7567
8243
  };
7568
8244
 
7569
8245
  // src/core/command/builtin/help.ts
8246
+ init_esm_shims();
7570
8247
  var helpCommand = {
7571
8248
  description: "Show system and agent command help",
7572
8249
  usage: "/help",
@@ -7591,6 +8268,7 @@ var helpCommand = {
7591
8268
  };
7592
8269
 
7593
8270
  // src/core/command/builtin/session.ts
8271
+ init_esm_shims();
7594
8272
  var bindingService2 = new BindingService();
7595
8273
  function formatDuration(start, end) {
7596
8274
  const endTime = end ?? /* @__PURE__ */ new Date();
@@ -7648,7 +8326,7 @@ var listHandler = {
7648
8326
  for (const [agentType, agentSessions] of byAgent) {
7649
8327
  lines.push(`**${agentType}** (${agentSessions.length})`);
7650
8328
  for (const session of agentSessions) {
7651
- lines.push(`- \`${session.id}\` (${session.status}, ${formatDuration(session.startedAt)})`);
8329
+ lines.push(`- \`${session.id}\` (${session.status}, ${formatDuration(new Date(session.createdAt))})`);
7652
8330
  }
7653
8331
  lines.push("");
7654
8332
  }
@@ -7674,8 +8352,8 @@ var statusHandler = {
7674
8352
  `Agent: ${session.agentType}`,
7675
8353
  `Transport: ${session.transportType}`,
7676
8354
  `Status: ${session.status}`,
7677
- `Started: ${session.startedAt.toISOString()}`,
7678
- `Duration: ${formatDuration(session.startedAt)}`
8355
+ `Started: ${new Date(session.createdAt).toISOString()}`,
8356
+ `Duration: ${formatDuration(new Date(session.createdAt))}`
7679
8357
  ];
7680
8358
  if (session.cwd) {
7681
8359
  lines.push(`Workdir: \`${session.cwd}\``);
@@ -7768,6 +8446,7 @@ function registerSessionCommands(registerFn) {
7768
8446
  }
7769
8447
 
7770
8448
  // src/core/command/builtin/start.ts
8449
+ init_esm_shims();
7771
8450
  var bindingService3 = new BindingService();
7772
8451
  var startCommand = {
7773
8452
  description: "Show the quick-start guide for this channel",
@@ -7789,6 +8468,7 @@ var startCommand = {
7789
8468
  };
7790
8469
 
7791
8470
  // src/core/command/builtin/system.ts
8471
+ init_esm_shims();
7792
8472
  import process2 from "process";
7793
8473
  import os from "os";
7794
8474
  var systemStartTime = Date.now();
@@ -8077,6 +8757,7 @@ function setupCommandHandler(bus, sessionManager, logger5) {
8077
8757
  }
8078
8758
 
8079
8759
  // src/gateway/handlers/permission.ts
8760
+ init_esm_shims();
8080
8761
  function setupPermissionHandler(bus, interactionQueue, logger5) {
8081
8762
  const unsubscribe = bus.onInteractionResponse((event) => {
8082
8763
  const { requestId, response, reason } = event;
@@ -8114,11 +8795,13 @@ function setupAllHandlers(bus, gateway, interactionQueue, logger5) {
8114
8795
  }
8115
8796
 
8116
8797
  // src/gateway/notification-handler.ts
8798
+ init_esm_shims();
8117
8799
  var NotificationHandler = class {
8118
- constructor(bus, logger5, getSessionAgentType, bindingService4) {
8800
+ constructor(bus, logger5, getSessionAgentType, getSessionInfo, bindingService4) {
8119
8801
  this.bus = bus;
8120
8802
  this.logger = logger5;
8121
8803
  this.getSessionAgentType = getSessionAgentType;
8804
+ this.getSessionInfo = getSessionInfo;
8122
8805
  this.bindingService = bindingService4;
8123
8806
  if (!this.bindingService) {
8124
8807
  this.bindingService = new BindingService(logger5);
@@ -8127,6 +8810,7 @@ var NotificationHandler = class {
8127
8810
  bus;
8128
8811
  logger;
8129
8812
  getSessionAgentType;
8813
+ getSessionInfo;
8130
8814
  bindingService;
8131
8815
  unsubscribeFns = [];
8132
8816
  sessionAgentMap = /* @__PURE__ */ new Map();
@@ -8264,6 +8948,7 @@ var NotificationHandler = class {
8264
8948
  }
8265
8949
  async handleTurnFinished(event) {
8266
8950
  this.logger.debug({ sessionId: event.sessionId, cwd: event.cwd }, "[NotificationHandler] handleTurnFinished");
8951
+ const sessionInfo = this.getSessionInfo?.(event.sessionId);
8267
8952
  const context = {
8268
8953
  eventType: "turn:finished",
8269
8954
  sessionId: event.sessionId,
@@ -8276,6 +8961,7 @@ var NotificationHandler = class {
8276
8961
  thinking: event.thinking,
8277
8962
  durationMs: event.durationMs,
8278
8963
  usage: event.usage,
8964
+ model: sessionInfo?.model,
8279
8965
  summary: event.usage || event.durationMs ? {
8280
8966
  durationMs: event.durationMs,
8281
8967
  inputTokens: event.usage?.inputTokens,
@@ -8374,7 +9060,14 @@ var NotificationHandler = class {
8374
9060
  }
8375
9061
  };
8376
9062
 
9063
+ // src/adapters/channels/index.ts
9064
+ init_esm_shims();
9065
+
9066
+ // src/adapters/channels/telegram/index.ts
9067
+ init_esm_shims();
9068
+
8377
9069
  // src/core/channel/base.ts
9070
+ init_esm_shims();
8378
9071
  var BaseChannel = class {
8379
9072
  /**
8380
9073
  * 是否支持流式消息输出
@@ -8628,6 +9321,7 @@ var BaseChannel = class {
8628
9321
  };
8629
9322
 
8630
9323
  // src/adapters/channels/telegram/bot.ts
9324
+ init_esm_shims();
8631
9325
  import { Bot } from "grammy";
8632
9326
  var TelegramBot = class {
8633
9327
  /** grammy Bot 实例 */
@@ -8758,13 +9452,13 @@ var TelegramBot = class {
8758
9452
  * @param timeoutMs - 超时时间(毫秒)
8759
9453
  */
8760
9454
  async startWithTimeout(timeoutMs) {
8761
- return new Promise((resolve2, reject) => {
9455
+ return new Promise((resolve3, reject) => {
8762
9456
  const timeout = setTimeout(() => {
8763
9457
  reject(new Error(`Bot start timed out after ${timeoutMs}ms`));
8764
9458
  }, timeoutMs);
8765
9459
  this.bot.start().then(() => {
8766
9460
  clearTimeout(timeout);
8767
- resolve2();
9461
+ resolve3();
8768
9462
  }).catch((error2) => {
8769
9463
  clearTimeout(timeout);
8770
9464
  reject(error2);
@@ -8776,14 +9470,27 @@ var TelegramBot = class {
8776
9470
  * @param ms - 毫秒
8777
9471
  */
8778
9472
  sleep(ms) {
8779
- return new Promise((resolve2) => setTimeout(resolve2, ms));
9473
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
8780
9474
  }
8781
9475
  };
8782
9476
 
9477
+ // src/adapters/channels/telegram/formatter.ts
9478
+ init_esm_shims();
9479
+
9480
+ // src/gateway/notification-context.ts
9481
+ init_esm_shims();
9482
+
9483
+ // src/i18n/index.ts
9484
+ init_esm_shims();
9485
+
9486
+ // src/i18n/types.ts
9487
+ init_esm_shims();
9488
+
8783
9489
  // src/i18n/index.ts
8784
9490
  import i18next from "i18next";
8785
9491
 
8786
9492
  // src/i18n/locales/en.ts
9493
+ init_esm_shims();
8787
9494
  var en_default = {
8788
9495
  wizard: {
8789
9496
  section: {
@@ -9319,6 +10026,7 @@ var TelegramFormatter = class {
9319
10026
  var formatter = new TelegramFormatter();
9320
10027
 
9321
10028
  // src/shared/channelInstance.ts
10029
+ init_esm_shims();
9322
10030
  import { createHash } from "crypto";
9323
10031
  function getChannelInstanceId(channelType, credential) {
9324
10032
  const hash = createHash("sha256").update(credential).digest("hex").slice(0, 12);
@@ -9982,6 +10690,7 @@ TelegramChannel = __decorateElement(_init, 0, "TelegramChannel", _TelegramChanne
9982
10690
  __runInitializers(_init, 1, TelegramChannel);
9983
10691
 
9984
10692
  // src/adapters/channels/logger/index.ts
10693
+ init_esm_shims();
9985
10694
  var _LoggerChannel_decorators, _init2, _a3;
9986
10695
  _LoggerChannel_decorators = [Channel("logger")];
9987
10696
  var LoggerChannel = class extends (_a3 = BaseChannel) {
@@ -10024,7 +10733,11 @@ _init2 = __decoratorStart(_a3);
10024
10733
  LoggerChannel = __decorateElement(_init2, 0, "LoggerChannel", _LoggerChannel_decorators, LoggerChannel);
10025
10734
  __runInitializers(_init2, 1, LoggerChannel);
10026
10735
 
10736
+ // src/adapters/channels/feishu/index.ts
10737
+ init_esm_shims();
10738
+
10027
10739
  // src/adapters/channels/feishu/client.ts
10740
+ init_esm_shims();
10028
10741
  import {
10029
10742
  Client,
10030
10743
  WSClient,
@@ -10224,6 +10937,7 @@ var FeishuClient = class {
10224
10937
  };
10225
10938
 
10226
10939
  // src/adapters/channels/feishu/formatter.ts
10940
+ init_esm_shims();
10227
10941
  var FeishuFormatter = class {
10228
10942
  /**
10229
10943
  * 将内容转换为飞书 post 格式
@@ -10472,6 +11186,27 @@ ${JSON.stringify(content.permission.args, null, 2)}
10472
11186
  };
10473
11187
  return JSON.stringify(cardJson);
10474
11188
  }
11189
+ /**
11190
+ * Format a message notification card
11191
+ */
11192
+ formatMessageCard(params) {
11193
+ const { buildMessageCard: buildMessageCard2 } = (init_message(), __toCommonJS(message_exports));
11194
+ return buildMessageCard2(params);
11195
+ }
11196
+ /**
11197
+ * Format a permission request card
11198
+ */
11199
+ formatPermissionCard(params) {
11200
+ const { buildPermissionCard: buildPermissionCard2 } = (init_permission(), __toCommonJS(permission_exports));
11201
+ return buildPermissionCard2(params);
11202
+ }
11203
+ /**
11204
+ * Format a question request card
11205
+ */
11206
+ formatQuestionCard(params) {
11207
+ const { buildQuestionCard: buildQuestionCard2 } = (init_question(), __toCommonJS(question_exports));
11208
+ return buildQuestionCard2(params);
11209
+ }
10475
11210
  };
10476
11211
 
10477
11212
  // src/adapters/channels/feishu/index.ts
@@ -10498,6 +11233,7 @@ var FeishuChannel = class extends (_a4 = BaseChannel) {
10498
11233
  pendingOptions = /* @__PURE__ */ new Map();
10499
11234
  pendingToolNames = /* @__PURE__ */ new Map();
10500
11235
  // requestId -> toolName for always_allow
11236
+ pendingSelections = /* @__PURE__ */ new Map();
10501
11237
  unsubscribeInteractionResponse;
10502
11238
  formatter = new FeishuFormatter();
10503
11239
  constructor(config, bus, logger5) {
@@ -10561,6 +11297,7 @@ var FeishuChannel = class extends (_a4 = BaseChannel) {
10561
11297
  this.pendingRequests.clear();
10562
11298
  this.pendingOptions.clear();
10563
11299
  this.pendingToolNames.clear();
11300
+ this.pendingSelections.clear();
10564
11301
  this.client?.stopWebSocket();
10565
11302
  await super.stop();
10566
11303
  this.logger.info({ channel: this.name }, "[Channel] Stopped");
@@ -10587,33 +11324,48 @@ var FeishuChannel = class extends (_a4 = BaseChannel) {
10587
11324
  const ctx = message.context;
10588
11325
  const interaction = ctx?.interaction;
10589
11326
  const requestId = ctx?.requestId;
10590
- let buttons;
10591
- let isInteractionRequest = false;
10592
- if ((eventType === "permission:request" || eventType === "question:request") && requestId && interaction) {
10593
- isInteractionRequest = true;
10594
- if (eventType === "permission:request") {
10595
- const toolName = ctx?.toolName || "";
11327
+ if (eventType === "permission:request") {
11328
+ const toolName = ctx?.toolName || "";
11329
+ if (requestId) {
10596
11330
  this.pendingToolNames.set(requestId, toolName);
10597
- buttons = [
10598
- { text: "\u2705 Allow", type: "primary_filled", callbackValue: { action: "agree", requestId } },
10599
- { text: "\u274C Deny", type: "danger_filled", callbackValue: { action: "reject", requestId } },
10600
- { text: "\u{1F513} Always Allow", type: "primary", callbackValue: { action: "always_allow", requestId } }
10601
- ];
10602
- } else if (eventType === "question:request" && interaction.question) {
10603
- const question = interaction.question;
11331
+ }
11332
+ const content = this.formatContextToMarkdown(message.context);
11333
+ const buttons = [
11334
+ { text: "\u2705 Allow", type: "primary_filled", value: "agree" },
11335
+ { text: "\u274C Deny", type: "danger_filled", value: "reject", confirm: { title: "\u786E\u8BA4\u62D2\u7EDD", text: "\u786E\u8BA4\u62D2\u7EDD\u8BE5\u5DE5\u5177\u8C03\u7528\uFF1F" } },
11336
+ { text: "\u{1F513} Always Allow", type: "default", value: "always_allow", confirm: { title: "\u786E\u8BA4\u603B\u662F\u5141\u8BB8", text: "\u603B\u662F\u5141\u8BB8\u5C06\u653E\u884C\u8BE5\u5DE5\u5177\u7684\u6240\u6709\u8C03\u7528\uFF0C\u8BF7\u786E\u8BA4\u3002" } }
11337
+ ];
11338
+ const cardContent = this.formatter.formatPermissionCard({ title: this.getTitleForContext(message.context), content, buttons });
11339
+ await this.sendCardRaw(cardContent, message);
11340
+ } else if (eventType === "question:request") {
11341
+ const question = interaction?.question;
11342
+ const content = this.formatContextToMarkdown(message.context);
11343
+ const mode = question?.multiSelect ? "multiple" : "single";
11344
+ const items = (question?.options || []).map((opt) => ({ id: opt.id, label: opt.label }));
11345
+ if (requestId && question) {
10604
11346
  this.pendingOptions.set(
10605
11347
  requestId,
10606
11348
  question.options.map((opt) => ({ id: opt.id, value: opt.value }))
10607
11349
  );
10608
- buttons = question.options.map((opt) => ({
10609
- text: opt.label,
10610
- type: "primary",
10611
- callbackValue: { action: "select", requestId, optionId: opt.id }
10612
- }));
10613
11350
  }
10614
- }
10615
- await this.sendCard(message, buttons);
10616
- if (isInteractionRequest && requestId) {
11351
+ const cardContent = this.formatter.formatQuestionCard({ title: this.getTitleForContext(message.context), content, mode, items });
11352
+ await this.sendCardRaw(cardContent, message);
11353
+ } else {
11354
+ const content = message.context ? this.formatContextToMarkdown(message.context) : message.text || "";
11355
+ let meta = "";
11356
+ if (message.context?.eventType === "turn:finished") {
11357
+ const finishedCtx = message.context;
11358
+ const model = finishedCtx.model || finishedCtx.agentType || "-";
11359
+ const duration = finishedCtx.durationMs ? `${(finishedCtx.durationMs / 1e3).toFixed(1)}s` : "-";
11360
+ const outTokens = finishedCtx.usage?.outputTokens;
11361
+ const inTokens = finishedCtx.usage?.inputTokens;
11362
+ const tokens = outTokens !== void 0 && inTokens !== void 0 ? `${outTokens}\u2191 ${inTokens}\u2193` : "-";
11363
+ meta = `${model} \xB7 ${duration} \xB7 ${tokens}`;
11364
+ }
11365
+ const cardContent = this.formatter.formatMessageCard({ title: this.getTitleForContext(message.context), content, meta });
11366
+ await this.sendCardRaw(cardContent, message);
11367
+ }
11368
+ if ((eventType === "permission:request" || eventType === "question:request") && requestId) {
10617
11369
  if (!this.pendingRequests.has(requestId)) {
10618
11370
  this.pendingRequests.set(requestId, /* @__PURE__ */ new Set());
10619
11371
  }
@@ -10731,7 +11483,7 @@ var FeishuChannel = class extends (_a4 = BaseChannel) {
10731
11483
  this.pendingOptions.delete(event.requestId);
10732
11484
  }
10733
11485
  /**
10734
- * 处理卡片按钮回调
11486
+ * Handle card button / checker callbacks
10735
11487
  */
10736
11488
  async handleCardAction(data) {
10737
11489
  const { action, requestId, userId, optionId } = data;
@@ -10743,10 +11495,6 @@ var FeishuChannel = class extends (_a4 = BaseChannel) {
10743
11495
  this.logger.warn({ requestId }, "Invalid request ID format");
10744
11496
  return;
10745
11497
  }
10746
- if (!["agree", "reject", "always_allow", "select"].includes(action)) {
10747
- this.logger.warn({ action }, "Invalid card action");
10748
- return;
10749
- }
10750
11498
  if (!this.isAllowed(userId)) {
10751
11499
  this.logger.warn({ userId, requestId }, "Unauthorized user tried to respond to request");
10752
11500
  return;
@@ -10760,6 +11508,47 @@ var FeishuChannel = class extends (_a4 = BaseChannel) {
10760
11508
  this.logger.warn({ userId, requestId }, "User tried to respond to request they did not receive");
10761
11509
  return;
10762
11510
  }
11511
+ if (action === "check") {
11512
+ if (!optionId) {
11513
+ this.logger.warn({ requestId, userId }, "[Channel] Check missing optionId");
11514
+ return;
11515
+ }
11516
+ if (!this.pendingSelections.has(requestId)) {
11517
+ this.pendingSelections.set(requestId, /* @__PURE__ */ new Set());
11518
+ }
11519
+ const selected = this.pendingSelections.get(requestId);
11520
+ if (selected.has(optionId)) {
11521
+ selected.delete(optionId);
11522
+ } else {
11523
+ selected.add(optionId);
11524
+ }
11525
+ this.logger.info({ requestId, userId, optionId, selectedCount: selected.size }, "[Channel] Checker toggled");
11526
+ return;
11527
+ }
11528
+ if (action === "submit") {
11529
+ const selected = this.pendingSelections.get(requestId);
11530
+ const optionIds = selected ? Array.from(selected) : [];
11531
+ if (optionIds.length === 0) {
11532
+ this.logger.warn({ requestId, userId }, "[Channel] Submit with no selections");
11533
+ return;
11534
+ }
11535
+ const options = this.pendingOptions.get(requestId);
11536
+ const selectedValues = optionIds.map((id) => options?.find((opt) => opt.id === id)?.value).filter((v) => v !== void 0);
11537
+ this.bus.publishInteractionResponse({
11538
+ requestId,
11539
+ response: {
11540
+ requestId,
11541
+ action: "select",
11542
+ selectedValues
11543
+ },
11544
+ reason: `User submitted multi-select via Feishu`
11545
+ });
11546
+ this.logger.info({ requestId, userId, selectedCount: optionIds.length }, "[Channel] Multi-select submitted");
11547
+ this.pendingSelections.delete(requestId);
11548
+ this.pendingRequests.delete(requestId);
11549
+ this.pendingOptions.delete(requestId);
11550
+ return;
11551
+ }
10763
11552
  if (action === "agree" || action === "reject" || action === "always_allow") {
10764
11553
  const decision = action === "reject" ? "deny" : "allow";
10765
11554
  const isAlwaysAllow = action === "always_allow";
@@ -10768,7 +11557,6 @@ var FeishuChannel = class extends (_a4 = BaseChannel) {
10768
11557
  rules: [{ toolName: this.pendingToolNames.get(requestId) ?? "*", ruleContent: "*" }],
10769
11558
  behavior: "allow",
10770
11559
  destination: "localSettings"
10771
- // Project's settings.local.json
10772
11560
  }] : void 0;
10773
11561
  this.bus.publishInteractionResponse({
10774
11562
  requestId,
@@ -10780,6 +11568,8 @@ var FeishuChannel = class extends (_a4 = BaseChannel) {
10780
11568
  reason: `User clicked ${action} button via Feishu`
10781
11569
  });
10782
11570
  this.pendingToolNames.delete(requestId);
11571
+ this.pendingRequests.delete(requestId);
11572
+ this.pendingOptions.delete(requestId);
10783
11573
  this.logger.info({ requestId, userId, action: decision }, "[Channel] User response received");
10784
11574
  return;
10785
11575
  }
@@ -10804,28 +11594,20 @@ var FeishuChannel = class extends (_a4 = BaseChannel) {
10804
11594
  reason: `User selected option ${optionId} via Feishu`
10805
11595
  });
10806
11596
  this.logger.info({ requestId, userId, action: "select", optionId }, "[Channel] User response received");
11597
+ this.pendingRequests.delete(requestId);
11598
+ this.pendingOptions.delete(requestId);
10807
11599
  return;
10808
11600
  }
11601
+ this.logger.warn({ action, requestId }, "Unknown card action");
10809
11602
  }
10810
11603
  /**
10811
- * 发送带按钮的卡片消息
11604
+ * Send a pre-built card JSON string
10812
11605
  */
10813
- async sendCard(message, buttons) {
11606
+ async sendCardRaw(cardContent, message) {
10814
11607
  if (!this.client) {
10815
11608
  this.logger.error("Feishu client not initialized");
10816
11609
  throw new Error("Feishu client not initialized");
10817
11610
  }
10818
- let content;
10819
- if (message.context) {
10820
- content = this.formatContextToMarkdown(message.context);
10821
- } else if (message.text) {
10822
- content = message.text;
10823
- } else {
10824
- this.logger.warn("No content to send in Feishu card message");
10825
- return;
10826
- }
10827
- const title = this.getTitleForContext(message.context);
10828
- const cardContent = this.formatter.formatCard({ title, content, buttons });
10829
11611
  const targetUsers = this.feishuConfig.allowed_users || [];
10830
11612
  for (const userId of targetUsers) {
10831
11613
  if (userId === "*") continue;
@@ -11001,7 +11783,11 @@ _init3 = __decoratorStart(_a4);
11001
11783
  FeishuChannel = __decorateElement(_init3, 0, "FeishuChannel", _FeishuChannel_decorators, FeishuChannel);
11002
11784
  __runInitializers(_init3, 1, FeishuChannel);
11003
11785
 
11786
+ // src/adapters/channels/app/index.ts
11787
+ init_esm_shims();
11788
+
11004
11789
  // src/adapters/channels/app/mapper.ts
11790
+ init_esm_shims();
11005
11791
  function mapOutboundMessageToAppEvent(message, options = {}) {
11006
11792
  const context = message.context;
11007
11793
  if (!context) {
@@ -11161,6 +11947,7 @@ function readChannelInstanceId(message) {
11161
11947
  }
11162
11948
 
11163
11949
  // src/adapters/channels/app/server.ts
11950
+ init_esm_shims();
11164
11951
  import { WebSocketServer as NodeWebSocketServer, WebSocket as WebSocket2 } from "ws";
11165
11952
  var logger4 = getLogger();
11166
11953
  var DEFAULT_PATH = "/ws/channels/app";
@@ -11211,8 +11998,8 @@ var AppChannelWebSocketServer = class {
11211
11998
  if (!this.wss) {
11212
11999
  return;
11213
12000
  }
11214
- await new Promise((resolve2) => {
11215
- this.wss?.close(() => resolve2());
12001
+ await new Promise((resolve3) => {
12002
+ this.wss?.close(() => resolve3());
11216
12003
  });
11217
12004
  this.wss = null;
11218
12005
  }
@@ -11405,9 +12192,11 @@ function readFrameId(frame) {
11405
12192
  }
11406
12193
 
11407
12194
  // src/adapters/channels/app/protocol.ts
12195
+ init_esm_shims();
11408
12196
  import { randomUUID as randomUUID5 } from "crypto";
11409
12197
 
11410
12198
  // src/adapters/channels/app/query-service.ts
12199
+ init_esm_shims();
11411
12200
  var DEFAULT_CAPABILITIES = {
11412
12201
  chat: true,
11413
12202
  multiTurn: true,
@@ -11763,6 +12552,7 @@ function error(id, code, message) {
11763
12552
  }
11764
12553
 
11765
12554
  // src/core/session/SessionRecoveryService.ts
12555
+ init_esm_shims();
11766
12556
  import { readdirSync as readdirSync2, readFileSync as readFileSync5 } from "fs";
11767
12557
  import { join as join7, extname } from "path";
11768
12558
  var SessionRecoveryService = class {
@@ -11813,7 +12603,11 @@ var SessionRecoveryService = class {
11813
12603
  await gateway.createSession(
11814
12604
  claudeAgent.token,
11815
12605
  sessionData.sessionId,
11816
- { metadata: { kind: sessionData.kind, entrypoint: sessionData.entrypoint }, cwd: sessionData.cwd },
12606
+ {
12607
+ metadata: { kind: sessionData.kind, entrypoint: sessionData.entrypoint },
12608
+ cwd: sessionData.cwd,
12609
+ createdAt: sessionData.startedAt
12610
+ },
11817
12611
  true
11818
12612
  // skipPublishSessionStart — don't duplicate start notification
11819
12613
  );
@@ -11845,9 +12639,9 @@ var SessionRecoveryService = class {
11845
12639
  return [];
11846
12640
  }
11847
12641
  }
11848
- parseSessionFile(path2) {
12642
+ parseSessionFile(path3) {
11849
12643
  try {
11850
- const raw = readFileSync5(path2, "utf-8");
12644
+ const raw = readFileSync5(path3, "utf-8");
11851
12645
  const data = JSON.parse(raw);
11852
12646
  if (!data.sessionId || typeof data.pid !== "number") {
11853
12647
  return null;
@@ -11855,7 +12649,7 @@ var SessionRecoveryService = class {
11855
12649
  return data;
11856
12650
  } catch (err) {
11857
12651
  this.logger.warn(
11858
- { file: path2, error: err instanceof Error ? err.message : String(err) },
12652
+ { file: path3, error: err instanceof Error ? err.message : String(err) },
11859
12653
  "Failed to parse session file"
11860
12654
  );
11861
12655
  return null;
@@ -11983,6 +12777,7 @@ async function main() {
11983
12777
  bus,
11984
12778
  logger5,
11985
12779
  (id) => gateway.getSessionAgentType(id),
12780
+ (id) => gateway.getSessionInfo(id),
11986
12781
  bindingService4
11987
12782
  );
11988
12783
  notificationHandler.start();