aemeathcli 1.0.10 → 1.0.12

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 (184) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -54
  3. package/dist/App-JQ622M66.js +4431 -0
  4. package/dist/App-JQ622M66.js.map +1 -0
  5. package/dist/agent-store/architect.md +32 -0
  6. package/dist/agent-store/debugger.md +32 -0
  7. package/dist/agent-store/developer.md +29 -0
  8. package/dist/agent-store/documenter.md +30 -0
  9. package/dist/agent-store/researcher.md +31 -0
  10. package/dist/agent-store/reviewer.md +28 -0
  11. package/dist/agent-store/supervisor.md +37 -0
  12. package/dist/agent-store/tester.md +30 -0
  13. package/dist/api-key-fallback-RJLPM3KH.js +11 -0
  14. package/dist/{api-key-fallback-YQQBOQIL.js.map → api-key-fallback-RJLPM3KH.js.map} +1 -1
  15. package/dist/auth-status-JQJOKUPF.js +13 -0
  16. package/dist/auth-status-JQJOKUPF.js.map +1 -0
  17. package/dist/{chunk-RWCNNAL7.js → chunk-2KMA5RBC.js} +25 -48
  18. package/dist/chunk-2KMA5RBC.js.map +1 -0
  19. package/dist/{chunk-CYQNBB25.js → chunk-2Y7TR6BS.js} +28 -5
  20. package/dist/chunk-2Y7TR6BS.js.map +1 -0
  21. package/dist/{chunk-DAHGLHNR.js → chunk-2ZYK5IJG.js} +6 -141
  22. package/dist/chunk-2ZYK5IJG.js.map +1 -0
  23. package/dist/chunk-36RXCZOV.js +88 -0
  24. package/dist/chunk-36RXCZOV.js.map +1 -0
  25. package/dist/{chunk-DMBPX3RG.js → chunk-7EBLXPL4.js} +9 -9
  26. package/dist/{chunk-DMBPX3RG.js.map → chunk-7EBLXPL4.js.map} +1 -1
  27. package/dist/chunk-BIMQL4AG.js +186 -0
  28. package/dist/chunk-BIMQL4AG.js.map +1 -0
  29. package/dist/{chunk-NBR3GHMT.js → chunk-D275MCIH.js} +39 -7
  30. package/dist/chunk-D275MCIH.js.map +1 -0
  31. package/dist/{chunk-Y5XVD2CD.js → chunk-FFS4T7BZ.js} +109 -82
  32. package/dist/chunk-FFS4T7BZ.js.map +1 -0
  33. package/dist/{chunk-CARHU3DO.js → chunk-GXAJGP2T.js} +64 -16
  34. package/dist/chunk-GXAJGP2T.js.map +1 -0
  35. package/dist/{chunk-I5PZ4JTS.js → chunk-HESQLCLU.js} +4 -4
  36. package/dist/{chunk-I5PZ4JTS.js.map → chunk-HESQLCLU.js.map} +1 -1
  37. package/dist/{chunk-JAXXTYID.js → chunk-IR5HLBMH.js} +2 -2
  38. package/dist/{chunk-JAXXTYID.js.map → chunk-IR5HLBMH.js.map} +1 -1
  39. package/dist/{chunk-MFBHNWGV.js → chunk-K2FCMRXH.js} +11 -19
  40. package/dist/chunk-K2FCMRXH.js.map +1 -0
  41. package/dist/{chunk-H66O5Z2V.js → chunk-KIC7UI5U.js} +41 -6
  42. package/dist/chunk-KIC7UI5U.js.map +1 -0
  43. package/dist/{chunk-MXZSI3AY.js → chunk-KMOAJRDE.js} +42 -10
  44. package/dist/chunk-KMOAJRDE.js.map +1 -0
  45. package/dist/chunk-LQBALETG.js +71 -0
  46. package/dist/chunk-LQBALETG.js.map +1 -0
  47. package/dist/chunk-M3FPQSRU.js +12 -0
  48. package/dist/chunk-M3FPQSRU.js.map +1 -0
  49. package/dist/chunk-NQEUK763.js +26 -0
  50. package/dist/chunk-NQEUK763.js.map +1 -0
  51. package/dist/chunk-OPWAFS6Y.js +38 -0
  52. package/dist/chunk-OPWAFS6Y.js.map +1 -0
  53. package/dist/{chunk-6PDJ45T4.js → chunk-PS4WEFW6.js} +50 -25
  54. package/dist/chunk-PS4WEFW6.js.map +1 -0
  55. package/dist/{chunk-HMJRPNPZ.js → chunk-QK7TKNHV.js} +93 -21
  56. package/dist/chunk-QK7TKNHV.js.map +1 -0
  57. package/dist/{chunk-LSOYPSAT.js → chunk-RADJSEG5.js} +4 -4
  58. package/dist/chunk-RADJSEG5.js.map +1 -0
  59. package/dist/{chunk-4IJD72YB.js → chunk-SNWPI6XJ.js} +7 -7
  60. package/dist/chunk-SNWPI6XJ.js.map +1 -0
  61. package/dist/{chunk-TEVZS4FA.js → chunk-UM7MSLOV.js} +16 -9
  62. package/dist/chunk-UM7MSLOV.js.map +1 -0
  63. package/dist/chunk-VNZ3YTQD.js +232 -0
  64. package/dist/chunk-VNZ3YTQD.js.map +1 -0
  65. package/dist/{chunk-IYW62KKR.js → chunk-WXIN65UG.js} +66 -23
  66. package/dist/chunk-WXIN65UG.js.map +1 -0
  67. package/dist/chunk-XEXWX7C7.js +241 -0
  68. package/dist/chunk-XEXWX7C7.js.map +1 -0
  69. package/dist/{chunk-CGEV3ARR.js → chunk-YCCYXDW7.js} +3 -3
  70. package/dist/chunk-YCCYXDW7.js.map +1 -0
  71. package/dist/chunk-YPQ2MLAV.js +140 -0
  72. package/dist/chunk-YPQ2MLAV.js.map +1 -0
  73. package/dist/chunk-ZCOVMVK4.js +26 -0
  74. package/dist/chunk-ZCOVMVK4.js.map +1 -0
  75. package/dist/{claude-login-5WELXPKT.js → claude-login-AIFIWTYF.js} +9 -9
  76. package/dist/{claude-login-5WELXPKT.js.map → claude-login-AIFIWTYF.js.map} +1 -1
  77. package/dist/cli.js +370 -171
  78. package/dist/cli.js.map +1 -1
  79. package/dist/{codex-login-GZIFXUWD.js → codex-login-LW5X7GAM.js} +10 -10
  80. package/dist/codex-login-LW5X7GAM.js.map +1 -0
  81. package/dist/config-store-NF56VHFU.js +7 -0
  82. package/dist/{config-store-W6FBCQAQ.js.map → config-store-NF56VHFU.js.map} +1 -1
  83. package/dist/conversation-store-7GRDQZD2.js +4 -0
  84. package/dist/conversation-store-7GRDQZD2.js.map +1 -0
  85. package/dist/detect-providers-QICJ5U3R.js +4 -0
  86. package/dist/detect-providers-QICJ5U3R.js.map +1 -0
  87. package/dist/executor-FTABX2AW.js +4 -0
  88. package/dist/{executor-6RIKIGXK.js.map → executor-FTABX2AW.js.map} +1 -1
  89. package/dist/first-run-ADROZVYF.js +230 -0
  90. package/dist/first-run-ADROZVYF.js.map +1 -0
  91. package/dist/{gemini-login-AZGL3CE7.js → gemini-login-TST454MX.js} +9 -9
  92. package/dist/{gemini-login-AZGL3CE7.js.map → gemini-login-TST454MX.js.map} +1 -1
  93. package/dist/index.d.ts +46 -70
  94. package/dist/index.js +79 -468
  95. package/dist/index.js.map +1 -1
  96. package/dist/input-history-BEICE7PT.js +57 -0
  97. package/dist/input-history-BEICE7PT.js.map +1 -0
  98. package/dist/kimi-adapter-7FYOAKOI.js +6 -0
  99. package/dist/{kimi-adapter-JN4HFFHU.js.map → kimi-adapter-7FYOAKOI.js.map} +1 -1
  100. package/dist/{kimi-login-6LUWB7P6.js → kimi-login-3IGVOBJI.js} +9 -9
  101. package/dist/{kimi-login-6LUWB7P6.js.map → kimi-login-3IGVOBJI.js.map} +1 -1
  102. package/dist/logger-KGHUQ4VE.js +3 -0
  103. package/dist/logger-KGHUQ4VE.js.map +1 -0
  104. package/dist/model-discovery-AAJDHRFO.js +6 -0
  105. package/dist/model-discovery-AAJDHRFO.js.map +1 -0
  106. package/dist/native-cli-adapters-CLONTZOA.js +8 -0
  107. package/dist/{native-cli-adapters-OLW3XX57.js.map → native-cli-adapters-CLONTZOA.js.map} +1 -1
  108. package/dist/ollama-adapter-2N5OQIEV.js +5 -0
  109. package/dist/{ollama-adapter-OJQ3FKWK.js.map → ollama-adapter-2N5OQIEV.js.map} +1 -1
  110. package/dist/pathResolver-UVAB2FCW.js +3 -0
  111. package/dist/pathResolver-UVAB2FCW.js.map +1 -0
  112. package/dist/profile-loader-EMLV4J7S.js +162 -0
  113. package/dist/profile-loader-EMLV4J7S.js.map +1 -0
  114. package/dist/registry-LRURZVUL.js +5 -0
  115. package/dist/{registry-AZ2LOHHJ.js.map → registry-LRURZVUL.js.map} +1 -1
  116. package/dist/registry-MVNSXCEF.js +6 -0
  117. package/dist/{registry-H7B3AHPQ.js.map → registry-MVNSXCEF.js.map} +1 -1
  118. package/dist/server-manager-THGZBBZB.js +5 -0
  119. package/dist/{server-manager-PTGBHCLS.js.map → server-manager-THGZBBZB.js.map} +1 -1
  120. package/dist/session-manager-X3DXT53M.js +12 -0
  121. package/dist/{session-manager-XOMDMC77.js.map → session-manager-X3DXT53M.js.map} +1 -1
  122. package/dist/skills/built-in/code-review/SKILL.md +85 -0
  123. package/dist/skills/built-in/commit/SKILL.md +83 -0
  124. package/dist/skills/built-in/debug/SKILL.md +119 -0
  125. package/dist/skills/built-in/plan/SKILL.md +123 -0
  126. package/dist/skills/built-in/refactor/SKILL.md +132 -0
  127. package/dist/skills/built-in/test/SKILL.md +128 -0
  128. package/dist/sqlite-store-7OECRTXM.js +5 -0
  129. package/dist/sqlite-store-7OECRTXM.js.map +1 -0
  130. package/dist/team-manager-2VSMALAA.js +11 -0
  131. package/dist/{team-manager-HC4XGCFY.js.map → team-manager-2VSMALAA.js.map} +1 -1
  132. package/dist/team-state-HZNVMQHT.js +3 -0
  133. package/dist/team-state-HZNVMQHT.js.map +1 -0
  134. package/dist/tmux-manager-57QCUVHU.js +6 -0
  135. package/dist/{tmux-manager-GPYZ3WQH.js.map → tmux-manager-57QCUVHU.js.map} +1 -1
  136. package/dist/tools-KWFSYT56.js +6 -0
  137. package/dist/{tools-TSMXMHIF.js.map → tools-KWFSYT56.js.map} +1 -1
  138. package/package.json +11 -11
  139. package/dist/App-FKRSMFMB.js +0 -2789
  140. package/dist/App-FKRSMFMB.js.map +0 -1
  141. package/dist/api-key-fallback-YQQBOQIL.js +0 -11
  142. package/dist/chunk-4IJD72YB.js.map +0 -1
  143. package/dist/chunk-6PDJ45T4.js.map +0 -1
  144. package/dist/chunk-CARHU3DO.js.map +0 -1
  145. package/dist/chunk-CGEV3ARR.js.map +0 -1
  146. package/dist/chunk-CS5X3BWX.js +0 -27
  147. package/dist/chunk-CS5X3BWX.js.map +0 -1
  148. package/dist/chunk-CYQNBB25.js.map +0 -1
  149. package/dist/chunk-DAHGLHNR.js.map +0 -1
  150. package/dist/chunk-H66O5Z2V.js.map +0 -1
  151. package/dist/chunk-HMJRPNPZ.js.map +0 -1
  152. package/dist/chunk-IYW62KKR.js.map +0 -1
  153. package/dist/chunk-LSOYPSAT.js.map +0 -1
  154. package/dist/chunk-MFBHNWGV.js.map +0 -1
  155. package/dist/chunk-MXZSI3AY.js.map +0 -1
  156. package/dist/chunk-NBR3GHMT.js.map +0 -1
  157. package/dist/chunk-RWCNNAL7.js.map +0 -1
  158. package/dist/chunk-TEVZS4FA.js.map +0 -1
  159. package/dist/chunk-UY2SYSEZ.js +0 -211
  160. package/dist/chunk-UY2SYSEZ.js.map +0 -1
  161. package/dist/chunk-WAHVZH7V.js +0 -260
  162. package/dist/chunk-WAHVZH7V.js.map +0 -1
  163. package/dist/chunk-WPP3PEDE.js +0 -234
  164. package/dist/chunk-WPP3PEDE.js.map +0 -1
  165. package/dist/chunk-Y5XVD2CD.js.map +0 -1
  166. package/dist/claude-adapter-QMLFMSP3.js +0 -6
  167. package/dist/claude-adapter-QMLFMSP3.js.map +0 -1
  168. package/dist/codex-login-GZIFXUWD.js.map +0 -1
  169. package/dist/config-store-W6FBCQAQ.js +0 -6
  170. package/dist/executor-6RIKIGXK.js +0 -4
  171. package/dist/gemini-adapter-6JIHZ7WI.js +0 -6
  172. package/dist/gemini-adapter-6JIHZ7WI.js.map +0 -1
  173. package/dist/kimi-adapter-JN4HFFHU.js +0 -6
  174. package/dist/native-cli-adapters-OLW3XX57.js +0 -6
  175. package/dist/ollama-adapter-OJQ3FKWK.js +0 -6
  176. package/dist/openai-adapter-XU46EN7B.js +0 -6
  177. package/dist/openai-adapter-XU46EN7B.js.map +0 -1
  178. package/dist/registry-AZ2LOHHJ.js +0 -6
  179. package/dist/registry-H7B3AHPQ.js +0 -5
  180. package/dist/server-manager-PTGBHCLS.js +0 -5
  181. package/dist/session-manager-XOMDMC77.js +0 -12
  182. package/dist/team-manager-HC4XGCFY.js +0 -11
  183. package/dist/tmux-manager-GPYZ3WQH.js +0 -6
  184. package/dist/tools-TSMXMHIF.js +0 -6
