@kky42/pievo-server 2.4.14 → 3.0.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 (90) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{actionUi-5PtES4q0.js → actionUi-BZrLpgHT.js} +1 -1
  3. package/.output/public/assets/app-DXLuQNb9.css +2 -0
  4. package/.output/public/assets/index-Di_wpAtL.js +10 -0
  5. package/.output/public/assets/loops._loopId-X3ClNPMY.js +67 -0
  6. package/.output/public/assets/loops._loopId_.runs._runId-ByU2BSyF.js +3 -0
  7. package/.output/public/assets/preload-helper-hRTYB_ju.js +3 -0
  8. package/.output/public/assets/{routes-Dm_3J2aV.js → routes-BIOJZsig.js} +1 -1
  9. package/.output/public/assets/routes-K8D5uBiV.js +1 -0
  10. package/.output/server/_chunks/ssr-renderer.mjs +1 -1
  11. package/.output/server/_libs/{drizzle-orm+postgres.mjs → drizzle-orm.mjs} +93 -2218
  12. package/.output/server/_ssr/{MachinesModal-BaEtzycr.mjs → MachinesModal-CmVMec6B.mjs} +46 -46
  13. package/.output/server/_ssr/{actionUi-5HOCZnom.mjs → actionUi-DE-Pb2tv.mjs} +1 -2
  14. package/.output/server/_ssr/{artifactFiles-DO43wwXA.mjs → artifactFiles-Di1xDKvX.mjs} +5 -8
  15. package/.output/server/_ssr/{artifactKind-DwDr8IYc.mjs → artifactKind-DqpmtxDU.mjs} +3 -9
  16. package/.output/server/_ssr/{boot-C472kLwY.mjs → boot-CYRi-wez.mjs} +2152 -351
  17. package/.output/server/_ssr/lifecycleUi-BsbUsi5K.mjs +106 -0
  18. package/.output/server/_ssr/{loopApi-DT751TJA.mjs → loopApi-Bez1rHV0.mjs} +50 -66
  19. package/.output/server/_ssr/{loopProjection-qaD2I48a.mjs → loopProjection-esCjyZJg.mjs} +4 -23
  20. package/.output/server/_ssr/{loops._loopId-CXgw2Rz1.mjs → loops._loopId-KUezNY69.mjs} +8 -23
  21. package/.output/server/_ssr/{loops._loopId_.runs._runId-Dk94Z0Jq.mjs → loops._loopId_.runs._runId-BFP9oMrp.mjs} +2 -7
  22. package/.output/server/_ssr/{loops._loopId_.runs._runId-SASSqOfy.mjs → loops._loopId_.runs._runId-DOkUEesG.mjs} +18 -33
  23. package/.output/server/_ssr/{machineFns-BSrIgn3f.mjs → machineFns-CniGcY8s.mjs} +13 -50
  24. package/.output/server/_ssr/networkAccess-CIlK3ION.mjs +30 -0
  25. package/.output/server/_ssr/router-BFIH2UAE.mjs +362 -0
  26. package/.output/server/_ssr/routes-BSVBANI3.mjs +12 -0
  27. package/.output/server/_ssr/{routes-Cr-9yDEH.mjs → routes-DnE7XDe_.mjs} +91 -50
  28. package/.output/server/_ssr/{routes-DRBS4Zi4.mjs → routes-ngpX7h8D.mjs} +2 -4
  29. package/.output/server/_ssr/ssr.mjs +25 -34
  30. package/.output/server/_ssr/start-B5_9Z5W-.mjs +35 -0
  31. package/.output/server/{_tanstack-start-manifest_v-DxLIQ0cc.mjs → _tanstack-start-manifest_v-DnwAupbZ.mjs} +8 -13
  32. package/.output/server/drizzle/0000_baseline.sql +6 -97
  33. package/.output/server/drizzle/meta/_journal.json +2 -23
  34. package/.output/server/index.mjs +45 -52
  35. package/drizzle/0000_baseline.sql +6 -97
  36. package/drizzle/meta/_journal.json +2 -23
  37. package/package.json +4 -8
  38. package/scripts/pievo-server.mjs +49 -47
  39. package/scripts/server-cli-lib.mjs +21 -12
  40. package/scripts/server-network.mjs +139 -0
  41. package/.output/public/assets/SignIn-CIFwnZtF.js +0 -1
  42. package/.output/public/assets/app-DvHMhs7S.css +0 -2
  43. package/.output/public/assets/index-CRX2pu0W.js +0 -10
  44. package/.output/public/assets/loops._loopId-BsuV-Rmf.js +0 -67
  45. package/.output/public/assets/loops._loopId_.runs._runId-DpK_fzmZ.js +0 -3
  46. package/.output/public/assets/preload-helper-sAZOZb3G.js +0 -5
  47. package/.output/public/assets/routes-DxF_s3cD.js +0 -1
  48. package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +0 -419
  49. package/.output/server/_libs/@aws-sdk/checksums+[...].mjs +0 -10732
  50. package/.output/server/_libs/@aws-sdk/client-s3+[...].mjs +0 -9475
  51. package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +0 -137
  52. package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +0 -440
  53. package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +0 -62
  54. package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +0 -818
  55. package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +0 -59
  56. package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +0 -342
  57. package/.output/server/_libs/aws-crypto__crc32c.mjs +0 -314
  58. package/.output/server/_libs/aws-sdk__nested-clients.mjs +0 -2671
  59. package/.output/server/_ssr/SignIn-sHQaBQJC.mjs +0 -53
  60. package/.output/server/_ssr/artifacts-Cd7Qx3Qp.mjs +0 -2
  61. package/.output/server/_ssr/auth-0AamrwHo.mjs +0 -38355
  62. package/.output/server/_ssr/auth-client-lSMb_Idt.mjs +0 -1070
  63. package/.output/server/_ssr/bun-sqlite-dialect-BW9W1_Ps-DLIXocA0.mjs +0 -162
  64. package/.output/server/_ssr/core-RrmWoKne.mjs +0 -5
  65. package/.output/server/_ssr/d1-sqlite-dialect-BLC8LXE6-BoFMIPr_.mjs +0 -112
  66. package/.output/server/_ssr/db-BzvMQ2kx.mjs +0 -2
  67. package/.output/server/_ssr/dist-ClzqkwxD.mjs +0 -342
  68. package/.output/server/_ssr/factory-ixUjZqJn.mjs +0 -6903
  69. package/.output/server/_ssr/kysely-adapter-DkZbmKgV.mjs +0 -2
  70. package/.output/server/_ssr/kysely-migration-tables-JkVUjPF_-bPAX9LR_.mjs +0 -19
  71. package/.output/server/_ssr/logger-DDjsYB2X.mjs +0 -2
  72. package/.output/server/_ssr/loopTags-CXx5UdGf.mjs +0 -3356
  73. package/.output/server/_ssr/node-sqlite-dialect-BbUqnnYv.mjs +0 -162
  74. package/.output/server/_ssr/router-BlLlhfJe.mjs +0 -543
  75. package/.output/server/_ssr/routes-DTBltabU.mjs +0 -27
  76. package/.output/server/_ssr/start-4ifArtKx.mjs +0 -4
  77. package/.output/server/_ssr/store-vDZ9INSa.mjs +0 -2
  78. package/.output/server/_ssr/tokens-BHiCElYD.mjs +0 -2
  79. package/.output/server/drizzle/0001_add_pi_agent.sql +0 -9
  80. package/.output/server/drizzle/0002_remove_teams.sql +0 -15
  81. package/.output/server/drizzle/0003_add_loop_tags.sql +0 -5
  82. package/.output/server/node_modules/tslib/modules/index.js +0 -70
  83. package/.output/server/node_modules/tslib/modules/package.json +0 -3
  84. package/.output/server/node_modules/tslib/package.json +0 -47
  85. package/.output/server/node_modules/tslib/tslib.js +0 -484
  86. package/.output/server/package.json +0 -9
  87. package/drizzle/0001_add_pi_agent.sql +0 -9
  88. package/drizzle/0002_remove_teams.sql +0 -15
  89. package/drizzle/0003_add_loop_tags.sql +0 -5
  90. package/scripts/prestart.mjs +0 -66
