shennian 0.2.88 → 0.2.90

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 (143) hide show
  1. package/dist/assets/wechat-channel/macos/manifest.json +22 -0
  2. package/dist/assets/wechat-channel/macos/shennian-wechat-channel-helper +0 -0
  3. package/dist/bin/shennian.js +1 -1
  4. package/dist/publish-build-manifest.json +548 -0
  5. package/dist/scripts/wechat-rpa-confirmation.mjs +5 -97
  6. package/dist/src/agent-env.js +4 -105
  7. package/dist/src/agents/adapter.d.ts +6 -0
  8. package/dist/src/agents/adapter.js +1 -19
  9. package/dist/src/agents/claude.js +8 -305
  10. package/dist/src/agents/codex-control.d.ts +35 -0
  11. package/dist/src/agents/codex-control.js +2 -0
  12. package/dist/src/agents/codex-utils.js +7 -200
  13. package/dist/src/agents/codex.d.ts +8 -0
  14. package/dist/src/agents/codex.js +15 -863
  15. package/dist/src/agents/command-spec.js +2 -413
  16. package/dist/src/agents/config-status.js +1 -226
  17. package/dist/src/agents/cursor.js +1 -249
  18. package/dist/src/agents/custom.js +4 -271
  19. package/dist/src/agents/detect.js +1 -56
  20. package/dist/src/agents/external-channel-instructions.js +10 -94
  21. package/dist/src/agents/gemini.js +1 -173
  22. package/dist/src/agents/manager.js +13 -157
  23. package/dist/src/agents/model-registry/cache.js +1 -37
  24. package/dist/src/agents/model-registry/discovery.js +2 -187
  25. package/dist/src/agents/model-registry/parsers.js +4 -447
  26. package/dist/src/agents/model-registry/runner.js +1 -30
  27. package/dist/src/agents/model-registry/service.js +1 -78
  28. package/dist/src/agents/model-registry/types.js +1 -8
  29. package/dist/src/agents/model-registry.js +1 -18
  30. package/dist/src/agents/openclaw.js +2 -275
  31. package/dist/src/agents/opencode.js +1 -231
  32. package/dist/src/agents/pi-context.js +12 -217
  33. package/dist/src/agents/pi.js +14 -723
  34. package/dist/src/agents/platform-instructions.js +9 -54
  35. package/dist/src/channels/base.d.ts +4 -1
  36. package/dist/src/channels/base.js +1 -3
  37. package/dist/src/channels/registry.js +1 -30
  38. package/dist/src/channels/reply-split.js +10 -89
  39. package/dist/src/channels/runtime.d.ts +1 -0
  40. package/dist/src/channels/runtime.js +5 -533
  41. package/dist/src/channels/secret-registry.d.ts +1 -0
  42. package/dist/src/channels/secret-registry.js +1 -46
  43. package/dist/src/channels/websocket.js +8 -378
  44. package/dist/src/channels/wechat-channel/anchor.d.ts +10 -0
  45. package/dist/src/channels/wechat-channel/anchor.js +1 -0
  46. package/dist/src/channels/wechat-channel/client.d.ts +74 -0
  47. package/dist/src/channels/wechat-channel/client.js +1 -0
  48. package/dist/src/channels/wechat-channel/cooldown.d.ts +15 -0
  49. package/dist/src/channels/wechat-channel/cooldown.js +1 -0
  50. package/dist/src/channels/wechat-channel/fingerprint.d.ts +28 -0
  51. package/dist/src/channels/wechat-channel/fingerprint.js +1 -0
  52. package/dist/src/channels/wechat-channel/helper-assets.d.ts +37 -0
  53. package/dist/src/channels/wechat-channel/helper-assets.js +1 -0
  54. package/dist/src/channels/wechat-channel/helper-client.d.ts +25 -0
  55. package/dist/src/channels/wechat-channel/helper-client.js +3 -0
  56. package/dist/src/channels/wechat-channel/helper-protocol.d.ts +84 -0
  57. package/dist/src/channels/wechat-channel/helper-protocol.js +1 -0
  58. package/dist/src/channels/wechat-channel/index.d.ts +17 -0
  59. package/dist/src/channels/wechat-channel/index.js +1 -0
  60. package/dist/src/channels/wechat-channel/ledger.d.ts +33 -0
  61. package/dist/src/channels/wechat-channel/ledger.js +1 -0
  62. package/dist/src/channels/wechat-channel/media-resolver.d.ts +32 -0
  63. package/dist/src/channels/wechat-channel/media-resolver.js +1 -0
  64. package/dist/src/channels/wechat-channel/message-key.d.ts +19 -0
  65. package/dist/src/channels/wechat-channel/message-key.js +1 -0
  66. package/dist/src/channels/wechat-channel/observer.d.ts +64 -0
  67. package/dist/src/channels/wechat-channel/observer.js +1 -0
  68. package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +69 -0
  69. package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -0
  70. package/dist/src/channels/wechat-channel/outbound-sender.d.ts +26 -0
  71. package/dist/src/channels/wechat-channel/outbound-sender.js +1 -0
  72. package/dist/src/channels/wechat-channel/preflight.d.ts +37 -0
  73. package/dist/src/channels/wechat-channel/preflight.js +1 -0
  74. package/dist/src/channels/wechat-channel/runner.d.ts +34 -0
  75. package/dist/src/channels/wechat-channel/runner.js +1 -0
  76. package/dist/src/channels/wechat-channel/runtime.d.ts +45 -0
  77. package/dist/src/channels/wechat-channel/runtime.js +1 -0
  78. package/dist/src/channels/wechat-channel/scheduler.d.ts +35 -0
  79. package/dist/src/channels/wechat-channel/scheduler.js +1 -0
  80. package/dist/src/channels/wechat-rpa/macos-flow.js +1 -96
  81. package/dist/src/channels/wechat-rpa/macos.js +6 -48
  82. package/dist/src/channels/wechat-rpa/normalizer.js +7 -127
  83. package/dist/src/channels/wechat-rpa.d.ts +21 -0
  84. package/dist/src/channels/wechat-rpa.js +6 -1022
  85. package/dist/src/channels/wecom.js +4 -357
  86. package/dist/src/commands/agent.js +6 -131
  87. package/dist/src/commands/daemon-windows.js +8 -48
  88. package/dist/src/commands/daemon.js +19 -1013
  89. package/dist/src/commands/external-attachments.js +1 -51
  90. package/dist/src/commands/external.js +1 -137
  91. package/dist/src/commands/manager.js +2 -389
  92. package/dist/src/commands/pair-qr.js +1 -6
  93. package/dist/src/commands/pair.js +9 -287
  94. package/dist/src/commands/tools.js +1 -34
  95. package/dist/src/commands/upgrade.js +1 -198
  96. package/dist/src/config/index.js +1 -35
  97. package/dist/src/daemon-log.js +6 -58
  98. package/dist/src/env-path.js +1 -64
  99. package/dist/src/fs/boundary.js +1 -126
  100. package/dist/src/fs/handler.js +1 -130
  101. package/dist/src/fs/security.js +1 -32
  102. package/dist/src/fs/text-decoder.d.ts +10 -0
  103. package/dist/src/fs/text-decoder.js +1 -0
  104. package/dist/src/index.js +2 -404
  105. package/dist/src/log-reporter.js +1 -16
  106. package/dist/src/manager/prompt.js +29 -34
  107. package/dist/src/manager/registry.js +2 -269
  108. package/dist/src/manager/runtime.js +19 -1003
  109. package/dist/src/native-fusion/config.js +1 -5
  110. package/dist/src/native-fusion/opencode-parser.js +3 -123
  111. package/dist/src/native-fusion/parser-common.js +8 -264
  112. package/dist/src/native-fusion/parsers.js +8 -729
  113. package/dist/src/native-fusion/service.d.ts +10 -0
  114. package/dist/src/native-fusion/service.js +2 -198
  115. package/dist/src/native-fusion/state.js +1 -22
  116. package/dist/src/native-fusion/types.js +1 -1
  117. package/dist/src/region.js +1 -88
  118. package/dist/src/relay/client.js +1 -343
  119. package/dist/src/session/archive-zip.js +1 -220
  120. package/dist/src/session/handlers/agent-config.js +1 -150
  121. package/dist/src/session/handlers/agents.js +1 -55
  122. package/dist/src/session/handlers/chat.js +2 -733
  123. package/dist/src/session/handlers/control.js +1 -55
  124. package/dist/src/session/handlers/fs.js +1 -747
  125. package/dist/src/session/handlers/session-refresh.js +1 -35
  126. package/dist/src/session/handlers/skills.js +1 -121
  127. package/dist/src/session/handlers/title.js +1 -60
  128. package/dist/src/session/handlers/tool-detail.d.ts +3 -0
  129. package/dist/src/session/handlers/tool-detail.js +1 -0
  130. package/dist/src/session/manager.d.ts +3 -0
  131. package/dist/src/session/manager.js +1 -261
  132. package/dist/src/session/projection.js +1 -54
  133. package/dist/src/session/queue.js +4 -317
  134. package/dist/src/session/remote-attachments.js +1 -72
  135. package/dist/src/session/store.js +3 -109
  136. package/dist/src/session/types.d.ts +4 -0
  137. package/dist/src/session/types.js +1 -4
  138. package/dist/src/skills/registry.js +15 -148
  139. package/dist/src/skills/setup.js +1 -101
  140. package/dist/src/tools/markdown-to-pdf.js +10 -346
  141. package/dist/src/upgrade/engine.js +3 -347
  142. package/package.json +3 -2
  143. package/dist/scripts/wechat-rpa-download-candidates.mjs +0 -105
