loopable-cli 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/_connectorId-CDCuSgpN.js +1 -0
  3. package/.output/public/assets/_loopId-DOnIsVTW.js +1 -0
  4. package/.output/public/assets/_taskId-BO5MZnlZ.js +1 -0
  5. package/.output/public/assets/agents-CBozi7oi.js +1 -0
  6. package/.output/public/assets/alert-Bn_wjgTX.js +1 -0
  7. package/.output/public/assets/button-K3ypIhAZ.js +1 -0
  8. package/.output/public/assets/card-DiVnaTIE.js +1 -0
  9. package/.output/public/assets/chevron-right-BrctLtFK.js +1 -0
  10. package/.output/public/assets/connection-status-DKWelvLO.js +1 -0
  11. package/.output/public/assets/connector-icon-CEbdE71G.js +1 -0
  12. package/.output/public/assets/connectors-JyX3IzJj.js +1 -0
  13. package/.output/public/assets/gaps-PjmcbaWo.js +1 -0
  14. package/.output/public/assets/inbox-CujRR0Cz.js +1 -0
  15. package/.output/public/assets/index-C9SQ_Baq.js +16 -0
  16. package/.output/public/assets/loop-form-Dw3cuTzw.js +1 -0
  17. package/.output/public/assets/loops-DcEfZa2_.js +1 -0
  18. package/.output/public/assets/manifests-yJpevyye.js +1 -0
  19. package/.output/public/assets/new-CwsnNuRW.js +1 -0
  20. package/.output/public/assets/page-bvnfRMum.js +1 -0
  21. package/.output/public/assets/play-yHLs4DjK.js +1 -0
  22. package/.output/public/assets/plus-Ber25lrU.js +1 -0
  23. package/.output/public/assets/preload-helper-BoU_7EQC.js +3 -0
  24. package/.output/public/assets/{refresh-cw-C3xBnKfy.js → refresh-cw-BzSY7M8I.js} +1 -1
  25. package/.output/public/assets/rotate-ccw-DLv9EfCX.js +1 -0
  26. package/.output/public/assets/runners-DzX-RU3i.js +2 -0
  27. package/.output/public/assets/select-C9grIFwG.js +1 -0
  28. package/.output/public/assets/setting-fields-DUc3npgh.js +3 -0
  29. package/.output/public/assets/styles-B9B98zLk.css +2 -0
  30. package/.output/public/assets/switch-DwABVI6d.js +1 -0
  31. package/.output/public/assets/task-list-Ddk8-qt7.js +1 -0
  32. package/.output/public/assets/textarea-Ds-gIYUQ.js +1 -0
  33. package/.output/public/assets/time-goBWd-5J.js +1 -0
  34. package/.output/public/assets/use-live-tasks-DZNNuECy.js +1 -0
  35. package/.output/public/assets/useCompositeListItem-P4Nmmn7j.js +1 -0
  36. package/.output/public/assets/usePositioner-B7i9Ejzh.js +1 -0
  37. package/.output/server/_chunks/ssr-renderer.mjs +1 -1
  38. package/.output/server/{_connectorId-C9yydJrC.mjs → _connectorId-COuQN02a.mjs} +198 -188
  39. package/.output/server/_libs/@base-ui/react+[...].mjs +1410 -804
  40. package/.output/server/_libs/@tanstack/react-router+[...].mjs +1 -1
  41. package/.output/server/_libs/lucide-react.mjs +93 -84
  42. package/.output/server/_libs/next-themes.mjs +1 -1
  43. package/.output/server/_libs/sonner.mjs +1 -1
  44. package/.output/server/_loopId-CZh6_Yhr.mjs +310 -0
  45. package/.output/server/_ssr/{agents-DG643yoJ.mjs → agents-B_qo1gpL.mjs} +195 -6
  46. package/.output/server/_ssr/{agents-C7B6RJ6-.mjs → agents-Bz10gz_m.mjs} +8 -8
  47. package/.output/server/_ssr/agents-CjbOUp3Z.mjs +206 -0
  48. package/.output/server/_ssr/{alert-DQvzE7bu.mjs → alert-C2WBWfzo.mjs} +2 -2
  49. package/.output/server/_ssr/card-r1cV-PCN.mjs +36 -0
  50. package/.output/server/_ssr/{client-BtVRVhQ2.mjs → client-Dk3SD8Il.mjs} +5 -1
  51. package/.output/server/_ssr/connection-status-BogAL-Fj.mjs +32 -0
  52. package/.output/server/_ssr/{connections-Df-aDpfJ.mjs → connections-Cqvb6Gw2.mjs} +372 -325
  53. package/.output/server/_ssr/connector-icon-DrhVbhs6.mjs +190 -0
  54. package/.output/server/_ssr/connectors-BfS5tQKr.mjs +81 -0
  55. package/.output/server/_ssr/{connectors-e0mf2pMs.mjs → connectors-DJI-rzPU.mjs} +10 -10
  56. package/.output/server/_ssr/{createServerRpc-DPDrnFdH.mjs → createServerRpc-DDrp2nLT.mjs} +2 -2
  57. package/.output/server/_ssr/{gaps-Cz76ZicM.mjs → gaps-CcvHiLcj.mjs} +15 -7
  58. package/.output/server/_ssr/inbox-D1ef761v.mjs +178 -0
  59. package/.output/server/_ssr/loop-form-DWwOR05R.mjs +346 -0
  60. package/.output/server/_ssr/{loops-D8WuK7Ke.mjs → loops-6WhUe_lc.mjs} +37 -27
  61. package/.output/server/_ssr/loops-DHPjzG-t.mjs +217 -0
  62. package/.output/server/_ssr/new-ChKBdcXJ.mjs +245 -0
  63. package/.output/server/_ssr/page-DZVxKvdn.mjs +120 -0
  64. package/.output/server/_ssr/{router-54IDWTVz.mjs → router-DdwREiOf.mjs} +162 -489
  65. package/.output/server/_ssr/runners-CK9Cx9fS.mjs +217 -0
  66. package/.output/server/_ssr/runners-CrznFPHt.mjs +140 -0
  67. package/.output/server/_ssr/{runners-Cj6z9Mqh.mjs → runners-W-pgo5yo.mjs} +5 -5
  68. package/.output/server/_ssr/{secrets-CRnpwGBh.mjs → secrets-CV5scFlt.mjs} +2 -2
  69. package/.output/server/_ssr/select-BtndHhHb.mjs +76 -0
  70. package/.output/server/_ssr/{setting-fields-DzBlslan.mjs → setting-fields-LNgywAW7.mjs} +25 -20
  71. package/.output/server/_ssr/ssr.mjs +43 -42
  72. package/.output/server/_ssr/{start-Vq3Oan3v.mjs → start-C_j-e4vF.mjs} +9 -4
  73. package/.output/server/_ssr/{switch-1pnd_bPJ.mjs → switch-odxNO_S4.mjs} +3 -3
  74. package/.output/server/_ssr/task-list-Dnmq_WeE.mjs +150 -0
  75. package/.output/server/_ssr/{tasks-Qtml5TlK.mjs → tasks-D-kXLgVP.mjs} +13 -13
  76. package/.output/server/_ssr/{tasks-BDqznm57.mjs → tasks-D7aUvA33.mjs} +44 -17
  77. package/.output/server/_ssr/{textarea-CHJTKtsJ.mjs → textarea-D2c_vTIC.mjs} +2 -2
  78. package/.output/server/_ssr/time-Cy8TZP0Z.mjs +13 -0
  79. package/.output/server/_ssr/use-live-tasks-BzhTkEOL.mjs +40 -0
  80. package/.output/server/_tanstack-start-manifest_v-2HUdn-2E.mjs +166 -0
  81. package/.output/server/_taskId-D3KkNJW1.mjs +263 -0
  82. package/.output/server/index.mjs +199 -164
  83. package/README.md +36 -6
  84. package/dist/cli.mjs +161 -8
  85. package/dist/dispatcher.mjs +671 -285
  86. package/dist/runner.mjs +333 -46
  87. package/drizzle/0025_prompt_tasks_done.sql +2 -0
  88. package/drizzle/0026_guidance_into_prompt.sql +3 -0
  89. package/drizzle/0027_relative_folders.sql +5 -0
  90. package/drizzle/0028_runner_version.sql +5 -0
  91. package/drizzle/meta/_journal.json +29 -1
  92. package/package.json +4 -2
  93. package/.output/public/assets/_connectorId-CkygNLny.js +0 -1
  94. package/.output/public/assets/_loopId-Cshlc5Ja.js +0 -1
  95. package/.output/public/assets/_taskId-BKDIJ_Fg.js +0 -1
  96. package/.output/public/assets/alert-BT2EVMJP.js +0 -1
  97. package/.output/public/assets/arrow-left-CWUZt6k2.js +0 -1
  98. package/.output/public/assets/arrow-right-dy_oOg_c.js +0 -1
  99. package/.output/public/assets/connection-status-DCqqmY_6.js +0 -1
  100. package/.output/public/assets/connector-icon-BUoK6Cru.js +0 -1
  101. package/.output/public/assets/connectors-CeLBtEtg.js +0 -1
  102. package/.output/public/assets/external-link-DC11orFA.js +0 -1
  103. package/.output/public/assets/gaps-BtFoD7mF.js +0 -1
  104. package/.output/public/assets/inbox-BYNjkNDJ.js +0 -1
  105. package/.output/public/assets/index-0yP3Jn_G.js +0 -18
  106. package/.output/public/assets/loader-B4Epchm_.js +0 -1
  107. package/.output/public/assets/loop-form-DnSJNc1k.js +0 -1
  108. package/.output/public/assets/loops-1CvbqO6m.js +0 -1
  109. package/.output/public/assets/new-m5NlqYQT.js +0 -1
  110. package/.output/public/assets/play-DD4xQgvi.js +0 -1
  111. package/.output/public/assets/preload-helper-CfdAYKD7.js +0 -3
  112. package/.output/public/assets/rolldown-runtime-CbXtAM7H.js +0 -1
  113. package/.output/public/assets/runners-D8QVl-Y6.js +0 -1
  114. package/.output/public/assets/select-Cppu-hti.js +0 -1
  115. package/.output/public/assets/setting-fields-bJ_gTG7Q.js +0 -3
  116. package/.output/public/assets/styles-ClTGaXU0.css +0 -2
  117. package/.output/public/assets/switch-hRIbNGOj.js +0 -1
  118. package/.output/public/assets/task-list-BAxjcVgr.js +0 -1
  119. package/.output/public/assets/textarea-Fyuzi6Vp.js +0 -1
  120. package/.output/public/assets/trash-2-BXZzBsoV.js +0 -1
  121. package/.output/public/assets/useValueChanged-VVyq4hb9.js +0 -1
  122. package/.output/server/_loopId-B0VG-eBC.mjs +0 -301
  123. package/.output/server/_ssr/connection-status-BZr3Y-IC.mjs +0 -31
  124. package/.output/server/_ssr/connector-icon-WvxwZ5TF.mjs +0 -56
  125. package/.output/server/_ssr/connectors-BU0IiRge.mjs +0 -107
  126. package/.output/server/_ssr/inbox-CAUBa1I3.mjs +0 -114
  127. package/.output/server/_ssr/loop-form-FqSaXiHl.mjs +0 -413
  128. package/.output/server/_ssr/loops-Dqoebe8q.mjs +0 -222
  129. package/.output/server/_ssr/new-bBsVaWD6.mjs +0 -169
  130. package/.output/server/_ssr/runners-D2UAdLyj.mjs +0 -106
  131. package/.output/server/_ssr/runners-DGWaVvWi.mjs +0 -116
  132. package/.output/server/_ssr/task-list-_qgBS9LU.mjs +0 -187
  133. package/.output/server/_tanstack-start-manifest_v-CvheE7ZF.mjs +0 -131
  134. package/.output/server/_taskId-V4QLBO2N.mjs +0 -256
