shennian 0.2.0 → 0.2.5

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.
Files changed (282) hide show
  1. package/dist/bin/shennian.d.ts +0 -1
  2. package/dist/bin/shennian.js +0 -1
  3. package/dist/src/agents/adapter.d.ts +0 -1
  4. package/dist/src/agents/adapter.js +0 -1
  5. package/dist/src/agents/claude.d.ts +1 -1
  6. package/dist/src/agents/claude.js +12 -6
  7. package/dist/src/agents/codex.d.ts +18 -1
  8. package/dist/src/agents/codex.js +372 -13
  9. package/dist/src/agents/command-spec.d.ts +28 -3
  10. package/dist/src/agents/command-spec.js +251 -10
  11. package/dist/src/agents/cursor.d.ts +0 -1
  12. package/dist/src/agents/cursor.js +2 -4
  13. package/dist/src/agents/custom.d.ts +0 -6
  14. package/dist/src/agents/custom.js +4 -40
  15. package/dist/src/agents/detect.d.ts +0 -1
  16. package/dist/src/agents/detect.js +0 -1
  17. package/dist/src/agents/gemini.d.ts +0 -1
  18. package/dist/src/agents/gemini.js +7 -3
  19. package/dist/src/agents/model-registry/cache.d.ts +0 -1
  20. package/dist/src/agents/model-registry/cache.js +0 -1
  21. package/dist/src/agents/model-registry/discovery.d.ts +0 -1
  22. package/dist/src/agents/model-registry/discovery.js +90 -48
  23. package/dist/src/agents/model-registry/parsers.d.ts +4 -1
  24. package/dist/src/agents/model-registry/parsers.js +168 -1
  25. package/dist/src/agents/model-registry/runner.d.ts +2 -7
  26. package/dist/src/agents/model-registry/runner.js +3 -134
  27. package/dist/src/agents/model-registry/service.d.ts +0 -1
  28. package/dist/src/agents/model-registry/service.js +12 -10
  29. package/dist/src/agents/model-registry/types.d.ts +0 -1
  30. package/dist/src/agents/model-registry/types.js +0 -1
  31. package/dist/src/agents/model-registry.d.ts +3 -2
  32. package/dist/src/agents/model-registry.js +3 -2
  33. package/dist/src/agents/openclaw.d.ts +0 -1
  34. package/dist/src/agents/openclaw.js +13 -4
  35. package/dist/src/agents/pi.d.ts +0 -1
  36. package/dist/src/agents/pi.js +0 -1
  37. package/dist/src/commands/agent.d.ts +0 -1
  38. package/dist/src/commands/agent.js +2 -33
  39. package/dist/src/commands/daemon.d.ts +6 -1
  40. package/dist/src/commands/daemon.js +153 -18
  41. package/dist/src/commands/pair-qr.d.ts +0 -1
  42. package/dist/src/commands/pair-qr.js +0 -1
  43. package/dist/src/commands/pair.d.ts +0 -1
  44. package/dist/src/commands/pair.js +0 -1
  45. package/dist/src/commands/upgrade.d.ts +0 -1
  46. package/dist/src/commands/upgrade.js +0 -1
  47. package/dist/src/config/index.d.ts +0 -1
  48. package/dist/src/config/index.js +0 -1
  49. package/dist/src/fs/handler.d.ts +0 -1
  50. package/dist/src/fs/handler.js +18 -1
  51. package/dist/src/fs/security.d.ts +0 -1
  52. package/dist/src/fs/security.js +5 -1
  53. package/dist/src/index.d.ts +0 -1
  54. package/dist/src/index.js +36 -8
  55. package/dist/src/log-reporter.d.ts +0 -1
  56. package/dist/src/log-reporter.js +2 -20
  57. package/dist/src/native-fusion/parsers.d.ts +0 -1
  58. package/dist/src/native-fusion/parsers.js +407 -44
  59. package/dist/src/native-fusion/service.d.ts +0 -1
  60. package/dist/src/native-fusion/service.js +16 -10
  61. package/dist/src/native-fusion/state.d.ts +0 -1
  62. package/dist/src/native-fusion/state.js +0 -1
  63. package/dist/src/native-fusion/types.d.ts +0 -1
  64. package/dist/src/native-fusion/types.js +0 -1
  65. package/dist/src/region.d.ts +0 -1
  66. package/dist/src/region.js +0 -1
  67. package/dist/src/relay/client.d.ts +11 -2
  68. package/dist/src/relay/client.js +22 -4
  69. package/dist/src/session/handlers/agents.d.ts +0 -1
  70. package/dist/src/session/handlers/agents.js +0 -1
  71. package/dist/src/session/handlers/chat.d.ts +0 -1
  72. package/dist/src/session/handlers/chat.js +49 -8
  73. package/dist/src/session/handlers/control.d.ts +0 -1
  74. package/dist/src/session/handlers/control.js +0 -1
  75. package/dist/src/session/handlers/fs.d.ts +0 -1
  76. package/dist/src/session/handlers/fs.js +37 -3
  77. package/dist/src/session/manager.d.ts +1 -1
  78. package/dist/src/session/manager.js +23 -4
  79. package/dist/src/session/store.d.ts +0 -1
  80. package/dist/src/session/store.js +0 -1
  81. package/dist/src/session/types.d.ts +6 -1
  82. package/dist/src/session/types.js +0 -1
  83. package/dist/src/upgrade/engine.d.ts +0 -1
  84. package/dist/src/upgrade/engine.js +0 -1
  85. package/package.json +3 -2
  86. package/dist/bin/shennian.d.ts.map +0 -1
  87. package/dist/bin/shennian.js.map +0 -1
  88. package/dist/src/__experiments__/probe-debug.d.ts +0 -2
  89. package/dist/src/__experiments__/probe-debug.d.ts.map +0 -1
  90. package/dist/src/__experiments__/probe-debug.js +0 -66
  91. package/dist/src/__experiments__/probe-debug.js.map +0 -1
  92. package/dist/src/__experiments__/probe-final-benchmark.d.ts +0 -3
  93. package/dist/src/__experiments__/probe-final-benchmark.d.ts.map +0 -1
  94. package/dist/src/__experiments__/probe-final-benchmark.js +0 -234
  95. package/dist/src/__experiments__/probe-final-benchmark.js.map +0 -1
  96. package/dist/src/__experiments__/probe-models-final.d.ts +0 -19
  97. package/dist/src/__experiments__/probe-models-final.d.ts.map +0 -1
  98. package/dist/src/__experiments__/probe-models-final.js +0 -250
  99. package/dist/src/__experiments__/probe-models-final.js.map +0 -1
  100. package/dist/src/__experiments__/probe-models.d.ts +0 -7
  101. package/dist/src/__experiments__/probe-models.d.ts.map +0 -1
  102. package/dist/src/__experiments__/probe-models.js +0 -251
  103. package/dist/src/__experiments__/probe-models.js.map +0 -1
  104. package/dist/src/__tests__/agents-e2e.d.ts +0 -21
  105. package/dist/src/__tests__/agents-e2e.d.ts.map +0 -1
  106. package/dist/src/__tests__/agents-e2e.js +0 -146
  107. package/dist/src/__tests__/agents-e2e.js.map +0 -1
  108. package/dist/src/__tests__/claude-adapter.test.d.ts +0 -2
  109. package/dist/src/__tests__/claude-adapter.test.d.ts.map +0 -1
  110. package/dist/src/__tests__/claude-adapter.test.js +0 -75
  111. package/dist/src/__tests__/claude-adapter.test.js.map +0 -1
  112. package/dist/src/__tests__/codex-adapter.test.d.ts +0 -2
  113. package/dist/src/__tests__/codex-adapter.test.d.ts.map +0 -1
  114. package/dist/src/__tests__/codex-adapter.test.js +0 -224
  115. package/dist/src/__tests__/codex-adapter.test.js.map +0 -1
  116. package/dist/src/__tests__/config.test.d.ts +0 -2
  117. package/dist/src/__tests__/config.test.d.ts.map +0 -1
  118. package/dist/src/__tests__/config.test.js +0 -60
  119. package/dist/src/__tests__/config.test.js.map +0 -1
  120. package/dist/src/__tests__/cursor-adapter.test.d.ts +0 -2
  121. package/dist/src/__tests__/cursor-adapter.test.d.ts.map +0 -1
  122. package/dist/src/__tests__/cursor-adapter.test.js +0 -69
  123. package/dist/src/__tests__/cursor-adapter.test.js.map +0 -1
  124. package/dist/src/__tests__/custom-agent-flow.test.d.ts +0 -2
  125. package/dist/src/__tests__/custom-agent-flow.test.d.ts.map +0 -1
  126. package/dist/src/__tests__/custom-agent-flow.test.js +0 -244
  127. package/dist/src/__tests__/custom-agent-flow.test.js.map +0 -1
  128. package/dist/src/__tests__/daemon-autostart.test.d.ts +0 -2
  129. package/dist/src/__tests__/daemon-autostart.test.d.ts.map +0 -1
  130. package/dist/src/__tests__/daemon-autostart.test.js +0 -60
  131. package/dist/src/__tests__/daemon-autostart.test.js.map +0 -1
  132. package/dist/src/__tests__/e2e-relay.d.ts +0 -19
  133. package/dist/src/__tests__/e2e-relay.d.ts.map +0 -1
  134. package/dist/src/__tests__/e2e-relay.js +0 -256
  135. package/dist/src/__tests__/e2e-relay.js.map +0 -1
  136. package/dist/src/__tests__/model-discovery.test.d.ts +0 -2
  137. package/dist/src/__tests__/model-discovery.test.d.ts.map +0 -1
  138. package/dist/src/__tests__/model-discovery.test.js +0 -47
  139. package/dist/src/__tests__/model-discovery.test.js.map +0 -1
  140. package/dist/src/__tests__/model-switching.test.d.ts +0 -2
  141. package/dist/src/__tests__/model-switching.test.d.ts.map +0 -1
  142. package/dist/src/__tests__/model-switching.test.js +0 -253
  143. package/dist/src/__tests__/model-switching.test.js.map +0 -1
  144. package/dist/src/__tests__/native-fusion-parsers.test.d.ts +0 -2
  145. package/dist/src/__tests__/native-fusion-parsers.test.d.ts.map +0 -1
  146. package/dist/src/__tests__/native-fusion-parsers.test.js +0 -216
  147. package/dist/src/__tests__/native-fusion-parsers.test.js.map +0 -1
  148. package/dist/src/__tests__/native-fusion-service.test.d.ts +0 -2
  149. package/dist/src/__tests__/native-fusion-service.test.d.ts.map +0 -1
  150. package/dist/src/__tests__/native-fusion-service.test.js +0 -157
  151. package/dist/src/__tests__/native-fusion-service.test.js.map +0 -1
  152. package/dist/src/__tests__/native-session-sync.test.d.ts +0 -2
  153. package/dist/src/__tests__/native-session-sync.test.d.ts.map +0 -1
  154. package/dist/src/__tests__/native-session-sync.test.js +0 -198
  155. package/dist/src/__tests__/native-session-sync.test.js.map +0 -1
  156. package/dist/src/__tests__/pair-qr.test.d.ts +0 -2
  157. package/dist/src/__tests__/pair-qr.test.d.ts.map +0 -1
  158. package/dist/src/__tests__/pair-qr.test.js +0 -13
  159. package/dist/src/__tests__/pair-qr.test.js.map +0 -1
  160. package/dist/src/__tests__/pi-context.test.d.ts +0 -2
  161. package/dist/src/__tests__/pi-context.test.d.ts.map +0 -1
  162. package/dist/src/__tests__/pi-context.test.js +0 -261
  163. package/dist/src/__tests__/pi-context.test.js.map +0 -1
  164. package/dist/src/__tests__/session-manager.test.d.ts +0 -2
  165. package/dist/src/__tests__/session-manager.test.d.ts.map +0 -1
  166. package/dist/src/__tests__/session-manager.test.js +0 -592
  167. package/dist/src/__tests__/session-manager.test.js.map +0 -1
  168. package/dist/src/__tests__/session-store.test.d.ts +0 -2
  169. package/dist/src/__tests__/session-store.test.d.ts.map +0 -1
  170. package/dist/src/__tests__/session-store.test.js +0 -106
  171. package/dist/src/__tests__/session-store.test.js.map +0 -1
  172. package/dist/src/agents/adapter.d.ts.map +0 -1
  173. package/dist/src/agents/adapter.js.map +0 -1
  174. package/dist/src/agents/claude.d.ts.map +0 -1
  175. package/dist/src/agents/claude.js.map +0 -1
  176. package/dist/src/agents/codex.d.ts.map +0 -1
  177. package/dist/src/agents/codex.js.map +0 -1
  178. package/dist/src/agents/command-spec.d.ts.map +0 -1
  179. package/dist/src/agents/command-spec.js.map +0 -1
  180. package/dist/src/agents/cursor.d.ts.map +0 -1
  181. package/dist/src/agents/cursor.js.map +0 -1
  182. package/dist/src/agents/custom.d.ts.map +0 -1
  183. package/dist/src/agents/custom.js.map +0 -1
  184. package/dist/src/agents/detect.d.ts.map +0 -1
  185. package/dist/src/agents/detect.js.map +0 -1
  186. package/dist/src/agents/gemini.d.ts.map +0 -1
  187. package/dist/src/agents/gemini.js.map +0 -1
  188. package/dist/src/agents/model-registry/cache.d.ts.map +0 -1
  189. package/dist/src/agents/model-registry/cache.js.map +0 -1
  190. package/dist/src/agents/model-registry/discovery.d.ts.map +0 -1
  191. package/dist/src/agents/model-registry/discovery.js.map +0 -1
  192. package/dist/src/agents/model-registry/parsers.d.ts.map +0 -1
  193. package/dist/src/agents/model-registry/parsers.js.map +0 -1
  194. package/dist/src/agents/model-registry/runner.d.ts.map +0 -1
  195. package/dist/src/agents/model-registry/runner.js.map +0 -1
  196. package/dist/src/agents/model-registry/service.d.ts.map +0 -1
  197. package/dist/src/agents/model-registry/service.js.map +0 -1
  198. package/dist/src/agents/model-registry/types.d.ts.map +0 -1
  199. package/dist/src/agents/model-registry/types.js.map +0 -1
  200. package/dist/src/agents/model-registry.d.ts.map +0 -1
  201. package/dist/src/agents/model-registry.js.map +0 -1
  202. package/dist/src/agents/openclaw.d.ts.map +0 -1
  203. package/dist/src/agents/openclaw.js.map +0 -1
  204. package/dist/src/agents/pi.d.ts.map +0 -1
  205. package/dist/src/agents/pi.js.map +0 -1
  206. package/dist/src/commands/agent.d.ts.map +0 -1
  207. package/dist/src/commands/agent.js.map +0 -1
  208. package/dist/src/commands/daemon.d.ts.map +0 -1
  209. package/dist/src/commands/daemon.js.map +0 -1
  210. package/dist/src/commands/pair-qr.d.ts.map +0 -1
  211. package/dist/src/commands/pair-qr.js.map +0 -1
  212. package/dist/src/commands/pair.d.ts.map +0 -1
  213. package/dist/src/commands/pair.js.map +0 -1
  214. package/dist/src/commands/upgrade.d.ts.map +0 -1
  215. package/dist/src/commands/upgrade.js.map +0 -1
  216. package/dist/src/config/index.d.ts.map +0 -1
  217. package/dist/src/config/index.js.map +0 -1
  218. package/dist/src/fs/handler.d.ts.map +0 -1
  219. package/dist/src/fs/handler.js.map +0 -1
  220. package/dist/src/fs/multimodal.d.ts +0 -5
  221. package/dist/src/fs/multimodal.d.ts.map +0 -1
  222. package/dist/src/fs/multimodal.js +0 -39
  223. package/dist/src/fs/multimodal.js.map +0 -1
  224. package/dist/src/fs/security.d.ts.map +0 -1
  225. package/dist/src/fs/security.js.map +0 -1
  226. package/dist/src/index.d.ts.map +0 -1
  227. package/dist/src/index.js.map +0 -1
  228. package/dist/src/log-reporter.d.ts.map +0 -1
  229. package/dist/src/log-reporter.js.map +0 -1
  230. package/dist/src/native-fusion/parsers.d.ts.map +0 -1
  231. package/dist/src/native-fusion/parsers.js.map +0 -1
  232. package/dist/src/native-fusion/service.d.ts.map +0 -1
  233. package/dist/src/native-fusion/service.js.map +0 -1
  234. package/dist/src/native-fusion/state.d.ts.map +0 -1
  235. package/dist/src/native-fusion/state.js.map +0 -1
  236. package/dist/src/native-fusion/types.d.ts.map +0 -1
  237. package/dist/src/native-fusion/types.js.map +0 -1
  238. package/dist/src/native-sync/discover.d.ts +0 -6
  239. package/dist/src/native-sync/discover.d.ts.map +0 -1
  240. package/dist/src/native-sync/discover.js +0 -69
  241. package/dist/src/native-sync/discover.js.map +0 -1
  242. package/dist/src/native-sync/parsers.d.ts +0 -3
  243. package/dist/src/native-sync/parsers.d.ts.map +0 -1
  244. package/dist/src/native-sync/parsers.js +0 -373
  245. package/dist/src/native-sync/parsers.js.map +0 -1
  246. package/dist/src/native-sync/service.d.ts +0 -16
  247. package/dist/src/native-sync/service.d.ts.map +0 -1
  248. package/dist/src/native-sync/service.js +0 -95
  249. package/dist/src/native-sync/service.js.map +0 -1
  250. package/dist/src/native-sync/state.d.ts +0 -6
  251. package/dist/src/native-sync/state.d.ts.map +0 -1
  252. package/dist/src/native-sync/state.js +0 -34
  253. package/dist/src/native-sync/state.js.map +0 -1
  254. package/dist/src/native-sync/types.d.ts +0 -23
  255. package/dist/src/native-sync/types.d.ts.map +0 -1
  256. package/dist/src/native-sync/types.js +0 -4
  257. package/dist/src/native-sync/types.js.map +0 -1
  258. package/dist/src/region.d.ts.map +0 -1
  259. package/dist/src/region.js.map +0 -1
  260. package/dist/src/relay/client.d.ts.map +0 -1
  261. package/dist/src/relay/client.js.map +0 -1
  262. package/dist/src/session/handlers/agents.d.ts.map +0 -1
  263. package/dist/src/session/handlers/agents.js.map +0 -1
  264. package/dist/src/session/handlers/chat.d.ts.map +0 -1
  265. package/dist/src/session/handlers/chat.js.map +0 -1
  266. package/dist/src/session/handlers/control.d.ts.map +0 -1
  267. package/dist/src/session/handlers/control.js.map +0 -1
  268. package/dist/src/session/handlers/fs.d.ts.map +0 -1
  269. package/dist/src/session/handlers/fs.js.map +0 -1
  270. package/dist/src/session/handlers/queue.d.ts +0 -4
  271. package/dist/src/session/handlers/queue.d.ts.map +0 -1
  272. package/dist/src/session/handlers/queue.js +0 -66
  273. package/dist/src/session/handlers/queue.js.map +0 -1
  274. package/dist/src/session/manager.d.ts.map +0 -1
  275. package/dist/src/session/manager.js.map +0 -1
  276. package/dist/src/session/store.d.ts.map +0 -1
  277. package/dist/src/session/store.js.map +0 -1
  278. package/dist/src/session/types.d.ts.map +0 -1
  279. package/dist/src/session/types.js.map +0 -1
  280. package/dist/src/upgrade/engine.d.ts.map +0 -1
  281. package/dist/src/upgrade/engine.js.map +0 -1
  282. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -4,6 +4,7 @@ import { createHash } from 'node:crypto';