@@ -5,30 +5,9 @@
5
5
  {
6
6
  "idx": 0,
7
7
  "version": "7",
8
- "when": 1785146849042,
8
+ "when": 1792651729223,
9
9
  "tag": "0000_baseline",
10
10
  "breakpoints": true
11
- },
12
- {
13
- "idx": 1,
14
- "version": "7",
15
- "when": 1785146849043,
16
- "tag": "0001_add_pi_agent",
17
- "breakpoints": true
18
- },
19
- {
20
- "idx": 2,
21
- "version": "7",
22
- "when": 1785146849044,
23
- "tag": "0002_remove_teams",
24
- "breakpoints": true
25
- },
26
- {
27
- "idx": 3,
28
- "version": "7",
29
- "when": 1786301181156,
30
- "tag": "0003_add_loop_tags",
31
- "breakpoints": true
32
11
  }
33
12
  ]
34
- }
13
+ }
@@ -11,80 +11,73 @@ var headers = ((m) => function headersRouteRule(event) {
11
11
  //#endregion
12
12
  //#region #nitro/virtual/public-assets-data
13
13
  var public_assets_data_default = {
14
+ "/assets/actionUi-BZrLpgHT.js": {
15
+ "type": "text/javascript; charset=utf-8",
16
+ "etag": "\"4286-Qit0x3bDDnN7vmOhgEqWGOFur4I\"",
17
+ "mtime": "2026-10-22T07:10:25.845Z",
18
+ "size": 17030,
19
+ "path": "../public/assets/actionUi-BZrLpgHT.js"
20
+ },
21
+ "/assets/app-DXLuQNb9.css": {
22
+ "type": "text/css; charset=utf-8",
23
+ "etag": "\"982e-ISvSlt1vwctZ1Z6CMWC173FpzQY\"",
24
+ "mtime": "2026-10-22T07:10:25.845Z",
25
+ "size": 38958,
26
+ "path": "../public/assets/app-DXLuQNb9.css"
27
+ },
14
28
  "/favicon.svg": {
15
29
  "type": "image/svg+xml",
16
30
  "etag": "\"2f9-diQHMODwkdsIQ2ssl9fzDaFKaXE\"",
17
- "mtime": "2026-08-10T01:06:28.350Z",
31
+ "mtime": "2026-10-22T07:10:26.305Z",
18
32
  "size": 761,
19
33
  "path": "../public/favicon.svg"
20
34
  },
21
- "/assets/SignIn-CIFwnZtF.js": {
22
- "type": "text/javascript; charset=utf-8",
23
- "etag": "\"40c-2rs0DSexiNCb72JsSSpXd0NasjQ\"",
24
- "mtime": "2026-08-10T01:06:27.499Z",
25
- "size": 1036,
26
- "path": "../public/assets/SignIn-CIFwnZtF.js"
27
- },
28
- "/assets/actionUi-5PtES4q0.js": {
35
+ "/assets/loops._loopId_.runs._runId-ByU2BSyF.js": {
29
36
  "type": "text/javascript; charset=utf-8",
30
- "etag": "\"4291-Qip7gU3oZ0DhRdO+agF1M/wjQdk\"",
31
- "mtime": "2026-08-10T01:06:27.499Z",
32
- "size": 17041,
33
- "path": "../public/assets/actionUi-5PtES4q0.js"
34
- },
35
- "/assets/app-DvHMhs7S.css": {
36
- "type": "text/css; charset=utf-8",
37
- "etag": "\"9b16-2OiJVtJYlZqGnZ1zxya8M2r8dwo\"",
38
- "mtime": "2026-08-10T01:06:27.500Z",
39
- "size": 39702,
40
- "path": "../public/assets/app-DvHMhs7S.css"
37
+ "etag": "\"329d-FjaefYK56yjpjbOEISrMQmnn39E\"",
38
+ "mtime": "2026-10-22T07:10:25.845Z",
39
+ "size": 12957,
40
+ "path": "../public/assets/loops._loopId_.runs._runId-ByU2BSyF.js"
41
41
  },
42
- "/assets/loops._loopId-BsuV-Rmf.js": {
42
+ "/assets/preload-helper-hRTYB_ju.js": {
43
43
  "type": "text/javascript; charset=utf-8",
44
- "etag": "\"1764c-nikBeaC2+r4UoKv9zhAqMGPFxGc\"",
45
- "mtime": "2026-08-10T01:06:27.499Z",
46
- "size": 95820,
47
- "path": "../public/assets/loops._loopId-BsuV-Rmf.js"
44
+ "etag": "\"11674-LVTbrEq23Rxhef/ahfiBpq1pgSo\"",
45
+ "mtime": "2026-10-22T07:10:25.845Z",
46
+ "size": 71284,
47
+ "path": "../public/assets/preload-helper-hRTYB_ju.js"
48
48
  },
49
- "/assets/loops._loopId_.runs._runId-DpK_fzmZ.js": {
49
+ "/assets/index-Di_wpAtL.js": {
50
50
  "type": "text/javascript; charset=utf-8",
51
- "etag": "\"33f3-kdFmoz9qUQuwLYEywD9Ly5ZD6iE\"",
52
- "mtime": "2026-08-10T01:06:27.499Z",
53
- "size": 13299,
54
- "path": "../public/assets/loops._loopId_.runs._runId-DpK_fzmZ.js"
51
+ "etag": "\"5e2fa-fuWeczqLYxjWaK1uhVFAhHesD/M\"",
52
+ "mtime": "2026-10-22T07:10:25.844Z",
53
+ "size": 385786,
54
+ "path": "../public/assets/index-Di_wpAtL.js"
55
55
  },
56
- "/assets/index-CRX2pu0W.js": {
56
+ "/assets/loops._loopId-X3ClNPMY.js": {
57
57
  "type": "text/javascript; charset=utf-8",
58
- "etag": "\"5def1-sVvbabEyPmXuKmSaK1pWDF1HSPg\"",
59
- "mtime": "2026-08-10T01:06:27.499Z",
60
- "size": 384753,
61
- "path": "../public/assets/index-CRX2pu0W.js"
58
+ "etag": "\"1749a-wvaPKbjZ5o8Gbh6hWtl3zld70zs\"",
59
+ "mtime": "2026-10-22T07:10:25.845Z",
60
+ "size": 95386,
61
+ "path": "../public/assets/loops._loopId-X3ClNPMY.js"
62
62
  },
63
- "/assets/routes-Dm_3J2aV.js": {
63
+ "/assets/routes-BIOJZsig.js": {
64
64
  "type": "text/javascript; charset=utf-8",
65
- "etag": "\"135-m+5pzcK0mToJrOEQv+dqjYiJYEs\"",
66
- "mtime": "2026-08-10T01:06:27.500Z",
65
+ "etag": "\"135-XoZP43FtQXsg+qNy3Rq8mg5WHbw\"",
66
+ "mtime": "2026-10-22T07:10:25.845Z",
67
67
  "size": 309,
68
- "path": "../public/assets/routes-Dm_3J2aV.js"
69
- },
70
- "/assets/routes-DxF_s3cD.js": {
71
- "type": "text/javascript; charset=utf-8",
72
- "etag": "\"1f4-3t0cgqrPmuajC0RY2kyeo64RxDQ\"",
73
- "mtime": "2026-08-10T01:06:27.500Z",
74
- "size": 500,
75
- "path": "../public/assets/routes-DxF_s3cD.js"
68
+ "path": "../public/assets/routes-BIOJZsig.js"
76
69
  },
77
- "/assets/preload-helper-sAZOZb3G.js": {
70
+ "/assets/routes-K8D5uBiV.js": {
78
71
  "type": "text/javascript; charset=utf-8",
79
- "etag": "\"18d18-g49yLMFDSKWfjoY0LWsdw76xYUU\"",
80
- "mtime": "2026-08-10T01:06:27.499Z",
81
- "size": 101656,
82
- "path": "../public/assets/preload-helper-sAZOZb3G.js"
72
+ "etag": "\"b7-hAMu5A8ozNBh8/2rgmiGEhnAvIs\"",
73
+ "mtime": "2026-10-22T07:10:25.845Z",
74
+ "size": 183,
75
+ "path": "../public/assets/routes-K8D5uBiV.js"
83
76
  },
84
77
  "/fonts/GeistPixel-Square.woff2": {
85
78
  "type": "font/woff2",
86
79
  "etag": "\"6f7c-IQXyklzDeInO8O/YtOs5/0tckOE\"",
87
- "mtime": "2026-08-10T01:06:28.350Z",
80
+ "mtime": "2026-10-22T07:10:26.305Z",
88
81
  "size": 28540,
89
82
  "path": "../public/fonts/GeistPixel-Square.woff2"
90
83
  }
@@ -18,17 +18,14 @@ CREATE TABLE "blobs" (
18
18
  --> statement-breakpoint
19
19
  CREATE TABLE "connect_keys" (
20
20
  "machine_id" text PRIMARY KEY NOT NULL,
21
- "user_id" text NOT NULL,
22
- "team_id" text NOT NULL,
23
21
  "minted_at" text NOT NULL
24
22
  );
25
23
  --> statement-breakpoint
26
24
  CREATE TABLE "loops" (
27
25
  "id" text PRIMARY KEY NOT NULL,
28
- "user_id" text NOT NULL,
29
- "team_id" text NOT NULL,
30
26
  "machine_id" text NOT NULL,
31
27
  "name" text NOT NULL,
28
+ "tags" text[] DEFAULT ARRAY[]::text[] NOT NULL,
32
29
  "prompt" text NOT NULL,
33
30
  "status_keep" text NOT NULL,
34
31
  "status_no_change" text NOT NULL,
@@ -51,15 +48,15 @@ CREATE TABLE "loops" (
51
48
  "last_run_index" integer DEFAULT 0 NOT NULL,
52
49
  "created_at" text NOT NULL,
53
50
  "updated_at" text NOT NULL,
54
- CONSTRAINT "loops_agent_check" CHECK ("loops"."agent" IN ('claude-code', 'codex')),
51
+ CONSTRAINT "loops_agent_check" CHECK ("loops"."agent" IN ('claude-code', 'codex', 'pi')),
52
+ CONSTRAINT "loops_tags_count_check" CHECK (cardinality("loops"."tags") <= 4),
53
+ CONSTRAINT "loops_tags_reserved_check" CHECK (NOT ("loops"."tags" && ARRAY['all loops', 'active', 'paused', 'blocked']::text[])),
55
54
  CONSTRAINT "loops_schedule_mode_check" CHECK ("loops"."schedule_mode" IN ('cron', 'continuous')),
56
55
  CONSTRAINT "loops_cron_overlap_check" CHECK ("loops"."cron_overlap" IN ('skip', 'queue-one'))
57
56
  );
58
57
  --> statement-breakpoint
59
58
  CREATE TABLE "machines" (
60
59
  "id" text PRIMARY KEY NOT NULL,
61
- "user_id" text NOT NULL,
62
- "team_id" text NOT NULL,
63
60
  "name" text NOT NULL,
64
61
  "hostname" text,
65
62
  "platform" text,
@@ -125,40 +122,12 @@ CREATE TABLE "runs" (
125
122
  "cancel_requested_at" timestamp with time zone,
126
123
  "heartbeat_at" text,
127
124
  "report_incident" jsonb,
128
- CONSTRAINT "runs_agent_check" CHECK ("runs"."agent" IS NULL OR "runs"."agent" IN ('claude-code', 'codex')),
125
+ CONSTRAINT "runs_agent_check" CHECK ("runs"."agent" IS NULL OR "runs"."agent" IN ('claude-code', 'codex', 'pi')),
129
126
  CONSTRAINT "runs_phase_check" CHECK ("runs"."phase" IN ('pending', 'running', 'done', 'error', 'canceled')),
130
127
  CONSTRAINT "runs_requested_by_check" CHECK ("runs"."requested_by" IN ('owner', 'system')),
131
128
  CONSTRAINT "runs_status_check" CHECK ("runs"."status" IS NULL OR "runs"."status" IN ('keep', 'no-change', 'block'))
132
129
  );
133
130
  --> statement-breakpoint
134
- CREATE TABLE "team_invites" (
135
- "token" text PRIMARY KEY NOT NULL,
136
- "team_id" text NOT NULL,
137
- "role" text DEFAULT 'member' NOT NULL,
138
- "invited_by_user_id" text NOT NULL,
139
- "expires_at" text NOT NULL,
140
- "redeemed_at" text,
141
- "redeemed_by_user_id" text,
142
- "created_at" text NOT NULL,
143
- CONSTRAINT "team_invites_role_check" CHECK ("team_invites"."role" IN ('owner', 'member'))
144
- );
145
- --> statement-breakpoint
146
- CREATE TABLE "team_members" (
147
- "id" text PRIMARY KEY NOT NULL,
148
- "team_id" text NOT NULL,
149
- "user_id" text NOT NULL,
150
- "role" text DEFAULT 'member' NOT NULL,
151
- "created_at" text NOT NULL,
152
- CONSTRAINT "team_members_role_check" CHECK ("team_members"."role" IN ('owner', 'member'))
153
- );
154
- --> statement-breakpoint
155
- CREATE TABLE "teams" (
156
- "id" text PRIMARY KEY NOT NULL,
157
- "name" text NOT NULL,
158
- "owner_user_id" text,
159
- "created_at" text NOT NULL
160
- );
161
- --> statement-breakpoint
162
131
  CREATE TABLE "terminal_report_incidents" (
163
132
  "id" text PRIMARY KEY NOT NULL,
164
133
  "run_id" text NOT NULL,
@@ -170,65 +139,11 @@ CREATE TABLE "terminal_report_incidents" (
170
139
  CONSTRAINT "terminal_report_incidents_disposition_check" CHECK ("terminal_report_incidents"."disposition" IN ('run-error', 'telemetry-rejected'))
171
140
  );
172
141
  --> statement-breakpoint
173
- CREATE TABLE "account" (
174
- "id" text PRIMARY KEY NOT NULL,
175
- "account_id" text NOT NULL,
176
- "provider_id" text NOT NULL,
177
- "user_id" text NOT NULL,
178
- "access_token" text,
179
- "refresh_token" text,
180
- "id_token" text,
181
- "access_token_expires_at" timestamp,
182
- "refresh_token_expires_at" timestamp,
183
- "scope" text,
184
- "password" text,
185
- "created_at" timestamp DEFAULT now() NOT NULL,
186
- "updated_at" timestamp NOT NULL
187
- );
188
- --> statement-breakpoint
189
- CREATE TABLE "session" (
190
- "id" text PRIMARY KEY NOT NULL,
191
- "expires_at" timestamp NOT NULL,
192
- "token" text NOT NULL,
193
- "created_at" timestamp DEFAULT now() NOT NULL,
194
- "updated_at" timestamp NOT NULL,
195
- "ip_address" text,
196
- "user_agent" text,
197
- "user_id" text NOT NULL,
198
- CONSTRAINT "session_token_unique" UNIQUE("token")
199
- );
200
- --> statement-breakpoint
201
- CREATE TABLE "user" (
202
- "id" text PRIMARY KEY NOT NULL,
203
- "name" text NOT NULL,
204
- "email" text NOT NULL,
205
- "email_verified" boolean DEFAULT false NOT NULL,
206
- "image" text,
207
- "created_at" timestamp DEFAULT now() NOT NULL,
208
- "updated_at" timestamp DEFAULT now() NOT NULL,
209
- CONSTRAINT "user_email_unique" UNIQUE("email")
210
- );
211
- --> statement-breakpoint
212
- CREATE TABLE "verification" (
213
- "id" text PRIMARY KEY NOT NULL,
214
- "identifier" text NOT NULL,
215
- "value" text NOT NULL,
216
- "expires_at" timestamp NOT NULL,
217
- "created_at" timestamp DEFAULT now() NOT NULL,
218
- "updated_at" timestamp DEFAULT now() NOT NULL
219
- );
220
- --> statement-breakpoint
221
- ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
222
- ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
223
142
  CREATE INDEX "artifact_files_loop_idx" ON "artifact_files" USING btree ("loop_id");--> statement-breakpoint
224
143
  CREATE UNIQUE INDEX "artifact_files_loop_path_idx" ON "artifact_files" USING btree ("loop_id","path");--> statement-breakpoint
225
144
  CREATE INDEX "artifact_files_hash_idx" ON "artifact_files" USING btree ("hash");--> statement-breakpoint
226
- CREATE INDEX "loops_user_idx" ON "loops" USING btree ("user_id");--> statement-breakpoint
227
- CREATE INDEX "loops_team_idx" ON "loops" USING btree ("team_id");--> statement-breakpoint
228
145
  CREATE INDEX "loops_machine_idx" ON "loops" USING btree ("machine_id");--> statement-breakpoint
229
146
  CREATE INDEX "delete_requested_loops" ON "loops" USING btree ("delete_requested_at") WHERE "loops"."delete_requested_at" IS NOT NULL;--> statement-breakpoint
230
- CREATE INDEX "machines_user_idx" ON "machines" USING btree ("user_id");--> statement-breakpoint
231
- CREATE INDEX "machines_team_idx" ON "machines" USING btree ("team_id");--> statement-breakpoint
232
147
  CREATE INDEX "run_leases_run_idx" ON "run_leases" USING btree ("run_id");--> statement-breakpoint
233
148
  CREATE INDEX "run_leases_loop_idx" ON "run_leases" USING btree ("loop_id");--> statement-breakpoint
234
149
  CREATE INDEX "report_receipts_created" ON "run_report_receipts" USING btree ("created_at");--> statement-breakpoint
@@ -241,11 +156,5 @@ CREATE UNIQUE INDEX "runs_loop_run_index_idx" ON "runs" USING btree ("loop_id","
241
156
  CREATE INDEX "runs_loop_terminal_history_idx" ON "runs" USING btree ("loop_id","run_index") WHERE "runs"."run_index" IS NOT NULL AND "runs"."phase" IN ('done', 'error', 'canceled');--> statement-breakpoint
242
157
  CREATE UNIQUE INDEX "runs_loop_pending_idx" ON "runs" USING btree ("loop_id") WHERE "runs"."phase" = 'pending';--> statement-breakpoint
243
158
  CREATE UNIQUE INDEX "one_running_run_per_loop" ON "runs" USING btree ("loop_id") WHERE "runs"."phase" = 'running';--> statement-breakpoint
244
- CREATE INDEX "team_invites_team_idx" ON "team_invites" USING btree ("team_id");--> statement-breakpoint
245
- CREATE INDEX "team_members_team_idx" ON "team_members" USING btree ("team_id");--> statement-breakpoint
246
- CREATE INDEX "team_members_user_idx" ON "team_members" USING btree ("user_id");--> statement-breakpoint
247
159
  CREATE INDEX "terminal_report_incidents_report_id" ON "terminal_report_incidents" USING btree ("report_id");--> statement-breakpoint
248
- CREATE INDEX "terminal_report_incidents_created" ON "terminal_report_incidents" USING btree ("created_at");--> statement-breakpoint
249
- CREATE INDEX "account_userId_idx" ON "account" USING btree ("user_id");--> statement-breakpoint
250
- CREATE INDEX "session_userId_idx" ON "session" USING btree ("user_id");--> statement-breakpoint
251
- CREATE INDEX "verification_identifier_idx" ON "verification" USING btree ("identifier");
160
+ CREATE INDEX "terminal_report_incidents_created" ON "terminal_report_incidents" USING btree ("created_at");
@@ -5,30 +5,9 @@
5
5
  {
6
6
  "idx": 0,
7
7
  "version": "7",
8
- "when": 1785146849042,
8
+ "when": 1792651729223,
9
9
  "tag": "0000_baseline",
10
10
  "breakpoints": true
11
- },
12
- {
13
- "idx": 1,
14
- "version": "7",
15
- "when": 1785146849043,
16
- "tag": "0001_add_pi_agent",
17
- "breakpoints": true
18
- },
19
- {
20
- "idx": 2,
21
- "version": "7",
22
- "when": 1785146849044,
23
- "tag": "0002_remove_teams",
24
- "breakpoints": true
25
- },
26
- {
27
- "idx": 3,
28
- "version": "7",
29
- "when": 1786301181156,
30
- "tag": "0003_add_loop_tags",
31
- "breakpoints": true
32
11
  }
33
12
  ]
34
- }
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kky42/pievo-server",
3
- "version": "2.4.14",
3
+ "version": "3.0.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,7 +8,7 @@
8
8
  "directory": "packages/server"
9
9
  },
10
10
  "type": "module",
11
- "description": "Pievo server — a self-hostable zero-exec control plane for scheduled agent loops.",
11
+ "description": "Pievo server — the single-user dashboard and scheduler for Pievo loops. Usually run through `pievo server`.",
12
12
  "bin": {
13
13
  "pievo-server": "scripts/pievo-server.mjs"
14
14
  },
@@ -17,7 +17,7 @@
17
17
  "drizzle",
18
18
  "scripts/pievo-server.mjs",
19
19
  "scripts/server-cli-lib.mjs",
20
- "scripts/prestart.mjs",
20
+ "scripts/server-network.mjs",
21
21
  "LICENSE"
22
22
  ],
23
23
  "publishConfig": {
@@ -30,28 +30,24 @@
30
30
  "dev": "vite dev",
31
31
  "build": "vite build && node scripts/copy-pglite-assets.mjs",
32
32
  "build:publish": "vite build && node scripts/copy-pglite-assets.mjs --strict",
33
- "start": "node scripts/prestart.mjs && node .output/server/index.mjs",
33
+ "start": "node scripts/pievo-server.mjs start --foreground",
34
34
  "routes:generate": "tsr generate",
35
35
  "typecheck": "tsr generate && tsc --noEmit",
36
36
  "test": "node --test ../../scripts/dev-profile.test.mjs && vitest run",
37
37
  "db:generate": "drizzle-kit generate",
38
- "db:migrate": "drizzle-kit migrate",
39
38
  "verify:package": "node scripts/verify-package.mjs",
40
39
  "prepublishOnly": "pnpm build:publish"
41
40
  },
42
41
  "dependencies": {
43
- "@aws-sdk/client-s3": "^3.1075.0",
44
42
  "@base-ui/react": "^1.6.0",
45
43
  "@electric-sql/pglite": "^0.5.4",
46
44
  "@tanstack/react-router": "^1.170.16",
47
45
  "@tanstack/react-start": "^1.168.26",
48
- "better-auth": "^1.6.19",
49
46
  "croner": "^10.0.1",
50
47
  "diff": "^9.0.0",
51
48
  "dompurify": "^3.4.11",
52
49
  "drizzle-orm": "^0.45.2",
53
50
  "marked": "^18.0.5",
54
- "postgres": "^3.4.9",
55
51
  "pino": "^10.3.1",
56
52
  "pino-pretty": "^13.1.3",
57
53
  "react": "^19.2.7",
@@ -24,6 +24,7 @@ import {
24
24
  withLaunchNonce,
25
25
  writePidRecord,
26
26
  } from "./server-cli-lib.mjs";
27
+ import { currentHttpsUrl, disableHttps, enableHttps, reachableUrls, tailscaleInfo } from "./server-network.mjs";
27
28
 
28
29
  const scriptFile = fileURLToPath(import.meta.url);
29
30
  const packageRoot = path.resolve(path.dirname(scriptFile), "..");
@@ -37,7 +38,6 @@ const LOCK_HANDOFF_TIMEOUT_MS = 5_000;
37
38
  function installShutdown(plan, expected) {
38
39
  let stopping = false;
39
40
  let stopSignal;
40
- let prestartChild;
41
41
  let nitroLoaded = false;
42
42
  let replayedForNitro = false;
43
43
 
@@ -55,9 +55,6 @@ function installShutdown(plan, expected) {
55
55
  stopSignal = signal;
56
56
  console.log(`[pievo-server] received ${signal}; shutting down`);
57
57
  shutdownApplication();
58
- if (prestartChild?.exitCode === null && prestartChild?.signalCode === null) {
59
- try { prestartChild.kill(signal); } catch {}
60
- }
61
58
  }
62
59
  };
63
60
 
@@ -69,8 +66,6 @@ function installShutdown(plan, expected) {
69
66
 
70
67
  return {
71
68
  get stopping() { return stopping; },
72
- trackPrestart(child) { prestartChild = child; },
73
- clearPrestart(child) { if (prestartChild === child) prestartChild = undefined; },
74
69
  nitroLoaded() {
75
70
  nitroLoaded = true;
76
71
  // If the first signal arrived while Nitro was importing, its graceful HTTP
@@ -94,25 +89,32 @@ function installShutdown(plan, expected) {
94
89
  };
95
90
  }
96
91
 
97
- async function runPrestart(plan, shutdown) {
98
- const child = spawn(process.execPath, [path.join(packageRoot, "scripts", "prestart.mjs")], {
99
- cwd: packageRoot,
100
- env: plan.env,
101
- stdio: "inherit",
102
- });
103
- shutdown.trackPrestart(child);
104
- try {
105
- const result = await new Promise((resolve, reject) => {
106
- child.once("error", reject);
107
- child.once("exit", (code, signal) => resolve({ code, signal }));
108
- });
109
- if (shutdown.stopping) throw new Error("startup interrupted by shutdown signal");
110
- if (result.code !== 0) {
111
- throw new Error(`migration prestart failed (${result.signal ? `signal ${result.signal}` : `exit ${result.code ?? "unknown"}`})`);
112
- }
113
- } finally {
114
- shutdown.clearPrestart(child);
92
+ /** Publish Tailscale HTTPS (when enabled) and pass the best connect URL to the server. */
93
+ function publishNetwork(plan) {
94
+ const tailscale = tailscaleInfo();
95
+ let https;
96
+ let httpsNote;
97
+ if (plan.https && tailscale) {
98
+ const result = enableHttps(tailscale, plan.port);
99
+ if (result.ok) https = result.url;
100
+ else httpsNote = result.reason;
115
101
  }
102
+ const urls = reachableUrls({ host: plan.host, port: plan.port, https, tailscale });
103
+ return { urls, httpsNote, plan: { ...plan, env: { ...plan.env, PIEVO_PUBLIC_URL: urls.connect } } };
104
+ }
105
+
106
+ function retractHttps(record) {
107
+ if (record?.https === false) return;
108
+ const tailscale = tailscaleInfo();
109
+ if (tailscale) disableHttps(tailscale, record.port);
110
+ }
111
+
112
+ function printUrls(urls, httpsNote) {
113
+ console.log(` local ${urls.local}`);
114
+ if (urls.lan.length) console.log(` lan ${urls.lan.join(" ")}`);
115
+ if (urls.tailscale.length) console.log(` tailscale ${urls.tailscale.join(" ")}`);
116
+ if (urls.https) console.log(` https ${urls.https}`);
117
+ if (httpsNote) console.log(` https unavailable: ${httpsNote}`);
116
118
  }
117
119
 
118
120
  async function waitForPidAuthority(plan, expected, shutdown) {
@@ -127,7 +129,7 @@ async function waitForPidAuthority(plan, expected, shutdown) {
127
129
 
128
130
  async function serve(plan, expected) {
129
131
  // Signal handling comes first: startup remains controllable while waiting for
130
- // the parent record and while the async migration child is running.
132
+ // the parent record.
131
133
  const shutdown = installShutdown(plan, expected);
132
134
  if (!(await waitForPidAuthority(plan, expected, shutdown))) {
133
135
  throw new Error("launcher did not establish pid authority before startup");
@@ -139,15 +141,6 @@ async function serve(plan, expected) {
139
141
  throw new Error("pid authority changed before startup");
140
142
  }
141
143
 
142
- await runPrestart(plan, shutdown);
143
- if (shutdown.stopping) return;
144
- const afterPrestart = readPidRecord(plan.pidFile);
145
- if (afterPrestart?.pid !== expected.pid
146
- || afterPrestart.startTime !== expected.startTime
147
- || afterPrestart.launchNonce !== expected.launchNonce) {
148
- throw new Error("pid authority changed during migration prestart");
149
- }
150
-
151
144
  try {
152
145
  await import(pathToFileURL(path.join(packageRoot, ".output", "server", "index.mjs")).href);
153
146
  shutdown.nitroLoaded();
@@ -160,7 +153,7 @@ async function serve(plan, expected) {
160
153
  if (shutdown.stopping) return;
161
154
  if (!ready) throw new Error(`server did not become ready at ${plan.readyUrl}`);
162
155
  updatePidRecordState(plan, expected, "running");
163
- console.log(`[pievo-server] ready at http://${plan.host}:${plan.port} (pid ${process.pid})`);
156
+ console.log(`[pievo-server] ready on ${plan.host}:${plan.port} (pid ${process.pid})`);
164
157
  } catch (error) {
165
158
  // Once Nitro may own a listening socket, ask its srvx signal handler to drain
166
159
  // HTTP rather than forcing process.exit from our application handler.
@@ -196,6 +189,7 @@ async function waitForDetachedReady(plan, expected) {
196
189
  }
197
190
 
198
191
  async function cleanFailedLaunch(plan, expected) {
192
+ retractHttps(expected);
199
193
  const state = recordedProcessState(expected);
200
194
  if (state.state === "gone") {
201
195
  clearPidRecord(plan.pidFile, expected);
@@ -212,7 +206,7 @@ async function cleanFailedLaunch(plan, expected) {
212
206
  async function start(basePlan, foreground) {
213
207
  const existing = pidStatus(basePlan.pidFile);
214
208
  if (existing.state === "running") {
215
- console.log(`pievo-server is already ${existing.record.state === "starting" ? "starting" : "running"} (pid ${existing.record.pid}, http://${existing.record.host}:${existing.record.port})`);
209
+ console.log(`pievo server is already ${existing.record.state === "starting" ? "starting" : "running"} (pid ${existing.record.pid}); run \`pievo server status\` for its URLs`);
216
210
  return;
217
211
  }
218
212
  if (existing.state === "unsafe") throw new Error(`${existing.error}; refusing to start over the existing pid record`);
@@ -221,13 +215,15 @@ async function start(basePlan, foreground) {
221
215
  try {
222
216
  const raced = pidStatus(basePlan.pidFile);
223
217
  if (raced.state === "running") {
224
- console.log(`pievo-server is already ${raced.record.state === "starting" ? "starting" : "running"} (pid ${raced.record.pid})`);
218
+ console.log(`pievo server is already ${raced.record.state === "starting" ? "starting" : "running"} (pid ${raced.record.pid})`);
225
219
  return;
226
220
  }
227
221
  if (raced.state === "unsafe") throw new Error(`${raced.error}; refusing to start over the existing pid record`);
228
222
 
229
- const plan = withLaunchNonce(basePlan);
223
+ const published = publishNetwork(basePlan);
224
+ const plan = withLaunchNonce(published.plan);
230
225
  if (foreground) {
226
+ printUrls(published.urls, published.httpsNote);
231
227
  applyProcessEnv(plan.env);
232
228
  const record = writePidRecord(plan, {
233
229
  launchNonce: plan.launchNonce,
@@ -274,8 +270,9 @@ async function start(basePlan, foreground) {
274
270
  }
275
271
  throw error;
276
272
  }
277
- console.log(`pievo-server started (pid ${child.pid}, http://${plan.host}:${plan.port})`);
278
- console.log(`log: ${plan.logFile}`);
273
+ console.log(`pievo server started (pid ${child.pid})`);
274
+ printUrls(published.urls, published.httpsNote);
275
+ console.log(` log ${plan.logFile}`);
279
276
  } finally {
280
277
  release();
281
278
  }
@@ -319,8 +316,10 @@ async function stop(plan) {
319
316
  clearPidRecord(plan.pidFile, stoppedRecord);
320
317
  }
321
318
 
322
- if (stoppedRecord) console.log(`pievo-server stopped (pid ${stoppedRecord.pid})`);
323
- else console.log("pievo-server is not running");
319
+ if (stoppedRecord) {
320
+ retractHttps(stoppedRecord);
321
+ console.log(`pievo server stopped (pid ${stoppedRecord.pid})`);
322
+ } else console.log("pievo server is not running");
324
323
  } finally {
325
324
  release?.();
326
325
  }
@@ -329,17 +328,20 @@ async function stop(plan) {
329
328
  function status(plan) {
330
329
  const current = pidStatus(plan.pidFile);
331
330
  if (current.state === "running") {
332
- console.log(`pievo-server is ${current.record.state === "starting" ? "starting" : "running"} (pid ${current.record.pid})`);
333
- console.log(`url: http://${current.record.host}:${current.record.port}`);
334
- console.log(`data: ${plan.dataDir}`);
331
+ const { host, port } = current.record;
332
+ const tailscale = tailscaleInfo();
333
+ const https = tailscale ? currentHttpsUrl(tailscale, port) : undefined;
334
+ console.log(`pievo server is ${current.record.state === "starting" ? "starting" : "running"} (pid ${current.record.pid})`);
335
+ printUrls(reachableUrls({ host, port, https, tailscale }));
336
+ console.log(` data ${plan.dataDir}`);
335
337
  return 0;
336
338
  }
337
339
  if (current.state === "unsafe") {
338
340
  const pid = current.record?.pid ? ` (pid ${current.record.pid})` : "";
339
- console.error(`pievo-server status is unsafe: ${current.error}${pid}`);
341
+ console.error(`pievo server status is unsafe: ${current.error}${pid}`);
340
342
  return 1;
341
343
  }
342
- console.log(`pievo-server is stopped${current.stale ? " (cleared stale pid file)" : ""}`);
344
+ console.log(`pievo server is stopped${current.stale ? " (cleared stale pid file)" : ""}`);
343
345
  return 1;
344
346
  }
345
347