@lovelybunch/api 1.0.75-alpha.4 → 1.0.75-alpha.5

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 (105) hide show
  1. package/dist/routes/api/v1/ai/index.js +0 -2
  2. package/dist/routes/api/v1/ai/route.js +105 -241
  3. package/dist/routes/api/v1/events/status/route.d.ts +1 -1
  4. package/dist/routes/api/v1/jobs/[id]/run/route.d.ts +2 -2
  5. package/dist/routes/api/v1/jobs/[id]/runs/[runId]/route.d.ts +2 -2
  6. package/dist/routes/api/v1/jobs/status/route.d.ts +1 -1
  7. package/dist/routes/api/v1/proposals/[id]/route.d.ts +8 -8
  8. package/package.json +6 -4
  9. package/static/assets/{ActivityPage-BI-4IFaP.js → ActivityPage-6xf2Jxp0.js} +1 -1
  10. package/static/assets/{AgentDetailPage-eVEOya9x.js → AgentDetailPage-1hbFBTeB.js} +1 -1
  11. package/static/assets/{AgentEditPage-Ds5XXaak.js → AgentEditPage-qMmg057j.js} +1 -1
  12. package/static/assets/{AgentsPage-CE59G63x.js → AgentsPage-DyyJrXqo.js} +2 -2
  13. package/static/assets/{AgentsSettingsPage-uVKYxuov.js → AgentsSettingsPage-Bf61k6i0.js} +2 -2
  14. package/static/assets/{ApiKeysSettingsPage-CTPK48rU.js → ApiKeysSettingsPage-DlWMBuQb.js} +2 -2
  15. package/static/assets/{ArchitectureEditPage-Cn4zVbPK.js → ArchitectureEditPage-C6MWFHCp.js} +1 -1
  16. package/static/assets/{ArchitecturePage-CCocwST0.js → ArchitecturePage-CxQtPG4d.js} +1 -1
  17. package/static/assets/{AuthSettingsPage-C-nDwiO4.js → AuthSettingsPage-w0blkw8Q.js} +2 -2
  18. package/static/assets/{CallbackPage-ZcrfbMj2.js → CallbackPage-ByjWTMuG.js} +1 -1
  19. package/static/assets/{CodePage-DuHcwCCu.js → CodePage-aWl0jKwx.js} +2 -2
  20. package/static/assets/{CollapsibleSection-DreaKHR1.js → CollapsibleSection-B1AU3exJ.js} +1 -1
  21. package/static/assets/{DashboardPage-Da0zfmye.js → DashboardPage-CAToLPqr.js} +2 -2
  22. package/static/assets/{GitPage-DE0oU3cj.js → GitPage-DGjEzIUs.js} +1 -1
  23. package/static/assets/{GitSettingsPage-DndQUnzg.js → GitSettingsPage-X1GEO1Ti.js} +2 -2
  24. package/static/assets/{IdentityPage-DD-9upeG.js → IdentityPage-L0foq6qN.js} +3 -3
  25. package/static/assets/{ImplementationStepsEditor-C3vh3Hc0.js → ImplementationStepsEditor-Dn88eiVP.js} +1 -1
  26. package/static/assets/IntegrationsSettingsPage-WX1lSaWr.js +1 -0
  27. package/static/assets/JobDetailPage-CvNs3cEP.js +1 -0
  28. package/static/assets/KnowledgeDetailPage-DXjmZdQl.js +1 -0
  29. package/static/assets/KnowledgeEditPage-C70yoVFM.js +1 -0
  30. package/static/assets/{KnowledgePage-cOsVzN4A.js → KnowledgePage-EUJ9c9By.js} +2 -2
  31. package/static/assets/{LoginPage-CvVZ8le4.js → LoginPage-Df_q-ACP.js} +1 -1
  32. package/static/assets/{McpSettingsPage-_q1tdgv0.js → McpSettingsPage-4b5M8tpH.js} +1 -1
  33. package/static/assets/{NewAgentPage-DIzdUSPb.js → NewAgentPage-BqvZZJmC.js} +1 -1
  34. package/static/assets/NewKnowledgePage-CqKz6_K-.js +9 -0
  35. package/static/assets/{NewProposalPage-h91-EksD.js → NewProposalPage-DR9UZich.js} +2 -2
  36. package/static/assets/{ProjectEditPage-CcwGPvlc.js → ProjectEditPage-5YxG7Xxd.js} +1 -1
  37. package/static/assets/ProjectPage-BBhGv2fS.js +1 -0
  38. package/static/assets/{PromptsSettingsPage-BTOf3Xzc.js → PromptsSettingsPage-DLrpZcDA.js} +1 -1
  39. package/static/assets/ProposalDetailPage-C4tagoNE.js +1 -0
  40. package/static/assets/ProposalEditPage-Bz-oEsLL.js +1 -0
  41. package/static/assets/{ProposalsPage-ekrWnqoo.js → ProposalsPage-BKRjNF4y.js} +1 -1
  42. package/static/assets/{ResourcesPage-90Wdfshd.js → ResourcesPage-BZrToY-V.js} +4 -4
  43. package/static/assets/{RoleEditPage-DY75XHIO.js → RoleEditPage-C2vWadxy.js} +1 -1
  44. package/static/assets/{RolePage-CXas69QY.js → RolePage-CE9y3rMd.js} +1 -1
  45. package/static/assets/{RulesSettingsPage-p6AjPCI0.js → RulesSettingsPage-BidnZaAT.js} +2 -2
  46. package/static/assets/SchedulePage-DU7ng6Gq.js +4 -0
  47. package/static/assets/SourceInput-CCa7okhU.js +1 -0
  48. package/static/assets/{TagInput-Dfue2spU.js → TagInput-Chn207ze.js} +1 -1
  49. package/static/assets/TerminalPage-CEYgdKT2.js +1 -0
  50. package/static/assets/{TerminalSessionPage-FueIeaIL.js → TerminalSessionPage-C8YA0AmM.js} +4 -4
  51. package/static/assets/{UserPreferencesPage-C9yXdIdZ.js → UserPreferencesPage-lPgr1ngr.js} +1 -1
  52. package/static/assets/{UserSettingsPage-ba7UUKyG.js → UserSettingsPage-ctHFqz6e.js} +1 -1
  53. package/static/assets/{UtilitiesPage-5Zot5Svs.js → UtilitiesPage-BVxyh0Ce.js} +1 -1
  54. package/static/assets/{alert-BhJUdRgG.js → alert-D5jzRTa5.js} +1 -1
  55. package/static/assets/{arrow-down-BYk0k85B.js → arrow-down-4I_8gyhd.js} +1 -1
  56. package/static/assets/{arrow-left-TQT21N4S.js → arrow-left-DZzHrGWA.js} +1 -1
  57. package/static/assets/{arrow-up-BkSi1XTr.js → arrow-up-B4VxSS3_.js} +1 -1
  58. package/static/assets/{badge-DS8SPg0q.js → badge-DvLOhob-.js} +1 -1
  59. package/static/assets/{browser-modal-CgvW-bbQ.js → browser-modal-DzaD2oDW.js} +2 -2
  60. package/static/assets/{calendar-AzmVUvxT.js → calendar-BNe2rz1T.js} +1 -1
  61. package/static/assets/{card-C4vq6AMz.js → card-BguljVtN.js} +1 -1
  62. package/static/assets/{chevron-left-CeRwwCqx.js → chevron-left-DZQ_tMvU.js} +1 -1
  63. package/static/assets/{chevrons-up-BdEukQhU.js → chevrons-up-BCenbxtV.js} +1 -1
  64. package/static/assets/{circle-alert-C1JRie1k.js → circle-alert-CZtpB74t.js} +1 -1
  65. package/static/assets/{circle-check-big-CQBGgL4s.js → circle-check-big-CTApxALS.js} +1 -1
  66. package/static/assets/{circle-check-DxiLNIIS.js → circle-check-hWIEYAMH.js} +1 -1
  67. package/static/assets/{circle-play-qq_sLPT0.js → circle-play-BF3gDlvZ.js} +1 -1
  68. package/static/assets/{circle-x-kpttvnBF.js → circle-x-BtYTEkcT.js} +1 -1
  69. package/static/assets/{clipboard-CBBHo2mi.js → clipboard-B8Tnfm3W.js} +1 -1
  70. package/static/assets/{clock-Ck6whvmg.js → clock-_sj3uVNp.js} +1 -1
  71. package/static/assets/{download-Cx4OcU33.js → download-CPGv4d5Q.js} +1 -1
  72. package/static/assets/external-link-CtxWkvSs.js +6 -0
  73. package/static/assets/{eye-2CnfcAd3.js → eye-_nXnan_b.js} +1 -1
  74. package/static/assets/{folder-git-2-CvwpDtwI.js → folder-git-2-C_Zkp5wq.js} +1 -1
  75. package/static/assets/index-BlLRLvWP.js +462 -0
  76. package/static/assets/index-DVTgTsDa.css +2 -0
  77. package/static/assets/{info-BO6_vv66.js → info-fJ-d5-p-.js} +1 -1
  78. package/static/assets/{label-B-1O5hdX.js → label-PINvlQb-.js} +1 -1
  79. package/static/assets/{markdown-editor-H-rT6Hat.js → markdown-editor-B7Zxgu1u.js} +1 -1
  80. package/static/assets/{pause-CW39bpDf.js → pause-C9zNWRax.js} +1 -1
  81. package/static/assets/{play-Bqd-yHZN.js → play-BpXD0Ub0.js} +1 -1
  82. package/static/assets/{plus-BWhZkuI2.js → plus-DBJTL6qk.js} +1 -1
  83. package/static/assets/{radio-group-CHbb2Tdt.js → radio-group-DBaY5DVP.js} +1 -1
  84. package/static/assets/{refresh-cw-CaOTs34G.js → refresh-cw-SQsUc3_C.js} +1 -1
  85. package/static/assets/{search-D2duvyuf.js → search-CBNlhD-8.js} +1 -1
  86. package/static/assets/{switch-BRsOxt7T.js → switch-C3ys7mIF.js} +1 -1
  87. package/static/assets/{tabs--rTULKlo.js → tabs-BpxOu6UL.js} +1 -1
  88. package/static/assets/{tag-BQ5pJD32.js → tag-Cu4oj34X.js} +1 -1
  89. package/static/assets/{terminal-preview-ewZC6O1I.js → terminal-preview-B5-BekLC.js} +1 -1
  90. package/static/assets/{use-terminal-Cya6EYny.js → use-terminal-CDMgbskg.js} +1 -1
  91. package/static/assets/{zap-DQNov92q.js → zap-LrtVPxxV.js} +1 -1
  92. package/static/index.html +2 -2
  93. package/static/assets/IntegrationsSettingsPage-B4J4wDXt.js +0 -1
  94. package/static/assets/JobDetailPage-tHRLIpQI.js +0 -1
  95. package/static/assets/KnowledgeDetailPage-Dh315TpW.js +0 -1
  96. package/static/assets/KnowledgeEditPage-B5bNMMvh.js +0 -1
  97. package/static/assets/NewKnowledgePage-weR174CB.js +0 -9
  98. package/static/assets/ProjectPage-D9APD9HG.js +0 -1
  99. package/static/assets/ProposalDetailPage-DbUTHokj.js +0 -1
  100. package/static/assets/ProposalEditPage-97pQXtDD.js +0 -1
  101. package/static/assets/SchedulePage-C-Yevtfw.js +0 -4
  102. package/static/assets/SourceInput-CLzuDG61.js +0 -1
  103. package/static/assets/TerminalPage-BbA46X-G.js +0 -1
  104. package/static/assets/index-C8_b70Ej.css +0 -2
  105. package/static/assets/index-Df8kpDhM.js +0 -468