@@ -1,16 +1,19 @@
1
1
  import { i as __toESM } from "./_runtime.mjs";
2
- import { U as require_jsx_runtime, W as require_react, a as AvatarFallback$1, o as AvatarImage$1, s as AvatarRoot } from "./_libs/@base-ui/react+[...].mjs";
2
+ import { K as require_jsx_runtime, c as AvatarFallback$1, l as AvatarImage$1, q as require_react, u as AvatarRoot } from "./_libs/@base-ui/react+[...].mjs";
3
3
  import { f as Link, m as useRouter } from "./_libs/@tanstack/react-router+[...].mjs";
4
- import { i as connectionNoun, o as connectorManifest } from "./_ssr/connections-Df-aDpfJ.mjs";
4
+ import { a as connectionNoun, d as destinationLabel, s as connectorManifest } from "./_ssr/connections-Cqvb6Gw2.mjs";
5
5
  import { l as registrableCallbackUrl } from "./_ssr/access-DTttr563.mjs";
6
- import { B as ArrowLeft, C as ExternalLink, M as CircleAlert, c as RotateCcw, g as Loader, i as Trash2, l as RefreshCw } from "./_libs/lucide-react.mjs";
6
+ import { F as ChevronRight, N as CircleAlert, c as RefreshCw, g as Loader, l as Plus, s as RotateCcw } from "./_libs/lucide-react.mjs";
7
7
  import { n as toast } from "./_libs/sonner.mjs";
