@lovelybunch/api 1.0.78-alpha.2 → 1.0.78-alpha.4

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 (141) hide show
  1. package/dist/lib/auth/auth-manager.d.ts +1 -1
  2. package/dist/lib/auth/auth-manager.js +2 -1
  3. package/dist/lib/symlinks/symlink-manager.d.ts +3 -4
  4. package/dist/lib/symlinks/symlink-manager.js +49 -30
  5. package/dist/lib/terminal/terminal-manager.d.ts +8 -5
  6. package/dist/lib/terminal/terminal-manager.js +29 -5
  7. package/dist/middleware/auth.d.ts +23 -2
  8. package/dist/middleware/auth.js +44 -4
  9. package/dist/routes/api/v1/ai/route.js +117 -4
  10. package/dist/routes/api/v1/api-keys/route.js +7 -1
  11. package/dist/routes/api/v1/jobs/[id]/route.d.ts +20 -20
  12. package/dist/routes/api/v1/jobs/route.d.ts +20 -20
  13. package/dist/routes/api/v1/knowledge/[filename]/route.js +29 -7
  14. package/dist/routes/api/v1/knowledge/route.js +13 -3
  15. package/dist/routes/api/v1/terminal/[taskId]/create/route.js +2 -1
  16. package/dist/routes/api/v1/terminal/[taskId]/destroy/route.js +2 -1
  17. package/dist/routes/api/v1/terminal/[taskId]/resize/route.js +2 -1
  18. package/dist/routes/api/v1/terminal/code/route.js +2 -1
  19. package/dist/routes/api/v1/terminal/sessions/route.js +5 -3
  20. package/dist/server-with-static.js +3 -3
  21. package/dist/server.js +3 -3
  22. package/package.json +4 -4
  23. package/static/assets/{ActivityPage-B83wvBeD.js → ActivityPage-CtFAFqlg.js} +1 -1
  24. package/static/assets/{AgentsContextEditPage-CgHVDbMV.js → AgentsContextEditPage-CsRJvzE6.js} +1 -1
  25. package/static/assets/{AgentsContextPage-DMf6khxC.js → AgentsContextPage-CWCs8CgG.js} +1 -1
  26. package/static/assets/{ApiKeysSettingsPage-DzwmYsom.js → ApiKeysSettingsPage-B4b_fmJg.js} +1 -1
  27. package/static/assets/{AuthSettingsPage-B5auAs_s.js → AuthSettingsPage-O3UdLrHC.js} +1 -1
  28. package/static/assets/{CallbackPage-Cxc5lXE4.js → CallbackPage-WTwVSxdx.js} +1 -1
  29. package/static/assets/{CoconutCallbackPage-D7Xkrh70.js → CoconutCallbackPage-LEWgUV8J.js} +1 -1
  30. package/static/assets/{CodePage-D37jAzN1.js → CodePage-DpVmg_UD.js} +1 -1
  31. package/static/assets/{CollapsibleSection-Bp5C0iRa.js → CollapsibleSection-BHag26Vf.js} +1 -1
  32. package/static/assets/{DashboardPage-DvWWsMjr.js → DashboardPage-BZnCikpf.js} +1 -1
  33. package/static/assets/{GitPage-yXgpwI2f.js → GitPage-DD6dgeNu.js} +1 -1
  34. package/static/assets/{GitSettingsPage-B5bgtLBU.js → GitSettingsPage-CLHCZ6at.js} +1 -1
  35. package/static/assets/{IdentityPage-Dpr6Z5Id.js → IdentityPage-DtzLSTYd.js} +1 -1
  36. package/static/assets/{ImplementationStepsEditor-B2e4ML0a.js → ImplementationStepsEditor-Ca1aygKs.js} +1 -1
  37. package/static/assets/{IntegrationsSettingsPage-CHknhE_l.js → IntegrationsSettingsPage-C2tzpbuI.js} +1 -1
  38. package/static/assets/{JobDetailPage-BnuDmxZF.js → JobDetailPage-B03z4VgG.js} +1 -1
  39. package/static/assets/{KnowledgeDetailPage-DFxjt46s.js → KnowledgeDetailPage-XslT5GUv.js} +1 -1
  40. package/static/assets/{KnowledgeEditPage-Bu1l5VHq.js → KnowledgeEditPage-5NFEnGJh.js} +1 -1
  41. package/static/assets/{KnowledgePage-CzPB44SA.js → KnowledgePage-Dzh409qU.js} +1 -1
  42. package/static/assets/{LoginPage-D_ZO_RBy.js → LoginPage-IDVkR1zN.js} +1 -1
  43. package/static/assets/{MailInboxPage-CXlwKTvH.js → MailInboxPage-CXaBqNl2.js} +1 -1
  44. package/static/assets/{MailProcessingModal-_C2SsbSm.js → MailProcessingModal-BWyzTMEv.js} +1 -1
  45. package/static/assets/{MailReadPage-BtgLL4bW.js → MailReadPage-DPGuT0gC.js} +1 -1
  46. package/static/assets/{MailSentPage-nhZKfZOk.js → MailSentPage-Dtq37Kap.js} +1 -1
  47. package/static/assets/{McpSettingsPage-C6PdoBPD.js → McpSettingsPage-BiCSPaAJ.js} +1 -1
  48. package/static/assets/{MemoryEditPage-BpioH6_S.js → MemoryEditPage-Dfa6MsnE.js} +1 -1
  49. package/static/assets/{MemoryPage-DrPL8CG7.js → MemoryPage-BqUngqIS.js} +1 -1
  50. package/static/assets/{NewKnowledgePage-rqgKv0VA.js → NewKnowledgePage-BmYwcO98.js} +1 -1
  51. package/static/assets/{NewSkillPage-0pSUX9z9.js → NewSkillPage-BfNaXH37.js} +1 -1
  52. package/static/assets/{NewTaskPage-BpCJGis6.js → NewTaskPage-Ctmh2uiJ.js} +1 -1
  53. package/static/assets/{NotFoundPage-sSYe1QSz.js → NotFoundPage-a2erdq4H.js} +1 -1
  54. package/static/assets/{NotificationsSettingsPage-CS_ZT6t0.js → NotificationsSettingsPage-BB9QuyUf.js} +1 -1
  55. package/static/assets/{PromptsSettingsPage-DTq8cZqP.js → PromptsSettingsPage-BZLwTFcd.js} +1 -1
  56. package/static/assets/{ResourceDetailPage-DYriLbDS.js → ResourceDetailPage-DRWNjykw.js} +1 -1
  57. package/static/assets/{ResourcesPage-D8QBQrZP.js → ResourcesPage-C3Lx8hz_.js} +1 -1
  58. package/static/assets/{RoleEditPage-Ci_1L_e_.js → RoleEditPage-W9SV6Mwr.js} +1 -1
  59. package/static/assets/{RolePage-DMJ7_wD0.js → RolePage-DWWo77tA.js} +1 -1
  60. package/static/assets/{RulesSettingsPage-CuB55bRV.js → RulesSettingsPage-BKsadZ7r.js} +1 -1
  61. package/static/assets/{RunDetailPage-CBW-swIi.js → RunDetailPage-C6miynGX.js} +1 -1
  62. package/static/assets/{SchedulePage-BIklILDy.js → SchedulePage-B6s-CkVg.js} +1 -1
  63. package/static/assets/{SkillDetailPage-D-1PWQiM.js → SkillDetailPage-DYkLxRjB.js} +1 -1
  64. package/static/assets/{SkillEditPage-BZB-YL56.js → SkillEditPage-DIB2lUMz.js} +1 -1
  65. package/static/assets/{SkillsPage-BezXmUjc.js → SkillsPage-BgR2gdCy.js} +1 -1
  66. package/static/assets/{SkillsSettingsPage-Cqo9_iDG.js → SkillsSettingsPage-CoDOG0YQ.js} +1 -1
  67. package/static/assets/{SourceInput-TEQpt4P-.js → SourceInput-CS6u1yPi.js} +1 -1
  68. package/static/assets/{TagInput-DBUiVBgy.js → TagInput-C3WzbX6I.js} +1 -1
  69. package/static/assets/{TaskDetailPage-Dq0gDy_e.js → TaskDetailPage-DEBBE0D8.js} +1 -1
  70. package/static/assets/{TaskEditPage-CWGvjTjo.js → TaskEditPage-B26tEsUP.js} +1 -1
  71. package/static/assets/{TasksPage-BIPx8Qde.js → TasksPage-pqQ7VlC3.js} +1 -1
  72. package/static/assets/{TeamEditPage-BlNa1eMV.js → TeamEditPage-C6DugOii.js} +1 -1
  73. package/static/assets/{TeamPage-D1usM-fA.js → TeamPage-BDqQZ6Rr.js} +1 -1
  74. package/static/assets/{TerminalPage-CLh6hap0.js → TerminalPage-pjss7X1h.js} +1 -1
  75. package/static/assets/{TerminalSessionPage-DaHcsdNf.js → TerminalSessionPage-C9sJ_13t.js} +1 -1
  76. package/static/assets/{UserPreferencesPage-CL-nPXv7.js → UserPreferencesPage-BrpKf14p.js} +1 -1
  77. package/static/assets/{UserSettingsPage-BGIalWgn.js → UserSettingsPage-BbazpvdQ.js} +1 -1
  78. package/static/assets/{UtilitiesPage-ewlEzigp.js → UtilitiesPage-niclH8kb.js} +1 -1
  79. package/static/assets/{alert-0GENnoy_.js → alert-DBhIskRX.js} +1 -1
  80. package/static/assets/{arrow-down-Bfya-JPw.js → arrow-down-TpeNydxP.js} +1 -1
  81. package/static/assets/{arrow-left-CY9PaWRG.js → arrow-left-_lXkdm9Q.js} +1 -1
  82. package/static/assets/{arrow-up-BAAEIUsa.js → arrow-up-DaIMsmSO.js} +1 -1
  83. package/static/assets/{arrow-up-down-0F-DzXlw.js → arrow-up-down-C7wqirJv.js} +1 -1
  84. package/static/assets/{badge-D1sVaZJG.js → badge-TeAh_Zh0.js} +1 -1
  85. package/static/assets/{browser-modal-CELhtOVM.js → browser-modal-BpGFpZZj.js} +1 -1
  86. package/static/assets/{card-D2eA49nP.js → card-CiLixwCG.js} +1 -1
  87. package/static/assets/{chevron-left-Cbc591ge.js → chevron-left-CuMfw52D.js} +1 -1
  88. package/static/assets/{chevron-up-DD_GdI6e.js → chevron-up-B4J4D5aE.js} +1 -1
  89. package/static/assets/{chevrons-up-CQ8ZAERh.js → chevrons-up-Dcs-Dj4B.js} +1 -1
  90. package/static/assets/{circle-alert-DsESVtwL.js → circle-alert-nI75emvr.js} +1 -1
  91. package/static/assets/{circle-check-big-HtBmMXFt.js → circle-check-big-CxxxVvOw.js} +1 -1
  92. package/static/assets/{circle-check-BXiPFdlh.js → circle-check-k6ER9afD.js} +1 -1
  93. package/static/assets/{circle-play-KOICOGsB.js → circle-play-B4D0d7YW.js} +1 -1
  94. package/static/assets/{circle-x-B_4fmWCG.js → circle-x-BzPgPb47.js} +1 -1
  95. package/static/assets/{clipboard-ByOf6HYl.js → clipboard-CLObCrC4.js} +1 -1
  96. package/static/assets/{clock-CdH0GtRs.js → clock-BK-8XMqv.js} +1 -1
  97. package/static/assets/{code-7mdwwNlt.js → code-lhIVzb1q.js} +1 -1
  98. package/static/assets/{download-Bh7rihtL.js → download-ChgFRTfC.js} +1 -1
  99. package/static/assets/{external-link-DGl8WNOe.js → external-link-D4kianlP.js} +1 -1
  100. package/static/assets/{eye-C_ckl4MB.js → eye-H1JnZ9E9.js} +1 -1
  101. package/static/assets/{folder-git-2-C9MVgN94.js → folder-git-2-BZGvXcyj.js} +1 -1
  102. package/static/assets/{globe-BvwRv4le.js → globe-DAzCOUla.js} +1 -1
  103. package/static/assets/{index-C611wGVc.js → index-B7UEVagI.js} +1 -1
  104. package/static/assets/{index-DrTHjwZ8.js → index-Bik-wLXi.js} +1 -1
  105. package/static/assets/{index-5M1EX2JZ.js → index-BlOxV6pf.js} +1 -1
  106. package/static/assets/{index-BUOPcczo.js → index-C7dpn8dK.js} +1 -1
  107. package/static/assets/{index-CnEgD2Gk.js → index-C9wsYS8C.js} +1 -1
  108. package/static/assets/{index-CzcqLknE.js → index-Ck9sMDuo.js} +1 -1
  109. package/static/assets/{index-DFPcCMnD.js → index-DMeIDO6W.js} +1 -1
  110. package/static/assets/{index-BjiLTiAs.js → index-DOpjlxVe.js} +1 -1
  111. package/static/assets/{index-CjL8t7WM.js → index-DT4K0HgO.js} +1 -1
  112. package/static/assets/{index-Dx8evZfS.js → index-DeF-CCVg.js} +1 -1
  113. package/static/assets/{index-ja6BPXln.js → index-DkvhkCo1.js} +1 -1
  114. package/static/assets/{index-BD57V9U9.js → index-DuDW1LwX.js} +1 -1
  115. package/static/assets/{index-D1CqgHy0.js → index-Dy_-mpPq.js} +1 -1
  116. package/static/assets/{index-Bx26Q2JC.js → index-SUQrIHd7.js} +3 -3
  117. package/static/assets/{index-DH0iEeh5.js → index-c-gr7Bew.js} +1 -1
  118. package/static/assets/{index-Ci5Lsqgb.js → index-kJaEkklL.js} +1 -1
  119. package/static/assets/{index-CjU4ihqi.js → index-rslXoTnS.js} +1 -1
  120. package/static/assets/{index-CLD_gdRP.js → index-rwsZ-IsL.js} +1 -1
  121. package/static/assets/{index-CCq3bqJI.js → index-sBbL8_xu.js} +1 -1
  122. package/static/assets/{info-_JNAJSs5.js → info-CVmPHERQ.js} +1 -1
  123. package/static/assets/{label-fHWG59jZ.js → label-n5pqaObd.js} +1 -1
  124. package/static/assets/{markdown-editor-Dmq8d9Xs.js → markdown-editor-Cvh5pZzJ.js} +3 -3
  125. package/static/assets/{message-square-BaejhTPJ.js → message-square-BmnqRsu6.js} +1 -1
  126. package/static/assets/{paperclip-xnYUFZwQ.js → paperclip-BwcNeQ_C.js} +1 -1
  127. package/static/assets/{pause-plM13_Um.js → pause-CUswidZW.js} +1 -1
  128. package/static/assets/{play-DR4AKc9R.js → play-DyZbNGiK.js} +1 -1
  129. package/static/assets/{radio-group-CE9meIEG.js → radio-group-Bzu_d7xN.js} +1 -1
  130. package/static/assets/{refresh-cw-CLSROYiq.js → refresh-cw-DvQ0rmk7.js} +1 -1
  131. package/static/assets/{search-VcMqZsDm.js → search-kc_tG8Rf.js} +1 -1
  132. package/static/assets/{select-ChtjmmOf.js → select-CIOYQA7a.js} +1 -1
  133. package/static/assets/{server-DVlnoAGu.js → server-CWIJxRf0.js} +1 -1
  134. package/static/assets/{switch-BMBFkcUU.js → switch-DczkR77Y.js} +1 -1
  135. package/static/assets/{tabs-DE4DShnU.js → tabs-DOEakD76.js} +1 -1
  136. package/static/assets/{tag-czmQSC6D.js → tag-Dc8sXXlM.js} +1 -1
  137. package/static/assets/{terminal-preview-B8UB7Pz6.js → terminal-preview-D8oASUdZ.js} +1 -1
  138. package/static/assets/{triangle-alert-RuOrTU7H.js → triangle-alert-C-5ixej6.js} +1 -1
  139. package/static/assets/{use-terminal-C3O4m83z.js → use-terminal-xdcf4Z2G.js} +1 -1
  140. package/static/assets/{video-BEV0GqmB.js → video-CBneSE9B.js} +1 -1
  141. package/static/index.html +1 -1
