circuschief 0.5.0 → 0.7.0

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 (169) hide show
  1. package/package.json +2 -1
  2. package/packages/server/src/agents/AgentGateway.js +36 -3
  3. package/packages/server/src/agents/BaseAgent.js +15 -1
  4. package/packages/server/src/agents/LoggingAgentWrapper.js +4 -0
  5. package/packages/server/src/agents/adapters/ClaudeCodeAdapter.js +9 -6
  6. package/packages/server/src/agents/adapters/CodexAdapter.js +262 -14
  7. package/packages/server/src/agents/adapters/codexCliRunner.js +185 -0
  8. package/packages/server/src/agents/adapters/codexEventMapper.js +235 -0
  9. package/packages/server/src/agents/types.js +1 -0
  10. package/packages/server/src/agents/vcr/VCRAgentAdapter.js +8 -0
  11. package/packages/server/src/api/agents.js +27 -0
  12. package/packages/server/src/api/canvas.js +20 -0
  13. package/packages/server/src/api/index.js +2 -0
  14. package/packages/server/src/api/projects-session-helpers.js +25 -0
  15. package/packages/server/src/api/projects.js +8 -0
  16. package/packages/server/src/api/providers.js +1 -0
  17. package/packages/server/src/api/sessions-draft.js +1 -0
  18. package/packages/server/src/api/sessions-messages.js +6 -0
  19. package/packages/server/src/api/settings.js +52 -4
  20. package/packages/server/src/db/ConversationRepository.js +16 -3
  21. package/packages/server/src/db/ProjectDefaultsRepository.js +47 -37
  22. package/packages/server/src/db/ProviderRepository.js +62 -6
  23. package/packages/server/src/db/SessionRepository.js +74 -14
  24. package/packages/server/src/db/SettingsRepository.js +44 -16
  25. package/packages/server/src/db/conversation-helpers.js +1 -0
  26. package/packages/server/src/db/migrations/conversationsMigrations.js +4 -0
  27. package/packages/server/src/db/migrations/index.js +4 -0
  28. package/packages/server/src/db/migrations/miscMigrations.js +53 -3
  29. package/packages/server/src/db/migrations/sessionsMigrations.js +6 -1
  30. package/packages/server/src/db/session-helpers.js +8 -0
  31. package/packages/server/src/schema.sql +9 -0
  32. package/packages/server/src/services/agentCallLogger.js +1 -1
  33. package/packages/server/src/services/codexSpawnHelper.js +37 -0
  34. package/packages/server/src/services/commandButtonPrompts.js +48 -0
  35. package/packages/server/src/services/conversationContext.js +27 -0
  36. package/packages/server/src/services/draftSessionService.js +15 -2
  37. package/packages/server/src/services/kanbanTriggers.js +3 -0
  38. package/packages/server/src/services/providerTestService.js +115 -15
  39. package/packages/server/src/services/sessionAgentGuard.js +38 -0
  40. package/packages/server/src/services/sessionExecution.js +127 -33
  41. package/packages/server/src/services/sessionManager.js +45 -8
  42. package/packages/server/src/services/sessionPrompts.js +29 -0
  43. package/packages/server/src/services/sessionProvider.js +160 -41
  44. package/packages/server/src/services/streamEventCallbacks.js +72 -40
  45. package/packages/server/src/services/streamEventHandler.js +16 -2
  46. package/packages/server/src/services/streamUsageHandler.js +6 -0
  47. package/packages/server/src/services/summaryClaudeClient.js +37 -12
  48. package/packages/server/src/services/summaryModelClient.js +154 -0
  49. package/packages/server/src/services/summaryModelResolver.js +148 -0
  50. package/packages/server/src/services/summaryService.js +6 -4
  51. package/packages/server/src/services/templateTriggerService.js +2 -0
  52. package/packages/server/src/services/usageTracker.js +5 -1
  53. package/packages/server/src/services/visibleFinalErrorMessage.js +123 -0
  54. package/packages/shared/src/constants.js +1 -2
  55. package/packages/shared/src/contracts/projects.js +2 -0
  56. package/packages/shared/src/contracts/providers.js +24 -7
  57. package/packages/shared/src/contracts/sessions.js +1 -1
  58. package/packages/shared/src/index.js +1 -0
  59. package/packages/shared/src/types.js +28 -0
  60. package/packages/shared/src/utils.js +9 -17
  61. package/packages/web/dist/assets/ActiveSessionsView-UJsCILDL.js +1 -0
  62. package/packages/web/dist/assets/{AgentLogsView-DCF2WvP2.js → AgentLogsView-BGFPLjLa.js} +1 -1
  63. package/packages/web/dist/assets/ApiClient-B4YTtyY4.js +1 -0
  64. package/packages/web/dist/assets/{ArchiveConfirmModal-fgoEQhfq.js → ArchiveConfirmModal-OFaj_uX5.js} +1 -1
  65. package/packages/web/dist/assets/{CommandButtonDetailView-DAg07cDQ.js → CommandButtonDetailView-D8S258uP.js} +1 -1
  66. package/packages/web/dist/assets/EffortLevelSelector-C2378L8e.js +1 -0
  67. package/packages/web/dist/assets/{GeneralSettingsView-Cn9VI2du.js → GeneralSettingsView-DsHChEhv.js} +1 -1
  68. package/packages/web/dist/assets/{InputWithButton-BvboBGbz.js → InputWithButton-Ci15ox0a.js} +1 -1
  69. package/packages/web/dist/assets/{InterpolationHelp-0GoSBPgf.js → InterpolationHelp-CIkOSkWX.js} +1 -1
  70. package/packages/web/dist/assets/MarkdownEditor-5-bexzUT.js +2 -0
  71. package/packages/web/dist/assets/ModelSelector-BMpR0DPr.js +1 -0
  72. package/packages/web/dist/assets/{ModelSelector-DPPD-92R.css → ModelSelector-D8hbTRIt.css} +1 -1
  73. package/packages/web/dist/assets/{NewSessionView-C77YVqgY.js → NewSessionView-BCqtIgWH.js} +2 -2
  74. package/packages/web/dist/assets/{NewSessionView-D_Hi7M9g.css → NewSessionView-CUUdHkfv.css} +1 -1
  75. package/packages/web/dist/assets/ProjectEditView-D9sK0fdH.css +1 -0
  76. package/packages/web/dist/assets/ProjectEditView-RFaxHhAX.js +1 -0
  77. package/packages/web/dist/assets/{ProjectListView-CLwtuJ0J.js → ProjectListView-B9FuWESY.js} +1 -1
  78. package/packages/web/dist/assets/{ProjectNewView-CzDtVibO.js → ProjectNewView-D62jYlBL.js} +1 -1
  79. package/packages/web/dist/assets/ProvidersView-DDKMIQWZ.js +1 -0
  80. package/packages/web/dist/assets/ProvidersView-DE82G_5W.css +1 -0
  81. package/packages/web/dist/assets/QuickResponseSettings-CDm5vwP7.js +1 -0
  82. package/packages/web/dist/assets/{QuickResponsesPanel-DIBQFj0W.css → QuickResponsesPanel-BlFDvnZ2.css} +1 -1
  83. package/packages/web/dist/assets/{QuickResponsesPanel-CTXYjMF-.js → QuickResponsesPanel-DZ_Lre_l.js} +1 -1
  84. package/packages/web/dist/assets/{ResizableTextarea-Cw6aL4rp.js → ResizableTextarea-DiIOEGjN.js} +1 -1
  85. package/packages/web/dist/assets/ResizableTextarea-DsU3TVwF.css +1 -0
  86. package/packages/web/dist/assets/SessionCard-BMGC2HqI.css +1 -0
  87. package/packages/web/dist/assets/SessionCard-DmjnVYWn.js +1 -0
  88. package/packages/web/dist/assets/SessionDetailView-CL7nmfiB.js +36 -0
  89. package/packages/web/dist/assets/SessionDetailView-CupIkI7u.css +1 -0
  90. package/packages/web/dist/assets/SessionFormOptions-BpUALRKn.css +1 -0
  91. package/packages/web/dist/assets/SessionFormOptions-DYUISplS.js +1 -0
  92. package/packages/web/dist/assets/SessionListView-BcxGz4aC.js +1 -0
  93. package/packages/web/dist/assets/{SessionListView-DVhoZHN9.css → SessionListView-fHlQyecX.css} +1 -1
  94. package/packages/web/dist/assets/{SessionLogStream-DIndOyFR.js → SessionLogStream-DpUE6Xsh.js} +1 -1
  95. package/packages/web/dist/assets/{SettingsView-CmJ5JPd5.js → SettingsView-BC055tIA.js} +1 -1
  96. package/packages/web/dist/assets/SlashCommandWizard-DmTyNG9O.js +1 -0
  97. package/packages/web/dist/assets/SlashCommandWizard-Dn7sNaBd.css +1 -0
  98. package/packages/web/dist/assets/SummarySettingsView-BgnRCwlq.js +1 -0
  99. package/packages/web/dist/assets/SummarySettingsView-l2bxHmZZ.css +1 -0
  100. package/packages/web/dist/assets/TemplateDetailView-BlhOmLUX.js +1 -0
  101. package/packages/web/dist/assets/{commandButtons-D74TkPNU.js → commandButtons-D4RPpLiu.js} +1 -1
  102. package/packages/web/dist/assets/index-4rhEeO0B.js +1 -0
  103. package/packages/web/dist/assets/index-9vb2KaAd.js +1 -0
  104. package/packages/web/dist/assets/index-B0CvZXuN.js +7 -0
  105. package/packages/web/dist/assets/index-B6G18FqB.js +82 -0
  106. package/packages/web/dist/assets/{index-DMZZCi2u.js → index-BGwH4Cfn.js} +3 -3
  107. package/packages/web/dist/assets/index-BUhvkAdF.js +1 -0
  108. package/packages/web/dist/assets/index-BcnkUk2o.js +1 -0
  109. package/packages/web/dist/assets/{index-DQMHi05L.js → index-Bn5xdGFM.js} +2 -2
  110. package/packages/web/dist/assets/index-CNwkdB0T.js +1 -0
  111. package/packages/web/dist/assets/index-CfL84oGW.js +1 -0
  112. package/packages/web/dist/assets/index-CkmxO8Mm.js +1 -0
  113. package/packages/web/dist/assets/index-Cpy4-yv3.js +1 -0
  114. package/packages/web/dist/assets/index-CrAQJmoZ.js +1 -0
  115. package/packages/web/dist/assets/{index-gmCCsCQ1.css → index-Cs2nxhrT.css} +1 -1
  116. package/packages/web/dist/assets/index-D6Ky9vJe.js +3 -0
  117. package/packages/web/dist/assets/index-DfrE0gAC.js +1 -0
  118. package/packages/web/dist/assets/index-KwEyz0F3.js +1 -0
  119. package/packages/web/dist/assets/index-OfCywayk.js +1 -0
  120. package/packages/web/dist/assets/index-PDesaJc6.js +1 -0
  121. package/packages/web/dist/assets/index-uB6nhSvz.js +1 -0
  122. package/packages/web/dist/assets/{projects-D_C9dE9s.js → projects-BUiOGmmb.js} +1 -1
  123. package/packages/web/dist/assets/providers-Bh1ZiiJi.js +1 -0
  124. package/packages/web/dist/assets/sessions-DH1R-NhV.js +1 -0
  125. package/packages/web/dist/assets/settings-Z4AVVmkJ.js +1 -0
  126. package/packages/web/dist/index.html +2 -2
  127. package/packages/web/dist/assets/ActiveSessionsView-BafIafEu.js +0 -1
  128. package/packages/web/dist/assets/ApiClient-CcqJ-GAv.js +0 -1
  129. package/packages/web/dist/assets/EffortLevelSelector-xE3gidpq.js +0 -1
  130. package/packages/web/dist/assets/MarkdownEditor-HCKnwRye.js +0 -2
  131. package/packages/web/dist/assets/ModelSelector-B0RdlCHT.js +0 -1
  132. package/packages/web/dist/assets/ProjectEditView-BBHOsgBV.js +0 -1
  133. package/packages/web/dist/assets/ProjectEditView-CpeKj-_w.css +0 -1
  134. package/packages/web/dist/assets/ProvidersView-Eg93KbyC.js +0 -1
  135. package/packages/web/dist/assets/ProvidersView-uD8SKWpA.css +0 -1
  136. package/packages/web/dist/assets/QuickResponseSettings-BBHMapcA.js +0 -1
  137. package/packages/web/dist/assets/ResizableTextarea-B5nAA0RV.css +0 -1
  138. package/packages/web/dist/assets/SessionCard-CCapYVjy.js +0 -1
  139. package/packages/web/dist/assets/SessionCard-CcqIjL8q.css +0 -1
  140. package/packages/web/dist/assets/SessionDetailView-BL83oPiI.css +0 -1
  141. package/packages/web/dist/assets/SessionDetailView-CrZvMb3j.js +0 -36
  142. package/packages/web/dist/assets/SessionFormOptions-BuLlDF-7.css +0 -1
  143. package/packages/web/dist/assets/SessionFormOptions-Em7sQCGb.js +0 -1
  144. package/packages/web/dist/assets/SessionListView-3zdDtqhw.js +0 -1
  145. package/packages/web/dist/assets/SlashCommandWizard-BB30cSvo.css +0 -1
  146. package/packages/web/dist/assets/SlashCommandWizard-C_cSgF-P.js +0 -1
  147. package/packages/web/dist/assets/SummarySettingsView-DQM1n3bc.js +0 -1
  148. package/packages/web/dist/assets/SummarySettingsView-DcsmSVJI.css +0 -1
  149. package/packages/web/dist/assets/TemplateDetailView-B8clSBPk.js +0 -1
  150. package/packages/web/dist/assets/index-B5ocUoPf.js +0 -1
  151. package/packages/web/dist/assets/index-BELtFs3n.js +0 -1
  152. package/packages/web/dist/assets/index-BGAW2Nqa.js +0 -82
  153. package/packages/web/dist/assets/index-BsDR4w2c.js +0 -1
  154. package/packages/web/dist/assets/index-CVozYqQ-.js +0 -3
  155. package/packages/web/dist/assets/index-CefzeYRE.js +0 -1
  156. package/packages/web/dist/assets/index-CrLh8vw5.js +0 -1
  157. package/packages/web/dist/assets/index-DIvveuSK.js +0 -1
  158. package/packages/web/dist/assets/index-DPt6qBRK.js +0 -1
  159. package/packages/web/dist/assets/index-DYWZ8lD-.js +0 -1
  160. package/packages/web/dist/assets/index-DrlwE0Zo.js +0 -7
  161. package/packages/web/dist/assets/index-DuXChAe-.js +0 -1
  162. package/packages/web/dist/assets/index-Dz7jFUYU.js +0 -1
  163. package/packages/web/dist/assets/index-Gre8tUfC.js +0 -1
  164. package/packages/web/dist/assets/index-_Lv79l46.js +0 -1
  165. package/packages/web/dist/assets/index-f315nDFm.js +0 -1
  166. package/packages/web/dist/assets/index-rjbX81sm.js +0 -1
  167. package/packages/web/dist/assets/providers-BdvbPVdE.js +0 -1
  168. package/packages/web/dist/assets/sessions-Bs5FA6JZ.js +0 -1
  169. package/packages/web/dist/assets/settings-6Rw9xt-G.js +0 -1
@@ -4,6 +4,7 @@ import { setupGitForSession } from './gitSessionSetup.js';
4
4
  import { runSession } from './sessionManager.js';
5
5
  import { broadcastToProject } from '../websocket.js';
6
6
  import { WS_MESSAGE_TYPES } from '../../../shared/src/index.js';
7
+ import { resolveAgentTypeFromModel } from './sessionProvider.js';
7
8
 
8
9
  const liquid = new Liquid();
9
10
 
@@ -157,6 +158,7 @@ function buildChildSessionOptions(template, parentSession, settings) {
157
158
  status: 'starting',
158
159
  model: settings.model,
159
160
  effortLevel: settings.effortLevel,
161
+ agentType: resolveAgentTypeFromModel(settings.model),
160
162
  };
161
163
 