8
- import { B as Card, F as disconnectConnection, H as CardHeader, I as saveConnectionSettings, L as verifyConnection, M as beginQrLogin, N as connectWithToken, P as continueQrLogin, R as Badge, S as Input$1, U as CardTitle, V as CardContent, W as cn, b as Label, u as Route$14, x as Separator$1, z as Button$1 } from "./_ssr/router-54IDWTVz.mjs";
9
- import { n as initialFieldValues, t as SettingFieldInputs } from "./_ssr/setting-fields-DzBlslan.mjs";
10
- import { t as ConnectionStatusBadge } from "./_ssr/connection-status-BZr3Y-IC.mjs";
11
- import { t as ConnectorIcon } from "./_ssr/connector-icon-WvxwZ5TF.mjs";
12
- import { n as AlertDescription, r as AlertTitle, t as Alert } from "./_ssr/alert-DQvzE7bu.mjs";
13
- //#region node_modules/.nitro/vite/services/ssr/assets/_connectorId-C9yydJrC.js
8
+ import { A as continueQrLogin, M as saveConnectionSettings, N as verifyConnection, O as beginQrLogin, P as cn, _ as Badge, g as Input$1, j as disconnectConnection, k as connectWithToken, u as Route$14, v as Button$1 } from "./_ssr/router-DdwREiOf.mjs";
9
+ import { t as ConnectorIcon } from "./_ssr/connector-icon-DrhVbhs6.mjs";
10
+ import { a as List, o as PageHeader, r as Label, t as Empty } from "./_ssr/page-DZVxKvdn.mjs";
11
+ import { n as initialFieldValues, t as SettingFieldInputs } from "./_ssr/setting-fields-LNgywAW7.mjs";
12
+ import { t as ConnectionStatusBadge } from "./_ssr/connection-status-BogAL-Fj.mjs";
13
+ import { n as AlertDescription, r as AlertTitle, t as Alert } from "./_ssr/alert-C2WBWfzo.mjs";
14
+ import { n as CardContent, t as Card } from "./_ssr/card-r1cV-PCN.mjs";
15
+ import { t as ago } from "./_ssr/time-Cy8TZP0Z.mjs";
16
+ //#region node_modules/.nitro/vite/services/ssr/assets/_connectorId-COuQN02a.js
14
17
  var import_react = /* @__PURE__ */ __toESM(require_react());
