codebay 0.13.0 → 0.15.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 (85) hide show
  1. package/.mochi/manifest.json +522 -443
  2. package/.mochi/svelte-client/HydratableIsland-smgsf0ma.js +1 -0
  3. package/.mochi/svelte-client/_hydrate-AppShell_2rtnxn6pgp2rh-9vc087ep.js +2 -0
  4. package/.mochi/svelte-client/_hydrate-AvatarsView_257s9yq1wwr4f-a48xq47a.js +14 -0
  5. package/.mochi/svelte-client/_hydrate-InstanceView_2ma45l9bybfhl-d4zehrqz.js +3 -0
  6. package/.mochi/svelte-client/_hydrate-SettingsView_8hmarwmf8onq-t5175pf5.js +44 -0
  7. package/.mochi/svelte-client/chunk-0mstgbtr.js +2 -0
  8. package/.mochi/svelte-client/chunk-0q9g0kpg.js +1 -0
  9. package/.mochi/svelte-client/chunk-3fwjzw1r.js +1 -0
  10. package/.mochi/svelte-client/{chunk-spk1b2r4.js → chunk-5pg0be5f.js} +1 -1
  11. package/.mochi/svelte-client/{chunk-ccfh8hxz.js → chunk-a2hty99b.js} +1 -1
  12. package/.mochi/svelte-client/{chunk-0mc09cyb.js → chunk-ds9yn9cq.js} +1 -1
  13. package/.mochi/svelte-client/{chunk-phf7v5jj.js → chunk-fn03gxer.js} +1 -1
  14. package/.mochi/svelte-client/chunk-jhgq7f65.js +2 -0
  15. package/.mochi/svelte-client/chunk-p5a07kx1.js +1 -0
  16. package/.mochi/svelte-client/chunk-p5wpyhsf.js +2 -0
  17. package/.mochi/svelte-client/chunk-t2kfvtb6.js +2 -0
  18. package/.mochi/svelte-client/{chunk-x0m3k0rn.js → chunk-v3wg9mdy.js} +1 -1
  19. package/.mochi/svelte-compile/{App-94xsdn0w.server.js → App-68f9a9fq.server.js} +64 -59
  20. package/.mochi/svelte-compile/{Avatars-fnccw47h.server.js → Avatars-vyh3rwxx.server.js} +14 -29
  21. package/.mochi/svelte-compile/Instance-yfw7s5mp.server.js +627 -0
  22. package/.mochi/svelte-compile/{Settings-h7gsjyz3.server.js → Settings-0b5t9kw9.server.js} +348 -151
  23. package/.mochi/svelte-compile/{chunk-w0hca7va.js → chunk-0y3wrae9.js} +13 -1
  24. package/.mochi/svelte-compile/{chunk-ed46m58e.js → chunk-2qzc07gt.js} +13 -1
  25. package/.mochi/svelte-compile/chunk-ef3hvegw.js +21 -0
  26. package/.mochi/svelte-compile/chunk-f9td8ej2.js +24 -0
  27. package/.mochi/svelte-compile/{chunk-pqb403fh.js → chunk-g0eravvj.js} +5 -16
  28. package/.mochi/svelte-css/AgentLogBox-38adby5iygny7.css +1 -0
  29. package/.mochi/svelte-css/{InstanceCard-25z7nas7y98zk.css → InstanceCard-3vxozrp9uoads.css} +1 -1
  30. package/.mochi/svelte-css/{SettingsView-bccw34agd2bj.css → SettingsView-2400myxb9ot56.css} +1 -1
  31. package/README.md +32 -1
  32. package/migrations/0009_agent_runs.sql +24 -0
  33. package/migrations/0010_agent_run_model.sql +2 -0
  34. package/package.json +6 -2
  35. package/public/favicon.svg +9 -0
  36. package/src/components/AgentLogBox.svelte +458 -0
  37. package/src/components/AppShell.svelte +11 -0
  38. package/src/components/FolderBrowser.svelte +13 -5
  39. package/src/components/InstanceCard.svelte +38 -0
  40. package/src/components/InstanceView.svelte +8 -0
  41. package/src/components/SettingsView.svelte +260 -0
  42. package/src/components/UiShowcase.svelte +4 -2
  43. package/src/container-injections/claude-code-credentials.ts +2 -3
  44. package/src/container-injections/claude-code-skills.ts +125 -0
  45. package/src/container-injections/claude-output-style.ts +2 -3
  46. package/src/container-injections/claude-statusline.ts +9 -17
  47. package/src/container-injections/github-credentials.ts +12 -1
  48. package/src/index.ts +32 -7
  49. package/src/lib/agent-run-stream.ts +246 -0
  50. package/src/lib/agent-runs.server.ts +724 -0
  51. package/src/lib/auth.server.ts +11 -2
  52. package/src/lib/build-freshness.server.ts +71 -0
  53. package/src/lib/config.server.ts +29 -6
  54. package/src/lib/container-files.server.ts +23 -1
  55. package/src/lib/data-dir-lock.server.ts +78 -0
  56. package/src/lib/db.server.ts +120 -1
  57. package/src/lib/devcontainer.server.ts +60 -14
  58. package/src/lib/docker-client.server.ts +11 -5
  59. package/src/lib/drives.ts +11 -0
  60. package/src/lib/exec.server.ts +66 -5
  61. package/src/lib/host-claude.server.ts +31 -0
  62. package/src/lib/injections.server.ts +2 -0
  63. package/src/lib/instances.server.ts +45 -3
  64. package/src/lib/log-capture.server.ts +17 -5
  65. package/src/lib/mcp-auth.server.ts +52 -0
  66. package/src/lib/picker.server.ts +23 -2
  67. package/src/lib/sandbox-ops.server.ts +263 -0
  68. package/src/mcp/routes.server.ts +25 -0
  69. package/src/mcp/server.server.ts +52 -0
  70. package/src/mcp/tools.server.ts +494 -0
  71. package/src/pages/Settings.svelte +15 -0
  72. package/src/routes.ts +72 -1
  73. package/src/shell.html +1 -0
  74. package/src/types.ts +15 -0
  75. package/.mochi/svelte-client/HydratableIsland-zrdsrsmg.js +0 -1
  76. package/.mochi/svelte-client/_hydrate-AppShell_2rtnxn6pgp2rh-v7y7dh53.js +0 -2
  77. package/.mochi/svelte-client/_hydrate-AvatarsView_257s9yq1wwr4f-tmwd6fpb.js +0 -14
  78. package/.mochi/svelte-client/_hydrate-InstanceView_2ma45l9bybfhl-m7t64dbh.js +0 -1
  79. package/.mochi/svelte-client/_hydrate-SettingsView_8hmarwmf8onq-wedc9x9y.js +0 -39
  80. package/.mochi/svelte-client/chunk-5jwfs4p9.js +0 -2
  81. package/.mochi/svelte-client/chunk-6qg4q98a.js +0 -2
  82. package/.mochi/svelte-client/chunk-tmeh70wg.js +0 -2
  83. package/.mochi/svelte-client/chunk-vs1yjbqt.js +0 -2
  84. package/.mochi/svelte-client/chunk-y7f4jbdm.js +0 -2
  85. package/.mochi/svelte-compile/Instance-knnkcn2p.server.js +0 -377