@@ -1,7 +1,5 @@
1
1
  import { Hono } from 'hono';
2
2
  import { POST } from './route.js';
3
- import { POST as toolsPost } from './tools.js';
4
3
  const app = new Hono();
5
4
  app.post('/', POST);
6
- app.post('/tools', toolsPost);
7
5
  export default app;
@@ -4,6 +4,8 @@ import { existsSync, readFileSync, promises as fs, createReadStream } from 'fs';
4
4
  import { fileURLToPath } from 'url';
5
5
  import readline from 'readline';
6
6
  import { ZodError } from 'zod';
7
+ import { streamText, tool, jsonSchema, stepCountIs } from 'ai';
8
+ import { createAnthropic } from '@ai-sdk/anthropic';
7
9
  import { getLogsDir, listProposals, getProposal, createProposal, updateProposal, deleteProposal, } from '@lovelybunch/core';
8
10
  import { proposalsFullTool, knowledgeTool, normalizeKnowledgeMetadata, eventsTool, projectContextTool, architectureContextTool, roleContextTool } from '@lovelybunch/mcp';
9
11
  import matter from 'gray-matter';
@@ -37,279 +39,141 @@ function getGlobalApiKey(provider) {
37
39
  }
38
40
  export async function POST(c) {
39
41
  try {
40
- const { message: userMessage, history, model, context, contextContent, agentPersona, systemPrompt: systemOverride, maxTokens, enableTools, attachedContextFiles, stream } = await c.req.json();
42
+ const { message: userMessage, history, context, contextContent, agentPersona, systemPrompt: systemOverride, attachedContextFiles } = await c.req.json();
41
43
  if (!userMessage) {
42
44
  return c.json({ error: "Message is required" }, 400);
43
45
  }
44
46
  // Prefer global config key (set via CLI/UI), fallback to env var
45
- let openRouterKey = getGlobalApiKey('openrouter') || process.env.OPENROUTER_API_KEY;
46
- if (!openRouterKey) {
47
+ const apiKey = getGlobalApiKey('anthropic') || process.env.ANTHROPIC_API_KEY;
48
+ if (!apiKey) {
47
49
  return c.json({
48
- error: "OpenRouter API key not configured",
49
- hint: "Set via 'coconut config set-key -p openrouter -k <KEY>' (or 'nut config set-key -p openrouter -k <KEY>'), or set OPENROUTER_API_KEY env var"
50
+ error: "Anthropic API key not configured",
51
+ hint: "Set via 'coconut config set-key -p anthropic -k <KEY>' (or 'nut config set-key -p anthropic -k <KEY>'), or set ANTHROPIC_API_KEY env var"
50
52
  }, 500);
51
53
  }
54
+ // Initialize Anthropic model via AI SDK
55
+ const anthropicClient = createAnthropic({ apiKey });
56
+ const model = anthropicClient('claude-sonnet-4-5-20250929');
52
57
  const baseSystem = systemOverride || getSystemPrompt();
53
58
  const systemPrompt = agentPersona
54
59
  ? `${baseSystem}\n\nThe following persona is authoritative and overrides general guidance above. You must strictly follow it.\n\n${agentPersona}`
55
60
  : baseSystem;
56
- // Prepare tools for function calling
57
- // Note: proposals/knowledge/project/architecture are read+write, events is read-only
58
- const tools = enableTools ? [
59
- {
60
- type: "function",
61
- function: proposalsFullTool
62
- },
63
- {
64
- type: "function",
65
- function: knowledgeTool
66
- },
67
- {
68
- type: "function",
69
- function: eventsTool
70
- },
71
- {
72
- type: "function",
73
- function: projectContextTool
74
- },
75
- {
76
- type: "function",
77
- function: architectureContextTool
78
- },
79
- {
80
- type: "function",
81
- function: roleContextTool
61
+ // Build context messages from attached files
62
+ const contextMessages = [];
63
+ if (Array.isArray(attachedContextFiles)) {
64
+ for (const file of attachedContextFiles) {
65
+ if (file && typeof file.content === 'string' && file.content.trim().length > 0) {
66
+ contextMessages.push({
67
+ role: 'user',
68
+ content: `[ATTACHED CONTEXT - FULL CONTENT INCLUDED BELOW - DO NOT USE TOOLS TO FETCH THIS FILE]\nDocument: ${file.name || file.path || 'reference'}\nType: ${file.type || 'context'}\n\n--- BEGIN CONTENT ---\n${file.content}\n--- END CONTENT ---`
69
+ });
70
+ // Add a brief assistant acknowledgment so the conversation alternates correctly
71
+ contextMessages.push({
72
+ role: 'assistant',
73
+ content: `I've noted the attached context document "${file.name || 'reference'}". I'll reference it as needed.`
74
+ });
75
+ }
82
76
  }
83
- ] : null;
84
- const contextMessages = Array.isArray(attachedContextFiles)
85
- ? attachedContextFiles
86
- .filter((file) => file && typeof file.content === 'string' && file.content.trim().length > 0)
87
- .map((file) => ({
88
- role: 'system',
89
- content: `[ATTACHED CONTEXT - FULL CONTENT INCLUDED BELOW - DO NOT USE TOOLS TO FETCH THIS FILE]\nDocument: ${file.name || file.path || 'reference'}\nType: ${file.type || 'context'}\n\n--- BEGIN CONTENT ---\n${file.content}\n--- END CONTENT ---`
90
- }))
91
- : [];
92
- // Compose the message list: system + history (preferred) or single message
77
+ }
78
+ // Compose the message list: history (preferred) or single message
93
79
  let messagesPayload;
94
80
  if (Array.isArray(history) && history.length > 0) {
95
- // sanitize roles to user/assistant only, preserve order
96
- const sanitized = history.filter(m => m && (m.role === 'user' || m.role === 'assistant') && typeof m.content === 'string');
81
+ // Sanitize roles to user/assistant only, preserve order
82
+ const sanitized = history.filter((m) => m && (m.role === 'user' || m.role === 'assistant') && typeof m.content === 'string');
97
83
  messagesPayload = [
98
- { role: 'system', content: systemPrompt },
99
84
  ...contextMessages,
100
85
  ...sanitized,
101
86
  ];
102
87
  }
103
88
  else {
104
89
  messagesPayload = [
105
- { role: 'system', content: systemPrompt },
106
90
  ...contextMessages,
107
91
  { role: 'user', content: userMessage },
108
92
  ];
109
93
  }
110
- const requestBody = {
111
- model: model || "openai/gpt-4o",
112
- messages: messagesPayload,
113
- temperature: 0.7,
114
- max_tokens: typeof maxTokens === 'number' ? Math.max(256, Math.min(8000, Math.floor(maxTokens))) : 8000,
115
- stream: stream === true,
94
+ // Define tools with execute functions using AI SDK tool()
95
+ // Using tool<any, string>() to properly type jsonSchema-based tools
96
+ const storage = new FileStorageAdapter();
97
+ const aiTools = {
98
+ change_proposals: tool({
99
+ description: proposalsFullTool.description,
100
+ inputSchema: jsonSchema(proposalsFullTool.parameters),
101
+ execute: async (args) => {
102
+ const result = await executeProposalsToolDirect(args, storage);
103
+ return JSON.stringify(result);
104
+ },
105
+ }),
106
+ knowledge_documents: tool({
107
+ description: knowledgeTool.description,
108
+ inputSchema: jsonSchema(knowledgeTool.parameters),
109
+ execute: async (args) => {
110
+ const result = await executeKnowledgeToolDirect(args);
111
+ return JSON.stringify(result);
112
+ },
113
+ }),
114
+ activity_events: tool({
115
+ description: eventsTool.description,
116
+ inputSchema: jsonSchema(eventsTool.parameters),
117
+ execute: async (args) => {
118
+ const result = await executeEventsToolDirect(args);
119
+ return JSON.stringify(result);
120
+ },
121
+ }),
122
+ project_context: tool({
123
+ description: projectContextTool.description,
124
+ inputSchema: jsonSchema(projectContextTool.parameters),
125
+ execute: async (args) => {
126
+ const result = await executeProjectContextToolDirect(args);
127
+ return JSON.stringify(result);
128
+ },
129
+ }),
130
+ architecture_context: tool({
131
+ description: architectureContextTool.description,
132
+ inputSchema: jsonSchema(architectureContextTool.parameters),
133
+ execute: async (args) => {
134
+ const result = await executeArchitectureContextToolDirect(args);
135
+ return JSON.stringify(result);
136
+ },
137
+ }),
138
+ role_context: tool({
139
+ description: roleContextTool.description,
140
+ inputSchema: jsonSchema(roleContextTool.parameters),
141
+ execute: async (args) => {
142
+ const result = await executeRoleContextToolDirect(args);
143
+ return JSON.stringify(result);
144
+ },
145
+ }),
116
146
  };
117
- // Add tools if enabled
118
- if (tools) {
119
- requestBody.tools = tools;
120
- requestBody.tool_choice = "auto";
121
- }
122
147
  // Debug logging
123
148
  console.log('AI Request Debug:', {
124
- enableTools,
125
- tools: tools ? tools.length : 'null',
126
- hasToolChoice: !!requestBody.tool_choice,
127
- model: requestBody.model
149
+ toolCount: Object.keys(aiTools).length,
150
+ messageCount: messagesPayload.length,
151
+ model: 'claude-sonnet-4-5-20250929'
128
152
  });
129
- const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
130
- method: "POST",
131
- headers: {
132
- "Authorization": `Bearer ${openRouterKey}`,
133
- "Content-Type": "application/json",
134
- "HTTP-Referer": process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3001",
135
- "X-Title": "Coconut AI Assistant",
136
- },
137
- body: JSON.stringify(requestBody),
153
+ // Use AI SDK streamText - handles the entire LLM + tool loop automatically
154
+ const result = streamText({
155
+ model,
156
+ system: systemPrompt,
157
+ messages: messagesPayload,
158
+ tools: aiTools,
159
+ stopWhen: stepCountIs(5), // Max 5 tool-use rounds
160
+ temperature: 0.7,
161
+ maxOutputTokens: 8000,
138
162
  });
139
- if (!response.ok) {
140
- const errorText = await response.text();
141
- console.error("OpenRouter API error:", {
142
- status: response.status,
143
- statusText: response.statusText,
144
- error: errorText,
145
- model: requestBody.model
146
- });
147
- // Try to parse error for more detail
148
- let errorDetail = "Failed to get AI response";
149
- try {
150
- const errorJson = JSON.parse(errorText);
151
- errorDetail = errorJson.error?.message || errorJson.error || errorDetail;
152
- }
153
- catch {
154
- // Use raw text if not JSON
155
- if (errorText.length < 200) {
156
- errorDetail = errorText || errorDetail;
157
- }
158
- }
159
- return c.json({ error: errorDetail, status: response.status }, response.status);
160
- }
161
- // Handle streaming response
162
- if (stream === true && response.body) {
163
- return c.newResponse(response.body, {
164
- status: 200,
165
- headers: {
166
- 'Content-Type': 'text/event-stream',
167
- 'Cache-Control': 'no-cache',
168
- 'Connection': 'keep-alive',
169
- },
170
- });
171
- }
172
- const data = await response.json();
173
- const aiMessage = data.choices?.[0]?.message;
174
- if (!aiMessage) {
175
- console.error("No AI message in response:", {
176
- model: requestBody.model,
177
- choices: data.choices,
178
- error: data.error
179
- });
180
- const errorDetail = data.error?.message || data.error || "No response from AI model";
181
- return c.json({ error: errorDetail }, 500);
182
- }
183
- // Handle tool calls
184
- if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {
185
- const toolResults = await executeToolCalls(aiMessage.tool_calls);
186
- // Add tool results to the conversation and get final response
187
- const messagesWithTools = [
188
- ...messagesPayload,
189
- aiMessage,
190
- ...toolResults.map(result => ({
191
- role: 'tool',
192
- content: result.content,
193
- tool_call_id: result.tool_call_id
194
- }))
195
- ];
196
- // Get final response from AI with tool results
197
- // Use lower max_tokens for tool result synthesis (typically just needs to summarize)
198
- const finalResponse = await fetch("https://openrouter.ai/api/v1/chat/completions", {
199
- method: "POST",
200
- headers: {
201
- "Authorization": `Bearer ${openRouterKey}`,
202
- "Content-Type": "application/json",
203
- "HTTP-Referer": process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3001",
204
- "X-Title": "Coconut AI Assistant",
205
- },
206
- body: JSON.stringify({
207
- model: model || "openai/gpt-4o",
208
- messages: messagesWithTools,
209
- temperature: 0.5, // Lower temperature for more consistent tool result summaries
210
- max_tokens: 2000, // Reduced from 8000 - tool summaries don't need to be as long
211
- }),
212
- });
213
- if (!finalResponse.ok) {
214
- const error = await finalResponse.text();
215
- console.error("OpenRouter API error for final response:", error);
216
- return c.json({ error: "Failed to get final AI response" }, 500);
217
- }
218
- const finalData = await finalResponse.json();
219
- const finalMessage = finalData.choices?.[0]?.message;
220
- return c.json({
221
- response: finalMessage?.content || "Tool execution completed",
222
- toolCalls: aiMessage.tool_calls,
223
- toolResults: toolResults
224
- });
225
- }
226
- return c.json({ response: aiMessage.content });
163
+ // Return a plain text stream response
164
+ // toTextStreamResponse() streams text-delta events as UTF-8 chunks,
165
+ // ignoring tool calls, tool results, and other non-text events
166
+ return result.toTextStreamResponse();
227
167
  }
228
168
  catch (error) {
229
169
  console.error("AI API error:", error);
230
170
  return c.json({ error: "Internal server error" }, 500);
231
171
  }
232
172
  }
233
- async function executeToolCalls(toolCalls) {
234
- const storage = new FileStorageAdapter();
235
- // Execute all tool calls in parallel for better performance
236
- const resultPromises = toolCalls.map(async (toolCall) => {
237
- try {
238
- // Handle both function calling formats
239
- const functionName = toolCall.function?.name || toolCall.name;
240
- let functionArgs;
241
- if (toolCall.function?.arguments) {
242
- try {
243
- // Try to sanitize common JSON issues before parsing
244
- let argsStr = toolCall.function.arguments;
245
- // Remove trailing commas before ] or }
246
- argsStr = argsStr.replace(/,(\s*[}\]])/g, '$1');
247
- // Fix common LLM JSON issues:
248
- // Remove control characters (except \n, \r, \t which are valid in JSON strings)
249
- argsStr = argsStr.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, '');
250
- functionArgs = JSON.parse(argsStr);
251
- }
252
- catch (parseError) {
253
- // LLM may generate invalid JSON with unescaped characters in long content
254
- const errorMsg = parseError instanceof Error ? parseError.message : 'Unknown parse error';
255
- const hint = errorMsg.includes('position')
256
- ? 'The content may contain unescaped quotes or special characters. Try updating with shorter/simpler content, or update one field at a time.'
257
- : 'Please retry with simpler content.';
258
- return {
259
- tool_call_id: toolCall.id,
260
- content: JSON.stringify({
261
- success: false,
262
- error: `Invalid tool arguments: ${errorMsg}. ${hint}`
263
- })
264
- };
265
- }
266
- }
267
- else {
268
- functionArgs = toolCall.arguments;
269
- }
270
- let result = { success: false, error: 'Unknown tool' };
271
- // Execute tools directly instead of making HTTP requests
272
- if (functionName === 'change_proposals') {
273
- result = await executeProposalsToolDirect(functionArgs, storage);
274
- }
275
- else if (functionName === 'knowledge_documents') {
276
- result = await executeKnowledgeToolDirect(functionArgs);
277
- }
278
- else if (functionName === 'activity_events') {
279
- result = await executeEventsToolDirect(functionArgs);
280
- }
281
- else if (functionName === 'project_context') {
282
- result = await executeProjectContextToolDirect(functionArgs);
283
- }
284
- else if (functionName === 'architecture_context') {
285
- result = await executeArchitectureContextToolDirect(functionArgs);
286
- }
287
- else if (functionName === 'role_context') {
288
- result = await executeRoleContextToolDirect(functionArgs);
289
- }
290
- return {
291
- tool_call_id: toolCall.id,
292
- content: JSON.stringify({
293
- success: result.success,
294
- data: result.data,
295
- message: result.message,
296
- error: result.error
297
- })
298
- };
299
- }
300
- catch (error) {
301
- return {
302
- tool_call_id: toolCall.id,
303
- content: JSON.stringify({
304
- success: false,
305
- error: error instanceof Error ? error.message : 'Unknown error'
306
- })
307
- };
308
- }
309
- });
310
- return Promise.all(resultPromises);
311
- }
312
- // Proposals tool - full CRUD operations using @lovelybunch/core
173
+ // ─── Tool Execution Functions ────────────────────────────────────────────────
174
+ // These are unchanged from the previous implementation. They handle the actual
175
+ // business logic for each tool, called automatically by the AI SDK when the
176
+ // LLM makes tool calls.
313
177
  async function executeProposalsToolDirect(args, _storage) {
314
178
  const { operation, id, filters, proposal, updates } = args;
315
179
  try {
@@ -381,7 +245,6 @@ async function executeProposalsToolDirect(args, _storage) {
381
245
  }
382
246
  }
383
247
  catch (error) {
384
- // Handle Zod validation errors specially
385
248
  if (error instanceof ZodError) {
386
249
  return {
387
250
  success: false,
@@ -953,6 +816,7 @@ async function executeRoleContextToolDirect(args) {
953
816
  return { success: false, error: error.message || 'Role context tool execution failed' };
954
817
  }
955
818
  }
819
+ // ─── Helper Functions ────────────────────────────────────────────────────────
956
820
  function getContextBasePath() {
957
821
  let basePath;
958
822
  if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
@@ -1017,14 +881,14 @@ async function readKnowledgeDocument(basePath, filename) {
1017
881
  fs.stat(filePath)
1018
882
  ]);
1019
883
  const { data, content } = matter(raw);
1020
- const metadata = normalizeKnowledgeMetadata(data);
884
+ const normalizedMeta = normalizeKnowledgeMetadata(data);
1021
885
  // Use file mtime for updated timestamp instead of frontmatter
1022
- metadata.updated = stats.mtime.toISOString();
886
+ normalizedMeta.updated = stats.mtime.toISOString();
1023
887
  const title = extractKnowledgeTitle(content, actualFilename);
1024
888
  return {
1025
889
  filename: actualFilename,
1026
890
  title,
1027
- metadata,
891
+ metadata: normalizedMeta,
1028
892
  content
1029
893
  };
1030
894
  }
@@ -7,9 +7,9 @@ import { Context } from "hono";
7
7
  * Get logging system status and configuration
8
8
  */
9
9
  export declare function GET(c: Context): Promise<(Response & import("hono").TypedResponse<{
10
+ [x: string]: any;
10
11
  currentFile: string;
11
12
  sizeBytes: number;
12
- lastSeq: number;
13
13
  rotateBytes: number;
14
14
  logsDir: string;
15
15
  }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
@@ -12,8 +12,8 @@ export declare function POST(c: Context): Promise<(Response & import("hono").Typ
12
12
  run: {
13
13
  id: string;
14
14
  jobId: string;
15
- trigger: import("@lovelybunch/core").ScheduledJobTrigger;
16
- status: import("@lovelybunch/core").ScheduledJobRunStatus;
15
+ trigger: import("@lovelybunch/types").ScheduledJobTrigger;
16
+ status: import("@lovelybunch/types").ScheduledJobRunStatus;
17
17
  startedAt: string;
18
18
  finishedAt?: string;
19
19
  outputPath?: string;
@@ -10,8 +10,8 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
10
10
  data: {
11
11
  id: string;
12
12
  jobId: string;
13
- trigger: import("@lovelybunch/core").ScheduledJobTrigger;
14
- status: import("@lovelybunch/core").ScheduledJobRunStatus;
13
+ trigger: import("@lovelybunch/types").ScheduledJobTrigger;
14
+ status: import("@lovelybunch/types").ScheduledJobRunStatus;
15
15
  startedAt: string;
16
16
  finishedAt?: string;
17
17
  outputPath?: string;
@@ -7,7 +7,7 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
7
7
  runningCount: number;
8
8
  jobs: {
9
9
  id: string;
10
- status: import("@lovelybunch/core").ScheduledJobStatus;
10
+ status: import("@lovelybunch/types").ScheduledJobStatus;
11
11
  nextRunAt?: string;
12
12
  lastRunAt?: string;
13
13
  timerActive: boolean;
@@ -13,7 +13,7 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
13
13
  intent?: string;
14
14
  content?: string;
15
15
  author: {
16
- type: import("@lovelybunch/core").AuthorType;
16
+ type: import("@lovelybunch/types").AuthorType;
17
17
  id: string;
18
18
  name: string;
19
19
  email?: string;
@@ -48,7 +48,7 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
48
48
  version: string;
49
49
  name: string;
50
50
  description: string;
51
- type: import("@lovelybunch/core").FeatureFlagType;
51
+ type: import("@lovelybunch/types").FeatureFlagType;
52
52
  defaultValue: any;
53
53
  scopes: string[];
54
54
  targets: {
@@ -96,7 +96,7 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
96
96
  minimumSampleSize: number;
97
97
  testType: "two-tailed" | "one-tailed";
98
98
  };
99
- status: import("@lovelybunch/core").ExperimentStatus;
99
+ status: import("@lovelybunch/types").ExperimentStatus;
100
100
  startedAt?: string;
101
101
  endedAt?: string;
102
102
  }[];
@@ -134,7 +134,7 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
134
134
  schedule?: string;
135
135
  rollbackPlan?: string;
136
136
  };
137
- status: import("@lovelybunch/core").CPStatus;
137
+ status: import("@lovelybunch/types").CPStatus;
138
138
  comments?: {
139
139
  id: string;
140
140
  author: string;
@@ -177,7 +177,7 @@ export declare function PATCH(c: Context): Promise<(Response & import("hono").Ty
177
177
  intent?: string;
178
178
  content?: string;
179
179
  author: {
180
- type: import("@lovelybunch/core").AuthorType;
180
+ type: import("@lovelybunch/types").AuthorType;
181
181
  id: string;
182
182
  name: string;
183
183
  email?: string;
@@ -212,7 +212,7 @@ export declare function PATCH(c: Context): Promise<(Response & import("hono").Ty
212
212
  version: string;
213
213
  name: string;
214
214
  description: string;
215
- type: import("@lovelybunch/core").FeatureFlagType;
215
+ type: import("@lovelybunch/types").FeatureFlagType;
216
216
  defaultValue: any;
217
217
  scopes: string[];
218
218
  targets: {
@@ -260,7 +260,7 @@ export declare function PATCH(c: Context): Promise<(Response & import("hono").Ty
260
260
  minimumSampleSize: number;
261
261
  testType: "two-tailed" | "one-tailed";
262
262
  };
263
- status: import("@lovelybunch/core").ExperimentStatus;
263
+ status: import("@lovelybunch/types").ExperimentStatus;
264
264
  startedAt?: string;
265
265
  endedAt?: string;
266
266
  }[];
@@ -298,7 +298,7 @@ export declare function PATCH(c: Context): Promise<(Response & import("hono").Ty
298
298
  schedule?: string;
299
299
  rollbackPlan?: string;
300
300
  };
301
- status: import("@lovelybunch/core").CPStatus;
301
+ status: import("@lovelybunch/types").CPStatus;
302
302
  comments?: {
303
303
  id: string;
304
304
  author: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovelybunch/api",
3
- "version": "1.0.75-alpha.4",
3
+ "version": "1.0.75-alpha.5",
4
4
  "type": "module",
5
5
  "main": "dist/server-with-static.js",
6
6
  "exports": {
@@ -34,11 +34,13 @@
34
34
  "license": "ISC",
35
35
  "description": "Coconut API server",
36
36
  "dependencies": {
37
+ "@ai-sdk/anthropic": "^3.0.41",
37
38
  "@hono/node-server": "^1.13.7",
38
39
  "@hono/node-ws": "^1.0.6",
39
- "@lovelybunch/core": "^1.0.75-alpha.4",
40
- "@lovelybunch/mcp": "^1.0.75-alpha.4",
41
- "@lovelybunch/types": "^1.0.75-alpha.4",
40
+ "@lovelybunch/core": "^1.0.75-alpha.5",
41
+ "@lovelybunch/mcp": "^1.0.75-alpha.5",
42
+ "@lovelybunch/types": "^1.0.75-alpha.5",
43
+ "ai": "^6.0.79",
42
44
  "arctic": "^1.9.2",
43
45
  "bcrypt": "^5.1.1",
44
46
  "cookie": "^0.6.0",
@@ -1 +1 @@
1
- import{r as a,A as p,j as e,J as v,bj as y,B as N,v as w,C as b}from"./index-Df8kpDhM.js";import{C as c,a as d,b as k,c as C}from"./card-C4vq6AMz.js";import{B as m}from"./badge-DS8SPg0q.js";import{R as E}from"./refresh-cw-CaOTs34G.js";const A=5e3;function $(){const[n,o]=a.useState([]),[i,x]=a.useState(!0),[h,u]=a.useState(new Set),l=a.useCallback(async()=>{x(!0);try{const s=await fetch(`${p}/api/v1/events?limit=${A}`);if(!s.ok)throw new Error("Failed to load events");const t=await s.json();o(Array.isArray(t.items)?[...t.items].reverse():[])}catch(s){console.error("Failed to load events:",s),o([])}finally{x(!1)}},[]),g=a.useCallback(s=>{u(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},[]);a.useEffect(()=>{l()},[l]);const f=s=>{if(!s)return"Unknown time";try{return new Date(s).toLocaleString()}catch{return s}},j=s=>{switch(s?.toLowerCase()){case"error":return"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200";case"warn":case"warning":return"bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200";case"info":return"bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200";case"debug":return"bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200";default:return"bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200"}};return i?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Activity"}),e.jsx("p",{className:"text-muted-foreground",children:"View system activity and events"})]}),e.jsx(c,{children:e.jsx(d,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-center",children:[e.jsx(v,{className:"h-8 w-8 animate-spin text-muted-foreground"}),e.jsx("span",{className:"ml-2 text-muted-foreground",children:"Loading events..."})]})})})]}):n.length===0?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Activity"}),e.jsx("p",{className:"text-muted-foreground",children:"View system activity and events"})]}),e.jsx(c,{children:e.jsx(d,{className:"pt-6",children:e.jsxs("div",{className:"text-center",children:[e.jsx(y,{className:"mx-auto h-12 w-12 text-muted-foreground"}),e.jsx("h3",{className:"mt-4 text-lg font-semibold",children:"No Events Found"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:"Activity events will appear here as they occur."})]})})})]}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Activity"}),e.jsxs("p",{className:"text-muted-foreground",children:["View system activity and events (",n.length," events)"]})]}),e.jsxs(N,{variant:"outline",size:"sm",onClick:()=>void l(),disabled:i,children:[e.jsx(E,{className:`h-4 w-4 mr-2 ${i?"animate-spin":""}`}),"Refresh"]})]}),e.jsx("div",{className:"space-y-3",children:n.map(s=>{const t=h.has(s.seq);return e.jsxs(c,{className:"transition-colors",children:[e.jsx(k,{className:"py-3 cursor-pointer hover:bg-muted/30",onClick:()=>g(s.seq),children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"flex items-start gap-2 flex-1 min-w-0",children:[t?e.jsx(w,{className:"h-4 w-4 mt-0.5 text-muted-foreground shrink-0"}):e.jsx(b,{className:"h-4 w-4 mt-0.5 text-muted-foreground shrink-0"}),e.jsxs("div",{className:"space-y-1 flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsxs(C,{className:"text-sm font-medium",children:["#",s.seq]}),s.kind&&e.jsx(m,{variant:"outline",className:"text-xs",children:s.kind}),s.level&&e.jsx(m,{className:`text-xs ${j(s.level)}`,children:s.level})]}),s.message&&e.jsx("p",{className:`text-sm text-muted-foreground ${t?"":"truncate"}`,children:s.message})]})]}),e.jsx("span",{className:"text-xs text-muted-foreground whitespace-nowrap",children:f(s.ts)})]})}),t&&e.jsx(d,{className:"pt-0 pb-4",children:e.jsx("pre",{className:"text-xs bg-muted p-3 rounded-md overflow-x-auto",children:JSON.stringify(s,null,2)})})]},s.seq)})})]})}export{$ as default};
1
+ import{r as a,A as p,j as e,H as v,bh as y,B as N,v as w,C as b}from"./index-BlLRLvWP.js";import{C as c,a as d,b as k,c as C}from"./card-BguljVtN.js";import{B as m}from"./badge-DvLOhob-.js";import{R as E}from"./refresh-cw-SQsUc3_C.js";const A=5e3;function $(){const[n,o]=a.useState([]),[i,x]=a.useState(!0),[h,u]=a.useState(new Set),l=a.useCallback(async()=>{x(!0);try{const s=await fetch(`${p}/api/v1/events?limit=${A}`);if(!s.ok)throw new Error("Failed to load events");const t=await s.json();o(Array.isArray(t.items)?[...t.items].reverse():[])}catch(s){console.error("Failed to load events:",s),o([])}finally{x(!1)}},[]),g=a.useCallback(s=>{u(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},[]);a.useEffect(()=>{l()},[l]);const f=s=>{if(!s)return"Unknown time";try{return new Date(s).toLocaleString()}catch{return s}},j=s=>{switch(s?.toLowerCase()){case"error":return"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200";case"warn":case"warning":return"bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200";case"info":return"bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200";case"debug":return"bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200";default:return"bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200"}};return i?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Activity"}),e.jsx("p",{className:"text-muted-foreground",children:"View system activity and events"})]}),e.jsx(c,{children:e.jsx(d,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-center",children:[e.jsx(v,{className:"h-8 w-8 animate-spin text-muted-foreground"}),e.jsx("span",{className:"ml-2 text-muted-foreground",children:"Loading events..."})]})})})]}):n.length===0?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Activity"}),e.jsx("p",{className:"text-muted-foreground",children:"View system activity and events"})]}),e.jsx(c,{children:e.jsx(d,{className:"pt-6",children:e.jsxs("div",{className:"text-center",children:[e.jsx(y,{className:"mx-auto h-12 w-12 text-muted-foreground"}),e.jsx("h3",{className:"mt-4 text-lg font-semibold",children:"No Events Found"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:"Activity events will appear here as they occur."})]})})})]}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold tracking-tight",children:"Activity"}),e.jsxs("p",{className:"text-muted-foreground",children:["View system activity and events (",n.length," events)"]})]}),e.jsxs(N,{variant:"outline",size:"sm",onClick:()=>void l(),disabled:i,children:[e.jsx(E,{className:`h-4 w-4 mr-2 ${i?"animate-spin":""}`}),"Refresh"]})]}),e.jsx("div",{className:"space-y-3",children:n.map(s=>{const t=h.has(s.seq);return e.jsxs(c,{className:"transition-colors",children:[e.jsx(k,{className:"py-3 cursor-pointer hover:bg-muted/30",onClick:()=>g(s.seq),children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"flex items-start gap-2 flex-1 min-w-0",children:[t?e.jsx(w,{className:"h-4 w-4 mt-0.5 text-muted-foreground shrink-0"}):e.jsx(b,{className:"h-4 w-4 mt-0.5 text-muted-foreground shrink-0"}),e.jsxs("div",{className:"space-y-1 flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsxs(C,{className:"text-sm font-medium",children:["#",s.seq]}),s.kind&&e.jsx(m,{variant:"outline",className:"text-xs",children:s.kind}),s.level&&e.jsx(m,{className:`text-xs ${j(s.level)}`,children:s.level})]}),s.message&&e.jsx("p",{className:`text-sm text-muted-foreground ${t?"":"truncate"}`,children:s.message})]})]}),e.jsx("span",{className:"text-xs text-muted-foreground whitespace-nowrap",children:f(s.ts)})]})}),t&&e.jsx(d,{className:"pt-0 pb-4",children:e.jsx("pre",{className:"text-xs bg-muted p-3 rounded-md overflow-x-auto",children:JSON.stringify(s,null,2)})})]},s.seq)})})]})}export{$ as default};
@@ -1 +1 @@
1
- import{Q as A,u as E,r as h,j as e,B as i,L as d,R as k,W as B,p as S,A as N}from"./index-Df8kpDhM.js";import{C as l,b as o,a as m,c as f,d as z}from"./card-C4vq6AMz.js";import{B as v}from"./badge-DS8SPg0q.js";import{A as u}from"./arrow-left-TQT21N4S.js";const D=t=>t?Array.isArray(t)?t.filter(r=>typeof r=="string").map(r=>r.trim()).filter(Boolean):typeof t=="string"?t.split(",").map(r=>r.trim()).filter(Boolean):[]:[],c={blue:{bg:"#dbeafe",border:"#2563eb",text:"#1e40af"},green:{bg:"#dcfce7",border:"#16a34a",text:"#166534"},red:{bg:"#fee2e2",border:"#dc2626",text:"#991b1b"},emerald:{bg:"#d1fae5",border:"#10b981",text:"#047857"},purple:{bg:"#f3e8ff",border:"#9333ea",text:"#6b21a8"},orange:{bg:"#fed7aa",border:"#ea580c",text:"#9a3412"},yellow:{bg:"#fef9c3",border:"#eab308",text:"#854d0e"},teal:{bg:"#ccfbf1",border:"#14b8a6",text:"#0f766e"},indigo:{bg:"#e0e7ff",border:"#6366f1",text:"#4338ca"},pink:{bg:"#fce7f3",border:"#ec4899",text:"#9f1239"},cyan:{bg:"#cffafe",border:"#06b6d4",text:"#155e75"},slate:{bg:"#f1f5f9",border:"#475569",text:"#334155"},gray:{bg:"#f3f4f6",border:"#6b7280",text:"#374151"}};function F(){const t=A(),r=E(),[s,y]=h.useState(null),[w,j]=h.useState(!0),[p,x]=h.useState(null);h.useEffect(()=>{async function a(){try{j(!0);const g=await(await fetch(`${N}/api/v1/agents/${t.id}`)).json();g.success?y(g.document):x(g.error||"Failed to fetch agent")}catch(n){x(n instanceof Error?n.message:"Unknown error")}finally{j(!1)}}t.id&&a()},[t.id]);const C=async()=>{if(!(!s||!confirm("Are you sure you want to delete this agent?")))try{const n=await(await fetch(`${N}/api/v1/agents/${s.filename.replace(".md","")}`,{method:"DELETE"})).json();n.success?r("/agents"):x(n.error?.message||"Failed to delete agent")}catch(a){x(a instanceof Error?a.message:"Unknown error")}};if(w)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"h-8 bg-muted rounded w-64 animate-pulse"}),e.jsx("div",{className:"h-4 bg-muted rounded w-32 animate-pulse mt-2"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,className:"px-2 hover:bg-transparent",children:e.jsx(d,{to:"/agents",className:"flex items-center text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})})})]}),e.jsx(l,{children:e.jsxs(o,{children:[e.jsx("div",{className:"h-6 bg-muted rounded w-48 animate-pulse"}),e.jsx("div",{className:"h-4 bg-muted rounded w-64 animate-pulse"})]})})]});if(p||!s)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Agent Not Found"}),e.jsx("p",{className:"text-muted-foreground",children:"The requested agent could not be found"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,className:"px-2 hover:bg-transparent",children:e.jsx(d,{to:"/agents",className:"flex items-center text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})})})]}),e.jsx(l,{children:e.jsx(m,{className:"pt-6",children:e.jsx("div",{className:"text-center",children:e.jsx("p",{className:"text-destructive",children:p||"Agent not found"})})})})]});const b=D(s.metadata.tools);return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"space-y-1",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsx("h1",{className:"text-xl sm:text-2xl font-bold tracking-tight",children:s.metadata.name}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(d,{to:"/agents",className:"flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})}),e.jsx(i,{variant:"outline",size:"sm",asChild:!0,children:e.jsxs(d,{to:`/agents/${s.filename.replace(".md","")}/edit`,children:[e.jsx(k,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Edit"})]})}),e.jsxs(i,{variant:"destructive",size:"sm",onClick:C,children:[e.jsx(B,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Delete"})]})]})]})}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[e.jsxs("div",{className:"lg:col-span-2 space-y-6",children:[e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Description"})}),e.jsx(m,{children:e.jsx("p",{children:s.metadata.description})})]}),s.content&&e.jsxs(l,{children:[e.jsxs(o,{children:[e.jsx(f,{children:"Instructions"}),e.jsx(z,{children:"System prompt and behavior instructions for this agent"})]}),e.jsx(m,{children:e.jsx("pre",{className:"whitespace-pre-wrap text-sm bg-muted p-4 rounded-md",children:s.content})})]})]}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Actions"})}),e.jsx(m,{className:"space-y-2",children:e.jsx(i,{variant:"default",className:"w-full justify-start",asChild:!0,children:e.jsxs(d,{to:`/terminal/ag-${s.filename.replace(".md","")}`,children:[e.jsx(S,{className:"h-4 w-4 mr-2"}),"Start Agent"]})})})]}),e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Information"})}),e.jsxs(m,{className:"space-y-2",children:[s.metadata.color&&e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium mb-2",children:"Color"}),e.jsx(v,{variant:"outline",className:"capitalize border-2",style:{backgroundColor:c[s.metadata.color]?.bg||c.blue.bg,color:c[s.metadata.color]?.text||c.blue.text,borderColor:c[s.metadata.color]?.border||c.blue.border},children:s.metadata.color})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium",children:"Tools"}),b.length>0?e.jsx("div",{className:"flex flex-wrap gap-2 mt-1",children:b.map(a=>e.jsx(v,{variant:"secondary",children:a},a))}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"No specific tools configured - inherits all tools"})]})]})]})]})]})]})}export{F as default};
1
+ import{P as A,u as E,r as h,j as e,B as i,L as d,Q as k,V as B,p as S,A as N}from"./index-BlLRLvWP.js";import{C as l,b as o,a as m,c as f,d as z}from"./card-BguljVtN.js";import{B as v}from"./badge-DvLOhob-.js";import{A as u}from"./arrow-left-DZzHrGWA.js";const D=t=>t?Array.isArray(t)?t.filter(r=>typeof r=="string").map(r=>r.trim()).filter(Boolean):typeof t=="string"?t.split(",").map(r=>r.trim()).filter(Boolean):[]:[],c={blue:{bg:"#dbeafe",border:"#2563eb",text:"#1e40af"},green:{bg:"#dcfce7",border:"#16a34a",text:"#166534"},red:{bg:"#fee2e2",border:"#dc2626",text:"#991b1b"},emerald:{bg:"#d1fae5",border:"#10b981",text:"#047857"},purple:{bg:"#f3e8ff",border:"#9333ea",text:"#6b21a8"},orange:{bg:"#fed7aa",border:"#ea580c",text:"#9a3412"},yellow:{bg:"#fef9c3",border:"#eab308",text:"#854d0e"},teal:{bg:"#ccfbf1",border:"#14b8a6",text:"#0f766e"},indigo:{bg:"#e0e7ff",border:"#6366f1",text:"#4338ca"},pink:{bg:"#fce7f3",border:"#ec4899",text:"#9f1239"},cyan:{bg:"#cffafe",border:"#06b6d4",text:"#155e75"},slate:{bg:"#f1f5f9",border:"#475569",text:"#334155"},gray:{bg:"#f3f4f6",border:"#6b7280",text:"#374151"}};function F(){const t=A(),r=E(),[s,y]=h.useState(null),[w,j]=h.useState(!0),[p,x]=h.useState(null);h.useEffect(()=>{async function a(){try{j(!0);const g=await(await fetch(`${N}/api/v1/agents/${t.id}`)).json();g.success?y(g.document):x(g.error||"Failed to fetch agent")}catch(n){x(n instanceof Error?n.message:"Unknown error")}finally{j(!1)}}t.id&&a()},[t.id]);const C=async()=>{if(!(!s||!confirm("Are you sure you want to delete this agent?")))try{const n=await(await fetch(`${N}/api/v1/agents/${s.filename.replace(".md","")}`,{method:"DELETE"})).json();n.success?r("/agents"):x(n.error?.message||"Failed to delete agent")}catch(a){x(a instanceof Error?a.message:"Unknown error")}};if(w)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"h-8 bg-muted rounded w-64 animate-pulse"}),e.jsx("div",{className:"h-4 bg-muted rounded w-32 animate-pulse mt-2"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,className:"px-2 hover:bg-transparent",children:e.jsx(d,{to:"/agents",className:"flex items-center text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})})})]}),e.jsx(l,{children:e.jsxs(o,{children:[e.jsx("div",{className:"h-6 bg-muted rounded w-48 animate-pulse"}),e.jsx("div",{className:"h-4 bg-muted rounded w-64 animate-pulse"})]})})]});if(p||!s)return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Agent Not Found"}),e.jsx("p",{className:"text-muted-foreground",children:"The requested agent could not be found"})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,className:"px-2 hover:bg-transparent",children:e.jsx(d,{to:"/agents",className:"flex items-center text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})})})]}),e.jsx(l,{children:e.jsx(m,{className:"pt-6",children:e.jsx("div",{className:"text-center",children:e.jsx("p",{className:"text-destructive",children:p||"Agent not found"})})})})]});const b=D(s.metadata.tools);return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"space-y-1",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsx("h1",{className:"text-xl sm:text-2xl font-bold tracking-tight",children:s.metadata.name}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx(i,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(d,{to:"/agents",className:"flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(u,{className:"h-4 w-4"})})}),e.jsx(i,{variant:"outline",size:"sm",asChild:!0,children:e.jsxs(d,{to:`/agents/${s.filename.replace(".md","")}/edit`,children:[e.jsx(k,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Edit"})]})}),e.jsxs(i,{variant:"destructive",size:"sm",onClick:C,children:[e.jsx(B,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Delete"})]})]})]})}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[e.jsxs("div",{className:"lg:col-span-2 space-y-6",children:[e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Description"})}),e.jsx(m,{children:e.jsx("p",{children:s.metadata.description})})]}),s.content&&e.jsxs(l,{children:[e.jsxs(o,{children:[e.jsx(f,{children:"Instructions"}),e.jsx(z,{children:"System prompt and behavior instructions for this agent"})]}),e.jsx(m,{children:e.jsx("pre",{className:"whitespace-pre-wrap text-sm bg-muted p-4 rounded-md",children:s.content})})]})]}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Actions"})}),e.jsx(m,{className:"space-y-2",children:e.jsx(i,{variant:"default",className:"w-full justify-start",asChild:!0,children:e.jsxs(d,{to:`/terminal/ag-${s.filename.replace(".md","")}`,children:[e.jsx(S,{className:"h-4 w-4 mr-2"}),"Start Agent"]})})})]}),e.jsxs(l,{children:[e.jsx(o,{children:e.jsx(f,{children:"Information"})}),e.jsxs(m,{className:"space-y-2",children:[s.metadata.color&&e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium mb-2",children:"Color"}),e.jsx(v,{variant:"outline",className:"capitalize border-2",style:{backgroundColor:c[s.metadata.color]?.bg||c.blue.bg,color:c[s.metadata.color]?.text||c.blue.text,borderColor:c[s.metadata.color]?.border||c.blue.border},children:s.metadata.color})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium",children:"Tools"}),b.length>0?e.jsx("div",{className:"flex flex-wrap gap-2 mt-1",children:b.map(a=>e.jsx(v,{variant:"secondary",children:a},a))}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"No specific tools configured - inherits all tools"})]})]})]})]})]})]})}export{F as default};