@@ -12,6 +12,16 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
12
12
  id: string;
13
13
  name: string;
14
14
  status: ScheduledJobStatus;
15
+ tags?: string[];
16
+ description?: string;
17
+ model: string;
18
+ metadata: {
19
+ createdAt: string;
20
+ updatedAt: string;
21
+ lastRunAt?: string;
22
+ nextRunAt?: string;
23
+ };
24
+ prompt: string;
15
25
  schedule: {
16
26
  type: "cron";
17
27
  expression: string;
@@ -24,16 +34,6 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
24
34
  timezone?: string;
25
35
  anchorHour?: number;
26
36
  };
27
- description?: string;
28
- prompt: string;
29
- model: string;
30
- metadata: {
31
- createdAt: string;
32
- updatedAt: string;
33
- lastRunAt?: string;
34
- nextRunAt?: string;
35
- };
36
- tags?: string[];
37
37
  contextPaths?: string[];
38
38
  agentId?: string;
39
39
  agentIds?: string[];
@@ -73,6 +73,16 @@ export declare function PATCH(c: Context): Promise<(Response & import("hono").Ty
73
73
  id: string;
74
74
  name: string;
75
75
  status: ScheduledJobStatus;
76
+ tags?: string[];
77
+ description?: string;
78
+ model: string;
79
+ metadata: {
80
+ createdAt: string;
81
+ updatedAt: string;
82
+ lastRunAt?: string;
83
+ nextRunAt?: string;
84
+ };
85
+ prompt: string;
76
86
  schedule: {
77
87
  type: "cron";
78
88
  expression: string;
@@ -85,16 +95,6 @@ export declare function PATCH(c: Context): Promise<(Response & import("hono").Ty
85
95
  timezone?: string;
86
96
  anchorHour?: number;
87
97
  };
88
- description?: string;
89
- prompt: string;
90
- model: string;
91
- metadata: {
92
- createdAt: string;
93
- updatedAt: string;
94
- lastRunAt?: string;
95
- nextRunAt?: string;
96
- };
97
- tags?: string[];
98
98
  contextPaths?: string[];
99
99
  agentId?: string;
100
100
  agentIds?: string[];
@@ -14,6 +14,16 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
14
14
  id: string;
15
15
  name: string;
16
16
  status: ScheduledJobStatus;
17
+ tags?: string[];
18
+ description?: string;
19
+ model: string;
20
+ metadata: {
21
+ createdAt: string;
22
+ updatedAt: string;
23
+ lastRunAt?: string;
24
+ nextRunAt?: string;
25
+ };
26
+ prompt: string;
17
27
  schedule: {
18
28
  type: "cron";
19
29
  expression: string;
@@ -26,16 +36,6 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
26
36
  timezone?: string;
27
37
  anchorHour?: number;
28
38
  };
29
- description?: string;
30
- prompt: string;
31
- model: string;
32
- metadata: {
33
- createdAt: string;
34
- updatedAt: string;
35
- lastRunAt?: string;
36
- nextRunAt?: string;
37
- };
38
- tags?: string[];
39
39
  contextPaths?: string[];
40
40
  agentId?: string;
41
41
  agentIds?: string[];
@@ -69,6 +69,16 @@ export declare function POST(c: Context): Promise<(Response & import("hono").Typ
69
69
  id: string;
70
70
  name: string;
71
71
  status: ScheduledJobStatus;
72
+ tags?: string[];
73
+ description?: string;
74
+ model: string;
75
+ metadata: {
76
+ createdAt: string;
77
+ updatedAt: string;
78
+ lastRunAt?: string;
79
+ nextRunAt?: string;
80
+ };
81
+ prompt: string;
72
82
  schedule: {
73
83
  type: "cron";
74
84
  expression: string;
@@ -81,16 +91,6 @@ export declare function POST(c: Context): Promise<(Response & import("hono").Typ
81
91
  timezone?: string;
82
92
  anchorHour?: number;
83
93
  };
84
- description?: string;
85
- prompt: string;
86
- model: string;
87
- metadata: {
88
- createdAt: string;
89
- updatedAt: string;
90
- lastRunAt?: string;
91
- nextRunAt?: string;
92
- };
93
- tags?: string[];
94
94
  contextPaths?: string[];
95
95
  agentId?: string;
96
96
  agentIds?: string[];
@@ -47,6 +47,22 @@ function generateFilename(title) {
47
47
  .replace(/^-|-$/g, '') // Remove leading/trailing hyphens
48
48
  + '.md';
49
49
  }
50
+ function resolveKnowledgeFile(knowledgePath, filename) {
51
+ const actualFilename = filename.endsWith('.md') ? filename : `${filename}.md`;
52
+ if (!actualFilename ||
53
+ actualFilename.includes('/') ||
54
+ actualFilename.includes('\\') ||
55
+ actualFilename.split(/[\\/]/).some(part => part === '..')) {
56
+ throw new Error('Invalid knowledge filename');
57
+ }
58
+ const resolvedBase = path.resolve(knowledgePath);
59
+ const filePath = path.resolve(resolvedBase, actualFilename);
60
+ const relative = path.relative(resolvedBase, filePath);
61
+ if (relative === '' || relative.startsWith('..') || path.isAbsolute(relative)) {
62
+ throw new Error('Invalid knowledge filename');
63
+ }
64
+ return { actualFilename, filePath };
65
+ }
50
66
  /**
51
67
  * GET /api/v1/knowledge/:filename
52
68
  * Load a specific knowledge document
@@ -55,8 +71,7 @@ app.get('/:filename', async (c) => {
55
71
  try {
56
72
  const filename = c.req.param('filename');
57
73
  const knowledgePath = getKnowledgePath();
58
- const actualFilename = filename.endsWith('.md') ? filename : `${filename}.md`;
59
- const filePath = path.join(knowledgePath, actualFilename);
74
+ const { actualFilename, filePath } = resolveKnowledgeFile(knowledgePath, filename);
60
75
  const [fileContent, stats] = await Promise.all([
61
76
  fs.readFile(filePath, 'utf-8'),
62
77
  fs.stat(filePath)
@@ -84,6 +99,9 @@ app.get('/:filename', async (c) => {
84
99
  });
85
100
  }
86
101
  catch (error) {
102
+ if (error.message === 'Invalid knowledge filename') {
103
+ return c.json({ success: false, error: 'Invalid knowledge filename' }, 400);
104
+ }
87
105
  if (error.code === 'ENOENT') {
88
106
  return c.json({ success: false, error: 'Knowledge document not found' }, 404);
89
107
  }
@@ -100,8 +118,7 @@ app.put('/:filename', async (c) => {
100
118
  const filename = c.req.param('filename');
101
119
  const body = await c.req.json();
102
120
  const knowledgePath = getKnowledgePath();
103
- const actualFilename = filename.endsWith('.md') ? filename : `${filename}.md`;
104
- const filePath = path.join(knowledgePath, actualFilename);
121
+ const { actualFilename, filePath } = resolveKnowledgeFile(knowledgePath, filename);
105
122
  // Check if file exists
106
123
  try {
107
124
  await fs.access(filePath);
@@ -136,7 +153,7 @@ app.put('/:filename', async (c) => {
136
153
  // Only rename file if title explicitly changed
137
154
  if (titleChanged) {
138
155
  newFilename = generateFilename(newTitle);
139
- newFilePath = path.join(knowledgePath, newFilename);
156
+ newFilePath = resolveKnowledgeFile(knowledgePath, newFilename).filePath;
140
157
  // Check if new filename conflicts with existing file (unless it's the same file)
141
158
  if (newFilename !== actualFilename) {
142
159
  try {
@@ -189,6 +206,9 @@ app.put('/:filename', async (c) => {
189
206
  });
190
207
  }
191
208
  catch (error) {
209
+ if (error.message === 'Invalid knowledge filename') {
210
+ return c.json({ success: false, error: 'Invalid knowledge filename' }, 400);
211
+ }
192
212
  console.error('Error updating knowledge document:', error);
193
213
  return c.json({ success: false, error: 'Failed to update knowledge document' }, 500);
194
214
  }
@@ -201,8 +221,7 @@ app.delete('/:filename', async (c) => {
201
221
  try {
202
222
  const filename = c.req.param('filename');
203
223
  const knowledgePath = getKnowledgePath();
204
- const actualFilename = filename.endsWith('.md') ? filename : `${filename}.md`;
205
- const filePath = path.join(knowledgePath, actualFilename);
224
+ const { actualFilename, filePath } = resolveKnowledgeFile(knowledgePath, filename);
206
225
  // Check if file exists
207
226
  try {
208
227
  await fs.access(filePath);
@@ -247,6 +266,9 @@ app.delete('/:filename', async (c) => {
247
266
  });
248
267
  }
249
268
  catch (error) {
269
+ if (error.message === 'Invalid knowledge filename') {
270
+ return c.json({ success: false, error: 'Invalid knowledge filename' }, 400);
271
+ }
250
272
  console.error('Error deleting knowledge document:', error);
251
273
  return c.json({ success: false, error: 'Failed to delete knowledge document' }, 500);
252
274
  }
@@ -3,7 +3,7 @@ import { promises as fs } from 'fs';
3
3
  import path from 'path';
4
4
  import matter from 'gray-matter';
5
5
  import filenameRoute from './[filename]/index.js';
6
- import { listKnowledge } from '@lovelybunch/core';
6
+ import { listKnowledge, sanitizeProvidedFilename } from '@lovelybunch/core';
7
7
  import { getLogger, KnowledgeKinds } from '@lovelybunch/core/logging';
8
8
  import { requireAuth } from '../../../../middleware/auth.js';
9
9
  // Helper function to generate a simple summary from content
@@ -104,12 +104,22 @@ app.post('/', async (c) => {
104
104
  }
105
105
  const knowledgePath = getKnowledgePath();
106
106
  await fs.mkdir(knowledgePath, { recursive: true });
107
- const filename = generateFilename(body.title);
107
+ let filename;
108
+ if (typeof body.filename === 'string' && body.filename.trim().length > 0) {
109
+ const sanitized = sanitizeProvidedFilename(body.filename);
110
+ if (!sanitized) {
111
+ return c.json({ success: false, error: 'Invalid filename' }, 400);
112
+ }
113
+ filename = sanitized;
114
+ }
115
+ else {
116
+ filename = generateFilename(body.title);
117
+ }
108
118
  const filePath = path.join(knowledgePath, filename);
109
119
  // Check if file already exists
110
120
  try {
111
121
  await fs.access(filePath);
112
- return c.json({ success: false, error: 'A document with this title already exists' }, 409);
122
+ return c.json({ success: false, error: 'A document with this filename already exists' }, 409);
113
123
  }
114
124
  catch {
115
125
  // File doesn't exist, which is what we want
@@ -1,5 +1,6 @@
1
1
  import { getGlobalTerminalManager } from '../../../../../../lib/terminal/global-manager.js';
2
2
  import { loadUserSettings } from '../../../../../../lib/user-preferences.js';
3
+ import { getAuthPrincipalKey } from '../../../../../../middleware/auth.js';
3
4
  export async function POST(c) {
4
5
  try {
5
6
  const taskId = c.req.param('taskId');
@@ -13,7 +14,7 @@ export async function POST(c) {
13
14
  const shellPreference = (userSettings.preferences.terminalShell || 'bash');
14
15
  // Create a new terminal session for this task
15
16
  const terminalManager = getGlobalTerminalManager();
16
- const session = await terminalManager.createSession(taskId, shellPreference, startupCommand);
17
+ const session = await terminalManager.createSession(taskId, shellPreference, startupCommand, getAuthPrincipalKey(c));
17
18
  return c.json({
18
19
  sessionId: session.id,
19
20
  taskId: session.taskId,
@@ -1,4 +1,5 @@
1
1
  import { getGlobalTerminalManager } from '../../../../../../lib/terminal/global-manager.js';
2
+ import { getAuthPrincipalKey } from '../../../../../../middleware/auth.js';
2
3
  export async function POST(c) {
3
4
  try {
4
5
  const taskId = c.req.param('taskId');
@@ -8,7 +9,7 @@ export async function POST(c) {
8
9
  return c.json({ error: 'Session ID is required' }, 400);
9
10
  }
10
11
  const terminalManager = getGlobalTerminalManager();
11
- const success = terminalManager.destroySession(sessionId);
12
+ const success = terminalManager.destroySession(sessionId, getAuthPrincipalKey(c));
12
13
  if (!success) {
13
14
  return c.json({ error: 'Session not found' }, 404);
14
15
  }
@@ -1,4 +1,5 @@
1
1
  import { getGlobalTerminalManager } from '../../../../../../lib/terminal/global-manager.js';
2
+ import { getAuthPrincipalKey } from '../../../../../../middleware/auth.js';
2
3
  export async function POST(c) {
3
4
  try {
4
5
  const taskId = c.req.param('taskId');
@@ -8,7 +9,7 @@ export async function POST(c) {
8
9
  return c.json({ error: 'Session ID, cols, and rows are required' }, 400);
9
10
  }
10
11
  const terminalManager = getGlobalTerminalManager();
11
- const success = terminalManager.resizeSession(sessionId, cols, rows);
12
+ const success = terminalManager.resizeSession(sessionId, cols, rows, getAuthPrincipalKey(c));
12
13
  if (!success) {
13
14
  return c.json({ error: 'Session not found or resize failed' }, 404);
14
15
  }
@@ -5,6 +5,7 @@ import matter from 'gray-matter';
5
5
  import { getGlobalTerminalManager } from '../../../../../lib/terminal/global-manager.js';
6
6
  import { loadUserSettings } from '../../../../../lib/user-preferences.js';
7
7
  import { FileStorageAdapter } from '../../../../../lib/storage/file-storage.js';
8
+ import { getAuthPrincipalKey } from '../../../../../middleware/auth.js';
8
9
  import { buildPipelineScript, buildPipelineBanner } from '@lovelybunch/core';
9
10
  const storage = new FileStorageAdapter();
10
11
  const VALID_AGENTS = ['claude', 'gemini', 'codex', 'droid', 'kiro'];
@@ -143,7 +144,7 @@ export async function POST(c) {
143
144
  ? `cd '${worktreePath.replace(/'/g, "'\\''")}' && ${command}`
144
145
  : command;
145
146
  const terminalManager = getGlobalTerminalManager();
146
- const session = await terminalManager.createSession(taskId, shellPreference, startupCommand);
147
+ const session = await terminalManager.createSession(taskId, shellPreference, startupCommand, getAuthPrincipalKey(c));
147
148
  return c.json({
148
149
  sessionId: session.id,
149
150
  taskId: session.taskId,
@@ -1,4 +1,5 @@
1
1
  import { getGlobalTerminalManager } from '../../../../../lib/terminal/global-manager.js';
2
+ import { getAuthPrincipalKey } from '../../../../../middleware/auth.js';
2
3
  // Lightweight ANSI escape sequence stripper to keep preview readable
3
4
  // This avoids adding a dependency just for previews
4
5
  const ANSI_REGEX = /[\u001B\u009B][[\]()#;?]*(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
@@ -40,16 +41,17 @@ export async function GET(c) {
40
41
  const previewBytes = Number.isFinite(maxBytesParam) && maxBytesParam > 0 ? Math.min(maxBytesParam, 8192) : 4096; // cap at 8KB
41
42
  const colorize = ['1', 'true', 'yes'].includes((searchParams.get('colorize') || '').toLowerCase());
42
43
  const terminalManager = getGlobalTerminalManager();
44
+ const ownerId = getAuthPrincipalKey(c);
43
45
  let sessions;
44
46
  if (sessionId) {
45
47
  const s = terminalManager.getSession(sessionId);
46
- sessions = s ? [s] : [];
48
+ sessions = terminalManager.canAccessSession(s, ownerId) && s ? [s] : [];
47
49
  }
48
50
  else if (taskId) {
49
- sessions = terminalManager.getSessionsByTask(taskId);
51
+ sessions = terminalManager.getSessionsByTask(taskId).filter(session => terminalManager.canAccessSession(session, ownerId));
50
52
  }
51
53
  else {
52
- sessions = terminalManager.getAllSessions();
54
+ sessions = terminalManager.getSessionsForOwner(ownerId);
53
55
  }
54
56
  // Return session info without the PTY instance
55
57
  const sessionInfo = sessions.map(session => ({
@@ -105,7 +105,7 @@ app.use('/api/*', cors({
105
105
  // Handle trailing slashes consistently for API routes
106
106
  app.use('/api/*', trimTrailingSlash());
107
107
  // Import and apply authentication middleware
108
- import { authMiddleware } from './middleware/auth.js';
108
+ import { authMiddleware, getAuthPrincipalKey } from './middleware/auth.js';
109
109
  app.use('/api/*', authMiddleware);
110
110
  app.use('/ws/*', authMiddleware);
111
111
  // Create WebSocket support
@@ -123,7 +123,7 @@ app.get('/ws/terminal/:sessionId', upgradeWebSocket((c) => ({
123
123
  ws.close(1000, 'WebSocket error');
124
124
  return;
125
125
  }
126
- const success = terminalManager.attachWebSocket(sessionId, rawWs);
126
+ const success = terminalManager.attachWebSocket(sessionId, rawWs, getAuthPrincipalKey(c));
127
127
  if (!success) {
128
128
  console.error(`Failed to attach WebSocket to session: ${sessionId}`);
129
129
  ws.close(1000, 'Session not found');
@@ -152,7 +152,7 @@ app.get('/ws/terminal-preview/:sessionId', upgradeWebSocket((c) => ({
152
152
  catch { }
153
153
  return;
154
154
  }
155
- const success = terminalManager.attachPreviewWebSocket(sessionId, rawWs);
155
+ const success = terminalManager.attachPreviewWebSocket(sessionId, rawWs, getAuthPrincipalKey(c));
156
156
  if (!success) {
157
157
  try {
158
158
  ws.close(1000, 'Session not found');
package/dist/server.js CHANGED
@@ -99,7 +99,7 @@ app.use('*', cors({
99
99
  // Handle trailing slashes consistently for API routes
100
100
  app.use('/api/*', trimTrailingSlash());
101
101
  // Import and apply authentication middleware
102
- import { authMiddleware } from './middleware/auth.js';
102
+ import { authMiddleware, getAuthPrincipalKey } from './middleware/auth.js';
103
103
  app.use('/api/*', authMiddleware);
104
104
  app.use('/ws/*', authMiddleware);
105
105
  // Create WebSocket support
@@ -117,7 +117,7 @@ app.get('/ws/terminal/:sessionId', upgradeWebSocket((c) => ({
117
117
  ws.close(1000, 'WebSocket error');
118
118
  return;
119
119
  }
120
- const success = terminalManager.attachWebSocket(sessionId, rawWs);
120
+ const success = terminalManager.attachWebSocket(sessionId, rawWs, getAuthPrincipalKey(c));
121
121
  if (!success) {
122
122
  console.error(`Failed to attach WebSocket to session: ${sessionId}`);
123
123
  ws.close(1000, 'Session not found');
@@ -146,7 +146,7 @@ app.get('/ws/terminal-preview/:sessionId', upgradeWebSocket((c) => ({
146
146
  catch { }
147
147
  return;
148
148
  }
149
- const success = terminalManager.attachPreviewWebSocket(sessionId, rawWs);
149
+ const success = terminalManager.attachPreviewWebSocket(sessionId, rawWs, getAuthPrincipalKey(c));
150
150
  if (!success) {
151
151
  try {
152
152
  ws.close(1000, 'Session not found');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovelybunch/api",
3
- "version": "1.0.78-alpha.2",
3
+ "version": "1.0.78-alpha.4",
4
4
  "type": "module",
5
5
  "main": "dist/server-with-static.js",
6
6
  "exports": {
@@ -40,9 +40,9 @@
40
40
  "sharp": "^0.33.5",
41
41
  "ws": "^8.18.0",
42
42
  "zod": "^3.23.0",
43
- "@lovelybunch/core": "1.0.78-alpha.2",
44
- "@lovelybunch/types": "1.0.78-alpha.2",
45
- "@lovelybunch/mcp": "1.0.78-alpha.2"
43
+ "@lovelybunch/types": "1.0.78-alpha.4",
44
+ "@lovelybunch/core": "1.0.78-alpha.4",
45
+ "@lovelybunch/mcp": "1.0.78-alpha.4"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/adm-zip": "^0.5.7",
@@ -1 +1 @@
1
- import{r as a,A as p,j as e,v,bN as y,B as N,n as w,C as b}from"./index-Bx26Q2JC.js";import{C as c,a as d,b as k,c as C}from"./card-D2eA49nP.js";import{B as m}from"./badge-D1sVaZJG.js";import{R as E}from"./refresh-cw-CLSROYiq.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,v,bN as y,B as N,n as w,C as b}from"./index-SUQrIHd7.js";import{C as c,a as d,b as k,c as C}from"./card-CiLixwCG.js";import{B as m}from"./badge-TeAh_Zh0.js";import{R as E}from"./refresh-cw-DvQ0rmk7.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,4 +1,4 @@
1
- import{u as p,a as j,r as n,A as l,j as e,B as h,L as v,a5 as N}from"./index-Bx26Q2JC.js";import{C as m,a as x,b as C,c as S}from"./card-D2eA49nP.js";import{M as w}from"./markdown-editor-Dmq8d9Xs.js";import{A as y}from"./arrow-left-CY9PaWRG.js";import{C as A}from"./circle-check-big-HtBmMXFt.js";import"./index-5M1EX2JZ.js";function F(){const f=p(),{toast:t}=j(),[a,i]=n.useState(""),[g,r]=n.useState(!0),[o,c]=n.useState(!1);n.useEffect(()=>{fetch(`${l}/api/v1/context/agents`).then(s=>s.json()).then(s=>{s.success&&i(s.document.content.trim()),r(!1)}).catch(s=>{console.error("Failed to load context:",s),t({title:"Error",description:"Failed to load agents definition",variant:"destructive"}),r(!1)})},[t]);const u=async()=>{c(!0);try{const d=await(await fetch(`${l}/api/v1/context/agents`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:a,metadata:{}})})).json();if(d.success)t({title:"Success",description:"Agents definition saved successfully",action:e.jsx(A,{className:"h-4 w-4"})}),f("/context/agents");else throw new Error(d.error||"Failed to save")}catch(s){console.error("Save error:",s),t({title:"Error",description:"Failed to save agents definition",variant:"destructive"})}finally{c(!1)}};return g?e.jsx("div",{className:"space-y-6",children:e.jsx(m,{children:e.jsx(x,{className:"pt-6",children:e.jsx("div",{className:"text-center",children:e.jsx("p",{children:"Loading..."})})})})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("h1",{className:"text-xl sm:text-2xl font-bold tracking-tight",children:"Edit Agents Definition"}),e.jsx("p",{className:"text-muted-foreground text-sm hidden sm:block",children:"Define agents, their capabilities, and configurations"})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx(h,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(v,{to:"/context/agents",className:"text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(y,{className:"w-4 h-4"})})}),e.jsxs(h,{onClick:u,disabled:o,size:"sm",children:[e.jsx(N,{className:"w-4 h-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:o?"Saving...":"Save"})]})]})]}),e.jsxs(m,{children:[e.jsx(C,{children:e.jsx(S,{children:"Agents Documentation"})}),e.jsx(x,{children:e.jsx(w,{value:a,onChange:s=>i(s||""),placeholder:`Write your agents definition in markdown...
1
+ import{u as p,a as j,r as n,A as l,j as e,B as h,L as v,a5 as N}from"./index-SUQrIHd7.js";import{C as m,a as x,b as C,c as S}from"./card-CiLixwCG.js";import{M as w}from"./markdown-editor-Cvh5pZzJ.js";import{A as y}from"./arrow-left-_lXkdm9Q.js";import{C as A}from"./circle-check-big-CxxxVvOw.js";import"./index-BlOxV6pf.js";function F(){const f=p(),{toast:t}=j(),[a,i]=n.useState(""),[g,r]=n.useState(!0),[o,c]=n.useState(!1);n.useEffect(()=>{fetch(`${l}/api/v1/context/agents`).then(s=>s.json()).then(s=>{s.success&&i(s.document.content.trim()),r(!1)}).catch(s=>{console.error("Failed to load context:",s),t({title:"Error",description:"Failed to load agents definition",variant:"destructive"}),r(!1)})},[t]);const u=async()=>{c(!0);try{const d=await(await fetch(`${l}/api/v1/context/agents`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:a,metadata:{}})})).json();if(d.success)t({title:"Success",description:"Agents definition saved successfully",action:e.jsx(A,{className:"h-4 w-4"})}),f("/context/agents");else throw new Error(d.error||"Failed to save")}catch(s){console.error("Save error:",s),t({title:"Error",description:"Failed to save agents definition",variant:"destructive"})}finally{c(!1)}};return g?e.jsx("div",{className:"space-y-6",children:e.jsx(m,{children:e.jsx(x,{className:"pt-6",children:e.jsx("div",{className:"text-center",children:e.jsx("p",{children:"Loading..."})})})})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("h1",{className:"text-xl sm:text-2xl font-bold tracking-tight",children:"Edit Agents Definition"}),e.jsx("p",{className:"text-muted-foreground text-sm hidden sm:block",children:"Define agents, their capabilities, and configurations"})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx(h,{variant:"ghost",size:"sm",asChild:!0,children:e.jsx(v,{to:"/context/agents",className:"text-muted-foreground hover:text-foreground transition-colors",children:e.jsx(y,{className:"w-4 h-4"})})}),e.jsxs(h,{onClick:u,disabled:o,size:"sm",children:[e.jsx(N,{className:"w-4 h-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:o?"Saving...":"Save"})]})]})]}),e.jsxs(m,{children:[e.jsx(C,{children:e.jsx(S,{children:"Agents Documentation"})}),e.jsx(x,{children:e.jsx(w,{value:a,onChange:s=>i(s||""),placeholder:`Write your agents definition in markdown...
2
2
 
3
3
  ## Agent Definitions
4
4
 
@@ -1 +1 @@
1
- import{a as g,r as t,A as N,j as e,v,az as C,B as a,L as d,a2 as l,M as w,ay as y,au as E}from"./index-Bx26Q2JC.js";import{C as i,a as c,b}from"./card-D2eA49nP.js";import{c as A}from"./clipboard-B9ndUJKl.js";function D(){const{toast:r}=g(),[o,m]=t.useState(null),[x,h]=t.useState(!0),[u,n]=t.useState(!1);t.useEffect(()=>{fetch(`${N}/api/v1/context/agents`).then(s=>{if(s.ok)return s.json();throw new Error("Not found")}).then(s=>{s.success?(m(s.document),n(!0)):n(!1)}).catch(()=>{n(!1)}).finally(()=>{h(!1)})},[]);const p=async()=>{const s=".nut/context/agents.md";try{await A(s),r({title:"Copied!",description:`Path ${s} copied to clipboard`})}catch(f){console.error("Failed to copy path:",f),r({title:"Error",description:"Failed to copy path to clipboard",variant:"destructive"})}},j=()=>{const s=new CustomEvent("discuss-in-chat",{detail:{type:"context",id:"agents-md",filename:"agents.md",name:"agents.md",path:".nut/context/agents.md"}});window.dispatchEvent(s)};return x?e.jsx("div",{className:"space-y-6",children:e.jsx(i,{children:e.jsx(c,{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 agents definition..."})]})})})}):!u||!o?e.jsx("div",{className:"space-y-6",children:e.jsx(i,{children:e.jsx(c,{className:"pt-6",children:e.jsxs("div",{className:"text-center",children:[e.jsx(C,{className:"mx-auto h-12 w-12 text-muted-foreground"}),e.jsx("h3",{className:"mt-4 text-lg font-semibold",children:"No Agents Definition Found"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:"Agents definition will appear here once created."}),e.jsx(a,{className:"mt-4",asChild:!0,children:e.jsxs(d,{to:"/context/agents/edit",children:[e.jsx(l,{className:"h-4 w-4 mr-2"}),"Create Agents Definition"]})})]})})})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Agents"}),e.jsx("p",{className:"text-muted-foreground",children:"Agent definitions and configurations"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(a,{variant:"outline",size:"sm",onClick:j,children:[e.jsx(w,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Discuss"})]}),e.jsxs(a,{variant:"outline",size:"sm",onClick:p,children:[e.jsx(y,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Copy Path"})]}),e.jsx(a,{size:"sm",asChild:!0,children:e.jsxs(d,{to:"/context/agents/edit",children:[e.jsx(l,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Edit"})]})})]})]}),e.jsxs(i,{children:[e.jsx(b,{className:"pb-0"}),e.jsx(c,{children:e.jsx("div",{className:"prose prose-sm max-w-none dark:prose-invert",children:e.jsx(E,{children:o.content||"No content available"})})})]})]})}export{D as default};
1
+ import{a as g,r as t,A as N,j as e,v,az as C,B as a,L as d,a2 as l,M as w,ay as y,au as E}from"./index-SUQrIHd7.js";import{C as i,a as c,b}from"./card-CiLixwCG.js";import{c as A}from"./clipboard-B9ndUJKl.js";function D(){const{toast:r}=g(),[o,m]=t.useState(null),[x,h]=t.useState(!0),[u,n]=t.useState(!1);t.useEffect(()=>{fetch(`${N}/api/v1/context/agents`).then(s=>{if(s.ok)return s.json();throw new Error("Not found")}).then(s=>{s.success?(m(s.document),n(!0)):n(!1)}).catch(()=>{n(!1)}).finally(()=>{h(!1)})},[]);const p=async()=>{const s=".nut/context/agents.md";try{await A(s),r({title:"Copied!",description:`Path ${s} copied to clipboard`})}catch(f){console.error("Failed to copy path:",f),r({title:"Error",description:"Failed to copy path to clipboard",variant:"destructive"})}},j=()=>{const s=new CustomEvent("discuss-in-chat",{detail:{type:"context",id:"agents-md",filename:"agents.md",name:"agents.md",path:".nut/context/agents.md"}});window.dispatchEvent(s)};return x?e.jsx("div",{className:"space-y-6",children:e.jsx(i,{children:e.jsx(c,{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 agents definition..."})]})})})}):!u||!o?e.jsx("div",{className:"space-y-6",children:e.jsx(i,{children:e.jsx(c,{className:"pt-6",children:e.jsxs("div",{className:"text-center",children:[e.jsx(C,{className:"mx-auto h-12 w-12 text-muted-foreground"}),e.jsx("h3",{className:"mt-4 text-lg font-semibold",children:"No Agents Definition Found"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:"Agents definition will appear here once created."}),e.jsx(a,{className:"mt-4",asChild:!0,children:e.jsxs(d,{to:"/context/agents/edit",children:[e.jsx(l,{className:"h-4 w-4 mr-2"}),"Create Agents Definition"]})})]})})})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight",children:"Agents"}),e.jsx("p",{className:"text-muted-foreground",children:"Agent definitions and configurations"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(a,{variant:"outline",size:"sm",onClick:j,children:[e.jsx(w,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Discuss"})]}),e.jsxs(a,{variant:"outline",size:"sm",onClick:p,children:[e.jsx(y,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Copy Path"})]}),e.jsx(a,{size:"sm",asChild:!0,children:e.jsxs(d,{to:"/context/agents/edit",children:[e.jsx(l,{className:"h-4 w-4 sm:mr-2"}),e.jsx("span",{className:"hidden sm:inline",children:"Edit"})]})})]})]}),e.jsxs(i,{children:[e.jsx(b,{className:"pb-0"}),e.jsx(c,{children:e.jsx("div",{className:"prose prose-sm max-w-none dark:prose-invert",children:e.jsx(E,{children:o.content||"No content available"})})})]})]})}export{D as default};
@@ -1,2 +1,2 @@
1
- import{t as R,r as t,E as y,j as e,B as a,P as X,bH as Y,Q as J,D as j,b as g,d as v,f,g as A,I as F,a1 as N,ai as Q,w as i}from"./index-Bx26Q2JC.js";import{C as W,b as G,c as V,d as Z,a as _}from"./card-D2eA49nP.js";import{L as w}from"./label-fHWG59jZ.js";import{B as ee}from"./badge-D1sVaZJG.js";import{A as I,a as C}from"./alert-0GENnoy_.js";import{I as L}from"./info-_JNAJSs5.js";import{C as se}from"./circle-alert-DsESVtwL.js";function oe(){const{authEnabled:n}=R(),[P,k]=t.useState([]),[b,K]=t.useState(!0),[O,l]=t.useState(!1),[M,d]=t.useState(!1),[x,D]=t.useState(""),[h,E]=t.useState("never"),[c,S]=t.useState(null),[m,o]=t.useState(null);t.useEffect(()=>{p()},[]);const p=async()=>{K(!0);try{const s=await y("/api/v1/api-keys");s.success&&k(s.data?.apiKeys||[])}catch(s){console.error("Failed to load API keys:",s),k([])}finally{K(!1)}},U=async()=>{if(!x.trim()){i({title:"Error",description:"Please provide a name for the API key",variant:"destructive"});return}try{const s={name:x,scopes:["*"]};h!=="never"&&(s.expiresIn=h);const r=await y("/api/v1/api-keys",{method:"POST",body:JSON.stringify(s)});r.success&&(S(r.data),l(!1),d(!0),D(""),E("never"),await p(),i({title:"API Key Created",description:"Make sure to copy your API key now. You won't be able to see it again!"}))}catch(s){console.error("Failed to create API key:",s),i({title:"Error",description:"Failed to create API key",variant:"destructive"})}},B=async s=>{try{(await y(`/api/v1/api-keys/${s}`,{method:"DELETE"})).success&&(await p(),o(null),i({title:"API Key Deleted",description:"The API key has been permanently deleted"}))}catch(r){console.error("Failed to delete API key:",r),i({title:"Error",description:"Failed to delete API key",variant:"destructive"})}},H=async s=>{try{await navigator.clipboard.writeText(s),i({title:"Copied",description:"API key copied to clipboard"})}catch{i({title:"Error",description:"Failed to copy to clipboard",variant:"destructive"})}},u=s=>new Date(s).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}),$=s=>s?new Date(s)<new Date:!1,q=typeof window<"u"?window.location.origin:"http://localhost:3000",z=c?`curl -H "X-API-Key: ${c.key}" \\
1
+ import{t as R,r as t,E as y,j as e,B as a,P as X,bH as Y,Q as J,D as j,b as g,d as v,f,g as A,I as F,a1 as N,ai as Q,w as i}from"./index-SUQrIHd7.js";import{C as W,b as G,c as V,d as Z,a as _}from"./card-CiLixwCG.js";import{L as w}from"./label-n5pqaObd.js";import{B as ee}from"./badge-TeAh_Zh0.js";import{A as I,a as C}from"./alert-DBhIskRX.js";import{I as L}from"./info-CVmPHERQ.js";import{C as se}from"./circle-alert-nI75emvr.js";function oe(){const{authEnabled:n}=R(),[P,k]=t.useState([]),[b,K]=t.useState(!0),[O,l]=t.useState(!1),[M,d]=t.useState(!1),[x,D]=t.useState(""),[h,E]=t.useState("never"),[c,S]=t.useState(null),[m,o]=t.useState(null);t.useEffect(()=>{p()},[]);const p=async()=>{K(!0);try{const s=await y("/api/v1/api-keys");s.success&&k(s.data?.apiKeys||[])}catch(s){console.error("Failed to load API keys:",s),k([])}finally{K(!1)}},U=async()=>{if(!x.trim()){i({title:"Error",description:"Please provide a name for the API key",variant:"destructive"});return}try{const s={name:x,scopes:["*"]};h!=="never"&&(s.expiresIn=h);const r=await y("/api/v1/api-keys",{method:"POST",body:JSON.stringify(s)});r.success&&(S(r.data),l(!1),d(!0),D(""),E("never"),await p(),i({title:"API Key Created",description:"Make sure to copy your API key now. You won't be able to see it again!"}))}catch(s){console.error("Failed to create API key:",s),i({title:"Error",description:"Failed to create API key",variant:"destructive"})}},B=async s=>{try{(await y(`/api/v1/api-keys/${s}`,{method:"DELETE"})).success&&(await p(),o(null),i({title:"API Key Deleted",description:"The API key has been permanently deleted"}))}catch(r){console.error("Failed to delete API key:",r),i({title:"Error",description:"Failed to delete API key",variant:"destructive"})}},H=async s=>{try{await navigator.clipboard.writeText(s),i({title:"Copied",description:"API key copied to clipboard"})}catch{i({title:"Error",description:"Failed to copy to clipboard",variant:"destructive"})}},u=s=>new Date(s).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}),$=s=>s?new Date(s)<new Date:!1,q=typeof window<"u"?window.location.origin:"http://localhost:3000",z=c?`curl -H "X-API-Key: ${c.key}" \\
2
2
  + ${q}/api/v1/tasks`:"",T=n?null:e.jsxs(I,{children:[e.jsx(L,{className:"h-4 w-4"}),e.jsxs(C,{children:["Authentication is currently disabled. API keys will only be required once you enable authentication in the ",e.jsx("a",{href:"/settings/authentication",className:"underline",children:"Authentication settings"}),"."]})]});return!n&&b?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-medium",children:"API Keys"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Manage API keys for programmatic access"})]}),T]}):b?e.jsx("div",{className:"space-y-6",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-medium",children:"API Keys"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading..."})]})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-medium",children:"API Keys"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Manage API keys for programmatic access to your Coconut instance"})]}),T,n&&e.jsxs(I,{children:[e.jsx(L,{className:"h-4 w-4"}),e.jsxs(C,{children:["API keys provide programmatic access to your Coconut instance. Use them in CI/CD pipelines or automation scripts by including the key in the ",e.jsx("code",{className:"bg-muted px-1 py-0.5 rounded",children:"X-API-Key"})," header."]})]}),e.jsxs(W,{children:[e.jsx(G,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx(V,{children:"Active API Keys"}),e.jsx(Z,{children:"API keys you've created for programmatic access"})]}),e.jsxs(a,{onClick:()=>l(!0),disabled:!n,children:[e.jsx(X,{className:"mr-2 h-4 w-4"}),"Create API Key"]})]})}),e.jsx(_,{children:P.length===0?e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(Y,{className:"h-12 w-12 mx-auto mb-4 opacity-20"}),e.jsx("p",{children:"No API keys yet"}),e.jsx("p",{className:"text-sm",children:"Create an API key to get started with programmatic access"})]}):e.jsx("div",{className:"space-y-4",children:P.map(s=>e.jsxs("div",{className:"flex items-center justify-between p-4 border rounded-lg",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("p",{className:"font-medium",children:s.name}),$(s.expiresAt)&&e.jsx(ee,{variant:"destructive",children:"Expired"})]}),e.jsx("p",{className:"text-sm text-muted-foreground font-mono",children:s.keyPreview}),e.jsxs("div",{className:"flex items-center gap-4 mt-2 text-xs text-muted-foreground",children:[e.jsxs("span",{children:["Created: ",u(s.createdAt)]}),s.expiresAt&&e.jsxs("span",{children:["Expires: ",u(s.expiresAt)]}),s.lastUsedAt&&e.jsxs("span",{children:["Last used: ",u(s.lastUsedAt)]})]})]}),e.jsx(a,{variant:"ghost",size:"icon",onClick:()=>o(s.id),children:e.jsx(J,{className:"h-4 w-4 text-destructive"})})]},s.id))})})]}),e.jsx(j,{open:O,onOpenChange:l,children:e.jsxs(g,{children:[e.jsxs(v,{children:[e.jsx(f,{children:"Create API Key"}),e.jsx(A,{children:"Create a new API key for programmatic access. The key will only be shown once."})]}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(w,{htmlFor:"keyName",children:"Name"}),e.jsx(F,{id:"keyName",placeholder:"CI/CD Pipeline",value:x,onChange:s=>D(s.target.value)}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"A descriptive name to identify this API key"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(w,{htmlFor:"keyExpiry",children:"Expiration"}),e.jsxs("select",{id:"keyExpiry",className:"w-full rounded-md border border-input bg-background px-3 py-2 text-sm",value:h,onChange:s=>E(s.target.value),children:[e.jsx("option",{value:"never",children:"Never"}),e.jsx("option",{value:"30d",children:"30 days"}),e.jsx("option",{value:"90d",children:"90 days"}),e.jsx("option",{value:"1y",children:"1 year"})]})]})]}),e.jsxs(N,{children:[e.jsx(a,{variant:"outline",onClick:()=>l(!1),children:"Cancel"}),e.jsx(a,{onClick:U,disabled:!n,children:"Create API Key"})]})]})}),e.jsx(j,{open:M,onOpenChange:d,children:e.jsxs(g,{className:"sm:max-w-[600px]",children:[e.jsxs(v,{children:[e.jsx(f,{children:"API Key Created"}),e.jsx(A,{children:"Make sure to copy your API key now. You won't be able to see it again!"})]}),e.jsxs(I,{variant:"destructive",className:"my-4",children:[e.jsx(se,{className:"h-4 w-4"}),e.jsx(C,{children:"This is the only time you will see this key. Store it securely."})]}),c&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(w,{children:"API Key"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(F,{readOnly:!0,value:c.key,className:"font-mono text-sm"}),e.jsx(a,{variant:"outline",size:"icon",onClick:()=>H(c.key),children:e.jsx(Q,{className:"h-4 w-4"})})]})]}),e.jsxs("div",{className:"text-sm text-muted-foreground",children:[e.jsx("p",{className:"mb-2",children:"Usage example:"}),e.jsx("pre",{className:"bg-muted p-3 rounded-md whitespace-pre-wrap break-words",children:e.jsx("code",{className:"font-mono text-xs",children:z})})]})]}),e.jsx(N,{children:e.jsx(a,{onClick:()=>{d(!1),S(null)},children:"I've Saved My Key"})})]})}),e.jsx(j,{open:!!m,onOpenChange:s=>!s&&o(null),children:e.jsxs(g,{children:[e.jsxs(v,{children:[e.jsx(f,{children:"Delete API Key"}),e.jsx(A,{children:"Are you sure you want to delete this API key? This action cannot be undone and any scripts using this key will stop working."})]}),e.jsxs(N,{children:[e.jsx(a,{variant:"outline",onClick:()=>o(null),children:"Cancel"}),e.jsx(a,{variant:"destructive",onClick:()=>m&&B(m),children:"Delete API Key"})]})]})})]})}export{oe as default};
@@ -1,4 +1,4 @@
1
- import{c as te,t as me,r as n,E as l,j as e,bB as _,i as H,D as q,a0 as z,B as d,b as B,d as Y,f as K,g as Q,I as x,a1 as G,J as ge,N as je,Q as pe,R as ve,U as fe,V as we,W as ye,Y as Ce,_ as Ne,$ as Se,w as r}from"./index-Bx26Q2JC.js";import{C as m,b as g,c as j,d as p,a as v}from"./card-D2eA49nP.js";import{L as c}from"./label-fHWG59jZ.js";import{S as X,a as Z,b as ee,c as se,d as a}from"./select-ChtjmmOf.js";import{S as N}from"./switch-BMBFkcUU.js";import{B as F}from"./badge-D1sVaZJG.js";import{C as be}from"./circle-alert-DsESVtwL.js";import"./index-5M1EX2JZ.js";import"./chevron-up-DD_GdI6e.js";/**
1
+ import{c as te,t as me,r as n,E as l,j as e,bB as _,i as H,D as q,a0 as z,B as d,b as B,d as Y,f as K,g as Q,I as x,a1 as G,J as ge,N as je,Q as pe,R as ve,U as fe,V as we,W as ye,Y as Ce,_ as Ne,$ as Se,w as r}from"./index-SUQrIHd7.js";import{C as m,b as g,c as j,d as p,a as v}from"./card-CiLixwCG.js";import{L as c}from"./label-n5pqaObd.js";import{S as X,a as Z,b as ee,c as se,d as a}from"./select-CIOYQA7a.js";import{S as N}from"./switch-DczkR77Y.js";import{B as F}from"./badge-TeAh_Zh0.js";import{C as be}from"./circle-alert-nI75emvr.js";import"./index-BlOxV6pf.js";import"./chevron-up-B4J4D5aE.js";/**
2
2
  * @license lucide-react v0.542.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{r as m,j as e,v as x,A as f}from"./index-Bx26Q2JC.js";import{C as w}from"./circle-check-BXiPFdlh.js";import{C as b}from"./circle-x-B_4fmWCG.js";const r="coconut/github-auth-state";function j(s){try{window.opener&&window.opener.postMessage({type:"github-auth",...s},window.location.origin)}catch{}}const y=()=>{const[s,d]=m.useState("pending"),[h,p]=m.useState("Authorizing GitHub…");return m.useEffect(()=>{const a=new URLSearchParams(window.location.search),u=a.get("error"),l=a.get("token"),n=a.get("expires_at")||a.get("expiresAt"),c=a.get("state"),o=t=>{j(t),d(t.success?"success":"error"),p(t.message),setTimeout(()=>{try{window.close()}catch{}},1200)};if(u){localStorage.removeItem(r),o({success:!1,message:decodeURIComponent(u)});return}if(!l||!n||!c){localStorage.removeItem(r),o({success:!1,message:"Missing authorization parameters. Please try again."});return}const g=localStorage.getItem(r);if(!g||g!==c){localStorage.removeItem(r),o({success:!1,message:"Authorization state mismatch. Please start again."});return}(async()=>{try{const t=await fetch(`${f}/api/v1/git/providers/github/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:l,expiresAt:n,state:c})}),i=await t.json();if(!t.ok||!i.success)throw new Error(i?.error?.message||"Failed to store GitHub token");localStorage.removeItem(r),o({success:!0,message:"GitHub connected successfully!",expiresAt:i.data?.expiresAt||n})}catch(t){localStorage.removeItem(r),o({success:!1,message:t?.message||"Failed to store GitHub token. Please try again."})}})()},[]),e.jsx("div",{className:"flex h-screen items-center justify-center bg-background px-6",children:e.jsxs("div",{className:"max-w-sm rounded-lg border bg-card p-6 text-center shadow-sm",children:[e.jsxs("div",{className:"mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted",children:[s==="pending"&&e.jsx(x,{className:"h-6 w-6 animate-spin text-muted-foreground"}),s==="success"&&e.jsx(w,{className:"h-6 w-6 text-green-600"}),s==="error"&&e.jsx(b,{className:"h-6 w-6 text-red-600"})]}),e.jsx("h1",{className:"text-lg font-semibold",children:"GitHub Authorization"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:h}),s!=="pending"&&e.jsx("p",{className:"mt-4 text-xs text-muted-foreground",children:"You can close this window and return to Coconut."})]})})};export{y as default};
1
+ import{r as m,j as e,v as x,A as f}from"./index-SUQrIHd7.js";import{C as w}from"./circle-check-k6ER9afD.js";import{C as b}from"./circle-x-BzPgPb47.js";const r="coconut/github-auth-state";function j(s){try{window.opener&&window.opener.postMessage({type:"github-auth",...s},window.location.origin)}catch{}}const y=()=>{const[s,d]=m.useState("pending"),[h,p]=m.useState("Authorizing GitHub…");return m.useEffect(()=>{const a=new URLSearchParams(window.location.search),u=a.get("error"),l=a.get("token"),n=a.get("expires_at")||a.get("expiresAt"),c=a.get("state"),o=t=>{j(t),d(t.success?"success":"error"),p(t.message),setTimeout(()=>{try{window.close()}catch{}},1200)};if(u){localStorage.removeItem(r),o({success:!1,message:decodeURIComponent(u)});return}if(!l||!n||!c){localStorage.removeItem(r),o({success:!1,message:"Missing authorization parameters. Please try again."});return}const g=localStorage.getItem(r);if(!g||g!==c){localStorage.removeItem(r),o({success:!1,message:"Authorization state mismatch. Please start again."});return}(async()=>{try{const t=await fetch(`${f}/api/v1/git/providers/github/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:l,expiresAt:n,state:c})}),i=await t.json();if(!t.ok||!i.success)throw new Error(i?.error?.message||"Failed to store GitHub token");localStorage.removeItem(r),o({success:!0,message:"GitHub connected successfully!",expiresAt:i.data?.expiresAt||n})}catch(t){localStorage.removeItem(r),o({success:!1,message:t?.message||"Failed to store GitHub token. Please try again."})}})()},[]),e.jsx("div",{className:"flex h-screen items-center justify-center bg-background px-6",children:e.jsxs("div",{className:"max-w-sm rounded-lg border bg-card p-6 text-center shadow-sm",children:[e.jsxs("div",{className:"mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted",children:[s==="pending"&&e.jsx(x,{className:"h-6 w-6 animate-spin text-muted-foreground"}),s==="success"&&e.jsx(w,{className:"h-6 w-6 text-green-600"}),s==="error"&&e.jsx(b,{className:"h-6 w-6 text-red-600"})]}),e.jsx("h1",{className:"text-lg font-semibold",children:"GitHub Authorization"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:h}),s!=="pending"&&e.jsx("p",{className:"mt-4 text-xs text-muted-foreground",children:"You can close this window and return to Coconut."})]})})};export{y as default};
@@ -1 +1 @@
1
- import{u as E,x as S,t as j,r as i,j as e,v,y as p,z as y,E as C,O as k,w as N}from"./index-Bx26Q2JC.js";function I(){const c=E(),[a]=S(),{oauth:t,refreshUser:u,isLoading:l}=j(),[w,r]=i.useState("working"),[b,s]=i.useState(null),d=i.useRef(!1);return i.useEffect(()=>{if(d.current||l)return;d.current=!0,(async()=>{const g=a.get("code"),h=a.get("error");if(h){r("error"),s(a.get("error_description")||h);return}if(!g){r("error"),s("Missing authorization code in callback URL");return}if(!t.enabled||!t.clientId||!t.issuer){r("error"),s("OAuth is not enabled on this coconut");return}let o=null;try{o=sessionStorage.getItem(p)}catch{o=null}if(!o){r("error"),s("Missing PKCE verifier - please start sign-in again");return}try{const n=await y({issuer:t.issuer,clientId:t.clientId,code:g,verifier:o});if(!n.id_token)throw new Error('Clerk did not return an id_token (is the "openid" scope registered for this client?)');const m=await C("/api/v1/auth/oauth/exchange",{method:"POST",body:JSON.stringify({idToken:n.id_token})});if(!m.success)throw new Error(m.error||"Server rejected OAuth token");try{sessionStorage.removeItem(p)}catch{}await u();let f="/";try{const x=sessionStorage.getItem(k);x&&(sessionStorage.removeItem(k),f=x)}catch{}N({title:"Welcome back",description:"Signed in with Coconut"}),c(f,{replace:!0})}catch(n){console.error("OAuth callback failed:",n),r("error"),s(n?.message||"OAuth callback failed")}})()},[l,c,t,u,a]),e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-gradient-to-br from-background to-muted p-4",children:e.jsx("div",{className:"max-w-sm text-center space-y-4",children:w==="working"?e.jsxs(e.Fragment,{children:[e.jsx(v,{className:"h-8 w-8 animate-spin text-muted-foreground mx-auto"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Finishing sign-in with Coconut..."})]}):e.jsxs(e.Fragment,{children:[e.jsx("h1",{className:"text-lg font-semibold",children:"Sign-in failed"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:b||"Something went wrong completing OAuth sign-in."}),e.jsx("button",{type:"button",className:"text-sm underline",onClick:()=>c("/login",{replace:!0}),children:"Back to login"})]})})})}export{I as default};
1
+ import{u as E,x as S,t as j,r as i,j as e,v,y as p,z as y,E as C,O as k,w as N}from"./index-SUQrIHd7.js";function I(){const c=E(),[a]=S(),{oauth:t,refreshUser:u,isLoading:l}=j(),[w,r]=i.useState("working"),[b,s]=i.useState(null),d=i.useRef(!1);return i.useEffect(()=>{if(d.current||l)return;d.current=!0,(async()=>{const g=a.get("code"),h=a.get("error");if(h){r("error"),s(a.get("error_description")||h);return}if(!g){r("error"),s("Missing authorization code in callback URL");return}if(!t.enabled||!t.clientId||!t.issuer){r("error"),s("OAuth is not enabled on this coconut");return}let o=null;try{o=sessionStorage.getItem(p)}catch{o=null}if(!o){r("error"),s("Missing PKCE verifier - please start sign-in again");return}try{const n=await y({issuer:t.issuer,clientId:t.clientId,code:g,verifier:o});if(!n.id_token)throw new Error('Clerk did not return an id_token (is the "openid" scope registered for this client?)');const m=await C("/api/v1/auth/oauth/exchange",{method:"POST",body:JSON.stringify({idToken:n.id_token})});if(!m.success)throw new Error(m.error||"Server rejected OAuth token");try{sessionStorage.removeItem(p)}catch{}await u();let f="/";try{const x=sessionStorage.getItem(k);x&&(sessionStorage.removeItem(k),f=x)}catch{}N({title:"Welcome back",description:"Signed in with Coconut"}),c(f,{replace:!0})}catch(n){console.error("OAuth callback failed:",n),r("error"),s(n?.message||"OAuth callback failed")}})()},[l,c,t,u,a]),e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-gradient-to-br from-background to-muted p-4",children:e.jsx("div",{className:"max-w-sm text-center space-y-4",children:w==="working"?e.jsxs(e.Fragment,{children:[e.jsx(v,{className:"h-8 w-8 animate-spin text-muted-foreground mx-auto"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Finishing sign-in with Coconut..."})]}):e.jsxs(e.Fragment,{children:[e.jsx("h1",{className:"text-lg font-semibold",children:"Sign-in failed"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:b||"Something went wrong completing OAuth sign-in."}),e.jsx("button",{type:"button",className:"text-sm underline",onClick:()=>c("/login",{replace:!0}),children:"Back to login"})]})})})}export{I as default};