@@ -0,0 +1,241 @@
1
+ import { logger } from './chunk-IR5HLBMH.js';
2
+ import { randomUUID } from 'crypto';
3
+
4
+ var ConversationStore = class {
5
+ store;
6
+ constructor(store) {
7
+ this.store = store;
8
+ }
9
+ createConversation(projectRoot, defaultModel, metadata) {
10
+ const id = randomUUID();
11
+ const metadataJson = JSON.stringify(metadata ?? {});
12
+ this.store.run(
13
+ `INSERT INTO conversations (id, project_root, default_model, metadata)
14
+ VALUES (?, ?, ?, ?)`,
15
+ id,
16
+ projectRoot,
17
+ defaultModel ?? null,
18
+ metadataJson
19
+ );
20
+ logger.info({ conversationId: id, projectRoot }, "Conversation created");
21
+ const row = this.store.get(
22
+ "SELECT * FROM conversations WHERE id = ?",
23
+ id
24
+ );
25
+ if (!row) {
26
+ throw new Error(`Failed to retrieve created conversation: ${id}`);
27
+ }
28
+ return this.mapConversationRow(row);
29
+ }
30
+ getConversation(id) {
31
+ const row = this.store.get(
32
+ "SELECT * FROM conversations WHERE id = ?",
33
+ id
34
+ );
35
+ return row ? this.mapConversationRow(row) : void 0;
36
+ }
37
+ listConversations(projectRoot) {
38
+ const rows = projectRoot ? this.store.all(
39
+ "SELECT * FROM conversations WHERE project_root = ? ORDER BY updated_at DESC",
40
+ projectRoot
41
+ ) : this.store.all(
42
+ "SELECT * FROM conversations ORDER BY updated_at DESC"
43
+ );
44
+ return rows.map((row) => this.mapConversationRow(row));
45
+ }
46
+ deleteConversation(id) {
47
+ this.store.run("DELETE FROM conversations WHERE id = ?", id);
48
+ logger.info({ conversationId: id }, "Conversation deleted");
49
+ }
50
+ addMessage(params) {
51
+ const toolCallsJson = params.toolCalls ? JSON.stringify(params.toolCalls) : null;
52
+ const tokenUsageJson = params.tokenUsage ? JSON.stringify(params.tokenUsage) : null;
53
+ const result = this.store.run(
54
+ `INSERT INTO messages
55
+ (conversation_id, role, model, provider, content, tool_calls, token_usage)
56
+ VALUES (?, ?, ?, ?, ?, ?, ?)`,
57
+ params.conversationId,
58
+ params.role,
59
+ params.model ?? null,
60
+ params.provider ?? null,
61
+ params.content,
62
+ toolCallsJson,
63
+ tokenUsageJson
64
+ );
65
+ this.store.run(
66
+ "UPDATE conversations SET updated_at = datetime('now') WHERE id = ?",
67
+ params.conversationId
68
+ );
69
+ const row = this.store.get(
70
+ "SELECT * FROM messages WHERE id = ?",
71
+ result.lastInsertRowid
72
+ );
73
+ if (!row) {
74
+ throw new Error("Failed to retrieve created message");
75
+ }
76
+ return this.mapMessageRow(row);
77
+ }
78
+ getMessages(conversationId, pagination) {
79
+ const limit = pagination?.limit ?? 100;
80
+ const offset = pagination?.offset ?? 0;
81
+ const rows = this.store.all(
82
+ `SELECT * FROM messages
83
+ WHERE conversation_id = ?
84
+ ORDER BY created_at ASC
85
+ LIMIT ? OFFSET ?`,
86
+ conversationId,
87
+ limit,
88
+ offset
89
+ );
90
+ return rows.map((row) => this.mapMessageRow(row));
91
+ }
92
+ getMessageCount(conversationId) {
93
+ const result = this.store.get(
94
+ "SELECT COUNT(*) as count FROM messages WHERE conversation_id = ?",
95
+ conversationId
96
+ );
97
+ return result?.count ?? 0;
98
+ }
99
+ addFileContext(params) {
100
+ const result = this.store.run(
101
+ `INSERT INTO file_context
102
+ (conversation_id, file_path, content_hash, token_count)
103
+ VALUES (?, ?, ?, ?)`,
104
+ params.conversationId,
105
+ params.filePath,
106
+ params.contentHash ?? null,
107
+ params.tokenCount ?? null
108
+ );
109
+ const row = this.store.get(
110
+ "SELECT * FROM file_context WHERE id = ?",
111
+ result.lastInsertRowid
112
+ );
113
+ if (!row) {
114
+ throw new Error("Failed to retrieve created file context");
115
+ }
116
+ return this.mapFileContextRow(row);
117
+ }
118
+ getFileContext(conversationId) {
119
+ const rows = this.store.all(
120
+ "SELECT * FROM file_context WHERE conversation_id = ? ORDER BY added_at DESC",
121
+ conversationId
122
+ );
123
+ return rows.map((row) => this.mapFileContextRow(row));
124
+ }
125
+ removeFileContext(conversationId, filePath) {
126
+ this.store.run(
127
+ "DELETE FROM file_context WHERE conversation_id = ? AND file_path = ?",
128
+ conversationId,
129
+ filePath
130
+ );
131
+ }
132
+ addCost(params) {
133
+ const result = this.store.run(
134
+ `INSERT INTO cost_tracking
135
+ (conversation_id, provider, model, role, input_tokens, output_tokens, cost_usd)
136
+ VALUES (?, ?, ?, ?, ?, ?, ?)`,
137
+ params.conversationId,
138
+ params.provider,
139
+ params.model,
140
+ params.role ?? null,
141
+ params.inputTokens ?? null,
142
+ params.outputTokens ?? null,
143
+ params.costUsd ?? null
144
+ );
145
+ const row = this.store.get(
146
+ "SELECT * FROM cost_tracking WHERE id = ?",
147
+ result.lastInsertRowid
148
+ );
149
+ if (!row) {
150
+ throw new Error("Failed to retrieve created cost entry");
151
+ }
152
+ return this.mapCostRow(row);
153
+ }
154
+ getConversationCost(conversationId) {
155
+ const result = this.store.get(
156
+ "SELECT SUM(cost_usd) as total FROM cost_tracking WHERE conversation_id = ?",
157
+ conversationId
158
+ );
159
+ return result?.total ?? 0;
160
+ }
161
+ getCostBreakdown(conversationId) {
162
+ const rows = this.store.all(
163
+ "SELECT * FROM cost_tracking WHERE conversation_id = ? ORDER BY created_at ASC",
164
+ conversationId
165
+ );
166
+ return rows.map((row) => this.mapCostRow(row));
167
+ }
168
+ // ── Private row mappers ─────────────────────────────────────────────
169
+ mapConversationRow(row) {
170
+ let metadata = {};
171
+ try {
172
+ metadata = JSON.parse(row.metadata);
173
+ } catch {
174
+ metadata = {};
175
+ }
176
+ return {
177
+ id: row.id,
178
+ projectRoot: row.project_root,
179
+ defaultModel: row.default_model,
180
+ createdAt: row.created_at,
181
+ updatedAt: row.updated_at,
182
+ metadata
183
+ };
184
+ }
185
+ mapMessageRow(row) {
186
+ let toolCalls = null;
187
+ if (row.tool_calls) {
188
+ try {
189
+ toolCalls = JSON.parse(row.tool_calls);
190
+ } catch {
191
+ toolCalls = null;
192
+ }
193
+ }
194
+ let tokenUsage = null;
195
+ if (row.token_usage) {
196
+ try {
197
+ tokenUsage = JSON.parse(row.token_usage);
198
+ } catch {
199
+ tokenUsage = null;
200
+ }
201
+ }
202
+ return {
203
+ id: row.id,
204
+ conversationId: row.conversation_id,
205
+ role: row.role,
206
+ model: row.model,
207
+ provider: row.provider,
208
+ content: row.content,
209
+ toolCalls,
210
+ tokenUsage,
211
+ createdAt: row.created_at
212
+ };
213
+ }
214
+ mapFileContextRow(row) {
215
+ return {
216
+ id: row.id,
217
+ conversationId: row.conversation_id,
218
+ filePath: row.file_path,
219
+ contentHash: row.content_hash,
220
+ tokenCount: row.token_count,
221
+ addedAt: row.added_at
222
+ };
223
+ }
224
+ mapCostRow(row) {
225
+ return {
226
+ id: row.id,
227
+ conversationId: row.conversation_id,
228
+ provider: row.provider,
229
+ model: row.model,
230
+ role: row.role,
231
+ inputTokens: row.input_tokens,
232
+ outputTokens: row.output_tokens,
233
+ costUsd: row.cost_usd,
234
+ createdAt: row.created_at
235
+ };
236
+ }
237
+ };
238
+
239
+ export { ConversationStore };
240
+ //# sourceMappingURL=chunk-XEXWX7C7.js.map
241
+ //# sourceMappingURL=chunk-XEXWX7C7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/conversation-store.ts"],"names":[],"mappings":"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","file":"chunk-XEXWX7C7.js","sourcesContent":["/**\n * Conversation store — PRD section 17.1\n * CRUD for conversations, messages, file context, and cost tracking.\n * All queries use parameterized prepared statements.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { logger } from \"../utils/logger.js\";\nimport type { SqliteStore } from \"./sqlite-store.js\";\nimport type { MessageRole } from \"../types/message.js\";\nimport type { ProviderName } from \"../types/model.js\";\nimport type {\n IConversationRow,\n IMessageRow,\n IFileContextRow,\n ICostRow,\n IConversation,\n IMessage,\n IStoredTokenUsage,\n IFileContext,\n ICostEntry,\n IPaginationOptions,\n IAddMessageParams,\n IAddCostParams,\n IAddFileContextParams,\n} from \"./conversation-types.js\";\n\nexport type {\n IConversation,\n IMessage,\n IStoredTokenUsage,\n IFileContext,\n ICostEntry,\n IPaginationOptions,\n IAddMessageParams,\n IAddCostParams,\n IAddFileContextParams,\n} from \"./conversation-types.js\";\n\nexport class ConversationStore {\n private readonly store: SqliteStore;\n\n constructor(store: SqliteStore) {\n this.store = store;\n }\n\n createConversation(\n projectRoot: string,\n defaultModel?: string,\n metadata?: Record<string, unknown>,\n ): IConversation {\n const id = randomUUID();\n const metadataJson = JSON.stringify(metadata ?? {});\n\n this.store.run(\n `INSERT INTO conversations (id, project_root, default_model, metadata)\n VALUES (?, ?, ?, ?)`,\n id,\n projectRoot,\n defaultModel ?? null,\n metadataJson,\n );\n\n logger.info({ conversationId: id, projectRoot }, \"Conversation created\");\n\n const row = this.store.get(\n \"SELECT * FROM conversations WHERE id = ?\",\n id,\n ) as IConversationRow | undefined;\n\n if (!row) {\n throw new Error(`Failed to retrieve created conversation: ${id}`);\n }\n\n return this.mapConversationRow(row);\n }\n\n getConversation(id: string): IConversation | undefined {\n const row = this.store.get(\n \"SELECT * FROM conversations WHERE id = ?\",\n id,\n ) as IConversationRow | undefined;\n return row ? this.mapConversationRow(row) : undefined;\n }\n\n listConversations(projectRoot?: string): IConversation[] {\n const rows = projectRoot\n ? (this.store.all(\n \"SELECT * FROM conversations WHERE project_root = ? ORDER BY updated_at DESC\",\n projectRoot,\n ) as IConversationRow[])\n : (this.store.all(\n \"SELECT * FROM conversations ORDER BY updated_at DESC\",\n ) as IConversationRow[]);\n\n return rows.map((row) => this.mapConversationRow(row));\n }\n\n deleteConversation(id: string): void {\n this.store.run(\"DELETE FROM conversations WHERE id = ?\", id);\n logger.info({ conversationId: id }, \"Conversation deleted\");\n }\n\n addMessage(params: IAddMessageParams): IMessage {\n const toolCallsJson = params.toolCalls\n ? JSON.stringify(params.toolCalls)\n : null;\n const tokenUsageJson = params.tokenUsage\n ? JSON.stringify(params.tokenUsage)\n : null;\n\n const result = this.store.run(\n `INSERT INTO messages\n (conversation_id, role, model, provider, content, tool_calls, token_usage)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n params.conversationId,\n params.role,\n params.model ?? null,\n params.provider ?? null,\n params.content,\n toolCallsJson,\n tokenUsageJson,\n );\n\n this.store.run(\n \"UPDATE conversations SET updated_at = datetime('now') WHERE id = ?\",\n params.conversationId,\n );\n\n const row = this.store.get(\n \"SELECT * FROM messages WHERE id = ?\",\n result.lastInsertRowid,\n ) as IMessageRow | undefined;\n\n if (!row) {\n throw new Error(\"Failed to retrieve created message\");\n }\n\n return this.mapMessageRow(row);\n }\n\n getMessages(\n conversationId: string,\n pagination?: IPaginationOptions,\n ): IMessage[] {\n const limit = pagination?.limit ?? 100;\n const offset = pagination?.offset ?? 0;\n\n const rows = this.store.all(\n `SELECT * FROM messages\n WHERE conversation_id = ?\n ORDER BY created_at ASC\n LIMIT ? OFFSET ?`,\n conversationId,\n limit,\n offset,\n ) as IMessageRow[];\n\n return rows.map((row) => this.mapMessageRow(row));\n }\n\n getMessageCount(conversationId: string): number {\n const result = this.store.get(\n \"SELECT COUNT(*) as count FROM messages WHERE conversation_id = ?\",\n conversationId,\n ) as { count: number } | undefined;\n return result?.count ?? 0;\n }\n\n addFileContext(params: IAddFileContextParams): IFileContext {\n const result = this.store.run(\n `INSERT INTO file_context\n (conversation_id, file_path, content_hash, token_count)\n VALUES (?, ?, ?, ?)`,\n params.conversationId,\n params.filePath,\n params.contentHash ?? null,\n params.tokenCount ?? null,\n );\n\n const row = this.store.get(\n \"SELECT * FROM file_context WHERE id = ?\",\n result.lastInsertRowid,\n ) as IFileContextRow | undefined;\n\n if (!row) {\n throw new Error(\"Failed to retrieve created file context\");\n }\n\n return this.mapFileContextRow(row);\n }\n\n getFileContext(conversationId: string): IFileContext[] {\n const rows = this.store.all(\n \"SELECT * FROM file_context WHERE conversation_id = ? ORDER BY added_at DESC\",\n conversationId,\n ) as IFileContextRow[];\n return rows.map((row) => this.mapFileContextRow(row));\n }\n\n removeFileContext(conversationId: string, filePath: string): void {\n this.store.run(\n \"DELETE FROM file_context WHERE conversation_id = ? AND file_path = ?\",\n conversationId,\n filePath,\n );\n }\n\n addCost(params: IAddCostParams): ICostEntry {\n const result = this.store.run(\n `INSERT INTO cost_tracking\n (conversation_id, provider, model, role, input_tokens, output_tokens, cost_usd)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n params.conversationId,\n params.provider,\n params.model,\n params.role ?? null,\n params.inputTokens ?? null,\n params.outputTokens ?? null,\n params.costUsd ?? null,\n );\n\n const row = this.store.get(\n \"SELECT * FROM cost_tracking WHERE id = ?\",\n result.lastInsertRowid,\n ) as ICostRow | undefined;\n\n if (!row) {\n throw new Error(\"Failed to retrieve created cost entry\");\n }\n\n return this.mapCostRow(row);\n }\n\n getConversationCost(conversationId: string): number {\n const result = this.store.get(\n \"SELECT SUM(cost_usd) as total FROM cost_tracking WHERE conversation_id = ?\",\n conversationId,\n ) as { total: number | null } | undefined;\n return result?.total ?? 0;\n }\n\n getCostBreakdown(conversationId: string): ICostEntry[] {\n const rows = this.store.all(\n \"SELECT * FROM cost_tracking WHERE conversation_id = ? ORDER BY created_at ASC\",\n conversationId,\n ) as ICostRow[];\n return rows.map((row) => this.mapCostRow(row));\n }\n\n // ── Private row mappers ─────────────────────────────────────────────\n\n private mapConversationRow(row: IConversationRow): IConversation {\n let metadata: Record<string, unknown> = {};\n try {\n metadata = JSON.parse(row.metadata) as Record<string, unknown>;\n } catch {\n metadata = {};\n }\n\n return {\n id: row.id,\n projectRoot: row.project_root,\n defaultModel: row.default_model,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n metadata,\n };\n }\n\n private mapMessageRow(row: IMessageRow): IMessage {\n let toolCalls: unknown[] | null = null;\n if (row.tool_calls) {\n try {\n toolCalls = JSON.parse(row.tool_calls) as unknown[];\n } catch {\n toolCalls = null;\n }\n }\n\n let tokenUsage: IStoredTokenUsage | null = null;\n if (row.token_usage) {\n try {\n tokenUsage = JSON.parse(row.token_usage) as IStoredTokenUsage;\n } catch {\n tokenUsage = null;\n }\n }\n\n return {\n id: row.id,\n conversationId: row.conversation_id,\n role: row.role as MessageRole,\n model: row.model,\n provider: row.provider as ProviderName | null,\n content: row.content,\n toolCalls,\n tokenUsage,\n createdAt: row.created_at,\n };\n }\n\n private mapFileContextRow(row: IFileContextRow): IFileContext {\n return {\n id: row.id,\n conversationId: row.conversation_id,\n filePath: row.file_path,\n contentHash: row.content_hash,\n tokenCount: row.token_count,\n addedAt: row.added_at,\n };\n }\n\n private mapCostRow(row: ICostRow): ICostEntry {\n return {\n id: row.id,\n conversationId: row.conversation_id,\n provider: row.provider,\n model: row.model,\n role: row.role,\n inputTokens: row.input_tokens,\n outputTokens: row.output_tokens,\n costUsd: row.cost_usd,\n createdAt: row.created_at,\n };\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { SUPPORTED_MODELS } from './chunk-HCIHOHLX.js';
2
- import { logger } from './chunk-JAXXTYID.js';
2
+ import { logger } from './chunk-IR5HLBMH.js';
3
3
 
