shennian 0.2.89 → 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 (118) hide show
  1. package/dist/assets/wechat-channel/macos/manifest.json +13 -4
  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.js +1 -19
  8. package/dist/src/agents/claude.js +8 -305
  9. package/dist/src/agents/codex-control.js +2 -188
  10. package/dist/src/agents/codex-utils.js +7 -200
  11. package/dist/src/agents/codex.js +15 -916
  12. package/dist/src/agents/command-spec.js +2 -413
  13. package/dist/src/agents/config-status.js +1 -226
  14. package/dist/src/agents/cursor.js +1 -249
  15. package/dist/src/agents/custom.js +4 -271
  16. package/dist/src/agents/detect.js +1 -56
  17. package/dist/src/agents/external-channel-instructions.js +10 -94
  18. package/dist/src/agents/gemini.js +1 -173
  19. package/dist/src/agents/manager.js +13 -157
  20. package/dist/src/agents/model-registry/cache.js +1 -37
  21. package/dist/src/agents/model-registry/discovery.js +2 -187
  22. package/dist/src/agents/model-registry/parsers.js +4 -447
  23. package/dist/src/agents/model-registry/runner.js +1 -30
  24. package/dist/src/agents/model-registry/service.js +1 -78
  25. package/dist/src/agents/model-registry/types.js +1 -8
  26. package/dist/src/agents/model-registry.js +1 -18
  27. package/dist/src/agents/openclaw.js +2 -275
  28. package/dist/src/agents/opencode.js +1 -231
  29. package/dist/src/agents/pi-context.js +12 -217
  30. package/dist/src/agents/pi.js +14 -723
  31. package/dist/src/agents/platform-instructions.js +9 -54
  32. package/dist/src/channels/base.js +1 -3
  33. package/dist/src/channels/registry.js +1 -30
  34. package/dist/src/channels/reply-split.js +10 -89
  35. package/dist/src/channels/runtime.js +5 -564
  36. package/dist/src/channels/secret-registry.js +1 -46
  37. package/dist/src/channels/websocket.js +8 -378
  38. package/dist/src/channels/wechat-channel/anchor.js +1 -65
  39. package/dist/src/channels/wechat-channel/client.js +1 -96
  40. package/dist/src/channels/wechat-channel/cooldown.js +1 -38
  41. package/dist/src/channels/wechat-channel/fingerprint.js +1 -71
  42. package/dist/src/channels/wechat-channel/helper-assets.d.ts +10 -1
  43. package/dist/src/channels/wechat-channel/helper-assets.js +1 -68
  44. package/dist/src/channels/wechat-channel/helper-client.js +3 -149
  45. package/dist/src/channels/wechat-channel/helper-protocol.d.ts +1 -1
  46. package/dist/src/channels/wechat-channel/helper-protocol.js +1 -115
  47. package/dist/src/channels/wechat-channel/index.d.ts +1 -0
  48. package/dist/src/channels/wechat-channel/index.js +1 -19
  49. package/dist/src/channels/wechat-channel/ledger.js +1 -54
  50. package/dist/src/channels/wechat-channel/media-resolver.js +1 -181
  51. package/dist/src/channels/wechat-channel/message-key.js +1 -105
  52. package/dist/src/channels/wechat-channel/observer.js +1 -118
  53. package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +3 -0
  54. package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -112
  55. package/dist/src/channels/wechat-channel/outbound-sender.d.ts +26 -0
  56. package/dist/src/channels/wechat-channel/outbound-sender.js +1 -0
  57. package/dist/src/channels/wechat-channel/preflight.js +1 -48
  58. package/dist/src/channels/wechat-channel/runner.js +1 -84
  59. package/dist/src/channels/wechat-channel/runtime.js +1 -66
  60. package/dist/src/channels/wechat-channel/scheduler.d.ts +5 -0
  61. package/dist/src/channels/wechat-channel/scheduler.js +1 -152
  62. package/dist/src/channels/wechat-rpa/macos-flow.js +1 -96
  63. package/dist/src/channels/wechat-rpa/macos.js +6 -48
  64. package/dist/src/channels/wechat-rpa/normalizer.js +7 -127
  65. package/dist/src/channels/wechat-rpa.js +6 -1028
  66. package/dist/src/channels/wecom.js +4 -357
  67. package/dist/src/commands/agent.js +6 -131
  68. package/dist/src/commands/daemon-windows.js +8 -48
  69. package/dist/src/commands/daemon.js +19 -1013
  70. package/dist/src/commands/external-attachments.js +1 -51
  71. package/dist/src/commands/external.js +1 -137
  72. package/dist/src/commands/manager.js +2 -391
  73. package/dist/src/commands/pair-qr.js +1 -6
  74. package/dist/src/commands/pair.js +9 -287
  75. package/dist/src/commands/tools.js +1 -34
  76. package/dist/src/commands/upgrade.js +1 -198
  77. package/dist/src/config/index.js +1 -35
  78. package/dist/src/daemon-log.js +6 -58
  79. package/dist/src/env-path.js +1 -64
  80. package/dist/src/fs/boundary.js +1 -126
  81. package/dist/src/fs/handler.js +1 -130
  82. package/dist/src/fs/security.js +1 -32
  83. package/dist/src/fs/text-decoder.js +1 -110
  84. package/dist/src/index.js +2 -404
  85. package/dist/src/log-reporter.js +1 -16
  86. package/dist/src/manager/prompt.js +29 -34
  87. package/dist/src/manager/registry.js +2 -269
  88. package/dist/src/manager/runtime.js +19 -1007
  89. package/dist/src/native-fusion/config.js +1 -5
  90. package/dist/src/native-fusion/opencode-parser.js +3 -123
  91. package/dist/src/native-fusion/parser-common.js +8 -264
  92. package/dist/src/native-fusion/parsers.js +8 -729
  93. package/dist/src/native-fusion/service.js +2 -225
  94. package/dist/src/native-fusion/state.js +1 -22
  95. package/dist/src/native-fusion/types.js +1 -1
  96. package/dist/src/region.js +1 -88
  97. package/dist/src/relay/client.js +1 -343
  98. package/dist/src/session/archive-zip.js +1 -220
  99. package/dist/src/session/handlers/agent-config.js +1 -150
  100. package/dist/src/session/handlers/agents.js +1 -55
  101. package/dist/src/session/handlers/chat.js +2 -751
  102. package/dist/src/session/handlers/control.js +1 -55
  103. package/dist/src/session/handlers/fs.js +1 -783
  104. package/dist/src/session/handlers/session-refresh.js +1 -47
  105. package/dist/src/session/handlers/skills.js +1 -121
  106. package/dist/src/session/handlers/title.js +1 -60
  107. package/dist/src/session/handlers/tool-detail.js +1 -218
  108. package/dist/src/session/manager.js +1 -319
  109. package/dist/src/session/projection.js +1 -54
  110. package/dist/src/session/queue.js +4 -317
  111. package/dist/src/session/remote-attachments.js +1 -72
  112. package/dist/src/session/store.js +3 -109
  113. package/dist/src/session/types.js +1 -4
  114. package/dist/src/skills/registry.js +15 -148
  115. package/dist/src/skills/setup.js +1 -101
  116. package/dist/src/tools/markdown-to-pdf.js +10 -346
  117. package/dist/src/upgrade/engine.js +3 -347
  118. package/package.json +3 -2
@@ -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};