@@ -0,0 +1,627 @@
1
+ // @bun
2
+ import {
3
+ Chevron_right,
4
+ StatusBadge,
5
+ forwardedPortUrl
6
+ } from "./chunk-2qzc07gt.js";
7
+ import {
8
+ Bot
9
+ } from "./chunk-f9td8ej2.js";
10
+ import {
11
+ Message_square
12
+ } from "./chunk-ef3hvegw.js";
13
+ import {
14
+ Terminal,
15
+ apiDelete,
16
+ apiFetch,
17
+ apiPost,
18
+ ideUrl
19
+ } from "./chunk-0y3wrae9.js";
20
+ import {
21
+ HydratableBoundary,
22
+ Icon,
23
+ X,
24
+ emitIslandProps
25
+ } from "./chunk-60mpagr9.js";
26
+ import"./chunk-xpt1a7jm.js";
27
+
28
+ // src/pages/Instance.svelte
29
+ import"svelte/internal/flags/async";
30
+ import * as $11 from "svelte/internal/server";
31
+
32
+ // src/components/InstanceView.svelte
33
+ import"svelte/internal/flags/async";
34
+ import * as $10 from "svelte/internal/server";
35
+
36
+ // node_modules/@lucide/svelte/dist/icons/arrow-left.svelte
37
+ import"svelte/internal/flags/async";
38
+ import * as $ from "svelte/internal/server";
39
+ function Arrow_left($$renderer, $$props) {
40
+ let { $$slots, $$events, ...props } = $$props;
41
+ const iconNode = [
42
+ ["path", { d: "m12 19-7-7 7-7" }],
43
+ ["path", { d: "M19 12H5" }]
44
+ ];
45
+ Icon($$renderer, $.spread_props([{ name: "arrow-left" }, props, { iconNode }]));
46
+ }
47
+ // node_modules/@lucide/svelte/dist/icons/arrow-up-right.svelte
48
+ import"svelte/internal/flags/async";
49
+ import * as $2 from "svelte/internal/server";
50
+ function Arrow_up_right($$renderer, $$props) {
51
+ let { $$slots, $$events, ...props } = $$props;
52
+ const iconNode = [["path", { d: "M7 7h10v10" }], ["path", { d: "M7 17 17 7" }]];
53
+ Icon($$renderer, $2.spread_props([{ name: "arrow-up-right" }, props, { iconNode }]));
54
+ }
55
+ // src/components/HealthBox.svelte
56
+ import"svelte/internal/flags/async";
57
+ import * as $5 from "svelte/internal/server";
58
+
59
+ // node_modules/@lucide/svelte/dist/icons/check.svelte
60
+ import"svelte/internal/flags/async";
61
+ import * as $3 from "svelte/internal/server";
62
+ function Check($$renderer, $$props) {
63
+ let { $$slots, $$events, ...props } = $$props;
64
+ const iconNode = [["path", { d: "M20 6 9 17l-5-5" }]];
65
+ Icon($$renderer, $3.spread_props([{ name: "check" }, props, { iconNode }]));
66
+ }
67
+ // src/components/Skeleton.svelte
68
+ import"svelte/internal/flags/async";
69
+ import * as $4 from "svelte/internal/server";
70
+ function Skeleton($$renderer, $$props) {
71
+ let { variant = "text", width } = $$props;
72
+ $$renderer.push(`<span${$4.attr_class(`skel ${$4.stringify(variant)}`, "svelte-tl058d")}${$4.attr_style("", { width })}></span>`);
73
+ }
74
+
75
+ // src/components/HealthBox.svelte
76
+ function HealthBox($$renderer, $$props) {
77
+ $$renderer.component(($$renderer2) => {
78
+ let {
79
+ health = null,
80
+ lastFetchedAt = null,
81
+ active = true,
82
+ injectionChecks = 0,
83
+ mode = "ide"
84
+ } = $$props;
85
+ const FIXED_CHECKS = $5.derived(() => [
86
+ "Container running",
87
+ mode === "terminal" ? "Terminal reachable" : "Code-server reachable"
88
+ ]);
89
+ const checks = $5.derived(() => {
90
+ if (!health)
91
+ return [];
92
+ const v = (ok) => ({ ok, value: ok ? "OK" : "\u2014" });
93
+ return [
94
+ { label: FIXED_CHECKS()[0], ...v(health.containerRunning) },
95
+ { label: FIXED_CHECKS()[1], ...v(health.codeServerAccessible) },
96
+ ...health.injections.map((i) => ({ label: i.label, ...v(i.ok) }))
97
+ ];
98
+ });
99
+ function getNumberOfChecks() {
100
+ return health ? checks().length : FIXED_CHECKS().length + injectionChecks;
101
+ }
102
+ let now = Date.now();
103
+ const agoLabel = $5.derived(() => {
104
+ if (!active && !health)
105
+ return "Container not running";
106
+ if (!lastFetchedAt)
107
+ return "Waiting for first check\u2026";
108
+ const secs = Math.max(0, Math.round((now - lastFetchedAt) / 1000));
109
+ return `Updated ${secs}s ago`;
110
+ });
111
+ $$renderer2.push(`<div${$5.attr_class("healthwrap panel svelte-1hnopyv", undefined, { dim: !active && !health })}><div class="panel-bar">Health</div> <div class="health svelte-1hnopyv">`);
112
+ if (health) {
113
+ $$renderer2.push("<!--[0-->");
114
+ $$renderer2.push(`<!--[-->`);
115
+ const each_array = $5.ensure_array_like(checks());
116
+ for (let $$index = 0, $$length = each_array.length;$$index < $$length; $$index++) {
117
+ let check = each_array[$$index];
118
+ $$renderer2.push(`<div class="hrow svelte-1hnopyv"><span${$5.attr_class(`box ${check.ok ? "ok" : "bad"}`, "svelte-1hnopyv")}>`);
119
+ if (check.ok) {
120
+ $$renderer2.push("<!--[0-->");
121
+ Check($$renderer2, { size: 12, strokeWidth: 3 });
122
+ } else {
123
+ $$renderer2.push("<!--[-1-->");
124
+ X($$renderer2, { size: 12, strokeWidth: 3 });
125
+ }
126
+ $$renderer2.push(`<!--]--></span> <span class="hlabel svelte-1hnopyv">${$5.escape(check.label)}</span> <span class="hvalue svelte-1hnopyv">${$5.escape(check.value)}</span></div>`);
127
+ }
128
+ $$renderer2.push(`<!--]-->`);
129
+ } else if (active) {
130
+ $$renderer2.push("<!--[1-->");
131
+ $$renderer2.push(`<!--[-->`);
132
+ const each_array_1 = $5.ensure_array_like(Array(getNumberOfChecks()));
133
+ for (let i = 0, $$length = each_array_1.length;i < $$length; i++) {
134
+ let _ = each_array_1[i];
135
+ $$renderer2.push(`<div class="hrow svelte-1hnopyv"><span class="box idle svelte-1hnopyv"></span> `);
136
+ Skeleton($$renderer2, { width: "120px" });
137
+ $$renderer2.push(`<!----> `);
138
+ Skeleton($$renderer2, { variant: "pill" });
139
+ $$renderer2.push(`<!----></div>`);
140
+ }
141
+ $$renderer2.push(`<!--]-->`);
142
+ } else {
143
+ $$renderer2.push("<!--[-1-->");
144
+ $$renderer2.push(`<!--[-->`);
145
+ const each_array_2 = $5.ensure_array_like(FIXED_CHECKS());
146
+ for (let $$index_2 = 0, $$length = each_array_2.length;$$index_2 < $$length; $$index_2++) {
147
+ let label = each_array_2[$$index_2];
148
+ $$renderer2.push(`<div class="hrow svelte-1hnopyv"><span class="box idle svelte-1hnopyv"></span> <span class="hlabel svelte-1hnopyv">${$5.escape(label)}</span> <span class="hvalue svelte-1hnopyv">\u2014</span></div>`);
149
+ }
150
+ $$renderer2.push(`<!--]-->`);
151
+ }
152
+ $$renderer2.push(`<!--]--></div> <div class="hfoot svelte-1hnopyv">${$5.escape(agoLabel())}</div></div>`);
153
+ });
154
+ }
155
+
156
+ // src/components/AgentLogBox.svelte
157
+ import"svelte/internal/flags/async";
158
+ import * as $9 from "svelte/internal/server";
159
+
160
+ // node_modules/@lucide/svelte/dist/icons/refresh-cw.svelte
161
+ import"svelte/internal/flags/async";
162
+ import * as $6 from "svelte/internal/server";
163
+ function Refresh_cw($$renderer, $$props) {
164
+ let { $$slots, $$events, ...props } = $$props;
165
+ const iconNode = [
166
+ [
167
+ "path",
168
+ { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }
169
+ ],
170
+ ["path", { d: "M21 3v5h-5" }],
171
+ [
172
+ "path",
173
+ { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }
174
+ ],
175
+ ["path", { d: "M8 16H3v5" }]
176
+ ];
177
+ Icon($$renderer, $6.spread_props([{ name: "refresh-cw" }, props, { iconNode }]));
178
+ }
179
+ // node_modules/@lucide/svelte/dist/icons/circle-check.svelte
180
+ import"svelte/internal/flags/async";
181
+ import * as $7 from "svelte/internal/server";
182
+ function Circle_check($$renderer, $$props) {
183
+ let { $$slots, $$events, ...props } = $$props;
184
+ const iconNode = [
185
+ ["circle", { cx: "12", cy: "12", r: "10" }],
186
+ ["path", { d: "m9 12 2 2 4-4" }]
187
+ ];
188
+ Icon($$renderer, $7.spread_props([{ name: "circle-check" }, props, { iconNode }]));
189
+ }
190
+ // node_modules/@lucide/svelte/dist/icons/circle-x.svelte
191
+ import"svelte/internal/flags/async";
192
+ import * as $8 from "svelte/internal/server";
193
+ function Circle_x($$renderer, $$props) {
194
+ let { $$slots, $$events, ...props } = $$props;
195
+ const iconNode = [
196
+ ["circle", { cx: "12", cy: "12", r: "10" }],
197
+ ["path", { d: "m15 9-6 6" }],
198
+ ["path", { d: "m9 9 6 6" }]
199
+ ];
200
+ Icon($$renderer, $8.spread_props([{ name: "circle-x" }, props, { iconNode }]));
201
+ }
202
+ // src/components/AgentLogBox.svelte
203
+ import { untrack } from "svelte";
204
+ function AgentLogBox($$renderer, $$props) {
205
+ $$renderer.component(($$renderer2) => {
206
+ let { id, bump = 0 } = $$props;
207
+ let runs = [];
208
+ let timelines = {};
209
+ let open = [];
210
+ let newest = null;
211
+ let loaded = false;
212
+ let error = null;
213
+ const isOpen = (runId) => open.includes(runId);
214
+ async function load() {
215
+ try {
216
+ const q = open.length ? `?run_ids=${encodeURIComponent(open.join(","))}` : "";
217
+ const data = await apiFetch(`/api/instances/${id}/agent-log${q}`, undefined, "Could not load the agent log");
218
+ runs = Array.isArray(data.runs) ? data.runs : [];
219
+ timelines = { ...timelines, ...data.timelines ?? {} };
220
+ const top = data.runs[0]?.id ?? null;
221
+ if (top && top !== newest) {
222
+ newest = top;
223
+ open = [top];
224
+ }
225
+ error = null;
226
+ } catch (err) {
227
+ error = err.message;
228
+ } finally {
229
+ loaded = true;
230
+ }
231
+ }
232
+ function toggle(runId) {
233
+ const opening = !isOpen(runId);
234
+ open = opening ? [...open, runId] : open.filter((r) => r !== runId);
235
+ if (opening && !timelines[runId])
236
+ load();
237
+ }
238
+ const ICONS = {
239
+ tool: Terminal,
240
+ text: Message_square,
241
+ retry: Refresh_cw,
242
+ result: Circle_check
243
+ };
244
+ const isLive = (run) => run.status === "running" || run.status === "queued";
245
+ const newestFirst = (entries) => entries.map((entry, index) => ({ entry, index })).reverse();
246
+ const modelOf = (run) => run.model ?? run.requested_model;
247
+ function modelTitle(run) {
248
+ if (run.model && run.requested_model && run.model !== run.requested_model) {
249
+ return `Requested as ${run.requested_model}`;
250
+ }
251
+ return run.model ? undefined : "Requested; Claude has not reported the model it is using yet";
252
+ }
253
+ const sessionOf = (run) => run.session_id ?? run.resume_session_id;
254
+ const shortSession = (sid) => sid.slice(0, 8);
255
+ function sessionTitle(run) {
256
+ const sid = sessionOf(run);
257
+ if (!sid)
258
+ return "";
259
+ const lead = run.resume_session_id ? "Continues an earlier run in this session" : "New session, started by this run";
260
+ return `${lead}
261
+ Session ${sid}${run.session_id ? "" : " (requested; not started yet)"}`;
262
+ }
263
+ function when(run) {
264
+ return new Date(run.created_at).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
265
+ }
266
+ function meta(run) {
267
+ const bits = [];
268
+ if (run.num_turns != null)
269
+ bits.push(`${run.num_turns} turns`);
270
+ if (run.cost_usd != null)
271
+ bits.push(`$${run.cost_usd.toFixed(4)}`);
272
+ if (run.duration_ms != null)
273
+ bits.push(`${(run.duration_ms / 1000).toFixed(1)}s`);
274
+ return bits.join(" \xB7 ");
275
+ }
276
+ function peek(run) {
277
+ if (run.status === "queued")
278
+ return "Queued";
279
+ if (isLive(run))
280
+ return (run.last_activity ?? "Working\u2026").replace(/\s+/g, " ").trim();
281
+ return (run.error ?? run.result ?? run.prompt).replace(/\s+/g, " ").trim();
282
+ }
283
+ if (loaded && runs.length > 0) {
284
+ $$renderer2.push("<!--[0-->");
285
+ $$renderer2.push(`<section class="agentwrap panel svelte-rfwj7e"><div class="agent-bar panel-bar svelte-rfwj7e"><span class="svelte-rfwj7e">`);
286
+ Bot($$renderer2, { size: 14 });
287
+ $$renderer2.push(`<!----> Agent log</span> <span class="count svelte-rfwj7e">${$9.escape(runs.length)} run${$9.escape(runs.length === 1 ? "" : "s")}</span></div> <!--[-->`);
288
+ const each_array = $9.ensure_array_like(runs);
289
+ for (let $$index_1 = 0, $$length = each_array.length;$$index_1 < $$length; $$index_1++) {
290
+ let run = each_array[$$index_1];
291
+ const expanded = isOpen(run.id);
292
+ $$renderer2.push(`<div class="run svelte-rfwj7e"><button type="button" class="run-head svelte-rfwj7e"${$9.attr("aria-expanded", expanded)}><span${$9.attr_class("chev svelte-rfwj7e", undefined, { down: expanded })}>`);
293
+ Chevron_right($$renderer2, { size: 14 });
294
+ $$renderer2.push(`<!----></span> <span class="when svelte-rfwj7e">${$9.escape(when(run))}</span> <span${$9.attr_class("status svelte-rfwj7e", undefined, { bad: run.is_error, live: isLive(run) })}>`);
295
+ if (isLive(run)) {
296
+ $$renderer2.push("<!--[0-->");
297
+ $$renderer2.push(`<span class="pulse svelte-rfwj7e"></span>`);
298
+ } else {
299
+ $$renderer2.push("<!--[-1-->");
300
+ }
301
+ $$renderer2.push(`<!--]--> ${$9.escape(run.status)}</span> `);
302
+ if (modelOf(run)) {
303
+ $$renderer2.push("<!--[0-->");
304
+ $$renderer2.push(`<span class="model svelte-rfwj7e"${$9.attr("title", modelTitle(run))}>${$9.escape(modelOf(run))}</span>`);
305
+ } else {
306
+ $$renderer2.push("<!--[-1-->");
307
+ }
308
+ $$renderer2.push(`<!--]--> `);
309
+ if (sessionOf(run)) {
310
+ $$renderer2.push("<!--[0-->");
311
+ const sid = sessionOf(run);
312
+ $$renderer2.push(`<span${$9.attr_class("session svelte-rfwj7e", undefined, { resumed: run.resume_session_id })}${$9.attr("title", sessionTitle(run))}>${$9.escape(run.resume_session_id ? "\u2937" : "\u25C6")}
313
+ ${$9.escape(shortSession(sid))}</span>`);
314
+ } else {
315
+ $$renderer2.push("<!--[-1-->");
316
+ }
317
+ $$renderer2.push(`<!--]--> `);
318
+ if (!expanded) {
319
+ $$renderer2.push("<!--[0-->");
320
+ $$renderer2.push(`<span class="peek svelte-rfwj7e">${$9.escape(peek(run))}</span>`);
321
+ } else {
322
+ $$renderer2.push("<!--[-1-->");
323
+ }
324
+ $$renderer2.push(`<!--]--> <span class="run-meta svelte-rfwj7e">${$9.escape(meta(run))}</span></button> `);
325
+ if (expanded) {
326
+ $$renderer2.push("<!--[0-->");
327
+ $$renderer2.push(`<div class="prompt svelte-rfwj7e"><div class="ptitle svelte-rfwj7e">Initial prompt</div> <div class="ptext svelte-rfwj7e">${$9.escape(run.prompt)}</div></div> <ol class="steps svelte-rfwj7e">`);
328
+ if (isLive(run)) {
329
+ $$renderer2.push("<!--[0-->");
330
+ $$renderer2.push(`<li class="step svelte-rfwj7e"><span class="ico svelte-rfwj7e"><span class="pulse svelte-rfwj7e"></span></span> <span class="body svelte-rfwj7e"><span class="text svelte-rfwj7e">${$9.escape(run.status === "queued" ? "Queued \u2014 waiting for the sandbox" : "Working\u2026")}</span></span></li>`);
331
+ } else if ((timelines[run.id] ?? []).length === 0) {
332
+ $$renderer2.push("<!--[1-->");
333
+ $$renderer2.push(`<li class="step svelte-rfwj7e"><span class="body svelte-rfwj7e"><span class="text svelte-rfwj7e">No steps recorded.</span></span></li>`);
334
+ } else {
335
+ $$renderer2.push("<!--[-1-->");
336
+ }
337
+ $$renderer2.push(`<!--]--> <!--[-->`);
338
+ const each_array_1 = $9.ensure_array_like(newestFirst(timelines[run.id] ?? []));
339
+ for (let $$index = 0, $$length2 = each_array_1.length;$$index < $$length2; $$index++) {
340
+ let { entry, index } = each_array_1[$$index];
341
+ $$renderer2.push(`<li${$9.attr_class("step svelte-rfwj7e", undefined, { sub: entry.subagent })}><span${$9.attr_class("ico svelte-rfwj7e", undefined, { bad: entry.kind === "result" && entry.isError })}>`);
342
+ if (entry.kind === "result" && entry.isError) {
343
+ $$renderer2.push("<!--[0-->");
344
+ Circle_x($$renderer2, { size: 14 });
345
+ } else {
346
+ $$renderer2.push("<!--[-1-->");
347
+ const Icon2 = ICONS[entry.kind];
348
+ if (Icon2) {
349
+ $$renderer2.push("<!--[-->");
350
+ Icon2($$renderer2, { size: 14 });
351
+ $$renderer2.push("<!--]-->");
352
+ } else {
353
+ $$renderer2.push("<!--[!-->");
354
+ $$renderer2.push("<!--]-->");
355
+ }
356
+ }
357
+ $$renderer2.push(`<!--]--></span> <span class="body svelte-rfwj7e">`);
358
+ if (entry.name) {
359
+ $$renderer2.push("<!--[0-->");
360
+ $$renderer2.push(`<span class="tool svelte-rfwj7e">${$9.escape(entry.name)}</span>`);
361
+ } else {
362
+ $$renderer2.push("<!--[-1-->");
363
+ }
364
+ $$renderer2.push(`<!--]--> <span class="text svelte-rfwj7e">${$9.escape(entry.text)}</span></span></li>`);
365
+ }
366
+ $$renderer2.push(`<!--]--></ol> `);
367
+ if (run.error && !isLive(run)) {
368
+ $$renderer2.push("<!--[0-->");
369
+ $$renderer2.push(`<div class="err svelte-rfwj7e">${$9.escape(run.error)}</div>`);
370
+ } else {
371
+ $$renderer2.push("<!--[-1-->");
372
+ }
373
+ $$renderer2.push(`<!--]-->`);
374
+ } else {
375
+ $$renderer2.push("<!--[-1-->");
376
+ }
377
+ $$renderer2.push(`<!--]--></div>`);
378
+ }
379
+ $$renderer2.push(`<!--]--> `);
380
+ if (error) {
381
+ $$renderer2.push("<!--[0-->");
382
+ $$renderer2.push(`<div class="err svelte-rfwj7e">${$9.escape(error)}</div>`);
383
+ } else {
384
+ $$renderer2.push("<!--[-1-->");
385
+ }
386
+ $$renderer2.push(`<!--]--></section>`);
387
+ } else {
388
+ $$renderer2.push("<!--[-1-->");
389
+ }
390
+ $$renderer2.push(`<!--]-->`);
391
+ });
392
+ }
393
+
394
+ // src/components/InstanceView.svelte
395
+ import { tick } from "svelte";
396
+ function InstanceView($$renderer, $$props) {
397
+ $$renderer.component(($$renderer2) => {
398
+ let { id, injectionChecks = 0 } = $$props;
399
+ let instance = null;
400
+ let health = null;
401
+ let lastFetchedAt = null;
402
+ let logs = "";
403
+ let runBump = 0;
404
+ let logEl = null;
405
+ let following = true;
406
+ async function scrollToBottom() {
407
+ await tick();
408
+ logEl?.scrollTo(0, logEl.scrollHeight);
409
+ }
410
+ function toggleFollow() {
411
+ following = !following;
412
+ if (following)
413
+ scrollToBottom();
414
+ }
415
+ const url = $10.derived(() => instance ? ideUrl(instance) : "#");
416
+ let newPort = "";
417
+ let portError = null;
418
+ let pendingRebuild = false;
419
+ const forwards = $10.derived(() => instance?.forwarded_ports ?? []);
420
+ const building = $10.derived(() => instance?.status === "creating");
421
+ async function portAction(run) {
422
+ portError = null;
423
+ try {
424
+ await run();
425
+ return true;
426
+ } catch (err) {
427
+ portError = err.message;
428
+ return false;
429
+ }
430
+ }
431
+ async function addPort(e) {
432
+ e.preventDefault();
433
+ const port = Number.parseInt(newPort, 10);
434
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
435
+ portError = "Enter a port number between 1 and 65535";
436
+ return;
437
+ }
438
+ const ok = await portAction(() => apiPost(`/api/instances/${id}/ports`, { port }));
439
+ if (ok) {
440
+ newPort = "";
441
+ pendingRebuild = true;
442
+ }
443
+ }
444
+ async function removePort(port) {
445
+ const ok = await portAction(() => apiDelete(`/api/instances/${id}/ports/${port}`));
446
+ if (ok)
447
+ pendingRebuild = true;
448
+ }
449
+ async function restart() {
450
+ const ok = await portAction(() => apiPost(`/api/instances/${id}/rebuild`));
451
+ if (ok)
452
+ pendingRebuild = false;
453
+ }
454
+ let restartError = null;
455
+ let restarting = false;
456
+ const restartOpts = {
457
+ onPending: (v) => restarting = v,
458
+ submit: () => {
459
+ restartError = null;
460
+ return ({ result }) => {
461
+ if (result.type === "failure") {
462
+ restartError = result.data?.error ?? "Restart failed";
463
+ } else if (result.type === "error") {
464
+ restartError = "Network error. Try again.";
465
+ }
466
+ };
467
+ }
468
+ };
469
+ let copied = false;
470
+ let copyTimer;
471
+ async function copyLogs() {
472
+ await navigator.clipboard.writeText(logs);
473
+ copied = true;
474
+ clearTimeout(copyTimer);
475
+ copyTimer = setTimeout(() => copied = false, 2000);
476
+ }
477
+ $$renderer2.push(`<header class="topbar svelte-15fxkvm"><a class="back svelte-15fxkvm" href="/">`);
478
+ Arrow_left($$renderer2, { size: 15 });
479
+ $$renderer2.push(`<!----> All instances</a> <div class="title svelte-15fxkvm"><span class="name svelte-15fxkvm">${$10.escape(instance?.name ?? "Instance")}</span> `);
480
+ if (instance) {
481
+ $$renderer2.push("<!--[0-->");
482
+ StatusBadge($$renderer2, { status: instance.status });
483
+ } else {
484
+ $$renderer2.push("<!--[-1-->");
485
+ Skeleton($$renderer2, { variant: "pill" });
486
+ }
487
+ $$renderer2.push(`<!--]--></div> `);
488
+ if (instance?.status === "running") {
489
+ $$renderer2.push("<!--[0-->");
490
+ $$renderer2.push(`<form method="POST" action="?/restart" class="svelte-15fxkvm"><button class="restart svelte-15fxkvm" type="submit"${$10.attr("disabled", restarting || building(), true)}>${$10.escape(restarting || building() ? "Restarting\u2026" : "Restart container")}</button></form> <a class="open svelte-15fxkvm"${$10.attr("href", url())} target="_blank" rel="noopener">Open in new tab `);
491
+ Arrow_up_right($$renderer2, { size: 15 });
492
+ $$renderer2.push(`<!----></a>`);
493
+ } else {
494
+ $$renderer2.push("<!--[-1-->");
495
+ }
496
+ $$renderer2.push(`<!--]--></header> `);
497
+ if (restartError) {
498
+ $$renderer2.push("<!--[0-->");
499
+ $$renderer2.push(`<p class="restart-err svelte-15fxkvm">${$10.escape(restartError)}</p>`);
500
+ } else {
501
+ $$renderer2.push("<!--[-1-->");
502
+ }
503
+ $$renderer2.push(`<!--]--> <main class="stage svelte-15fxkvm"><div class="meta svelte-15fxkvm"><span class="k svelte-15fxkvm">Source</span> `);
504
+ if (instance) {
505
+ $$renderer2.push("<!--[0-->");
506
+ $$renderer2.push(`<code class="svelte-15fxkvm">${$10.escape(instance.source_path)}</code>`);
507
+ } else {
508
+ $$renderer2.push("<!--[-1-->");
509
+ Skeleton($$renderer2, { variant: "wide" });
510
+ }
511
+ $$renderer2.push(`<!--]--> <span class="k svelte-15fxkvm">Image</span> `);
512
+ if (instance) {
513
+ $$renderer2.push("<!--[0-->");
514
+ if (instance.image_source === "local") {
515
+ $$renderer2.push("<!--[0-->");
516
+ $$renderer2.push(`<code class="svelte-15fxkvm">local (project devcontainer.json)</code>`);
517
+ } else if (instance.image_source) {
518
+ $$renderer2.push("<!--[1-->");
519
+ $$renderer2.push(`<code class="svelte-15fxkvm">${$10.escape(instance.image_source)}</code>`);
520
+ } else {
521
+ $$renderer2.push("<!--[-1-->");
522
+ $$renderer2.push(`<code class="muted svelte-15fxkvm">\u2014</code>`);
523
+ }
524
+ $$renderer2.push(`<!--]-->`);
525
+ } else {
526
+ $$renderer2.push("<!--[-1-->");
527
+ Skeleton($$renderer2, { variant: "wide" });
528
+ }
529
+ $$renderer2.push(`<!--]--></div> <div class="healthslot svelte-15fxkvm">`);
530
+ HealthBox($$renderer2, {
531
+ health,
532
+ lastFetchedAt,
533
+ injectionChecks,
534
+ active: !instance || instance.status === "running",
535
+ mode: instance?.mode ?? "ide"
536
+ });
537
+ $$renderer2.push(`<!----></div> <section class="ports panel svelte-15fxkvm"><div class="ports-bar panel-bar svelte-15fxkvm"><span class="svelte-15fxkvm">Forwarded ports</span> `);
538
+ if (pendingRebuild) {
539
+ $$renderer2.push("<!--[0-->");
540
+ $$renderer2.push(`<button class="rebuild svelte-15fxkvm"${$10.attr("disabled", building(), true)}>${$10.escape(building() ? "Restarting\u2026" : "Restart to apply")}</button>`);
541
+ } else {
542
+ $$renderer2.push("<!--[-1-->");
543
+ }
544
+ $$renderer2.push(`<!--]--></div> <div class="ports-body svelte-15fxkvm">`);
545
+ if (forwards().length) {
546
+ $$renderer2.push("<!--[0-->");
547
+ $$renderer2.push(`<ul class="port-list svelte-15fxkvm"><!--[-->`);
548
+ const each_array = $10.ensure_array_like(forwards());
549
+ for (let $$index = 0, $$length = each_array.length;$$index < $$length; $$index++) {
550
+ let f = each_array[$$index];
551
+ $$renderer2.push(`<li class="svelte-15fxkvm"><span class="cp svelte-15fxkvm">:${$10.escape(f.container_port)}</span> <span class="arr svelte-15fxkvm">\u2192</span> <a${$10.attr("href", forwardedPortUrl(f.host_port))} target="_blank" rel="noopener" class="svelte-15fxkvm">${$10.escape(forwardedPortUrl(f.host_port).replace("http://", ""))} `);
552
+ Arrow_up_right($$renderer2, { size: 12 });
553
+ $$renderer2.push(`<!----></a> <button class="rm svelte-15fxkvm" title="Remove">\xD7</button></li>`);
554
+ }
555
+ $$renderer2.push(`<!--]--></ul>`);
556
+ } else {
557
+ $$renderer2.push("<!--[-1-->");
558
+ $$renderer2.push(`<p class="empty svelte-15fxkvm">No ports forwarded yet.</p>`);
559
+ }
560
+ $$renderer2.push(`<!--]--> <form class="add svelte-15fxkvm"><input type="number" min="1" max="65535" placeholder="container port (e.g. 3000)"${$10.attr("value", newPort)} spellcheck="false" class="svelte-15fxkvm"/> <button type="submit" class="svelte-15fxkvm">Add</button></form> `);
561
+ if (portError) {
562
+ $$renderer2.push("<!--[0-->");
563
+ $$renderer2.push(`<p class="port-err svelte-15fxkvm">${$10.escape(portError)}</p>`);
564
+ } else {
565
+ $$renderer2.push("<!--[-1-->");
566
+ }
567
+ $$renderer2.push(`<!--]--> `);
568
+ if (pendingRebuild) {
569
+ $$renderer2.push("<!--[0-->");
570
+ $$renderer2.push(`<p class="hint pending svelte-15fxkvm">Port changes apply when you <strong class="svelte-15fxkvm">Restart</strong> (recreates the container).</p>`);
571
+ } else {
572
+ $$renderer2.push("<!--[-1-->");
573
+ }
574
+ $$renderer2.push(`<!--]--> <p class="hint svelte-15fxkvm">Your app must bind to <code class="svelte-15fxkvm">0.0.0.0</code> inside the container to be reachable.</p></div></section> `);
575
+ AgentLogBox($$renderer2, { id, bump: runBump });
576
+ $$renderer2.push(`<!----> <div class="logwrap panel svelte-15fxkvm"><div class="log-bar panel-bar svelte-15fxkvm"><span class="svelte-15fxkvm">Boot log</span> <div class="log-actions svelte-15fxkvm"><button${$10.attr_class("copy svelte-15fxkvm", undefined, { active: following })}${$10.attr("aria-pressed", following)}${$10.attr("title", following ? "Following \u2014 click to pause" : "Paused \u2014 click to follow new output")}>`);
577
+ if (following) {
578
+ $$renderer2.push("<!--[0-->");
579
+ $$renderer2.push(`<span class="dot svelte-15fxkvm"></span>`);
580
+ } else {
581
+ $$renderer2.push("<!--[-1-->");
582
+ }
583
+ $$renderer2.push(`<!--]--> ${$10.escape(following ? "Following" : "Follow log")}</button> <button class="copy svelte-15fxkvm"${$10.attr("disabled", !logs, true)}>${$10.escape(copied ? "Copied!" : "Copy logs")}</button></div></div> <div class="logs svelte-15fxkvm"><pre class="svelte-15fxkvm">${$10.escape(logs || "Waiting for output\u2026")}<span class="caret svelte-15fxkvm"></span></pre></div> `);
584
+ if (instance?.status === "error" && instance.error) {
585
+ $$renderer2.push("<!--[0-->");
586
+ $$renderer2.push(`<div class="err svelte-15fxkvm">${$10.escape(instance.error)}</div>`);
587
+ } else {
588
+ $$renderer2.push("<!--[-1-->");
589
+ }
590
+ $$renderer2.push(`<!--]--></div></main>`);
591
+ });
592
+ }
593
+
594
+ // src/pages/Instance.svelte
595
+ function Instance($$renderer, $$props) {
596
+ $$renderer.component(($$renderer2) => {
597
+ let { id, injectionChecks } = $$props;
598
+ if (true) {
599
+ let failed = function($$renderer3, error) {
600
+ $$renderer3.push(`<mochi-island-failure data-component="InstanceView"${$11.attr("data-message", error.message)}></mochi-island-failure>`);
601
+ };
602
+ $$renderer2.push("<!--[0-->");
603
+ $$renderer2.boundary({ failed }, ($$renderer3) => {
604
+ $$renderer3.push(`<!--[-->`);
605
+ {
606
+ HydratableBoundary($$renderer3, {
607
+ children: ($$renderer4) => {
608
+ $$renderer4.push(`<mochi-hydratable-island component-name="InstanceView_2ma45l9bybfhl" component-url="__MOCHI_COMPONENT_URL__InstanceView_2ma45l9bybfhl__"${$11.attr("props-ref", emitIslandProps({ id, injectionChecks }))}>`);
609
+ $$renderer4.push(`<!--[-->`);
610
+ {
611
+ InstanceView($$renderer4, { id, injectionChecks });
612
+ }
613
+ $$renderer4.push(`<!--]-->`);
614
+ $$renderer4.push(`</mochi-hydratable-island>`);
615
+ },
616
+ $$slots: { default: true }
617
+ });
618
+ }
619
+ $$renderer3.push(`<!--]-->`);
620
+ });
621
+ }
622
+ $$renderer2.push(`<!--]-->`);
623
+ });
624
+ }
625
+ export {
626
+ Instance as default
627
+ };