@@ -1,269 +1,2 @@
1
- // @arch docs/features/manager-agent.md
2
- // @test src/__tests__/manager-runtime.test.ts
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import { randomUUID } from 'node:crypto';
6
- import { extractPayloadText, isToolPayload } from '@shennian/wire';
7
- import { resolveShennianPath } from '../config/index.js';
8
- import { listSessionRecords, readMessages } from '../session/store.js';
9
- import { listProjectedSessions } from '../session/projection.js';
10
- const REGISTRY_PATH = resolveShennianPath('manager-registry.json');
11
- function nowIso() {
12
- return new Date().toISOString();
13
- }
14
- function emptyRegistry() {
15
- return { managers: {}, workers: {}, replyTargets: {} };
16
- }
17
- export class ManagerRegistry {
18
- load() {
19
- try {
20
- const parsed = JSON.parse(fs.readFileSync(REGISTRY_PATH, 'utf-8'));
21
- return {
22
- managers: parsed.managers ?? {},
23
- workers: parsed.workers ?? {},
24
- replyTargets: parsed.replyTargets ?? {},
25
- };
26
- }
27
- catch {
28
- return emptyRegistry();
29
- }
30
- }
31
- save(registry) {
32
- fs.mkdirSync(path.dirname(REGISTRY_PATH), { recursive: true });
33
- fs.writeFileSync(REGISTRY_PATH, JSON.stringify(registry, null, 2));
34
- }
35
- upsertManager(input) {
36
- const registry = this.load();
37
- const existing = registry.managers[input.sessionId];
38
- const timestamp = nowIso();
39
- const record = {
40
- sessionId: input.sessionId,
41
- agentSessionId: input.agentSessionId ?? existing?.agentSessionId ?? null,
42
- workDir: input.workDir,
43
- machineId: input.machineId ?? existing?.machineId ?? null,
44
- modelId: input.modelId,
45
- defaultWorkerAgentType: input.defaultWorkerAgentType ?? existing?.defaultWorkerAgentType ?? null,
46
- defaultWorkerModelId: input.defaultWorkerModelId ?? existing?.defaultWorkerModelId ?? null,
47
- status: input.status ?? existing?.status ?? 'idle',
48
- managedWorkerSessionIds: existing?.managedWorkerSessionIds ?? [],
49
- attachedExternalChannels: existing?.attachedExternalChannels ?? [],
50
- createdAt: existing?.createdAt ?? timestamp,
51
- updatedAt: timestamp,
52
- };
53
- registry.managers[input.sessionId] = record;
54
- this.save(registry);
55
- return record;
56
- }
57
- getManager(sessionId) {
58
- return this.load().managers[sessionId];
59
- }
60
- addWorker(input) {
61
- const registry = this.load();
62
- const manager = registry.managers[input.managerSessionId];
63
- if (!manager)
64
- throw new Error('Manager runtime is not registered');
65
- const sessionId = input.sessionId ?? `sess_worker_${randomUUID()}`;
66
- const timestamp = nowIso();
67
- const record = {
68
- sessionId,
69
- agentType: input.agentType,
70
- workDir: input.workDir,
71
- managedBy: input.managerSessionId,
72
- status: 'running',
73
- createdAt: timestamp,
74
- updatedAt: timestamp,
75
- lastActivityAt: timestamp,
76
- summary: input.summary ?? null,
77
- agentSessionId: null,
78
- runId: null,
79
- };
80
- registry.workers[sessionId] = record;
81
- if (!manager.managedWorkerSessionIds.includes(sessionId)) {
82
- manager.managedWorkerSessionIds.push(sessionId);
83
- }
84
- manager.updatedAt = timestamp;
85
- this.save(registry);
86
- return record;
87
- }
88
- updateWorker(sessionId, patch) {
89
- const registry = this.load();
90
- const existing = registry.workers[sessionId];
91
- if (!existing)
92
- return undefined;
93
- const record = {
94
- ...existing,
95
- ...patch,
96
- updatedAt: nowIso(),
97
- };
98
- registry.workers[sessionId] = record;
99
- this.save(registry);
100
- return record;
101
- }
102
- listWorkers(managerSessionId, opts = {}) {
103
- const registry = this.load();
104
- const manager = registry.managers[managerSessionId];
105
- if (!manager)
106
- return [];
107
- const managedWorkers = Object.values(registry.workers)
108
- .filter((worker) => worker.workDir === manager.workDir)
109
- .filter((worker) => opts.includeManagers || worker.agentType !== 'manager')
110
- .map((worker) => this.decorateManagedWorker(worker, opts.runningSessionIds));
111
- const managedIds = new Set(managedWorkers.map((worker) => worker.sessionId));
112
- const projectSessions = listSessionRecords()
113
- .filter((session) => session.workDir === manager.workDir)
114
- .filter((session) => opts.includeManagers || session.agentType !== 'manager')
115
- .filter((session) => !managedIds.has(session.sessionId))
116
- .map((session) => this.sessionRecordToWorker(session, opts.runningSessionIds));
117
- const knownIds = new Set([...managedWorkers, ...projectSessions].map((session) => session.sessionId));
118
- const projectedSource = opts.projectedSessions ?? listProjectedSessions();
119
- const projectedSessions = projectedSource
120
- .filter((session) => session.workDir === manager.workDir)
121
- .filter((session) => opts.includeManagers || session.agentType !== 'manager')
122
- .filter((session) => !knownIds.has(session.id))
123
- .map((session) => this.projectedSessionToWorker(session, opts.runningSessionIds));
124
- return [...managedWorkers, ...projectSessions, ...projectedSessions]
125
- .sort((a, b) => b.lastActivityAt.localeCompare(a.lastActivityAt));
126
- }
127
- getWorkerForManager(managerSessionId, sessionId) {
128
- const registry = this.load();
129
- const manager = registry.managers[managerSessionId];
130
- const worker = registry.workers[sessionId];
131
- if (!manager)
132
- return undefined;
133
- if (worker) {
134
- if (worker.workDir !== manager.workDir)
135
- return undefined;
136
- if (worker.agentType === 'manager')
137
- return undefined;
138
- return this.decorateManagedWorker(worker);
139
- }
140
- const session = listSessionRecords().find((item) => item.sessionId === sessionId);
141
- if (!session || session.workDir !== manager.workDir || session.agentType === 'manager')
142
- return undefined;
143
- return this.sessionRecordToWorker(session);
144
- }
145
- decorateManagedWorker(worker, runningSessionIds) {
146
- const status = runningSessionIds?.has(worker.sessionId) ? 'running' : worker.status;
147
- const transcript = this.readTranscriptSummary(worker.sessionId, worker.summary ?? null);
148
- const lastMessagePreview = transcript.lastMessagePreview ?? worker.lastMessagePreview ?? worker.summary ?? null;
149
- const userGoal = worker.userGoal ?? transcript.userGoal ?? null;
150
- return {
151
- ...worker,
152
- managedBy: worker.managedBy ?? null,
153
- status,
154
- title: worker.title ?? userGoal ?? lastMessagePreview ?? worker.summary ?? worker.sessionId,
155
- userGoal,
156
- lastMessagePreview,
157
- summary: worker.summary ?? lastMessagePreview,
158
- canResume: worker.canResume ?? worker.status !== 'aborted',
159
- source: worker.source ?? 'manager_registry',
160
- role: 'managed_worker',
161
- };
162
- }
163
- sessionRecordToWorker(session, runningSessionIds) {
164
- const transcript = this.readTranscriptSummary(session.sessionId, session.lastMessagePreview ?? null);
165
- const lastMessagePreview = transcript.lastMessagePreview ?? session.lastMessagePreview ?? null;
166
- const userGoal = transcript.userGoal;
167
- const status = runningSessionIds?.has(session.sessionId)
168
- ? 'running'
169
- : session.status === 'failed'
170
- ? 'error'
171
- : session.status === 'completed'
172
- ? 'final'
173
- : 'idle';
174
- return {
175
- sessionId: session.sessionId,
176
- agentType: session.agentType,
177
- workDir: session.workDir,
178
- managedBy: null,
179
- status,
180
- createdAt: session.createdAt,
181
- updatedAt: session.updatedAt,
182
- lastActivityAt: session.lastActivityAt,
183
- title: userGoal ?? lastMessagePreview ?? session.sessionId,
184
- userGoal,
185
- lastMessagePreview,
186
- summary: lastMessagePreview ?? userGoal ?? null,
187
- agentSessionId: session.agentSessionId ?? null,
188
- runId: null,
189
- canResume: Boolean(session.agentSessionId),
190
- source: 'local_index',
191
- role: 'project_session',
192
- };
193
- }
194
- projectedSessionToWorker(session, runningSessionIds) {
195
- const lastMessagePreview = session.lastMessagePreview ?? null;
196
- const userGoal = session.title?.trim() || lastMessagePreview;
197
- const status = runningSessionIds?.has(session.id)
198
- ? 'running'
199
- : session.status === 'failed'
200
- ? 'error'
201
- : session.status === 'completed'
202
- ? 'final'
203
- : 'idle';
204
- return {
205
- sessionId: session.id,
206
- agentType: session.agentType,
207
- workDir: session.workDir,
208
- managedBy: null,
209
- status,
210
- createdAt: session.createdAt,
211
- updatedAt: session.updatedAt,
212
- lastActivityAt: session.lastActivityAt || session.updatedAt,
213
- title: userGoal ?? session.id,
214
- userGoal: userGoal ?? null,
215
- lastMessagePreview,
216
- summary: lastMessagePreview ?? userGoal ?? null,
217
- agentSessionId: session.agentSessionId ?? null,
218
- runId: session.activity?.runId ?? null,
219
- canResume: true,
220
- source: 'app_projection',
221
- role: 'project_session',
222
- };
223
- }
224
- readTranscriptSummary(sessionId, fallbackPreview) {
225
- const messages = readMessages(sessionId, { limit: 200 });
226
- if (!messages.length)
227
- return { userGoal: null, lastMessagePreview: fallbackPreview };
228
- const chronological = [...messages].sort((a, b) => a.ts - b.ts);
229
- const firstUser = chronological.find((message) => message.role === 'user');
230
- const lastReadable = [...chronological].reverse().find((message) => readableText(message));
231
- return {
232
- userGoal: firstUser ? clip(readableText(firstUser), 160) : null,
233
- lastMessagePreview: clip(readableText(lastReadable), 180) ?? fallbackPreview,
234
- };
235
- }
236
- createReplyTarget(input) {
237
- const registry = this.load();
238
- const record = {
239
- replyTarget: `rt_${randomUUID()}`,
240
- managerSessionId: input.managerSessionId,
241
- channelId: input.channelId,
242
- conversationId: input.conversationId,
243
- messageId: input.messageId ?? null,
244
- createdAt: nowIso(),
245
- };
246
- registry.replyTargets[record.replyTarget] = record;
247
- this.save(registry);
248
- return record;
249
- }
250
- getReplyTarget(replyTarget) {
251
- return this.load().replyTargets[replyTarget];
252
- }
253
- getLatestReplyTargetForManager(managerSessionId) {
254
- return Object.values(this.load().replyTargets)
255
- .filter((target) => target.managerSessionId === managerSessionId)
256
- .sort((a, b) => b.createdAt.localeCompare(a.createdAt))[0];
257
- }
258
- }
259
- function readableText(message) {
260
- if (!message || isToolPayload(message.payload))
261
- return null;
262
- const text = extractPayloadText(message.payload).replace(/\r\n/g, '\n').trim();
263
- return text || null;
264
- }
265
- function clip(text, max) {
266
- if (!text)
267
- return null;
268
- return text.length > max ? `${text.slice(0, max)}...` : text;
269
- }
1
+ import u from"node:fs";import h from"node:path";import{randomUUID as y}from"node:crypto";import{extractPayloadText as k,isToolPayload as T}from"@shennian/wire";import{resolveShennianPath as A}from"../config/index.js";import{listSessionRecords as I,readMessages as w}from"../session/store.js";import{listProjectedSessions as v}from"../session/projection.js";const g=A("manager-registry.json");function l(){return new Date().toISOString()}function M(){return{managers:{},workers:{},replyTargets:{}}}class B{load(){try{const e=JSON.parse(u.readFileSync(g,"utf-8"));return{managers:e.managers??{},workers:e.workers??{},replyTargets:e.replyTargets??{}}}catch{return M()}}save(e){u.mkdirSync(h.dirname(g),{recursive:!0}),u.writeFileSync(g,JSON.stringify(e,null,2))}upsertManager(e){const t=this.load(),r=t.managers[e.sessionId],a=l(),s={sessionId:e.sessionId,agentSessionId:e.agentSessionId??r?.agentSessionId??null,workDir:e.workDir,machineId:e.machineId??r?.machineId??null,modelId:e.modelId,defaultWorkerAgentType:e.defaultWorkerAgentType??r?.defaultWorkerAgentType??null,defaultWorkerModelId:e.defaultWorkerModelId??r?.defaultWorkerModelId??null,status:e.status??r?.status??"idle",managedWorkerSessionIds:r?.managedWorkerSessionIds??[],attachedExternalChannels:r?.attachedExternalChannels??[],createdAt:r?.createdAt??a,updatedAt:a};return t.managers[e.sessionId]=s,this.save(t),s}getManager(e){return this.load().managers[e]}addWorker(e){const t=this.load(),r=t.managers[e.managerSessionId];if(!r)throw new Error("Manager runtime is not registered");const a=e.sessionId??`sess_worker_${y()}`,s=l(),o={sessionId:a,agentType:e.agentType,workDir:e.workDir,managedBy:e.managerSessionId,status:"running",createdAt:s,updatedAt:s,lastActivityAt:s,summary:e.summary??null,agentSessionId:null,runId:null};return t.workers[a]=o,r.managedWorkerSessionIds.includes(a)||r.managedWorkerSessionIds.push(a),r.updatedAt=s,this.save(t),o}updateWorker(e,t){const r=this.load(),a=r.workers[e];if(!a)return;const s={...a,...t,updatedAt:l()};return r.workers[e]=s,this.save(r),s}listWorkers(e,t={}){const r=this.load(),a=r.managers[e];if(!a)return[];const s=Object.values(r.workers).filter(n=>n.workDir===a.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").map(n=>this.decorateManagedWorker(n,t.runningSessionIds)),o=new Set(s.map(n=>n.sessionId)),d=I().filter(n=>n.workDir===a.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").filter(n=>!o.has(n.sessionId)).map(n=>this.sessionRecordToWorker(n,t.runningSessionIds)),c=new Set([...s,...d].map(n=>n.sessionId)),f=(t.projectedSessions??v()).filter(n=>n.workDir===a.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").filter(n=>!c.has(n.id)).map(n=>this.projectedSessionToWorker(n,t.runningSessionIds));return[...s,...d,...f].sort((n,S)=>S.lastActivityAt.localeCompare(n.lastActivityAt))}getWorkerForManager(e,t){const r=this.load(),a=r.managers[e],s=r.workers[t];if(!a)return;if(s)return s.workDir!==a.workDir||s.agentType==="manager"?void 0:this.decorateManagedWorker(s);const o=I().find(d=>d.sessionId===t);if(!(!o||o.workDir!==a.workDir||o.agentType==="manager"))return this.sessionRecordToWorker(o)}decorateManagedWorker(e,t){const r=t?.has(e.sessionId)?"running":e.status,a=this.readTranscriptSummary(e.sessionId,e.summary??null),s=a.lastMessagePreview??e.lastMessagePreview??e.summary??null,o=e.userGoal??a.userGoal??null;return{...e,managedBy:e.managedBy??null,status:r,title:e.title??o??s??e.summary??e.sessionId,userGoal:o,lastMessagePreview:s,summary:e.summary??s,canResume:e.canResume??e.status!=="aborted",source:e.source??"manager_registry",role:"managed_worker"}}sessionRecordToWorker(e,t){const r=this.readTranscriptSummary(e.sessionId,e.lastMessagePreview??null),a=r.lastMessagePreview??e.lastMessagePreview??null,s=r.userGoal,o=t?.has(e.sessionId)?"running":e.status==="failed"?"error":e.status==="completed"?"final":"idle";return{sessionId:e.sessionId,agentType:e.agentType,workDir:e.workDir,managedBy:null,status:o,createdAt:e.createdAt,updatedAt:e.updatedAt,lastActivityAt:e.lastActivityAt,title:s??a??e.sessionId,userGoal:s,lastMessagePreview:a,summary:a??s??null,agentSessionId:e.agentSessionId??null,runId:null,canResume:!!e.agentSessionId,source:"local_index",role:"project_session"}}projectedSessionToWorker(e,t){const r=e.lastMessagePreview??null,a=e.title?.trim()||r,s=t?.has(e.id)?"running":e.status==="failed"?"error":e.status==="completed"?"final":"idle";return{sessionId:e.id,agentType:e.agentType,workDir:e.workDir,managedBy:null,status:s,createdAt:e.createdAt,updatedAt:e.updatedAt,lastActivityAt:e.lastActivityAt||e.updatedAt,title:a??e.id,userGoal:a??null,lastMessagePreview:r,summary:r??a??null,agentSessionId:e.agentSessionId??null,runId:e.activity?.runId??null,canResume:!0,source:"app_projection",role:"project_session"}}readTranscriptSummary(e,t){const r=w(e,{limit:200});if(!r.length)return{userGoal:null,lastMessagePreview:t};const a=[...r].sort((d,c)=>d.ts-c.ts),s=a.find(d=>d.role==="user"),o=[...a].reverse().find(d=>m(d));return{userGoal:s?p(m(s),160):null,lastMessagePreview:p(m(o),180)??t}}createReplyTarget(e){const t=this.load(),r={replyTarget:`rt_${y()}`,managerSessionId:e.managerSessionId,channelId:e.channelId,conversationId:e.conversationId,messageId:e.messageId??null,createdAt:l()};return t.replyTargets[r.replyTarget]=r,this.save(t),r}getReplyTarget(e){return this.load().replyTargets[e]}getLatestReplyTargetForManager(e){return Object.values(this.load().replyTargets).filter(t=>t.managerSessionId===e).sort((t,r)=>r.createdAt.localeCompare(t.createdAt))[0]}}function m(i){return!i||T(i.payload)?null:k(i.payload).replace(/\r\n/g,`
2
+ `).trim()||null}function p(i,e){return i?i.length>e?`${i.slice(0,e)}...`:i:null}export{B as ManagerRegistry};