@baochunli/flakes 0.0.5 → 0.0.6
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/dist/node_modules/@flakes/auth/package.json +1 -1
- package/dist/node_modules/@flakes/console/.output/nitro.json +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/{DocumentationPage-CNPk8RVl.js → DocumentationPage-CGIcMKwf.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/ProjectsPage-ByTl4Kyy.js +1 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/RunPage-5MmbVpaE.js +3 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/{RunsPage-CJbycrqM.js → RunsPage-fbDKP9kM.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/{SandboxesLens-BoLM52PY.js → SandboxesLens-DPG87mUE.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/SandboxesPage-DIpzR_Ef.js +1 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/TranscriptPage-mCgSqfv0.js +1 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/_-CM2hE2sZ.js +1 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/_runId-3ZZOAqUK.js +2 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/_taskId-cy4RxW8Y.js +2 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/{account-BoRurhrq.js → account-BWoGGXJw.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/{account-forms-D4eVqOhW.js → account-forms-Dq70JDyg.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/{auth-layout-DBnq_eif.js → auth-layout-BFusNq3W.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/{bits-BOMPEHvv.js → bits-CTGNpp-v.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/device-BajR3eSF.js +1 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/documentation-6ao_Ux6x.js +1 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/{forgot-password-BSQ4TWpA.js → forgot-password-DOKn8_7P.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/main-DVO9gWzi.js +1215 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/{otp-verification-CussJQT1.js → otp-verification-qolVtiom.js} +2 -2
- package/dist/node_modules/@flakes/console/.output/public/assets/projects-n5LSsNi3.js +2 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/{reset-password-DwWhVkEh.js → reset-password-D-OlZeHQ.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/runs-BB9ogobQ.js +2 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/sandboxes-BIimz5FI.js +2 -0
- package/dist/node_modules/@flakes/console/.output/public/assets/{security-MjM55vIw.js → security-DdQNcp6k.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/{signin-KbA1cD6o.js → signin-BoZiVxyq.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/{signin-form-CBF-d8iK.js → signin-form-tTBWDjhi.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/{signup-CbHsThKr.js → signup-CBSszmUC.js} +1 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/styles-B8OXOvkO.css +2 -0
- package/dist/node_modules/@flakes/console/.output/server/{_-BULJ6utw.mjs → _-BGsKgsbF.mjs} +3 -3
- package/dist/node_modules/@flakes/console/.output/server/{_-_ST9QYWn.mjs → _-DtPMXzt0.mjs} +3 -3
- package/dist/node_modules/@flakes/console/.output/server/_chunks/ProjectsPage.mjs +1 -2
- package/dist/node_modules/@flakes/console/.output/server/_chunks/RunPage.mjs +1 -2
- package/dist/node_modules/@flakes/console/.output/server/_chunks/RunsPage.mjs +1 -2
- package/dist/node_modules/@flakes/console/.output/server/_chunks/SandboxesLens.mjs +1 -1
- package/dist/node_modules/@flakes/console/.output/server/_chunks/SandboxesPage.mjs +253 -18
- package/dist/node_modules/@flakes/console/.output/server/_chunks/TranscriptPage.mjs +1 -2
- package/dist/node_modules/@flakes/console/.output/server/_chunks/bits.mjs +1 -1
- package/dist/node_modules/@flakes/console/.output/server/_chunks/button.mjs +461 -3
- package/dist/node_modules/@flakes/console/.output/server/_chunks/card.mjs +1 -1
- package/dist/node_modules/@flakes/console/.output/server/_chunks/router.mjs +3 -4
- package/dist/node_modules/@flakes/console/.output/server/_chunks/table.mjs +1 -1
- package/dist/node_modules/@flakes/console/.output/server/{_runId-WZmbo654.mjs → _runId-P1u-vfcm.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/{_runId-CmYWNL8A.mjs → _runId-vO4tlCOP.mjs} +3 -3
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{App-CUx8Ftit.mjs → App-C-XaVKoO.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{DocumentationPage-0I9oWWJT.mjs → DocumentationPage-BR2KosFz.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{ProjectsPage-CGj9V2Of.mjs → ProjectsPage-BUrep1wl.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{RunPage-B2vhVaj6.mjs → RunPage-BHs-v0LU.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{RunsPage-BifKogQE.mjs → RunsPage-iTNYVwL0.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/SandboxesPage-C1Z6dVce.mjs +423 -0
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{TranscriptPage-deSxVZaQ.mjs → TranscriptPage-BcomoTls.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{account-D5y9vkAc.mjs → account-Cp0s_IQK.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{documentation-C91gfyy0.mjs → documentation-BnxmM-Yo.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{documentation-C69e9_eF.mjs → documentation-Cgyr3VKK.mjs} +3 -3
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{hooks-DrgN35zn.mjs → hooks-CsVtQ1m-.mjs} +117 -51
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{projects-lJ2tIIPj.mjs → projects-R9sxR_t4.mjs} +1 -1
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{router-DHxFQ03L.mjs → router-CobdI6gO.mjs} +12 -12
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{runs-dnPfp9dt.mjs → runs-D8MHe3QU.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{runs-BWxEGKO_.mjs → runs-mTxbc_pm.mjs} +3 -3
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{sandboxes-v28LJQM3.mjs → sandboxes-B2z_9JyU.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/_ssr/{sandboxes-hxFINxDS.mjs → sandboxes-r0y6Ihg6.mjs} +3 -3
- package/dist/node_modules/@flakes/console/.output/server/_ssr/ssr.mjs +2 -2
- package/dist/node_modules/@flakes/console/.output/server/{_tanstack-start-manifest_v-DfwuEzTr.mjs → _tanstack-start-manifest_v-DpAwCFK9.mjs} +32 -33
- package/dist/node_modules/@flakes/console/.output/server/{_taskId-CBo95z-s.mjs → _taskId-Cz9xwj5L.mjs} +2 -2
- package/dist/node_modules/@flakes/console/.output/server/{_taskId-Sil3-PKh.mjs → _taskId-wQsG2CQj.mjs} +3 -3
- package/dist/node_modules/@flakes/console/package.json +1 -1
- package/dist/node_modules/@flakes/control-plane/dist/host-credentials.d.ts +1 -1
- package/dist/node_modules/@flakes/control-plane/dist/host-credentials.d.ts.map +1 -1
- package/dist/node_modules/@flakes/control-plane/dist/routes/sandboxes.js +48 -3
- package/dist/node_modules/@flakes/control-plane/dist/routes/sandboxes.js.map +1 -1
- package/dist/node_modules/@flakes/control-plane/package.json +1 -1
- package/dist/node_modules/@flakes/core/package.json +1 -1
- package/dist/node_modules/@flakes/harness-agent/package.json +1 -1
- package/dist/node_modules/@flakes/harness-sdk/package.json +1 -1
- package/dist/node_modules/@flakes/pi-agent/package.json +1 -1
- package/dist/node_modules/@flakes/protocol/package.json +1 -1
- package/dist/node_modules/@flakes/sandbox-runtime/package.json +1 -1
- package/dist/node_modules/@flakes/store/dist/managed-sandbox-instances-store.d.ts +9 -1
- package/dist/node_modules/@flakes/store/dist/managed-sandbox-instances-store.d.ts.map +1 -1
- package/dist/node_modules/@flakes/store/dist/managed-sandbox-instances-store.js +407 -6
- package/dist/node_modules/@flakes/store/dist/managed-sandbox-instances-store.js.map +1 -1
- package/dist/node_modules/@flakes/store/dist/mappers.d.ts.map +1 -1
- package/dist/node_modules/@flakes/store/dist/mappers.js +1 -0
- package/dist/node_modules/@flakes/store/dist/mappers.js.map +1 -1
- package/dist/node_modules/@flakes/store/dist/types.d.ts +30 -1
- package/dist/node_modules/@flakes/store/dist/types.d.ts.map +1 -1
- package/dist/node_modules/@flakes/store/package.json +1 -1
- package/package.json +1 -1
- package/dist/node_modules/@flakes/auth/dist/better-auth-shape.d.ts +0 -10
- package/dist/node_modules/@flakes/auth/dist/better-auth-shape.d.ts.map +0 -1
- package/dist/node_modules/@flakes/auth/dist/better-auth-shape.js +0 -16
- package/dist/node_modules/@flakes/auth/dist/better-auth-shape.js.map +0 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/ProjectsPage-CKPR1nnu.js +0 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/RunPage-BdugbnA3.js +0 -3
- package/dist/node_modules/@flakes/console/.output/public/assets/SandboxesPage-6KHjMeaR.js +0 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/TranscriptPage-CHSq0_qN.js +0 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/_-CD1Voz9h.js +0 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/_runId-_0VPmGYe.js +0 -2
- package/dist/node_modules/@flakes/console/.output/public/assets/_taskId-CPAKAp4X.js +0 -2
- package/dist/node_modules/@flakes/console/.output/public/assets/device-FqII-S41.js +0 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/dist-BEfdrJTS.js +0 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/documentation-2C3ncAuV.js +0 -1
- package/dist/node_modules/@flakes/console/.output/public/assets/main-LpSDdT-S.js +0 -1215
- package/dist/node_modules/@flakes/console/.output/public/assets/projects-CLgKBrCe.js +0 -2
- package/dist/node_modules/@flakes/console/.output/public/assets/runs-CFYk2iRh.js +0 -2
- package/dist/node_modules/@flakes/console/.output/public/assets/sandboxes-mGsOcVFL.js +0 -2
- package/dist/node_modules/@flakes/console/.output/public/assets/styles-DtA2wbW8.css +0 -2
- package/dist/node_modules/@flakes/console/.output/server/_chunks/utils.mjs +0 -393
- package/dist/node_modules/@flakes/console/.output/server/_ssr/SandboxesPage-DGji_OdB.mjs +0 -187
- package/dist/node_modules/@flakes/control-plane/dist/managed-sandbox-provisioner.d.ts +0 -71
- package/dist/node_modules/@flakes/control-plane/dist/managed-sandbox-provisioner.d.ts.map +0 -1
- package/dist/node_modules/@flakes/control-plane/dist/managed-sandbox-provisioner.js +0 -243
- package/dist/node_modules/@flakes/control-plane/dist/managed-sandbox-provisioner.js.map +0 -1
- package/dist/node_modules/@flakes/control-plane/dist/routes/sandboxes-admin.d.ts +0 -3
- package/dist/node_modules/@flakes/control-plane/dist/routes/sandboxes-admin.d.ts.map +0 -1
- package/dist/node_modules/@flakes/control-plane/dist/routes/sandboxes-admin.js +0 -153
- package/dist/node_modules/@flakes/control-plane/dist/routes/sandboxes-admin.js.map +0 -1
- package/dist/node_modules/@flakes/control-plane/dist/sandbox-drain.d.ts +0 -19
- package/dist/node_modules/@flakes/control-plane/dist/sandbox-drain.d.ts.map +0 -1
- package/dist/node_modules/@flakes/control-plane/dist/sandbox-drain.js +0 -46
- package/dist/node_modules/@flakes/control-plane/dist/sandbox-drain.js.map +0 -1
- package/dist/node_modules/@flakes/store/dist/sqlite.d.ts +0 -4
- package/dist/node_modules/@flakes/store/dist/sqlite.d.ts.map +0 -1
- package/dist/node_modules/@flakes/store/dist/sqlite.js +0 -34
- package/dist/node_modules/@flakes/store/dist/sqlite.js.map +0 -1
|
@@ -1,6 +1,464 @@
|
|
|
1
1
|
import { c as require_jsx_runtime, i as Slot } from "../_libs/@radix-ui/react-arrow+[...].mjs";
|
|
2
|
-
import { t as
|
|
3
|
-
import { t as
|
|
2
|
+
import { t as createServerFn } from "../_libs/@tanstack/start-client-core+[...].mjs";
|
|
3
|
+
import { i as useQuery, n as useMutation, o as useQueryClient, t as useInfiniteQuery } from "../_libs/tanstack__react-query.mjs";
|
|
4
|
+
import { n as clsx, t as cva } from "../_libs/class-variance-authority+clsx.mjs";
|
|
5
|
+
import { t as twMerge } from "../_libs/tailwind-merge.mjs";
|
|
6
|
+
import { n as normalizeConsolePath } from "./paths.mjs";
|
|
7
|
+
//#region src/api/server-functions.ts
|
|
8
|
+
var consoleGetJson = createServerFn({ method: "GET" }).inputValidator(validatePathInput).handler(async ({ data }) => {
|
|
9
|
+
const { proxyJsonHandler } = await import("./server-runtime.mjs");
|
|
10
|
+
return proxyJsonHandler("GET", data);
|
|
11
|
+
});
|
|
12
|
+
var consoleGetText = createServerFn({ method: "GET" }).inputValidator(validatePathInput).handler(async ({ data }) => {
|
|
13
|
+
const { proxyTextHandler } = await import("./server-runtime.mjs");
|
|
14
|
+
return proxyTextHandler(data);
|
|
15
|
+
});
|
|
16
|
+
var consolePostJson = createServerFn({ method: "POST" }).inputValidator(validateJsonInput).handler(async ({ data }) => {
|
|
17
|
+
const { proxyJsonHandler } = await import("./server-runtime.mjs");
|
|
18
|
+
return proxyJsonHandler("POST", data);
|
|
19
|
+
});
|
|
20
|
+
var consolePutJson = createServerFn({ method: "POST" }).inputValidator(validateJsonInput).handler(async ({ data }) => {
|
|
21
|
+
const { proxyJsonHandler } = await import("./server-runtime.mjs");
|
|
22
|
+
return proxyJsonHandler("PUT", data);
|
|
23
|
+
});
|
|
24
|
+
var consoleDeleteJson = createServerFn({ method: "POST" }).inputValidator(validatePathInput).handler(async ({ data }) => {
|
|
25
|
+
const { proxyJsonHandler } = await import("./server-runtime.mjs");
|
|
26
|
+
return proxyJsonHandler("DELETE", data);
|
|
27
|
+
});
|
|
28
|
+
function validatePathInput(data) {
|
|
29
|
+
return { path: requireConsolePath(requireRecord(data, "path input").path) };
|
|
30
|
+
}
|
|
31
|
+
function validateJsonInput(data) {
|
|
32
|
+
const record = requireRecord(data, "json input");
|
|
33
|
+
return {
|
|
34
|
+
path: requireConsolePath(record.path),
|
|
35
|
+
...record.body === void 0 ? {} : { body: record.body }
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function requireConsolePath(value) {
|
|
39
|
+
if (typeof value !== "string" || value.length === 0) throw new Error("path must be a non-empty string");
|
|
40
|
+
return normalizeConsolePath(value);
|
|
41
|
+
}
|
|
42
|
+
function requireRecord(value, label) {
|
|
43
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/api/client.ts
|
|
48
|
+
/** Raised on 401/403 so views can redirect through user auth. */
|
|
49
|
+
var AuthError = class extends Error {};
|
|
50
|
+
/** Raised on 404 so views can render an explicit missing-resource state. */
|
|
51
|
+
var NotFoundError = class extends Error {};
|
|
52
|
+
/** Raised for non-auth API failures with the server-provided message. */
|
|
53
|
+
var ApiError = class extends Error {
|
|
54
|
+
status;
|
|
55
|
+
details;
|
|
56
|
+
constructor(message, status, details) {
|
|
57
|
+
super(message);
|
|
58
|
+
this.status = status;
|
|
59
|
+
this.details = details;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/** GET through the TanStack Start server function layer. */
|
|
63
|
+
async function apiGet(path) {
|
|
64
|
+
return unwrapResult(await consoleGetJson({ data: { path } }));
|
|
65
|
+
}
|
|
66
|
+
async function apiGetText(path) {
|
|
67
|
+
return unwrapResult(await consoleGetText({ data: { path } }));
|
|
68
|
+
}
|
|
69
|
+
/** POST JSON through the TanStack Start server function layer. */
|
|
70
|
+
async function apiPost(path, body) {
|
|
71
|
+
return unwrapResult(await consolePostJson({ data: {
|
|
72
|
+
path,
|
|
73
|
+
body
|
|
74
|
+
} }));
|
|
75
|
+
}
|
|
76
|
+
/** PUT JSON through the TanStack Start server function layer. */
|
|
77
|
+
async function apiPut(path, body) {
|
|
78
|
+
return unwrapResult(await consolePutJson({ data: {
|
|
79
|
+
path,
|
|
80
|
+
body
|
|
81
|
+
} }));
|
|
82
|
+
}
|
|
83
|
+
/** DELETE through the TanStack Start server function layer. */
|
|
84
|
+
async function apiDelete(path) {
|
|
85
|
+
return unwrapResult(await consoleDeleteJson({ data: { path } }));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Fetches a file through the TanStack Start server route and triggers a
|
|
89
|
+
* browser download. The bearer token stays server-side in the console session.
|
|
90
|
+
*/
|
|
91
|
+
async function downloadFile(path, filename) {
|
|
92
|
+
const response = await fetch(`/console/api/download?path=${encodeURIComponent(path)}`);
|
|
93
|
+
if (response.status === 401 || response.status === 403) throw new AuthError(`auth failed (${response.status})`);
|
|
94
|
+
if (!response.ok) throw await apiError(response, path);
|
|
95
|
+
const blob = await response.blob();
|
|
96
|
+
const url = URL.createObjectURL(blob);
|
|
97
|
+
const anchor = document.createElement("a");
|
|
98
|
+
anchor.href = url;
|
|
99
|
+
anchor.download = filename;
|
|
100
|
+
document.body.appendChild(anchor);
|
|
101
|
+
anchor.click();
|
|
102
|
+
anchor.remove();
|
|
103
|
+
URL.revokeObjectURL(url);
|
|
104
|
+
}
|
|
105
|
+
async function apiError(response, path) {
|
|
106
|
+
let details;
|
|
107
|
+
let message = `${path} failed (${response.status})`;
|
|
108
|
+
try {
|
|
109
|
+
details = await response.clone().json();
|
|
110
|
+
if (isRecord$1(details) && typeof details.message === "string") message = details.message;
|
|
111
|
+
else if (isRecord$1(details) && typeof details.error === "string") message = details.error;
|
|
112
|
+
} catch {
|
|
113
|
+
try {
|
|
114
|
+
const text = await response.clone().text();
|
|
115
|
+
if (text.trim().length > 0) message = text.trim();
|
|
116
|
+
} catch {}
|
|
117
|
+
}
|
|
118
|
+
return new ApiError(message, response.status, details);
|
|
119
|
+
}
|
|
120
|
+
function unwrapResult(result) {
|
|
121
|
+
if (result.ok) return result.data;
|
|
122
|
+
if (result.status === 401 || result.status === 403) throw new AuthError(result.message);
|
|
123
|
+
if (result.status === 404) throw new NotFoundError(result.message);
|
|
124
|
+
throw new ApiError(result.message, result.status, result.details);
|
|
125
|
+
}
|
|
126
|
+
function isRecord$1(value) {
|
|
127
|
+
return typeof value === "object" && value !== null;
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/lib/managed-sandbox-delete.ts
|
|
131
|
+
var deletableStatuses = new Set([
|
|
132
|
+
"running",
|
|
133
|
+
"draining",
|
|
134
|
+
"stopping",
|
|
135
|
+
"stopped",
|
|
136
|
+
"failed",
|
|
137
|
+
"expired",
|
|
138
|
+
"cancelled"
|
|
139
|
+
]);
|
|
140
|
+
var blockerText = {
|
|
141
|
+
unsafe_status: "sandbox is not in a stale lifecycle state",
|
|
142
|
+
live_sandbox: "sandbox is live",
|
|
143
|
+
accepted_running_assignments: "sandbox has accepted running assignments",
|
|
144
|
+
provider_cleanup_required: "provider cleanup is required"
|
|
145
|
+
};
|
|
146
|
+
function canRequestManagedSandboxDelete(sandbox) {
|
|
147
|
+
return sandbox.sandboxStatus !== "active" && deletableStatuses.has(sandbox.status);
|
|
148
|
+
}
|
|
149
|
+
function managedSandboxDeleteAction(sandbox, pending, confirming) {
|
|
150
|
+
if (pending) return "pending";
|
|
151
|
+
if (!canRequestManagedSandboxDelete(sandbox)) return "hidden";
|
|
152
|
+
return confirming ? "confirm" : "request";
|
|
153
|
+
}
|
|
154
|
+
function applyManagedSandboxDeleteResult(sandboxes, result) {
|
|
155
|
+
if (result.status === "deleted") return sandboxes.filter((sandbox) => sandbox.sandboxId !== result.sandboxId);
|
|
156
|
+
return sandboxes.map((sandbox) => sandbox.sandboxId === result.sandboxId ? {
|
|
157
|
+
...sandbox,
|
|
158
|
+
status: "deleting"
|
|
159
|
+
} : sandbox);
|
|
160
|
+
}
|
|
161
|
+
function managedSandboxDeleteErrorMessage(error) {
|
|
162
|
+
if (error instanceof NotFoundError) return "Sandbox is unavailable or already deleted.";
|
|
163
|
+
if (error instanceof ApiError && error.status === 409) {
|
|
164
|
+
const blockers = deleteBlockers(error.details);
|
|
165
|
+
if (blockers.length > 0) return `Delete blocked: ${blockers.map(blockerMessage).join("; ")}.`;
|
|
166
|
+
}
|
|
167
|
+
return error instanceof Error ? error.message : "Failed to delete sandbox.";
|
|
168
|
+
}
|
|
169
|
+
function deleteBlockers(details) {
|
|
170
|
+
if (!isRecord(details) || !Array.isArray(details.blockers)) return [];
|
|
171
|
+
return details.blockers.filter((blocker) => typeof blocker === "string");
|
|
172
|
+
}
|
|
173
|
+
function blockerMessage(blocker) {
|
|
174
|
+
return blockerText[blocker] ?? blocker.replaceAll("_", " ");
|
|
175
|
+
}
|
|
176
|
+
function isRecord(value) {
|
|
177
|
+
return typeof value === "object" && value !== null;
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region src/lib/project-placement.ts
|
|
181
|
+
function hostProjectWorkspaceRootPath(hostId) {
|
|
182
|
+
return `/v1/hosts/${encodeURIComponent(hostId)}/project-workspace-root`;
|
|
183
|
+
}
|
|
184
|
+
function hostProjectBindingsPath(hostId) {
|
|
185
|
+
return `/v1/hosts/${encodeURIComponent(hostId)}/project-bindings`;
|
|
186
|
+
}
|
|
187
|
+
function hostProjectBindingPath(hostId, projectKey) {
|
|
188
|
+
return `${hostProjectBindingsPath(hostId)}/${encodeURIComponent(projectKey)}`;
|
|
189
|
+
}
|
|
190
|
+
function hostProjectWorkspacePath(projectWorkspaceRoot, projectKey) {
|
|
191
|
+
const separator = projectWorkspaceRoot.includes("\\") && !projectWorkspaceRoot.includes("/") ? "\\" : "/";
|
|
192
|
+
return projectWorkspaceRoot.endsWith("/") || projectWorkspaceRoot.endsWith("\\") ? `${projectWorkspaceRoot}${projectKey}` : `${projectWorkspaceRoot}${separator}${projectKey}`;
|
|
193
|
+
}
|
|
194
|
+
function bindingValidationView(binding) {
|
|
195
|
+
if (binding === void 0) return {
|
|
196
|
+
tone: "idle",
|
|
197
|
+
label: "Not bound",
|
|
198
|
+
detail: "No host binding has been saved for this project."
|
|
199
|
+
};
|
|
200
|
+
if (binding.availability === "available") return {
|
|
201
|
+
tone: "available",
|
|
202
|
+
label: "Available",
|
|
203
|
+
detail: `Validated ${binding.lastValidatedAt ?? binding.updatedAt}.`
|
|
204
|
+
};
|
|
205
|
+
if (binding.availability === "unavailable") return {
|
|
206
|
+
tone: "unavailable",
|
|
207
|
+
label: "Unavailable",
|
|
208
|
+
detail: binding.validationReason ?? `Last rejected ${binding.lastValidatedAt ?? binding.updatedAt}.`
|
|
209
|
+
};
|
|
210
|
+
return {
|
|
211
|
+
tone: "pending",
|
|
212
|
+
label: "Pending validation",
|
|
213
|
+
detail: "Waiting for the host runtime to validate this binding."
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function poolChoicesForBinding(pools, binding) {
|
|
217
|
+
const selected = new Set(binding?.poolKeys ?? []);
|
|
218
|
+
return pools.map((pool) => {
|
|
219
|
+
const status = pool.status ?? "available";
|
|
220
|
+
return {
|
|
221
|
+
poolKey: pool.poolKey,
|
|
222
|
+
selected: selected.has(pool.poolKey),
|
|
223
|
+
status,
|
|
224
|
+
statusLabel: status
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
//#endregion
|
|
229
|
+
//#region src/api/hooks.ts
|
|
230
|
+
var POLL_MS = 1e3;
|
|
231
|
+
function useRuns(input) {
|
|
232
|
+
const state = typeof input === "string" ? input : input?.state;
|
|
233
|
+
const projectKey = typeof input === "string" ? void 0 : input?.projectKey;
|
|
234
|
+
return useInfiniteQuery({
|
|
235
|
+
queryKey: [
|
|
236
|
+
"runs",
|
|
237
|
+
state ?? null,
|
|
238
|
+
projectKey ?? null
|
|
239
|
+
],
|
|
240
|
+
initialPageParam: void 0,
|
|
241
|
+
queryFn: ({ pageParam }) => {
|
|
242
|
+
const params = new URLSearchParams();
|
|
243
|
+
if (state !== void 0) params.set("state", state);
|
|
244
|
+
if (projectKey !== void 0) params.set("projectKey", projectKey);
|
|
245
|
+
if (pageParam !== void 0) params.set("cursor", pageParam);
|
|
246
|
+
const query = params.toString();
|
|
247
|
+
return apiGet(`/v1/runs${query ? `?${query}` : ""}`);
|
|
248
|
+
},
|
|
249
|
+
getNextPageParam: (lastPage) => lastPage.nextCursor,
|
|
250
|
+
maxPages: 10,
|
|
251
|
+
refetchInterval: POLL_MS
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
function useProjects() {
|
|
255
|
+
return useQuery({
|
|
256
|
+
queryKey: ["projects"],
|
|
257
|
+
queryFn: () => apiGet("/v1/projects"),
|
|
258
|
+
refetchInterval: POLL_MS
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
function useHosts() {
|
|
262
|
+
return useQuery({
|
|
263
|
+
queryKey: ["hosts"],
|
|
264
|
+
queryFn: () => apiGet("/v1/hosts"),
|
|
265
|
+
refetchInterval: POLL_MS
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function useHostPools(hostId) {
|
|
269
|
+
return useQuery({
|
|
270
|
+
queryKey: ["host-pools", hostId],
|
|
271
|
+
enabled: hostId !== null,
|
|
272
|
+
queryFn: () => apiGet(`/v1/hosts/${encodeURIComponent(requireHostId(hostId, "useHostPools"))}/pools`),
|
|
273
|
+
refetchInterval: POLL_MS
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
function useSandboxFleet() {
|
|
277
|
+
return useQuery({
|
|
278
|
+
queryKey: ["sandbox-fleet"],
|
|
279
|
+
queryFn: () => apiGet("/v1/sandboxes"),
|
|
280
|
+
refetchInterval: POLL_MS
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
function useDeleteManagedSandbox() {
|
|
284
|
+
const queryClient = useQueryClient();
|
|
285
|
+
return useMutation({
|
|
286
|
+
mutationFn: (sandboxId) => apiDelete(`/v1/sandboxes/${encodeURIComponent(sandboxId)}`),
|
|
287
|
+
onSuccess: async (result) => {
|
|
288
|
+
queryClient.setQueryData(["sandbox-fleet"], (current) => current ? { sandboxes: applyManagedSandboxDeleteResult(current.sandboxes, result) } : current);
|
|
289
|
+
if (result.status === "deleted") queryClient.removeQueries({ queryKey: ["managed-sandbox", result.sandboxId] });
|
|
290
|
+
await Promise.all([queryClient.invalidateQueries({ queryKey: ["sandbox-fleet"] }), queryClient.invalidateQueries({ queryKey: ["managed-sandbox", result.sandboxId] })]);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
function useHostProjectBindings(hostId, enabled = true) {
|
|
295
|
+
return useQuery({
|
|
296
|
+
queryKey: ["host-project-bindings", hostId],
|
|
297
|
+
enabled: hostId !== null && enabled,
|
|
298
|
+
queryFn: () => apiGet(hostProjectBindingsPath(requireHostId(hostId, "useHostProjectBindings"))),
|
|
299
|
+
refetchInterval: POLL_MS
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
function useSetHostProjectWorkspaceRoot() {
|
|
303
|
+
const queryClient = useQueryClient();
|
|
304
|
+
return useMutation({
|
|
305
|
+
mutationFn: (input) => apiPut(hostProjectWorkspaceRootPath(input.hostId), { path: input.path }),
|
|
306
|
+
onSuccess: async (root) => {
|
|
307
|
+
await Promise.all([queryClient.invalidateQueries({ queryKey: ["hosts"] }), queryClient.invalidateQueries({ queryKey: ["host-project-bindings", root.hostId] })]);
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
function useUpsertHostProjectBinding() {
|
|
312
|
+
const queryClient = useQueryClient();
|
|
313
|
+
return useMutation({
|
|
314
|
+
mutationFn: (input) => apiPut(hostProjectBindingPath(input.hostId, input.projectKey), { poolKeys: input.poolKeys }),
|
|
315
|
+
onSuccess: async (_binding, input) => {
|
|
316
|
+
await queryClient.invalidateQueries({ queryKey: ["host-project-bindings", input.hostId] });
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
function useRun(runId) {
|
|
321
|
+
return useQuery({
|
|
322
|
+
queryKey: ["run", runId],
|
|
323
|
+
queryFn: () => apiGet(`/v1/runs/${encodeURIComponent(runId)}`),
|
|
324
|
+
refetchInterval: POLL_MS
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
function useRunTasks(runId) {
|
|
328
|
+
return useQuery({
|
|
329
|
+
queryKey: ["run-tasks", runId],
|
|
330
|
+
queryFn: () => apiGet(`/v1/runs/${encodeURIComponent(runId)}/tasks`),
|
|
331
|
+
refetchInterval: POLL_MS
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
function useRunArtifacts(runId) {
|
|
335
|
+
return useQuery({
|
|
336
|
+
queryKey: ["run-artifacts", runId],
|
|
337
|
+
queryFn: () => apiGet(`/v1/runs/${encodeURIComponent(runId)}/artifacts`),
|
|
338
|
+
refetchInterval: POLL_MS
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
function useRunMetrics(runId) {
|
|
342
|
+
return useQuery({
|
|
343
|
+
queryKey: ["run-metrics", runId],
|
|
344
|
+
queryFn: () => apiGet(`/v1/runs/${encodeURIComponent(runId)}/metrics`),
|
|
345
|
+
refetchInterval: POLL_MS
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
function useRunFileReservations(runId) {
|
|
349
|
+
return useQuery({
|
|
350
|
+
queryKey: ["run-file-reservations", runId],
|
|
351
|
+
queryFn: () => apiGet(`/v1/runs/${encodeURIComponent(runId)}/file-reservations`),
|
|
352
|
+
refetchInterval: POLL_MS
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
function useDeleteRun() {
|
|
356
|
+
const queryClient = useQueryClient();
|
|
357
|
+
return useMutation({
|
|
358
|
+
mutationFn: (runId) => apiDelete(`/v1/runs/${encodeURIComponent(runId)}`),
|
|
359
|
+
onSuccess: async (_data, runId) => {
|
|
360
|
+
queryClient.removeQueries({ queryKey: ["run", runId] });
|
|
361
|
+
queryClient.removeQueries({ queryKey: ["run-tasks", runId] });
|
|
362
|
+
queryClient.removeQueries({ queryKey: ["run-artifacts", runId] });
|
|
363
|
+
queryClient.removeQueries({ queryKey: ["run-metrics", runId] });
|
|
364
|
+
queryClient.removeQueries({ queryKey: ["run-file-reservations", runId] });
|
|
365
|
+
await queryClient.invalidateQueries({ queryKey: ["runs"] });
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
function useTaskPiSession(taskId, poll) {
|
|
370
|
+
return useQuery({
|
|
371
|
+
queryKey: ["task-pi-session", taskId],
|
|
372
|
+
enabled: taskId !== null,
|
|
373
|
+
queryFn: async () => {
|
|
374
|
+
const id = requireTaskId(taskId, "useTaskPiSession");
|
|
375
|
+
try {
|
|
376
|
+
return await apiGet(`/v1/tasks/${encodeURIComponent(id)}/pi-session`);
|
|
377
|
+
} catch (error) {
|
|
378
|
+
if (error instanceof NotFoundError) return null;
|
|
379
|
+
throw error;
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
refetchInterval: poll ? POLL_MS : false
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
function useTaskPiSessionRaw(taskId, enabled, poll) {
|
|
386
|
+
return useQuery({
|
|
387
|
+
queryKey: ["task-pi-session-raw", taskId],
|
|
388
|
+
enabled: taskId !== null && enabled,
|
|
389
|
+
queryFn: async () => {
|
|
390
|
+
const id = requireTaskId(taskId, "useTaskPiSessionRaw");
|
|
391
|
+
try {
|
|
392
|
+
return await apiGetText(`/v1/tasks/${encodeURIComponent(id)}/pi-session?format=raw`);
|
|
393
|
+
} catch (error) {
|
|
394
|
+
if (error instanceof NotFoundError) return null;
|
|
395
|
+
throw error;
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
refetchInterval: poll ? POLL_MS : false
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
function useSendTaskMessage(taskId) {
|
|
402
|
+
const queryClient = useQueryClient();
|
|
403
|
+
return useMutation({
|
|
404
|
+
mutationFn: (input) => {
|
|
405
|
+
const id = requireTaskId(taskId, "useSendTaskMessage");
|
|
406
|
+
return apiPost(`/v1/tasks/${encodeURIComponent(id)}/messages`, input);
|
|
407
|
+
},
|
|
408
|
+
onSuccess: async () => {
|
|
409
|
+
await queryClient.invalidateQueries({ queryKey: ["task-pi-session", taskId] });
|
|
410
|
+
await queryClient.invalidateQueries({ queryKey: ["task-pi-session-raw", taskId] });
|
|
411
|
+
await queryClient.invalidateQueries({ queryKey: ["task-activity", taskId] });
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
function useTaskWorkpad(taskId, poll) {
|
|
416
|
+
return useQuery({
|
|
417
|
+
queryKey: ["task-workpad", taskId],
|
|
418
|
+
enabled: taskId !== null,
|
|
419
|
+
queryFn: () => apiGet(`/v1/tasks/${encodeURIComponent(requireTaskId(taskId, "useTaskWorkpad"))}/workpad`),
|
|
420
|
+
refetchInterval: poll ? POLL_MS : false
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
function useSaveTaskWorkpad(taskId) {
|
|
424
|
+
const queryClient = useQueryClient();
|
|
425
|
+
return useMutation({
|
|
426
|
+
mutationFn: (input) => {
|
|
427
|
+
const id = requireTaskId(taskId, "useSaveTaskWorkpad");
|
|
428
|
+
return apiPut(`/v1/tasks/${encodeURIComponent(id)}/workpad`, input);
|
|
429
|
+
},
|
|
430
|
+
onSuccess: async (workpad) => {
|
|
431
|
+
queryClient.setQueryData(["task-workpad", taskId], workpad);
|
|
432
|
+
await queryClient.invalidateQueries({ queryKey: ["run-tasks", workpad.runId] });
|
|
433
|
+
await queryClient.invalidateQueries({ queryKey: ["task-activity", taskId] });
|
|
434
|
+
},
|
|
435
|
+
onSettled: async () => {
|
|
436
|
+
await queryClient.invalidateQueries({ queryKey: ["task-workpad", taskId] });
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
function useTaskActivity(taskId, poll) {
|
|
441
|
+
return useQuery({
|
|
442
|
+
queryKey: ["task-activity", taskId],
|
|
443
|
+
enabled: taskId !== null,
|
|
444
|
+
queryFn: () => apiGet(`/v1/tasks/${encodeURIComponent(requireTaskId(taskId, "useTaskActivity"))}/activity?limit=20`),
|
|
445
|
+
refetchInterval: poll ? POLL_MS : false
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
function requireTaskId(taskId, hookName) {
|
|
449
|
+
if (taskId === null) throw new Error(`${hookName} called without taskId`);
|
|
450
|
+
return taskId;
|
|
451
|
+
}
|
|
452
|
+
function requireHostId(hostId, hookName) {
|
|
453
|
+
if (hostId === null) throw new Error(`${hookName} called without hostId`);
|
|
454
|
+
return hostId;
|
|
455
|
+
}
|
|
456
|
+
//#endregion
|
|
457
|
+
//#region src/lib/utils.ts
|
|
458
|
+
function cn(...inputs) {
|
|
459
|
+
return twMerge(clsx(inputs));
|
|
460
|
+
}
|
|
461
|
+
//#endregion
|
|
4
462
|
//#region src/components/ui/button.tsx
|
|
5
463
|
var import_jsx_runtime = require_jsx_runtime();
|
|
6
464
|
var buttonVariants = cva("inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
@@ -43,4 +501,4 @@ function Button({ className, variant = "default", size = "default", asChild = fa
|
|
|
43
501
|
});
|
|
44
502
|
}
|
|
45
503
|
//#endregion
|
|
46
|
-
export { Button as t };
|
|
504
|
+
export { downloadFile as A, useUpsertHostProjectBinding as C, managedSandboxDeleteAction as D, poolChoicesForBinding as E, managedSandboxDeleteErrorMessage as O, useTaskWorkpad as S, hostProjectWorkspacePath as T, useSendTaskMessage as _, useHostPools as a, useTaskPiSession as b, useProjects as c, useRunFileReservations as d, useRunMetrics as f, useSaveTaskWorkpad as g, useSandboxFleet as h, useDeleteRun as i, ApiError as k, useRun as l, useRuns as m, cn as n, useHostProjectBindings as o, useRunTasks as p, useDeleteManagedSandbox as r, useHosts as s, Button as t, useRunArtifacts as u, useSetHostProjectWorkspaceRoot as v, bindingValidationView as w, useTaskPiSessionRaw as x, useTaskActivity as y };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as require_jsx_runtime } from "../_libs/@radix-ui/react-arrow+[...].mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { n as cn } from "./button.mjs";
|
|
3
3
|
//#region src/components/ui/card.tsx
|
|
4
4
|
var import_jsx_runtime = require_jsx_runtime();
|
|
5
5
|
function Card({ className, ...props }) {
|
|
@@ -11,8 +11,7 @@ import { t as Markdown } from "../_libs/react-markdown+[...].mjs";
|
|
|
11
11
|
import { t as remarkGfm } from "../_libs/remark-gfm.mjs";
|
|
12
12
|
import { n as jt, t as Lt } from "../_libs/input-otp.mjs";
|
|
13
13
|
import { t as authRouteHandlers } from "./auth.mjs";
|
|
14
|
-
import {
|
|
15
|
-
import { t as Button } from "./button.mjs";
|
|
14
|
+
import { c as useProjects, i as useDeleteRun, m as useRuns, n as cn, t as Button } from "./button.mjs";
|
|
16
15
|
import { i as splitProjectsByStatus, n as projectLabelForRun, t as groupRunsByProject } from "./project-navigation.mjs";
|
|
17
16
|
import { a as CardTitle, i as CardHeader, n as CardContent, r as CardDescription, t as Card } from "./card.mjs";
|
|
18
17
|
//#region src/components/console-brand.tsx
|
|
@@ -1062,7 +1061,7 @@ function AuthenticatedConsole(props) {
|
|
|
1062
1061
|
var favicon_default = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%3e%3ctitle%3eFlakes%3c/title%3e%3cdefs%3e%3ccircle%20id='n'%20cx='12'%20cy='4.2'%20r='1.9'%20fill='%2310b981'/%3e%3c/defs%3e%3cuse%20href='%23n'/%3e%3cuse%20href='%23n'%20transform='rotate(60%2012%2012)'/%3e%3cuse%20href='%23n'%20transform='rotate(120%2012%2012)'/%3e%3cuse%20href='%23n'%20transform='rotate(180%2012%2012)'/%3e%3cuse%20href='%23n'%20transform='rotate(240%2012%2012)'/%3e%3cuse%20href='%23n'%20transform='rotate(300%2012%2012)'/%3e%3ccircle%20cx='12'%20cy='12'%20r='2.4'%20fill='%2310b981'/%3e%3c/svg%3e";
|
|
1063
1062
|
//#endregion
|
|
1064
1063
|
//#region src/styles.css?url
|
|
1065
|
-
var styles_default = "/console/assets/styles-
|
|
1064
|
+
var styles_default = "/console/assets/styles-B8OXOvkO.css";
|
|
1066
1065
|
//#endregion
|
|
1067
1066
|
//#region src/routes/__root.tsx
|
|
1068
1067
|
var Route$18 = createRootRoute({
|
|
@@ -2218,7 +2217,7 @@ var docs_default = "---\ntitle: Overview\ndescription: What is Flakes?\n---\n\n[
|
|
|
2218
2217
|
var observe_and_steer_default = "---\ntitle: Observing And Steering\ndescription: Inspecting workflow runs in the console, read task history, and send live input.\n---\n\nUse the console at `https://flakes.dev/console` to watch durable work, inspect\nwhat an agent did, and send live input while a task is running.\n\nThe important boundary: durable task state is the source of truth. Status,\ndependencies, workpads, activity, artifacts, and transcript pointers live in\nthe control plane. A transient agent process, sandbox assignment, or local\nsession can end and be replaced without erasing that durable task state.\n\n## Runs\n\nThe Runs page lists every run your account can read, newest first. Use the\nstate filters for all, running, succeeded, or failed runs. Each row shows the\nrun name, run id, current state, task progress, creation time, and last update.\nOpen a row to inspect the run.\n\nQueued work is visible here as a running run whose task progress has not moved\nto terminal states yet. If a run remains active longer than expected, open the\nrun and check whether tasks are waiting for capacity, waiting for dependencies,\nrunning on a sandbox, or blocked on input.\n\n## Run Detail\n\nRun detail starts with the run state, elapsed time, task terminal count, and a\ndownload action for the run history. The Overview tab has three views:\n\n- Map: shows the task graph and dependency shape.\n- Timeline: shows queue time and execution time for each task.\n- By Sandbox: groups tasks by the sandbox that ran or is running them.\n\nThe Tasks table is the operational list. It shows task number, task name,\nstatus, workpad version, sandbox, dependencies, accepted time, finished time,\nand a Task button that opens task detail.\n\nOther run tabs show declared artifacts, metrics, and active file reservations.\nDelete is available only after the run is terminal; it removes finished run\nhistory and is not a control for stopping active work.\n\n## Task Detail\n\nOpen a task from the run map, timeline, sandbox view, or Tasks table. Task\ndetail shows the task brief, acceptance criteria, adapter, live round state when\npresent, dependencies, sandbox, attempt, accepted time, heartbeat, and finished\ntime.\n\nThe Workpad panel is the durable task note. Use it for current plan, progress,\nfindings, and handoff notes. The console saves with a version check, so if\nsomeone else updated the workpad first, your edit is rejected instead of\nsilently overwriting newer text.\n\nThe Activity panel is the short timeline for product events. It can show\nworkpad edits, human input, live round events, `permission.requested`, and\n`permission.responded`. Activity is not a full transcript and does not replace\nthe workpad.\n\nThe Agent transcript panel shows the saved Pi session when the task uses the\nPi adapter. Use Parsed for a readable conversation and tool view. Use Raw when\nyou need the underlying session record. A transcript is evidence of what the\nagent did; it is not how Flakes decides whether the task succeeded.\n\n## Steer Running Work\n\nThe task transcript includes live input controls while the task is running:\n\n- Follow up: add information or answer a question from the agent.\n- Steer: nudge direction without replacing the task definition.\n\nThe console queues the message and sends it to the active running task. The\nmessage is accepted only while the task is running on a connected sandbox. If\nthe task has already finished, is waiting, or its sandbox is offline, the\ncomposer is disabled or the send fails and you can retry only after there is an\nactive running assignment again.\n\nLive input does not edit the saved task. It is an event delivered to the\ncurrent agent process. The durable record is the task state, activity entry,\nworkpad, and transcript update that follow.\n\n## Permission Requests\n\nWhen an adapter needs human approval, it can create a durable permission\nrequest. The task activity shows `permission.requested`; after a response is\naccepted it shows `permission.responded` with the decision.\n\nIf your console deployment renders an inline permission prompt, answer it from\nthe task page by approving or denying the request and include a reason when the\nprompt asks for one. A permission request accepts only one response. Flakes\ndelivers the answer only to the active assignment for that task, so stale\nagents cannot receive answers for work they no longer own.\n\nPermission requests are always visible as durable activity events. Some\ndeployments or integrations may also render an inline approval prompt in the\nconsole, but do not assume every task page has a general approve or deny\ncontrol. When no control is visible, answer the request through the integration\nor API client that surfaced it, then use the console activity and transcript to\nconfirm the response was recorded and delivered.\n\n## What To Do By State\n\n| State | What it means | What you can do |\n| --- | --- | --- |\n| queued | The task is admitted but has not started. | Check dependencies, required capabilities, and connected host capacity. Usually the right action is to wait for capacity or connect capacity that advertises the needed adapter and capabilities. |\n| running | A sandbox currently owns the task. | Watch heartbeat, activity, workpad, and transcript. Send a follow-up or steer message if the agent needs more context. |\n| waiting | The task yielded because a durable wait condition is not satisfied. | Inspect the group or dependency that must settle. Do not expect the old process to resume; Flakes resumes the logical task from durable state when the wait condition resolves. |\n| failed | The task reached a terminal failure. | Open task detail, read the activity and transcript, inspect the workpad, and decide whether to create follow-up work in a new or still-open run. |\n| blocked on input | The task needs a human answer, such as a permission decision or missing context. | Use the visible prompt or live follow-up control when available. If no permission control is visible, respond through the client or integration that owns the prompt and verify `permission.responded` in activity. |\n\nFor scheduling issues, start with the run Timeline and By Sandbox views. For\nagent behavior, start with task Activity, Workpad, and Agent transcript. For\nhuman intervention, use Follow up, Steer, and the permission response path\navailable in your deployment.\n";
|
|
2219
2218
|
//#endregion
|
|
2220
2219
|
//#region ../../docs/content/docs/reference/index.mdx?raw
|
|
2221
|
-
var reference_default = "---\ntitle: Reference\ndescription: CLI commands, host configuration, selected API routes, and integrator exports for hosted Flakes.\n---\n\nUse this page after you understand the main workflows. It is a lookup for the\nhosted console at `https://flakes.dev`, the `flakes` CLI, user-supplied hosts,\nand selected integration surfaces.\n\nFor first-run steps, start with [Installing and Authorizing the CLI](/docs/cli).\nFor host setup, see [Connecting Your Hosts](/docs/connect-a-host).\n\n## CLI Command Reference\n\nCLI commands target the hosted control plane at `https://flakes.dev`. Most\ncommands use the stored credential from `flakes auth login`; commands that also\naccept `--token` are mainly for trusted automation.\n\n### Auth\n\n| Command | Use |\n| --- | --- |\n| `flakes auth login` | Start device authorization, open the browser approval page, and save the CLI credential. |\n| `flakes auth login --no-open` | Print the verification URL and user code without opening a browser. Useful on remote shells. |\n| `flakes auth login --timeout-ms 600000` | Wait longer for browser approval. |\n| `flakes auth login --json` | Emit the device-code and authenticated records as newline-delimited JSON for automation. |\n| `flakes auth status` | Show whether the stored CLI credential is authenticated, expired, or missing. |\n| `flakes auth status --json` | Emit structured credential status. |\n| `flakes auth logout` | Remove the stored CLI credential. |\n| `flakes auth logout --json` | Emit structured logout output. |\n\n### Local Runtime And Config\n\nThese commands are mostly for local development, smoke checks, or authoring\nruntime config files. The hosted path usually starts with auth and host setup.\n\n| Command | Use |\n| --- | --- |\n| `flakes server --config <server.toml>` | Validate config, open the PostgreSQL store, and start the control-plane server. `-c` is also accepted. |\n| `flakes server --config <server.toml> --host 127.0.0.1 --port 7733 --dry-run` | Validate server config and print a redacted JSON summary without starting the daemon. |\n| `flakes sandbox --config <sandbox.toml>` | Validate config, load adapters, and start the sandbox daemon. `-c` is also accepted. |\n| `flakes sandbox --config <sandbox.toml> --dry-run` | Validate sandbox config and print the daemon descriptor without opening a control-plane stream. |\n| `flakes down --session flakes --dry-run --json` | Stop or preview stopping a local tmux runtime session. |\n| `flakes config schema` | Print annotated TOML examples for server and sandbox config. |\n| `flakes config schema server` | Print only the server config example. `sandbox` is also supported. |\n\n### Projects\n\n| Command | Use |\n| --- | --- |\n| `flakes projects create --key <project-key> --name <name>` | Create or idempotently read an active Project namespace for new runs. |\n| `flakes projects list` | List Projects owned by the authenticated account, including archived Projects. |\n| `flakes projects archive <project-key>` | Archive a Project so new runs and host bindings cannot use it. Existing history remains visible. |\n| `flakes projects bind-host <project-key> --host <host-id> --pool <pool-key>` | Bind a Project to a host pool. Repeat `--pool` to allow more than one pool on the same host. |\n\nProject keys are lowercase path-safe names. They are used for hosted identity\nand for the host-local directory under each configured project root.\n\n### Host Setup And Operation\n\n| Command | Use |\n| --- | --- |\n| `flakes host setup --config <host.toml>` | Create a host and first host-scoped credential through direct CLI user auth, then write the host config. |\n| `flakes host setup --config <host.toml> --credential-file <path> --state-dir <dir> --host-name <name>` | Override the credential file, state directory, or displayed host name. |\n| `flakes host setup --config <host.toml> --no-open --timeout-ms 600000` | Run setup on a remote shell and let the embedded device-login flow wait longer for approval. |\n| `flakes host setup --config <host.toml> --json` | Emit structured setup output with redacted host and credential summaries. The raw credential is not printed. |\n| `flakes host rotate --config <host.toml>` | Request a new host credential, write it to the configured credential file, and retire the replaced credential. Restart the host process afterward. |\n| `flakes host rotate --config <host.toml> --json` | Emit structured rotation output, including the new credential summary and next steps. The raw credential is not printed. |\n| `flakes host project-root set --config <host.toml> --path <absolute-root>` | Store the host-local project root on the hosted control plane. The server stores the path but does not inspect the host filesystem. |\n| `flakes host run --config <host.toml>` | Start the host runtime and connect capacity to Flakes. This process should stay running. |\n| `flakes host status --config <host.toml>` | Validate local config and, when a CLI credential is available, read remote host, pool, and credential status. |\n| `flakes host status --config <host.toml> --json` | Emit structured local and remote status. |\n\nSetup writes new files only when the target config and credential file do not\nalready exist. Setup and rotation require an authenticated CLI user credential\nfor the same hosted origin; they are direct user bearer auth flows, not console\nproxy flows.\n\n### Runs\n\n| Command | Use |\n| --- | --- |\n| `flakes runs create --project <project-key> --key <run-key> --name \"Release notes\"` | Create or reuse a run identified by a stable run key inside an active Project. |\n| `flakes runs create --project <project-key> --key <run-key> --name \"Release notes\" --token <token>` | Create a run using an explicit automation bearer token instead of the stored CLI credential. `-t` is also accepted. |\n| `flakes runs close <run-key>` | Close the run so no more top-level tasks can be admitted. |\n| `flakes runs close <run-key> --wait --timeout-ms 600000` | Close the run and poll until the run reaches a terminal state or the timeout expires. |\n| `flakes runs close <run-key> --token <token>` | Close a run using an explicit automation bearer token. `-t` is also accepted. |\n| `flakes inspect <run-id-or-key>` | Read a run. A non-`run_` value is treated as a run key. |\n| `flakes inspect <task-id> --task` | Read a task explicitly. |\n| `flakes logs <task-id> --after <cursor> --limit <n>` | Read bounded task logs. |\n| `flakes metrics <run-id>` | Read run metrics. |\n\n`runs`, `inspect`, `logs`, and `metrics` accept `--token <token>` or `-t\n<token>` when trusted automation should bypass the stored CLI credential.\n\n### Tasks\n\n| Command | Use |\n| --- | --- |\n| `flakes tasks save --run <run-key> --key <task-key> --title \"Draft\" --adapter pi --body \"Write the draft.\"` | Save or update a not-yet-admitted task. |\n| `flakes tasks save --run <run-key> --key <task-key> --title \"Draft\" --adapter pi --body-file prompt.md --required-capability pi --depends-on outline` | Save a task with a file body, capability requirement, and dependency. |\n| `flakes tasks save --run <run-key> --key <task-key> --title \"Plan\" --adapter harness --harness-file harnesses/paper-writer.ts --tool-grant flakes.tasks.spawn` | Submit a harness module as a normal task. |\n| `flakes tasks admit --run <run-key> <task-key>` | Admit specific saved tasks for scheduling. |\n| `flakes tasks admit --run <run-key> --all` | Admit all saved tasks that are ready for admission. |\n\nTask save accepts `--acceptance`, `--depends-on`, `--required-capability`, and\n`--tool-grant` more than once. `--harness-file` requires `--adapter harness`.\nTask commands that call the hosted API accept `--token <token>` or `-t <token>`\nfor trusted automation.\n\n### Workpads And File Reservations\n\n| Command | Use |\n| --- | --- |\n| `flakes tasks workpad show <task-id>` | Read a task workpad as JSON. |\n| `flakes tasks workpad show <task-id> --raw` | Print only the Markdown body. |\n| `flakes tasks workpad save <task-id> --file <workpad.md> --base-version <version>` | Save a workpad with an optimistic version check. `-f` is also accepted for `--file`. |\n| `flakes tasks workpad template <task-id> --output <workpad.md>` | Create a local Markdown template for editing. `-o` is also accepted. |\n| `flakes tasks workpad pull` | Inside a running Flakes task, pull the assignment-local workpad into the thread state directory. |\n| `flakes tasks workpad push` | Inside a running Flakes task, push the assignment-local workpad with its saved base version. |\n| `flakes tasks files reserve <path...> --reason \"editing\" --json` | Inside a running task, reserve assignment-scoped file paths before editing. |\n| `flakes tasks files reserve <path...> --prefix --json` | Reserve path prefixes instead of exact paths. |\n| `flakes tasks files release <path...> --json` | Release assignment-scoped file reservations. |\n| `flakes tasks files release <path...> --prefix --json` | Release prefix reservations instead of exact-path reservations. |\n| `flakes tasks files release --all --json` | Release all reservations owned by the current assignment. |\n| `flakes tasks files list --json` | List current assignment file reservations. |\n| `flakes tasks files check <path...> --json` | Check whether paths conflict with existing reservations. |\n| `flakes tasks files check <path...> --prefix --json` | Check prefix selectors for conflicts. |\n\nThe `pull`, `push`, and `files` commands are attached to a running task through\nthread-local environment variables. They fail outside a running Flakes task.\n\n### Messages And Permissions\n\nMessages and permission responses do not have standalone top-level CLI commands.\nUse the console controls when available, or call the selected API routes:\n\n| Route | Use |\n| --- | --- |\n| `POST /v1/tasks/:taskId/messages` | Send a `follow_up` or `steer` message to a running task. |\n| `POST /v1/tasks/:taskId/permissions/:permissionRequestId/respond` | Answer a task permission request with `approved` or `denied`. |\n\nBoth routes require the task to be running on a connected sandbox. See\n[Observing And Steering](/docs/observe-and-steer) for user-facing behavior.\n\n### Harness Checks\n\n| Command | Use |\n| --- | --- |\n| `flakes harness init --template paper --dir harnesses` | Create a starter harness module. |\n| `flakes harness init --template review-revise --dir harnesses --file review.ts --force` | Write a specific template and overwrite the target file. |\n| `flakes harness check harnesses/paper-writer.ts` | Typecheck and validate a harness module before submission. |\n| `flakes harness check harnesses/paper-writer.ts --defaults harnesses/defaults.json --json` | Check with adapter/agent defaults and emit structured diagnostics. |\n\nCurrent template names are `paper`, `review-revise`, `fanout-fanin`,\n`autowrite`, and `autoresearch`.\n\n### Artifacts\n\n| Command | Use |\n| --- | --- |\n| `flakes artifacts create --file artifact.json` | Create artifact metadata, optionally with inline bytes in the JSON payload. `-f` is also accepted. |\n| `flakes artifacts get <artifact-id>` | Read artifact metadata. |\n| `flakes artifacts fetch <artifact-id> --location-id <location-id>` | Fetch a specific artifact location when more than one location is available. |\n| `flakes artifacts fetch <artifact-id> --output <file>` | Fetch artifact bytes to a file. `-o` is also accepted. |\n| `flakes artifacts fetch <artifact-id> --raw` | Write exact artifact bytes to stdout. |\n\nArtifact commands accept `--token <token>` or `-t <token>` for trusted\nautomation.\n\n## Host Config Reference\n\n`flakes host setup` writes a starter Host config TOML file. Add at least one\npool before running `flakes host run`.\n\nHost config TOML describes host identity, credentials, state, and capacity\npools. Host TOML pools do not contain `workspace`; the project workspace root\nis stored in the control plane with `flakes host project-root set`.\nThe project workspace root is stored in the control plane, not in Host TOML.\n\n```toml\ncontrolPlaneUrl = \"https://flakes.dev\"\nhostId = \"host_abc123\"\ncredentialFile = \"/Users/me/.config/flakes/host.credential\"\nstateDir = \"/Users/me/.config/flakes/state\"\n\n[[pools]]\npoolKey = \"mac-coding\"\nmatchlockImage = \"registry.example/flakes/macos:latest\"\nmounts = [\"/Users/me/.cache/flakes:/cache\"]\nadapter = \"pi\"\nmaxInstances = 2\nmaxConcurrency = 1\nadvertisedCapabilities = [\"pi\", \"node\", \"mac\"]\n\n[pools.resourceBounds]\nmemoryMb = 8192\ncpus = 4\n\n[pools.env]\nEXAMPLE = \"value\"\n\n[pools.executablePaths]\nmatchlock = \"/usr/local/bin/matchlock\"\nflakes = \"/usr/local/bin/flakes\"\n```\n\n### Top-Level Fields\n\n| Field | Required | Meaning |\n| --- | --- | --- |\n| `controlPlaneUrl` | Yes | Hosted API origin. Host setup writes `https://flakes.dev`. |\n| `hostId` | Yes | Host identity returned by setup. It must be a non-empty identifier. |\n| `credentialFile` | Yes | Absolute path to the host-scoped credential file. `credentialFile must be an absolute path`; it must be a regular file owned by the current user, not a symlink, with `0600` permissions. |\n| `stateDir` | No | Absolute private directory for host runtime state. When omitted, it defaults beside the credential file. The runtime also creates a generated sandbox config directory under this state directory. |\n| `pools` | Yes | One to 64 pool definitions. A config with no pools is invalid for `flakes host run`. |\n\n### Pool Fields\n\n| Field | Required | Meaning |\n| --- | --- | --- |\n| `poolKey` | Yes | Stable pool identifier advertised to Flakes. Must be unique within the host config. |\n| `provider` | Implied | The current provider is `matchlock`. It is advertised as `provider: \"matchlock\"`; it is not a required TOML field. |\n| `matchlockImage` | Yes | Local MatchLock image or template used by the host to launch sandboxes. This is local-only and is not sent in the sanitized pool advertisement. |\n| `mounts` | No | Local mount strings passed to the provider. These stay on the host. |\n| `adapter` | Yes | Adapter the sandbox should run, such as `pi` or `harness`. This is advertised for scheduling. |\n| `maxInstances` | Yes | Positive integer limit for provider instances in the pool. |\n| `maxConcurrency` | Yes | Positive integer limit for concurrent work in each advertised sandbox config. |\n| `advertisedCapabilities` | Yes | Up to 64 scheduling capability strings, such as `pi`, `node`, or `mac`. These become advertised as `capabilities`. |\n| `resourceBounds` | No | Small sanitized record for scheduler-facing bounds, such as CPU or memory. Oversized or unsafe records are rejected. |\n| `env` | No | Local environment variables for provider startup. These are local-only and are not advertised. |\n| `executablePaths.matchlock` | Yes | Absolute path to the MatchLock executable. It must exist, be a file, be executable, and not be a symlink. |\n| `executablePaths.<name>` | No | Additional executable paths, for example `flakes`. These are local-only. |\n\n### Sanitized Pool Advertisement\n\nThe host sends only a sanitized pool advertisement to the control plane:\n\n- `poolKey`\n- `provider`\n- `adapter`\n- `maxInstances`\n- `maxConcurrency`\n- `capabilities`\n- sanitized `resourceBounds`, when present\n\nLocal-only fields stay on the host: `matchlockImage`, `mounts`, `env`,\n`credentialFile`, `stateDir`, `executablePaths`, and the derived Project\nworkspace paths. Do not rely on those fields appearing in the console or API\npool responses.\n\n`workspace` is rejected inside `[[pools]]`. Configure Project placement with\n`PUT /v1/hosts/:hostId/project-workspace-root` or\n`flakes host project-root set`, then bind Projects to allowed pool keys.\n\n## Selected API Reference\n\nThis section is for integrators. Ordinary users should prefer the console and\nCLI workflows above. Unless noted otherwise, routes use `/v1`, require a user\nbearer credential for the same hosted origin, and are scoped to the authenticated\nowner.\n\n### Projects\n\n| Route | Use |\n| --- | --- |\n| `GET /v1/projects` | List owned Projects. Archived Projects remain visible unless a client filters them. |\n| `PUT /v1/projects/:projectKey` | Create or idempotently read a Project. Body includes `projectKey`, `name`, and optional user metadata. |\n| `GET /v1/projects/:projectKey` | Read one owned Project by key. |\n| `PATCH /v1/projects/:projectKey` | Update safe Project display fields such as `name` and user metadata. The key is immutable. |\n| `POST /v1/projects/:projectKey/archive` | Archive an owned Project. Archived Projects cannot be used for new run creation or new host bindings. |\n\nProject DTOs include `projectId`, `projectKey`, `name`, `status`, timestamps,\nand user metadata. Project identity is stored as Project fields on runs and\ntasks; do not encode it into a generic metadata value.\n\n### Runs And Tasks\n\n| Route | Use |\n| --- | --- |\n| `PUT /v1/runs/:runKey` | Create or idempotently read a Project-scoped run by stable key. Body includes `name` and either `projectKey` or `projectId`. |\n| `GET /v1/runs?projectKey=<project-key>&state=<state>&cursor=<cursor>&limit=<n>` | List owned runs, optionally filtered by Project key and state. |\n| `GET /v1/runs/:runId` | Read one owned run by run ID. |\n| `DELETE /v1/runs/:runId` | Delete an owned run after cancel delivery is attempted for live tasks. |\n| `POST /v1/runs/:runKey/close` | Close a run so no more top-level work can be admitted. |\n| `GET /v1/runs/:runId/tasks` | List tasks with workpad metadata for console task overview screens. |\n| `PUT /v1/runs/:runKey/tasks/:taskKey` | Save a task before admission. Body includes task metadata, target adapter, input, dependencies, capabilities, and grants. |\n| `POST /v1/runs/:runKey/tasks/admit` | Admit selected task keys or all saved tasks. |\n| `GET /v1/tasks/:taskId` | Read one task. |\n| `POST /v1/tasks/:taskId/cancel` | Request cancellation for a live task and record task state. |\n| `GET /v1/tasks/:taskId/logs` | Read bounded task logs. |\n| `GET /v1/tasks/:taskId/activity` | Read activity events such as workpad updates, human input, and permission events. |\n\n### Workpads, Messages, And Permissions\n\n| Route | Use |\n| --- | --- |\n| `GET /v1/tasks/:taskId/workpad` | Read the current task workpad. |\n| `PUT /v1/tasks/:taskId/workpad` | Save Markdown with `bodyMarkdown` and `baseVersion`. A stale version returns `workpad_version_conflict` with the current workpad. Workpads are limited to 512 KiB. |\n| `POST /v1/tasks/:taskId/messages` | Queue `follow_up` or `steer` input for a running task. Messages must be non-empty and at most 20000 characters. |\n| `POST /v1/tasks/:taskId/permissions/:permissionRequestId/respond` | Send `approved` or `denied` for a permission request. A request accepts only one answer and must still belong to the active assignment. |\n| `GET /v1/tasks/:taskId/rounds/:roundKey/outputs/:outputKey/fetch` | Read a bounded JSON or text live-round output. |\n| `GET /v1/tasks/:taskId/rounds/:roundKey/outputs/:outputKey/workspace` | Resolve a live-round workspace output handle. |\n\n### Hosts\n\n| Route | Use |\n| --- | --- |\n| `GET /v1/hosts` | List owned hosts. |\n| `POST /v1/hosts` | Create a host record directly for integrator workflows that do not need the CLI to mint a local host credential. |\n| `POST /v1/hosts/setup` | Create a host and its first host-scoped credential in one transaction. Requires direct user bearer auth and returns the raw credential exactly once for CLI persistence. |\n| `GET /v1/hosts/:hostId` | Read one owned host. |\n| `PATCH /v1/hosts/:hostId` | Update safe display fields and user metadata. Runtime, adapter, path, env, image, provider, and status metadata keys are rejected. |\n| `PUT /v1/hosts/:hostId/project-workspace-root` | Store an absolute host-local Project root. The control plane stores the string and does not perform filesystem checks. |\n| `PUT /v1/hosts/:hostId/project-bindings/:projectKey` | Bind an active owned Project to one or more existing pool keys on the owned host. Body includes `poolKeys`. |\n| `GET /v1/hosts/:hostId/project-bindings` | List Project bindings for the host, including derived `workspacePath`, allowed `poolKeys`, availability, and validation reason. |\n| `POST /v1/hosts/:hostId/disable` | Disable a host. Disabled hosts cannot claim new work. |\n| `DELETE /v1/hosts/:hostId` | Delete a host only when active lifecycle state no longer blocks deletion. |\n| `GET /v1/hosts/:hostId/pools` | Read pools synced from the running host. There is no user-facing pool write route; edit host TOML and restart or reconnect the host. |\n| `GET /v1/hosts/:hostId/credentials` | List redacted host credential summaries. |\n| `GET /v1/hosts/:hostId/credentials/:hostCredentialId` | Read one redacted host credential summary. |\n| `POST /v1/hosts/:hostId/credentials/rotate` | Rotate a host credential. Requires direct user bearer auth and returns the raw replacement credential once. |\n| `POST /v1/hosts/:hostId/credentials/:hostCredentialId/revoke` | Revoke a host credential. |\n\nHost setup and credential rotation require direct user bearer auth. Do not send\nthose requests through the browser console proxy.\n\n### Artifacts And Run Outputs\n\n| Route | Use |\n| --- | --- |\n| `POST /v1/artifacts` | Create artifact metadata and optional inline bytes. |\n| `GET /v1/artifacts/:artifactId` | Read artifact metadata. |\n| `GET /v1/artifacts/:artifactId/fetch` | Fetch artifact bytes. |\n| `GET /v1/runs/:runId/artifacts` | List artifacts associated with a run. |\n| `GET /v1/runs/:runId/history.jsonl` | Export redacted run history as JSONL. |\n| `GET /v1/runs/:runId/file-reservations` | List file reservations visible for the run. |\n| `GET /v1/runs/:runId/metrics` | Read evaluation metrics for the run. |\n\nSandbox-scoped workspace, group, and live-round routes are runtime surfaces for\nadapters and harness execution. Integrators should normally use the CLI,\nselected client routes, or Harness SDK helpers instead of calling those routes\ndirectly.\n\n## Relevant Exports\n\nThe hosted API and CLI are the primary user boundary. These exports are useful\nonly for integrations, harness modules, adapters, or repository-local tooling.\n\n| Export | Use |\n| --- | --- |\n| `@flakes/harness-sdk` | Harness authors import `defineHarness`, use `HarnessContext`, and call helpers such as `ctx.group(...)`, `ctx.groups.open(...)`, `ctx.output.json(...)`, `ctx.outputs.readJson(...)`, `ctx.workpads.read(...)`, `ctx.workspace.commit(...)`, `ctx.workspace.promote(...)`, and `ctx.liveTasks.send(...)`. |\n| `@flakes/core` | Integrators that build typed payloads can reuse schemas and types for run/task IDs, saved tasks, task metadata, task groups, task spawn requests, workpads, file reservations, and workspace handles. Common names include `WorkspaceHandle`, `WorkspaceHandleSchema`, `TaskProductMetadataSchema`, and `TaskWorkpadPutRequestSchema`. |\n| `@flakes/protocol` | Runtime implementers can parse and validate sandbox and host stream messages with protocol schemas and safe parse helpers. Ordinary API clients do not need these types. |\n| `@flakes/cli` | Test harnesses or wrappers can call `runCli(...)` with injected IO and transport dependencies instead of shelling out. The installed binary remains `flakes`. |\n\nDo not treat this table as a package architecture guide. It lists only the\nexports a user, harness author, or integrator might reasonably need.\n";
|
|
2220
|
+
var reference_default = "---\ntitle: Reference\ndescription: CLI commands, host configuration, selected API routes, and integrator exports for hosted Flakes.\n---\n\nUse this page after you understand the main workflows. It is a lookup for the\nhosted console at `https://flakes.dev`, the `flakes` CLI, user-supplied hosts,\nand selected integration surfaces.\n\nFor first-run steps, start with [Installing and Authorizing the CLI](/docs/cli).\nFor host setup, see [Connecting Your Hosts](/docs/connect-a-host).\n\n## CLI Command Reference\n\nCLI commands target the hosted control plane at `https://flakes.dev`. Most\ncommands use the stored credential from `flakes auth login`; commands that also\naccept `--token` are mainly for trusted automation.\n\n### Auth\n\n| Command | Use |\n| --- | --- |\n| `flakes auth login` | Start device authorization, open the browser approval page, and save the CLI credential. |\n| `flakes auth login --no-open` | Print the verification URL and user code without opening a browser. Useful on remote shells. |\n| `flakes auth login --timeout-ms 600000` | Wait longer for browser approval. |\n| `flakes auth login --json` | Emit the device-code and authenticated records as newline-delimited JSON for automation. |\n| `flakes auth status` | Show whether the stored CLI credential is authenticated, expired, or missing. |\n| `flakes auth status --json` | Emit structured credential status. |\n| `flakes auth logout` | Remove the stored CLI credential. |\n| `flakes auth logout --json` | Emit structured logout output. |\n\n### Local Runtime And Config\n\nThese commands are mostly for local development, smoke checks, or authoring\nruntime config files. The hosted path usually starts with auth and host setup.\n\n| Command | Use |\n| --- | --- |\n| `flakes server --config <server.toml>` | Validate config, open the PostgreSQL store, and start the control-plane server. `-c` is also accepted. |\n| `flakes server --config <server.toml> --host 127.0.0.1 --port 7733 --dry-run` | Validate server config and print a redacted JSON summary without starting the daemon. |\n| `flakes sandbox --config <sandbox.toml>` | Validate config, load adapters, and start the sandbox daemon. `-c` is also accepted. |\n| `flakes sandbox --config <sandbox.toml> --dry-run` | Validate sandbox config and print the daemon descriptor without opening a control-plane stream. |\n| `flakes down --session flakes --dry-run --json` | Stop or preview stopping a local tmux runtime session. |\n| `flakes config schema` | Print annotated TOML examples for server and sandbox config. |\n| `flakes config schema server` | Print only the server config example. `sandbox` is also supported. |\n\n### Projects\n\n| Command | Use |\n| --- | --- |\n| `flakes projects create --key <project-key> --name <name>` | Create or idempotently read an active Project namespace for new runs. |\n| `flakes projects list` | List Projects owned by the authenticated account, including archived Projects. |\n| `flakes projects archive <project-key>` | Archive a Project so new runs and host bindings cannot use it. Existing history remains visible. |\n| `flakes projects bind-host <project-key> --host <host-id> --pool <pool-key>` | Bind a Project to a host pool. Repeat `--pool` to allow more than one pool on the same host. |\n\nProject keys are lowercase path-safe names. They are used for hosted identity\nand for the host-local directory under each configured project root.\n\n### Host Setup And Operation\n\n| Command | Use |\n| --- | --- |\n| `flakes host setup --config <host.toml>` | Create a host and first host-scoped credential through direct CLI user auth, then write the host config. |\n| `flakes host setup --config <host.toml> --credential-file <path> --state-dir <dir> --host-name <name>` | Override the credential file, state directory, or displayed host name. |\n| `flakes host setup --config <host.toml> --no-open --timeout-ms 600000` | Run setup on a remote shell and let the embedded device-login flow wait longer for approval. |\n| `flakes host setup --config <host.toml> --json` | Emit structured setup output with redacted host and credential summaries. The raw credential is not printed. |\n| `flakes host rotate --config <host.toml>` | Request a new host credential, write it to the configured credential file, and retire the replaced credential. Restart the host process afterward. |\n| `flakes host rotate --config <host.toml> --json` | Emit structured rotation output, including the new credential summary and next steps. The raw credential is not printed. |\n| `flakes host project-root set --config <host.toml> --path <absolute-root>` | Store the host-local project root on the hosted control plane. The server stores the path but does not inspect the host filesystem. |\n| `flakes host run --config <host.toml>` | Start the host runtime and connect capacity to Flakes. This process should stay running. |\n| `flakes host status --config <host.toml>` | Validate local config and, when a CLI credential is available, read remote host, pool, and credential status. |\n| `flakes host status --config <host.toml> --json` | Emit structured local and remote status. |\n\nSetup writes new files only when the target config and credential file do not\nalready exist. Setup and rotation require an authenticated CLI user credential\nfor the same hosted origin; they are direct user bearer auth flows, not console\nproxy flows.\n\n### Runs\n\n| Command | Use |\n| --- | --- |\n| `flakes runs create --project <project-key> --key <run-key> --name \"Release notes\"` | Create or reuse a run identified by a stable run key inside an active Project. |\n| `flakes runs create --project <project-key> --key <run-key> --name \"Release notes\" --token <token>` | Create a run using an explicit automation bearer token instead of the stored CLI credential. `-t` is also accepted. |\n| `flakes runs close <run-key>` | Close the run so no more top-level tasks can be admitted. |\n| `flakes runs close <run-key> --wait --timeout-ms 600000` | Close the run and poll until the run reaches a terminal state or the timeout expires. |\n| `flakes runs close <run-key> --token <token>` | Close a run using an explicit automation bearer token. `-t` is also accepted. |\n| `flakes inspect <run-id-or-key>` | Read a run. A non-`run_` value is treated as a run key. |\n| `flakes inspect <task-id> --task` | Read a task explicitly. |\n| `flakes logs <task-id> --after <cursor> --limit <n>` | Read bounded task logs. |\n| `flakes metrics <run-id>` | Read run metrics. |\n\n`runs`, `inspect`, `logs`, and `metrics` accept `--token <token>` or `-t\n<token>` when trusted automation should bypass the stored CLI credential.\n\n### Tasks\n\n| Command | Use |\n| --- | --- |\n| `flakes tasks save --run <run-key> --key <task-key> --title \"Draft\" --adapter pi --body \"Write the draft.\"` | Save or update a not-yet-admitted task. |\n| `flakes tasks save --run <run-key> --key <task-key> --title \"Draft\" --adapter pi --body-file prompt.md --required-capability pi --depends-on outline` | Save a task with a file body, capability requirement, and dependency. |\n| `flakes tasks save --run <run-key> --key <task-key> --title \"Plan\" --adapter harness --harness-file harnesses/paper-writer.ts --tool-grant flakes.tasks.spawn` | Submit a harness module as a normal task. |\n| `flakes tasks admit --run <run-key> <task-key>` | Admit specific saved tasks for scheduling. |\n| `flakes tasks admit --run <run-key> --all` | Admit all saved tasks that are ready for admission. |\n\nTask save accepts `--acceptance`, `--depends-on`, `--required-capability`, and\n`--tool-grant` more than once. `--harness-file` requires `--adapter harness`.\nTask commands that call the hosted API accept `--token <token>` or `-t <token>`\nfor trusted automation.\n\n### Workpads And File Reservations\n\n| Command | Use |\n| --- | --- |\n| `flakes tasks workpad show <task-id>` | Read a task workpad as JSON. |\n| `flakes tasks workpad show <task-id> --raw` | Print only the Markdown body. |\n| `flakes tasks workpad save <task-id> --file <workpad.md> --base-version <version>` | Save a workpad with an optimistic version check. `-f` is also accepted for `--file`. |\n| `flakes tasks workpad template <task-id> --output <workpad.md>` | Create a local Markdown template for editing. `-o` is also accepted. |\n| `flakes tasks workpad pull` | Inside a running Flakes task, pull the assignment-local workpad into the thread state directory. |\n| `flakes tasks workpad push` | Inside a running Flakes task, push the assignment-local workpad with its saved base version. |\n| `flakes tasks files reserve <path...> --reason \"editing\" --json` | Inside a running task, reserve assignment-scoped file paths before editing. |\n| `flakes tasks files reserve <path...> --prefix --json` | Reserve path prefixes instead of exact paths. |\n| `flakes tasks files release <path...> --json` | Release assignment-scoped file reservations. |\n| `flakes tasks files release <path...> --prefix --json` | Release prefix reservations instead of exact-path reservations. |\n| `flakes tasks files release --all --json` | Release all reservations owned by the current assignment. |\n| `flakes tasks files list --json` | List current assignment file reservations. |\n| `flakes tasks files check <path...> --json` | Check whether paths conflict with existing reservations. |\n| `flakes tasks files check <path...> --prefix --json` | Check prefix selectors for conflicts. |\n\nThe `pull`, `push`, and `files` commands are attached to a running task through\nthread-local environment variables. They fail outside a running Flakes task.\n\n### Messages And Permissions\n\nMessages and permission responses do not have standalone top-level CLI commands.\nUse the console controls when available, or call the selected API routes:\n\n| Route | Use |\n| --- | --- |\n| `POST /v1/tasks/:taskId/messages` | Send a `follow_up` or `steer` message to a running task. |\n| `POST /v1/tasks/:taskId/permissions/:permissionRequestId/respond` | Answer a task permission request with `approved` or `denied`. |\n\nBoth routes require the task to be running on a connected sandbox. See\n[Observing And Steering](/docs/observe-and-steer) for user-facing behavior.\n\n### Harness Checks\n\n| Command | Use |\n| --- | --- |\n| `flakes harness init --template paper --dir harnesses` | Create a starter harness module. |\n| `flakes harness init --template review-revise --dir harnesses --file review.ts --force` | Write a specific template and overwrite the target file. |\n| `flakes harness check harnesses/paper-writer.ts` | Typecheck and validate a harness module before submission. |\n| `flakes harness check harnesses/paper-writer.ts --defaults harnesses/defaults.json --json` | Check with adapter/agent defaults and emit structured diagnostics. |\n\nCurrent template names are `paper`, `review-revise`, `fanout-fanin`,\n`autowrite`, and `autoresearch`.\n\n### Artifacts\n\n| Command | Use |\n| --- | --- |\n| `flakes artifacts create --file artifact.json` | Create artifact metadata, optionally with inline bytes in the JSON payload. `-f` is also accepted. |\n| `flakes artifacts get <artifact-id>` | Read artifact metadata. |\n| `flakes artifacts fetch <artifact-id> --location-id <location-id>` | Fetch a specific artifact location when more than one location is available. |\n| `flakes artifacts fetch <artifact-id> --output <file>` | Fetch artifact bytes to a file. `-o` is also accepted. |\n| `flakes artifacts fetch <artifact-id> --raw` | Write exact artifact bytes to stdout. |\n\nArtifact commands accept `--token <token>` or `-t <token>` for trusted\nautomation.\n\n## Host Config Reference\n\n`flakes host setup` writes a starter Host config TOML file. Add at least one\npool before running `flakes host run`.\n\nHost config TOML describes host identity, credentials, state, and capacity\npools. Host TOML pools do not contain `workspace`; the project workspace root\nis stored in the control plane with `flakes host project-root set`.\nThe project workspace root is stored in the control plane, not in Host TOML.\n\n```toml\ncontrolPlaneUrl = \"https://flakes.dev\"\nhostId = \"host_abc123\"\ncredentialFile = \"/Users/me/.config/flakes/host.credential\"\nstateDir = \"/Users/me/.config/flakes/state\"\n\n[[pools]]\npoolKey = \"mac-coding\"\nmatchlockImage = \"registry.example/flakes/macos:latest\"\nmounts = [\"/Users/me/.cache/flakes:/cache\"]\nadapter = \"pi\"\nmaxInstances = 2\nmaxConcurrency = 1\nadvertisedCapabilities = [\"pi\", \"node\", \"mac\"]\n\n[pools.resourceBounds]\nmemoryMb = 8192\ncpus = 4\n\n[pools.env]\nEXAMPLE = \"value\"\n\n[pools.executablePaths]\nmatchlock = \"/usr/local/bin/matchlock\"\nflakes = \"/usr/local/bin/flakes\"\n```\n\n### Top-Level Fields\n\n| Field | Required | Meaning |\n| --- | --- | --- |\n| `controlPlaneUrl` | Yes | Hosted API origin. Host setup writes `https://flakes.dev`. |\n| `hostId` | Yes | Host identity returned by setup. It must be a non-empty identifier. |\n| `credentialFile` | Yes | Absolute path to the host-scoped credential file. `credentialFile must be an absolute path`; it must be a regular file owned by the current user, not a symlink, with `0600` permissions. |\n| `stateDir` | No | Absolute private directory for host runtime state. When omitted, it defaults beside the credential file. The runtime also creates a generated sandbox config directory under this state directory. |\n| `pools` | Yes | One to 64 pool definitions. A config with no pools is invalid for `flakes host run`. |\n\n### Pool Fields\n\n| Field | Required | Meaning |\n| --- | --- | --- |\n| `poolKey` | Yes | Stable pool identifier advertised to Flakes. Must be unique within the host config. |\n| `provider` | Implied | The current provider is `matchlock`. It is advertised as `provider: \"matchlock\"`; it is not a required TOML field. |\n| `matchlockImage` | Yes | Local MatchLock image or template used by the host to launch sandboxes. This is local-only and is not sent in the sanitized pool advertisement. |\n| `mounts` | No | Local mount strings passed to the provider. These stay on the host. |\n| `adapter` | Yes | Adapter the sandbox should run, such as `pi` or `harness`. This is advertised for scheduling. |\n| `maxInstances` | Yes | Positive integer limit for provider instances in the pool. |\n| `maxConcurrency` | Yes | Positive integer limit for concurrent work in each advertised sandbox config. |\n| `advertisedCapabilities` | Yes | Up to 64 scheduling capability strings, such as `pi`, `node`, or `mac`. These become advertised as `capabilities`. |\n| `resourceBounds` | No | Small sanitized record for scheduler-facing bounds, such as CPU or memory. Oversized or unsafe records are rejected. |\n| `env` | No | Local environment variables for provider startup. These are local-only and are not advertised. |\n| `executablePaths.matchlock` | Yes | Absolute path to the MatchLock executable. It must exist, be a file, be executable, and not be a symlink. |\n| `executablePaths.<name>` | No | Additional executable paths, for example `flakes`. These are local-only. |\n\n### Sanitized Pool Advertisement\n\nThe host sends only a sanitized pool advertisement to the control plane:\n\n- `poolKey`\n- `provider`\n- `adapter`\n- `maxInstances`\n- `maxConcurrency`\n- `capabilities`\n- sanitized `resourceBounds`, when present\n\nLocal-only fields stay on the host: `matchlockImage`, `mounts`, `env`,\n`credentialFile`, `stateDir`, `executablePaths`, and the derived Project\nworkspace paths. Do not rely on those fields appearing in the console or API\npool responses.\n\n`workspace` is rejected inside `[[pools]]`. Configure Project placement with\n`PUT /v1/hosts/:hostId/project-workspace-root` or\n`flakes host project-root set`, then bind Projects to allowed pool keys.\n\n## Selected API Reference\n\nThis section is for integrators. Ordinary users should prefer the console and\nCLI workflows above. Unless noted otherwise, routes use `/v1`, require a user\nbearer credential for the same hosted origin, and are scoped to the authenticated\nowner.\n\n### Projects\n\n| Route | Use |\n| --- | --- |\n| `GET /v1/projects` | List owned Projects. Archived Projects remain visible unless a client filters them. |\n| `PUT /v1/projects/:projectKey` | Create or idempotently read a Project. Body includes `projectKey`, `name`, and optional user metadata. |\n| `GET /v1/projects/:projectKey` | Read one owned Project by key. |\n| `PATCH /v1/projects/:projectKey` | Update safe Project display fields such as `name` and user metadata. The key is immutable. |\n| `POST /v1/projects/:projectKey/archive` | Archive an owned Project. Archived Projects cannot be used for new run creation or new host bindings. |\n\nProject DTOs include `projectId`, `projectKey`, `name`, `status`, timestamps,\nand user metadata. Project identity is stored as Project fields on runs and\ntasks; do not encode it into a generic metadata value.\n\n### Runs And Tasks\n\n| Route | Use |\n| --- | --- |\n| `PUT /v1/runs/:runKey` | Create or idempotently read a Project-scoped run by stable key. Body includes `name` and either `projectKey` or `projectId`. |\n| `GET /v1/runs?projectKey=<project-key>&state=<state>&cursor=<cursor>&limit=<n>` | List owned runs, optionally filtered by Project key and state. |\n| `GET /v1/runs/:runId` | Read one owned run by run ID. |\n| `DELETE /v1/runs/:runId` | Delete an owned run after cancel delivery is attempted for live tasks. |\n| `POST /v1/runs/:runKey/close` | Close a run so no more top-level work can be admitted. |\n| `GET /v1/runs/:runId/tasks` | List tasks with workpad metadata for console task overview screens. |\n| `PUT /v1/runs/:runKey/tasks/:taskKey` | Save a task before admission. Body includes task metadata, target adapter, input, dependencies, capabilities, and grants. |\n| `POST /v1/runs/:runKey/tasks/admit` | Admit selected task keys or all saved tasks. |\n| `GET /v1/tasks/:taskId` | Read one task. |\n| `POST /v1/tasks/:taskId/cancel` | Request cancellation for a live task and record task state. |\n| `GET /v1/tasks/:taskId/logs` | Read bounded task logs. |\n| `GET /v1/tasks/:taskId/activity` | Read activity events such as workpad updates, human input, and permission events. |\n\n### Workpads, Messages, And Permissions\n\n| Route | Use |\n| --- | --- |\n| `GET /v1/tasks/:taskId/workpad` | Read the current task workpad. |\n| `PUT /v1/tasks/:taskId/workpad` | Save Markdown with `bodyMarkdown` and `baseVersion`. A stale version returns `workpad_version_conflict` with the current workpad. Workpads are limited to 512 KiB. |\n| `POST /v1/tasks/:taskId/messages` | Queue `follow_up` or `steer` input for a running task. Messages must be non-empty and at most 20000 characters. |\n| `POST /v1/tasks/:taskId/permissions/:permissionRequestId/respond` | Send `approved` or `denied` for a permission request. A request accepts only one answer and must still belong to the active assignment. |\n| `GET /v1/tasks/:taskId/rounds/:roundKey/outputs/:outputKey/fetch` | Read a bounded JSON or text live-round output. |\n| `GET /v1/tasks/:taskId/rounds/:roundKey/outputs/:outputKey/workspace` | Resolve a live-round workspace output handle. |\n\n### Hosts\n\n| Route | Use |\n| --- | --- |\n| `GET /v1/hosts` | List owned hosts. |\n| `POST /v1/hosts` | Create a host record directly for integrator workflows that do not need the CLI to mint a local host credential. |\n| `POST /v1/hosts/setup` | Create a host and its first host-scoped credential in one transaction. Requires direct user bearer auth and returns the raw credential exactly once for CLI persistence. |\n| `GET /v1/hosts/:hostId` | Read one owned host. |\n| `PATCH /v1/hosts/:hostId` | Update safe display fields and user metadata. Runtime, adapter, path, env, image, provider, and status metadata keys are rejected. |\n| `PUT /v1/hosts/:hostId/project-workspace-root` | Store an absolute host-local Project root. The control plane stores the string and does not perform filesystem checks. |\n| `PUT /v1/hosts/:hostId/project-bindings/:projectKey` | Bind an active owned Project to one or more existing pool keys on the owned host. Body includes `poolKeys`. |\n| `GET /v1/hosts/:hostId/project-bindings` | List Project bindings for the host, including derived `workspacePath`, allowed `poolKeys`, availability, and validation reason. |\n| `POST /v1/hosts/:hostId/disable` | Disable a host. Disabled hosts cannot claim new work. |\n| `DELETE /v1/hosts/:hostId` | Delete a host only when active lifecycle state no longer blocks deletion. |\n| `GET /v1/hosts/:hostId/pools` | Read pools synced from the running host. There is no user-facing pool write route; edit host TOML and restart or reconnect the host. |\n| `GET /v1/hosts/:hostId/credentials` | List redacted host credential summaries. |\n| `GET /v1/hosts/:hostId/credentials/:hostCredentialId` | Read one redacted host credential summary. |\n| `POST /v1/hosts/:hostId/credentials/rotate` | Rotate a host credential. Requires direct user bearer auth and returns the raw replacement credential once. |\n| `POST /v1/hosts/:hostId/credentials/:hostCredentialId/revoke` | Revoke a host credential. |\n\nHost setup and credential rotation require direct user bearer auth. Do not send\nthose requests through the browser console proxy.\n\n### Sandbox Fleet\n\n| Route | Use |\n| --- | --- |\n| `GET /v1/sandboxes` | List owned fleet entries, including lifecycle status and retained sandbox liveness status when present. |\n| `GET /v1/sandboxes/:sandboxId` | Read one owned fleet entry. Missing and wrong-owner sandboxes return `404`. |\n| `DELETE /v1/sandboxes/:sandboxId` | Delete a stale owned entry immediately when no provider resource remains, or queue provider cleanup when one does. Returns `deleted`, `cleanup_queued`, `404`, or `409 sandbox_delete_blocked`. |\n| `POST /v1/sandboxes/:sandboxId/drain` | Mark an owned running entry as draining and clear unaccepted assignments. |\n| `POST /v1/sandboxes/:sandboxId/stop` | Start the stop path for an owned provider-backed entry. |\n\nDelete is intentionally owner-scoped. A stale entry can be deleted when it has\nno live sandbox stream and no accepted running work. Entries in unsafe lifecycle\nstates return `409 sandbox_delete_blocked` with displayable blockers. If the\nentry still has a provider resource, Flakes marks it `deleting` and queues\nprovider cleanup; the Console keeps the row visible as `Cleanup queued` until\nthe cleanup succeeds and the durable row is removed.\n\nImmediate delete response:\n\n```json\n{\n \"status\": \"deleted\",\n \"sandboxId\": \"sandbox_123\",\n \"instanceId\": \"managed_instance_123\",\n \"clearedAssignments\": 0\n}\n```\n\nQueued cleanup response:\n\n```json\n{\n \"status\": \"cleanup_queued\",\n \"sandboxId\": \"sandbox_123\",\n \"instanceId\": \"managed_instance_123\",\n \"clearedAssignments\": 0\n}\n```\n\n### Artifacts And Run Outputs\n\n| Route | Use |\n| --- | --- |\n| `POST /v1/artifacts` | Create artifact metadata and optional inline bytes. |\n| `GET /v1/artifacts/:artifactId` | Read artifact metadata. |\n| `GET /v1/artifacts/:artifactId/fetch` | Fetch artifact bytes. |\n| `GET /v1/runs/:runId/artifacts` | List artifacts associated with a run. |\n| `GET /v1/runs/:runId/history.jsonl` | Export redacted run history as JSONL. |\n| `GET /v1/runs/:runId/file-reservations` | List file reservations visible for the run. |\n| `GET /v1/runs/:runId/metrics` | Read evaluation metrics for the run. |\n\nSandbox-scoped workspace, group, and live-round routes are runtime surfaces for\nadapters and harness execution. Integrators should normally use the CLI,\nselected client routes, or Harness SDK helpers instead of calling those routes\ndirectly.\n\n## Relevant Exports\n\nThe hosted API and CLI are the primary user boundary. These exports are useful\nonly for integrations, harness modules, adapters, or repository-local tooling.\n\n| Export | Use |\n| --- | --- |\n| `@flakes/harness-sdk` | Harness authors import `defineHarness`, use `HarnessContext`, and call helpers such as `ctx.group(...)`, `ctx.groups.open(...)`, `ctx.output.json(...)`, `ctx.outputs.readJson(...)`, `ctx.workpads.read(...)`, `ctx.workspace.commit(...)`, `ctx.workspace.promote(...)`, and `ctx.liveTasks.send(...)`. |\n| `@flakes/core` | Integrators that build typed payloads can reuse schemas and types for run/task IDs, saved tasks, task metadata, task groups, task spawn requests, workpads, file reservations, and workspace handles. Common names include `WorkspaceHandle`, `WorkspaceHandleSchema`, `TaskProductMetadataSchema`, and `TaskWorkpadPutRequestSchema`. |\n| `@flakes/protocol` | Runtime implementers can parse and validate sandbox and host stream messages with protocol schemas and safe parse helpers. Ordinary API clients do not need these types. |\n| `@flakes/cli` | Test harnesses or wrappers can call `runCli(...)` with injected IO and transport dependencies instead of shelling out. The installed binary remains `flakes`. |\n\nDo not treat this table as a package architecture guide. It lists only the\nexports a user, harness author, or integrator might reasonably need.\n";
|
|
2222
2221
|
//#endregion
|
|
2223
2222
|
//#region ../../docs/content/docs/run-work.mdx?raw
|
|
2224
2223
|
var run_work_default = "---\ntitle: Running Workflows\ndescription: Launching workflows, saving tasks, admitting ready work, and closing durable workflows.\n---\n\nThis section covers the Flakes workflow for creating and launching distributed\nagent workflows. Use it after you can sign in at `https://flakes.dev/console`,\nauthorize the CLI, create a Project, and see enough connected host capacity\nbound to that Project for the adapter you want to use.\n\n## The Model\n\nA Project is the work namespace for related runs and the host workspace root\nmapping used by task execution. Every new run belongs to exactly one active\nProject. Project identity is a first-class run field, not run metadata.\n\nA run is the durable container for one job inside a Project. It holds saved\ntasks, admitted tasks, dependencies, task status, workpads, activity, artifacts,\nand history. That durable task state lives in Flakes even if an agent process\nexits, a sandbox disconnects, or a transient agent process starts again on\nanother assignment.\n\nA saved task is a draft definition inside an open run. Save tasks while you are\nstill shaping the graph: title, Markdown body, acceptance criteria, target\nadapter, dependencies, required capabilities, and any grants needed by a\nplanner or harness. Saved tasks are not schedulable yet.\n\nAdmission turns saved tasks into durable runtime work. After a task is\nadmitted, treat it as immutable user intent: do not expect to edit, delete, or\nrewire it. Add another saved task before admission, or have an authorized\nrunning task append children through its granted runtime tools.\n\nClosing a run means no more top-level saved tasks should be admitted by the\nclient. Close does not stop work that is already admitted. With `--wait`, the\nCLI waits for the run to reach a terminal state or until the timeout expires.\nIf the timeout expires, the run can still continue in the console.\n\n## Create A Run\n\nThis example uses the hosted user-auth flow. It assumes the CLI is already\ninstalled and host capacity has been connected by you or your host operator.\n\n```bash\nflakes auth login\n\nflakes projects create --key alpha --name \"Alpha\"\n\nflakes runs create --project alpha --key release-notes --name \"Draft release notes\"\n\nflakes tasks save \\\n --run release-notes \\\n --key draft \\\n --title \"Draft release notes\" \\\n --adapter pi \\\n --body \"Read the shipped changes and draft concise release notes for users.\" \\\n --acceptance \"Notes describe user-visible changes\" \\\n --acceptance \"Open questions are listed at the end\" \\\n --required-capability pi\n\nflakes tasks save \\\n --run release-notes \\\n --key review \\\n --title \"Review release notes\" \\\n --adapter pi \\\n --body \"Review the draft for accuracy, missing risks, and unclear wording.\" \\\n --depends-on draft \\\n --acceptance \"Review comments are actionable\" \\\n --required-capability pi\n\nflakes tasks admit --run release-notes --all\nflakes runs close release-notes --wait --timeout-ms 600000\n```\n\nThe first command authorizes the CLI against `https://flakes.dev`. The Project\nis created under your account. The run is created inside that Project, the two\ntasks are saved under stable keys, and the `review` task depends on `draft`.\nAdmission makes both tasks part of the durable graph. The close command tells\nFlakes there is no more top-level work to add and then waits for the graph to\nsettle.\n\n## Shape The Graph\n\nUse dependencies only for real ordering requirements. A task with unsatisfied\ndependencies is not ready, even if capacity is available. In the example above,\n`review` waits until `draft` is terminal according to the dependency policy\nbefore it can run.\n\nUse required capabilities to keep work on compatible capacity. A task that\nrequires `pi` should only be assigned to connected capacity that advertises the\n`pi` capability and the matching adapter. The run Project must also be bound to\nthe host pool. If no connected host capacity can satisfy the Project, adapter,\nand required capabilities, the task stays queued.\n\nAcceptance criteria should be short, observable checks. The agent receives the\ntask title, body, and acceptance criteria as its brief, and the console shows\nthe same user-facing context on the task page.\n\n## Scheduling\n\nFlakes schedules admitted, ready tasks to connected host capacity. A host\nadvertises sanitized pool capacity: adapter, capabilities, and concurrency,\nnot local paths, secrets, mounts, or private execution details. The scheduler\nmatches each queued task against its Project, ready dependencies, required\ncapabilities, and available concurrency.\n\nQueued work usually means one of three things:\n\n- a dependency has not finished;\n- no connected host capacity currently matches the Project binding, adapter, or\n required capabilities;\n- matching capacity exists, but all concurrency is busy.\n\nWhen capacity appears, Flakes can assign the task to a sandbox. The task then\nmoves through running status as the sandbox accepts the assignment and starts\nthe agent process. The process and its local session are transient. The task\nrecord, status, workpad, activity, artifacts, and transcript pointers are the\ndurable state.\n\n## Dynamic Work\n\nA trusted client should use `flakes tasks save` and `flakes tasks admit` for the\ninitial graph. A running planner or harness can append children only when its\nadmitted task includes the needed grants, such as `flakes.tasks.spawn` and the\ntask-group grants documented in [Harnesses](/docs/harnesses).\n\nSpawned children are appended to the same run. They do not edit existing\naccepted tasks, and they do not inherit broad graph-editing powers unless the\nparent explicitly grants the runtime tools the workflow needs.\n\n## Close And Wait\n\nClose a run when the client has admitted all intended top-level work. Keep the\nrun open while a planner is expected to add children. Close it after the\nplanner has created the work you want the scheduler to drain.\n\n`flakes runs close RUN_KEY --wait` is useful for scripts and handoffs. It\nreturns the latest run body after the wait completes or times out, while the\nconsole remains the best place to inspect detailed task state.\n\n`WAITING` is different from queued capacity. A task in `WAITING` has yielded its\ncurrent assignment because it is waiting on durable state, such as a closed\ntask group. It is not schedulable until the wait condition is satisfied. When\nthe condition resolves, Flakes can resume the logical task from durable state\nwith a fresh assignment.\n";
|