15
18
  var import_jsx_runtime = require_jsx_runtime();
16
19
  /** Renders a connector's settings from its manifest, so no page knows the fields. */
@@ -130,7 +133,7 @@ function QrConnect({ connectorId, note, onDone }) {
130
133
  onDone
131
134
  ]);
132
135
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, {
133
- className: "flex flex-col items-center gap-4 py-8",
136
+ className: "flex flex-col items-center gap-4 py-4",
134
137
  children: [
135
138
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
136
139
  className: "max-w-md text-center text-sm text-muted-foreground",
@@ -189,18 +192,17 @@ function TokenConnect({ connectorId, fields, note, helpUrl, onDone }) {
189
192
  }
190
193
  };
191
194
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, {
192
- className: "flex flex-col gap-4 py-6",
195
+ className: "flex flex-col gap-4 py-2",
193
196
  children: [
194
- note ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
195
- className: "text-sm text-muted-foreground",
196
- children: note
197
- }) : null,
198
- helpUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
199
- href: helpUrl,
200
- target: "_blank",
201
- rel: "noreferrer",
202
- className: "text-sm text-muted-foreground hover:text-foreground",
203
- children: "Open the app dashboard"
197
+ note ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
198
+ className: "text-xs text-muted-foreground",
199
+ children: [note, helpUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [" ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
200
+ href: helpUrl,
201
+ target: "_blank",
202
+ rel: "noreferrer",
203
+ className: "underline hover:text-foreground",
204
+ children: "Open the app dashboard"
205
+ })] }) : null]
204
206
  }) : null,
