loopable-cli 0.2.0 → 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 (138) 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-BzSY7M8I.js +1 -0
  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-COuQN02a.mjs +512 -0
  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/{callback-D20cVD2w.mjs → access-DTttr563.mjs} +37 -20
  46. package/.output/server/_ssr/{agents-CrUmIQpi.mjs → agents-B_qo1gpL.mjs} +196 -7
  47. package/.output/server/_ssr/{agents-Dms_6TBF.mjs → agents-Bz10gz_m.mjs} +8 -8
  48. package/.output/server/_ssr/agents-CjbOUp3Z.mjs +206 -0
  49. package/.output/server/_ssr/{alert-DQvzE7bu.mjs → alert-C2WBWfzo.mjs} +2 -2
  50. package/.output/server/_ssr/card-r1cV-PCN.mjs +36 -0
  51. package/.output/server/_ssr/{client-BtVRVhQ2.mjs → client-Dk3SD8Il.mjs} +5 -1
  52. package/.output/server/_ssr/connection-status-BogAL-Fj.mjs +32 -0
  53. package/.output/server/_ssr/{connections-ypex3qUd.mjs → connections-Cqvb6Gw2.mjs} +1109 -263
  54. package/.output/server/_ssr/connector-icon-DrhVbhs6.mjs +190 -0
  55. package/.output/server/_ssr/connectors-BfS5tQKr.mjs +81 -0
  56. package/.output/server/_ssr/{connectors-BZly0yGF.mjs → connectors-DJI-rzPU.mjs} +21 -10
  57. package/.output/server/_ssr/{createServerRpc-DPDrnFdH.mjs → createServerRpc-DDrp2nLT.mjs} +2 -2
  58. package/.output/server/_ssr/{gaps-D2Zh8sEo.mjs → gaps-CcvHiLcj.mjs} +18 -10
  59. package/.output/server/_ssr/inbox-D1ef761v.mjs +178 -0
  60. package/.output/server/_ssr/loop-form-DWwOR05R.mjs +346 -0
  61. package/.output/server/_ssr/{loops-Og_G3KyZ.mjs → loops-6WhUe_lc.mjs} +228 -25
  62. package/.output/server/_ssr/loops-DHPjzG-t.mjs +217 -0
  63. package/.output/server/_ssr/new-ChKBdcXJ.mjs +245 -0
  64. package/.output/server/_ssr/page-DZVxKvdn.mjs +120 -0
  65. package/.output/server/_ssr/{router-BbrBz36P.mjs → router-DdwREiOf.mjs} +167 -489
  66. package/.output/server/_ssr/runners-CK9Cx9fS.mjs +217 -0
  67. package/.output/server/_ssr/runners-CrznFPHt.mjs +140 -0
  68. package/.output/server/_ssr/runners-W-pgo5yo.mjs +55 -0
  69. package/.output/server/_ssr/{secrets-CRnpwGBh.mjs → secrets-CV5scFlt.mjs} +2 -2
  70. package/.output/server/_ssr/select-BtndHhHb.mjs +76 -0
  71. package/.output/server/_ssr/{setting-fields-mpXfGftI.mjs → setting-fields-LNgywAW7.mjs} +25 -20
  72. package/.output/server/_ssr/ssr.mjs +49 -40
  73. package/.output/server/_ssr/{start-BgTj-h_C.mjs → start-C_j-e4vF.mjs} +10 -6
  74. package/.output/server/_ssr/{switch-1pnd_bPJ.mjs → switch-odxNO_S4.mjs} +3 -3
  75. package/.output/server/_ssr/task-list-Dnmq_WeE.mjs +150 -0
  76. package/.output/server/_ssr/{tasks-LIi-W4cy.mjs → tasks-D-kXLgVP.mjs} +13 -13
  77. package/.output/server/_ssr/{tasks-B_QmDFVs.mjs → tasks-D7aUvA33.mjs} +55 -17
  78. package/.output/server/_ssr/{textarea-CHJTKtsJ.mjs → textarea-D2c_vTIC.mjs} +2 -2
  79. package/.output/server/_ssr/time-Cy8TZP0Z.mjs +13 -0
  80. package/.output/server/_ssr/use-live-tasks-BzhTkEOL.mjs +40 -0
  81. package/.output/server/_tanstack-start-manifest_v-2HUdn-2E.mjs +166 -0
  82. package/.output/server/_taskId-D3KkNJW1.mjs +263 -0
  83. package/.output/server/index.mjs +204 -162
  84. package/README.md +54 -19
  85. package/dist/cli.mjs +185 -67
  86. package/dist/dispatcher.mjs +1443 -277
  87. package/dist/runner.mjs +333 -46
  88. package/drizzle/0025_prompt_tasks_done.sql +2 -0
  89. package/drizzle/0026_guidance_into_prompt.sql +3 -0
  90. package/drizzle/0027_relative_folders.sql +5 -0
  91. package/drizzle/0028_runner_version.sql +5 -0
  92. package/drizzle/meta/_journal.json +29 -1
  93. package/package.json +23 -17
  94. package/.output/public/assets/_connectorId-m67WbiJ8.js +0 -1
  95. package/.output/public/assets/_loopId-Bf4K5sdd.js +0 -1
  96. package/.output/public/assets/_taskId-eCKkcVOx.js +0 -1
  97. package/.output/public/assets/alert-BT2EVMJP.js +0 -1
  98. package/.output/public/assets/arrow-left-CWUZt6k2.js +0 -1
  99. package/.output/public/assets/arrow-right-dy_oOg_c.js +0 -1
  100. package/.output/public/assets/connection-status-DCqqmY_6.js +0 -1
  101. package/.output/public/assets/connector-icon-qGpNsPgH.js +0 -1
  102. package/.output/public/assets/connectors-DxXlc9zF.js +0 -1
  103. package/.output/public/assets/external-link-DC11orFA.js +0 -1
  104. package/.output/public/assets/gaps-CoTA-PzA.js +0 -1
  105. package/.output/public/assets/inbox-CLEXUXCI.js +0 -1
  106. package/.output/public/assets/index-Cndsw84p.js +0 -16
  107. package/.output/public/assets/loader-B4Epchm_.js +0 -1
  108. package/.output/public/assets/loop-form-BvizlZdR.js +0 -1
  109. package/.output/public/assets/loops-Dbe_mf5T.js +0 -1
  110. package/.output/public/assets/new-DPEaXKAY.js +0 -1
  111. package/.output/public/assets/play-DD4xQgvi.js +0 -1
  112. package/.output/public/assets/preload-helper-CfdAYKD7.js +0 -3
  113. package/.output/public/assets/rolldown-runtime-CbXtAM7H.js +0 -1
  114. package/.output/public/assets/runners-BVBggS5B.js +0 -1
  115. package/.output/public/assets/select-Cppu-hti.js +0 -1
  116. package/.output/public/assets/setting-fields-BT1naVJX.js +0 -3
  117. package/.output/public/assets/styles-D3sonCfX.css +0 -2
  118. package/.output/public/assets/switch-hRIbNGOj.js +0 -1
  119. package/.output/public/assets/task-list-CrptnI1N.js +0 -1
  120. package/.output/public/assets/textarea-Fyuzi6Vp.js +0 -1
  121. package/.output/public/assets/trash-2-BXZzBsoV.js +0 -1
  122. package/.output/public/assets/useValueChanged-VVyq4hb9.js +0 -1
  123. package/.output/server/_connectorId-DcSnoRjk.mjs +0 -421
  124. package/.output/server/_loopId-G_TAkYtS.mjs +0 -272
  125. package/.output/server/_ssr/access-B7TcOZ7F.mjs +0 -42
  126. package/.output/server/_ssr/connection-status-BZr3Y-IC.mjs +0 -31
  127. package/.output/server/_ssr/connector-icon-CFrrHjzR.mjs +0 -37
  128. package/.output/server/_ssr/connectors-4yzKb0KG.mjs +0 -106
  129. package/.output/server/_ssr/inbox-C2VBGLa5.mjs +0 -114
  130. package/.output/server/_ssr/loop-form-D-U-kU4k.mjs +0 -413
  131. package/.output/server/_ssr/loops-D0XJ8eBb.mjs +0 -222
  132. package/.output/server/_ssr/new-CajvgIog.mjs +0 -169
  133. package/.output/server/_ssr/runners-B_WuF8UJ.mjs +0 -32
  134. package/.output/server/_ssr/runners-D-0_lfiq.mjs +0 -106
  135. package/.output/server/_ssr/runners-zqF_zbEc.mjs +0 -116
  136. package/.output/server/_ssr/task-list-BnQJ94Dk.mjs +0 -187
  137. package/.output/server/_tanstack-start-manifest_v-BCHAazE8.mjs +0 -129
  138. package/.output/server/_taskId-CIv0ajIx.mjs +0 -256
