@openacp/cli 2026.330.2 → 2026.331.1

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 (145) hide show
  1. package/README.md +17 -0
  2. package/dist/adapter-ELG3VRZ3.js +14 -0
  3. package/dist/{agent-catalog-SZQQERV7.js → agent-catalog-UYD26QDK.js} +3 -3
  4. package/dist/{api-client-XTLRRFPX.js → api-client-PEMHYL5U.js} +2 -2
  5. package/dist/{api-server-JLBDKCU4.js → api-server-DATG2KBR.js} +3 -3
  6. package/dist/api-server-L5Z7XACW.js +7 -0
  7. package/dist/chunk-23SRIVG4.js +50 -0
  8. package/dist/chunk-23SRIVG4.js.map +1 -0
  9. package/dist/{chunk-YIGBJFJL.js → chunk-7GXEMMEV.js} +15 -15
  10. package/dist/{chunk-QWVHCTCA.js → chunk-7U6IZIJP.js} +37 -23
  11. package/dist/chunk-7U6IZIJP.js.map +1 -0
  12. package/dist/{chunk-FCTC7KDT.js → chunk-7YIKTRSM.js} +14 -10
  13. package/dist/chunk-7YIKTRSM.js.map +1 -0
  14. package/dist/{chunk-MITTQMGZ.js → chunk-BYCJQPMN.js} +5 -5
  15. package/dist/chunk-BYCJQPMN.js.map +1 -0
  16. package/dist/{chunk-5ZNBNIK3.js → chunk-EWVXSTQK.js} +193 -53
  17. package/dist/chunk-EWVXSTQK.js.map +1 -0
  18. package/dist/{chunk-UWH7KIAA.js → chunk-FPKQYCQS.js} +88 -13
  19. package/dist/chunk-FPKQYCQS.js.map +1 -0
  20. package/dist/{chunk-GEOXPGCO.js → chunk-K6UY5M75.js} +12 -9
  21. package/dist/chunk-K6UY5M75.js.map +1 -0
  22. package/dist/{chunk-KDU3ZEWT.js → chunk-KGAQW6F4.js} +12 -3
  23. package/dist/chunk-KGAQW6F4.js.map +1 -0
  24. package/dist/{chunk-7RKPIM3E.js → chunk-LRV56K2M.js} +205 -16
  25. package/dist/chunk-LRV56K2M.js.map +1 -0
  26. package/dist/{chunk-V2YZWYXT.js → chunk-MDJHCCFS.js} +18 -17
  27. package/dist/chunk-MDJHCCFS.js.map +1 -0
  28. package/dist/chunk-NHD5XDD2.js +686 -0
  29. package/dist/chunk-NHD5XDD2.js.map +1 -0
  30. package/dist/{chunk-APS6UEFU.js → chunk-NJX75BLK.js} +1 -1
  31. package/dist/chunk-NJX75BLK.js.map +1 -0
  32. package/dist/{chunk-5HKQCYOI.js → chunk-NOEAJNTK.js} +14 -3
  33. package/dist/chunk-NOEAJNTK.js.map +1 -0
  34. package/dist/chunk-ON7HB5O7.js +58 -0
  35. package/dist/chunk-ON7HB5O7.js.map +1 -0
  36. package/dist/{chunk-5OCGO27U.js → chunk-OSBZXY2W.js} +2 -1
  37. package/dist/chunk-OSBZXY2W.js.map +1 -0
  38. package/dist/{chunk-PA6MNBG4.js → chunk-P3HHJANC.js} +32 -13
  39. package/dist/chunk-P3HHJANC.js.map +1 -0
  40. package/dist/{chunk-BTJHGSLM.js → chunk-R2YLDQLI.js} +9 -10
  41. package/dist/chunk-R2YLDQLI.js.map +1 -0
  42. package/dist/{chunk-CFUJGWOP.js → chunk-SSLVNCEA.js} +27 -3
  43. package/dist/chunk-SSLVNCEA.js.map +1 -0
  44. package/dist/{chunk-MPGEHTGE.js → chunk-TGP34LQN.js} +9 -7
  45. package/dist/chunk-TGP34LQN.js.map +1 -0
  46. package/dist/{chunk-TMVTSWVH.js → chunk-VUSCVRJL.js} +2 -1
  47. package/dist/chunk-VUSCVRJL.js.map +1 -0
  48. package/dist/chunk-XRJUS6FE.js +53 -0
  49. package/dist/chunk-XRJUS6FE.js.map +1 -0
  50. package/dist/{chunk-W4LK6WJP.js → chunk-YZCKSNRN.js} +24 -17
  51. package/dist/chunk-YZCKSNRN.js.map +1 -0
  52. package/dist/{chunk-3NAFXVQM.js → chunk-ZIRH6QWW.js} +7 -5
  53. package/dist/chunk-ZIRH6QWW.js.map +1 -0
  54. package/dist/cli.d.ts +11 -0
  55. package/dist/cli.js +334 -140
  56. package/dist/cli.js.map +1 -1
  57. package/dist/config-X4UP7H6R.js +13 -0
  58. package/dist/config-editor-7BENRVG5.js +11 -0
  59. package/dist/{config-registry-ZXAIJNYB.js → config-registry-M3FFWEVM.js} +3 -2
  60. package/dist/context-FVGCU5TI.js +9 -0
  61. package/dist/core-plugins-JSY2I44L.js +25 -0
  62. package/dist/{daemon-XFEMMJSZ.js → daemon-UOSRDEXW.js} +8 -3
  63. package/dist/doctor-6DLACBR4.js +10 -0
  64. package/dist/{file-service-HHB3JQIO.js → file-service-FQQYME7M.js} +2 -2
  65. package/dist/index.d.ts +265 -32
  66. package/dist/index.js +44 -33
  67. package/dist/index.js.map +1 -1
  68. package/dist/{install-cloudflared-JRJ4BSOM.js → install-cloudflared-LNS5L5FR.js} +5 -4
  69. package/dist/install-cloudflared-LNS5L5FR.js.map +1 -0
  70. package/dist/{install-context-EHYV5WRY.js → install-context-KZO5FR4D.js} +4 -3
  71. package/dist/install-context-KZO5FR4D.js.map +1 -0
  72. package/dist/{install-jq-ISTGT263.js → install-jq-SN4IA5K4.js} +3 -3
  73. package/dist/instance-context-FLCE7VZ4.js +13 -0
  74. package/dist/instance-registry-SW5FWKHO.js +7 -0
  75. package/dist/{main-L2M4NTJY.js → main-D7M2AKRM.js} +91 -48
  76. package/dist/main-D7M2AKRM.js.map +1 -0
  77. package/dist/{plugin-create-EHL76ZZG.js → plugin-create-HFKS23JY.js} +4 -2
  78. package/dist/{plugin-create-EHL76ZZG.js.map → plugin-create-HFKS23JY.js.map} +1 -1
  79. package/dist/{post-upgrade-Y26S2ZQ7.js → post-upgrade-F4YPMTUT.js} +6 -6
  80. package/dist/{security-2BA265LN.js → security-O4XGN2CM.js} +2 -2
  81. package/dist/{setup-E6BNEYCS.js → setup-44WLBIOT.js} +209 -22
  82. package/dist/setup-44WLBIOT.js.map +1 -0
  83. package/dist/{speech-SG62JYIF.js → speech-GHTSWDAN.js} +2 -2
  84. package/dist/telegram-D7ASLVEB.js +7 -0
  85. package/dist/telegram-D7ASLVEB.js.map +1 -0
  86. package/dist/tunnel-ALJDPFDQ.js +10 -0
  87. package/dist/tunnel-ALJDPFDQ.js.map +1 -0
  88. package/dist/{tunnel-service-ZMO4THKE.js → tunnel-service-TBAHDXMF.js} +41 -547
  89. package/dist/tunnel-service-TBAHDXMF.js.map +1 -0
  90. package/package.json +1 -1
  91. package/dist/adapter-4U6MC5ZS.js +0 -13
  92. package/dist/api-server-5VNYFWJE.js +0 -7
  93. package/dist/chunk-3NAFXVQM.js.map +0 -1
  94. package/dist/chunk-4WXALZA3.js +0 -45
  95. package/dist/chunk-4WXALZA3.js.map +0 -1
  96. package/dist/chunk-5HKQCYOI.js.map +0 -1
  97. package/dist/chunk-5OCGO27U.js.map +0 -1
  98. package/dist/chunk-5ZNBNIK3.js.map +0 -1
  99. package/dist/chunk-7RKPIM3E.js.map +0 -1
  100. package/dist/chunk-APS6UEFU.js.map +0 -1
  101. package/dist/chunk-BTJHGSLM.js.map +0 -1
  102. package/dist/chunk-CFUJGWOP.js.map +0 -1
  103. package/dist/chunk-FCTC7KDT.js.map +0 -1
  104. package/dist/chunk-GEOXPGCO.js.map +0 -1
  105. package/dist/chunk-KDU3ZEWT.js.map +0 -1
  106. package/dist/chunk-MITTQMGZ.js.map +0 -1
  107. package/dist/chunk-MPGEHTGE.js.map +0 -1
  108. package/dist/chunk-PA6MNBG4.js.map +0 -1
  109. package/dist/chunk-QWVHCTCA.js.map +0 -1
  110. package/dist/chunk-TMVTSWVH.js.map +0 -1
  111. package/dist/chunk-UWH7KIAA.js.map +0 -1
  112. package/dist/chunk-V2YZWYXT.js.map +0 -1
  113. package/dist/chunk-W4LK6WJP.js.map +0 -1
  114. package/dist/config-KN6NKKPF.js +0 -20
  115. package/dist/config-editor-76RVZS4B.js +0 -10
  116. package/dist/context-NXXW62NJ.js +0 -9
  117. package/dist/core-plugins-OCHKGCIZ.js +0 -22
  118. package/dist/doctor-AV6AUO22.js +0 -9
  119. package/dist/install-cloudflared-JRJ4BSOM.js.map +0 -1
  120. package/dist/install-context-EHYV5WRY.js.map +0 -1
  121. package/dist/main-L2M4NTJY.js.map +0 -1
  122. package/dist/setup-E6BNEYCS.js.map +0 -1
  123. package/dist/telegram-EAVRDNFU.js +0 -7
  124. package/dist/tunnel-HWJ27WDH.js +0 -7
  125. package/dist/tunnel-service-ZMO4THKE.js.map +0 -1
  126. /package/dist/{adapter-4U6MC5ZS.js.map → adapter-ELG3VRZ3.js.map} +0 -0
  127. /package/dist/{agent-catalog-SZQQERV7.js.map → agent-catalog-UYD26QDK.js.map} +0 -0
  128. /package/dist/{api-client-XTLRRFPX.js.map → api-client-PEMHYL5U.js.map} +0 -0
  129. /package/dist/{api-server-5VNYFWJE.js.map → api-server-DATG2KBR.js.map} +0 -0
  130. /package/dist/{api-server-JLBDKCU4.js.map → api-server-L5Z7XACW.js.map} +0 -0
  131. /package/dist/{chunk-YIGBJFJL.js.map → chunk-7GXEMMEV.js.map} +0 -0
  132. /package/dist/{config-KN6NKKPF.js.map → config-X4UP7H6R.js.map} +0 -0
  133. /package/dist/{config-editor-76RVZS4B.js.map → config-editor-7BENRVG5.js.map} +0 -0
  134. /package/dist/{config-registry-ZXAIJNYB.js.map → config-registry-M3FFWEVM.js.map} +0 -0
  135. /package/dist/{context-NXXW62NJ.js.map → context-FVGCU5TI.js.map} +0 -0
  136. /package/dist/{core-plugins-OCHKGCIZ.js.map → core-plugins-JSY2I44L.js.map} +0 -0
  137. /package/dist/{daemon-XFEMMJSZ.js.map → daemon-UOSRDEXW.js.map} +0 -0
  138. /package/dist/{doctor-AV6AUO22.js.map → doctor-6DLACBR4.js.map} +0 -0
  139. /package/dist/{file-service-HHB3JQIO.js.map → file-service-FQQYME7M.js.map} +0 -0
  140. /package/dist/{install-jq-ISTGT263.js.map → install-jq-SN4IA5K4.js.map} +0 -0
  141. /package/dist/{security-2BA265LN.js.map → instance-context-FLCE7VZ4.js.map} +0 -0
  142. /package/dist/{speech-SG62JYIF.js.map → instance-registry-SW5FWKHO.js.map} +0 -0
  143. /package/dist/{post-upgrade-Y26S2ZQ7.js.map → post-upgrade-F4YPMTUT.js.map} +0 -0
  144. /package/dist/{telegram-EAVRDNFU.js.map → security-O4XGN2CM.js.map} +0 -0
  145. /package/dist/{tunnel-HWJ27WDH.js.map → speech-GHTSWDAN.js.map} +0 -0