205
207
  fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
206
208
  className: "flex flex-col gap-1.5",
@@ -259,44 +261,47 @@ function ConnectorDetailPage() {
259
261
  const tokens = manifest.auth.kind === "token";
260
262
  const [scanning, setScanning] = (0, import_react.useState)(false);
261
263
  const [pasting, setPasting] = (0, import_react.useState)(false);
264
+ const connectButton = state.readiness.ready && canAddAccount ? scans ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
265
+ onClick: () => setScanning((open) => !open),
266
+ children: scanning ? "Cancel" : "Connect"
267
+ }) : tokens ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
268
+ onClick: () => setPasting((open) => !open),
269
+ children: pasting ? "Cancel" : "Add bot"
270
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
271
+ nativeButton: false,
272
+ render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `/api/connectors/${connectorId}/authorize` }),
273
+ children: state.connections.length > 0 ? "Add account" : "Connect"
274
+ }) : null;
262
275
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
263
276
  className: "flex flex-col gap-6",
264
277
  children: [
265
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
266
- to: "/connectors",
267
- className: "flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground",
268
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowLeft, { className: "size-4" }), "Connectors"]
269
- }),
270
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
271
- className: "flex items-start gap-4",
272
- children: [
273
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectorIcon, {
274
- icon: manifest.icon,
275
- accent: manifest.accent,
276
- className: "size-11"
277
- }),
278
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
279
- className: "flex-1",
280
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
281
- className: "text-2xl font-semibold tracking-tight",
282
- children: manifest.name
283
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
284
- className: "mt-1 text-sm text-muted-foreground",
285
- children: manifest.tagline
286
- })]
287
- }),
288
- state.readiness.ready && canAddAccount ? scans ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
289
- onClick: () => setScanning((open) => !open),
290
- children: scanning ? "Cancel" : "Connect"
291
- }) : tokens ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
292
- onClick: () => setPasting((open) => !open),
293
- children: pasting ? "Cancel" : "Add bot"
294
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
295
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `/api/connectors/${connectorId}/authorize` }),
296
- children: state.connections.length > 0 ? "Add another account" : "Connect"
297
- }) : null
298
- ]
278
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PageHeader, {
279
+ back: {
280
+ to: "/connectors",
281
+ label: "Connectors"
282
+ },
283
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectorIcon, {
284
+ icon: manifest.icon,
285
+ accent: manifest.accent
286
+ }),
287
+ title: manifest.name,
288
+ description: manifest.tagline,
289
+ actions: connectButton
299
290
  }),