@@ -1,421 +0,0 @@
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";
3
- import { f as Link, m as useRouter } from "./_libs/@tanstack/react-router+[...].mjs";
4
- import { a as connectorManifest } from "./_ssr/connections-ypex3qUd.mjs";
5
- import { a as registrableCallbackUrl } from "./_ssr/callback-D20cVD2w.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";
7
- import { n as toast } from "./_libs/sonner.mjs";
8
- import { B as CardHeader, F as verifyConnection, H as cn, I as Badge, L as Button$1, M as continueQrLogin, N as disconnectConnection, P as saveConnectionSettings, R as Card, V as CardTitle, j as beginQrLogin, u as Route$14, x as Separator$1, z as CardContent } from "./_ssr/router-BbrBz36P.mjs";
9
- import { n as initialFieldValues, t as SettingFieldInputs } from "./_ssr/setting-fields-mpXfGftI.mjs";
10
- import { t as ConnectionStatusBadge } from "./_ssr/connection-status-BZr3Y-IC.mjs";
11
- import { t as ConnectorIcon } from "./_ssr/connector-icon-CFrrHjzR.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-DcSnoRjk.js
14
- var import_react = /* @__PURE__ */ __toESM(require_react());
15
- var import_jsx_runtime = require_jsx_runtime();
16
- /** Renders a connector's settings from its manifest, so no page knows the fields. */
17
- function ConnectionSettingsForm({ fields, connection }) {
18
- const router = useRouter();
19
- const [values, setValues] = (0, import_react.useState)(() => initialFieldValues(fields, connection.settings));
20
- const [saving, setSaving] = (0, import_react.useState)(false);
21
- if (fields.length === 0) return null;
22
- const save = async () => {
23
- setSaving(true);
24
- try {
25
- await saveConnectionSettings({ data: {
26
- id: connection.id,
27
- settings: values
28
- } });
29
- await router.invalidate();
30
- toast.success("Settings saved");
31
- } catch (error) {
32
- toast.error(error instanceof Error ? error.message : String(error));
33
- } finally {
34
- setSaving(false);
35
- }
36
- };
37
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
38
- className: "flex flex-col gap-5",
39
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SettingFieldInputs, {
40
- fields,
41
- values,
42
- onChange: (key, value) => setValues((prev) => ({
43
- ...prev,
44
- [key]: value
45
- }))
46
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
47
- onClick: save,
48
- disabled: saving,
49
- children: saving ? "Saving..." : "Save settings"
50
- }) })]
51
- });
52
- }
53
- var LOOK_EVERY_MS = 2e3;
54
- /**
55
- * A login that finishes on a phone.
56
- *
57
- * The waiting is the whole component: a code lasts about two minutes, so it
58
- * has to say plainly whether it is still good, and offer another the moment it
59
- * is not. A dead square with no explanation is the failure to avoid.
60
- */
61
- function QrConnect({ connectorId, note, onDone }) {
62
- const router = useRouter();
63
- const [code, setCode] = (0, import_react.useState)(null);
64
- const [hint, setHint] = (0, import_react.useState)(null);
65
- const [expired, setExpired] = (0, import_react.useState)(null);
66
- const [loading, setLoading] = (0, import_react.useState)(true);
67
- /** Polling reads this, so a code replaced mid-flight is not polled again. */
68
- const current = (0, import_react.useRef)(null);
69
- const fetchCode = async () => {
70
- setLoading(true);
71
- setExpired(null);
72
- setHint(null);
73
- try {
74
- const started = await beginQrLogin({ data: { connectorId } });
75
- current.current = started.attempt;
76
- setCode({
77
- image: started.image,
78
- attempt: started.attempt
79
- });
80
- } catch (error) {
81
- setExpired(error instanceof Error ? error.message : String(error));
82
- setCode(null);
83
- } finally {
84
- setLoading(false);
85
- }
86
- };
87
- (0, import_react.useEffect)(() => {
88
- fetchCode();
89
- }, [connectorId]);
90
- (0, import_react.useEffect)(() => {
91
- if (!code || expired) return;
92
- let stop = false;
93
- const look = async () => {
94
- while (!stop) {
95
- await new Promise((resolve) => setTimeout(resolve, LOOK_EVERY_MS));
96
- if (stop || current.current === null) return;
97
- try {
98
- const outcome = await continueQrLogin({ data: {
99
- connectorId,
100
- attempt: current.current
101
- } });
102
- if (stop) return;
103
- if (outcome.state === "connected") {
104
- toast.success(`Connected ${outcome.accountLabel ?? connectorId}`);
105
- await router.invalidate();
106
- onDone?.();
107
- return;
108
- }
109
- if (outcome.state === "expired") {
110
- setExpired(outcome.reason ?? "The code expired before it was scanned.");
111
- return;
112
- }
113
- current.current = outcome.attempt;
114
- setHint(outcome.hint ?? null);
115
- } catch (error) {
116
- if (stop) return;
117
- setHint(error instanceof Error ? error.message : String(error));
118
- }
119
- }
120
- };
121
- look();
122
- return () => {
123
- stop = true;
124
- };
125
- }, [
126
- code,
127
- expired,
128
- connectorId,
129
- router,
130
- onDone
131
- ]);
132
- 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",
134
- children: [
135
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
136
- className: "max-w-md text-center text-sm text-muted-foreground",
137
- children: note
138
- }),
139
- expired ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Alert, {
140
- variant: "destructive",
141
- className: "max-w-md",
142
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleAlert, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDescription, { children: expired })]
143
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
144
- className: "flex size-[240px] items-center justify-center rounded-lg border bg-white",
145
- children: loading || !code ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Loader, { className: "size-5 animate-spin text-muted-foreground" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
146
- src: code.image,
147
- alt: "Scan with WeChat to connect",
148
- className: "size-[240px]"
149
- })
150
- }),
151
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
152
- className: "text-sm text-muted-foreground",
153
- children: expired ? "Ask for another and scan it this time." : hint ?? "Waiting for a scan..."
154
- }),
155
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
156
- variant: expired ? "default" : "outline",
157
- size: "sm",
158
- onClick: fetchCode,
159
- disabled: loading,
160
- children: expired ? "New code" : "Start over"
161
- })
162
- ]
163
- }) });
164
- }
165
- function Avatar$1({ className, size = "default", ...props }) {
166
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarRoot, {
167
- "data-slot": "avatar",
168
- "data-size": size,
169
- className: cn("group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten", className),
170
- ...props
171
- });
172
- }
173
- function AvatarImage({ className, ...props }) {
174
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarImage$1, {
175
- "data-slot": "avatar-image",
176
- className: cn("aspect-square size-full rounded-full object-cover", className),
177
- ...props
178
- });
179
- }
180
- function AvatarFallback({ className, ...props }) {
181
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarFallback$1, {
182
- "data-slot": "avatar-fallback",
183
- className: cn("flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs", className),
184
- ...props
185
- });
186
- }
187
- function ConnectorDetailPage() {
188
- const { connectorId } = Route$14.useParams();
189
- const state = Route$14.useLoaderData();
190
- const manifest = connectorManifest(connectorId);
191
- const canAddAccount = manifest.allowsMultipleAccounts || state.connections.length === 0;
192
- const scans = manifest.auth.kind === "qr_scan";
193
- const [scanning, setScanning] = (0, import_react.useState)(false);
194
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
195
- className: "flex flex-col gap-6",
196
- children: [
197
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
198
- to: "/connectors",
199
- className: "flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground",
200
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowLeft, { className: "size-4" }), "Connectors"]
201
- }),
202
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
203
- className: "flex items-start gap-4",
204
- children: [
205
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectorIcon, {
206
- icon: manifest.icon,
207
- accent: manifest.accent,
208
- className: "size-11"
209
- }),
210
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
211
- className: "flex-1",
212
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
213
- className: "text-2xl font-semibold tracking-tight",
214
- children: manifest.name
215
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
216
- className: "mt-1 text-sm text-muted-foreground",
217
- children: manifest.tagline
218
- })]
219
- }),
220
- state.readiness.ready && canAddAccount ? scans ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
221
- onClick: () => setScanning((open) => !open),
222
- children: scanning ? "Cancel" : "Connect"
223
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
224
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `/api/connectors/${connectorId}/authorize` }),
225
- children: state.connections.length > 0 ? "Add another account" : "Connect"
226
- }) : null
227
- ]
228
- }),
229
- scanning && manifest.auth.kind === "qr_scan" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(QrConnect, {
230
- connectorId,
231
- note: manifest.auth.note,
232
- onDone: () => setScanning(false)
233
- }) : null,
234
- !state.readiness.ready ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Alert, {
235
- variant: "destructive",
236
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertTitle, { children: [manifest.name, " is not available in this build"] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDescription, {
237
- className: "flex flex-col gap-2",
238
- children: [
239
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: state.readiness.reason }),
240
- state.readiness.fixHint ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: state.readiness.fixHint }) : null,
241
- manifest.auth.kind === "oauth_redirect" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
242
- className: "text-xs",
243
- children: ["Callback URL to register: ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: registrableCallbackUrl(connectorId) })]
244
- }) : null
245
- ]
246
- })]
247
- }) : null,
248
- state.connections.length === 0 && state.readiness.ready && !scanning ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, {
249
- className: "py-8 text-center text-sm text-muted-foreground",
250
- children: [
251
- "No account connected yet.",
252
- manifest.auth.kind === "oauth_redirect" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
253
- " ",
254
- "Connecting opens ",
255
- manifest.name,
256
- " and asks for",
257
- " ",
258
- manifest.auth.scopes.join(", "),
259
- "."
260
- ] }) : null,
261
- manifest.auth.kind === "qr_scan" ? " Connecting shows a code to scan." : null
262
- ]
263
- }) }) : null,
264
- state.connections.map((connection) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectionCard, {
265
- connection,
266
- manifest
267
- }, connection.id)),
268
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
269
- className: "text-base",
270
- children: "What this connector can do"
271
- }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, {
272
- className: "flex flex-col gap-4",
273
- children: [
274
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CapabilityList, {
275
- title: "Workflows it offers",
276
- note: "Turn one on from the loops page.",
277
- empty: "None yet. An account can be connected, but no loop can be built on it.",
278
- items: manifest.workflows.map((workflow) => ({
279
- id: workflow.id,
280
- name: workflow.name,
281
- summary: workflow.summary
282
- }))
283
- }),
284
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator$1, {}),
285
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CapabilityList, {
286
- title: "What it writes",
287
- note: "A loop writes these back on its own.",
288
- empty: "Nothing. Loopable can read this account but cannot write to it.",
289
- items: manifest.actions.map((action) => ({
290
- id: action.id,
291
- name: action.name,
292
- summary: action.summary
293
- }))
294
- }),
295
- manifest.docsUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", {
296
- href: manifest.docsUrl,
297
- target: "_blank",
298
- rel: "noreferrer",
299
- className: "flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground",
300
- children: ["API documentation", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExternalLink, { className: "size-3.5" })]
301
- }) : null
302
- ]
303
- })] })
304
- ]
305
- });
306
- }
307
- function CapabilityList({ title, note, empty, items }) {
308
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
309
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
310
- className: "text-sm font-medium",
311
- children: title
312
- }),
313
- note && items.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
314
- className: "mt-0.5 text-xs text-muted-foreground",
315
- children: note
316
- }) : null,
317
- items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
318
- className: "mt-2 text-sm text-muted-foreground",
319
- children: empty
320
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
321
- className: "mt-3 flex flex-col gap-2",
322
- children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", {
323
- className: "text-sm",
324
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
325
- className: "font-medium",
326
- children: item.name
327
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
328
- className: "text-muted-foreground",
329
- children: [" — ", item.summary]
330
- })]
331
- }, item.id))
332
- })
333
- ] });
334
- }
335
- function ConnectionCard({ connection, manifest }) {
336
- const router = useRouter();
337
- const [busy, setBusy] = (0, import_react.useState)(null);
338
- const broken = connection.status === "needs_reauth" || connection.status === "error";
339
- const run = async (action) => {
340
- setBusy(action);
341
- try {
342
- if (action === "verify") {
343
- const updated = await verifyConnection({ data: { id: connection.id } });
344
- toast[updated.status === "connected" ? "success" : "error"](updated.status === "connected" ? `${updated.accountLabel} is reachable` : updated.lastError ?? "This connection is not usable");
345
- } else {
346
- await disconnectConnection({ data: { id: connection.id } });
347
- toast.success(`Disconnected ${connection.accountLabel}`);
348
- }
349
- await router.invalidate();
350
- } catch (error) {
351
- toast.error(error instanceof Error ? error.message : String(error));
352
- } finally {
353
- setBusy(null);
354
- }
355
- };
356
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardHeader, {
357
- className: "flex flex-row items-center gap-3",
358
- children: [
359
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Avatar$1, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarImage, {
360
- src: connection.avatarUrl ?? void 0,
361
- alt: connection.accountLabel
362
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarFallback, { children: connection.accountLabel.slice(0, 2).toUpperCase() })] }),
363
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
364
- className: "flex-1",
365
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
366
- className: "flex items-center gap-2",
367
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
368
- className: "font-medium",
369
- children: connection.accountLabel
370
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectionStatusBadge, { status: connection.status })]
371
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
372
- className: "mt-0.5 text-xs text-muted-foreground",
373
- children: connection.lastSyncedAt ? `Last checked ${new Date(connection.lastSyncedAt).toLocaleString()}` : "Not checked yet"
374
- })]
375
- }),
376
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
377
- variant: "outline",
378
- size: "sm",
379
- onClick: () => run("verify"),
380
- disabled: busy !== null,
381
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: busy === "verify" ? "animate-spin" : void 0 }), "Verify"]
382
- }),
383
- broken ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
384
- size: "sm",
385
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `/api/connectors/${connection.connectorId}/authorize` }),
386
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RotateCcw, {}), "Reconnect"]
387
- }) : null,
388
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
389
- variant: "outline",
390
- size: "sm",
391
- onClick: () => run("disconnect"),
392
- disabled: busy !== null,
393
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Trash2, {}), "Disconnect"]
394
- })
395
- ]
396
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, {
397
- className: "flex flex-col gap-5 border-t pt-5",
398
- children: [
399
- connection.lastError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Alert, {
400
- variant: "destructive",
401
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDescription, { children: connection.lastError })
402
- }) : null,
403
- connection.scopes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
404
- className: "text-sm font-medium",
405
- children: "Granted access"
406
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
407
- className: "mt-2 flex flex-wrap gap-1.5",
408
- children: connection.scopes.map((scope) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
409
- variant: "outline",
410
- children: scope
411
- }, scope))
412
- })] }) : null,
413
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConnectionSettingsForm, {
414
- fields: manifest.settings,
415
- connection
416
- })
417
- ]
418
- })] });
419
- }
420
- //#endregion
421
- export { ConnectorDetailPage as component };