4
4
  // src/utils/tokenCounter.ts
5
5
  function estimateTokenCount(text) {
@@ -76,5 +76,5 @@ function sleep(ms) {
76
76
  }
77
77
 
78
78
  export { createTokenUsage, estimateTokenCount, formatCost, formatTokenCount, sleep, withRetry };
79
- //# sourceMappingURL=chunk-CGEV3ARR.js.map
80
- //# sourceMappingURL=chunk-CGEV3ARR.js.map
79
+ //# sourceMappingURL=chunk-YCCYXDW7.js.map
80
+ //# sourceMappingURL=chunk-YCCYXDW7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/tokenCounter.ts","../src/utils/retry.ts"],"names":[],"mappings":"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","file":"chunk-YCCYXDW7.js","sourcesContent":["/**\n * Multi-provider token estimation per PRD section 7.5\n * Uses a universal approximation since we don't bundle tokenizers for each provider.\n */\n\nimport type { ITokenUsage } from \"../types/index.js\";\nimport { SUPPORTED_MODELS } from \"../types/index.js\";\n\n/**\n * Approximate token count using the ~4 chars per token heuristic.\n * For production cost tracking, we rely on provider-reported usage in API responses.\n */\nexport function estimateTokenCount(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/**\n * Calculate cost in USD based on token usage and model pricing.\n */\nexport function calculateCost(\n modelId: string,\n inputTokens: number,\n outputTokens: number,\n): number {\n const modelInfo = SUPPORTED_MODELS[modelId];\n if (!modelInfo) {\n return 0;\n }\n\n const inputCost = (inputTokens / 1_000_000) * modelInfo.inputPricePerMToken;\n const outputCost = (outputTokens / 1_000_000) * modelInfo.outputPricePerMToken;\n\n return Math.round((inputCost + outputCost) * 1_000_000) / 1_000_000;\n}\n\n/**\n * Create a token usage record with cost calculation.\n */\nexport function createTokenUsage(\n modelId: string,\n inputTokens: number,\n outputTokens: number,\n): ITokenUsage {\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUsd: calculateCost(modelId, inputTokens, outputTokens),\n };\n}\n\n/**\n * Format cost for display (e.g., \"$0.04\").\n */\nexport function formatCost(costUsd: number): string {\n if (costUsd < 0.01) {\n return `$${costUsd.toFixed(4)}`;\n }\n return `$${costUsd.toFixed(2)}`;\n}\n\n/**\n * Format token count for display (e.g., \"12.3K\").\n */\nexport function formatTokenCount(count: number): string {\n if (count < 1_000) {\n return String(count);\n }\n if (count < 1_000_000) {\n return `${(count / 1_000).toFixed(1)}K`;\n }\n return `${(count / 1_000_000).toFixed(1)}M`;\n}\n","/**\n * Retry with exponential backoff per PRD section 20.2\n * Provider failover: If primary model fails, auto-fallback to configured backup.\n */\n\nimport { logger } from \"./logger.js\";\n\nexport interface IRetryOptions {\n readonly maxRetries: number;\n readonly baseDelayMs: number;\n readonly maxDelayMs: number;\n readonly shouldRetry?: (error: unknown, attempt: number) => boolean;\n}\n\nconst DEFAULT_RETRY_OPTIONS: IRetryOptions = {\n maxRetries: 3,\n baseDelayMs: 1_000,\n maxDelayMs: 30_000,\n};\n\n/**\n * Execute a function with exponential backoff retry.\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options?: Partial<IRetryOptions>,\n): Promise<T> {\n const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error: unknown) {\n lastError = error;\n\n if (attempt === opts.maxRetries) {\n break;\n }\n\n if (opts.shouldRetry && !opts.shouldRetry(error, attempt)) {\n break;\n }\n\n const delay = Math.min(\n opts.baseDelayMs * Math.pow(2, attempt) + Math.random() * 1_000,\n opts.maxDelayMs,\n );\n\n logger.warn(\n { attempt: attempt + 1, maxRetries: opts.maxRetries, delayMs: delay },\n \"Retrying after error\",\n );\n\n await sleep(delay);\n }\n }\n\n throw lastError;\n}\n\n/**\n * Sleep for a specified duration.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Check if an error indicates a rate limit (should retry after delay).\n */\nexport function isRateLimitError(error: unknown): boolean {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n return message.includes(\"rate limit\") || message.includes(\"429\") || message.includes(\"too many requests\");\n }\n return false;\n}\n\n/**\n * Check if an error is transient (network issues, timeouts).\n */\nexport function isTransientError(error: unknown): boolean {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n return (\n message.includes(\"timeout\") ||\n message.includes(\"econnreset\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"socket hang up\") ||\n message.includes(\"503\") ||\n message.includes(\"502\")\n );\n }\n return false;\n}\n"]}
@@ -0,0 +1,140 @@
1
+ import { ModelNotFoundError } from './chunk-ZGOHARPV.js';
2
+ import { SUPPORTED_MODELS } from './chunk-HCIHOHLX.js';
3
+ import { logger } from './chunk-IR5HLBMH.js';
4
+
5
+ // src/core/model-router.ts
6
+ var ModelRouter = class {
7
+ config;
8
+ userOverride;
9
+ constructor(config) {
10
+ this.config = config;
11
+ }
12
+ /**
13
+ * Set a temporary user override that takes highest priority.
14
+ */
15
+ setUserOverride(modelId) {
16
+ if (modelId !== void 0) {
17
+ this.validateModel(modelId);
18
+ }
19
+ this.userOverride = modelId;
20
+ }
21
+ /**
22
+ * Resolve the best model for a given role through the priority pipeline.
23
+ */
24
+ resolve(role) {
25
+ if (this.userOverride) {
26
+ const info = this.getModelInfo(this.userOverride);
27
+ return {
28
+ modelId: this.userOverride,
29
+ provider: info.provider,
30
+ source: "user_override",
31
+ role
32
+ };
33
+ }
34
+ if (role) {
35
+ const roleConfig = this.config.roles[role];
36
+ if (roleConfig) {
37
+ if (this.isModelAvailable(roleConfig.primary)) {
38
+ const info = this.getModelInfo(roleConfig.primary);
39
+ return {
40
+ modelId: roleConfig.primary,
41
+ provider: info.provider,
42
+ source: "role_config",
43
+ role
44
+ };
45
+ }
46
+ for (const fallbackModel of roleConfig.fallback) {
47
+ if (this.isModelAvailable(fallbackModel)) {
48
+ const info = this.getModelInfo(fallbackModel);
49
+ logger.info(
50
+ { role, primary: roleConfig.primary, fallback: fallbackModel },
51
+ "Using fallback model for role"
52
+ );
53
+ return {
54
+ modelId: fallbackModel,
55
+ provider: info.provider,
56
+ source: "fallback_chain",
57
+ role
58
+ };
59
+ }
60
+ }
61
+ }
62
+ }
63
+ const defaultModel = this.config.defaultModel;
64
+ if (this.isModelAvailable(defaultModel)) {
65
+ const info = this.getModelInfo(defaultModel);
66
+ return {
67
+ modelId: defaultModel,
68
+ provider: info.provider,
69
+ source: "system_default",
70
+ role
71
+ };
72
+ }
73
+ const anyAvailable = this.getAvailableModels()[0];
74
+ if (anyAvailable) {
75
+ return {
76
+ modelId: anyAvailable.id,
77
+ provider: anyAvailable.provider,
78
+ source: "system_default",
79
+ role
80
+ };
81
+ }
82
+ throw new ModelNotFoundError(defaultModel);
83
+ }
84
+ /**
85
+ * Check if a model is available (provider is enabled and model is known).
86
+ */
87
+ isModelAvailable(modelId) {
88
+ const info = SUPPORTED_MODELS[modelId];
89
+ if (!info) {
90
+ return false;
91
+ }
92
+ return this.config.enabledProviders.includes(info.provider);
93
+ }
94
+ /**
95
+ * Get model info by ID. Throws if not found.
96
+ */
97
+ getModelInfo(modelId) {
98
+ const info = SUPPORTED_MODELS[modelId];
99
+ if (!info) {
100
+ throw new ModelNotFoundError(modelId);
101
+ }
102
+ return info;
103
+ }
104
+ /**
105
+ * Get all available models (from enabled providers).
106
+ */
107
+ getAvailableModels() {
108
+ return Object.values(SUPPORTED_MODELS).filter(
109
+ (model) => this.config.enabledProviders.includes(model.provider)
110
+ );
111
+ }
112
+ /**
113
+ * List models recommended for a specific role.
114
+ */
115
+ getModelsForRole(role) {
116
+ return this.getAvailableModels().filter(
117
+ (model) => model.supportedRoles.includes(role)
118
+ );
119
+ }
120
+ /**
121
+ * Validate that a model ID exists. Throws ModelNotFoundError if not.
122
+ */
123
+ validateModel(modelId) {
124
+ if (!SUPPORTED_MODELS[modelId]) {
125
+ throw new ModelNotFoundError(modelId);
126
+ }
127
+ }
128
+ };
129
+ function createModelRouter(config) {
130
+ const enabledProviders = Object.entries(config.providers).filter(([, providerConfig]) => providerConfig.enabled).map(([name]) => name);
131
+ return new ModelRouter({
132
+ defaultModel: config.defaultModel,
133
+ roles: config.roles,
134
+ enabledProviders
135
+ });
136
+ }
137
+
138
+ export { ModelRouter, createModelRouter };
139
+ //# sourceMappingURL=chunk-YPQ2MLAV.js.map
140
+ //# sourceMappingURL=chunk-YPQ2MLAV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/model-router.ts"],"names":[],"mappings":"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","file":"chunk-YPQ2MLAV.js","sourcesContent":["/**\n * Role-based model selection per PRD section 7.2\n * Resolution pipeline: user override → role config → fallback chain → system default\n */\n\nimport type {\n ModelRole,\n IModelResolution,\n IRoleConfig,\n IGlobalConfig,\n ProviderName,\n IModelInfo,\n} from \"../types/index.js\";\nimport { SUPPORTED_MODELS, ModelNotFoundError } from \"../types/index.js\";\nimport { logger } from \"../utils/index.js\";\n\nexport interface IModelRouterConfig {\n readonly defaultModel: string;\n readonly roles: Partial<Record<ModelRole, IRoleConfig>>;\n readonly enabledProviders: readonly ProviderName[];\n}\n\nexport class ModelRouter {\n private readonly config: IModelRouterConfig;\n private userOverride: string | undefined;\n\n constructor(config: IModelRouterConfig) {\n this.config = config;\n }\n\n /**\n * Set a temporary user override that takes highest priority.\n */\n setUserOverride(modelId: string | undefined): void {\n if (modelId !== undefined) {\n this.validateModel(modelId);\n }\n this.userOverride = modelId;\n }\n\n /**\n * Resolve the best model for a given role through the priority pipeline.\n */\n resolve(role?: ModelRole): IModelResolution {\n // 1. User override (explicit flag: --model claude-opus-4-6)\n if (this.userOverride) {\n const info = this.getModelInfo(this.userOverride);\n return {\n modelId: this.userOverride,\n provider: info.provider,\n source: \"user_override\",\n role,\n };\n }\n\n // 2. Role config\n if (role) {\n const roleConfig = this.config.roles[role];\n if (roleConfig) {\n // Try primary model\n if (this.isModelAvailable(roleConfig.primary)) {\n const info = this.getModelInfo(roleConfig.primary);\n return {\n modelId: roleConfig.primary,\n provider: info.provider,\n source: \"role_config\",\n role,\n };\n }\n\n // 3. Fallback chain\n for (const fallbackModel of roleConfig.fallback) {\n if (this.isModelAvailable(fallbackModel)) {\n const info = this.getModelInfo(fallbackModel);\n logger.info(\n { role, primary: roleConfig.primary, fallback: fallbackModel },\n \"Using fallback model for role\",\n );\n return {\n modelId: fallbackModel,\n provider: info.provider,\n source: \"fallback_chain\",\n role,\n };\n }\n }\n }\n }\n\n // 4. System default\n const defaultModel = this.config.defaultModel;\n if (this.isModelAvailable(defaultModel)) {\n const info = this.getModelInfo(defaultModel);\n return {\n modelId: defaultModel,\n provider: info.provider,\n source: \"system_default\",\n role,\n };\n }\n\n // Last resort: find any available model\n const anyAvailable = this.getAvailableModels()[0];\n if (anyAvailable) {\n return {\n modelId: anyAvailable.id,\n provider: anyAvailable.provider,\n source: \"system_default\",\n role,\n };\n }\n\n throw new ModelNotFoundError(defaultModel);\n }\n\n /**\n * Check if a model is available (provider is enabled and model is known).\n */\n isModelAvailable(modelId: string): boolean {\n const info = SUPPORTED_MODELS[modelId];\n if (!info) {\n return false;\n }\n return this.config.enabledProviders.includes(info.provider);\n }\n\n /**\n * Get model info by ID. Throws if not found.\n */\n getModelInfo(modelId: string): IModelInfo {\n const info = SUPPORTED_MODELS[modelId];\n if (!info) {\n throw new ModelNotFoundError(modelId);\n }\n return info;\n }\n\n /**\n * Get all available models (from enabled providers).\n */\n getAvailableModels(): readonly IModelInfo[] {\n return Object.values(SUPPORTED_MODELS).filter((model) =>\n this.config.enabledProviders.includes(model.provider),\n );\n }\n\n /**\n * List models recommended for a specific role.\n */\n getModelsForRole(role: ModelRole): readonly IModelInfo[] {\n return this.getAvailableModels().filter((model) =>\n model.supportedRoles.includes(role),\n );\n }\n\n /**\n * Validate that a model ID exists. Throws ModelNotFoundError if not.\n */\n private validateModel(modelId: string): void {\n if (!SUPPORTED_MODELS[modelId]) {\n throw new ModelNotFoundError(modelId);\n }\n }\n}\n\n/**\n * Create a ModelRouter from the global config.\n */\nexport function createModelRouter(config: IGlobalConfig): ModelRouter {\n const enabledProviders = Object.entries(config.providers)\n .filter(([, providerConfig]) => providerConfig.enabled)\n .map(([name]) => name as ProviderName);\n\n return new ModelRouter({\n defaultModel: config.defaultModel,\n roles: config.roles,\n enabledProviders,\n });\n}\n"]}
@@ -0,0 +1,26 @@
1
+ // src/ui/team-state.ts
2
+ var activeTeamManager;
3
+ var activeTeamName;
4
+ var activeTmuxCleanup;
5
+ function getActiveTeamManager() {
6
+ return activeTeamManager;
7
+ }
8
+ function setActiveTeamManager(manager) {
9
+ activeTeamManager = manager;
10
+ }
11
+ function getActiveTeamName() {
12
+ return activeTeamName;
13
+ }
14
+ function setActiveTeamName(name) {
15
+ activeTeamName = name;
16
+ }
17
+ function getActiveTmuxCleanup() {
18
+ return activeTmuxCleanup;
19
+ }
20
+ function setActiveTmuxCleanup(cleanup) {
21
+ activeTmuxCleanup = cleanup;
22
+ }
23
+
24
+ export { getActiveTeamManager, getActiveTeamName, getActiveTmuxCleanup, setActiveTeamManager, setActiveTeamName, setActiveTmuxCleanup };
25
+ //# sourceMappingURL=chunk-ZCOVMVK4.js.map
26
+ //# sourceMappingURL=chunk-ZCOVMVK4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/team-state.ts"],"names":[],"mappings":";AAOA,IAAI,iBAAA;AACJ,IAAI,cAAA;AACJ,IAAI,iBAAA;AAEG,SAAS,oBAAA,GAAgD;AAC9D,EAAA,OAAO,iBAAA;AACT;AAEO,SAAS,qBAAqB,OAAA,EAAwC;AAC3E,EAAA,iBAAA,GAAoB,OAAA;AACtB;AAEO,SAAS,iBAAA,GAAwC;AACtD,EAAA,OAAO,cAAA;AACT;AAEO,SAAS,kBAAkB,IAAA,EAAgC;AAChE,EAAA,cAAA,GAAiB,IAAA;AACnB;AAEO,SAAS,oBAAA,GAA0D;AACxE,EAAA,OAAO,iBAAA;AACT;AAEO,SAAS,qBAAqB,OAAA,EAAkD;AACrF,EAAA,iBAAA,GAAoB,OAAA;AACtB","file":"chunk-ZCOVMVK4.js","sourcesContent":["/**\n * Module-level active team state shared between team commands and team launcher.\n * Extracted from App.tsx to enforce the 300-line component limit (PRD 6.2).\n */\n\nimport type { TeamManager } from \"../teams/team-manager.js\";\n\nlet activeTeamManager: TeamManager | undefined;\nlet activeTeamName: string | undefined;\nlet activeTmuxCleanup: (() => Promise<void>) | undefined;\n\nexport function getActiveTeamManager(): TeamManager | undefined {\n return activeTeamManager;\n}\n\nexport function setActiveTeamManager(manager: TeamManager | undefined): void {\n activeTeamManager = manager;\n}\n\nexport function getActiveTeamName(): string | undefined {\n return activeTeamName;\n}\n\nexport function setActiveTeamName(name: string | undefined): void {\n activeTeamName = name;\n}\n\nexport function getActiveTmuxCleanup(): (() => Promise<void>) | undefined {\n return activeTmuxCleanup;\n}\n\nexport function setActiveTmuxCleanup(cleanup: (() => Promise<void>) | undefined): void {\n activeTmuxCleanup = cleanup;\n}\n"]}
@@ -1,11 +1,11 @@
1
- import { CredentialStore } from './chunk-4IJD72YB.js';
2
- import './chunk-CGEV3ARR.js';
3
- import './chunk-CYQNBB25.js';
4
- import './chunk-NBR3GHMT.js';
5
- import './chunk-CS5X3BWX.js';
6
- import './chunk-HCIHOHLX.js';
1
+ import { CredentialStore } from './chunk-SNWPI6XJ.js';
2
+ import './chunk-YCCYXDW7.js';
3
+ import './chunk-OPWAFS6Y.js';
7
4
  import { AuthenticationError } from './chunk-ZGOHARPV.js';
8
- import { logger } from './chunk-JAXXTYID.js';
5
+ import './chunk-HCIHOHLX.js';
6
+ import './chunk-2Y7TR6BS.js';
7
+ import { logger } from './chunk-IR5HLBMH.js';
8
+ import './chunk-D275MCIH.js';
9
9
  import { createServer } from 'http';
10
10
  import { randomBytes, createHash } from 'crypto';
11
11
  import { execFile } from 'child_process';
@@ -320,5 +320,5 @@ var ClaudeLogin = class {
320
320
  };
321
321
 
322
322
  export { ClaudeLogin };
323
- //# sourceMappingURL=claude-login-5WELXPKT.js.map
324
- //# sourceMappingURL=claude-login-5WELXPKT.js.map
323
+ //# sourceMappingURL=claude-login-AIFIWTYF.js.map
324
+ //# sourceMappingURL=claude-login-AIFIWTYF.js.map