loopable-cli 0.1.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.
- package/.output/nitro.json +17 -0
- package/.output/public/apple-touch-icon.png +0 -0
- package/.output/public/assets/_connectorId-BWjYn5tm.js +1 -0
- package/.output/public/assets/_loopId-Ds4RkyEc.js +1 -0
- package/.output/public/assets/_taskId-BOzICXDf.js +1 -0
- package/.output/public/assets/alert-Bn9-Zm0l.js +1 -0
- package/.output/public/assets/arrow-left-BF9juV9T.js +1 -0
- package/.output/public/assets/arrow-right-CzqvnOY1.js +1 -0
- package/.output/public/assets/button-HCY6DCY-.js +1 -0
- package/.output/public/assets/connection-status-CYZB8kLy.js +1 -0
- package/.output/public/assets/connector-icon-BZ_MUJV_.js +1 -0
- package/.output/public/assets/connectors-BvzttfSu.js +1 -0
- package/.output/public/assets/connectors-DdJNwRN_.js +1 -0
- package/.output/public/assets/external-link-D46X-bXa.js +1 -0
- package/.output/public/assets/gaps-D-I6xiDc.js +1 -0
- package/.output/public/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/.output/public/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/.output/public/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/.output/public/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/.output/public/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/.output/public/assets/inbox-BUUu9xxE.js +1 -0
- package/.output/public/assets/index-ztzex0FN.js +10 -0
- package/.output/public/assets/loader-CcBl2u8m.js +1 -0
- package/.output/public/assets/loop-form-dB3CLcZb.js +1 -0
- package/.output/public/assets/loops-DRunQrxL.js +1 -0
- package/.output/public/assets/loops-oSdqMd29.js +1 -0
- package/.output/public/assets/manifests-DNMqf7Vi.js +7 -0
- package/.output/public/assets/new-uyFxVjuB.js +1 -0
- package/.output/public/assets/preload-helper-ORbuV86A.js +3 -0
- package/.output/public/assets/runners-DSU3r5Ww.js +1 -0
- package/.output/public/assets/setting-fields-ixkpdBb-.js +3 -0
- package/.output/public/assets/styles-DZL5V1o7.css +2 -0
- package/.output/public/assets/switch-d5ummmHY.js +1 -0
- package/.output/public/assets/task-list-BpOStt9v.js +1 -0
- package/.output/public/assets/tasks-B8MsKgic.js +1 -0
- package/.output/public/assets/trash-2-D6u6NpzO.js +1 -0
- package/.output/public/favicon.svg +9 -0
- package/.output/server/_chunks/ssr-renderer.mjs +26 -0
- package/.output/server/_connectorId-8nb5yOzG.mjs +421 -0
- package/.output/server/_libs/@base-ui/react+[...].mjs +12841 -0
- package/.output/server/_libs/@tanstack/react-router+[...].mjs +14349 -0
- package/.output/server/_libs/class-variance-authority+clsx.mjs +69 -0
- package/.output/server/_libs/dijkstrajs.mjs +118 -0
- package/.output/server/_libs/drizzle-orm.mjs +4349 -0
- package/.output/server/_libs/h3+rou3+srvx.mjs +1361 -0
- package/.output/server/_libs/lucide-react.mjs +911 -0
- package/.output/server/_libs/next-themes.mjs +53 -0
- package/.output/server/_libs/pngjs.mjs +1680 -0
- package/.output/server/_libs/qrcode.mjs +2583 -0
- package/.output/server/_libs/sonner.mjs +955 -0
- package/.output/server/_libs/tailwind-merge.mjs +3380 -0
- package/.output/server/_libs/tanstack__history.mjs +341 -0
- package/.output/server/_libs/ufo.mjs +64 -0
- package/.output/server/_loopId-BsUL1SeL.mjs +272 -0
- package/.output/server/_runtime.mjs +35 -0
- package/.output/server/_ssr/access-zIl15o8y.mjs +42 -0
- package/.output/server/_ssr/agents-Btql102J.mjs +657 -0
- package/.output/server/_ssr/agents-DAOZPgO2.mjs +76 -0
- package/.output/server/_ssr/alert-NEiOCTOl.mjs +37 -0
- package/.output/server/_ssr/callback-CUINvl7M.mjs +62 -0
- package/.output/server/_ssr/client-CKkOfh-s.mjs +335 -0
- package/.output/server/_ssr/connection-status-Bi5peUAk.mjs +31 -0
- package/.output/server/_ssr/connections-qnw2GVlP.mjs +2542 -0
- package/.output/server/_ssr/connector-icon-DZXQLLFo.mjs +37 -0
- package/.output/server/_ssr/connectors-BHNwuIMj.mjs +106 -0
- package/.output/server/_ssr/connectors-C28g0i4c.mjs +83 -0
- package/.output/server/_ssr/createServerRpc-DPDrnFdH.mjs +12 -0
- package/.output/server/_ssr/empty-plugin-adapters-BJ4m9L8g.mjs +5 -0
- package/.output/server/_ssr/gaps-RAFSXLZf.mjs +53 -0
- package/.output/server/_ssr/inbox-k5zHergU.mjs +35 -0
- package/.output/server/_ssr/loop-form-DlObSewZ.mjs +412 -0
- package/.output/server/_ssr/loops-APFcP0y6.mjs +311 -0
- package/.output/server/_ssr/loops-xt2Bn7_q.mjs +222 -0
- package/.output/server/_ssr/new-DfKyd2Wa.mjs +169 -0
- package/.output/server/_ssr/router-3WmpE5b_.mjs +1553 -0
- package/.output/server/_ssr/runners-By-mwc3F.mjs +32 -0
- package/.output/server/_ssr/runners-DI_NxpHC.mjs +116 -0
- package/.output/server/_ssr/runners-DtXs4Q8a.mjs +106 -0
- package/.output/server/_ssr/secrets-Hqti-niS.mjs +199 -0
- package/.output/server/_ssr/setting-fields-8vKFj4df.mjs +92 -0
- package/.output/server/_ssr/ssr.mjs +6605 -0
- package/.output/server/_ssr/start-Bdc2GJUI.mjs +51 -0
- package/.output/server/_ssr/switch-ReNglgH6.mjs +18 -0
- package/.output/server/_ssr/task-list-CUITIqkb.mjs +186 -0
- package/.output/server/_ssr/tasks-SAjNovX6.mjs +110 -0
- package/.output/server/_ssr/tasks-vcoodp_D.mjs +533 -0
- package/.output/server/_tanstack-start-manifest_v-C0cP5F0M.mjs +125 -0
- package/.output/server/_taskId-CXS3lod0.mjs +249 -0
- package/.output/server/index.mjs +541 -0
- package/README.md +81 -0
- package/dist/cli.mjs +165 -0
- package/dist/dispatcher.mjs +9871 -0
- package/dist/runner.mjs +657 -0
- package/drizzle/0000_cold_demogoblin.sql +29 -0
- package/drizzle/0001_fancy_blonde_phantom.sql +13 -0
- package/drizzle/0002_spooky_smiling_tiger.sql +16 -0
- package/drizzle/0003_small_golden_guardian.sql +25 -0
- package/drizzle/0004_wonderful_thunderbolts.sql +39 -0
- package/drizzle/0005_named_workflows.sql +7 -0
- package/drizzle/0006_signals.sql +18 -0
- package/drizzle/0007_review_comments.sql +1 -0
- package/drizzle/0008_held_signals.sql +1 -0
- package/drizzle/0009_work_item_ref.sql +58 -0
- package/drizzle/0010_signal_payload.sql +2 -0
- package/drizzle/0011_rule_poll_cursor.sql +1 -0
- package/drizzle/0012_loops.sql +63 -0
- package/drizzle/0013_loop_owns_action_and_prompt.sql +154 -0
- package/drizzle/0014_loop_poll_every.sql +4 -0
- package/drizzle/0015_machines.sql +10 -0
- package/drizzle/0016_task_machine.sql +1 -0
- package/drizzle/0017_loop_machine.sql +1 -0
- package/drizzle/0018_runners.sql +1 -0
- package/drizzle/0019_task_runner.sql +1 -0
- package/drizzle/0020_loop_runner.sql +1 -0
- package/drizzle/0021_drop_runner_kind.sql +1 -0
- package/drizzle/0022_drop_loop_runner.sql +1 -0
- package/drizzle/0023_shared_host.sql +6 -0
- package/drizzle/meta/0000_snapshot.json +206 -0
- package/drizzle/meta/0001_snapshot.json +284 -0
- package/drizzle/meta/0002_snapshot.json +390 -0
- package/drizzle/meta/0003_snapshot.json +566 -0
- package/drizzle/meta/0004_snapshot.json +633 -0
- package/drizzle/meta/0005_snapshot.json +626 -0
- package/drizzle/meta/0006_snapshot.json +752 -0
- package/drizzle/meta/0007_snapshot.json +759 -0
- package/drizzle/meta/0008_snapshot.json +766 -0
- package/drizzle/meta/0009_snapshot.json +752 -0
- package/drizzle/meta/0010_snapshot.json +766 -0
- package/drizzle/meta/0011_snapshot.json +773 -0
- package/drizzle/meta/0012_snapshot.json +773 -0
- package/drizzle/meta/0013_snapshot.json +817 -0
- package/drizzle/meta/_journal.json +174 -0
- package/package.json +88 -0
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
globalThis.__nitro_main__ = import.meta.url;
|
|
2
|
+
import { a as toEventHandler, c as serve, i as defineLazyEventHandler, n as HTTPError, r as defineHandler, s as NodeResponse, t as H3Core } from "./_libs/h3+rou3+srvx.mjs";
|
|
3
|
+
import { i as withoutTrailingSlash, n as joinURL, r as withLeadingSlash, t as decodePath } from "./_libs/ufo.mjs";
|
|
4
|
+
import { promises } from "node:fs";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { dirname, resolve } from "node:path";
|
|
7
|
+
//#region node_modules/.pnpm/nitro@3.0.260610-beta_@libsql+client@0.18.0_better-sqlite3@13.0.3_chokidar@5.0.0_dotenv_c0a0965703b3bad0e3d94216409cb606/node_modules/nitro/dist/runtime/internal/route-rules.mjs
|
|
8
|
+
var headers = ((m) => function headersRouteRule(event) {
|
|
9
|
+
for (const [key, value] of Object.entries(m.options || {})) event.res.headers.set(key, value);
|
|
10
|
+
});
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region #nitro/virtual/public-assets-data
|
|
13
|
+
var public_assets_data_default = {
|
|
14
|
+
"/apple-touch-icon.png": {
|
|
15
|
+
"type": "image/png",
|
|
16
|
+
"etag": "\"6e2-DpcPkINR92ffme+04R4KBRmf4jE\"",
|
|
17
|
+
"mtime": "2026-09-18T00:08:25.965Z",
|
|
18
|
+
"size": 1762,
|
|
19
|
+
"path": "../public/apple-touch-icon.png"
|
|
20
|
+
},
|
|
21
|
+
"/assets/_connectorId-BWjYn5tm.js": {
|
|
22
|
+
"type": "text/javascript; charset=utf-8",
|
|
23
|
+
"etag": "\"3032-gnIDiKhKaz4DRK5e9VkxwxYLTOk\"",
|
|
24
|
+
"mtime": "2026-09-18T00:08:25.618Z",
|
|
25
|
+
"size": 12338,
|
|
26
|
+
"path": "../public/assets/_connectorId-BWjYn5tm.js"
|
|
27
|
+
},
|
|
28
|
+
"/assets/_taskId-BOzICXDf.js": {
|
|
29
|
+
"type": "text/javascript; charset=utf-8",
|
|
30
|
+
"etag": "\"18b0-KE8FzeUmDGq60GCF3jSgeyYLM6s\"",
|
|
31
|
+
"mtime": "2026-09-18T00:08:25.618Z",
|
|
32
|
+
"size": 6320,
|
|
33
|
+
"path": "../public/assets/_taskId-BOzICXDf.js"
|
|
34
|
+
},
|
|
35
|
+
"/favicon.svg": {
|
|
36
|
+
"type": "image/svg+xml",
|
|
37
|
+
"etag": "\"1b3-uNgdb2Q4nmFEpsmW/cpMJbfKeng\"",
|
|
38
|
+
"mtime": "2026-09-18T00:08:25.965Z",
|
|
39
|
+
"size": 435,
|
|
40
|
+
"path": "../public/favicon.svg"
|
|
41
|
+
},
|
|
42
|
+
"/assets/_loopId-Ds4RkyEc.js": {
|
|
43
|
+
"type": "text/javascript; charset=utf-8",
|
|
44
|
+
"etag": "\"4a3a-QJd2crcmYz/WL+0nzrJBT2YHPno\"",
|
|
45
|
+
"mtime": "2026-09-18T00:08:25.618Z",
|
|
46
|
+
"size": 19002,
|
|
47
|
+
"path": "../public/assets/_loopId-Ds4RkyEc.js"
|
|
48
|
+
},
|
|
49
|
+
"/assets/alert-Bn9-Zm0l.js": {
|
|
50
|
+
"type": "text/javascript; charset=utf-8",
|
|
51
|
+
"etag": "\"4f0-wzjNbj9pbksm+Ncx8oEc2gwYX6s\"",
|
|
52
|
+
"mtime": "2026-09-18T00:08:25.618Z",
|
|
53
|
+
"size": 1264,
|
|
54
|
+
"path": "../public/assets/alert-Bn9-Zm0l.js"
|
|
55
|
+
},
|
|
56
|
+
"/assets/arrow-left-BF9juV9T.js": {
|
|
57
|
+
"type": "text/javascript; charset=utf-8",
|
|
58
|
+
"etag": "\"a3-6X251PYDTGl1L+lznar2X2azWAY\"",
|
|
59
|
+
"mtime": "2026-09-18T00:08:25.618Z",
|
|
60
|
+
"size": 163,
|
|
61
|
+
"path": "../public/assets/arrow-left-BF9juV9T.js"
|
|
62
|
+
},
|
|
63
|
+
"/assets/arrow-right-CzqvnOY1.js": {
|
|
64
|
+
"type": "text/javascript; charset=utf-8",
|
|
65
|
+
"etag": "\"a3-KlQKTBhSoKlWouRuoqez/GffHwo\"",
|
|
66
|
+
"mtime": "2026-09-18T00:08:25.618Z",
|
|
67
|
+
"size": 163,
|
|
68
|
+
"path": "../public/assets/arrow-right-CzqvnOY1.js"
|
|
69
|
+
},
|
|
70
|
+
"/assets/connector-icon-BZ_MUJV_.js": {
|
|
71
|
+
"type": "text/javascript; charset=utf-8",
|
|
72
|
+
"etag": "\"a39-bFZD5l+EH+upGkBxq9Fmv0TOEpQ\"",
|
|
73
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
74
|
+
"size": 2617,
|
|
75
|
+
"path": "../public/assets/connector-icon-BZ_MUJV_.js"
|
|
76
|
+
},
|
|
77
|
+
"/assets/connection-status-CYZB8kLy.js": {
|
|
78
|
+
"type": "text/javascript; charset=utf-8",
|
|
79
|
+
"etag": "\"17b-tLHIF9p0R6BT2F8GoOmHygkLQYk\"",
|
|
80
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
81
|
+
"size": 379,
|
|
82
|
+
"path": "../public/assets/connection-status-CYZB8kLy.js"
|
|
83
|
+
},
|
|
84
|
+
"/assets/connectors-BvzttfSu.js": {
|
|
85
|
+
"type": "text/javascript; charset=utf-8",
|
|
86
|
+
"etag": "\"2c0-1C2NuamGVl6c38xZLaiuYHCOHPg\"",
|
|
87
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
88
|
+
"size": 704,
|
|
89
|
+
"path": "../public/assets/connectors-BvzttfSu.js"
|
|
90
|
+
},
|
|
91
|
+
"/assets/button-HCY6DCY-.js": {
|
|
92
|
+
"type": "text/javascript; charset=utf-8",
|
|
93
|
+
"etag": "\"afa8-Vfn4qX+cIrHs8bQg5XucqcgY1aU\"",
|
|
94
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
95
|
+
"size": 44968,
|
|
96
|
+
"path": "../public/assets/button-HCY6DCY-.js"
|
|
97
|
+
},
|
|
98
|
+
"/assets/external-link-D46X-bXa.js": {
|
|
99
|
+
"type": "text/javascript; charset=utf-8",
|
|
100
|
+
"etag": "\"f9-eBCuKpj2Q12rvDuTfLX3btrdEio\"",
|
|
101
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
102
|
+
"size": 249,
|
|
103
|
+
"path": "../public/assets/external-link-D46X-bXa.js"
|
|
104
|
+
},
|
|
105
|
+
"/assets/gaps-D-I6xiDc.js": {
|
|
106
|
+
"type": "text/javascript; charset=utf-8",
|
|
107
|
+
"etag": "\"5d1-hE9c+GBWYcO1vAj3Ke3WyqQse50\"",
|
|
108
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
109
|
+
"size": 1489,
|
|
110
|
+
"path": "../public/assets/gaps-D-I6xiDc.js"
|
|
111
|
+
},
|
|
112
|
+
"/assets/connectors-DdJNwRN_.js": {
|
|
113
|
+
"type": "text/javascript; charset=utf-8",
|
|
114
|
+
"etag": "\"968-pJq4ir3C02NK3sVyhOrBWxKy1QE\"",
|
|
115
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
116
|
+
"size": 2408,
|
|
117
|
+
"path": "../public/assets/connectors-DdJNwRN_.js"
|
|
118
|
+
},
|
|
119
|
+
"/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2": {
|
|
120
|
+
"type": "font/woff2",
|
|
121
|
+
"etag": "\"1cfc-yYSDXNlt/tTRaj6rJo8ZMqvY7pQ\"",
|
|
122
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
123
|
+
"size": 7420,
|
|
124
|
+
"path": "../public/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2"
|
|
125
|
+
},
|
|
126
|
+
"/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2": {
|
|
127
|
+
"type": "font/woff2",
|
|
128
|
+
"etag": "\"3aec-5kpQSZEtAzzU5kdiuro3Zr2YR54\"",
|
|
129
|
+
"mtime": "2026-09-18T00:08:25.621Z",
|
|
130
|
+
"size": 15084,
|
|
131
|
+
"path": "../public/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2"
|
|
132
|
+
},
|
|
133
|
+
"/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2": {
|
|
134
|
+
"type": "font/woff2",
|
|
135
|
+
"etag": "\"4080-mZu3Z7sOWqglha+kefNbUA9Pp+Q\"",
|
|
136
|
+
"mtime": "2026-09-18T00:08:25.621Z",
|
|
137
|
+
"size": 16512,
|
|
138
|
+
"path": "../public/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2"
|
|
139
|
+
},
|
|
140
|
+
"/assets/inbox-BUUu9xxE.js": {
|
|
141
|
+
"type": "text/javascript; charset=utf-8",
|
|
142
|
+
"etag": "\"35b-+Ls68OrQ65uJxSSW1LvTzxytENk\"",
|
|
143
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
144
|
+
"size": 859,
|
|
145
|
+
"path": "../public/assets/inbox-BUUu9xxE.js"
|
|
146
|
+
},
|
|
147
|
+
"/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2": {
|
|
148
|
+
"type": "font/woff2",
|
|
149
|
+
"etag": "\"1f44-6MZ7/PEEOeDVF0eHI650KpwKQV8\"",
|
|
150
|
+
"mtime": "2026-09-18T00:08:25.621Z",
|
|
151
|
+
"size": 8004,
|
|
152
|
+
"path": "../public/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2"
|
|
153
|
+
},
|
|
154
|
+
"/assets/loader-CcBl2u8m.js": {
|
|
155
|
+
"type": "text/javascript; charset=utf-8",
|
|
156
|
+
"etag": "\"199-VPhtRiNGxOVytCs9kNWrDU9TYZ8\"",
|
|
157
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
158
|
+
"size": 409,
|
|
159
|
+
"path": "../public/assets/loader-CcBl2u8m.js"
|
|
160
|
+
},
|
|
161
|
+
"/assets/geist-latin-wght-normal-BgDaEnEv.woff2": {
|
|
162
|
+
"type": "font/woff2",
|
|
163
|
+
"etag": "\"72d8-9J+D7/6th5UzRxIgoFX9awJv47A\"",
|
|
164
|
+
"mtime": "2026-09-18T00:08:25.621Z",
|
|
165
|
+
"size": 29400,
|
|
166
|
+
"path": "../public/assets/geist-latin-wght-normal-BgDaEnEv.woff2"
|
|
167
|
+
},
|
|
168
|
+
"/assets/index-ztzex0FN.js": {
|
|
169
|
+
"type": "text/javascript; charset=utf-8",
|
|
170
|
+
"etag": "\"66f21-m8rGnzfLHFKLMm2ahSh72yWn/94\"",
|
|
171
|
+
"mtime": "2026-09-18T00:08:25.618Z",
|
|
172
|
+
"size": 421665,
|
|
173
|
+
"path": "../public/assets/index-ztzex0FN.js"
|
|
174
|
+
},
|
|
175
|
+
"/assets/loops-DRunQrxL.js": {
|
|
176
|
+
"type": "text/javascript; charset=utf-8",
|
|
177
|
+
"etag": "\"13e3-WOeRG9/ZYrRARUyGwUXRL1+vd+k\"",
|
|
178
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
179
|
+
"size": 5091,
|
|
180
|
+
"path": "../public/assets/loops-DRunQrxL.js"
|
|
181
|
+
},
|
|
182
|
+
"/assets/loop-form-dB3CLcZb.js": {
|
|
183
|
+
"type": "text/javascript; charset=utf-8",
|
|
184
|
+
"etag": "\"2a2d-737XAJOcUFC2pL/Y/BKYc3vJWsM\"",
|
|
185
|
+
"mtime": "2026-09-18T00:08:25.619Z",
|
|
186
|
+
"size": 10797,
|
|
187
|
+
"path": "../public/assets/loop-form-dB3CLcZb.js"
|
|
188
|
+
},
|
|
189
|
+
"/assets/loops-oSdqMd29.js": {
|
|
190
|
+
"type": "text/javascript; charset=utf-8",
|
|
191
|
+
"etag": "\"3fe-Ggk3DNo7u/tTjB3pFTLz0raqbL0\"",
|
|
192
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
193
|
+
"size": 1022,
|
|
194
|
+
"path": "../public/assets/loops-oSdqMd29.js"
|
|
195
|
+
},
|
|
196
|
+
"/assets/manifests-DNMqf7Vi.js": {
|
|
197
|
+
"type": "text/javascript; charset=utf-8",
|
|
198
|
+
"etag": "\"323e-hLOI0RbV0NM4/OHjGUHnrhztJ3k\"",
|
|
199
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
200
|
+
"size": 12862,
|
|
201
|
+
"path": "../public/assets/manifests-DNMqf7Vi.js"
|
|
202
|
+
},
|
|
203
|
+
"/assets/new-uyFxVjuB.js": {
|
|
204
|
+
"type": "text/javascript; charset=utf-8",
|
|
205
|
+
"etag": "\"ce8-2q60m4YShYoXWbiIkp0y10HnBdw\"",
|
|
206
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
207
|
+
"size": 3304,
|
|
208
|
+
"path": "../public/assets/new-uyFxVjuB.js"
|
|
209
|
+
},
|
|
210
|
+
"/assets/runners-DSU3r5Ww.js": {
|
|
211
|
+
"type": "text/javascript; charset=utf-8",
|
|
212
|
+
"etag": "\"af5-C997VFcGFPmj8WEOsf5mnGQj9cQ\"",
|
|
213
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
214
|
+
"size": 2805,
|
|
215
|
+
"path": "../public/assets/runners-DSU3r5Ww.js"
|
|
216
|
+
},
|
|
217
|
+
"/assets/styles-DZL5V1o7.css": {
|
|
218
|
+
"type": "text/css; charset=utf-8",
|
|
219
|
+
"etag": "\"14d06-3HG4i2QhQPZahzNUkqbHYznQ7wA\"",
|
|
220
|
+
"mtime": "2026-09-18T00:08:25.621Z",
|
|
221
|
+
"size": 85254,
|
|
222
|
+
"path": "../public/assets/styles-DZL5V1o7.css"
|
|
223
|
+
},
|
|
224
|
+
"/assets/setting-fields-ixkpdBb-.js": {
|
|
225
|
+
"type": "text/javascript; charset=utf-8",
|
|
226
|
+
"etag": "\"996-8IeAq+3l6FcaHVXVJGE/W0vjVP8\"",
|
|
227
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
228
|
+
"size": 2454,
|
|
229
|
+
"path": "../public/assets/setting-fields-ixkpdBb-.js"
|
|
230
|
+
},
|
|
231
|
+
"/assets/preload-helper-ORbuV86A.js": {
|
|
232
|
+
"type": "text/javascript; charset=utf-8",
|
|
233
|
+
"etag": "\"1b096-Ajo0JbfC/TtOQvuq+CiAJ4d7pRM\"",
|
|
234
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
235
|
+
"size": 110742,
|
|
236
|
+
"path": "../public/assets/preload-helper-ORbuV86A.js"
|
|
237
|
+
},
|
|
238
|
+
"/assets/switch-d5ummmHY.js": {
|
|
239
|
+
"type": "text/javascript; charset=utf-8",
|
|
240
|
+
"etag": "\"1135-U//8LYm4b+7jSqmbcvoSZ4Z56es\"",
|
|
241
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
242
|
+
"size": 4405,
|
|
243
|
+
"path": "../public/assets/switch-d5ummmHY.js"
|
|
244
|
+
},
|
|
245
|
+
"/assets/task-list-BpOStt9v.js": {
|
|
246
|
+
"type": "text/javascript; charset=utf-8",
|
|
247
|
+
"etag": "\"103b-6lHR69Yo1NT5g36X1c2eTtlDom4\"",
|
|
248
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
249
|
+
"size": 4155,
|
|
250
|
+
"path": "../public/assets/task-list-BpOStt9v.js"
|
|
251
|
+
},
|
|
252
|
+
"/assets/trash-2-D6u6NpzO.js": {
|
|
253
|
+
"type": "text/javascript; charset=utf-8",
|
|
254
|
+
"etag": "\"146-zgXIFcRhpCQsfWfW00/9nVPx354\"",
|
|
255
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
256
|
+
"size": 326,
|
|
257
|
+
"path": "../public/assets/trash-2-D6u6NpzO.js"
|
|
258
|
+
},
|
|
259
|
+
"/assets/tasks-B8MsKgic.js": {
|
|
260
|
+
"type": "text/javascript; charset=utf-8",
|
|
261
|
+
"etag": "\"5f8-Jwa10ZkoAWdeunD2ywF7X5v05y8\"",
|
|
262
|
+
"mtime": "2026-09-18T00:08:25.620Z",
|
|
263
|
+
"size": 1528,
|
|
264
|
+
"path": "../public/assets/tasks-B8MsKgic.js"
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
//#endregion
|
|
268
|
+
//#region #nitro/virtual/public-assets-node
|
|
269
|
+
function readAsset(id) {
|
|
270
|
+
const serverDir = dirname(fileURLToPath(globalThis.__nitro_main__));
|
|
271
|
+
return promises.readFile(resolve(serverDir, public_assets_data_default[id].path));
|
|
272
|
+
}
|
|
273
|
+
//#endregion
|
|
274
|
+
//#region #nitro/virtual/public-assets
|
|
275
|
+
var publicAssetBases = {};
|
|
276
|
+
function isPublicAssetURL(id = "") {
|
|
277
|
+
if (public_assets_data_default[id]) return true;
|
|
278
|
+
for (const base in publicAssetBases) if (id.startsWith(base)) return true;
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
function getAsset(id) {
|
|
282
|
+
return public_assets_data_default[id];
|
|
283
|
+
}
|
|
284
|
+
//#endregion
|
|
285
|
+
//#region node_modules/.pnpm/nitro@3.0.260610-beta_@libsql+client@0.18.0_better-sqlite3@13.0.3_chokidar@5.0.0_dotenv_c0a0965703b3bad0e3d94216409cb606/node_modules/nitro/dist/runtime/internal/static.mjs
|
|
286
|
+
var METHODS = /* @__PURE__ */ new Set(["HEAD", "GET"]);
|
|
287
|
+
var EncodingMap = {
|
|
288
|
+
gzip: ".gz",
|
|
289
|
+
br: ".br",
|
|
290
|
+
zstd: ".zst"
|
|
291
|
+
};
|
|
292
|
+
var static_default = defineHandler((event) => {
|
|
293
|
+
if (event.req.method && !METHODS.has(event.req.method)) return;
|
|
294
|
+
let id = decodePath(withLeadingSlash(withoutTrailingSlash(event.url.pathname)));
|
|
295
|
+
let asset;
|
|
296
|
+
const encodings = [...(event.req.headers.get("accept-encoding") || "").split(",").map((e) => EncodingMap[e.trim()]).filter(Boolean).sort(), ""];
|
|
297
|
+
for (const encoding of encodings) for (const _id of [id + encoding, joinURL(id, "index.html" + encoding)]) {
|
|
298
|
+
const _asset = getAsset(_id);
|
|
299
|
+
if (_asset) {
|
|
300
|
+
asset = _asset;
|
|
301
|
+
id = _id;
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (!asset) {
|
|
306
|
+
if (isPublicAssetURL(id)) {
|
|
307
|
+
event.res.headers.delete("Cache-Control");
|
|
308
|
+
throw new HTTPError({ status: 404 });
|
|
309
|
+
}
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (encodings.length > 1) event.res.headers.append("Vary", "Accept-Encoding");
|
|
313
|
+
if (event.req.headers.get("if-none-match") === asset.etag) {
|
|
314
|
+
event.res.status = 304;
|
|
315
|
+
event.res.statusText = "Not Modified";
|
|
316
|
+
return "";
|
|
317
|
+
}
|
|
318
|
+
const ifModifiedSinceH = event.req.headers.get("if-modified-since");
|
|
319
|
+
const mtimeDate = new Date(asset.mtime);
|
|
320
|
+
if (ifModifiedSinceH && asset.mtime && new Date(ifModifiedSinceH) >= mtimeDate) {
|
|
321
|
+
event.res.status = 304;
|
|
322
|
+
event.res.statusText = "Not Modified";
|
|
323
|
+
return "";
|
|
324
|
+
}
|
|
325
|
+
if (asset.type) event.res.headers.set("Content-Type", asset.type);
|
|
326
|
+
if (asset.etag && !event.res.headers.has("ETag")) event.res.headers.set("ETag", asset.etag);
|
|
327
|
+
if (asset.mtime && !event.res.headers.has("Last-Modified")) event.res.headers.set("Last-Modified", mtimeDate.toUTCString());
|
|
328
|
+
if (asset.encoding && !event.res.headers.has("Content-Encoding")) event.res.headers.set("Content-Encoding", asset.encoding);
|
|
329
|
+
if (asset.size > 0 && !event.res.headers.has("Content-Length")) event.res.headers.set("Content-Length", asset.size.toString());
|
|
330
|
+
return readAsset(id);
|
|
331
|
+
});
|
|
332
|
+
//#endregion
|
|
333
|
+
//#region #nitro/virtual/routing
|
|
334
|
+
var findRouteRules = /* @__PURE__ */ (() => {
|
|
335
|
+
const $0 = [{
|
|
336
|
+
name: "headers",
|
|
337
|
+
route: "/assets/**",
|
|
338
|
+
handler: headers,
|
|
339
|
+
options: { "cache-control": "public, max-age=31536000, immutable" }
|
|
340
|
+
}];
|
|
341
|
+
return (m, p) => {
|
|
342
|
+
let r = [];
|
|
343
|
+
if (p.charCodeAt(p.length - 1) === 47) p = p.slice(0, -1) || "/";
|
|
344
|
+
let s = p.split("/");
|
|
345
|
+
if (s.length > 1) {
|
|
346
|
+
if (s[1] === "assets") r.unshift({
|
|
347
|
+
data: $0,
|
|
348
|
+
params: { "_": s.slice(2).join("/") }
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
return r;
|
|
352
|
+
};
|
|
353
|
+
})();
|
|
354
|
+
var _lazy_Y4m24U = defineLazyEventHandler(() => import("./_chunks/ssr-renderer.mjs"));
|
|
355
|
+
var findRoute = /* @__PURE__ */ (() => {
|
|
356
|
+
const data = {
|
|
357
|
+
route: "/**",
|
|
358
|
+
handler: _lazy_Y4m24U
|
|
359
|
+
};
|
|
360
|
+
return ((_m, p) => {
|
|
361
|
+
return {
|
|
362
|
+
data,
|
|
363
|
+
params: { "_": p.slice(1) }
|
|
364
|
+
};
|
|
365
|
+
});
|
|
366
|
+
})();
|
|
367
|
+
var globalMiddleware = [toEventHandler(static_default)].filter(Boolean);
|
|
368
|
+
//#endregion
|
|
369
|
+
//#region node_modules/.pnpm/nitro@3.0.260610-beta_@libsql+client@0.18.0_better-sqlite3@13.0.3_chokidar@5.0.0_dotenv_c0a0965703b3bad0e3d94216409cb606/node_modules/nitro/dist/runtime/internal/error/prod.mjs
|
|
370
|
+
var errorHandler = (error, event) => {
|
|
371
|
+
const res = defaultHandler(error, event);
|
|
372
|
+
return new NodeResponse(typeof res.body === "string" ? res.body : JSON.stringify(res.body, null, 2), res);
|
|
373
|
+
};
|
|
374
|
+
function defaultHandler(error, event) {
|
|
375
|
+
const unhandled = error.unhandled ?? !HTTPError.isError(error);
|
|
376
|
+
const { status = 500, statusText = "" } = unhandled ? {} : error;
|
|
377
|
+
if (status === 404) {
|
|
378
|
+
const url = event.url || new URL(event.req.url);
|
|
379
|
+
const baseURL = "/";
|
|
380
|
+
if (/^\/[^/]/.test(baseURL) && !url.pathname.startsWith(baseURL)) return {
|
|
381
|
+
status: 302,
|
|
382
|
+
headers: new Headers({ location: `${baseURL}${url.pathname.slice(1)}${url.search}` })
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
const headers = new Headers(unhandled ? {} : error.headers);
|
|
386
|
+
headers.set("content-type", "application/json; charset=utf-8");
|
|
387
|
+
return {
|
|
388
|
+
status,
|
|
389
|
+
statusText,
|
|
390
|
+
headers,
|
|
391
|
+
body: {
|
|
392
|
+
error: true,
|
|
393
|
+
...unhandled ? {
|
|
394
|
+
status,
|
|
395
|
+
unhandled: true
|
|
396
|
+
} : typeof error.toJSON === "function" ? error.toJSON() : {
|
|
397
|
+
status,
|
|
398
|
+
statusText,
|
|
399
|
+
message: error.message
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
//#endregion
|
|
405
|
+
//#region #nitro/virtual/error-handler
|
|
406
|
+
var errorHandlers = [errorHandler];
|
|
407
|
+
async function error_handler_default(error, event) {
|
|
408
|
+
for (const handler of errorHandlers) try {
|
|
409
|
+
const response = await handler(error, event, { defaultHandler });
|
|
410
|
+
if (response) return response;
|
|
411
|
+
} catch (error) {
|
|
412
|
+
console.error(error);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
//#endregion
|
|
416
|
+
//#region #nitro/virtual/app
|
|
417
|
+
function createNitroApp() {
|
|
418
|
+
const captureError = (error, errorCtx) => {
|
|
419
|
+
if (errorCtx?.event) {
|
|
420
|
+
const errors = errorCtx.event.req.context?.nitro?.errors;
|
|
421
|
+
if (errors) errors.push({
|
|
422
|
+
error,
|
|
423
|
+
context: errorCtx
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
const h3App = createH3App({ onError(error, event) {
|
|
428
|
+
return error_handler_default(error, event);
|
|
429
|
+
} });
|
|
430
|
+
let appHandler = (req) => {
|
|
431
|
+
req.context ||= {};
|
|
432
|
+
req.context.nitro = req.context.nitro || { errors: [] };
|
|
433
|
+
return h3App.fetch(req);
|
|
434
|
+
};
|
|
435
|
+
return {
|
|
436
|
+
fetch: appHandler,
|
|
437
|
+
h3: h3App,
|
|
438
|
+
hooks: void 0,
|
|
439
|
+
captureError
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
function createH3App(config) {
|
|
443
|
+
const h3App = new H3Core(config);
|
|
444
|
+
h3App["~findRoute"] = (event) => findRoute(event.req.method, event.url.pathname);
|
|
445
|
+
h3App["~middleware"].push(...globalMiddleware);
|
|
446
|
+
h3App["~getMiddleware"] = (event, route) => {
|
|
447
|
+
const pathname = event.url.pathname;
|
|
448
|
+
const method = event.req.method;
|
|
449
|
+
const middleware = [];
|
|
450
|
+
const routeRules = getRouteRules(method, pathname);
|
|
451
|
+
event.context.routeRules = routeRules?.routeRules;
|
|
452
|
+
if (routeRules?.routeRuleMiddleware.length) middleware.push(...routeRules.routeRuleMiddleware);
|
|
453
|
+
middleware.push(...h3App["~middleware"]);
|
|
454
|
+
if (route?.data?.middleware?.length) middleware.push(...route.data.middleware);
|
|
455
|
+
return middleware;
|
|
456
|
+
};
|
|
457
|
+
return h3App;
|
|
458
|
+
}
|
|
459
|
+
//#endregion
|
|
460
|
+
//#region node_modules/.pnpm/nitro@3.0.260610-beta_@libsql+client@0.18.0_better-sqlite3@13.0.3_chokidar@5.0.0_dotenv_c0a0965703b3bad0e3d94216409cb606/node_modules/nitro/dist/runtime/internal/app.mjs
|
|
461
|
+
var APP_ID = "default";
|
|
462
|
+
function useNitroApp() {
|
|
463
|
+
let instance = useNitroApp._instance;
|
|
464
|
+
if (instance) return instance;
|
|
465
|
+
instance = useNitroApp._instance = createNitroApp();
|
|
466
|
+
globalThis.__nitro__ = globalThis.__nitro__ || {};
|
|
467
|
+
globalThis.__nitro__[APP_ID] = instance;
|
|
468
|
+
return instance;
|
|
469
|
+
}
|
|
470
|
+
function getRouteRules(method, pathname) {
|
|
471
|
+
const m = findRouteRules(method, pathname);
|
|
472
|
+
if (!m?.length) return { routeRuleMiddleware: [] };
|
|
473
|
+
const routeRules = {};
|
|
474
|
+
for (const layer of m) for (const rule of layer.data) {
|
|
475
|
+
const currentRule = routeRules[rule.name];
|
|
476
|
+
if (currentRule) {
|
|
477
|
+
if (rule.options === false) {
|
|
478
|
+
delete routeRules[rule.name];
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (typeof currentRule.options === "object" && typeof rule.options === "object") currentRule.options = {
|
|
482
|
+
...currentRule.options,
|
|
483
|
+
...rule.options
|
|
484
|
+
};
|
|
485
|
+
else currentRule.options = rule.options;
|
|
486
|
+
currentRule.route = rule.route;
|
|
487
|
+
currentRule.params = {
|
|
488
|
+
...currentRule.params,
|
|
489
|
+
...layer.params
|
|
490
|
+
};
|
|
491
|
+
} else if (rule.options !== false) routeRules[rule.name] = {
|
|
492
|
+
...rule,
|
|
493
|
+
params: layer.params
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
const middleware = [];
|
|
497
|
+
const orderedRules = Object.values(routeRules).sort((a, b) => (a.handler?.order || 0) - (b.handler?.order || 0));
|
|
498
|
+
for (const rule of orderedRules) {
|
|
499
|
+
if (rule.options === false || !rule.handler) continue;
|
|
500
|
+
middleware.push(rule.handler(rule));
|
|
501
|
+
}
|
|
502
|
+
return {
|
|
503
|
+
routeRules,
|
|
504
|
+
routeRuleMiddleware: middleware
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
//#endregion
|
|
508
|
+
//#region node_modules/.pnpm/nitro@3.0.260610-beta_@libsql+client@0.18.0_better-sqlite3@13.0.3_chokidar@5.0.0_dotenv_c0a0965703b3bad0e3d94216409cb606/node_modules/nitro/dist/runtime/internal/error/hooks.mjs
|
|
509
|
+
function _captureError(error, type) {
|
|
510
|
+
console.error(`[${type}]`, error);
|
|
511
|
+
useNitroApp().captureError?.(error, { tags: [type] });
|
|
512
|
+
}
|
|
513
|
+
function trapUnhandledErrors() {
|
|
514
|
+
process.on("unhandledRejection", (error) => _captureError(error, "unhandledRejection"));
|
|
515
|
+
process.on("uncaughtException", (error) => _captureError(error, "uncaughtException"));
|
|
516
|
+
}
|
|
517
|
+
//#endregion
|
|
518
|
+
//#region #nitro/virtual/tracing
|
|
519
|
+
var tracingSrvxPlugins = [];
|
|
520
|
+
//#endregion
|
|
521
|
+
//#region node_modules/.pnpm/nitro@3.0.260610-beta_@libsql+client@0.18.0_better-sqlite3@13.0.3_chokidar@5.0.0_dotenv_c0a0965703b3bad0e3d94216409cb606/node_modules/nitro/dist/presets/node/runtime/node-server.mjs
|
|
522
|
+
var _parsedPort = Number.parseInt(process.env.NITRO_PORT ?? process.env.PORT ?? "");
|
|
523
|
+
var port = Number.isNaN(_parsedPort) ? 3e3 : _parsedPort;
|
|
524
|
+
var host = process.env.NITRO_HOST || process.env.HOST;
|
|
525
|
+
var cert = process.env.NITRO_SSL_CERT;
|
|
526
|
+
var key = process.env.NITRO_SSL_KEY;
|
|
527
|
+
var nitroApp = useNitroApp();
|
|
528
|
+
serve({
|
|
529
|
+
port,
|
|
530
|
+
hostname: host,
|
|
531
|
+
tls: cert && key ? {
|
|
532
|
+
cert,
|
|
533
|
+
key
|
|
534
|
+
} : void 0,
|
|
535
|
+
fetch: nitroApp.fetch,
|
|
536
|
+
plugins: [...tracingSrvxPlugins]
|
|
537
|
+
});
|
|
538
|
+
trapUnhandledErrors();
|
|
539
|
+
var node_server_default = {};
|
|
540
|
+
//#endregion
|
|
541
|
+
export { node_server_default as default };
|
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Loopable
|
|
2
|
+
|
|
3
|
+
Loopable watches the tools a team already uses and finishes the work with a coding agent. It picks up a signal, does what the loop says, and writes the result back. Loops run on their own. Every run is recorded.
|
|
4
|
+
|
|
5
|
+
Connect GitHub or Gmail, write a loop, leave a runner on. Pull requests get reviewed, mail gets triaged, assigned issues get a draft. You see what happened in the inbox.
|
|
6
|
+
|
|
7
|
+
The words for the parts — loop, workflow, runner, and the rest — are in [docs/concepts.md](docs/concepts.md).
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
Three processes. The agent always runs on a Runner, never on the App or Dispatcher.
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
Signal → Loop → Task
|
|
15
|
+
→ Dispatcher prepares context, picks a Runner
|
|
16
|
+
→ Runner runs the Agent
|
|
17
|
+
→ Dispatcher writes back
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
Loopable ──HTTP── Runner ── Agent CLI
|
|
22
|
+
(App + Dispatcher)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
| Process | Does |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| **App** | UI, HTTP API, OAuth, the interface runners pull from |
|
|
28
|
+
| **Dispatcher** | Watches for signals, prepares tasks, writes back |
|
|
29
|
+
| **Runner** | Runs the agent CLI |
|
|
30
|
+
|
|
31
|
+
App and Dispatcher share one database and stay on the same host. Only one Dispatcher may run against that database. Runners join over HTTP: this machine, or others. Extra machines are in [docs/deploy.md](docs/deploy.md).
|
|
32
|
+
|
|
33
|
+
## Use it locally
|
|
34
|
+
|
|
35
|
+
You need Node 22+ and an agent CLI signed in on the runner host (Codex or Cursor Agent).
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install -g loopable-cli
|
|
39
|
+
loopable start # App + Dispatcher at http://127.0.0.1:4321
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Open the app. Connect an account. Write a loop. On Runners, copy the join command:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
loopable runner --url http://127.0.0.1:4321 --token <from Runners>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If the dispatcher is not running, the app says so. If no runner has joined, tasks wait.
|
|
49
|
+
|
|
50
|
+
Connect GitHub from `http://127.0.0.1:4321` on this machine. Extra runners on other machines are in [docs/deploy.md](docs/deploy.md).
|
|
51
|
+
|
|
52
|
+
State lives in `~/.loopable/`. Credentials stay in the OS keychain.
|
|
53
|
+
|
|
54
|
+
## Develop
|
|
55
|
+
|
|
56
|
+
This section is only for working on the code. Running Loopable as a product is the CLI above, not pnpm. Dev uses `~/.loopable-dev/` and a separate keychain namespace, so it does not touch the local deploy database.
|
|
57
|
+
|
|
58
|
+
TanStack Start (React + Vite), SQLite, Tailwind. Tests are Vitest.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pnpm install
|
|
62
|
+
pnpm dev # App + Dispatcher + Runner, ~/.loopable-dev, hot reload
|
|
63
|
+
pnpm typecheck
|
|
64
|
+
pnpm test
|
|
65
|
+
pnpm db:generate # after changing src/server/db/schema.ts
|
|
66
|
+
pnpm db:studio
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`pnpm runner` is only for a second machine while `pnpm dev` is already running.
|
|
70
|
+
|
|
71
|
+
| Path | Contents |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| `src/connectors/` | One folder per connector: `manifest.ts` (browser-safe) and `runtime.ts` (server) |
|
|
74
|
+
| `src/agents/` | One folder per agent, same split |
|
|
75
|
+
| `src/server/` | Database, secrets, queue, server functions |
|
|
76
|
+
| `src/dispatcher/` | Dispatcher process |
|
|
77
|
+
| `src/runner/` | Runner process |
|
|
78
|
+
| `src/routes/` | Pages and `/api/` |
|
|
79
|
+
| `drizzle/` | Migrations |
|
|
80
|
+
|
|
81
|
+
A new connector is a folder plus one line in `src/connectors/manifests.ts` and `src/connectors/runtimes.ts`. See [docs/connectors.md](docs/connectors.md).
|