4
4
  import fs from 'node:fs';
5
5
  import os from 'node:os';
6
6
  import path from 'node:path';
7
+ import { buildUserMessagePayload } from '@shennian/wire';
7
8
  function normalizeText(text) {
8
9
  return stripGitDirectiveArtifacts(text.replace(/\r\n/g, '\n').trim());
9
10
  }
@@ -46,6 +47,346 @@ function makeEventKey(filePath, offset, kind) {
46
47
  const fingerprint = createHash('sha1').update(filePath).digest('hex').slice(0, 16);
47
48
  return `${fingerprint}:${offset}:${kind}`;
48
49
  }
50
+ function safeStringify(value) {
51
+ if (value == null)
52
+ return '';
53
+ if (typeof value === 'string')
54
+ return value;
55
+ try {
56
+ return JSON.stringify(value);
57
+ }
58
+ catch {
59
+ return String(value);
60
+ }
61
+ }
62
+ function normalizeToolText(text) {
63
+ return text.replace(/\r\n/g, '\n').trim();
64
+ }
65
+ function parseStructuredString(value) {
66
+ if (typeof value !== 'string')
67
+ return value;
68
+ const trimmed = value.trim();
69
+ if (!trimmed)
70
+ return '';
71
+ try {
72
+ return JSON.parse(trimmed);
73
+ }
74
+ catch {
75
+ return value;
76
+ }
77
+ }
78
+ function summarizeToolResult(value) {
79
+ if (value == null)
80
+ return '';
81
+ if (typeof value === 'string')
82
+ return normalizeToolText(value);
83
+ if (Array.isArray(value)) {
84
+ const textParts = value
85
+ .map((item) => extractTextContent(item))
86
+ .filter(Boolean);
87
+ if (textParts.length > 0)
88
+ return normalizeToolText(textParts.join('\n\n'));
89
+ }
90
+ if (typeof value === 'object') {
91
+ const text = extractTextContent(value);
92
+ if (text)
93
+ return normalizeToolText(text);
94
+ }
95
+ return normalizeToolText(safeStringify(value));
96
+ }
97
+ function extractTextContent(value) {
98
+ if (value == null)
99
+ return '';
100
+ if (typeof value === 'string')
101
+ return value;
102
+ if (Array.isArray(value)) {
103
+ return value
104
+ .map((item) => extractTextContent(item))
105
+ .filter(Boolean)
106
+ .join('\n\n');
107
+ }
108
+ if (typeof value !== 'object')
109
+ return '';
110
+ const record = value;
111
+ if (typeof record.text === 'string')
112
+ return record.text;
113
+ if (typeof record.output === 'string')
114
+ return record.output;
115
+ if (typeof record.message === 'string')
116
+ return record.message;
117
+ if ('Ok' in record)
118
+ return extractTextContent(record.Ok);
119
+ if ('Err' in record)
120
+ return extractTextContent(record.Err);
121
+ if ('content' in record)
122
+ return extractTextContent(record.content);
123
+ if ('contentItems' in record)
124
+ return extractTextContent(record.contentItems);
125
+ if ('result' in record)
126
+ return extractTextContent(record.result);
127
+ return '';
128
+ }
129
+ function buildToolPayload(name, args, result) {
130
+ const payload = {
131
+ v: 1,
132
+ type: 'tool',
133
+ name,
134
+ };
135
+ if (args !== undefined)
136
+ payload.args = args;
137
+ if (result !== undefined)
138
+ payload.result = summarizeToolResult(result);
139
+ return JSON.stringify(payload);
140
+ }
141
+ function escapeMarkdownLabel(label) {
142
+ return label.replace(/[[\]\\]/g, '\\$&');
143
+ }
144
+ function buildMarkdownImageRef(filePath, label = 'Generated image') {
145
+ return `![${escapeMarkdownLabel(label)}](<${filePath}>)`;
146
+ }
147
+ function buildImagePayload(filePath) {
148
+ const name = path.basename(filePath) || 'generated-image.png';
149
+ return JSON.stringify({
150
+ v: 1,
151
+ type: 'image',
152
+ content: buildMarkdownImageRef(filePath, name),
153
+ attachments: [
154
+ {
155
+ path: filePath,
156
+ name,
157
+ mimeType: 'image/png',
158
+ kind: 'image',
159
+ },
160
+ ],
161
+ });
162
+ }
163
+ function inferMimeType(filePath) {
164
+ const ext = path.extname(filePath).toLowerCase();
165
+ if (ext === '.png')
166
+ return 'image/png';
167
+ if (ext === '.jpg' || ext === '.jpeg')
168
+ return 'image/jpeg';
169
+ if (ext === '.webp')
170
+ return 'image/webp';
171
+ if (ext === '.gif')
172
+ return 'image/gif';
173
+ return 'application/octet-stream';
174
+ }
175
+ function parseCodexLocalImageAttachment(value) {
176
+ if (typeof value === 'string') {
177
+ const imagePath = value.trim();
178
+ if (!imagePath)
179
+ return null;
180
+ return {
181
+ path: imagePath,
182
+ name: path.basename(imagePath) || 'image.png',
183
+ mimeType: inferMimeType(imagePath),
184
+ kind: 'image',
185
+ };
186
+ }
187
+ if (typeof value !== 'object' || value === null)
188
+ return null;
189
+ const entry = value;
190
+ const imagePath = typeof entry.path === 'string' ? entry.path
191
+ : typeof entry.file_path === 'string' ? entry.file_path
192
+ : typeof entry.saved_path === 'string' ? entry.saved_path
193
+ : '';
194
+ if (!imagePath.trim())
195
+ return null;
196
+ const name = typeof entry.name === 'string' && entry.name.trim()
197
+ ? entry.name
198
+ : path.basename(imagePath) || 'image.png';
199
+ const mimeType = typeof entry.mimeType === 'string' && entry.mimeType.trim()
200
+ ? entry.mimeType
201
+ : inferMimeType(imagePath);
202
+ return {
203
+ path: imagePath,
204
+ name,
205
+ mimeType,
206
+ kind: 'image',
207
+ };
208
+ }
209
+ function parseCodexTextElements(value) {
210
+ if (!Array.isArray(value))
211
+ return '';
212
+ const parts = value
213
+ .map((item) => {
214
+ if (typeof item === 'string')
215
+ return item;
216
+ if (typeof item === 'object' && item !== null) {
217
+ const record = item;
218
+ return typeof record.text === 'string' ? record.text : '';
219
+ }
220
+ return '';
221
+ })
222
+ .map((text) => normalizeText(text))
223
+ .filter(Boolean);
224
+ return parts.join('\n\n');
225
+ }
226
+ function stripCodexUserMessageWrapper(text) {
227
+ const normalized = normalizeText(text);
228
+ if (!normalized)
229
+ return '';
230
+ const requestMatch = normalized.match(/My request for Codex:\s*([\s\S]*)$/i);
231
+ if (requestMatch && requestMatch[1])
232
+ return normalizeText(requestMatch[1]);
233
+ return normalized;
234
+ }
235
+ function parseCodexUserMessage(payload) {
236
+ const textFromElements = parseCodexTextElements(payload.text_elements);
237
+ const textFromInput = Array.isArray(payload.input)
238
+ ? parseCodexTextElements(payload.input)
239
+ : '';
240
+ const textFromMessage = typeof payload.message === 'string'
241
+ ? stripCodexUserMessageWrapper(payload.message)
242
+ : '';
243
+ const text = textFromElements || textFromInput || textFromMessage;
244
+ const attachments = Array.isArray(payload.local_images)
245
+ ? payload.local_images
246
+ .map(parseCodexLocalImageAttachment)
247
+ .filter((item) => item != null)
248
+ : [];
249
+ if (!text && attachments.length === 0)
250
+ return null;
251
+ if (attachments.length > 0) {
252
+ return {
253
+ payload: buildUserMessagePayload(text, attachments),
254
+ titleText: text,
255
+ };
256
+ }
257
+ return { payload: text, titleText: text };
258
+ }
259
+ function pushCodexEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts, payload, title, modelId, workDir, role = 'agent') {
260
+ if (!payload)
261
+ return;
262
+ events.push({
263
+ agentType: 'codex',
264
+ sourceMode: 'codex_rollout_import',
265
+ sourceSessionKey,
266
+ sourceEventKey: makeEventKey(filePath, lineOffset, kind),
267
+ cursor: makeCursor(filePath, lineOffset),
268
+ role,
269
+ ts,
270
+ payload,
271
+ title,
272
+ modelId,
273
+ workDir,
274
+ });
275
+ }
276
+ function pushCodexToolEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts, toolName, title, modelId, workDir, args, result) {
277
+ pushCodexEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts, buildToolPayload(toolName, args, result), title, modelId, workDir);
278
+ }
279
+ function parseCodexResponseItem(events, filePath, lineOffset, payload, sourceSessionKey, ts, title, modelId, workDir) {
280
+ const itemType = typeof payload.type === 'string' ? payload.type : '';
281
+ if (!itemType)
282
+ return;
283
+ if (itemType === 'function_call') {
284
+ const name = typeof payload.name === 'string' ? payload.name : 'function_call';
285
+ pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, name, title, modelId, workDir, parseStructuredString(payload.arguments));
286
+ return;
287
+ }
288
+ if (itemType === 'function_call_output') {
289
+ pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, 'function_call_output', title, modelId, workDir, payload.call_id, payload.output);
290
+ return;
291
+ }
292
+ if (itemType === 'custom_tool_call') {
293
+ const name = typeof payload.name === 'string' ? payload.name : 'custom_tool_call';
294
+ const args = payload.input !== undefined ? { input: payload.input } : undefined;
295
+ pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, name, title, modelId, workDir, args);
296
+ return;
297
+ }
298
+ if (itemType === 'custom_tool_call_output') {
299
+ const name = typeof payload.name === 'string' ? payload.name : 'custom_tool_call_output';
300
+ const result = payload.output ?? payload.result ?? payload.content;
301
+ pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, name, title, modelId, workDir, payload.call_id, result);
302
+ return;
303
+ }
304
+ if (itemType === 'web_search_call') {
305
+ const action = typeof payload.action === 'object' && payload.action !== null
306
+ ? payload.action
307
+ : null;
308
+ pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, 'web_search', title, modelId, workDir, action ?? payload.query);
309
+ return;
310
+ }
311
+ }
312
+ function parseCodexEventMessage(events, filePath, lineOffset, payload, sourceSessionKey, ts, title, modelId, workDir) {
313
+ const eventType = typeof payload.type === 'string' ? payload.type : '';
314
+ if (!eventType)
315
+ return;
316
+ if (eventType === 'user_message') {
317
+ const parsedUser = parseCodexUserMessage(payload);
318
+ if (!parsedUser)
319
+ return;
320
+ pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, parsedUser.payload, title, modelId, workDir, 'user');
321
+ return;
322
+ }
323
+ if (eventType === 'agent_message') {
324
+ const text = typeof payload.message === 'string' ? normalizeText(payload.message) : '';
325
+ if (!text)
326
+ return;
327
+ pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, text, title, modelId, workDir);
328
+ return;
329
+ }
330
+ if (eventType === 'exec_command_end') {
331
+ const command = Array.isArray(payload.command) ? payload.command : payload.parsed_cmd ?? payload.command;
332
+ const exitCode = payload.exit_code ?? payload.exitCode;
333
+ const output = [
334
+ typeof payload.aggregated_output === 'string' ? payload.aggregated_output : '',
335
+ exitCode != null ? `\n(exit ${String(exitCode)})` : '',
336
+ ].join('');
337
+ pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, 'command_execution', title, modelId, workDir, { command }, output);
338
+ return;
339
+ }
340
+ if (eventType === 'patch_apply_end') {
341
+ pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, 'apply_patch', title, modelId, workDir, payload.changes, {
342
+ success: payload.success,
343
+ stdout: payload.stdout,
344
+ stderr: payload.stderr,
345
+ });
346
+ return;
347
+ }
348
+ if (eventType === 'mcp_tool_call_end') {
349
+ const invocation = typeof payload.invocation === 'object' && payload.invocation !== null
350
+ ? payload.invocation
351
+ : null;
352
+ const tool = typeof invocation?.tool === 'string' ? invocation.tool : 'mcp_tool_call';
353
+ const args = {
354
+ server: invocation?.server,
355
+ ...(typeof invocation?.arguments === 'object' && invocation.arguments !== null
356
+ ? invocation.arguments
357
+ : {}),
358
+ };
359
+ pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, tool, title, modelId, workDir, args, payload.result);
360
+ return;
361
+ }
362
+ if (eventType === 'dynamic_tool_call_request') {
363
+ const tool = typeof payload.tool === 'string' ? payload.tool : 'dynamic_tool_call';
364
+ pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, tool, title, modelId, workDir, payload.arguments);
365
+ return;
366
+ }
367
+ if (eventType === 'dynamic_tool_call_response') {
368
+ const tool = typeof payload.tool === 'string' ? payload.tool : 'dynamic_tool_call';
369
+ pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, tool, title, modelId, workDir, payload.callId ?? payload.call_id, payload.result ?? payload.output);
370
+ return;
371
+ }
372
+ if (eventType === 'web_search_end') {
373
+ const action = typeof payload.action === 'object' && payload.action !== null
374
+ ? payload.action
375
+ : null;
376
+ pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, 'web_search', title, modelId, workDir, action ?? payload.query, payload.query);
377
+ return;
378
+ }
379
+ if (eventType === 'image_generation_end') {
380
+ const savedPath = typeof payload.saved_path === 'string' ? payload.saved_path.trim() : '';
381
+ if (!savedPath)
382
+ return;
383
+ pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, buildImagePayload(savedPath), title, modelId, workDir);
384
+ return;
385
+ }
386
+ if (eventType === 'view_image_tool_call') {
387
+ pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, 'view_image', title, modelId, workDir, payload.path ?? payload.image_path ?? payload);
388
+ }
389
+ }
49
390
  function relativeProjectDir(cwd) {
50
391
  const home = os.homedir();
51
392
  if (cwd.startsWith(home))
@@ -82,6 +423,7 @@ function readCodexSessionMeta(filePath) {
82
423
  sourceSessionKey: '',
83
424
  workDir: '',
84
425
  modelId: null,
426
+ title: '',
85
427
  };
86
428
  }