291
+ !state.readiness.ready ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Alert, {
292
+ variant: "destructive",
293
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertTitle, { children: "Not available in this build" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDescription, {
294
+ className: "flex flex-col gap-1",
295
+ children: [
296
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: state.readiness.reason }),
297
+ state.readiness.fixHint ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: state.readiness.fixHint }) : null,
298
+ manifest.auth.kind === "oauth_redirect" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
299
+ className: "text-xs",
300
+ children: ["Callback URL: ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: registrableCallbackUrl(connectorId) })]
301
+ }) : null
302
+ ]
303
+ })]
304
+ }) : null,
300
305
  scanning && manifest.auth.kind === "qr_scan" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(QrConnect, {
301
306
  connectorId,
302
307
  note: manifest.auth.note,
@@ -309,111 +314,118 @@ function ConnectorDetailPage() {
309
314
  helpUrl: manifest.auth.helpUrl,
310
315
  onDone: () => setPasting(false)
311
316
  }) : null,
312
- !state.readiness.ready ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Alert, {
313
- variant: "destructive",
314
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertTitle, { children: [manifest.name, " is not available in this build"] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDescription, {
315
- className: "flex flex-col gap-2",
316
- children: [
317
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: state.readiness.reason }),
318
- state.readiness.fixHint ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: state.readiness.fixHint }) : null,
319
- manifest.auth.kind === "oauth_redirect" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
320
- className: "text-xs",
321
- children: ["Callback URL to register: ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: registrableCallbackUrl(connectorId) })]
322
- }) : null
323
- ]
324
- })]
325
- }) : null,
326
- state.connections.length === 0 && state.readiness.ready && !scanning && !pasting ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, {
327
- className: "py-8 text-center text-sm text-muted-foreground",
328
- children: [
329
- "No ",
330
- connectionNoun(connectorId),
331
- " connected yet.",
332
- manifest.auth.kind === "oauth_redirect" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
333
- " ",
334
- "Connecting opens ",
335
- manifest.name,
336
- " and asks for",
337
- " ",
338
- manifest.auth.scopes.join(", "),
339
- "."
340
- ] }) : null,
341
- manifest.auth.kind === "qr_scan" ? " Connecting shows a code to scan." : null,
342
- manifest.auth.kind === "token" ? " Connecting asks for app credentials, not a personal login." : null
343
- ]
344
- }) }) : null,
345
- state.connections.map((connection) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectionCard, {
317
+ state.connections.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(List, { children: state.connections.map((connection) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectionRow, {
346
318
  connection,
347
319
  manifest
348
- }, connection.id)),
349
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
350
- className: "text-base",
351
- children: "What this connector can do"
352
- }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, {
353
- className: "flex flex-col gap-4",
320
+ }, connection.id)) }) : state.readiness.ready && !scanning && !pasting ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Empty, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
321
+ "No ",
322
+ connectionNoun(connectorId),
323
+ " connected yet."
324
+ ] }), manifest.auth.kind === "oauth_redirect" && manifest.auth.note ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
325
+ className: "max-w-md text-xs",
326
+ children: manifest.auth.note
327
+ }) : null] }) : null,
328
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
329
+ className: "flex flex-col gap-2",
330
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
331
+ className: "flex items-center justify-between gap-3",
332
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", {
333
+ className: "text-sm font-medium",
334
+ children: "Loops"
335
+ }), manifest.triggers.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
336
+ variant: "ghost",
337
+ size: "sm",
338
+ nativeButton: false,
339
+ render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, { to: "/loops/new" }),
340
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Plus, {}), "New loop"]
341
+ }) : null]
342
+ }), state.loops.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
343
+ className: "text-sm text-muted-foreground",
344
+ children: [
345
+ "No loop uses ",
346
+ manifest.name,
347
+ " yet."
348
+ ]
349
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(List, { children: state.loops.map((loop) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
350
+ to: "/loops/$loopId",
351
+ params: { loopId: loop.id },
352
+ className: "flex items-center gap-3 px-4 py-2.5 transition-colors hover:bg-muted/50",
353
+ children: [
354
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
355
+ className: "min-w-0 flex-1",
356
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
357
+ className: "truncate text-sm font-medium",
358
+ children: loop.name
359
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
360
+ className: "truncate text-xs text-muted-foreground",
361
+ children: loop.connectorId === connectorId ? destinationLabel(loop.actionConnectorId, loop.actionId) : `Answers here, from ${connectorManifest(loop.connectorId)?.name ?? loop.connectorId}`
362
+ })]
363
+ }),
364
+ loop.enabled ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
365
+ variant: "secondary",
366
+ children: "Off"
367
+ }),
368
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: "size-4 text-muted-foreground" })
369
+ ]
370
+ }, loop.id)) })]
371
+ }),
372
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
373
+ className: "grid gap-6 sm:grid-cols-3",
354
374
  children: [
355
375
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CapabilityList, {
356
- title: "Workflows it offers",
357
- note: "Turn one on from the loops page.",
358
- empty: "None yet. An account can be connected, but no loop can be built on it.",
376
+ title: "Starts when",
377
+ empty: "Nothing. This connector cannot start a loop.",
378
+ items: manifest.triggers.map((trigger) => ({
379
+ id: trigger.id,
380
+ name: trigger.when,
381
+ summary: `When ${trigger.trigger}.`
382
+ }))
383
+ }),
384
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CapabilityList, {
385
+ title: "Workflows",
386
+ empty: "None. Use a custom loop.",
359
387
  items: manifest.workflows.map((workflow) => ({
360
388
  id: workflow.id,
361
389
  name: workflow.name,
362
390
  summary: workflow.summary
363
391
  }))
364
392
  }),