package/dist/index.js CHANGED
@@ -15,36 +15,41 @@ import {
15
15
  TypedEmitter,
16
16
  nodeToWebReadable,
17
17
  nodeToWebWritable
18
- } from "./chunk-7RKPIM3E.js";
18
+ } from "./chunk-LRV56K2M.js";
19
+ import {
20
+ AgentCatalog
21
+ } from "./chunk-MDJHCCFS.js";
22
+ import {
23
+ AgentStore
24
+ } from "./chunk-566W6INH.js";
19
25
  import {
20
26
  getPidPath,
21
27
  getStatus,
22
28
  startDaemon,
23
29
  stopDaemon
24
- } from "./chunk-QWVHCTCA.js";
30
+ } from "./chunk-7U6IZIJP.js";
25
31
  import {
26
32
  runConfigEditor
27
- } from "./chunk-MPGEHTGE.js";
33
+ } from "./chunk-TGP34LQN.js";
28
34
  import {
29
35
  installAutoStart,
30
36
  isAutoStartInstalled,
31
37
  isAutoStartSupported,
32
38
  uninstallAutoStart
33
39
  } from "./chunk-2R5XM3ES.js";
34
- import {
35
- AgentCatalog
36
- } from "./chunk-V2YZWYXT.js";
37
- import {
38
- AgentStore
39
- } from "./chunk-566W6INH.js";
40
40
  import {
41
41
  BaseRenderer,
42
+ DisplaySpecBuilder,
42
43
  KIND_ICONS,
43
44
  MessagingAdapter,
45
+ OutputModeResolver,
44
46
  PRODUCT_GUIDE,
45
47
  STATUS_ICONS,
46
48
  SendQueue,
47
49
  TelegramAdapter,
50
+ ThoughtBuffer,
51
+ ToolCardState,
52
+ ToolStateMap,
48
53
  extractContentText,
49
54
  formatTokens,
50
55
  formatToolSummary,
@@ -54,24 +59,29 @@ import {
54
59
  splitMessage,
55
60
  stripCodeFences,
56
61
  truncateContent
57
- } from "./chunk-5ZNBNIK3.js";
62
+ } from "./chunk-EWVXSTQK.js";
58
63
  import "./chunk-AFKX424Q.js";
59
64
  import {
60
65
  DoctorEngine
61
- } from "./chunk-GEOXPGCO.js";
66
+ } from "./chunk-K6UY5M75.js";
62
67
  import {
63
- NotificationManager
64
- } from "./chunk-7ZCQF6QM.js";
68
+ CONFIG_REGISTRY,
69
+ getConfigValue,
70
+ getFieldDef,
71
+ getSafeFields,
72
+ isHotReloadable,
73
+ resolveOptions
74
+ } from "./chunk-NOEAJNTK.js";
75
+ import {
76
+ ConfigManager,
77
+ expandHome
78
+ } from "./chunk-YZCKSNRN.js";
65
79
  import {
66
80
  ApiServer,
67
81
  SSEManager,
68
82
  StaticServer
69
- } from "./chunk-BTJHGSLM.js";
83
+ } from "./chunk-R2YLDQLI.js";
70
84
  import "./chunk-FNRSWA2K.js";
71
- import "./chunk-ZSLHHQPQ.js";
72
- import {
73
- SecurityGuard
74
- } from "./chunk-LGFWH3AE.js";
75
85
  import "./chunk-OYSAN7UX.js";