162
164
  const postCreateUpdate = {
@@ -1,4 +1,4 @@
1
- /** @type {Map<string, {inputTokens: number, outputTokens: number, lastMessageOutput: number, cacheReadInputTokens: number, cacheCreationInputTokens: number}>}
1
+ /** @type {Map<string, {inputTokens: number, outputTokens: number, thinkingTokens: number, lastMessageOutput: number, cacheReadInputTokens: number, cacheCreationInputTokens: number}>}
2
2
  * Current turn usage - accumulates across multiple messages within a turn
3
3
  * Keyed by conversationId (Issue #175)
4
4
  * - inputTokens: MAX seen across all messages (larger context with tool results)
@@ -31,6 +31,7 @@ function updateTurnUsage(conversationId, usage, eventType) {
31
31
  const current = currentTurnUsage.get(conversationId) || {
32
32
  inputTokens: 0,
33
33
  outputTokens: 0,
34
+ thinkingTokens: 0,
34
35
  lastMessageOutput: 0,
35
36
  cacheReadInputTokens: 0,
36
37
  cacheCreationInputTokens: 0,
@@ -46,11 +47,13 @@ function updateTurnUsage(conversationId, usage, eventType) {
46
47
  estimatedOutputTokens.delete(conversationId);
47
48
  // 4. For input tokens, keep the MAX (larger context with tool results)
48
49
  current.inputTokens = Math.max(current.inputTokens, usage.input_tokens || 0);
50
+ current.thinkingTokens = Math.max(current.thinkingTokens, usage.thinking_tokens || usage.thinkingTokens || 0);
49
51
  current.cacheReadInputTokens = Math.max(current.cacheReadInputTokens, usage.cache_read_input_tokens || 0);
50
52
  current.cacheCreationInputTokens = Math.max(current.cacheCreationInputTokens, usage.cache_creation_input_tokens || 0);
51
53
  } else if (eventType === 'message_delta') {
52
54
  // OUTPUT STREAMING - output_tokens is cumulative within this message
53
55
  current.lastMessageOutput = usage.output_tokens || 0;
56
+ current.thinkingTokens = Math.max(current.thinkingTokens, usage.thinking_tokens || usage.thinkingTokens || 0);
54
57
  // Clear estimate when actual output tokens arrive
55
58
  estimatedOutputTokens.delete(conversationId);
56
59
  }
@@ -61,6 +64,7 @@ function updateTurnUsage(conversationId, usage, eventType) {
61
64
  return {
62
65
  inputTokens: current.inputTokens,
63
66
  outputTokens: current.outputTokens + current.lastMessageOutput,
67
+ thinkingTokens: current.thinkingTokens,
64
68
  cacheReadInputTokens: current.cacheReadInputTokens,
65
69
  cacheCreationInputTokens: current.cacheCreationInputTokens,
66
70
  };
@@ -0,0 +1,123 @@
1
+ import { sessions, conversations, messages } from '../database.js';
2
+ import { broadcastToSession } from '../websocket.js';
3
+ import { WS_MESSAGE_TYPES } from '../../../shared/src/index.js';
4
+
5
+ export function normalizeFinalErrorMessage(error) {
6
+ if (error?.message) {
7
+ return error.message;
8
+ }
9
+ if (typeof error === 'string') {
10
+ return error;
11
+ }
12
+ if (error == null) {
13
+ return 'Unknown error';
14
+ }
15
+ return String(error);
16
+ }
17
+
18
+ function normalizeMessageContent(content) {
19
+ return (content || '').trim().replace(/\s+/g, ' ');
20
+ }
21
+
22
+ function buildVisibleErrorContent(agentType, errorMessage) {
23
+ if (agentType === 'codex') {
24
+ return `Codex failed before completing this turn:\n\n${errorMessage}`;
25
+ }
26
+ if (agentType === 'claude-code') {
27
+ return `Claude Code failed before completing this turn:\n\n${errorMessage}`;
28
+ }
29
+ return `The agent failed before completing this turn:\n\n${errorMessage}`;
30
+ }
31
+
32
+ /**
33
+ * Check if a visible error message already exists to prevent duplicates.
34
+ *
35
+ * Uses two strategies to detect existing failures:
36
+ *
37
+ * Strategy 1: Exact match with generated content
38
+ * - Checks if the latest message is an assistant message with content exactly matching
39
+ * what we would generate (e.g., "Codex failed before completing this turn:\n\nerror")
40
+ * - This catches cases where we already created the formatted error message
41
+ *
42
+ * Strategy 2: Raw error in messages after latest user message
43
+ * - Finds the latest user message, then checks all subsequent assistant messages
44
+ * - Returns true if any assistant message contains the raw error text
45
+ * - This catches cases where the agent itself already reported the error
46
+ * (e.g., "Run failed: usage limit reached" contains "usage limit reached")
47
+ *
48
+ * @param {Array} conversationMessages - All messages in the conversation
49
+ * @param {string} generatedContent - The formatted error content we would create
50
+ * @param {string} rawErrorMessage - The raw error message text
51
+ * @returns {boolean} True if a duplicate error message already exists
52
+ */
53
+ function hasExistingVisibleFailure(conversationMessages, generatedContent, rawErrorMessage) {
54
+ const normalizedGenerated = normalizeMessageContent(generatedContent);
55
+ const normalizedError = normalizeMessageContent(rawErrorMessage);
56
+ const latestMessage = conversationMessages[conversationMessages.length - 1];
57
+
58
+ // Strategy 1: Check if the latest message is an exact match with our generated content
59
+ if (
60
+ latestMessage?.role === 'assistant' &&
61
+ normalizeMessageContent(latestMessage.content) === normalizedGenerated
62
+ ) {
63
+ return true;
64
+ }
65
+
66
+ // Find the index of the latest user message
67
+ let latestUserIndex = -1;
68
+ for (let i = conversationMessages.length - 1; i >= 0; i -= 1) {
69
+ if (conversationMessages[i].role === 'user') {
70
+ latestUserIndex = i;
71
+ break;
72
+ }
73
+ }
74
+
75
+ // Strategy 2: Check if any assistant message after the latest user message contains the raw error
76
+ return conversationMessages
77
+ .slice(latestUserIndex + 1)
78
+ .some((message) => {
79
+ if (message.role !== 'assistant') {
80
+ return false;
81
+ }
82
+ const normalizedContent = normalizeMessageContent(message.content);
83
+ return normalizedContent === normalizedGenerated ||
84
+ (normalizedError && normalizedContent.includes(normalizedError));
85
+ });
86
+ }
87
+
88
+ function resolveErrorConversationId(sessionId, activeConversationIds) {
89
+ const activeConversationId = activeConversationIds.get(sessionId);
90
+ if (activeConversationId) {
91
+ return activeConversationId;
92
+ }
93
+ const activeConversation = conversations.ensureActiveConversation(sessionId);
94
+ if (activeConversation?.id) {
95
+ activeConversationIds.set(sessionId, activeConversation.id);
96
+ return activeConversation.id;
97
+ }
98
+ return null;
99
+ }
100
+
101
+ export function createVisibleFinalErrorMessage(sessionId, error, activeConversationIds) {
102
+ const conversationId = resolveErrorConversationId(sessionId, activeConversationIds);
103
+ if (!conversationId) {
104
+ return null;
105
+ }
106
+
107
+ const session = sessions.getById(sessionId);
108
+ const errorMessage = normalizeFinalErrorMessage(error);
109
+ const content = buildVisibleErrorContent(session?.agentType, errorMessage);
110
+ const conversationMessages = messages.getByConversationId(conversationId) || [];
111
+
112
+ if (hasExistingVisibleFailure(conversationMessages, content, errorMessage)) {
113
+ return null;
114
+ }
115
+
116
+ const message = messages.create(sessionId, 'assistant', content, { conversationId });
117
+ sessions.touch(sessionId);
118
+ broadcastToSession(sessionId, WS_MESSAGE_TYPES.SESSION_MESSAGE, {
119
+ message,
120
+ conversationId,
121
+ });
122
+ return message;
123
+ }
@@ -4,8 +4,7 @@ export const API_PREFIX = '/api';
4
4
  export const WS_PATH = '/ws';
5
5
 
6
6
  /**
7
- * Default token cost weights for calculating Billable Token Equivalent (BTE)
8
- * These weights represent relative costs compared to input tokens (1.0 = base rate)
7
+ * Legacy token cost weights kept for settings API compatibility.
9
8
  */
10
9
  export const DEFAULT_TOKEN_COST_WEIGHTS = {
11
10
  input: 1.0, // Base rate
@@ -49,6 +49,7 @@ export const ProjectSessionDefaultsRequest = z.object({
49
49
  gitMode: z.enum(['branch', 'worktree']).nullable().optional(),
50
50
  gitBranch: z.string().nullable().optional(),
51
51
  model: z.string().nullable().optional(),
52
+ providerId: z.string().nullable().optional(),
52
53
  });
53
54
 
54
55
  export const ProjectSessionDefaultsResponse = z.object({
@@ -61,6 +62,7 @@ export const ProjectSessionDefaultsResponse = z.object({
61
62
  gitMode: z.enum(['branch', 'worktree']).nullable(),
62
63
  gitBranch: z.string().nullable(),
63
64
  model: z.string().nullable(),
65
+ providerId: z.string().nullable(),
64
66
  createdAt: z.number(),
65
67
  updatedAt: z.number(),
66
68
  });
@@ -1,24 +1,40 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ /**
4
+ * Provider "kind" == wire protocol / env-var convention.
5
+ * 'anthropic' → Claude Code SDK (ANTHROPIC_* env vars)
6
+ * 'openai' → OpenAI-compatible / Codex (OPENAI_* env vars)
7
+ * Kind is **immutable after create**; switching kind invalidates the provider's
8
+ * registered models.
9
+ */
10
+ export const ProviderKind = z.enum(['anthropic', 'openai']);
11
+
3
12
  export const CreateProviderRequest = z.object({
4
13
  name: z.string().min(1).max(100),
14
+ kind: ProviderKind,
5
15
  baseUrl: z.string().url().nullable().optional(),
6
16
  authToken: z.string().nullable().optional(),
7
17
  apiTimeoutMs: z.number().int().positive().nullable().optional(),
8
18
  additionalEnvVars: z.record(z.string()).nullable().optional(),
9
19
  });
10
20
 
11
- export const UpdateProviderRequest = z.object({
12
- name: z.string().min(1).max(100).optional(),
13
- baseUrl: z.string().url().nullable().optional(),
14
- authToken: z.string().nullable().optional(),
15
- apiTimeoutMs: z.number().int().positive().nullable().optional(),
16
- additionalEnvVars: z.record(z.string()).nullable().optional(),
17
- });
21
+ // `kind` is intentionally omitted. `.strict()` makes any extra key (including
22
+ // `kind`) reject the request at the contract boundary; the repository also
23
+ // throws at runtime as defense-in-depth.
24
+ export const UpdateProviderRequest = z
25
+ .object({
26
+ name: z.string().min(1).max(100).optional(),
27
+ baseUrl: z.string().url().nullable().optional(),
28
+ authToken: z.string().nullable().optional(),
29
+ apiTimeoutMs: z.number().int().positive().nullable().optional(),
30
+ additionalEnvVars: z.record(z.string()).nullable().optional(),
31
+ })
32
+ .strict();
18
33
 
19
34
  export const ProviderResponse = z.object({
20
35
  id: z.string().uuid(),
21
36
  name: z.string(),
37
+ kind: ProviderKind,
22
38
  baseUrl: z.string().nullable(),
23
39
  authToken: z.string().nullable(), // Will be redacted in API responses
24
40
  apiTimeoutMs: z.number().nullable(),
@@ -61,6 +77,7 @@ export const ProviderModelResponse = z.object({
61
77
  export const ProviderModelListResponse = z.array(ProviderModelResponse);
62
78
 
63
79
  export const TestConnectionRequest = z.object({
80
+ kind: ProviderKind,
64
81
  baseUrl: z.string().url().nullable().optional(),
65
82
  authToken: z.string().nullable().optional(),
66
83
  defaultSonnetModel: z.string().nullable().optional(),
@@ -83,7 +83,7 @@ export const SessionResponse = z.object({
83
83
  laneTriggerDepth: z.number(),
84
84
  createdAt: z.number(),
85
85
  updatedAt: z.number(),
86
- lastActivityAt: z.number(),
86
+ lastActivityAt: z.number().nullable(),
87
87
  });
88
88
 
89
89
  export const SessionListResponse = z.array(SessionResponse);
@@ -3,3 +3,4 @@ export * from './protocol.js';
3
3
  export * from './constants.js';
4
4
  export * from './utils.js';
5
5
  export * from './contracts/canvas.js';
6
+ export * from './contracts/providers.js';
@@ -122,6 +122,34 @@ export const CLAUDE_MODELS = [
122
122
  ];
123
123
  export const DEFAULT_MODEL = 'claude-opus-4-7';
124
124
 
125
+ export const OPENAI_MODELS = [
126
+ {
127
+ id: 'gpt-5.5',
128
+ name: 'GPT-5.5',
129
+ description: 'Flagship coding and professional work',
130
+ seedId: 'openai-gpt-5-5',
131
+ },
132
+ {
133
+ id: 'gpt-5.4',
134
+ name: 'GPT-5.4',
135
+ description: 'High capability professional work',
136
+ seedId: 'openai-gpt-5-4',
137
+ },
138
+ {
139
+ id: 'gpt-5.4-mini',
140
+ name: 'GPT-5.4 mini',
141
+ description: 'Fast lower-cost coding and subagent work',
142
+ seedId: 'openai-gpt-5-4-mini',
143
+ },
144
+ {
145
+ id: 'gpt-5.3-codex',
146
+ name: 'GPT-5.3-Codex',
147
+ description: 'Coding-optimized agentic model',
148
+ seedId: 'openai-gpt-5-3-codex',
149
+ },
150
+ ];
151
+ export const DEFAULT_OPENAI_MODEL = 'gpt-5.5';
152
+
125
153
  /**
126
154
  * @typedef {Object} KanbanBoard
127
155
  * @property {string} id
@@ -1,5 +1,3 @@
1
- import { DEFAULT_TOKEN_COST_WEIGHTS } from './constants.js';
2
-
3
1
  /**
4
2
  * Generate a short random ID (4 hex characters)
5
3
  * @returns {string}
@@ -9,23 +7,17 @@ export function generateShortId() {
9
7
  }
10
8
 
11
9
  /**
12
- * Calculate Billable Token Equivalent (BTE) - a cost-weighted token score
13
- * @param {Object} usage - Token usage object
14
- * @param {number} [usage.inputTokens] - Number of input tokens
15
- * @param {number} [usage.outputTokens] - Number of output tokens
16
- * @param {number} [usage.cacheReadInputTokens] - Number of cache read tokens
17
- * @param {number} [usage.cacheCreationInputTokens] - Number of cache creation tokens
18
- * @param {Object} [weights] - Custom weights (defaults to DEFAULT_TOKEN_COST_WEIGHTS)
19
- * @returns {number} The calculated BTE score
10
+ * Calculate the canonical raw token total for display.
11
+ * @param {Object|null|undefined} usage - Token usage object
12
+ * @returns {number} The raw token total
20
13
  */
21
- export function calculateBillableTokens(usage, weights = DEFAULT_TOKEN_COST_WEIGHTS) {
14
+ export function calculateTokenTotal(usage) {
22
15
  if (!usage) return 0;
23
- return Math.round(
24
- (usage.inputTokens || 0) * weights.input +
25
- (usage.outputTokens || 0) * weights.output +
26
- (usage.cacheReadInputTokens || 0) * weights.cacheRead +
27
- (usage.cacheCreationInputTokens || 0) * weights.cacheCreation
28
- );
16
+ return (usage.inputTokens || 0) +
17
+ (usage.outputTokens || 0) +
18
+ (usage.thinkingTokens || 0) +
19
+ (usage.cacheReadInputTokens || 0) +
20
+ (usage.cacheCreationInputTokens || 0);
29
21
  }
30
22
 
31
23
  /**
@@ -0,0 +1 @@
1
+ import{u as K}from"./sessions-DH1R-NhV.js";import{u as Q}from"./commandButtons-D4RPpLiu.js";import{z as j,W as c,_ as X,o as Z,A as ee,l as te,a,c as l,b as f,F as A,r as C,E as O,u as S,t as b,d as se,w as re,f as ne,x as D,g as oe,n as ie,y as R,G as ae}from"./index-B6G18FqB.js";import{a as x}from"./ApiClient-B4YTtyY4.js";import{S as le}from"./SessionCard-DmjnVYWn.js";import"./SessionLogStream-DpUE6Xsh.js";function ce(){const{on:E,off:s}=j(),d=h=>p=>{const i=F=>{F.session&&p(F.session,F.projectId)};return E(h,i),()=>s(h,i)},I=d(c.SESSION_CREATED),w=d(c.SESSION_UPDATED);return{onSessionCreated:I,onSessionUpdated:w,onSessionDeleted:h=>{const p=i=>{i.sessionId&&h(i.sessionId,i.projectId)};return E(c.SESSION_DELETED,p),()=>s(c.SESSION_DELETED,p)},onSessionSummaryUpdated:h=>{const p=i=>{i.sessionId&&i.summary&&h(i.sessionId,i.summary,i.projectId)};return E(c.SESSION_SUMMARY_UPDATED,p),()=>s(c.SESSION_SUMMARY_UPDATED,p)}}}const de=["data-state"],ue={class:"filters-container"},fe={class:"status-filters"},Se=["onClick"],pe=["title"],me={key:0,class:"star-icon"},he={key:1,class:"star-icon star-crossed"},_e={key:2,class:"star-icon"},ye={key:0,class:"skeleton-list"},ve={key:1,class:"error-message"},Fe={key:2,class:"empty-state","data-testid":"active-sessions-empty"},Ee={key:3,class:"empty-state","data-testid":"active-sessions-empty"},Ie={key:4,class:"session-list"},we={__name:"ActiveSessionsView",setup(E){const s=K(),d=Q(),I=["waiting","stopped","error"],w=["running","starting"],v=ie(new Set),g=e=>{s.statusFilter===e?s.setStatusFilter(null):s.setStatusFilter(e)},h=()=>{s.starredFilter===null?s.setStarredFilter("starred"):s.starredFilter==="starred"?s.setStarredFilter("unstarred"):s.setStarredFilter(null)},p=D(()=>s.starredFilter==="starred"?"Showing starred sessions only. Click to filter unstarred.":s.starredFilter==="unstarred"?"Showing unstarred sessions only. Click to show all.":"Showing all sessions. Click to filter by starred."),i=D(()=>{let e=s.activeSessions;return s.statusFilter&&(e=e.filter(t=>{const r=t.status;return!!(s.statusFilter==="idle"&&I.includes(r)||s.statusFilter==="running"&&w.includes(r))})),s.starredFilter==="starred"?e=e.filter(t=>t.starred):s.starredFilter==="unstarred"&&(e=e.filter(t=>!t.starred)),e}),F=D(()=>s.loading?"loading":s.error?"error":s.activeSessions.length===0?"empty-all":i.value.length===0?"empty-filtered":"results"),_=R({}),u=R({}),m=R({});let N=null;const y=[],{onSessionCreated:P,onSessionUpdated:B,onSessionDeleted:L,onSessionSummaryUpdated:V}=ce();async function M(){const e=new Set(s.activeSessions.map(t=>t.projectId).filter(t=>t&&!v.value.has(t)));for(const t of e)try{await d.fetchButtons(t),await d.fetchLatestRunsForProject(t),v.value.add(t)}catch(r){console.error(`Failed to fetch buttons for project ${t}:`,r)}}function U(e,t,r){d.runs[e]||(d.runs[e]={runId:e,buttonId:t,sessionId:r,status:"running",output:"",exitCode:null,startedAt:Date.now(),outputTruncated:!1})}function H(e){["running","waiting","starting"].includes(e.status)&&(s.activeSessions.some(r=>r.id===e.id)||(s.activeSessions.unshift(e),e.projectId&&!v.value.has(e.projectId)&&(d.fetchButtons(e.projectId),v.value.add(e.projectId))))}function G(e){const t=["running","waiting","starting"].includes(e.status),r=s.activeSessions.findIndex(n=>n.id===e.id);t?r>=0?s.activeSessions[r]=e:s.activeSessions.unshift(e):r>=0&&(s.activeSessions.splice(r,1),delete _[e.id],delete u[e.id],delete m[e.id])}function W(e){const t=s.activeSessions.findIndex(r=>r.id===e);t>=0&&s.activeSessions.splice(t,1),delete _[e],delete u[e],delete m[e]}function Y(e,t){_[e]=t,u[e]=!1,m[e]=!1}function $(e,t,r){const n=o=>{U(o.runId,o.buttonId,o.sessionId),d.appendOutput(o.runId,o.output)};e(c.COMMAND_RUN_OUTPUT,n),r.push(()=>t(c.COMMAND_RUN_OUTPUT,n));const k=o=>{U(o.runId,o.buttonId,o.sessionId),d.completeRun(o.runId,o.exitCode,o.output)};e(c.COMMAND_RUN_COMPLETE,k),r.push(()=>t(c.COMMAND_RUN_COMPLETE,k));const T=o=>{U(o.runId,o.buttonId,o.sessionId),d.errorRun(o.runId,o.error)};e(c.COMMAND_RUN_ERROR,T),r.push(()=>t(c.COMMAND_RUN_ERROR,T))}Z(async()=>{s.restoreStatusFilter(),s.restoreStarredFilter(),await s.fetchActiveSessions(),await M(),y.push(P(H)),y.push(B(G)),y.push(L(W)),y.push(V(Y));const{on:e,off:t}=j();$(e,t,y),N=setInterval(()=>{s.fetchActiveSessions(!1)},3e4)}),ee(()=>{y.forEach(e=>e()),N&&clearInterval(N)}),te(()=>s.activeSessions,()=>{z(),M()},{immediate:!0});async function z(){const t=s.activeSessions.filter(r=>!_[r.id]&&!u[r.id]).map(r=>r.id);if(t.length!==0){for(const r of t)u[r]=!0,m[r]=!1;try{const r=await x.getSessionSummariesBatch(t);for(const n of t)r[n]&&(_[n]=r[n]),u[n]=!1}catch(r){console.warn("Failed to fetch summaries batch:",r.message);for(const n of t)m[n]=!0,u[n]=!1}}}async function q(e){var t;u[e]=!0,m[e]=!1;try{const r=await x.getSessionSummary(e);r&&(_[e]=r)}catch(r){((t=r.response)==null?void 0:t.status)!==404&&(console.warn(`Failed to fetch summary for session ${e}:`,r.message),m[e]=!0)}finally{u[e]=!1}}async function J(e){m[e]=!1,await q(e)}return(e,t)=>{const r=oe("router-link");return a(),l("div",{class:"container","data-testid":"active-sessions-view","data-state":F.value},[t[3]||(t[3]=f("div",{class:"page-header"},[f("div",null,[f("p",{class:"page-description"}," All active sessions across your projects ")])],-1)),f("div",ue,[f("div",fe,[(a(),l(A,null,C(["running","idle"],n=>f("button",{key:n,class:O(["filter-btn",{active:S(s).statusFilter===n}]),onClick:k=>g(n)},b(n),11,Se)),64)),f("button",{class:O(["filter-btn star-btn",{"star-filter-active":S(s).starredFilter==="starred","star-filter-unstarred":S(s).starredFilter==="unstarred","star-filter-all":S(s).starredFilter===null}]),title:p.value,onClick:h},[S(s).starredFilter==="starred"?(a(),l("span",me,"⭐")):S(s).starredFilter==="unstarred"?(a(),l("span",he,"⭐")):(a(),l("span",_e,"☆"))],10,pe)])]),S(s).loading?(a(),l("div",ye,[(a(),l(A,null,C(3,n=>f("div",{key:n,class:"skeleton card",style:{height:"120px"}})),64))])):S(s).error?(a(),l("div",ve,b(S(s).error),1)):S(s).activeSessions.length===0?(a(),l("div",Fe,[t[1]||(t[1]=f("p",null,"No active sessions. All sessions are completed or there are no sessions yet.",-1)),se(r,{to:"/",class:"btn btn-primary"},{default:re(()=>[...t[0]||(t[0]=[ne(" View Projects ",-1)])]),_:1})])):i.value.length===0?(a(),l("div",Ee,[...t[2]||(t[2]=[f("p",null,"No sessions match the current filter.",-1)])])):(a(),l("div",Ie,[(a(!0),l(A,null,C(i.value,n=>(a(),ae(le,{key:n.id,session:n,"show-project":!0,"show-summary":!0,summary:_[n.id],"summary-loading":u[n.id],"summary-error":m[n.id],onRetrySummary:J},null,8,["session","summary","summary-loading","summary-error"]))),128))]))],8,de)}}},Re=X(we,[["__scopeId","data-v-9a53578e"]]);export{Re as default};
@@ -1,2 +1,2 @@
1
- import{L as q,_ as O,a as r,c as i,b as t,F as k,r as $,t as f,i as _,E as A,x as p,g as W,f as F,G as z,w as G,o as H,A as J,d as w,u as m,n as B}from"./index-BGAW2Nqa.js";import{a as L}from"./ApiClient-CcqJ-GAv.js";const U=q("agentLogs",{state:()=>({logs:[],pagination:{total:0,limit:25,offset:0,hasMore:!1},filters:{agentType:null,callType:null,status:null,model:null,startDate:null,endDate:null,sessionId:null},filterOptions:{agentTypes:[],callTypes:[],statuses:[],models:[]},perPage:25,currentPage:1,sortBy:"started_at",sortOrder:"DESC",loading:!1,error:null}),getters:{totalPages:s=>Math.ceil(s.pagination.total/s.perPage)||0,activeFilters:s=>{const e={};for(const[y,h]of Object.entries(s.filters))h!=null&&(e[y]=h);return e}},actions:{async fetchLogs(){this.loading=!0,this.error=null;try{const s=(this.currentPage-1)*this.perPage,e=await L.getAgentCallLogs({limit:this.perPage,offset:s,...this.activeFilters,sortBy:this.sortBy,sortOrder:this.sortOrder});this.logs=e.logs,this.pagination=e.pagination}catch(s){this.error=s.message}finally{this.loading=!1}},async fetchFilterOptions(){try{const s=await L.getAgentCallFilterOptions();this.filterOptions=s}catch(s){console.error("Failed to fetch filter options:",s)}},setFilter(s,e){this.filters[s]=e||null,this.currentPage=1,this.fetchLogs()},clearFilters(){Object.keys(this.filters).forEach(s=>this.filters[s]=null),this.currentPage=1,this.fetchLogs()},setPage(s){this.currentPage=s,this.fetchLogs()},setPerPage(s){this.perPage=s,this.currentPage=1,this.fetchLogs()},setSort(s,e){this.sortBy=s,this.sortOrder=e,this.currentPage=1,this.fetchLogs()},async clearAllLogs(){this.loading=!0,this.error=null;try{await L.deleteAllAgentCallLogs(),this.logs=[],this.pagination={total:0,limit:this.perPage,offset:0,hasMore:!1},this.currentPage=1,await this.fetchFilterOptions()}catch(s){this.error=s.message}finally{this.loading=!1}}}}),Z={class:"filter-bar"},Q={class:"filter-row"},X={class:"filter-group"},Y=["value"],K={class:"filter-group"},tt=["value"],et={class:"filter-group"},st=["value"],lt=["value"],at={class:"filter-group"},nt=["value"],ot=["value"],rt={class:"filter-group"},it=["value"],ut=["value"],dt={class:"filter-group"},ct=["value"],ft=["value"],gt={__name:"AgentLogFilters",props:{filters:{type:Object,required:!0},filterOptions:{type:Object,required:!0},hasActiveFilters:{type:Boolean,default:!1},confirming:{type:Boolean,default:!1}},emits:["filter-change","date-change","clear-filters","clear-all"],setup(s){const e=s;function y(v){return new Date(v).toISOString().slice(0,10)}const h=p(()=>e.filters.startDate?y(e.filters.startDate):""),b=p(()=>e.filters.endDate?y(e.filters.endDate):"");return(v,a)=>(r(),i("div",Z,[t("div",Q,[t("div",X,[a[8]||(a[8]=t("label",{class:"filter-label"},"From",-1)),t("input",{type:"date",class:"filter-input",value:h.value,onChange:a[0]||(a[0]=n=>v.$emit("date-change","startDate",n))},null,40,Y)]),t("div",K,[a[9]||(a[9]=t("label",{class:"filter-label"},"To",-1)),t("input",{type:"date",class:"filter-input",value:b.value,onChange:a[1]||(a[1]=n=>v.$emit("date-change","endDate",n))},null,40,tt)]),t("div",et,[a[11]||(a[11]=t("label",{class:"filter-label"},"Agent Type",-1)),t("select",{class:"filter-select",value:s.filters.agentType||"",onChange:a[2]||(a[2]=n=>v.$emit("filter-change","agentType",n.target.value))},[a[10]||(a[10]=t("option",{value:""}," All ",-1)),(r(!0),i(k,null,$(s.filterOptions.agentTypes,n=>(r(),i("option",{key:n,value:n},f(n),9,lt))),128))],40,st)]),t("div",at,[a[13]||(a[13]=t("label",{class:"filter-label"},"Call Type",-1)),t("select",{class:"filter-select",value:s.filters.callType||"",onChange:a[3]||(a[3]=n=>v.$emit("filter-change","callType",n.target.value))},[a[12]||(a[12]=t("option",{value:""}," All ",-1)),(r(!0),i(k,null,$(s.filterOptions.callTypes,n=>(r(),i("option",{key:n,value:n},f(n),9,ot))),128))],40,nt)]),t("div",rt,[a[15]||(a[15]=t("label",{class:"filter-label"},"Status",-1)),t("select",{class:"filter-select",value:s.filters.status||"",onChange:a[4]||(a[4]=n=>v.$emit("filter-change","status",n.target.value))},[a[14]||(a[14]=t("option",{value:""}," All ",-1)),(r(!0),i(k,null,$(s.filterOptions.statuses,n=>(r(),i("option",{key:n,value:n},f(n),9,ut))),128))],40,it)]),t("div",dt,[a[17]||(a[17]=t("label",{class:"filter-label"},"Model",-1)),t("select",{class:"filter-select",value:s.filters.model||"",onChange:a[5]||(a[5]=n=>v.$emit("filter-change","model",n.target.value))},[a[16]||(a[16]=t("option",{value:""}," All ",-1)),(r(!0),i(k,null,$(s.filterOptions.models,n=>(r(),i("option",{key:n,value:n},f(n),9,ft))),128))],40,ct)]),s.hasActiveFilters?(r(),i("button",{key:0,class:"btn-clear",onClick:a[6]||(a[6]=n=>v.$emit("clear-filters"))}," Clear Filters ")):_("",!0),t("button",{class:A(["btn-clear-all",{confirming:s.confirming}]),onClick:a[7]||(a[7]=n=>v.$emit("clear-all"))},f(s.confirming?"Confirm Clear All?":"Clear All Logs"),3)])]))}},vt=O(gt,[["__scopeId","data-v-780329d3"]]),pt={class:"table-wrapper"},ht={key:0,class:"loading-overlay"},yt={class:"log-table"},bt=["onClick"],mt={key:0,class:"sort-indicator"},kt={key:0},$t=["colspan"],Ct={class:"td"},_t={class:"status-text"},Tt={class:"td font-mono text-sm"},At={class:"td font-mono text-sm"},Pt={class:"td model-cell"},Lt={class:"td"},Ot={key:1},St={class:"td"},Dt={key:1},Ft=["title"],wt={class:"td text-right"},Bt=["title"],Mt={__name:"AgentLogTable",props:{logs:{type:Array,required:!0},loading:{type:Boolean,default:!1},sortBy:{type:String,default:"started_at"},sortOrder:{type:String,default:"DESC"}},emits:["sort"],setup(s){const e=[{key:"status",label:"Status",sortable:!0},{key:"agent_type",label:"Agent Type",sortable:!0},{key:"call_type",label:"Call Type",sortable:!0},{key:"model",label:"Model",sortable:!0},{key:"session",label:"Session",sortable:!1},{key:"effort",label:"Effort",sortable:!1},{key:"total_tokens",label:"Tokens",sortable:!0},{key:"duration_ms",label:"Duration",sortable:!0},{key:"started_at",label:"Started",sortable:!0}];function y(l){switch(l){case"completed":return"dot-completed";case"error":return"dot-error";case"streaming":case"pending":return"dot-pending";default:return"dot-default"}}function h(l){const d=[];return l.inputTokens&&d.push(`Input: ${b(l.inputTokens)}`),l.outputTokens&&d.push(`Output: ${b(l.outputTokens)}`),l.thinkingTokens&&d.push(`Thinking: ${b(l.thinkingTokens)}`),l.cacheReadTokens&&d.push(`Cache Read: ${b(l.cacheReadTokens)}`),l.cacheWriteTokens&&d.push(`Cache Write: ${b(l.cacheWriteTokens)}`),d.join(`
1
+ import{L as q,_ as O,a as r,c as i,b as t,F as k,r as $,t as f,i as _,E as A,x as p,g as W,f as F,G as z,w as G,o as H,A as J,d as w,u as m,n as B}from"./index-B6G18FqB.js";import{a as L}from"./ApiClient-B4YTtyY4.js";const U=q("agentLogs",{state:()=>({logs:[],pagination:{total:0,limit:25,offset:0,hasMore:!1},filters:{agentType:null,callType:null,status:null,model:null,startDate:null,endDate:null,sessionId:null},filterOptions:{agentTypes:[],callTypes:[],statuses:[],models:[]},perPage:25,currentPage:1,sortBy:"started_at",sortOrder:"DESC",loading:!1,error:null}),getters:{totalPages:s=>Math.ceil(s.pagination.total/s.perPage)||0,activeFilters:s=>{const e={};for(const[y,h]of Object.entries(s.filters))h!=null&&(e[y]=h);return e}},actions:{async fetchLogs(){this.loading=!0,this.error=null;try{const s=(this.currentPage-1)*this.perPage,e=await L.getAgentCallLogs({limit:this.perPage,offset:s,...this.activeFilters,sortBy:this.sortBy,sortOrder:this.sortOrder});this.logs=e.logs,this.pagination=e.pagination}catch(s){this.error=s.message}finally{this.loading=!1}},async fetchFilterOptions(){try{const s=await L.getAgentCallFilterOptions();this.filterOptions=s}catch(s){console.error("Failed to fetch filter options:",s)}},setFilter(s,e){this.filters[s]=e||null,this.currentPage=1,this.fetchLogs()},clearFilters(){Object.keys(this.filters).forEach(s=>this.filters[s]=null),this.currentPage=1,this.fetchLogs()},setPage(s){this.currentPage=s,this.fetchLogs()},setPerPage(s){this.perPage=s,this.currentPage=1,this.fetchLogs()},setSort(s,e){this.sortBy=s,this.sortOrder=e,this.currentPage=1,this.fetchLogs()},async clearAllLogs(){this.loading=!0,this.error=null;try{await L.deleteAllAgentCallLogs(),this.logs=[],this.pagination={total:0,limit:this.perPage,offset:0,hasMore:!1},this.currentPage=1,await this.fetchFilterOptions()}catch(s){this.error=s.message}finally{this.loading=!1}}}}),Z={class:"filter-bar"},Q={class:"filter-row"},X={class:"filter-group"},Y=["value"],K={class:"filter-group"},tt=["value"],et={class:"filter-group"},st=["value"],lt=["value"],at={class:"filter-group"},nt=["value"],ot=["value"],rt={class:"filter-group"},it=["value"],ut=["value"],dt={class:"filter-group"},ct=["value"],ft=["value"],gt={__name:"AgentLogFilters",props:{filters:{type:Object,required:!0},filterOptions:{type:Object,required:!0},hasActiveFilters:{type:Boolean,default:!1},confirming:{type:Boolean,default:!1}},emits:["filter-change","date-change","clear-filters","clear-all"],setup(s){const e=s;function y(v){return new Date(v).toISOString().slice(0,10)}const h=p(()=>e.filters.startDate?y(e.filters.startDate):""),b=p(()=>e.filters.endDate?y(e.filters.endDate):"");return(v,a)=>(r(),i("div",Z,[t("div",Q,[t("div",X,[a[8]||(a[8]=t("label",{class:"filter-label"},"From",-1)),t("input",{type:"date",class:"filter-input",value:h.value,onChange:a[0]||(a[0]=n=>v.$emit("date-change","startDate",n))},null,40,Y)]),t("div",K,[a[9]||(a[9]=t("label",{class:"filter-label"},"To",-1)),t("input",{type:"date",class:"filter-input",value:b.value,onChange:a[1]||(a[1]=n=>v.$emit("date-change","endDate",n))},null,40,tt)]),t("div",et,[a[11]||(a[11]=t("label",{class:"filter-label"},"Agent Type",-1)),t("select",{class:"filter-select",value:s.filters.agentType||"",onChange:a[2]||(a[2]=n=>v.$emit("filter-change","agentType",n.target.value))},[a[10]||(a[10]=t("option",{value:""}," All ",-1)),(r(!0),i(k,null,$(s.filterOptions.agentTypes,n=>(r(),i("option",{key:n,value:n},f(n),9,lt))),128))],40,st)]),t("div",at,[a[13]||(a[13]=t("label",{class:"filter-label"},"Call Type",-1)),t("select",{class:"filter-select",value:s.filters.callType||"",onChange:a[3]||(a[3]=n=>v.$emit("filter-change","callType",n.target.value))},[a[12]||(a[12]=t("option",{value:""}," All ",-1)),(r(!0),i(k,null,$(s.filterOptions.callTypes,n=>(r(),i("option",{key:n,value:n},f(n),9,ot))),128))],40,nt)]),t("div",rt,[a[15]||(a[15]=t("label",{class:"filter-label"},"Status",-1)),t("select",{class:"filter-select",value:s.filters.status||"",onChange:a[4]||(a[4]=n=>v.$emit("filter-change","status",n.target.value))},[a[14]||(a[14]=t("option",{value:""}," All ",-1)),(r(!0),i(k,null,$(s.filterOptions.statuses,n=>(r(),i("option",{key:n,value:n},f(n),9,ut))),128))],40,it)]),t("div",dt,[a[17]||(a[17]=t("label",{class:"filter-label"},"Model",-1)),t("select",{class:"filter-select",value:s.filters.model||"",onChange:a[5]||(a[5]=n=>v.$emit("filter-change","model",n.target.value))},[a[16]||(a[16]=t("option",{value:""}," All ",-1)),(r(!0),i(k,null,$(s.filterOptions.models,n=>(r(),i("option",{key:n,value:n},f(n),9,ft))),128))],40,ct)]),s.hasActiveFilters?(r(),i("button",{key:0,class:"btn-clear",onClick:a[6]||(a[6]=n=>v.$emit("clear-filters"))}," Clear Filters ")):_("",!0),t("button",{class:A(["btn-clear-all",{confirming:s.confirming}]),onClick:a[7]||(a[7]=n=>v.$emit("clear-all"))},f(s.confirming?"Confirm Clear All?":"Clear All Logs"),3)])]))}},vt=O(gt,[["__scopeId","data-v-780329d3"]]),pt={class:"table-wrapper"},ht={key:0,class:"loading-overlay"},yt={class:"log-table"},bt=["onClick"],mt={key:0,class:"sort-indicator"},kt={key:0},$t=["colspan"],Ct={class:"td"},_t={class:"status-text"},Tt={class:"td font-mono text-sm"},At={class:"td font-mono text-sm"},Pt={class:"td model-cell"},Lt={class:"td"},Ot={key:1},St={class:"td"},Dt={key:1},Ft=["title"],wt={class:"td text-right"},Bt=["title"],Mt={__name:"AgentLogTable",props:{logs:{type:Array,required:!0},loading:{type:Boolean,default:!1},sortBy:{type:String,default:"started_at"},sortOrder:{type:String,default:"DESC"}},emits:["sort"],setup(s){const e=[{key:"status",label:"Status",sortable:!0},{key:"agent_type",label:"Agent Type",sortable:!0},{key:"call_type",label:"Call Type",sortable:!0},{key:"model",label:"Model",sortable:!0},{key:"session",label:"Session",sortable:!1},{key:"effort",label:"Effort",sortable:!1},{key:"total_tokens",label:"Tokens",sortable:!0},{key:"duration_ms",label:"Duration",sortable:!0},{key:"started_at",label:"Started",sortable:!0}];function y(l){switch(l){case"completed":return"dot-completed";case"error":return"dot-error";case"streaming":case"pending":return"dot-pending";default:return"dot-default"}}function h(l){const d=[];return l.inputTokens&&d.push(`Input: ${b(l.inputTokens)}`),l.outputTokens&&d.push(`Output: ${b(l.outputTokens)}`),l.thinkingTokens&&d.push(`Thinking: ${b(l.thinkingTokens)}`),l.cacheReadTokens&&d.push(`Cache Read: ${b(l.cacheReadTokens)}`),l.cacheWriteTokens&&d.push(`Cache Write: ${b(l.cacheWriteTokens)}`),d.join(`
2
2
  `)||"No token data"}function b(l){return l==null||l===0?"0":l.toLocaleString()}function v(l){if(l==null)return"—";if(l<1e3)return`${l}ms`;if(l<6e4)return`${(l/1e3).toFixed(1)}s`;const d=Math.floor(l/6e4),C=Math.floor(l%6e4/1e3);return`${d}m ${C}s`}function a(l){const d=Date.now()-l;return d<6e4?"just now":d<36e5?`${Math.floor(d/6e4)}m ago`:d<864e5?`${Math.floor(d/36e5)}h ago`:`${Math.floor(d/864e5)}d ago`}function n(l){try{if(l.metadata)return(typeof l.metadata=="string"?JSON.parse(l.metadata):l.metadata).effortLevel||null}catch{}return null}function P(l){return{auto:"Auto",low:"Low",medium:"Med",high:"High",max:"Max"}[l]||l}return(l,d)=>{const C=W("router-link");return r(),i("div",pt,[s.loading?(r(),i("div",ht,[...d[0]||(d[0]=[t("div",{class:"spinner"},null,-1)])])):_("",!0),t("table",yt,[t("thead",null,[t("tr",null,[(r(),i(k,null,$(e,o=>t("th",{key:o.key,class:A(["th",o.sortable?"sortable":""]),onClick:S=>o.sortable?l.$emit("sort",o.key):null},[F(f(o.label)+" ",1),o.sortable&&s.sortBy===o.key?(r(),i("span",mt,f(s.sortOrder==="ASC"?"↑":"↓"),1)):_("",!0)],10,bt)),64))])]),t("tbody",null,[!s.loading&&s.logs.length===0?(r(),i("tr",kt,[t("td",{colspan:e.length,class:"empty-cell"}," No agent call logs found. ",8,$t)])):_("",!0),(r(!0),i(k,null,$(s.logs,o=>(r(),i("tr",{key:o.id,class:"log-row"},[t("td",Ct,[t("span",{class:A(["status-dot",y(o.status)])},null,2),t("span",_t,f(o.status),1)]),t("td",Tt,f(o.agentType||"—"),1),t("td",At,f(o.callType||"—"),1),t("td",Pt,f(o.model||"—"),1),t("td",Lt,[o.sessionId?(r(),z(C,{key:0,to:`/sessions/${o.sessionId}`,class:"session-link"},{default:G(()=>[F(f(o.sessionName||o.sessionId),1)]),_:2},1032,["to"])):(r(),i("span",Ot,"—"))]),t("td",St,[n(o)?(r(),i("span",{key:0,class:A(["effort-badge",`effort-${n(o)}`])},f(P(n(o))),3)):(r(),i("span",Dt,"—"))]),t("td",{class:"td text-right",title:h(o)},f(b(o.totalTokens)),9,Ft),t("td",wt,f(v(o.durationMs)),1),t("td",{class:"td text-right",title:o.startedAt?new Date(o.startedAt).toLocaleString():""},f(o.startedAt?a(o.startedAt):"—"),9,Bt)]))),128))])])])}}},It=O(Mt,[["__scopeId","data-v-20d5856a"]]),Et={class:"agent-logs"},Nt={key:0,class:"error-banner"},Vt={key:1,class:"pagination-bar"},xt={class:"per-page-control"},jt=["value"],Rt=["value"],qt={class:"page-info"},Wt={class:"page-buttons"},zt=["disabled"],Gt=["disabled"],Ht={key:0,class:"page-ellipsis"},Jt=["onClick"],Ut=["disabled"],Zt=["disabled"],Qt={__name:"AgentLogsView",setup(s){const e=U(),y=B(!1),h=B(null),b=p(()=>e.logs),v=p(()=>e.pagination),a=p(()=>e.filters),n=p(()=>e.filterOptions),P=p(()=>e.perPage),l=p(()=>e.currentPage),d=p(()=>e.totalPages),C=p(()=>e.sortBy),o=p(()=>e.sortOrder),S=p(()=>e.loading),D=p(()=>e.error),M=p(()=>Object.values(e.filters).some(g=>g!=null)),I=p(()=>v.value.total===0?0:v.value.offset+1),E=p(()=>Math.min(v.value.offset+P.value,v.value.total)),N=p(()=>{const g=d.value,c=l.value;if(g<=7)return Array.from({length:g},(T,R)=>R+1);const u=[];return c<=4?u.push(1,2,3,4,5,"...",g):c>=g-3?u.push(1,"...",g-4,g-3,g-2,g-1,g):u.push(1,"...",c-1,c,c+1,"...",g),u});function V(g){C.value===g?e.setSort(g,o.value==="ASC"?"DESC":"ASC"):e.setSort(g,"DESC")}function x(g,c){const u=c.target.value;if(!u){e.setFilter(g,null);return}const T=new Date(`${u}T00:00:00Z`).getTime();e.filters[g]=T,e.currentPage=1,e.fetchLogs()}function j(){y.value?(h.value&&(clearTimeout(h.value),h.value=null),y.value=!1,e.clearAllLogs()):(y.value=!0,h.value=setTimeout(()=>{y.value=!1,h.value=null},3e3))}return H(()=>{e.fetchLogs(),e.fetchFilterOptions()}),J(()=>{h.value&&clearTimeout(h.value)}),(g,c)=>(r(),i("div",Et,[w(vt,{filters:a.value,"filter-options":n.value,"has-active-filters":M.value,confirming:y.value,onFilterChange:c[0]||(c[0]=(u,T)=>m(e).setFilter(u,T)),onDateChange:x,onClearFilters:c[1]||(c[1]=u=>m(e).clearFilters()),onClearAll:j},null,8,["filters","filter-options","has-active-filters","confirming"]),D.value?(r(),i("div",Nt,[t("span",null,f(D.value),1),t("button",{class:"btn-retry",onClick:c[2]||(c[2]=u=>m(e).fetchLogs())}," Retry ")])):_("",!0),w(It,{logs:b.value,loading:S.value,"sort-by":C.value,"sort-order":o.value,onSort:V},null,8,["logs","loading","sort-by","sort-order"]),v.value.total>0?(r(),i("div",Vt,[t("div",xt,[c[8]||(c[8]=t("label",{class:"filter-label"},"Per page",-1)),t("select",{class:"filter-select per-page-select",value:P.value,onChange:c[3]||(c[3]=u=>m(e).setPerPage(parseInt(u.target.value)))},[(r(),i(k,null,$([10,25,50,100],u=>t("option",{key:u,value:u},f(u),9,Rt)),64))],40,jt)]),t("div",qt," Showing "+f(I.value)+"–"+f(E.value)+" of "+f(v.value.total)+" logs ",1),t("div",Wt,[t("button",{class:"page-btn",disabled:l.value===1,onClick:c[4]||(c[4]=u=>m(e).setPage(1))}," « ",8,zt),t("button",{class:"page-btn",disabled:l.value===1,onClick:c[5]||(c[5]=u=>m(e).setPage(l.value-1))}," ‹ ",8,Gt),(r(!0),i(k,null,$(N.value,u=>(r(),i(k,{key:u},[u==="..."?(r(),i("span",Ht,"…")):(r(),i("button",{key:1,class:A(["page-btn",{"page-btn-active":u===l.value}]),onClick:T=>m(e).setPage(u)},f(u),11,Jt))],64))),128)),t("button",{class:"page-btn",disabled:l.value===d.value,onClick:c[6]||(c[6]=u=>m(e).setPage(l.value+1))}," › ",8,Ut),t("button",{class:"page-btn",disabled:l.value===d.value,onClick:c[7]||(c[7]=u=>m(e).setPage(d.value))}," » ",8,Zt)])])):_("",!0)]))}},Kt=O(Qt,[["__scopeId","data-v-e1df2011"]]);export{Kt as default};
@@ -0,0 +1 @@
1
+ var b=n=>{throw TypeError(n)};var g=(n,e,s)=>e.has(n)||b("Cannot "+s);var h=(n,e,s)=>(g(n,e,"read from private field"),s?s.call(n):e.get(n)),y=(n,e,s)=>e.has(n)?b("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(n):e.set(n,s),C=(n,e,s,t)=>(g(n,e,"write to private field"),t?t.call(n,s):e.set(n,s),s),l=(n,e,s)=>(g(n,e,"access private method"),s);function S(n){Object.assign(n.prototype,{async getProjects(){return this._get("/projects")},async getProject(e){return this._get(`/projects/${e}`)},async createProject(e){return this._post("/projects",e)},async updateProject(e,s){return this._put(`/projects/${e}`,s)},async deleteProject(e){return this._delete(`/projects/${e}`)}})}function j(n,e,s){for(const t of s)e[t]!==void 0&&e[t]!==null&&n.append(t,e[t])}function k(n,e,s){for(const t of s)e[t]!==void 0&&e[t]!==null&&n.append(t,String(e[t]))}function P(n,e){const s=new FormData;s.append("prompt",n.prompt),j(s,n,["name","mode","model","providerId","effortLevel","gitBranch","gitMode","templateId","parentSessionId"]),k(s,n,["thinkingEnabled","startImmediately","autoRescheduleEnabled","rescheduleOnTokenLimit","rescheduleOnServiceError"]),j(s,n,["scheduledAt","rescheduleDelayMinutes","maxRescheduleCount","maxTotalTokens","rescheduleAtTokenCount"]);for(const t of e)s.append("files",t);return s}function T(n){Object.assign(n.prototype,{async getActiveSessions(){return this._get("/sessions")},async getScheduledSessions(e=null){return this._get(this._buildQueryPath("/sessions/scheduled",{projectId:e||void 0}))},async getProjectSessions(e,s=null,t=null,{limit:r=null,offset:a=0}={}){const o={};return s!==null&&(o.archived=s),t==="starred"?o.starred=!0:t==="unstarred"&&(o.starred=!1),r!==null&&(o.limit=r,o.offset=a),this._get(this._buildQueryPath(`/projects/${e}/sessions`,o))},async createSession(e,s){const{files:t,...r}=s;if(t&&t.length>0){const a=P(r,t);return this._uploadFormData(`/projects/${e}/sessions`,a)}return this._post(`/projects/${e}/sessions`,r)},async getSession(e){return this._get(`/sessions/${e}`)},async getSessionMessages(e){return this._get(`/sessions/${e}/messages`)},async getSessionWorkLogs(e){return this._get(`/sessions/${e}/work-logs`)},async sendMessage(e,s,t=[],r=null){if(console.log(`[MODEL AUDIT - ApiClient] sendMessage called with model: "${r}"`),t&&t.length>0){const a=new FormData;a.append("content",s),r&&a.append("model",r);for(const o of t)a.append("files",o);return this._uploadFormData(`/sessions/${e}/message`,a)}return this._post(`/sessions/${e}/message`,{content:s,model:r})},async stopSession(e){return this._post(`/sessions/${e}/stop`)},async getSessionChanges(e,s="local",t=null){const r={};return s==="branch"&&(r.compareMode="branch",t&&(r.branch=t)),this._get(this._buildQueryPath(`/sessions/${e}/changes`,r))},async getSessionDefaultBranch(e){return this._get(`/sessions/${e}/default-branch`)},async getSessionFilesCount(e){return this._get(`/sessions/${e}/files-count`)},async getSessionFile(e,s){return this._get(`/sessions/${e}/file?path=${encodeURIComponent(s)}`)},async restartSession(e){return this._post(`/sessions/${e}/restart`)},async startSession(e,s,t,r){const a={};return s!==void 0&&(a.prompt=s),t!==void 0&&(a.model=t),r!==void 0&&(a.providerId=r),this._post(`/sessions/${e}/start`,Object.keys(a).length>0?a:void 0)},async updateSessionInitialPrompt(e,s){return this._put(`/sessions/${e}/initial-prompt`,{prompt:s})},async updateSession(e,s){return this._patch(`/sessions/${e}`,s)},async updateSessionPendingPrompt(e,s){return this._patch(`/sessions/${e}/pending-prompt`,{pendingPrompt:s})},async deleteSession(e){return this._delete(`/sessions/${e}`)},async archiveSession(e,{cleanup:s=!1}={}){return this._post(`/sessions/${e}/archive`,{cleanup:s})},async unarchiveSession(e){return this._post(`/sessions/${e}/unarchive`)},async toggleSessionStar(e){return this._post(`/sessions/${e}/star`)},async duplicateSession(e,s={}){return this._post(`/sessions/${e}/duplicate`,s)},async scheduleSession(e,s){return this._post(`/sessions/${e}/schedule`,s)}})}function w(n){Object.assign(n.prototype,{async getCanvasItems(e){return this._get(`/sessions/${e}/canvas`)},async getCanvasFileContent(e,s){return this._get(`/sessions/${e}/canvas/file/${encodeURIComponent(s)}/content`)},async getCanvasItemContent(e,s){return this._get(`/sessions/${e}/canvas/${s}/content`)},async getAllCanvasItems(e){return this._get(`/sessions/${e}/canvas/all`)},async uploadCanvasItem(e,s){const t=new FormData;return t.append("file",s),this._uploadFormData(`/sessions/${e}/canvas`,t)},async createCanvasItem(e,s){return this._post(`/sessions/${e}/canvas`,s)},async updateCanvasItem(e,s,t){return this._put(`/sessions/${e}/canvas/${s}`,t)},async deleteCanvasItem(e,s){return this._delete(`/sessions/${e}/canvas/${s}`)},async getCanvasTrash(e){return this._get(`/sessions/${e}/canvas-trash`)},async recoverCanvasItem(e,s){return this._post(`/sessions/${e}/canvas/${s}/recover`)},async recoverCanvasFile(e,s){return this._post(`/sessions/${e}/canvas-trash/recover-file/${encodeURIComponent(s)}`)},async permanentlyDeleteCanvasItem(e,s){return this._delete(`/sessions/${e}/canvas/${s}/permanent`)},async bulkDeleteCanvasItems(e,s){return this._post(`/sessions/${e}/canvas/bulk-delete`,{itemIds:s})},async bulkRecoverCanvasItems(e,s){return this._post(`/sessions/${e}/canvas/bulk-recover`,{itemIds:s})},async bulkPermanentlyDeleteCanvasItems(e,s){return this._delete(`/sessions/${e}/canvas/bulk-delete-permanent`,{itemIds:s})}})}function A(n){Object.assign(n.prototype,{async getProviders(){return this._get("/providers")},async getProvider(e){return this._get(`/providers/${e}`)},async createProvider(e){return this._post("/providers",e)},async updateProvider(e,s){return this._patch(`/providers/${e}`,s)},async deleteProvider(e){return this._delete(`/providers/${e}`)},async testProviderConnection(e){return this._post("/providers/test",e)},async testExistingProvider(e){return this._post(`/providers/${e}/test`)},async getProviderModels(e){return this._get(`/providers/${e}/models`)},async addProviderModel(e,s){return this._post(`/providers/${e}/models`,s)},async updateProviderModel(e,s,t){return this._patch(`/providers/${e}/models/${s}`,t)},async removeProviderModel(e,s){return this._delete(`/providers/${e}/models/${s}`)}})}function R(n){Object.assign(n.prototype,{async getAgents(){return this._get("/agents")}})}function I(n){Object.assign(n.prototype,{async getCommandButtons(e){return this._get(`/projects/${e}/command-buttons`)},async createCommandButton(e,s){return this._post(`/projects/${e}/command-buttons`,s)},async getCommandButton(e,s){return this._get(`/projects/${e}/command-buttons/${s}`)},async updateCommandButton(e,s,t){return this._patch(`/projects/${e}/command-buttons/${s}`,t)},async deleteCommandButton(e,s){return this._delete(`/projects/${e}/command-buttons/${s}`)},async runCommandButton(e,s){return this._post(`/sessions/${e}/command-buttons/${s}/run`)},async getActiveRuns(e){return this._get(`/sessions/${e}/command-buttons/runs`)},async getCommandRun(e,s){return this._get(`/sessions/${e}/command-buttons/runs/${s}`)},async getLatestRunsForProject(e){return this._get(`/projects/${e}/command-buttons/latest-runs`)},async killCommandRun(e,s){return this._post(`/sessions/${e}/command-buttons/runs/${s}/kill`)},async deleteCommandRun(e,s){return this._delete(`/sessions/${e}/command-buttons/runs/${s}`)},async deleteAllRunsForButton(e,s){return this._delete(`/sessions/${e}/command-buttons/${s}/runs/all`)}})}function O(n){Object.assign(n.prototype,{async getTokenCostWeights(){return this._get("/settings/token-weights")},async updateTokenCostWeights(e){return this._put("/settings/token-weights",e)},async resetTokenCostWeights(){return this._delete("/settings/token-weights")},async getSummarySettings(){return this._get("/settings/summary")},async updateSummarySettings(e){return this._put("/settings/summary",e)},async resetSummarySettings(){return this._delete("/settings/summary")},async getGeneralSettings(){return this._get("/settings/general")},async updateGeneralSettings(e){return this._put("/settings/general",e)},async resetGeneralSettings(){return this._delete("/settings/general")}})}function D(n){Object.assign(n.prototype,{async getConversations(e){return this._get(`/sessions/${e}/conversations`)},async createConversation(e,s=null){return this._post(`/sessions/${e}/conversations`,{name:s})},async getConversation(e,s){return this._get(`/sessions/${e}/conversations/${s}`)},async updateConversation(e,s,t){return this._patch(`/sessions/${e}/conversations/${s}`,t)},async deleteConversation(e,s){return this._delete(`/sessions/${e}/conversations/${s}`)},async branchConversation(e,s,t){return this._post(`/sessions/${e}/conversations/${s}/branch`,t)},async getConversationMessages(e,s){return this._get(`/sessions/${e}/messages?conversation_id=${s}`)}})}function F(n){Object.assign(n.prototype,{async getGlobalTemplates(){return this._get("/templates")},async createGlobalTemplate(e){return this._post("/templates",e)},async getTemplate(e){return this._get(`/templates/${e}`)},async updateTemplate(e,s){return this._patch(`/templates/${e}`,s)},async deleteTemplate(e){return this._delete(`/templates/${e}`)},async getProjectTemplates(e){return this._get(`/projects/${e}/templates`)},async createProjectTemplate(e,s){return this._post(`/projects/${e}/templates`,s)}})}function Q(n){Object.assign(n.prototype,{async getQuickResponses(e){return this._get(`/projects/${e}/quick-responses`)},async getGlobalQuickResponses(){return this._get("/quick-responses/global")},async createQuickResponse(e,s){return this._post(`/projects/${e}/quick-responses`,s)},async updateQuickResponse(e,s){return this._patch(`/quick-responses/${e}`,s)},async deleteQuickResponse(e){return this._delete(`/quick-responses/${e}`)},async reorderQuickResponses(e,s){return this._post(`/projects/${e}/quick-responses/reorder`,s)},async reorderGlobalQuickResponses(e){return this._post("/quick-responses/global/reorder",e)}})}function B(n){Object.assign(n.prototype,{async getGitStatus(e){return this._get(`/git/projects/${e}/status`)},async getWorktrees(e){return this._get(`/git/projects/${e}/worktrees`)},async detectWorktreePath(e){return this._get(this._buildQueryPath("/git/detect-worktree-path",{directory:e}))},async getSessionTodos(e,s=null){return this._get(this._buildQueryPath(`/sessions/${e}/todos`,{conversation_id:s||void 0}))},async getSessionSummary(e,s=!1){const t=s?this._buildQueryPath(`/sessions/${e}/summary`,{generate:"true"}):`/sessions/${e}/summary`;try{return await this._get(t)}catch(r){if(r.message.includes("404")||r.message.includes("not found"))return null;throw r}},async getSessionSummariesBatch(e){return!e||e.length===0?{}:this._post("/sessions/summaries/batch",{ids:e})},async generateSessionSummary(e){return this._post(`/sessions/${e}/summary`)},async getWorkflowLatestResponse(e){try{return await this._get(`/sessions/${e}/workflow-latest-response`)}catch(s){if(s.message.includes("404"))return null;throw s}},async getSessionNotes(e){return this._get(`/sessions/${e}/notes`)},async createNote(e,s){return this._post(`/sessions/${e}/notes`,{content:s})},async updateNote(e,s,t){return this._put(`/sessions/${e}/notes/${s}`,{content:t})},async deleteNote(e,s){return this._delete(`/sessions/${e}/notes/${s}`)},async browseDirectory(e=""){return this._get(this._buildQueryPath("/filesystem/browse",{path:e||void 0}))},async getSlashCommands(e){return this._get(`/commands?directory=${encodeURIComponent(e)}`)},async getSlashCommand(e,s){return this._get(`/commands/${encodeURIComponent(s)}?directory=${encodeURIComponent(e)}`)},async executeSlashCommand(e,s,t={}){return this._post(`/commands/${encodeURIComponent(s)}/execute`,{sessionId:e,args:t})},async getAgentCallLogs({limit:e,offset:s,agentType:t,callType:r,status:a,startDate:o,endDate:m,sessionId:_,model:$,sortBy:f,sortOrder:v}={}){const c={};return e!=null&&(c.limit=e),s!=null&&(c.offset=s),t&&(c.agentType=t),r&&(c.callType=r),a&&(c.status=a),o&&(c.startDate=o),m&&(c.endDate=m),_&&(c.sessionId=_),$&&(c.model=$),f&&(c.sortBy=f),v&&(c.sortOrder=v),this._get(this._buildQueryPath("/agent-calls",c))},async getAgentCallFilterOptions(){return this._get("/agent-calls/filter-options")},async deleteAllAgentCallLogs(){return this._delete("/agent-calls")},async getProjectSessionDefaults(e){return this._get(`/projects/${e}/session-defaults`)},async updateProjectSessionDefaults(e,s){return this._post(`/projects/${e}/session-defaults`,s)},async resetProjectSessionDefaults(e){return this._delete(`/projects/${e}/session-defaults`)}})}function L(n){Object.assign(n.prototype,{async getKanbanBoard(e){return this._get(`/projects/${e}/kanban`)},async deleteKanbanBoard(e){return this._delete(`/projects/${e}/kanban`)},async createKanbanLane(e,s){return this._post(`/projects/${e}/kanban/lanes`,s)},async updateKanbanLane(e,s,t){return this._patch(`/projects/${e}/kanban/lanes/${s}`,t)},async deleteKanbanLane(e,s){return this._delete(`/projects/${e}/kanban/lanes/${s}`)},async reorderKanbanLanes(e,s){return this._put(`/projects/${e}/kanban/lanes/reorder`,s)},async createKanbanCard(e,s){return this._post(`/projects/${e}/kanban/cards`,s)},async moveKanbanCard(e,s,t){return this._patch(`/projects/${e}/kanban/cards/${s}/move`,t)},async deleteKanbanCard(e,s){return this._delete(`/projects/${e}/kanban/cards/${s}`)},async reorderKanbanCards(e,s,t){return this._put(`/projects/${e}/kanban/lanes/${s}/cards/reorder`,t)}})}var p,u,d;class i{constructor(e="/api"){y(this,u);y(this,p);C(this,p,e)}get baseUrl(){return h(this,p)}async _uploadFormData(e,s){const t=await fetch(`${h(this,p)}${e}`,{method:"POST",body:s});if(!t.ok){const r=await t.json().catch(()=>({}));throw new Error(r.message||r.error||`HTTP ${t.status}`)}return t.json()}_buildQueryPath(e,s){const t=new URLSearchParams;for(const[a,o]of Object.entries(s))o!=null&&t.append(a,o);const r=t.toString();return r?`${e}?${r}`:e}_get(e){return l(this,u,d).call(this,"GET",e)}_post(e,s){return l(this,u,d).call(this,"POST",e,s)}_put(e,s){return l(this,u,d).call(this,"PUT",e,s)}_patch(e,s){return l(this,u,d).call(this,"PATCH",e,s)}_delete(e,s){return l(this,u,d).call(this,"DELETE",e,s)}}p=new WeakMap,u=new WeakSet,d=async function(e,s,t=null){const r={method:e,headers:{"Content-Type":"application/json"}};t&&e!=="GET"&&(r.body=JSON.stringify(t));const a=await fetch(`${h(this,p)}${s}`,r);if(!a.ok){const o=await a.json().catch(()=>({}));throw new Error(o.message||o.error||`HTTP ${a.status}`)}return a.status===204?null:a.json()};S(i);T(i);w(i);A(i);R(i);I(i);O(i);D(i);F(i);Q(i);B(i);L(i);const E=new i;export{E as a};
@@ -1 +1 @@
1
- import{_ as L,n as I,l as O,o as N,a,c as d,b as t,m as T,p as q,F as j,r as D,t as C,i as f,f as B,x,$ as K,k as P,G as z,d as U,q as w,v as A,j as F,V as G,y as W,A as H,E as Y,H as J}from"./index-BGAW2Nqa.js";import{u as Q,b as X}from"./EffortLevelSelector-xE3gidpq.js";import{M as Z}from"./ModelSelector-B0RdlCHT.js";import{M as ee}from"./SlashCommandWizard-C_cSgF-P.js";import{u as te}from"./SessionLogStream-DIndOyFR.js";const se={class:"template-selector"},le={class:"selector-wrapper"},ne=["disabled"],oe={key:0,label:"Project Templates"},ae=["value"],de={key:1,label:"Global Templates"},ie=["value"],ue=["disabled"],re={key:0,class:"template-preview"},ce={class:"template-prompt-preview"},me={key:0,class:"chain-indicator"},pe={key:1,class:"selector-help"},ve={key:2,class:"saving-indicator"},be={__name:"TemplateSelector",props:{sessionId:{type:String,required:!1,default:null},projectId:{type:String,required:!0},currentTemplateId:{type:String,default:null},disabled:{type:Boolean,default:!1}},emits:["update:templateId"],setup(o,{emit:M}){const n=o,k=M,p=Q(),v=I(n.currentTemplateId),u=I(!1),h=x(()=>p.loading),s=x(()=>p.projectTemplates),g=x(()=>p.globalTemplates),c=x(()=>v.value?p.getTemplateById(v.value):null),$=x(()=>{var S;if(!((S=c.value)!=null&&S.nextTemplateId))return null;const e=[];let i=c.value.nextTemplateId;const m=new Set;for(;i&&!m.has(i);){m.add(i);const l=p.getTemplateById(i);if(l)e.push(l.name),i=l.nextTemplateId;else{e.push("Unknown");break}if(e.length>=3){e.push("...");break}}return e.length>0?`Chains to: ${e.join(" → ")}`:null}),R=K(n,"currentTemplateId");O(R,e=>{v.value=e},{flush:"sync"}),N(()=>{n.projectId&&p.projectTemplates.length===0&&p.globalTemplates.length===0&&p.fetchProjectTemplates(n.projectId)});function _(e,i=100){return e?e.length<=i?e:`${e.substring(0,i)}...`:""}function E(e){var S;const i=((S=e==null?void 0:e.target)==null?void 0:S.value)||v.value,m=i===""?null:i;u.value=!0,k("update:templateId",m),setTimeout(()=>{u.value=!1},1e3)}function r(){v.value=null,E()}return(e,i)=>(a(),d("div",se,[i[3]||(i[3]=t("label",{class:"selector-label"},"Next Template",-1)),t("div",le,[T(t("select",{"onUpdate:modelValue":i[0]||(i[0]=m=>v.value=m),class:"form-input",disabled:o.disabled||h.value,onChange:E},[i[1]||(i[1]=t("option",{value:null}," Select a template to run... ",-1)),s.value.length?(a(),d("optgroup",oe,[(a(!0),d(j,null,D(s.value,m=>(a(),d("option",{key:m.id,value:m.id},C(m.name),9,ae))),128))])):f("",!0),g.value.length?(a(),d("optgroup",de,[(a(!0),d(j,null,D(g.value,m=>(a(),d("option",{key:m.id,value:m.id},C(m.name),9,ie))),128))])):f("",!0)],40,ne),[[q,v.value]]),v.value?(a(),d("button",{key:0,class:"btn-clear",title:"Clear selection",disabled:o.disabled||u.value,onClick:r}," ✕ ",8,ue)):f("",!0)]),c.value?(a(),d("div",re,[t("p",ce,C(_(c.value.prompt)),1),$.value?(a(),d("span",me,C($.value),1)):f("",!0)])):(a(),d("p",pe," When the agent finishes responding, a new session will automatically start using this template. ")),u.value?(a(),d("div",ve,[...i[2]||(i[2]=[t("span",{class:"loading-spinner"},null,-1),B(" Saving... ",-1)])])):f("",!0)]))}},he=L(be,[["__scopeId","data-v-77a4f989"]]),fe={class:"modal-content"},ge={class:"modal-header"},ke={class:"modal-title"},ye={class:"modal-body"},Te={key:0,class:"error-message"},Ce={class:"form-section"},Se={class:"form-group"},$e={class:"form-group"},xe={class:"form-group"},Ie={class:"toggle-switch"},Me={key:1,class:"form-group"},Ee=["min"],we={key:2,class:"form-section"},Re={class:"form-group"},_e={class:"toggle-switch"},Oe={key:3,class:"reschedule-settings"},Ae={class:"form-group"},Le={class:"checkbox-option"},Ve={class:"checkbox-option"},Ue={class:"form-group"},je={class:"form-group"},De={class:"form-group"},Be={class:"form-group"},Ne={key:0,class:"form-group"},Fe={class:"checkbox-option"},qe={class:"form-help"},Pe={class:"modal-footer"},ze=["disabled"],Ge={__name:"SchedulingEditModal",props:{isOpen:{type:Boolean,default:!1},session:{type:Object,default:null}},emits:["close","saved"],setup(o,{emit:M}){const n=o,k=M,p=X(),v=P(),u=I(!1),h=I(null),s=W({scheduledAtLocal:"",model:null,mode:"standard",thinkingEnabled:!1,nextTemplateId:null,autoRescheduleEnabled:!1,rescheduleDelayMinutes:15,rescheduleOnTokenLimit:!0,rescheduleOnServiceError:!0,maxRescheduleCount:null,maxTotalTokens:null,rescheduleAtTokenCount:null,resetRescheduleCount:!1}),g=x(()=>{const r=new Date;return r.setMinutes(r.getMinutes()+1),r.toISOString().slice(0,16)}),c=x(()=>{var r;return((r=n.session)==null?void 0:r.status)==="scheduled"?"Edit Scheduling Settings":"Auto-Reschedule Settings"});function $(){k("close")}function R(r){s.nextTemplateId=r}function _(r){if(!r)return"";const e=new Date(r),i=e.getFullYear(),m=String(e.getMonth()+1).padStart(2,"0"),S=String(e.getDate()).padStart(2,"0"),l=String(e.getHours()).padStart(2,"0"),b=String(e.getMinutes()).padStart(2,"0");return`${i}-${m}-${S}T${l}:${b}`}async function E(){var r;u.value=!0,h.value=null;try{const e={model:s.model,mode:s.mode,thinkingEnabled:s.thinkingEnabled,nextTemplateId:s.nextTemplateId,autoRescheduleEnabled:s.autoRescheduleEnabled,rescheduleDelayMinutes:s.rescheduleDelayMinutes,rescheduleOnTokenLimit:s.rescheduleOnTokenLimit,rescheduleOnServiceError:s.rescheduleOnServiceError,maxRescheduleCount:s.maxRescheduleCount||null,maxTotalTokens:s.maxTotalTokens||null,rescheduleAtTokenCount:s.rescheduleAtTokenCount||null};((r=n.session)==null?void 0:r.status)==="scheduled"&&s.scheduledAtLocal&&(e.scheduledAt=new Date(s.scheduledAtLocal).getTime()),s.resetRescheduleCount&&(e.rescheduleCount=0),await p.updateSessionFields(n.session.id,e),v.success("Settings saved"),k("saved"),$()}catch(e){h.value=e.message||"Failed to save settings",v.error(`Failed to save settings: ${h.value}`)}finally{u.value=!1}}return O(()=>n.isOpen,r=>{r&&n.session&&(h.value=null,s.scheduledAtLocal=_(n.session.scheduledAt),s.model=n.session.model||null,s.mode=n.session.mode||"standard",s.thinkingEnabled=n.session.thinkingEnabled||!1,s.nextTemplateId=n.session.nextTemplateId||null,s.autoRescheduleEnabled=n.session.autoRescheduleEnabled||!1,s.rescheduleDelayMinutes=n.session.rescheduleDelayMinutes||15,s.rescheduleOnTokenLimit=n.session.rescheduleOnTokenLimit??!0,s.rescheduleOnServiceError=n.session.rescheduleOnServiceError??!0,s.maxRescheduleCount=n.session.maxRescheduleCount,s.maxTotalTokens=n.session.maxTotalTokens,s.rescheduleAtTokenCount=n.session.rescheduleAtTokenCount,s.resetRescheduleCount=!1)}),(r,e)=>{var i,m,S;return a(),z(G,{to:"body"},[o.isOpen?(a(),d("div",{key:0,class:"modal-backdrop",onClick:F($,["self"])},[t("div",fe,[t("div",ge,[t("h2",ke,C(c.value),1),t("button",{class:"close-btn","aria-label":"Close",onClick:$}," × ")]),t("div",ye,[h.value?(a(),d("div",Te,C(h.value),1)):f("",!0),t("div",Ce,[e[16]||(e[16]=t("h3",{class:"section-title"}," Session Settings ",-1)),t("div",Se,[e[12]||(e[12]=t("label",{class:"form-label"},"Model",-1)),U(Z,{modelValue:s.model,"onUpdate:modelValue":e[0]||(e[0]=l=>s.model=l)},null,8,["modelValue"])]),t("div",$e,[e[13]||(e[13]=t("label",{class:"form-label"},"Mode",-1)),U(ee,{modelValue:s.mode,"onUpdate:modelValue":e[1]||(e[1]=l=>s.mode=l)},null,8,["modelValue"])]),t("div",xe,[t("label",Ie,[T(t("input",{"onUpdate:modelValue":e[2]||(e[2]=l=>s.thinkingEnabled=l),type:"checkbox"},null,512),[[w,s.thinkingEnabled]]),e[14]||(e[14]=t("span",{class:"toggle-slider"},null,-1)),e[15]||(e[15]=t("span",{class:"toggle-label"},"Extended Thinking",-1))])])]),((i=o.session)==null?void 0:i.status)==="scheduled"?(a(),d("div",Me,[e[17]||(e[17]=t("label",{for:"scheduled-at",class:"form-label"},"Scheduled Time",-1)),T(t("input",{id:"scheduled-at","onUpdate:modelValue":e[3]||(e[3]=l=>s.scheduledAtLocal=l),type:"datetime-local",min:g.value,class:"form-input"},null,8,Ee),[[A,s.scheduledAtLocal]])])):f("",!0),((m=o.session)==null?void 0:m.status)==="scheduled"?(a(),d("div",we,[e[18]||(e[18]=t("h3",{class:"section-title"}," Template Chain ",-1)),U(he,{"session-id":o.session.id,"project-id":o.session.projectId,"current-template-id":s.nextTemplateId,disabled:u.value,"onUpdate:templateId":R},null,8,["session-id","project-id","current-template-id","disabled"])])):f("",!0),t("div",Re,[t("label",_e,[T(t("input",{"onUpdate:modelValue":e[4]||(e[4]=l=>s.autoRescheduleEnabled=l),type:"checkbox"},null,512),[[w,s.autoRescheduleEnabled]]),e[19]||(e[19]=t("span",{class:"toggle-slider"},null,-1)),e[20]||(e[20]=t("span",{class:"toggle-label"},"Auto-reschedule on errors",-1))])]),s.autoRescheduleEnabled?(a(),d("div",Oe,[t("div",Ae,[e[23]||(e[23]=t("p",{class:"settings-label"}," Reschedule Triggers ",-1)),t("label",Le,[T(t("input",{"onUpdate:modelValue":e[5]||(e[5]=l=>s.rescheduleOnTokenLimit=l),type:"checkbox"},null,512),[[w,s.rescheduleOnTokenLimit]]),e[21]||(e[21]=t("span",null,"Token limit errors",-1))]),t("label",Ve,[T(t("input",{"onUpdate:modelValue":e[6]||(e[6]=l=>s.rescheduleOnServiceError=l),type:"checkbox"},null,512),[[w,s.rescheduleOnServiceError]]),e[22]||(e[22]=t("span",null,"Service unavailability",-1))])]),t("div",Ue,[e[25]||(e[25]=t("label",{class:"form-label"},"Reschedule Delay",-1)),T(t("select",{"onUpdate:modelValue":e[7]||(e[7]=l=>s.rescheduleDelayMinutes=l),class:"form-input"},[...e[24]||(e[24]=[t("option",{value:5}," 5 minutes ",-1),t("option",{value:15}," 15 minutes ",-1),t("option",{value:30}," 30 minutes ",-1),t("option",{value:60}," 1 hour ",-1),t("option",{value:120}," 2 hours ",-1)])],512),[[q,s.rescheduleDelayMinutes,void 0,{number:!0}]])]),t("div",je,[e[26]||(e[26]=t("label",{class:"form-label"},"Max Reschedule Count",-1)),T(t("input",{"onUpdate:modelValue":e[8]||(e[8]=l=>s.maxRescheduleCount=l),type:"number",min:"1",max:"100",class:"form-input",placeholder:"Unlimited"},null,512),[[A,s.maxRescheduleCount,void 0,{number:!0}]])]),t("div",De,[e[27]||(e[27]=t("label",{class:"form-label"},"Max Total Tokens",-1)),T(t("input",{"onUpdate:modelValue":e[9]||(e[9]=l=>s.maxTotalTokens=l),type:"number",min:"1000",step:"1000",class:"form-input",placeholder:"Unlimited"},null,512),[[A,s.maxTotalTokens,void 0,{number:!0}]])]),t("div",Be,[e[28]||(e[28]=t("label",{class:"form-label"},"Reschedule At Token Count",-1)),T(t("input",{"onUpdate:modelValue":e[10]||(e[10]=l=>s.rescheduleAtTokenCount=l),type:"number",min:"10000",step:"10000",class:"form-input",placeholder:"None"},null,512),[[A,s.rescheduleAtTokenCount,void 0,{number:!0}]])]),((S=o.session)==null?void 0:S.rescheduleCount)>0?(a(),d("div",Ne,[t("label",Fe,[T(t("input",{"onUpdate:modelValue":e[11]||(e[11]=l=>s.resetRescheduleCount=l),type:"checkbox"},null,512),[[w,s.resetRescheduleCount]]),e[29]||(e[29]=t("span",null,"Reset reschedule count to 0",-1))]),t("p",qe," Current count: "+C(o.session.rescheduleCount),1)])):f("",!0)])):f("",!0)]),t("div",Pe,[t("button",{class:"btn btn-secondary",onClick:$}," Cancel "),t("button",{class:"btn btn-primary",disabled:u.value,onClick:E},C(u.value?"Updating...":"Update"),9,ze)])])])):f("",!0)])}}},Mt=L(Ge,[["__scopeId","data-v-e1ffc2da"]]),He={class:"modal-content",role:"dialog","aria-labelledby":"modal-title"},Ke={class:"modal-body"},We={class:"moving-info"},Ye={class:"moving-session-name"},Je={key:0,class:"empty-state"},Qe={key:1,class:"lanes-list"},Xe={class:"lane-label"},Ze=["name","value","disabled","aria-disabled","aria-label"],et={class:"lane-info"},tt={class:"lane-name"},st={key:0,class:"lane-current-badge"},lt={key:1,class:"lane-automation-icon",title:"Automation enabled"},nt={key:2,class:"automation-option"},ot={class:"checkbox-label"},at={class:"modal-footer"},dt=["disabled"],it=["disabled","aria-label"],ut=["disabled"],rt={__name:"MoveCardModal",props:{isOpen:Boolean,projectId:{type:String,required:!0},cardId:{type:String,required:!0},currentLaneId:{type:String,required:!0},sessionName:{type:String,default:""}},emits:["update:isOpen","close","moved"],setup(o,{emit:M}){const n=o,k=M,p=te(),v=P(),u=I(null),h=I(!0),s=I(!1),g=I(!1),c=x(()=>{var l;return((l=p.board)==null?void 0:l.lanes)||[]}),$=x(()=>n.sessionName?n.sessionName:n.cardId||"Unnamed session"),R=x(()=>u.value&&c.value.find(l=>l.id===u.value)||null),_=x(()=>R.value?r(R.value):!1),E=x(()=>u.value&&u.value!==n.currentLaneId);function r(l){return l?!!(l.onEnterTemplateId||l.onEnterPrompt):!1}function e(){k("update:isOpen",!1),k("close"),u.value=null,h.value=!0}async function i(){if(!(!E.value||!n.cardId)){s.value=!0;try{await p.moveCard(n.projectId,n.cardId,u.value,{runOnEnterTemplate:h.value}),v.success("Card moved successfully"),k("moved"),e()}catch(l){console.error("Failed to move card:",l),v.error(l.message||"Failed to move card")}finally{s.value=!1}}}async function m(){if(confirm("Remove this session from the board?")){g.value=!0;try{await p.removeCard(n.projectId,n.cardId),v.success("Session removed from board"),k("close")}catch(l){console.error("Failed to remove card:",l),v.error(l.message||"Failed to remove session")}finally{g.value=!1}}}O(u,(l,b)=>{if(l!==b){const y=c.value.find(V=>V.id===l);h.value=r(y)}}),O(()=>n.isOpen,l=>{l&&(u.value=null,h.value=!0)});function S(l){l.key==="Escape"&&n.isOpen&&e()}return N(()=>{document.addEventListener("keydown",S)}),H(()=>{document.removeEventListener("keydown",S)}),(l,b)=>o.isOpen?(a(),d("div",{key:0,class:"modal-backdrop",onClick:F(e,["self"])},[t("div",He,[t("div",{class:"modal-header"},[b[2]||(b[2]=t("h2",{id:"modal-title",class:"modal-title"}," Move to Lane ",-1)),t("button",{class:"close-btn","aria-label":"Close modal",onClick:e}," × ")]),t("div",Ke,[t("div",We,[b[3]||(b[3]=t("span",{class:"moving-label"},"Moving:",-1)),t("span",Ye,C($.value),1)]),c.value.length===0?(a(),d("div",Je,[...b[4]||(b[4]=[t("p",null,"No lanes available",-1)])])):(a(),d("div",Qe,[(a(!0),d(j,null,D(c.value,y=>(a(),d("div",{key:y.id,class:Y(["lane-row",{"lane-row-current":y.id===o.currentLaneId,"lane-row-disabled":y.id===o.currentLaneId}])},[t("label",Xe,[T(t("input",{"onUpdate:modelValue":b[0]||(b[0]=V=>u.value=V),type:"radio",name:`lane-${o.cardId}`,value:y.id,disabled:y.id===o.currentLaneId,"aria-disabled":y.id===o.currentLaneId,"aria-label":`Move to ${y.name}`},null,8,Ze),[[J,u.value]]),t("span",et,[t("span",tt,C(y.name),1),y.id===o.currentLaneId?(a(),d("span",st,"(current)")):f("",!0),r(y)?(a(),d("span",lt,[...b[5]||(b[5]=[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"14",viewBox:"0 0 24 24",fill:"currentColor"},[t("path",{d:"M13 10V3L4 14h7v7l9-11h-7z"})],-1)])])):f("",!0)])])],2))),128))])),_.value?(a(),d("div",nt,[t("label",ot,[T(t("input",{"onUpdate:modelValue":b[1]||(b[1]=y=>h.value=y),type:"checkbox","aria-label":"Run automation on entry"},null,512),[[w,h.value]]),b[6]||(b[6]=t("span",null,"Run automation on entry",-1))])])):f("",!0)]),t("div",at,[t("button",{class:"btn btn-secondary",disabled:g.value,onClick:e}," Cancel ",8,dt),t("button",{class:"btn btn-danger",disabled:g.value,"aria-label":`Remove ${$.value} from board`,onClick:m},C(g.value?"Removing...":"Remove from Board"),9,it),t("button",{class:"btn btn-primary",disabled:!E.value||s.value||g.value,"aria-label":"Move card to selected lane",onClick:i},C(s.value?"Moving...":"Move"),9,ut)])])])):f("",!0)}},Et=L(rt,[["__scopeId","data-v-bddc7788"]]),ct={class:"modal-content",role:"dialog","aria-labelledby":"archive-modal-title"},mt={class:"modal-header"},pt=["disabled"],vt={class:"modal-body"},bt={class:"confirm-message"},ht={key:0,class:"cleanup-option"},ft={class:"checkbox-label"},gt={class:"modal-footer"},kt=["disabled"],yt=["disabled"],Tt={__name:"ArchiveConfirmModal",props:{isOpen:{type:Boolean,default:!1},sessionName:{type:String,default:"this session"},hasCleanupScript:{type:Boolean,default:!1},loading:{type:Boolean,default:!1}},emits:["confirm","cancel"],setup(o,{emit:M}){const n=o,k=M,p=I(!0);O(()=>n.isOpen,g=>{g&&(p.value=!0)});function v(){k("confirm",p.value)}function u(){n.loading||k("cancel")}function h(){n.loading||k("cancel")}function s(g){g.key==="Escape"&&n.isOpen&&!n.loading&&k("cancel")}return N(()=>{document.addEventListener("keydown",s)}),H(()=>{document.removeEventListener("keydown",s)}),(g,c)=>(a(),z(G,{to:"body"},[o.isOpen?(a(),d("div",{key:0,class:"modal-backdrop",onClick:F(h,["self"])},[t("div",ct,[t("div",mt,[c[1]||(c[1]=t("h2",{id:"archive-modal-title",class:"modal-title"}," Archive Session ",-1)),t("button",{class:"close-btn","aria-label":"Close modal",disabled:o.loading,onClick:u}," × ",8,pt)]),t("div",vt,[t("p",bt,[c[2]||(c[2]=B(" Are you sure you want to archive ",-1)),t("strong",null,C(o.sessionName),1),c[3]||(c[3]=B("? ",-1))]),o.hasCleanupScript?(a(),d("div",ht,[t("label",ft,[T(t("input",{"onUpdate:modelValue":c[0]||(c[0]=$=>p.value=$),type:"checkbox","aria-label":"Run git worktree cleanup"},null,512),[[w,p.value]]),c[4]||(c[4]=t("span",null,"Run git worktree cleanup",-1))])])):f("",!0)]),t("div",gt,[t("button",{class:"btn btn-secondary",disabled:o.loading,onClick:u}," Cancel ",8,kt),t("button",{class:"btn btn-primary",disabled:o.loading,onClick:v},C(o.loading?"Archiving...":"Archive"),9,yt)])])])):f("",!0)]))}},wt=L(Tt,[["__scopeId","data-v-140e797f"]]);export{wt as A,Et as M,Mt as S,he as T};
1
+ import{_ as L,n as I,l as O,o as N,a,c as d,b as t,m as T,p as q,F as j,r as D,t as C,i as f,f as B,x,Z as K,k as P,G as z,d as V,q as w,v as A,j as F,U as G,y as W,A as H,E as Y,H as Z}from"./index-B6G18FqB.js";import{u as J,b as Q}from"./EffortLevelSelector-C2378L8e.js";import{M as X}from"./ModelSelector-BMpR0DPr.js";import{M as ee}from"./SlashCommandWizard-DmTyNG9O.js";import{u as te}from"./SessionLogStream-DpUE6Xsh.js";const se={class:"template-selector"},le={class:"selector-wrapper"},ne=["disabled"],oe={key:0,label:"Project Templates"},ae=["value"],de={key:1,label:"Global Templates"},ie=["value"],ue=["disabled"],re={key:0,class:"template-preview"},ce={class:"template-prompt-preview"},me={key:0,class:"chain-indicator"},pe={key:1,class:"selector-help"},ve={key:2,class:"saving-indicator"},be={__name:"TemplateSelector",props:{sessionId:{type:String,required:!1,default:null},projectId:{type:String,required:!0},currentTemplateId:{type:String,default:null},disabled:{type:Boolean,default:!1}},emits:["update:templateId"],setup(o,{emit:M}){const n=o,k=M,p=J(),v=I(n.currentTemplateId),u=I(!1),h=x(()=>p.loading),s=x(()=>p.projectTemplates),g=x(()=>p.globalTemplates),c=x(()=>v.value?p.getTemplateById(v.value):null),$=x(()=>{var S;if(!((S=c.value)!=null&&S.nextTemplateId))return null;const e=[];let i=c.value.nextTemplateId;const m=new Set;for(;i&&!m.has(i);){m.add(i);const l=p.getTemplateById(i);if(l)e.push(l.name),i=l.nextTemplateId;else{e.push("Unknown");break}if(e.length>=3){e.push("...");break}}return e.length>0?`Chains to: ${e.join(" → ")}`:null}),R=K(n,"currentTemplateId");O(R,e=>{v.value=e},{flush:"sync"}),N(()=>{n.projectId&&p.projectTemplates.length===0&&p.globalTemplates.length===0&&p.fetchProjectTemplates(n.projectId)});function _(e,i=100){return e?e.length<=i?e:`${e.substring(0,i)}...`:""}function E(e){var S;const i=((S=e==null?void 0:e.target)==null?void 0:S.value)||v.value,m=i===""?null:i;u.value=!0,k("update:templateId",m),setTimeout(()=>{u.value=!1},1e3)}function r(){v.value=null,E()}return(e,i)=>(a(),d("div",se,[i[3]||(i[3]=t("label",{class:"selector-label"},"Next Template",-1)),t("div",le,[T(t("select",{"onUpdate:modelValue":i[0]||(i[0]=m=>v.value=m),class:"form-input",disabled:o.disabled||h.value,onChange:E},[i[1]||(i[1]=t("option",{value:null}," Select a template to run... ",-1)),s.value.length?(a(),d("optgroup",oe,[(a(!0),d(j,null,D(s.value,m=>(a(),d("option",{key:m.id,value:m.id},C(m.name),9,ae))),128))])):f("",!0),g.value.length?(a(),d("optgroup",de,[(a(!0),d(j,null,D(g.value,m=>(a(),d("option",{key:m.id,value:m.id},C(m.name),9,ie))),128))])):f("",!0)],40,ne),[[q,v.value]]),v.value?(a(),d("button",{key:0,class:"btn-clear",title:"Clear selection",disabled:o.disabled||u.value,onClick:r}," ✕ ",8,ue)):f("",!0)]),c.value?(a(),d("div",re,[t("p",ce,C(_(c.value.prompt)),1),$.value?(a(),d("span",me,C($.value),1)):f("",!0)])):(a(),d("p",pe," When the agent finishes responding, a new session will automatically start using this template. ")),u.value?(a(),d("div",ve,[...i[2]||(i[2]=[t("span",{class:"loading-spinner"},null,-1),B(" Saving... ",-1)])])):f("",!0)]))}},he=L(be,[["__scopeId","data-v-77a4f989"]]),fe={class:"modal-content"},ge={class:"modal-header"},ke={class:"modal-title"},ye={class:"modal-body"},Te={key:0,class:"error-message"},Ce={class:"form-section"},Se={class:"form-group"},$e={class:"form-group"},xe={class:"form-group"},Ie={class:"toggle-switch"},Me={key:1,class:"form-group"},Ee=["min"],we={key:2,class:"form-section"},Re={class:"form-group"},_e={class:"toggle-switch"},Oe={key:3,class:"reschedule-settings"},Ae={class:"form-group"},Le={class:"checkbox-option"},Ue={class:"checkbox-option"},Ve={class:"form-group"},je={class:"form-group"},De={class:"form-group"},Be={class:"form-group"},Ne={key:0,class:"form-group"},Fe={class:"checkbox-option"},qe={class:"form-help"},Pe={class:"modal-footer"},ze=["disabled"],Ge={__name:"SchedulingEditModal",props:{isOpen:{type:Boolean,default:!1},session:{type:Object,default:null}},emits:["close","saved"],setup(o,{emit:M}){const n=o,k=M,p=Q(),v=P(),u=I(!1),h=I(null),s=W({scheduledAtLocal:"",model:null,mode:"standard",thinkingEnabled:!1,nextTemplateId:null,autoRescheduleEnabled:!1,rescheduleDelayMinutes:15,rescheduleOnTokenLimit:!0,rescheduleOnServiceError:!0,maxRescheduleCount:null,maxTotalTokens:null,rescheduleAtTokenCount:null,resetRescheduleCount:!1}),g=x(()=>{const r=new Date;return r.setMinutes(r.getMinutes()+1),r.toISOString().slice(0,16)}),c=x(()=>{var r;return((r=n.session)==null?void 0:r.status)==="scheduled"?"Edit Scheduling Settings":"Auto-Reschedule Settings"});function $(){k("close")}function R(r){s.nextTemplateId=r}function _(r){if(!r)return"";const e=new Date(r),i=e.getFullYear(),m=String(e.getMonth()+1).padStart(2,"0"),S=String(e.getDate()).padStart(2,"0"),l=String(e.getHours()).padStart(2,"0"),b=String(e.getMinutes()).padStart(2,"0");return`${i}-${m}-${S}T${l}:${b}`}async function E(){var r;u.value=!0,h.value=null;try{const e={model:s.model,mode:s.mode,thinkingEnabled:s.thinkingEnabled,nextTemplateId:s.nextTemplateId,autoRescheduleEnabled:s.autoRescheduleEnabled,rescheduleDelayMinutes:s.rescheduleDelayMinutes,rescheduleOnTokenLimit:s.rescheduleOnTokenLimit,rescheduleOnServiceError:s.rescheduleOnServiceError,maxRescheduleCount:s.maxRescheduleCount||null,maxTotalTokens:s.maxTotalTokens||null,rescheduleAtTokenCount:s.rescheduleAtTokenCount||null};((r=n.session)==null?void 0:r.status)==="scheduled"&&s.scheduledAtLocal&&(e.scheduledAt=new Date(s.scheduledAtLocal).getTime()),s.resetRescheduleCount&&(e.rescheduleCount=0),await p.updateSessionFields(n.session.id,e),v.success("Settings saved"),k("saved"),$()}catch(e){h.value=e.message||"Failed to save settings",v.error(`Failed to save settings: ${h.value}`)}finally{u.value=!1}}return O(()=>n.isOpen,r=>{r&&n.session&&(h.value=null,s.scheduledAtLocal=_(n.session.scheduledAt),s.model=n.session.model||null,s.mode=n.session.mode||"standard",s.thinkingEnabled=n.session.thinkingEnabled||!1,s.nextTemplateId=n.session.nextTemplateId||null,s.autoRescheduleEnabled=n.session.autoRescheduleEnabled||!1,s.rescheduleDelayMinutes=n.session.rescheduleDelayMinutes||15,s.rescheduleOnTokenLimit=n.session.rescheduleOnTokenLimit??!0,s.rescheduleOnServiceError=n.session.rescheduleOnServiceError??!0,s.maxRescheduleCount=n.session.maxRescheduleCount,s.maxTotalTokens=n.session.maxTotalTokens,s.rescheduleAtTokenCount=n.session.rescheduleAtTokenCount,s.resetRescheduleCount=!1)}),(r,e)=>{var i,m,S;return a(),z(G,{to:"body"},[o.isOpen?(a(),d("div",{key:0,class:"modal-backdrop",onClick:F($,["self"])},[t("div",fe,[t("div",ge,[t("h2",ke,C(c.value),1),t("button",{class:"close-btn","aria-label":"Close",onClick:$}," × ")]),t("div",ye,[h.value?(a(),d("div",Te,C(h.value),1)):f("",!0),t("div",Ce,[e[16]||(e[16]=t("h3",{class:"section-title"}," Session Settings ",-1)),t("div",Se,[e[12]||(e[12]=t("label",{class:"form-label"},"Model",-1)),V(X,{modelValue:s.model,"onUpdate:modelValue":e[0]||(e[0]=l=>s.model=l)},null,8,["modelValue"])]),t("div",$e,[e[13]||(e[13]=t("label",{class:"form-label"},"Mode",-1)),V(ee,{modelValue:s.mode,"onUpdate:modelValue":e[1]||(e[1]=l=>s.mode=l)},null,8,["modelValue"])]),t("div",xe,[t("label",Ie,[T(t("input",{"onUpdate:modelValue":e[2]||(e[2]=l=>s.thinkingEnabled=l),type:"checkbox"},null,512),[[w,s.thinkingEnabled]]),e[14]||(e[14]=t("span",{class:"toggle-slider"},null,-1)),e[15]||(e[15]=t("span",{class:"toggle-label"},"Extended Thinking",-1))])])]),((i=o.session)==null?void 0:i.status)==="scheduled"?(a(),d("div",Me,[e[17]||(e[17]=t("label",{for:"scheduled-at",class:"form-label"},"Scheduled Time",-1)),T(t("input",{id:"scheduled-at","onUpdate:modelValue":e[3]||(e[3]=l=>s.scheduledAtLocal=l),type:"datetime-local",min:g.value,class:"form-input"},null,8,Ee),[[A,s.scheduledAtLocal]])])):f("",!0),((m=o.session)==null?void 0:m.status)==="scheduled"?(a(),d("div",we,[e[18]||(e[18]=t("h3",{class:"section-title"}," Template Chain ",-1)),V(he,{"session-id":o.session.id,"project-id":o.session.projectId,"current-template-id":s.nextTemplateId,disabled:u.value,"onUpdate:templateId":R},null,8,["session-id","project-id","current-template-id","disabled"])])):f("",!0),t("div",Re,[t("label",_e,[T(t("input",{"onUpdate:modelValue":e[4]||(e[4]=l=>s.autoRescheduleEnabled=l),type:"checkbox"},null,512),[[w,s.autoRescheduleEnabled]]),e[19]||(e[19]=t("span",{class:"toggle-slider"},null,-1)),e[20]||(e[20]=t("span",{class:"toggle-label"},"Auto-reschedule on errors",-1))])]),s.autoRescheduleEnabled?(a(),d("div",Oe,[t("div",Ae,[e[23]||(e[23]=t("p",{class:"settings-label"}," Reschedule Triggers ",-1)),t("label",Le,[T(t("input",{"onUpdate:modelValue":e[5]||(e[5]=l=>s.rescheduleOnTokenLimit=l),type:"checkbox"},null,512),[[w,s.rescheduleOnTokenLimit]]),e[21]||(e[21]=t("span",null,"Token limit errors",-1))]),t("label",Ue,[T(t("input",{"onUpdate:modelValue":e[6]||(e[6]=l=>s.rescheduleOnServiceError=l),type:"checkbox"},null,512),[[w,s.rescheduleOnServiceError]]),e[22]||(e[22]=t("span",null,"Service unavailability",-1))])]),t("div",Ve,[e[25]||(e[25]=t("label",{class:"form-label"},"Reschedule Delay",-1)),T(t("select",{"onUpdate:modelValue":e[7]||(e[7]=l=>s.rescheduleDelayMinutes=l),class:"form-input"},[...e[24]||(e[24]=[t("option",{value:5}," 5 minutes ",-1),t("option",{value:15}," 15 minutes ",-1),t("option",{value:30}," 30 minutes ",-1),t("option",{value:60}," 1 hour ",-1),t("option",{value:120}," 2 hours ",-1)])],512),[[q,s.rescheduleDelayMinutes,void 0,{number:!0}]])]),t("div",je,[e[26]||(e[26]=t("label",{class:"form-label"},"Max Reschedule Count",-1)),T(t("input",{"onUpdate:modelValue":e[8]||(e[8]=l=>s.maxRescheduleCount=l),type:"number",min:"1",max:"100",class:"form-input",placeholder:"Unlimited"},null,512),[[A,s.maxRescheduleCount,void 0,{number:!0}]])]),t("div",De,[e[27]||(e[27]=t("label",{class:"form-label"},"Max Total Tokens",-1)),T(t("input",{"onUpdate:modelValue":e[9]||(e[9]=l=>s.maxTotalTokens=l),type:"number",min:"1000",step:"1000",class:"form-input",placeholder:"Unlimited"},null,512),[[A,s.maxTotalTokens,void 0,{number:!0}]])]),t("div",Be,[e[28]||(e[28]=t("label",{class:"form-label"},"Reschedule At Token Count",-1)),T(t("input",{"onUpdate:modelValue":e[10]||(e[10]=l=>s.rescheduleAtTokenCount=l),type:"number",min:"10000",step:"10000",class:"form-input",placeholder:"None"},null,512),[[A,s.rescheduleAtTokenCount,void 0,{number:!0}]])]),((S=o.session)==null?void 0:S.rescheduleCount)>0?(a(),d("div",Ne,[t("label",Fe,[T(t("input",{"onUpdate:modelValue":e[11]||(e[11]=l=>s.resetRescheduleCount=l),type:"checkbox"},null,512),[[w,s.resetRescheduleCount]]),e[29]||(e[29]=t("span",null,"Reset reschedule count to 0",-1))]),t("p",qe," Current count: "+C(o.session.rescheduleCount),1)])):f("",!0)])):f("",!0)]),t("div",Pe,[t("button",{class:"btn btn-secondary",onClick:$}," Cancel "),t("button",{class:"btn btn-primary",disabled:u.value,onClick:E},C(u.value?"Updating...":"Update"),9,ze)])])])):f("",!0)])}}},Mt=L(Ge,[["__scopeId","data-v-e1ffc2da"]]),He={class:"modal-content",role:"dialog","aria-labelledby":"modal-title"},Ke={class:"modal-body"},We={class:"moving-info"},Ye={class:"moving-session-name"},Ze={key:0,class:"empty-state"},Je={key:1,class:"lanes-list"},Qe={class:"lane-label"},Xe=["name","value","disabled","aria-disabled","aria-label"],et={class:"lane-info"},tt={class:"lane-name"},st={key:0,class:"lane-current-badge"},lt={key:1,class:"lane-automation-icon",title:"Automation enabled"},nt={key:2,class:"automation-option"},ot={class:"checkbox-label"},at={class:"modal-footer"},dt=["disabled"],it=["disabled","aria-label"],ut=["disabled"],rt={__name:"MoveCardModal",props:{isOpen:Boolean,projectId:{type:String,required:!0},cardId:{type:String,required:!0},currentLaneId:{type:String,required:!0},sessionName:{type:String,default:""}},emits:["update:isOpen","close","moved"],setup(o,{emit:M}){const n=o,k=M,p=te(),v=P(),u=I(null),h=I(!0),s=I(!1),g=I(!1),c=x(()=>{var l;return((l=p.board)==null?void 0:l.lanes)||[]}),$=x(()=>n.sessionName?n.sessionName:n.cardId||"Unnamed session"),R=x(()=>u.value&&c.value.find(l=>l.id===u.value)||null),_=x(()=>R.value?r(R.value):!1),E=x(()=>u.value&&u.value!==n.currentLaneId);function r(l){return l?!!(l.onEnterTemplateId||l.onEnterPrompt):!1}function e(){k("update:isOpen",!1),k("close"),u.value=null,h.value=!0}async function i(){if(!(!E.value||!n.cardId)){s.value=!0;try{await p.moveCard(n.projectId,n.cardId,u.value,{runOnEnterTemplate:h.value}),v.success("Card moved successfully"),k("moved"),e()}catch(l){console.error("Failed to move card:",l),v.error(l.message||"Failed to move card")}finally{s.value=!1}}}async function m(){if(confirm("Remove this session from the board?")){g.value=!0;try{await p.removeCard(n.projectId,n.cardId),v.success("Session removed from board"),k("close")}catch(l){console.error("Failed to remove card:",l),v.error(l.message||"Failed to remove session")}finally{g.value=!1}}}O(u,(l,b)=>{if(l!==b){const y=c.value.find(U=>U.id===l);h.value=r(y)}}),O(()=>n.isOpen,l=>{l&&(u.value=null,h.value=!0)});function S(l){l.key==="Escape"&&n.isOpen&&e()}return N(()=>{document.addEventListener("keydown",S)}),H(()=>{document.removeEventListener("keydown",S)}),(l,b)=>o.isOpen?(a(),d("div",{key:0,class:"modal-backdrop",onClick:F(e,["self"])},[t("div",He,[t("div",{class:"modal-header"},[b[2]||(b[2]=t("h2",{id:"modal-title",class:"modal-title"}," Move to Lane ",-1)),t("button",{class:"close-btn","aria-label":"Close modal",onClick:e}," × ")]),t("div",Ke,[t("div",We,[b[3]||(b[3]=t("span",{class:"moving-label"},"Moving:",-1)),t("span",Ye,C($.value),1)]),c.value.length===0?(a(),d("div",Ze,[...b[4]||(b[4]=[t("p",null,"No lanes available",-1)])])):(a(),d("div",Je,[(a(!0),d(j,null,D(c.value,y=>(a(),d("div",{key:y.id,class:Y(["lane-row",{"lane-row-current":y.id===o.currentLaneId,"lane-row-disabled":y.id===o.currentLaneId}])},[t("label",Qe,[T(t("input",{"onUpdate:modelValue":b[0]||(b[0]=U=>u.value=U),type:"radio",name:`lane-${o.cardId}`,value:y.id,disabled:y.id===o.currentLaneId,"aria-disabled":y.id===o.currentLaneId,"aria-label":`Move to ${y.name}`},null,8,Xe),[[Z,u.value]]),t("span",et,[t("span",tt,C(y.name),1),y.id===o.currentLaneId?(a(),d("span",st,"(current)")):f("",!0),r(y)?(a(),d("span",lt,[...b[5]||(b[5]=[t("svg",{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"14",viewBox:"0 0 24 24",fill:"currentColor"},[t("path",{d:"M13 10V3L4 14h7v7l9-11h-7z"})],-1)])])):f("",!0)])])],2))),128))])),_.value?(a(),d("div",nt,[t("label",ot,[T(t("input",{"onUpdate:modelValue":b[1]||(b[1]=y=>h.value=y),type:"checkbox","aria-label":"Run automation on entry"},null,512),[[w,h.value]]),b[6]||(b[6]=t("span",null,"Run automation on entry",-1))])])):f("",!0)]),t("div",at,[t("button",{class:"btn btn-secondary",disabled:g.value,onClick:e}," Cancel ",8,dt),t("button",{class:"btn btn-danger",disabled:g.value,"aria-label":`Remove ${$.value} from board`,onClick:m},C(g.value?"Removing...":"Remove from Board"),9,it),t("button",{class:"btn btn-primary",disabled:!E.value||s.value||g.value,"aria-label":"Move card to selected lane",onClick:i},C(s.value?"Moving...":"Move"),9,ut)])])])):f("",!0)}},Et=L(rt,[["__scopeId","data-v-bddc7788"]]),ct={class:"modal-content",role:"dialog","aria-labelledby":"archive-modal-title"},mt={class:"modal-header"},pt=["disabled"],vt={class:"modal-body"},bt={class:"confirm-message"},ht={key:0,class:"cleanup-option"},ft={class:"checkbox-label"},gt={class:"modal-footer"},kt=["disabled"],yt=["disabled"],Tt={__name:"ArchiveConfirmModal",props:{isOpen:{type:Boolean,default:!1},sessionName:{type:String,default:"this session"},hasCleanupScript:{type:Boolean,default:!1},loading:{type:Boolean,default:!1}},emits:["confirm","cancel"],setup(o,{emit:M}){const n=o,k=M,p=I(!0);O(()=>n.isOpen,g=>{g&&(p.value=!0)});function v(){k("confirm",p.value)}function u(){n.loading||k("cancel")}function h(){n.loading||k("cancel")}function s(g){g.key==="Escape"&&n.isOpen&&!n.loading&&k("cancel")}return N(()=>{document.addEventListener("keydown",s)}),H(()=>{document.removeEventListener("keydown",s)}),(g,c)=>(a(),z(G,{to:"body"},[o.isOpen?(a(),d("div",{key:0,class:"modal-backdrop",onClick:F(h,["self"])},[t("div",ct,[t("div",mt,[c[1]||(c[1]=t("h2",{id:"archive-modal-title",class:"modal-title"}," Archive Session ",-1)),t("button",{class:"close-btn","aria-label":"Close modal",disabled:o.loading,onClick:u}," × ",8,pt)]),t("div",vt,[t("p",bt,[c[2]||(c[2]=B(" Are you sure you want to archive ",-1)),t("strong",null,C(o.sessionName),1),c[3]||(c[3]=B("? ",-1))]),o.hasCleanupScript?(a(),d("div",ht,[t("label",ft,[T(t("input",{"onUpdate:modelValue":c[0]||(c[0]=$=>p.value=$),type:"checkbox","aria-label":"Run git worktree cleanup"},null,512),[[w,p.value]]),c[4]||(c[4]=t("span",null,"Run git worktree cleanup",-1))])])):f("",!0)]),t("div",gt,[t("button",{class:"btn btn-secondary",disabled:o.loading,onClick:u}," Cancel ",8,kt),t("button",{class:"btn btn-primary",disabled:o.loading,onClick:v},C(o.loading?"Archiving...":"Archive"),9,yt)])])])):f("",!0)]))}},wt=L(Tt,[["__scopeId","data-v-140e797f"]]);export{wt as A,Et as M,Mt as S,he as T};
@@ -1 +1 @@
1
- import{_ as N,k as U,o as V,a as r,c as u,b as t,f as _,d as j,w as P,u as I,t as i,m as k,v as D,i as v,q as J,j as h,x as M,s as $,n as m,g as q,h as A}from"./index-BGAW2Nqa.js";import{u as F}from"./commandButtons-D74TkPNU.js";import{a as W}from"./ApiClient-CcqJ-GAv.js";const p={PROJECT_ID:"projectId",PROJECT_ID_ALT:"id",BUTTON_ID:"buttonId",SESSION_ID:"id",SESSION_TAB:"tab"},z={class:"container command-button-detail"},G={key:0,class:"loading-state"},H={key:1,class:"form-container"},K={class:"form-header"},Q={class:"form-group"},X={key:0,class:"form-error"},Y={class:"form-group"},Z={key:0,class:"form-error"},ee={class:"form-group"},te={key:0,class:"form-error"},oe={class:"form-group form-group-checkbox"},se={for:"showOnList",class:"checkbox-label"},ae={class:"form-actions"},le=["disabled"],ne={key:0,class:"form-error-message"},re={class:"modal-body"},ue={class:"modal-footer"},de=["disabled"],ie={__name:"CommandButtonDetailView",setup(me){const d=$(),w=A(),O=F(),b=U(),B=m(!1),C=m(!1),g=m(!1),f=m(!1),c=m(null),a=m({}),o=m({label:"",command:"",sortOrder:0,showOnList:!1}),y=M(()=>!!d.params.buttonId),S=async s=>{B.value=!0;try{const e=d.params[p.PROJECT_ID];let l=O.getButtonById(s);l||(l=await W.getCommandButton(e,s)),l&&(o.value={label:l.label,command:l.command,sortOrder:l.sortOrder||0,showOnList:l.showOnList||!1})}catch(e){c.value=`Failed to load button: ${e.message}`}finally{B.value=!1}},T=()=>(a.value={},o.value.label.trim()||(a.value.label="Label is required"),o.value.command.trim()||(a.value.command="Command is required"),o.value.sortOrder<0&&(a.value.sortOrder="Sort order must be 0 or greater"),Object.keys(a.value).length===0),L=async()=>{if(c.value=null,!!T()){C.value=!0;try{const s=d.params[p.PROJECT_ID],e={label:o.value.label,command:o.value.command,sortOrder:o.value.sortOrder,showOnList:o.value.showOnList};y.value?(await O.updateButton(s,d.params[p.BUTTON_ID],e),b.success("Command button updated")):(await O.createButton(s,e),b.success("Command button created")),w.push(`/projects/${s}/sessions`)}catch(s){c.value=s.message,b.error(s.message)}finally{C.value=!1}}},x=()=>{w.back()},E=()=>{f.value=!0},R=async()=>{g.value=!0;try{const s=d.params[p.PROJECT_ID],e=d.params[p.BUTTON_ID];await O.deleteButton(s,e),b.success("Command button deleted"),f.value=!1,w.push(`/projects/${s}/sessions`)}catch(s){c.value=s.message,b.error(s.message)}finally{g.value=!1}};return V(async()=>{y.value&&await S(d.params.buttonId)}),(s,e)=>{const l=q("router-link");return r(),u("div",z,[B.value?(r(),u("div",G,[...e[7]||(e[7]=[t("span",{class:"loading-spinner"},null,-1),_(" Loading... ",-1)])])):(r(),u("div",H,[t("div",K,[j(l,{to:`/projects/${I(d).params[I(p).PROJECT_ID]}/sessions`,class:"btn btn-outline-secondary"},{default:P(()=>[...e[8]||(e[8]=[_(" ← Back ",-1)])]),_:1},8,["to"]),t("h2",null,i(y.value?"Edit Command Button":"New Command Button"),1)]),t("form",{class:"command-button-form",onSubmit:h(L,["prevent"])},[t("div",Q,[e[9]||(e[9]=t("label",{for:"label"},"Label",-1)),k(t("input",{id:"label","onUpdate:modelValue":e[0]||(e[0]=n=>o.value.label=n),type:"text",class:"form-input",placeholder:"e.g., Run Tests",required:""},null,512),[[D,o.value.label]]),a.value.label?(r(),u("span",X,i(a.value.label),1)):v("",!0)]),t("div",Y,[e[10]||(e[10]=t("label",{for:"command"},"Command",-1)),k(t("textarea",{id:"command","onUpdate:modelValue":e[1]||(e[1]=n=>o.value.command=n),class:"form-input",placeholder:"e.g., npm test",rows:"4",required:""},null,512),[[D,o.value.command]]),a.value.command?(r(),u("span",Z,i(a.value.command),1)):v("",!0)]),t("div",ee,[e[11]||(e[11]=t("label",{for:"sortOrder"},"Sort Order (optional)",-1)),k(t("input",{id:"sortOrder","onUpdate:modelValue":e[2]||(e[2]=n=>o.value.sortOrder=n),type:"number",class:"form-input",placeholder:"0",min:"0"},null,512),[[D,o.value.sortOrder,void 0,{number:!0}]]),a.value.sortOrder?(r(),u("span",te,i(a.value.sortOrder),1)):v("",!0),e[12]||(e[12]=t("span",{class:"form-help"},"Buttons are displayed in ascending order. Leave as 0 for default.",-1))]),t("div",oe,[t("label",se,[k(t("input",{id:"showOnList","onUpdate:modelValue":e[3]||(e[3]=n=>o.value.showOnList=n),type:"checkbox",class:"form-checkbox"},null,512),[[J,o.value.showOnList]]),e[13]||(e[13]=t("span",null,"Show status indicator on session lists",-1))]),e[14]||(e[14]=t("span",{class:"form-help"},"When enabled, the button status will be displayed on session cards",-1))]),t("div",ae,[t("button",{type:"button",class:"btn btn-outline-secondary",onClick:x}," Cancel "),y.value?(r(),u("button",{key:0,type:"button",class:"btn btn-outline-danger",onClick:E}," Delete ")):v("",!0),t("button",{type:"submit",class:"btn btn-primary",disabled:C.value},i(C.value?"Saving...":y.value?"Update":"Create"),9,le)]),c.value?(r(),u("div",ne,i(c.value),1)):v("",!0)],32)])),f.value?(r(),u("div",{key:2,class:"modal-overlay",onClick:e[6]||(e[6]=n=>f.value=!1)},[t("div",{class:"modal-dialog",onClick:e[5]||(e[5]=h(()=>{},["stop"]))},[e[18]||(e[18]=t("div",{class:"modal-header"},[t("h4",null,"Delete Command Button")],-1)),t("div",re,[t("p",null,[e[15]||(e[15]=_('Are you sure you want to delete "',-1)),t("strong",null,i(o.value.label),1),e[16]||(e[16]=_('"?',-1))]),e[17]||(e[17]=t("p",null,"This action cannot be undone.",-1))]),t("div",ue,[t("button",{class:"btn btn-outline-secondary",onClick:e[4]||(e[4]=n=>f.value=!1)}," Cancel "),t("button",{class:"btn btn-danger",disabled:g.value,onClick:R},i(g.value?"Deleting...":"Delete"),9,de)])])])):v("",!0)])}}},be=N(ie,[["__scopeId","data-v-b4855495"]]);export{be as default};
1
+ import{_ as N,k as U,o as V,a as r,c as u,b as t,f as _,d as j,w as P,u as I,t as i,m as k,v as D,i as v,q as J,j as h,x as M,s as $,n as m,g as q,h as A}from"./index-B6G18FqB.js";import{u as F}from"./commandButtons-D4RPpLiu.js";import{a as W}from"./ApiClient-B4YTtyY4.js";const p={PROJECT_ID:"projectId",PROJECT_ID_ALT:"id",BUTTON_ID:"buttonId",SESSION_ID:"id",SESSION_TAB:"tab"},z={class:"container command-button-detail"},G={key:0,class:"loading-state"},H={key:1,class:"form-container"},K={class:"form-header"},Q={class:"form-group"},X={key:0,class:"form-error"},Y={class:"form-group"},Z={key:0,class:"form-error"},ee={class:"form-group"},te={key:0,class:"form-error"},oe={class:"form-group form-group-checkbox"},se={for:"showOnList",class:"checkbox-label"},ae={class:"form-actions"},le=["disabled"],ne={key:0,class:"form-error-message"},re={class:"modal-body"},ue={class:"modal-footer"},de=["disabled"],ie={__name:"CommandButtonDetailView",setup(me){const d=$(),w=A(),O=F(),b=U(),B=m(!1),C=m(!1),g=m(!1),f=m(!1),c=m(null),a=m({}),o=m({label:"",command:"",sortOrder:0,showOnList:!1}),y=M(()=>!!d.params.buttonId),S=async s=>{B.value=!0;try{const e=d.params[p.PROJECT_ID];let l=O.getButtonById(s);l||(l=await W.getCommandButton(e,s)),l&&(o.value={label:l.label,command:l.command,sortOrder:l.sortOrder||0,showOnList:l.showOnList||!1})}catch(e){c.value=`Failed to load button: ${e.message}`}finally{B.value=!1}},T=()=>(a.value={},o.value.label.trim()||(a.value.label="Label is required"),o.value.command.trim()||(a.value.command="Command is required"),o.value.sortOrder<0&&(a.value.sortOrder="Sort order must be 0 or greater"),Object.keys(a.value).length===0),L=async()=>{if(c.value=null,!!T()){C.value=!0;try{const s=d.params[p.PROJECT_ID],e={label:o.value.label,command:o.value.command,sortOrder:o.value.sortOrder,showOnList:o.value.showOnList};y.value?(await O.updateButton(s,d.params[p.BUTTON_ID],e),b.success("Command button updated")):(await O.createButton(s,e),b.success("Command button created")),w.push(`/projects/${s}/sessions`)}catch(s){c.value=s.message,b.error(s.message)}finally{C.value=!1}}},x=()=>{w.back()},E=()=>{f.value=!0},R=async()=>{g.value=!0;try{const s=d.params[p.PROJECT_ID],e=d.params[p.BUTTON_ID];await O.deleteButton(s,e),b.success("Command button deleted"),f.value=!1,w.push(`/projects/${s}/sessions`)}catch(s){c.value=s.message,b.error(s.message)}finally{g.value=!1}};return V(async()=>{y.value&&await S(d.params.buttonId)}),(s,e)=>{const l=q("router-link");return r(),u("div",z,[B.value?(r(),u("div",G,[...e[7]||(e[7]=[t("span",{class:"loading-spinner"},null,-1),_(" Loading... ",-1)])])):(r(),u("div",H,[t("div",K,[j(l,{to:`/projects/${I(d).params[I(p).PROJECT_ID]}/sessions`,class:"btn btn-outline-secondary"},{default:P(()=>[...e[8]||(e[8]=[_(" ← Back ",-1)])]),_:1},8,["to"]),t("h2",null,i(y.value?"Edit Command Button":"New Command Button"),1)]),t("form",{class:"command-button-form",onSubmit:h(L,["prevent"])},[t("div",Q,[e[9]||(e[9]=t("label",{for:"label"},"Label",-1)),k(t("input",{id:"label","onUpdate:modelValue":e[0]||(e[0]=n=>o.value.label=n),type:"text",class:"form-input",placeholder:"e.g., Run Tests",required:""},null,512),[[D,o.value.label]]),a.value.label?(r(),u("span",X,i(a.value.label),1)):v("",!0)]),t("div",Y,[e[10]||(e[10]=t("label",{for:"command"},"Command",-1)),k(t("textarea",{id:"command","onUpdate:modelValue":e[1]||(e[1]=n=>o.value.command=n),class:"form-input",placeholder:"e.g., npm test",rows:"4",required:""},null,512),[[D,o.value.command]]),a.value.command?(r(),u("span",Z,i(a.value.command),1)):v("",!0)]),t("div",ee,[e[11]||(e[11]=t("label",{for:"sortOrder"},"Sort Order (optional)",-1)),k(t("input",{id:"sortOrder","onUpdate:modelValue":e[2]||(e[2]=n=>o.value.sortOrder=n),type:"number",class:"form-input",placeholder:"0",min:"0"},null,512),[[D,o.value.sortOrder,void 0,{number:!0}]]),a.value.sortOrder?(r(),u("span",te,i(a.value.sortOrder),1)):v("",!0),e[12]||(e[12]=t("span",{class:"form-help"},"Buttons are displayed in ascending order. Leave as 0 for default.",-1))]),t("div",oe,[t("label",se,[k(t("input",{id:"showOnList","onUpdate:modelValue":e[3]||(e[3]=n=>o.value.showOnList=n),type:"checkbox",class:"form-checkbox"},null,512),[[J,o.value.showOnList]]),e[13]||(e[13]=t("span",null,"Show status indicator on session lists",-1))]),e[14]||(e[14]=t("span",{class:"form-help"},"When enabled, the button status will be displayed on session cards",-1))]),t("div",ae,[t("button",{type:"button",class:"btn btn-outline-secondary",onClick:x}," Cancel "),y.value?(r(),u("button",{key:0,type:"button",class:"btn btn-outline-danger",onClick:E}," Delete ")):v("",!0),t("button",{type:"submit",class:"btn btn-primary",disabled:C.value},i(C.value?"Saving...":y.value?"Update":"Create"),9,le)]),c.value?(r(),u("div",ne,i(c.value),1)):v("",!0)],32)])),f.value?(r(),u("div",{key:2,class:"modal-overlay",onClick:e[6]||(e[6]=n=>f.value=!1)},[t("div",{class:"modal-dialog",onClick:e[5]||(e[5]=h(()=>{},["stop"]))},[e[18]||(e[18]=t("div",{class:"modal-header"},[t("h4",null,"Delete Command Button")],-1)),t("div",re,[t("p",null,[e[15]||(e[15]=_('Are you sure you want to delete "',-1)),t("strong",null,i(o.value.label),1),e[16]||(e[16]=_('"?',-1))]),e[17]||(e[17]=t("p",null,"This action cannot be undone.",-1))]),t("div",ue,[t("button",{class:"btn btn-outline-secondary",onClick:e[4]||(e[4]=n=>f.value=!1)}," Cancel "),t("button",{class:"btn btn-danger",disabled:g.value,onClick:R},i(g.value?"Deleting...":"Delete"),9,de)])])])):v("",!0)])}}},be=N(ie,[["__scopeId","data-v-b4855495"]]);export{be as default};
@@ -0,0 +1 @@
1
+ import{L as f,$ as g,_ as b,k as E,n as h,l as _,a as p,c as m,b as I,F as w,r as x,t as j,u as L,x as C,Z as O}from"./index-B6G18FqB.js";import{a as r}from"./ApiClient-B4YTtyY4.js";import{u as P}from"./sessions-DH1R-NhV.js";const k=["low","medium","high","max","auto"],Y=[{id:"claude-haiku-4-5-20251001",name:"Haiku 4.5",description:"Fast & lightweight"},{id:"claude-sonnet-4-6",name:"Sonnet 4.6",description:"Balanced"},{id:"claude-opus-4-6",name:"Opus 4.6",description:"Previous generation"},{id:"claude-opus-4-7",name:"Opus 4.7",description:"Most capable (default)"}],$="claude-opus-4-7",z=[{id:"gpt-5.5",name:"GPT-5.5",description:"Flagship coding and professional work",seedId:"openai-gpt-5-5"},{id:"gpt-5.4",name:"GPT-5.4",description:"High capability professional work",seedId:"openai-gpt-5-4"},{id:"gpt-5.4-mini",name:"GPT-5.4 mini",description:"Fast lower-cost coding and subagent work",seedId:"openai-gpt-5-4-mini"},{id:"gpt-5.3-codex",name:"GPT-5.3-Codex",description:"Coding-optimized agentic model",seedId:"openai-gpt-5-3-codex"}],F=f("todos",{state:()=>({items:[],loading:!1,error:null,expanded:!1,currentConversationId:null}),getters:{hasTodos:t=>t.items.length>0,pendingCount:t=>t.items.filter(e=>e.status==="pending").length,inProgressCount:t=>t.items.filter(e=>e.status==="in_progress").length,completedCount:t=>t.items.filter(e=>e.status==="completed").length},actions:{async fetchTodos(t,e=null){this.loading=!0,this.error=null,this.currentConversationId=e;try{this.items=await r.getSessionTodos(t,e)}catch(s){this.error=s.message}finally{this.loading=!1}},updateTodos(t,e=null){(e===null||this.currentConversationId===null||e===this.currentConversationId)&&(this.items=t)},clearTodos(){this.items=[],this.loading=!1,this.error=null,this.currentConversationId=null,this.expanded=!1},toggleExpanded(){this.expanded=!this.expanded},setExpanded(t){this.expanded=t}}}),D=Symbol("overlay-sessions-store"),V=Symbol("overlay-todos-store");function B(){return g(D,P())}function Z(){return g(V,F())}const q=f("templates",{state:()=>({projectTemplates:[],globalTemplates:[],loading:!1,error:null}),getters:{allTemplates:t=>[...t.projectTemplates,...t.globalTemplates],getTemplateById:t=>e=>t.projectTemplates.find(s=>s.id===e)||t.globalTemplates.find(s=>s.id===e)},actions:{async fetchProjectTemplates(t){this.loading=!0,this.error=null;try{const e=await r.getProjectTemplates(t);this.projectTemplates=e.project||[],this.globalTemplates=e.global||[]}catch(e){this.error=e.message}finally{this.loading=!1}},async createProjectTemplate(t,e){this.loading=!0,this.error=null;try{const s=await r.createProjectTemplate(t,e);return this.projectTemplates.unshift(s),s}catch(s){throw this.error=s.message,s}finally{this.loading=!1}},async createGlobalTemplate(t){this.loading=!0,this.error=null;try{const e=await r.createGlobalTemplate(t);return this.globalTemplates.unshift(e),e}catch(e){throw this.error=e.message,e}finally{this.loading=!1}},async updateTemplate(t,e){this.loading=!0,this.error=null;try{const s=await r.updateTemplate(t,e);let l=this.projectTemplates.findIndex(o=>o.id===t);return l!==-1?this.projectTemplates[l]=s:(l=this.globalTemplates.findIndex(o=>o.id===t),l!==-1&&(this.globalTemplates[l]=s)),s}catch(s){throw this.error=s.message,s}finally{this.loading=!1}},async deleteTemplate(t){this.loading=!0,this.error=null;try{await r.deleteTemplate(t),this.projectTemplates=this.projectTemplates.filter(e=>e.id!==t),this.globalTemplates=this.globalTemplates.filter(e=>e.id!==t)}catch(e){throw this.error=e.message,e}finally{this.loading=!1}}}}),G={class:"effort-selector"},R=["value","disabled"],A=["value"],M={__name:"EffortLevelSelector",props:{sessionId:{type:String,default:null},modelValue:{type:String,default:null},disabled:{type:Boolean,default:!1}},emits:["update:modelValue"],setup(t,{emit:e}){const s=t,l=e,o=B(),T=E(),d=h(!1),y=["auto",...k.filter(a=>a!=="auto")].map(a=>({value:a,label:`${a.charAt(0).toUpperCase()+a.slice(1)} Effort`})),u=C(()=>{var a;return s.sessionId?((a=o.currentSession)==null?void 0:a.effortLevel)||"auto":s.modelValue||"auto"}),i=h(u.value),S=O(s,"modelValue");_([u,S],([a])=>{i.value=a||"auto"},{flush:"sync"});async function v(a){if(!d.value&&i.value!==a)if(i.value=a,s.sessionId){d.value=!0;try{await o.updateSessionFields(s.sessionId,{effortLevel:a==="auto"?null:a})}catch(c){i.value=u.value,T.error(c.message)}finally{d.value=!1}}else l("update:modelValue",a==="auto"?null:a)}return(a,c)=>(p(),m("div",G,[I("select",{id:"effort-select",value:i.value,disabled:t.disabled||d.value,class:"effort-select","aria-label":"Effort level",onChange:c[0]||(c[0]=n=>v(n.target.value))},[(p(!0),m(w,null,x(L(y),n=>(p(),m("option",{key:n.value,value:n.value},j(n.label),9,A))),128))],40,R)]))}},J=b(M,[["__scopeId","data-v-8bc1fe64"]]);export{Y as C,$ as D,J as E,z as O,D as S,V as T,F as a,B as b,Z as c,q as u};