365
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator$1, {}),
366
393
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CapabilityList, {
367
- title: "What it writes",
368
- note: "A loop writes these back on its own.",
369
- empty: "Nothing. Loopable can read this account but cannot write to it.",
394
+ title: "Send to",
395
+ empty: "Nothing. This connector only reads.",
370
396
  items: manifest.actions.map((action) => ({
371
397
  id: action.id,
372
398
  name: action.name,
373
399
  summary: action.summary
374
400
  }))
375
- }),
376
- manifest.docsUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", {
377
- href: manifest.docsUrl,
378
- target: "_blank",
379
- rel: "noreferrer",
380
- className: "flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground",
381
- children: ["API documentation", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExternalLink, { className: "size-3.5" })]
382
- }) : null
401
+ })
383
402
  ]
384
- })] })
403
+ })
385
404
  ]
386
405
  });
387
406
  }
388
- function CapabilityList({ title, note, empty, items }) {
389
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
390
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
407
+ function CapabilityList({ title, empty, items }) {
408
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
409
+ className: "flex flex-col gap-2",
410
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", {
391
411
  className: "text-sm font-medium",
392
412
  children: title
393
- }),
394
- note && items.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
395
- className: "mt-0.5 text-xs text-muted-foreground",
396
- children: note
397
- }) : null,
398
- items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
399
- className: "mt-2 text-sm text-muted-foreground",
413
+ }), items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
414
+ className: "text-sm text-muted-foreground",
400
415
  children: empty
401
416
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
402
- className: "mt-3 flex flex-col gap-2",
403
- children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", {
417
+ className: "flex flex-col gap-2",
418
+ children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
404
419
  className: "text-sm",
405
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
406
- className: "font-medium",
407
- children: item.name
408
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
409
- className: "text-muted-foreground",
410
- children: [" — ", item.summary]
411
- })]
412
- }, item.id))
413
- })
414
- ] });
420
+ children: item.name
421
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
422
+ className: "text-xs text-muted-foreground",
423
+ children: item.summary
424
+ })] }, item.id))
425
+ })]
426
+ });
415
427
  }