76
86
  import {
77
87
  FileService
@@ -79,25 +89,15 @@ import {
79
89
  import {
80
90
  ContextManager,
81
91
  EntireProvider
82
- } from "./chunk-MITTQMGZ.js";
83
- import "./chunk-APS6UEFU.js";
92
+ } from "./chunk-BYCJQPMN.js";
93
+ import "./chunk-NJX75BLK.js";
84
94
  import {
85
95
  GroqSTT,
86
96
  SpeechService
87
97
  } from "./chunk-2KT6TROD.js";
88
98
  import {
89
- CONFIG_REGISTRY,
90
- getConfigValue,
91
- getFieldDef,
92
- getSafeFields,
93
- isHotReloadable,
94
- resolveOptions
95
- } from "./chunk-5HKQCYOI.js";
96
- import {
97
- ConfigManager,
98
- PLUGINS_DIR,
99
- expandHome
100
- } from "./chunk-W4LK6WJP.js";
99
+ NotificationManager
100
+ } from "./chunk-7ZCQF6QM.js";
101
101
  import {
102
102
  cleanupOldSessionLogs,
103
103
  createChildLogger,
@@ -107,6 +107,11 @@ import {
107
107
  setLogLevel,
108
108
  shutdownLogger
109
109
  } from "./chunk-R6KZYF7D.js";
110
+ import "./chunk-ZSLHHQPQ.js";
111
+ import "./chunk-ON7HB5O7.js";
112
+ import {
113
+ SecurityGuard
114
+ } from "./chunk-LGFWH3AE.js";
110
115
 
111
116
  // src/core/channel.ts
112
117
  var ChannelAdapter = class {
@@ -128,6 +133,8 @@ var ChannelAdapter = class {
128
133
  }
129
134
  async cleanupSkillCommands(_sessionId) {
130
135
  }
136
+ async cleanupSessionState(_sessionId) {
137
+ }
131
138
  async archiveSessionTopic(_sessionId) {
132
139
  return "";
133
140
  }
@@ -482,6 +489,7 @@ export {
482
489
  CommandRegistry,
483
490
  ConfigManager,
484
491
  ContextManager,
492
+ DisplaySpecBuilder,
485
493
  DoctorEngine,
486
494
  DraftManager,
487
495
  EntireProvider,
@@ -493,7 +501,7 @@ export {
493
501
  MessagingAdapter,
494
502
  NotificationManager,
495
503
  OpenACPCore,
496
- PLUGINS_DIR,
504
+ OutputModeResolver,
497
505
  PRODUCT_GUIDE,
498
506
  PermissionGate,
499
507
  PromptQueue,
@@ -510,7 +518,10 @@ export {
510
518
  StderrCapture,
511
519
  StreamAdapter,
512
520
  TelegramAdapter,
521
+ ThoughtBuffer,
513
522
  ToolCallTracker,
523
+ ToolCardState,
524
+ ToolStateMap,
514
525
  TopicManager,
515
526
  TypedEmitter,
516
527
  cleanupOldSessionLogs,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/channel.ts","../../src/plugins/telegram/topic-manager.ts","../../src/core/adapter-primitives/stream-adapter.ts","../../src/core/adapter-primitives/primitives/draft-manager.ts","../../src/core/adapter-primitives/primitives/tool-call-tracker.ts","../../src/core/adapter-primitives/primitives/activity-tracker.ts"],"sourcesContent":["import type { OutgoingMessage, PermissionRequest, NotificationMessage, AgentCommand } from './types.js'\n\nexport interface ChannelConfig {\n enabled: boolean\n [key: string]: unknown\n}\n\nexport interface AdapterCapabilities {\n streaming: boolean\n richFormatting: boolean\n threads: boolean\n reactions: boolean\n fileUpload: boolean\n voice: boolean\n}\n\nexport interface IChannelAdapter {\n readonly name: string\n readonly capabilities: AdapterCapabilities\n\n start(): Promise<void>\n stop(): Promise<void>\n\n // Outgoing: core → channel\n sendMessage(sessionId: string, content: OutgoingMessage): Promise<void>\n sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void>\n sendNotification(notification: NotificationMessage): Promise<void>\n\n // Session lifecycle on channel side\n createSessionThread(sessionId: string, name: string): Promise<string> // returns threadId\n renameSessionThread(sessionId: string, newName: string): Promise<void>\n deleteSessionThread?(sessionId: string): Promise<void>\n archiveSessionTopic?(sessionId: string): Promise<string>\n\n // TTS strip — optional, called after TTS audio is synthesized to remove [TTS] block from text\n stripTTSBlock?(sessionId: string): Promise<void>\n\n // Skill commands — optional\n sendSkillCommands?(sessionId: string, commands: AgentCommand[]): Promise<void>\n cleanupSkillCommands?(sessionId: string): Promise<void>\n}\n\n/**\n * Base class providing default no-op implementations for optional methods.\n * Adapters can extend this or implement IChannelAdapter directly.\n * @deprecated Use MessagingAdapter or StreamAdapter instead. Kept for backward compat during migration.\n */\nexport abstract class ChannelAdapter<TCore = unknown> implements IChannelAdapter {\n abstract readonly name: string\n readonly capabilities: AdapterCapabilities = {\n streaming: false, richFormatting: false, threads: false,\n reactions: false, fileUpload: false, voice: false,\n }\n\n constructor(public readonly core: TCore, protected config: ChannelConfig) {}\n\n abstract start(): Promise<void>\n abstract stop(): Promise<void>\n\n abstract sendMessage(sessionId: string, content: OutgoingMessage): Promise<void>\n abstract sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void>\n abstract sendNotification(notification: NotificationMessage): Promise<void>\n\n abstract createSessionThread(sessionId: string, name: string): Promise<string>\n abstract renameSessionThread(sessionId: string, newName: string): Promise<void>\n async deleteSessionThread(_sessionId: string): Promise<void> {}\n\n async sendSkillCommands(_sessionId: string, _commands: AgentCommand[]): Promise<void> {}\n async cleanupSkillCommands(_sessionId: string): Promise<void> {}\n async archiveSessionTopic(_sessionId: string): Promise<string> { return \"\"; }\n}\n","import type { SessionManager } from '../../core/sessions/session-manager.js'\nimport type { IChannelAdapter } from '../../core/channel.js'\nimport type { SessionRecord } from '../../core/types.js'\nimport { createChildLogger } from '../../core/utils/log.js'\n\nconst log = createChildLogger({ module: 'topic-manager' })\n\nexport interface TopicInfo {\n sessionId: string\n topicId: number | null\n name: string | null\n status: string\n agentName: string\n lastActiveAt: string\n}\n\nexport interface DeleteTopicResult {\n ok: boolean\n needsConfirmation?: boolean\n topicId?: number | null\n session?: { id: string; name: string | null; status: string }\n error?: string\n}\n\nexport interface CleanupResult {\n deleted: string[]\n failed: { sessionId: string; error: string }[]\n}\n\ninterface SystemTopicIds {\n notificationTopicId: number | null\n assistantTopicId: number | null\n}\n\nexport class TopicManager {\n constructor(\n private sessionManager: SessionManager,\n private adapter: IChannelAdapter | null,\n private systemTopicIds: SystemTopicIds,\n ) {}\n\n listTopics(filter?: { statuses?: string[] }): TopicInfo[] {\n const records = this.sessionManager.listRecords(filter)\n return records\n .filter(r => !this.isSystemTopic(r))\n .filter(r => !filter?.statuses?.length || filter.statuses.includes(r.status))\n .map(r => ({\n sessionId: r.sessionId,\n topicId: (r.platform as Record<string, unknown>)?.topicId as number ?? null,\n name: r.name ?? null,\n status: r.status,\n agentName: r.agentName,\n lastActiveAt: r.lastActiveAt,\n }))\n }\n\n async deleteTopic(sessionId: string, options?: { confirmed?: boolean }): Promise<DeleteTopicResult> {\n const records = this.sessionManager.listRecords()\n const record = records.find(r => r.sessionId === sessionId)\n if (!record) return { ok: false, error: 'Session not found' }\n\n if (this.isSystemTopic(record)) return { ok: false, error: 'Cannot delete system topic' }\n\n const isActive = record.status === 'active' || record.status === 'initializing'\n if (isActive && !options?.confirmed) {\n return {\n ok: false,\n needsConfirmation: true,\n session: { id: record.sessionId, name: record.name ?? null, status: record.status },\n }\n }\n\n if (isActive) {\n await this.sessionManager.cancelSession(sessionId)\n }\n\n const topicId = (record.platform as Record<string, unknown>)?.topicId as number ?? null\n if (this.adapter && topicId) {\n try {\n await this.adapter.deleteSessionThread?.(sessionId)\n } catch (err) {\n log.warn({ err, sessionId, topicId }, 'Failed to delete platform thread, removing record anyway')\n }\n }\n\n await this.sessionManager.removeRecord(sessionId)\n return { ok: true, topicId }\n }\n\n async cleanup(statuses?: string[]): Promise<CleanupResult> {\n const targetStatuses = statuses?.length ? statuses : ['finished', 'error', 'cancelled']\n const records = this.sessionManager.listRecords({ statuses: targetStatuses })\n const targets = records\n .filter(r => !this.isSystemTopic(r))\n .filter(r => targetStatuses.includes(r.status))\n\n const deleted: string[] = []\n const failed: { sessionId: string; error: string }[] = []\n\n for (const record of targets) {\n try {\n // Cancel active/initializing sessions to prevent orphaned agent processes\n const isActive = record.status === 'active' || record.status === 'initializing'\n if (isActive) {\n await this.sessionManager.cancelSession(record.sessionId)\n }\n\n const topicId = (record.platform as Record<string, unknown>)?.topicId as number | undefined\n if (this.adapter && topicId) {\n try {\n await this.adapter.deleteSessionThread?.(record.sessionId)\n } catch (err) {\n log.warn({ err, sessionId: record.sessionId }, 'Failed to delete platform thread during cleanup')\n }\n }\n await this.sessionManager.removeRecord(record.sessionId)\n deleted.push(record.sessionId)\n } catch (err) {\n failed.push({ sessionId: record.sessionId, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n return { deleted, failed }\n }\n\n private isSystemTopic(record: SessionRecord): boolean {\n const topicId = (record.platform as Record<string, unknown>)?.topicId as number | undefined\n if (!topicId) return false\n return topicId === this.systemTopicIds.notificationTopicId\n || topicId === this.systemTopicIds.assistantTopicId\n }\n}\n","import type {\n IChannelAdapter,\n AdapterCapabilities,\n} from '../channel.js'\nimport type {\n OutgoingMessage,\n PermissionRequest,\n NotificationMessage,\n} from '../types.js'\n\nexport interface StreamEvent {\n type: string\n sessionId?: string\n payload: unknown\n timestamp: number\n}\n\nexport abstract class StreamAdapter implements IChannelAdapter {\n abstract readonly name: string\n\n capabilities: AdapterCapabilities\n\n constructor(config?: Partial<AdapterCapabilities>) {\n this.capabilities = {\n streaming: true,\n richFormatting: false,\n threads: false,\n reactions: false,\n fileUpload: false,\n voice: false,\n ...config,\n }\n }\n\n async sendMessage(sessionId: string, content: OutgoingMessage): Promise<void> {\n await this.emit(sessionId, {\n type: content.type,\n sessionId,\n payload: content,\n timestamp: Date.now(),\n })\n }\n\n async sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void> {\n await this.emit(sessionId, {\n type: 'permission_request',\n sessionId,\n payload: request,\n timestamp: Date.now(),\n })\n }\n\n async sendNotification(notification: NotificationMessage): Promise<void> {\n await this.broadcast({\n type: 'notification',\n payload: notification,\n timestamp: Date.now(),\n })\n }\n\n async createSessionThread(_sessionId: string, _name: string): Promise<string> {\n return ''\n }\n\n async renameSessionThread(sessionId: string, name: string): Promise<void> {\n await this.emit(sessionId, {\n type: 'session_rename',\n sessionId,\n payload: { name },\n timestamp: Date.now(),\n })\n }\n\n protected abstract emit(sessionId: string, event: StreamEvent): Promise<void>\n protected abstract broadcast(event: StreamEvent): Promise<void>\n abstract start(): Promise<void>\n abstract stop(): Promise<void>\n}\n","export interface DraftConfig {\n flushInterval: number\n maxLength: number\n onFlush: (sessionId: string, text: string, isEdit: boolean) => Promise<string | undefined>\n onError?: (sessionId: string, error: Error) => void\n}\n\nexport class Draft {\n private buffer = ''\n private _messageId?: string\n private firstFlushPending = false\n private flushTimer?: ReturnType<typeof setTimeout>\n private flushPromise: Promise<void> = Promise.resolve()\n\n constructor(\n private sessionId: string,\n private config: DraftConfig,\n ) {}\n\n get isEmpty(): boolean { return !this.buffer }\n get messageId(): string | undefined { return this._messageId }\n\n append(text: string): void {\n if (!text) return\n this.buffer += text\n this.scheduleFlush()\n }\n\n async finalize(): Promise<string | undefined> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = undefined\n }\n await this.flushPromise\n if (this.buffer) {\n await this.flush()\n }\n return this._messageId\n }\n\n destroy(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = undefined\n }\n this.buffer = ''\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return\n this.flushTimer = setTimeout(() => {\n this.flushTimer = undefined\n this.flushPromise = this.flushPromise\n .then(() => this.flush())\n .catch(() => {})\n }, this.config.flushInterval)\n }\n\n private async flush(): Promise<void> {\n if (!this.buffer || this.firstFlushPending) return\n\n const snapshot = this.buffer\n const isEdit = !!this._messageId\n\n if (!this._messageId) {\n this.firstFlushPending = true\n }\n\n try {\n const result = await this.config.onFlush(this.sessionId, snapshot, isEdit)\n if (!isEdit && result) {\n this._messageId = result\n }\n } catch (err) {\n this.config.onError?.(this.sessionId, err instanceof Error ? err : new Error(String(err)))\n } finally {\n this.firstFlushPending = false\n }\n }\n}\n\nexport class DraftManager {\n private drafts = new Map<string, Draft>()\n\n constructor(private config: DraftConfig) {}\n\n getOrCreate(sessionId: string): Draft {\n let draft = this.drafts.get(sessionId)\n if (!draft) {\n draft = new Draft(sessionId, this.config)\n this.drafts.set(sessionId, draft)\n }\n return draft\n }\n\n async finalize(sessionId: string): Promise<void> {\n const draft = this.drafts.get(sessionId)\n if (!draft) return\n await draft.finalize()\n this.drafts.delete(sessionId)\n }\n\n async finalizeAll(): Promise<void> {\n await Promise.all([...this.drafts.values()].map(d => d.finalize()))\n }\n\n destroy(sessionId: string): void {\n const draft = this.drafts.get(sessionId)\n if (draft) {\n draft.destroy()\n this.drafts.delete(sessionId)\n }\n }\n\n destroyAll(): void {\n for (const draft of this.drafts.values()) {\n draft.destroy()\n }\n this.drafts.clear()\n }\n}\n","import type { ToolCallMeta } from '../format-types.js'\n\nexport interface TrackedToolCall extends ToolCallMeta {\n messageId: string\n}\n\nexport class ToolCallTracker {\n private sessions = new Map<string, Map<string, TrackedToolCall>>()\n\n track(sessionId: string, meta: ToolCallMeta, messageId: string): void {\n if (!this.sessions.has(sessionId)) {\n this.sessions.set(sessionId, new Map())\n }\n this.sessions.get(sessionId)!.set(meta.id, { ...meta, messageId })\n }\n\n update(\n sessionId: string,\n toolId: string,\n status: string,\n patch?: Partial<Pick<ToolCallMeta, 'viewerLinks' | 'viewerFilePath' | 'name' | 'kind'>>,\n ): TrackedToolCall | null {\n const tool = this.sessions.get(sessionId)?.get(toolId)\n if (!tool) return null\n\n tool.status = status\n if (patch?.viewerLinks) tool.viewerLinks = patch.viewerLinks\n if (patch?.viewerFilePath) tool.viewerFilePath = patch.viewerFilePath\n if (patch?.name) tool.name = patch.name\n if (patch?.kind) tool.kind = patch.kind\n\n return tool\n }\n\n getActive(sessionId: string): TrackedToolCall[] {\n const session = this.sessions.get(sessionId)\n return session ? [...session.values()] : []\n }\n\n clear(sessionId: string): void {\n this.sessions.delete(sessionId)\n }\n\n clearAll(): void {\n this.sessions.clear()\n }\n}\n","export interface ActivityConfig {\n thinkingRefreshInterval: number\n maxThinkingDuration: number\n}\n\nexport interface ActivityCallbacks {\n sendThinkingIndicator(): Promise<void>\n updateThinkingIndicator(): Promise<void>\n removeThinkingIndicator(): Promise<void>\n}\n\ninterface SessionState {\n callbacks: ActivityCallbacks\n refreshTimer?: ReturnType<typeof setInterval>\n startTime: number\n dismissed: boolean\n}\n\nexport class ActivityTracker {\n private sessions = new Map<string, SessionState>()\n\n constructor(private config: ActivityConfig) {}\n\n onThinkingStart(sessionId: string, callbacks: ActivityCallbacks): void {\n this.cleanup(sessionId)\n\n const state: SessionState = {\n callbacks,\n startTime: Date.now(),\n dismissed: false,\n }\n this.sessions.set(sessionId, state)\n\n setTimeout(() => {\n if (state.dismissed) return\n callbacks.sendThinkingIndicator().catch(() => {})\n this.startRefresh(sessionId, state)\n }, 0)\n }\n\n onTextStart(sessionId: string): void {\n const state = this.sessions.get(sessionId)\n if (!state || state.dismissed) return\n state.dismissed = true\n this.stopRefresh(state)\n state.callbacks.removeThinkingIndicator().catch(() => {})\n }\n\n onSessionEnd(sessionId: string): void {\n this.cleanup(sessionId)\n }\n\n destroy(): void {\n for (const [id] of this.sessions) {\n this.cleanup(id)\n }\n }\n\n private cleanup(sessionId: string): void {\n const state = this.sessions.get(sessionId)\n if (!state) return\n state.dismissed = true\n this.stopRefresh(state)\n state.callbacks.removeThinkingIndicator().catch(() => {})\n this.sessions.delete(sessionId)\n }\n\n private startRefresh(sessionId: string, state: SessionState): void {\n state.refreshTimer = setInterval(() => {\n if (state.dismissed) {\n this.stopRefresh(state)\n return\n }\n if (Date.now() - state.startTime >= this.config.maxThinkingDuration) {\n state.dismissed = true\n this.stopRefresh(state)\n state.callbacks.removeThinkingIndicator().catch(() => {})\n return\n }\n state.callbacks.updateThinkingIndicator().catch(() => {})\n }, this.config.thinkingRefreshInterval)\n }\n\n private stopRefresh(state: SessionState): void {\n if (state.refreshTimer) {\n clearInterval(state.refreshTimer)\n state.refreshTimer = undefined\n }\n }\n}\n"],"mappings":"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","names":["log"]}
1
+ {"version":3,"sources":["../../src/core/channel.ts","../../src/plugins/telegram/topic-manager.ts","../../src/core/adapter-primitives/stream-adapter.ts","../../src/core/adapter-primitives/primitives/draft-manager.ts","../../src/core/adapter-primitives/primitives/tool-call-tracker.ts","../../src/core/adapter-primitives/primitives/activity-tracker.ts"],"sourcesContent":["import type { OutgoingMessage, PermissionRequest, NotificationMessage, AgentCommand } from './types.js'\n\nexport interface ChannelConfig {\n enabled: boolean\n [key: string]: unknown\n}\n\nexport interface AdapterCapabilities {\n streaming: boolean\n richFormatting: boolean\n threads: boolean\n reactions: boolean\n fileUpload: boolean\n voice: boolean\n}\n\nexport interface IChannelAdapter {\n readonly name: string\n readonly capabilities: AdapterCapabilities\n\n start(): Promise<void>\n stop(): Promise<void>\n\n // Outgoing: core → channel\n sendMessage(sessionId: string, content: OutgoingMessage): Promise<void>\n sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void>\n sendNotification(notification: NotificationMessage): Promise<void>\n\n // Session lifecycle on channel side\n createSessionThread(sessionId: string, name: string): Promise<string> // returns threadId\n renameSessionThread(sessionId: string, newName: string): Promise<void>\n deleteSessionThread?(sessionId: string): Promise<void>\n archiveSessionTopic?(sessionId: string): Promise<string>\n\n // TTS strip — optional, called after TTS audio is synthesized to remove [TTS] block from text\n stripTTSBlock?(sessionId: string): Promise<void>\n\n // Skill commands — optional\n sendSkillCommands?(sessionId: string, commands: AgentCommand[]): Promise<void>\n cleanupSkillCommands?(sessionId: string): Promise<void>\n\n // Agent switch cleanup — optional, called when switching agents to clear adapter-side per-session state\n cleanupSessionState?(sessionId: string): Promise<void>\n}\n\n/**\n * Base class providing default no-op implementations for optional methods.\n * Adapters can extend this or implement IChannelAdapter directly.\n * @deprecated Use MessagingAdapter or StreamAdapter instead. Kept for backward compat during migration.\n */\nexport abstract class ChannelAdapter<TCore = unknown> implements IChannelAdapter {\n abstract readonly name: string\n readonly capabilities: AdapterCapabilities = {\n streaming: false, richFormatting: false, threads: false,\n reactions: false, fileUpload: false, voice: false,\n }\n\n constructor(public readonly core: TCore, protected config: ChannelConfig) {}\n\n abstract start(): Promise<void>\n abstract stop(): Promise<void>\n\n abstract sendMessage(sessionId: string, content: OutgoingMessage): Promise<void>\n abstract sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void>\n abstract sendNotification(notification: NotificationMessage): Promise<void>\n\n abstract createSessionThread(sessionId: string, name: string): Promise<string>\n abstract renameSessionThread(sessionId: string, newName: string): Promise<void>\n async deleteSessionThread(_sessionId: string): Promise<void> {}\n\n async sendSkillCommands(_sessionId: string, _commands: AgentCommand[]): Promise<void> {}\n async cleanupSkillCommands(_sessionId: string): Promise<void> {}\n async cleanupSessionState(_sessionId: string): Promise<void> {}\n async archiveSessionTopic(_sessionId: string): Promise<string> { return \"\"; }\n}\n","import type { SessionManager } from '../../core/sessions/session-manager.js'\nimport type { IChannelAdapter } from '../../core/channel.js'\nimport type { SessionRecord } from '../../core/types.js'\nimport { createChildLogger } from '../../core/utils/log.js'\n\nconst log = createChildLogger({ module: 'topic-manager' })\n\nexport interface TopicInfo {\n sessionId: string\n topicId: number | null\n name: string | null\n status: string\n agentName: string\n lastActiveAt: string\n}\n\nexport interface DeleteTopicResult {\n ok: boolean\n needsConfirmation?: boolean\n topicId?: number | null\n session?: { id: string; name: string | null; status: string }\n error?: string\n}\n\nexport interface CleanupResult {\n deleted: string[]\n failed: { sessionId: string; error: string }[]\n}\n\ninterface SystemTopicIds {\n notificationTopicId: number | null\n assistantTopicId: number | null\n}\n\nexport class TopicManager {\n constructor(\n private sessionManager: SessionManager,\n private adapter: IChannelAdapter | null,\n private systemTopicIds: SystemTopicIds,\n ) {}\n\n listTopics(filter?: { statuses?: string[] }): TopicInfo[] {\n const records = this.sessionManager.listRecords(filter)\n return records\n .filter(r => !this.isSystemTopic(r))\n .filter(r => !filter?.statuses?.length || filter.statuses.includes(r.status))\n .map(r => ({\n sessionId: r.sessionId,\n topicId: (r.platform as Record<string, unknown>)?.topicId as number ?? null,\n name: r.name ?? null,\n status: r.status,\n agentName: r.agentName,\n lastActiveAt: r.lastActiveAt,\n }))\n }\n\n async deleteTopic(sessionId: string, options?: { confirmed?: boolean }): Promise<DeleteTopicResult> {\n const records = this.sessionManager.listRecords()\n const record = records.find(r => r.sessionId === sessionId)\n if (!record) return { ok: false, error: 'Session not found' }\n\n if (this.isSystemTopic(record)) return { ok: false, error: 'Cannot delete system topic' }\n\n const isActive = record.status === 'active' || record.status === 'initializing'\n if (isActive && !options?.confirmed) {\n return {\n ok: false,\n needsConfirmation: true,\n session: { id: record.sessionId, name: record.name ?? null, status: record.status },\n }\n }\n\n if (isActive) {\n await this.sessionManager.cancelSession(sessionId)\n }\n\n const topicId = (record.platform as Record<string, unknown>)?.topicId as number ?? null\n if (this.adapter && topicId) {\n try {\n await this.adapter.deleteSessionThread?.(sessionId)\n } catch (err) {\n log.warn({ err, sessionId, topicId }, 'Failed to delete platform thread, removing record anyway')\n }\n }\n\n await this.sessionManager.removeRecord(sessionId)\n return { ok: true, topicId }\n }\n\n async cleanup(statuses?: string[]): Promise<CleanupResult> {\n const targetStatuses = statuses?.length ? statuses : ['finished', 'error', 'cancelled']\n const records = this.sessionManager.listRecords({ statuses: targetStatuses })\n const targets = records\n .filter(r => !this.isSystemTopic(r))\n .filter(r => targetStatuses.includes(r.status))\n\n const deleted: string[] = []\n const failed: { sessionId: string; error: string }[] = []\n\n for (const record of targets) {\n try {\n // Cancel active/initializing sessions to prevent orphaned agent processes\n const isActive = record.status === 'active' || record.status === 'initializing'\n if (isActive) {\n await this.sessionManager.cancelSession(record.sessionId)\n }\n\n const topicId = (record.platform as Record<string, unknown>)?.topicId as number | undefined\n if (this.adapter && topicId) {\n try {\n await this.adapter.deleteSessionThread?.(record.sessionId)\n } catch (err) {\n log.warn({ err, sessionId: record.sessionId }, 'Failed to delete platform thread during cleanup')\n }\n }\n await this.sessionManager.removeRecord(record.sessionId)\n deleted.push(record.sessionId)\n } catch (err) {\n failed.push({ sessionId: record.sessionId, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n return { deleted, failed }\n }\n\n private isSystemTopic(record: SessionRecord): boolean {\n const topicId = (record.platform as Record<string, unknown>)?.topicId as number | undefined\n if (!topicId) return false\n return topicId === this.systemTopicIds.notificationTopicId\n || topicId === this.systemTopicIds.assistantTopicId\n }\n}\n","import type {\n IChannelAdapter,\n AdapterCapabilities,\n} from '../channel.js'\nimport type {\n OutgoingMessage,\n PermissionRequest,\n NotificationMessage,\n} from '../types.js'\n\nexport interface StreamEvent {\n type: string\n sessionId?: string\n payload: unknown\n timestamp: number\n}\n\nexport abstract class StreamAdapter implements IChannelAdapter {\n abstract readonly name: string\n\n capabilities: AdapterCapabilities\n\n constructor(config?: Partial<AdapterCapabilities>) {\n this.capabilities = {\n streaming: true,\n richFormatting: false,\n threads: false,\n reactions: false,\n fileUpload: false,\n voice: false,\n ...config,\n }\n }\n\n async sendMessage(sessionId: string, content: OutgoingMessage): Promise<void> {\n await this.emit(sessionId, {\n type: content.type,\n sessionId,\n payload: content,\n timestamp: Date.now(),\n })\n }\n\n async sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void> {\n await this.emit(sessionId, {\n type: 'permission_request',\n sessionId,\n payload: request,\n timestamp: Date.now(),\n })\n }\n\n async sendNotification(notification: NotificationMessage): Promise<void> {\n await this.broadcast({\n type: 'notification',\n payload: notification,\n timestamp: Date.now(),\n })\n }\n\n async createSessionThread(_sessionId: string, _name: string): Promise<string> {\n return ''\n }\n\n async renameSessionThread(sessionId: string, name: string): Promise<void> {\n await this.emit(sessionId, {\n type: 'session_rename',\n sessionId,\n payload: { name },\n timestamp: Date.now(),\n })\n }\n\n protected abstract emit(sessionId: string, event: StreamEvent): Promise<void>\n protected abstract broadcast(event: StreamEvent): Promise<void>\n abstract start(): Promise<void>\n abstract stop(): Promise<void>\n}\n","export interface DraftConfig {\n flushInterval: number\n maxLength: number\n onFlush: (sessionId: string, text: string, isEdit: boolean) => Promise<string | undefined>\n onError?: (sessionId: string, error: Error) => void\n}\n\nexport class Draft {\n private buffer = ''\n private _messageId?: string\n private firstFlushPending = false\n private flushTimer?: ReturnType<typeof setTimeout>\n private flushPromise: Promise<void> = Promise.resolve()\n\n constructor(\n private sessionId: string,\n private config: DraftConfig,\n ) {}\n\n get isEmpty(): boolean { return !this.buffer }\n get messageId(): string | undefined { return this._messageId }\n\n append(text: string): void {\n if (!text) return\n this.buffer += text\n this.scheduleFlush()\n }\n\n async finalize(): Promise<string | undefined> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = undefined\n }\n await this.flushPromise\n if (this.buffer) {\n await this.flush()\n }\n return this._messageId\n }\n\n destroy(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = undefined\n }\n this.buffer = ''\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return\n this.flushTimer = setTimeout(() => {\n this.flushTimer = undefined\n this.flushPromise = this.flushPromise\n .then(() => this.flush())\n .catch(() => {})\n }, this.config.flushInterval)\n }\n\n private async flush(): Promise<void> {\n if (!this.buffer || this.firstFlushPending) return\n\n const snapshot = this.buffer\n const isEdit = !!this._messageId\n\n if (!this._messageId) {\n this.firstFlushPending = true\n }\n\n try {\n const result = await this.config.onFlush(this.sessionId, snapshot, isEdit)\n if (!isEdit && result) {\n this._messageId = result\n }\n } catch (err) {\n this.config.onError?.(this.sessionId, err instanceof Error ? err : new Error(String(err)))\n } finally {\n this.firstFlushPending = false\n }\n }\n}\n\nexport class DraftManager {\n private drafts = new Map<string, Draft>()\n\n constructor(private config: DraftConfig) {}\n\n getOrCreate(sessionId: string): Draft {\n let draft = this.drafts.get(sessionId)\n if (!draft) {\n draft = new Draft(sessionId, this.config)\n this.drafts.set(sessionId, draft)\n }\n return draft\n }\n\n async finalize(sessionId: string): Promise<void> {\n const draft = this.drafts.get(sessionId)\n if (!draft) return\n await draft.finalize()\n this.drafts.delete(sessionId)\n }\n\n async finalizeAll(): Promise<void> {\n await Promise.all([...this.drafts.values()].map(d => d.finalize()))\n }\n\n destroy(sessionId: string): void {\n const draft = this.drafts.get(sessionId)\n if (draft) {\n draft.destroy()\n this.drafts.delete(sessionId)\n }\n }\n\n destroyAll(): void {\n for (const draft of this.drafts.values()) {\n draft.destroy()\n }\n this.drafts.clear()\n }\n}\n","import type { ToolCallMeta } from '../format-types.js'\n\nexport interface TrackedToolCall extends ToolCallMeta {\n messageId: string\n}\n\nexport class ToolCallTracker {\n private sessions = new Map<string, Map<string, TrackedToolCall>>()\n\n track(sessionId: string, meta: ToolCallMeta, messageId: string): void {\n if (!this.sessions.has(sessionId)) {\n this.sessions.set(sessionId, new Map())\n }\n this.sessions.get(sessionId)!.set(meta.id, { ...meta, messageId })\n }\n\n update(\n sessionId: string,\n toolId: string,\n status: string,\n patch?: Partial<Pick<ToolCallMeta, 'viewerLinks' | 'viewerFilePath' | 'name' | 'kind'>>,\n ): TrackedToolCall | null {\n const tool = this.sessions.get(sessionId)?.get(toolId)\n if (!tool) return null\n\n tool.status = status\n if (patch?.viewerLinks) tool.viewerLinks = patch.viewerLinks\n if (patch?.viewerFilePath) tool.viewerFilePath = patch.viewerFilePath\n if (patch?.name) tool.name = patch.name\n if (patch?.kind) tool.kind = patch.kind\n\n return tool\n }\n\n getActive(sessionId: string): TrackedToolCall[] {\n const session = this.sessions.get(sessionId)\n return session ? [...session.values()] : []\n }\n\n clear(sessionId: string): void {\n this.sessions.delete(sessionId)\n }\n\n clearAll(): void {\n this.sessions.clear()\n }\n}\n","export interface ActivityConfig {\n thinkingRefreshInterval: number\n maxThinkingDuration: number\n}\n\nexport interface ActivityCallbacks {\n sendThinkingIndicator(): Promise<void>\n updateThinkingIndicator(): Promise<void>\n removeThinkingIndicator(): Promise<void>\n}\n\ninterface SessionState {\n callbacks: ActivityCallbacks\n refreshTimer?: ReturnType<typeof setInterval>\n startTime: number\n dismissed: boolean\n}\n\nexport class ActivityTracker {\n private sessions = new Map<string, SessionState>()\n\n constructor(private config: ActivityConfig) {}\n\n onThinkingStart(sessionId: string, callbacks: ActivityCallbacks): void {\n this.cleanup(sessionId)\n\n const state: SessionState = {\n callbacks,\n startTime: Date.now(),\n dismissed: false,\n }\n this.sessions.set(sessionId, state)\n\n setTimeout(() => {\n if (state.dismissed) return\n callbacks.sendThinkingIndicator().catch(() => {})\n this.startRefresh(sessionId, state)\n }, 0)\n }\n\n onTextStart(sessionId: string): void {\n const state = this.sessions.get(sessionId)\n if (!state || state.dismissed) return\n state.dismissed = true\n this.stopRefresh(state)\n state.callbacks.removeThinkingIndicator().catch(() => {})\n }\n\n onSessionEnd(sessionId: string): void {\n this.cleanup(sessionId)\n }\n\n destroy(): void {\n for (const [id] of this.sessions) {\n this.cleanup(id)\n }\n }\n\n private cleanup(sessionId: string): void {\n const state = this.sessions.get(sessionId)\n if (!state) return\n state.dismissed = true\n this.stopRefresh(state)\n state.callbacks.removeThinkingIndicator().catch(() => {})\n this.sessions.delete(sessionId)\n }\n\n private startRefresh(sessionId: string, state: SessionState): void {\n state.refreshTimer = setInterval(() => {\n if (state.dismissed) {\n this.stopRefresh(state)\n return\n }\n if (Date.now() - state.startTime >= this.config.maxThinkingDuration) {\n state.dismissed = true\n this.stopRefresh(state)\n state.callbacks.removeThinkingIndicator().catch(() => {})\n return\n }\n state.callbacks.updateThinkingIndicator().catch(() => {})\n }, this.config.thinkingRefreshInterval)\n }\n\n private stopRefresh(state: SessionState): void {\n if (state.refreshTimer) {\n clearInterval(state.refreshTimer)\n state.refreshTimer = undefined\n }\n }\n}\n"],"mappings":"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","names":["log"]}
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  ensureBinary
3
- } from "./chunk-FCTC7KDT.js";
4
- import "./chunk-ZSLHHQPQ.js";
3
+ } from "./chunk-7YIKTRSM.js";
5
4
  import "./chunk-R6KZYF7D.js";
5
+ import "./chunk-ZSLHHQPQ.js";
6
6
 
7
7
  // src/plugins/tunnel/providers/install-cloudflared.ts
8
8
  var CLOUDFLARED_SPEC = {
@@ -11,7 +11,7 @@ var CLOUDFLARED_SPEC = {
11
11
  platforms: {
12
12
  darwin: {
13
13
  x64: "cloudflared-darwin-amd64.tgz",
14
- arm64: "cloudflared-darwin-amd64.tgz"
14
+ arm64: "cloudflared-darwin-arm64.tgz"
15
15
  },
16
16
  win32: {
17
17
  x64: "cloudflared-windows-amd64.exe"
@@ -27,6 +27,7 @@ async function ensureCloudflared() {
27
27
  return ensureBinary(CLOUDFLARED_SPEC);
28
28
  }
29
29
  export {
30
+ CLOUDFLARED_SPEC,
30
31
  ensureCloudflared
31
32
  };
32
- //# sourceMappingURL=install-cloudflared-JRJ4BSOM.js.map
33
+ //# sourceMappingURL=install-cloudflared-LNS5L5FR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugins/tunnel/providers/install-cloudflared.ts"],"sourcesContent":["import { ensureBinary, type BinarySpec } from '../../../core/utils/install-binary.js'\n\nexport const CLOUDFLARED_SPEC: BinarySpec = {\n name: 'cloudflared',\n githubBaseUrl: 'https://github.com/cloudflare/cloudflared/releases/latest/download',\n platforms: {\n darwin: {\n x64: 'cloudflared-darwin-amd64.tgz',\n arm64: 'cloudflared-darwin-arm64.tgz',\n },\n win32: {\n x64: 'cloudflared-windows-amd64.exe',\n },\n linux: {\n x64: 'cloudflared-linux-amd64',\n arm64: 'cloudflared-linux-arm64',\n },\n },\n isArchive: (url) => url.endsWith('.tgz'),\n}\n\nexport async function ensureCloudflared(): Promise<string> {\n return ensureBinary(CLOUDFLARED_SPEC)\n}\n"],"mappings":";;;;;;;AAEO,IAAM,mBAA+B;AAAA,EAC1C,MAAM;AAAA,EACN,eAAe;AAAA,EACf,WAAW;AAAA,IACT,QAAQ;AAAA,MACN,KAAK;AAAA,MACL,OAAO;AAAA,IACT;AAAA,IACA,OAAO;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA,OAAO;AAAA,MACL,KAAK;AAAA,MACL,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,WAAW,CAAC,QAAQ,IAAI,SAAS,MAAM;AACzC;AAEA,eAAsB,oBAAqC;AACzD,SAAO,aAAa,gBAAgB;AACtC;","names":[]}
@@ -60,7 +60,7 @@ function createTerminalIO() {
60
60
 
61
61
  // src/core/plugin/install-context.ts
62
62
  function createInstallContext(opts) {
63
- const { pluginName, settingsManager, basePath, legacyConfig } = opts;
63
+ const { pluginName, settingsManager, basePath, legacyConfig, instanceRoot } = opts;
64
64
  const dataDir = path.join(basePath, pluginName, "data");
65
65
  return {
66
66
  pluginName,
@@ -68,10 +68,11 @@ function createInstallContext(opts) {
68
68
  settings: settingsManager.createAPI(pluginName),
69
69
  legacyConfig,
70
70
  dataDir,
71
- log: log.child({ plugin: pluginName })
71
+ log: log.child({ plugin: pluginName }),
72
+ instanceRoot
72
73
  };
73
74
  }
74
75
  export {
75
76
  createInstallContext
76
77
  };
77
- //# sourceMappingURL=install-context-EHYV5WRY.js.map
78
+ //# sourceMappingURL=install-context-KZO5FR4D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/plugin/install-context.ts","../../src/core/plugin/terminal-io.ts"],"sourcesContent":["import path from 'node:path'\nimport type { InstallContext } from './types.js'\nimport type { SettingsManager } from './settings-manager.js'\nimport { createTerminalIO } from './terminal-io.js'\nimport { log as rootLog } from '../utils/log.js'\n\nexport interface CreateInstallContextOpts {\n pluginName: string\n settingsManager: SettingsManager\n basePath: string\n legacyConfig?: Record<string, unknown>\n instanceRoot?: string\n}\n\nexport function createInstallContext(opts: CreateInstallContextOpts): InstallContext {\n const { pluginName, settingsManager, basePath, legacyConfig, instanceRoot } = opts\n const dataDir = path.join(basePath, pluginName, 'data')\n\n return {\n pluginName,\n terminal: createTerminalIO(),\n settings: settingsManager.createAPI(pluginName),\n legacyConfig,\n dataDir,\n log: rootLog.child({ plugin: pluginName }),\n instanceRoot,\n }\n}\n","import * as clack from '@clack/prompts'\nimport type { TerminalIO } from './types.js'\n\nfunction isCancel(value: unknown): value is symbol {\n return typeof value === 'symbol'\n}\n\nfunction guardCancel<T>(value: T | symbol): T {\n if (isCancel(value)) {\n throw new Error('cancelled')\n }\n return value as T\n}\n\nexport function createTerminalIO(): TerminalIO {\n return {\n async text(opts) {\n const result = await clack.text(opts as Parameters<typeof clack.text>[0])\n return guardCancel(result)\n },\n async select<T>(opts: {\n message: string\n options: { value: T; label: string; hint?: string }[]\n }): Promise<T> {\n const result = await clack.select(opts as Parameters<typeof clack.select>[0])\n return guardCancel(result) as T\n },\n async confirm(opts) {\n const result = await clack.confirm(opts as Parameters<typeof clack.confirm>[0])\n return guardCancel(result)\n },\n async password(opts) {\n const result = await clack.password(opts as Parameters<typeof clack.password>[0])\n return guardCancel(result)\n },\n async multiselect<T>(opts: {\n message: string\n options: { value: T; label: string; hint?: string }[]\n required?: boolean\n }): Promise<T[]> {\n const result = await clack.multiselect(opts as Parameters<typeof clack.multiselect>[0])\n return guardCancel(result) as T[]\n },\n log: {\n info: (msg) => clack.log.info(msg),\n success: (msg) => clack.log.success(msg),\n warning: (msg) => clack.log.warning(msg),\n error: (msg) => clack.log.error(msg),\n step: (msg) => clack.log.step(msg),\n },\n spinner() {\n const s = clack.spinner()\n return {\n start: (msg: string) => s.start(msg),\n stop: (msg?: string) => s.stop(msg),\n fail: (msg?: string) => s.stop(msg ?? 'Failed'),\n }\n },\n note: (msg, title) => clack.note(msg, title),\n cancel: (msg) => clack.cancel(msg),\n }\n}\n"],"mappings":";;;;;AAAA,OAAO,UAAU;;;ACAjB,YAAY,WAAW;AAGvB,SAAS,SAAS,OAAiC;AACjD,SAAO,OAAO,UAAU;AAC1B;AAEA,SAAS,YAAe,OAAsB;AAC5C,MAAI,SAAS,KAAK,GAAG;AACnB,UAAM,IAAI,MAAM,WAAW;AAAA,EAC7B;AACA,SAAO;AACT;AAEO,SAAS,mBAA+B;AAC7C,SAAO;AAAA,IACL,MAAM,KAAK,MAAM;AACf,YAAM,SAAS,MAAY,WAAK,IAAwC;AACxE,aAAO,YAAY,MAAM;AAAA,IAC3B;AAAA,IACA,MAAM,OAAU,MAGD;AACb,YAAM,SAAS,MAAY,aAAO,IAA0C;AAC5E,aAAO,YAAY,MAAM;AAAA,IAC3B;AAAA,IACA,MAAM,QAAQ,MAAM;AAClB,YAAM,SAAS,MAAY,cAAQ,IAA2C;AAC9E,aAAO,YAAY,MAAM;AAAA,IAC3B;AAAA,IACA,MAAM,SAAS,MAAM;AACnB,YAAM,SAAS,MAAY,eAAS,IAA4C;AAChF,aAAO,YAAY,MAAM;AAAA,IAC3B;AAAA,IACA,MAAM,YAAe,MAIJ;AACf,YAAM,SAAS,MAAY,kBAAY,IAA+C;AACtF,aAAO,YAAY,MAAM;AAAA,IAC3B;AAAA,IACA,KAAK;AAAA,MACH,MAAM,CAAC,QAAc,UAAI,KAAK,GAAG;AAAA,MACjC,SAAS,CAAC,QAAc,UAAI,QAAQ,GAAG;AAAA,MACvC,SAAS,CAAC,QAAc,UAAI,QAAQ,GAAG;AAAA,MACvC,OAAO,CAAC,QAAc,UAAI,MAAM,GAAG;AAAA,MACnC,MAAM,CAAC,QAAc,UAAI,KAAK,GAAG;AAAA,IACnC;AAAA,IACA,UAAU;AACR,YAAM,IAAU,cAAQ;AACxB,aAAO;AAAA,QACL,OAAO,CAAC,QAAgB,EAAE,MAAM,GAAG;AAAA,QACnC,MAAM,CAAC,QAAiB,EAAE,KAAK,GAAG;AAAA,QAClC,MAAM,CAAC,QAAiB,EAAE,KAAK,OAAO,QAAQ;AAAA,MAChD;AAAA,IACF;AAAA,IACA,MAAM,CAAC,KAAK,UAAgB,WAAK,KAAK,KAAK;AAAA,IAC3C,QAAQ,CAAC,QAAc,aAAO,GAAG;AAAA,EACnC;AACF;;;AD/CO,SAAS,qBAAqB,MAAgD;AACnF,QAAM,EAAE,YAAY,iBAAiB,UAAU,cAAc,aAAa,IAAI;AAC9E,QAAM,UAAU,KAAK,KAAK,UAAU,YAAY,MAAM;AAEtD,SAAO;AAAA,IACL;AAAA,IACA,UAAU,iBAAiB;AAAA,IAC3B,UAAU,gBAAgB,UAAU,UAAU;AAAA,IAC9C;AAAA,IACA;AAAA,IACA,KAAK,IAAQ,MAAM,EAAE,QAAQ,WAAW,CAAC;AAAA,IACzC;AAAA,EACF;AACF;","names":[]}
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  ensureBinary
3
- } from "./chunk-FCTC7KDT.js";
4
- import "./chunk-ZSLHHQPQ.js";
3
+ } from "./chunk-7YIKTRSM.js";
5
4
  import "./chunk-R6KZYF7D.js";
5
+ import "./chunk-ZSLHHQPQ.js";
6
6
 
7
7
  // src/core/utils/install-jq.ts
8
8
  var JQ_SPEC = {
@@ -28,4 +28,4 @@ async function ensureJq() {
28
28
  export {
29
29
  ensureJq
30
30
  };
31
- //# sourceMappingURL=install-jq-ISTGT263.js.map
31
+ //# sourceMappingURL=install-jq-SN4IA5K4.js.map
@@ -0,0 +1,13 @@
1
+ import {
2
+ createInstanceContext,
3
+ generateSlug,
4
+ getGlobalRoot,
5
+ resolveInstanceRoot
6
+ } from "./chunk-ON7HB5O7.js";
7
+ export {
8
+ createInstanceContext,
9
+ generateSlug,
10
+ getGlobalRoot,
11
+ resolveInstanceRoot
12
+ };
13
+ //# sourceMappingURL=instance-context-FLCE7VZ4.js.map
@@ -0,0 +1,7 @@
1
+ import {
2
+ InstanceRegistry
3
+ } from "./chunk-23SRIVG4.js";
4
+ export {
5
+ InstanceRegistry
6
+ };
7
+ //# sourceMappingURL=instance-registry-SW5FWKHO.js.map
@@ -1,40 +1,38 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- corePlugins
4
- } from "./chunk-YIGBJFJL.js";
5
- import "./chunk-CFUJGWOP.js";
6
2
  import {
7
3
  SettingsManager
8
4
  } from "./chunk-MLF4W5R6.js";
9
- import "./chunk-3EWTPOF7.js";
10
- import "./chunk-PA6MNBG4.js";
11
- import "./chunk-KDU3ZEWT.js";
12
- import "./chunk-5OCGO27U.js";
13
- import "./chunk-3NAFXVQM.js";
14
- import "./chunk-UWH7KIAA.js";
15
- import "./chunk-TMVTSWVH.js";
5
+ import {
6
+ corePlugins
7
+ } from "./chunk-7GXEMMEV.js";
8
+ import "./chunk-KGAQW6F4.js";
9
+ import "./chunk-SSLVNCEA.js";
10
+ import "./chunk-P3HHJANC.js";
11
+ import "./chunk-NHD5XDD2.js";
12
+ import "./chunk-ZIRH6QWW.js";
13
+ import "./chunk-FPKQYCQS.js";
14
+ import "./chunk-VUSCVRJL.js";
16
15
  import "./chunk-5WGVYX3C.js";
16
+ import "./chunk-3EWTPOF7.js";
17
+ import {
18
+ InstanceRegistry
19
+ } from "./chunk-23SRIVG4.js";
17
20
  import {
18
21
  CommandRegistry,
19
22
  OpenACPCore
20
- } from "./chunk-7RKPIM3E.js";
21
- import "./chunk-V2YZWYXT.js";
23
+ } from "./chunk-LRV56K2M.js";
24
+ import "./chunk-MDJHCCFS.js";
22
25
  import "./chunk-566W6INH.js";
23
- import "./chunk-7ZCQF6QM.js";
26
+ import {
27
+ ConfigManager
28
+ } from "./chunk-YZCKSNRN.js";
24
29
  import "./chunk-FNRSWA2K.js";
25
- import "./chunk-ZSLHHQPQ.js";
26
- import "./chunk-LGFWH3AE.js";
27
30
  import "./chunk-OYSAN7UX.js";
28
31
  import "./chunk-IZ5UEZF7.js";
29
- import "./chunk-MITTQMGZ.js";
30
- import "./chunk-APS6UEFU.js";
32
+ import "./chunk-BYCJQPMN.js";
33
+ import "./chunk-NJX75BLK.js";
31
34
  import "./chunk-2KT6TROD.js";
32
- import {
33
- ConfigManager,
34
- OPENACP_DIR,
35
- PLUGINS_DATA_DIR,
36
- REGISTRY_PATH
37
- } from "./chunk-W4LK6WJP.js";
35
+ import "./chunk-7ZCQF6QM.js";
38
36
  import {
39
37
  cleanupOldSessionLogs,
40
38
  initLogger,
@@ -43,9 +41,16 @@ import {
43
41
  shutdownLogger,
44
42
  unmuteLogger
45
43
  } from "./chunk-R6KZYF7D.js";
44
+ import "./chunk-ZSLHHQPQ.js";
45
+ import {
46
+ createInstanceContext,
47
+ getGlobalRoot
48
+ } from "./chunk-ON7HB5O7.js";
46
49
  import {
47
50
  PluginRegistry
48
51
  } from "./chunk-W26AUH5B.js";
52
+ import "./chunk-OSBZXY2W.js";
53
+ import "./chunk-LGFWH3AE.js";
49
54
 
50
55
  // src/main.ts
51
56
  import path from "path";
@@ -262,6 +267,27 @@ function registerMenuCommand(registry, _core) {
262
267
  });
263
268
  }
264
269
 
270
+ // src/core/commands/switch.ts
271
+ function registerSwitchCommands(registry) {
272
+ registry.register({
273
+ name: "switch",
274
+ description: "Switch to a different agent",
275
+ usage: "[agent-name | label on|off]",
276
+ category: "system",
277
+ handler: async (args) => {
278
+ const raw = args.raw.trim();
279
+ if (raw.startsWith("label ")) {
280
+ const value = raw.slice(6).trim().toLowerCase();
281
+ if (value !== "on" && value !== "off") {
282
+ return { type: "error", message: "Usage: /switch label on|off" };
283
+ }
284
+ return { type: "silent" };
285
+ }
286
+ return { type: "silent" };
287
+ }
288
+ });
289
+ }
290
+
265
291
  // src/core/commands/index.ts
266
292
  function registerSystemCommands(registry, core) {
267
293
  registerSessionCommands(registry, core);
@@ -269,6 +295,7 @@ function registerSystemCommands(registry, core) {
269
295
  registerAdminCommands(registry, core);
270
296
  registerHelpCommand(registry, core);
271
297
  registerMenuCommand(registry, core);
298
+ registerSwitchCommands(registry);
272
299
  }
273
300
 
274
301
  // src/main.ts
@@ -276,12 +303,17 @@ import fs from "fs";
276
303
  var RESTART_EXIT_CODE = 75;
277
304
  var shuttingDown = false;
278
305
  async function startServer(opts) {
306
+ const ctx = opts?.instanceContext ?? createInstanceContext({
307
+ id: "main",
308
+ root: getGlobalRoot(),
309
+ isGlobal: true
310
+ });
279
311
  if (process.argv.includes("--daemon-child")) {
280
- const { writePidFile, readPidFile, getPidPath, shouldAutoStart } = await import("./daemon-XFEMMJSZ.js");
281
- if (!shouldAutoStart()) {
312
+ const { writePidFile, readPidFile, shouldAutoStart } = await import("./daemon-UOSRDEXW.js");
313
+ if (!shouldAutoStart(ctx.root)) {
282
314
  process.exit(0);
283
315
  }
284
- const pidPath = getPidPath();
316
+ const pidPath = ctx.paths.pid;
285
317
  const existingPid = readPidFile(pidPath);
286
318
  if (existingPid !== null && existingPid !== process.pid) {
287
319
  try {
@@ -293,13 +325,13 @@ async function startServer(opts) {
293
325
  }
294
326
  writePidFile(pidPath, process.pid);
295
327
  }
296
- const settingsManager = new SettingsManager(PLUGINS_DATA_DIR);
297
- const pluginRegistry = new PluginRegistry(REGISTRY_PATH);
328
+ const settingsManager = new SettingsManager(ctx.paths.pluginsData);
329
+ const pluginRegistry = new PluginRegistry(ctx.paths.pluginRegistry);
298
330
  await pluginRegistry.load();
299
- const configManager = new ConfigManager();
331
+ const configManager = new ConfigManager(ctx.paths.config);
300
332
  const configExists = await configManager.exists();
301
333
  if (!configExists) {
302
- const { runSetup } = await import("./setup-E6BNEYCS.js");
334
+ const { runSetup } = await import("./setup-44WLBIOT.js");
303
335
  const shouldStart = await runSetup(configManager, { settingsManager, pluginRegistry });
304
336
  if (!shouldStart) process.exit(0);
305
337
  }
@@ -312,7 +344,7 @@ async function startServer(opts) {
312
344
  }
313
345
  const isForegroundTTY = !!(process.stdout.isTTY && !process.env.NO_COLOR && config.runMode !== "daemon");
314
346
  if (isForegroundTTY) {
315
- const { printStartBanner } = await import("./setup-E6BNEYCS.js");
347
+ const { printStartBanner } = await import("./setup-44WLBIOT.js");
316
348
  await printStartBanner();
317
349
  }
318
350
  let spinner;
@@ -322,7 +354,7 @@ async function startServer(opts) {
322
354
  spinner = ora({ text: "Starting OpenACP...", spinner: "dots" }).start();
323
355
  }
324
356
  try {
325
- const { runPostUpgradeChecks } = await import("./post-upgrade-Y26S2ZQ7.js");
357
+ const { runPostUpgradeChecks } = await import("./post-upgrade-F4YPMTUT.js");
326
358
  await runPostUpgradeChecks(config);
327
359
  } catch (err) {
328
360
  log.warn({ err }, "Post-upgrade check failed");
@@ -330,7 +362,7 @@ async function startServer(opts) {
330
362
  cleanupOldSessionLogs(config.logging.sessionLogRetentionDays).catch(
331
363
  (err) => log.warn({ err }, "Session log cleanup failed")
332
364
  );
333
- const core = new OpenACPCore(configManager);
365
+ const core = new OpenACPCore(configManager, ctx);
334
366
  const commandRegistry = new CommandRegistry();
335
367
  const serviceRegistry = core.lifecycleManager.serviceRegistry;
336
368
  serviceRegistry.register("command-registry", commandRegistry, "core");
@@ -355,7 +387,7 @@ async function startServer(opts) {
355
387
  const pkg = JSON.parse(await fs.promises.readFile(pkgPath, "utf-8"));
356
388
  modulePath = path.join(resolved, pkg.main || "dist/index.js");
357
389
  } else {
358
- const nodeModulesDir = path.join(OPENACP_DIR, "plugins", "node_modules");
390
+ const nodeModulesDir = path.join(ctx.paths.plugins, "node_modules");
359
391
  let pkgDir = path.join(nodeModulesDir, name);
360
392
  if (!fs.existsSync(path.join(pkgDir, "package.json"))) {
361
393
  let found = false;
@@ -486,13 +518,13 @@ async function startServer(opts) {
486
518
  }
487
519
  const isDaemon = process.argv.includes("--daemon-child");
488
520
  if (isDaemon) {
489
- const { removePidFile, getPidPath } = await import("./daemon-XFEMMJSZ.js");
490
- removePidFile(getPidPath());
521
+ const { removePidFile } = await import("./daemon-UOSRDEXW.js");
522
+ removePidFile(ctx.paths.pid);
491
523
  }
492
524
  if (exitCode === RESTART_EXIT_CODE) {
493
525
  if (isDaemon) {
494
526
  const { spawn: spawnChild } = await import("child_process");
495
- const { expandHome } = await import("./config-KN6NKKPF.js");
527
+ const { expandHome } = await import("./config-X4UP7H6R.js");
496
528
  const fs2 = await import("fs");
497
529
  const pathMod = await import("path");
498
530
  const cliPath = pathMod.resolve(process.argv[1]);
@@ -534,6 +566,17 @@ async function startServer(opts) {
534
566
  log.error({ err }, "Unhandled rejection");
535
567
  });
536
568
  await core.start();
569
+ try {
570
+ const globalRoot = getGlobalRoot();
571
+ const registryPath = path.join(globalRoot, "instances.json");
572
+ const instanceReg = new InstanceRegistry(registryPath);
573
+ await instanceReg.load();
574
+ if (!instanceReg.getByRoot(ctx.root)) {
575
+ instanceReg.register(ctx.id, ctx.root);
576
+ await instanceReg.save();
577
+ }
578
+ } catch {
579
+ }
537
580
  if (isForegroundTTY) {
538
581
  if (spinner) spinner.stop();
539
582
  const ok = (msg) => console.log(`\x1B[32m\u2713\x1B[0m ${msg}`);
@@ -580,14 +623,14 @@ async function autoRegisterBuiltinPlugins(settingsManager, pluginRegistry, confi
580
623
  }
581
624
  if (legacyConfig) {
582
625
  const pluginModules = await Promise.allSettled([
583
- import("./security-2BA265LN.js"),
584
- import("./file-service-HHB3JQIO.js"),
585
- import("./context-NXXW62NJ.js"),
586
- import("./speech-SG62JYIF.js"),
626
+ import("./security-O4XGN2CM.js"),
627
+ import("./file-service-FQQYME7M.js"),
628
+ import("./context-FVGCU5TI.js"),
629
+ import("./speech-GHTSWDAN.js"),
587
630
  import("./notifications-MO23S7S3.js"),
588
- import("./tunnel-HWJ27WDH.js"),
589
- import("./api-server-5VNYFWJE.js"),
590
- import("./telegram-EAVRDNFU.js")
631
+ import("./tunnel-ALJDPFDQ.js"),
632
+ import("./api-server-L5Z7XACW.js"),
633
+ import("./telegram-D7ASLVEB.js")
591
634
  ]);
592
635
  for (const result of pluginModules) {
593
636
  if (result.status !== "fulfilled") continue;
@@ -596,11 +639,11 @@ async function autoRegisterBuiltinPlugins(settingsManager, pluginRegistry, confi
596
639
  try {
597
640
  const existing = await settingsManager.loadSettings(plugin.name);
598
641
  if (Object.keys(existing).length > 0) continue;
599
- const { createInstallContext } = await import("./install-context-EHYV5WRY.js");
642
+ const { createInstallContext } = await import("./install-context-KZO5FR4D.js");
600
643
  const ctx = createInstallContext({
601
644
  pluginName: plugin.name,
602
645
  settingsManager,
603
- basePath: PLUGINS_DATA_DIR,
646
+ basePath: settingsManager.getBasePath(),
604
647
  legacyConfig
605
648
  });
606
649
  ctx.terminal = createSilentTerminal();
@@ -651,4 +694,4 @@ export {
651
694
  RESTART_EXIT_CODE,
652
695
  startServer
653
696
  };
654
- //# sourceMappingURL=main-L2M4NTJY.js.map
697
+ //# sourceMappingURL=main-D7M2AKRM.js.map