87
429
  const payload = typeof parsed.payload === 'object' && parsed.payload !== null
@@ -92,12 +434,15 @@ function readCodexSessionMeta(filePath) {
92
434
  sourceSessionKey: '',
93
435
  workDir: '',
94
436
  modelId: null,
437
+ title: '',
95
438
  };
96
439
  }
440
+ const sourceSessionKey = typeof payload.id === 'string' ? payload.id : '';
97
441
  return {
98
- sourceSessionKey: typeof payload.id === 'string' ? payload.id : '',
442
+ sourceSessionKey,
99
443
  workDir: typeof payload.cwd === 'string' ? payload.cwd : '',
100
- modelId: typeof payload.model_provider === 'string' ? payload.model_provider : null,
444
+ modelId: readCodexModelId(payload),
445
+ title: lookupCodexThreadName(sourceSessionKey) ?? '',
101
446
  };
102
447
  }
103
448
  finally {
@@ -107,8 +452,52 @@ function readCodexSessionMeta(filePath) {
107
452
  sourceSessionKey: '',
108
453
  workDir: '',
109
454
  modelId: null,
455
+ title: '',
110
456
  };
111
457
  }
458
+ function readCodexModelId(payload) {
459
+ const model = typeof payload.model === 'string' ? payload.model.trim() : '';
460
+ return model || null;
461
+ }
462
+ function readCodexIndexTitle(parsed, sourceSessionKey) {
463
+ const id = typeof parsed.id === 'string'
464
+ ? parsed.id
465
+ : typeof parsed.thread_id === 'string'
466
+ ? parsed.thread_id
467
+ : typeof parsed.session_id === 'string'
468
+ ? parsed.session_id
469
+ : '';
470
+ if (id !== sourceSessionKey)
471
+ return null;
472
+ const title = typeof parsed.thread_name === 'string'
473
+ ? parsed.thread_name
474
+ : typeof parsed.title === 'string'
475
+ ? parsed.title
476
+ : '';
477
+ const trimmed = title.trim();
478
+ return trimmed ? trimmed.slice(0, 120) : null;
479
+ }
480
+ function lookupCodexThreadName(sourceSessionKey) {
481
+ if (!sourceSessionKey)
482
+ return null;
483
+ const indexPath = path.join(os.homedir(), '.codex', 'session_index.jsonl');
484
+ if (!fs.existsSync(indexPath))
485
+ return null;
486
+ const content = fs.readFileSync(indexPath, 'utf8');
487
+ const lines = content.split('\n');
488
+ for (let index = lines.length - 1; index >= 0; index -= 1) {
489
+ const line = lines[index];
490
+ if (!line.trim())
491
+ continue;
492
+ const parsed = safeParse(line);
493
+ if (!parsed)
494
+ continue;
495
+ const title = readCodexIndexTitle(parsed, sourceSessionKey);
496
+ if (title)
497
+ return title;
498
+ }
499
+ return null;
500
+ }
112
501
  export function listCodexRolloutFiles() {
113
502
  const root = path.join(os.homedir(), '.codex', 'sessions');
114
503
  if (!fs.existsSync(root))
@@ -175,8 +564,7 @@ export function parseCodexRolloutChunk(filePath, startOffset) {
175
564
  const chunk = chunkBuffer.subarray(0, lastNewline + 1).toString('utf8');
176
565
  const lines = chunk.split('\n').filter(Boolean);
177
566
  const events = [];
178
- let { sourceSessionKey, workDir, modelId } = readCodexSessionMeta(filePath);
179
- let title = '';
567
+ let { sourceSessionKey, workDir, modelId, title } = readCodexSessionMeta(filePath);
180
568
  for (let index = 0, offset = startOffset; index < lines.length; index++) {
181
569
  const line = lines[index];
182
570
  const parsed = safeParse(line);
@@ -194,49 +582,25 @@ export function parseCodexRolloutChunk(filePath, startOffset) {
194
582
  if (type === 'session_meta') {
195
583
  sourceSessionKey = typeof payload.id === 'string' ? payload.id : sourceSessionKey;
196
584
  workDir = typeof payload.cwd === 'string' ? payload.cwd : workDir;
197
- modelId = typeof payload.model_provider === 'string' ? payload.model_provider : modelId;
585
+ modelId = readCodexModelId(payload) ?? modelId;
586
+ if (!title)
587
+ title = lookupCodexThreadName(sourceSessionKey) ?? '';
198
588
  continue;
199
589
  }
200
- if (type !== 'event_msg' || !sourceSessionKey)
590
+ if (!sourceSessionKey)
591
+ continue;
592
+ if (type === 'response_item') {
593
+ parseCodexResponseItem(events, filePath, lineOffset, payload, sourceSessionKey, ts, title, modelId, workDir);
201
594
  continue;
202
- const eventType = typeof payload.type === 'string' ? payload.type : '';
203
- if (eventType === 'user_message') {
204
- const text = typeof payload.message === 'string' ? normalizeText(payload.message) : '';
205
- if (!text)
206
- continue;
207
- if (!title)
208
- title = text.slice(0, 80);
209
- events.push({
210
- agentType: 'codex',
211
- sourceMode: 'codex_rollout_import',
212
- sourceSessionKey,
213
- sourceEventKey: makeEventKey(filePath, lineOffset, 'user_message'),
214
- cursor: makeCursor(filePath, lineOffset),
215
- role: 'user',
216
- ts,
217
- payload: text,
218
- title,
219
- modelId,
220
- workDir,
221
- });
222
595
  }
223
- else if (eventType === 'agent_message') {
224
- const text = typeof payload.message === 'string' ? normalizeText(payload.message) : '';
225
- if (!text)
226
- continue;
227
- events.push({
228
- agentType: 'codex',
229
- sourceMode: 'codex_rollout_import',
230
- sourceSessionKey,
231
- sourceEventKey: makeEventKey(filePath, lineOffset, 'agent_message'),
232
- cursor: makeCursor(filePath, lineOffset),
233
- role: 'agent',
234
- ts,
235
- payload: text,
236
- title,
237
- modelId,
238
- workDir,
239
- });
596
+ if (type === 'event_msg') {
597
+ const eventType = typeof payload.type === 'string' ? payload.type : '';
598
+ if (eventType === 'user_message') {
599
+ const parsedUser = parseCodexUserMessage(payload);
600
+ if (parsedUser?.titleText && !title)
601
+ title = parsedUser.titleText.slice(0, 80);
602
+ }
603
+ parseCodexEventMessage(events, filePath, lineOffset, payload, sourceSessionKey, ts, title, modelId, workDir);
240
604
  }
241
605
  }
242
606
  return { nextOffset, events };
@@ -321,4 +685,3 @@ export function parseClaudeTranscriptChunk(filePath, startOffset) {
321
685
  }
322
686
  return { nextOffset, events };
323
687
  }
324
- //# sourceMappingURL=parsers.js.map
@@ -23,4 +23,3 @@ export declare class NativeSessionFusionService {
23
23
  private tryClaimManagedEcho;
24
24
  private isSuppressed;
25
25
  }
26
- //# sourceMappingURL=service.d.ts.map
@@ -4,10 +4,10 @@ import { randomUUID } from 'node:crypto';
4
4
  import fs from 'node:fs';
5
5
  import { listClaudeTranscriptFiles, listCodexRolloutFiles, parseClaudeTranscriptChunk, parseCodexRolloutChunk, } from './parsers.js';
6
6
  import { loadNativeScannerState, saveNativeScannerState } from './state.js';
7
- const SCAN_INTERVAL_MS = 8_000;
8
- const CLAIM_TTL_MS = 30_000;
9
- const SUPPRESSION_TTL_MS = 45_000;
10
- const MAX_BATCH_SIZE = 200;
7
+ const SCAN_INTERVAL_MS = 60_000;
8
+ const CLAIM_TTL_MS = SCAN_INTERVAL_MS * 2;
9
+ const MANAGED_RUN_SUPPRESSION_TTL_MS = 30 * 60_000;
10
+ const MAX_BATCH_SIZE = 20;
11
11
  function normalizeText(text) {
12
12
  return text.replace(/\r\n/g, '\n').trim();
13
13
  }
@@ -36,9 +36,6 @@ export class NativeSessionFusionService {
36
36
  }
37
37
  handleConnected() {
38
38
  this.start();
39
- void this.scanNow().catch((error) => {
40
- console.error('[native-fusion] initial scan failed', error);
41
- });
42
39
  }
43
40
  registerManagedSend(params) {
44
41
  if (!params.canonicalMessageId)
@@ -149,7 +146,7 @@ export class NativeSessionFusionService {
149
146
  agentType: event.agentType,
150
147
  sourceSessionKey: event.sourceSessionKey,
151
148
  startedAt: event.ts,
152
- endsAt: Math.max(now, event.ts) + SUPPRESSION_TTL_MS,
149
+ endsAt: Math.max(now, event.ts) + MANAGED_RUN_SUPPRESSION_TTL_MS,
153
150
  });
154
151
  return {
155
152
  ...event,
@@ -164,7 +161,16 @@ export class NativeSessionFusionService {
164
161
  const window = this.suppressionWindows.get(key);
165
162
  if (!window)
166
163
  return false;
167
- return event.ts >= window.startedAt && event.ts <= window.endsAt;
164
+ if (event.ts < window.startedAt)
165
+ return false;
166
+ if (event.ts > window.endsAt) {
167
+ this.suppressionWindows.delete(key);
168
+ return false;
169
+ }
170
+ if (event.role === 'user') {
171
+ this.suppressionWindows.delete(key);
172
+ return false;
173
+ }
174
+ return true;
168
175
  }
169
176
  }
170
- //# sourceMappingURL=service.js.map
@@ -1,4 +1,3 @@
1
1
  import type { NativeScannerState } from './types.js';
2
2
  export declare function loadNativeScannerState(): NativeScannerState;
3
3
  export declare function saveNativeScannerState(state: NativeScannerState): void;
4
- //# sourceMappingURL=state.d.ts.map
@@ -20,4 +20,3 @@ export function saveNativeScannerState(state) {
20
20
  fs.mkdirSync(path.dirname(STATE_FILE), { recursive: true });
21
21
  fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
22
22
  }
23
- //# sourceMappingURL=state.js.map
@@ -22,4 +22,3 @@ export type ManagedSuppressionWindow = {
22
22
  startedAt: number;
23
23
  endsAt: number;
24
24
  };
25
- //# sourceMappingURL=types.d.ts.map
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=types.js.map
@@ -13,4 +13,3 @@ export declare const SERVERS: Record<Region, {
13
13
  export declare function detectAndChooseServer(): Promise<string>;
14
14
  export declare function urlToRegion(url: string): Region;
15
15
  export declare function regionToUrl(region: Region): string;
16
- //# sourceMappingURL=region.d.ts.map
@@ -97,4 +97,3 @@ export function urlToRegion(url) {
97
97
  export function regionToUrl(region) {
98
98
  return SERVERS[region].url;
99
99
  }
100
- //# sourceMappingURL=region.js.map
@@ -6,9 +6,17 @@ export type CliRelayOptions = {
6
6
  agentList?: string[];
7
7
  onReq?: (req: ReqFrame) => void;
8
8
  onConnected?: () => void;
9
- onDisconnected?: () => void;
9
+ onDisconnected?: (info: CliRelayDisconnectInfo) => void;
10
10
  };
11
11
  export type CliRelayState = 'connecting' | 'connected' | 'disconnected';
12
+ export type CliRelayDisconnectInfo = {
13
+ code?: number;
14
+ reason?: string;
15
+ error?: string;
16
+ phase: 'connecting' | 'connected' | 'disconnected';
17
+ trigger?: 'connect-timeout' | 'pong-timeout' | 'heartbeat-timeout' | 'socket-error' | 'socket-close';
18
+ reconnectAttempt: number;
19
+ };
12
20
  export declare class CliRelayClient {
13
21
  private options;
14
22
  private ws;
@@ -20,6 +28,8 @@ export declare class CliRelayClient {
20
28
  private pingTimer;
21
29
  private pongTimer;
22
30
  private disposed;
31
+ private closeTrigger;
32
+ private lastSocketError;
23
33
  /** Buffered agent events awaiting server ack, keyed by event id */
24
34
  private sendBuffer;
25
35
  private pendingAcks;
@@ -50,4 +60,3 @@ export declare class CliRelayClient {
50
60
  private scheduleReconnect;
51
61
  private cleanup;
52
62
  }
53
- //# sourceMappingURL=client.d.ts.map