416
- function ConnectionCard({ connection, manifest }) {
428
+ function ConnectionRow({ connection, manifest }) {
417
429
  const router = useRouter();
418
430
  const [busy, setBusy] = (0, import_react.useState)(null);
419
431
  const broken = connection.status === "needs_reauth" || connection.status === "error";
@@ -434,69 +446,67 @@ function ConnectionCard({ connection, manifest }) {
434
446
  setBusy(null);
435
447
  }
436
448
  };
437
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardHeader, {
438
- className: "flex flex-row items-center gap-3",
449
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
450
+ className: "flex flex-col gap-4 px-4 py-3",
439
451
  children: [
440
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Avatar$1, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarImage, {
441
- src: connection.avatarUrl ?? void 0,
442
- alt: connection.accountLabel
443
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarFallback, { children: connection.accountLabel.slice(0, 2).toUpperCase() })] }),
444
452
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
445
- className: "flex-1",
446
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
447
- className: "flex items-center gap-2",
448
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
449
- className: "font-medium",
450
- children: connection.accountLabel
451
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectionStatusBadge, { status: connection.status })]
452
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
453
- className: "mt-0.5 text-xs text-muted-foreground",
454
- children: connection.lastSyncedAt ? `Last checked ${new Date(connection.lastSyncedAt).toLocaleString()}` : "Not checked yet"
455
- })]
456
- }),
457
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
458
- variant: "outline",
459
- size: "sm",
460
- onClick: () => run("verify"),
461
- disabled: busy !== null,
462
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: busy === "verify" ? "animate-spin" : void 0 }), "Verify"]
453
+ className: "flex items-center gap-3",
454
+ children: [
455
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Avatar$1, {
456
+ className: "size-8",
457
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarImage, {
458
+ src: connection.avatarUrl ?? void 0,
459
+ alt: connection.accountLabel
460
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarFallback, { children: connection.accountLabel.slice(0, 2).toUpperCase() })]
461
+ }),
462
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
463
+ className: "min-w-0 flex-1",
464
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
465
+ className: "flex items-center gap-2",
466
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
467
+ className: "truncate text-sm font-medium",
468
+ children: connection.accountLabel
469
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectionStatusBadge, { status: connection.status })]
470
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
471
+ suppressHydrationWarning: true,
472
+ className: "mt-0.5 truncate text-xs text-muted-foreground",
473
+ children: [connection.lastSyncedAt ? `Checked ${ago(connection.lastSyncedAt)}` : "Not checked yet", connection.scopes.length > 0 ? connection.scopes.join(", ") : null].filter(Boolean).join(" · ")
474
+ })]
475
+ }),
476
+ broken ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
477
+ size: "sm",
478
+ nativeButton: false,
479
+ render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `/api/connectors/${connection.connectorId}/authorize` }),
480
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RotateCcw, {}), "Reconnect"]
481
+ }) : null,
482
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
483
+ variant: "ghost",
484
+ size: "sm",
485
+ onClick: () => run("verify"),
486
+ disabled: busy !== null,
487
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: busy === "verify" ? "animate-spin" : void 0 }), "Verify"]
488
+ }),
489
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
490
+ variant: "ghost",
491
+ size: "sm",
492
+ onClick: () => {
493
+ if (window.confirm(`Disconnect ${connection.accountLabel}?`)) run("disconnect");
494
+ },
495
+ disabled: busy !== null,
496
+ children: "Disconnect"
497
+ })
498
+ ]
463
499
  }),
464
- broken ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
465
- size: "sm",
466
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `/api/connectors/${connection.connectorId}/authorize` }),
467
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RotateCcw, {}), "Reconnect"]
500
+ connection.lastError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
501
+ className: "text-xs text-destructive",
502
+ children: connection.lastError
468
503
  }) : null,
469
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
470
- variant: "outline",
471
- size: "sm",
472
- onClick: () => run("disconnect"),
473
- disabled: busy !== null,
474
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Trash2, {}), "Disconnect"]
475
- })
476
- ]
477
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, {
478
- className: "flex flex-col gap-5 border-t pt-5",
479
- children: [
480
- connection.lastError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Alert, {
481
- variant: "destructive",
482
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDescription, { children: connection.lastError })
483
- }) : null,
484
- connection.scopes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
485
- className: "text-sm font-medium",
486
- children: "Granted access"
487
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
488
- className: "mt-2 flex flex-wrap gap-1.5",
489
- children: connection.scopes.map((scope) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
490
- variant: "outline",
491
- children: scope
492
- }, scope))
493
- })] }) : null,
494
504
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectionSettingsForm, {
495
505
  fields: manifest.settings,
496
506
  connection
497
507
  })
498
508
  ]
499
- })] });
509
+ });
500
510
  }
501
511
  //#endregion
502
512
  export { ConnectorDetailPage as component };