@hasna/instructions 0.6.1 → 0.7.1
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/README.md +141 -10
- package/dist/chunks/{apply-ynfn1av7.js → apply-c3sd4agz.js} +5 -3
- package/dist/chunks/{apply-sfzja1f3.js → apply-pnn7a3y7.js} +6 -3
- package/dist/chunks/database-wstmr56z.js +23 -0
- package/dist/chunks/{index-pkscjnj5.js → index-3djthcm6.js} +0 -1
- package/dist/chunks/index-5d7zdftc.js +186 -0
- package/dist/chunks/{index-1hpwskwd.js → index-6jncnnw7.js} +318 -329
- package/dist/chunks/index-8rb7ng2y.js +148 -0
- package/dist/chunks/{index-v7dkb384.js → index-aj66f6xr.js} +243 -100
- package/dist/chunks/index-fpeyzn3n.js +186 -0
- package/dist/chunks/{index-9p9gn7gh.js → index-jg8ptcwh.js} +5 -7
- package/dist/chunks/index-mvckkf15.js +363 -0
- package/dist/chunks/index-n3fjspr0.js +119 -0
- package/dist/chunks/{index-85n5wnd8.js → index-pdpg8a44.js} +5 -7
- package/dist/chunks/{index-e9epbsvs.js → index-r7nfef2g.js} +15 -4
- package/dist/chunks/{index-axhwg61p.js → index-ypcef3a2.js} +15 -4
- package/dist/chunks/legacy-store-migration-z2m5yzyk.js +322 -0
- package/dist/chunks/{local-a9nen65z.js → local-0a9gja58.js} +142 -2
- package/dist/chunks/{local-0d8qrc92.js → local-969ye538.js} +153 -188
- package/dist/chunks/s3-backup-hxe3zpfz.js +240 -0
- package/dist/chunks/s3-config-hhght91k.js +14 -0
- package/dist/chunks/s3-object-store-n0s82swt.js +14 -0
- package/dist/chunks/{sync-vy1yjvs6.js → sync-q5hvwq6e.js} +4 -4
- package/dist/chunks/{sync-m46fc257.js → sync-xtkbm5br.js} +5 -4
- package/dist/chunks/{template-02wjvv05.js → template-fsfxpe4p.js} +1 -1
- package/dist/chunks/{template-ke972qqe.js → template-wgnzdn7h.js} +1 -1
- package/dist/cli/index.js +1236 -256
- package/dist/data/config-store.d.ts +10 -1
- package/dist/data/config-store.d.ts.map +1 -1
- package/dist/db/configs.d.ts +4 -1
- package/dist/db/configs.d.ts.map +1 -1
- package/dist/db/local.d.ts +1 -1
- package/dist/db/local.d.ts.map +1 -1
- package/dist/index.js +1086 -215
- package/dist/lib/apply.d.ts +7 -0
- package/dist/lib/apply.d.ts.map +1 -1
- package/dist/lib/compact-output.d.ts +3 -18
- package/dist/lib/compact-output.d.ts.map +1 -1
- package/dist/lib/export.d.ts +22 -3
- package/dist/lib/export.d.ts.map +1 -1
- package/dist/lib/import.d.ts +18 -0
- package/dist/lib/import.d.ts.map +1 -1
- package/dist/lib/legacy-store-migration.d.ts +39 -0
- package/dist/lib/legacy-store-migration.d.ts.map +1 -0
- package/dist/lib/managed-skill-runtimes.d.ts +1 -0
- package/dist/lib/managed-skill-runtimes.d.ts.map +1 -1
- package/dist/lib/sync-dir.d.ts.map +1 -1
- package/dist/mcp/index.js +41 -30
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +229 -10
- package/dist/sdk/resolve.d.ts +1 -1
- package/dist/sdk/resolve.d.ts.map +1 -1
- package/dist/sdk/v1-client.d.ts +58 -0
- package/dist/sdk/v1-client.d.ts.map +1 -0
- package/dist/sdk/v1.generated.d.ts +242 -21
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.d.ts +13 -5
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1261 -427
- package/dist/server/openapi.d.ts +1379 -93
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/v1.d.ts +25 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/cloud-store.d.ts +45 -2
- package/dist/storage/cloud-store.d.ts.map +1 -1
- package/dist/storage/index.d.ts +7 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +744 -0
- package/dist/storage/s3-backup.d.ts +76 -0
- package/dist/storage/s3-backup.d.ts.map +1 -0
- package/dist/storage/s3-config.d.ts +46 -0
- package/dist/storage/s3-config.d.ts.map +1 -0
- package/dist/storage/s3-object-store.d.ts +70 -0
- package/dist/storage/s3-object-store.d.ts.map +1 -0
- package/dist/types/index.d.ts +98 -3
- package/dist/types/index.d.ts.map +1 -1
- package/hasna.contract.json +110 -0
- package/migrations/0001_instructions.sql +63 -0
- package/migrations/0002_api_keys.sql +20 -0
- package/migrations/0003_idempotency_receipts.sql +24 -0
- package/package.json +24 -13
- package/assets/skills/inbox/SKILL.md +0 -86
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/storage/s3-config.ts
|
|
3
|
+
var INSTRUCTIONS_S3_ENV = {
|
|
4
|
+
bucket: "HASNA_INSTRUCTIONS_S3_BUCKET",
|
|
5
|
+
prefix: "HASNA_INSTRUCTIONS_S3_PREFIX",
|
|
6
|
+
region: "HASNA_INSTRUCTIONS_AWS_REGION",
|
|
7
|
+
endpoint: "HASNA_INSTRUCTIONS_S3_ENDPOINT",
|
|
8
|
+
forcePathStyle: "HASNA_INSTRUCTIONS_S3_FORCE_PATH_STYLE",
|
|
9
|
+
accessKeyId: "HASNA_INSTRUCTIONS_S3_ACCESS_KEY_ID",
|
|
10
|
+
secretAccessKey: "HASNA_INSTRUCTIONS_S3_SECRET_ACCESS_KEY",
|
|
11
|
+
sessionToken: "HASNA_INSTRUCTIONS_S3_SESSION_TOKEN"
|
|
12
|
+
};
|
|
13
|
+
var INSTRUCTIONS_S3_ALIAS_ENV = {
|
|
14
|
+
bucket: "INSTRUCTIONS_S3_BUCKET",
|
|
15
|
+
prefix: "INSTRUCTIONS_S3_PREFIX",
|
|
16
|
+
region: "INSTRUCTIONS_AWS_REGION",
|
|
17
|
+
endpoint: "INSTRUCTIONS_S3_ENDPOINT",
|
|
18
|
+
forcePathStyle: "INSTRUCTIONS_S3_FORCE_PATH_STYLE",
|
|
19
|
+
accessKeyId: "INSTRUCTIONS_S3_ACCESS_KEY_ID",
|
|
20
|
+
secretAccessKey: "INSTRUCTIONS_S3_SECRET_ACCESS_KEY",
|
|
21
|
+
sessionToken: "INSTRUCTIONS_S3_SESSION_TOKEN"
|
|
22
|
+
};
|
|
23
|
+
var BUCKET_PATTERN = /^(?!xn--)[a-z0-9](?:[a-z0-9.-]{1,61}[a-z0-9])?$/;
|
|
24
|
+
var REGION_PATTERN = /^[a-z]{2}(?:-gov)?-[a-z0-9-]+-\d$/;
|
|
25
|
+
var CONTROL_CHARACTERS = /[\u0000-\u001f\u007f]/;
|
|
26
|
+
function loadInstructionsS3Config(env = process.env) {
|
|
27
|
+
const bucket = readEnv(env, "bucket");
|
|
28
|
+
const configuredWithoutBucket = Object.keys(INSTRUCTIONS_S3_ENV).filter((key) => key !== "bucket").some((key) => readEnv(env, key) !== undefined);
|
|
29
|
+
if (!bucket) {
|
|
30
|
+
if (configuredWithoutBucket) {
|
|
31
|
+
throw new Error(`${INSTRUCTIONS_S3_ENV.bucket} is required when any Instructions S3 setting is configured`);
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
validateBucket(bucket);
|
|
36
|
+
const prefix = normalizeInstructionsS3Prefix(readEnv(env, "prefix") ?? "instructions/");
|
|
37
|
+
const region = readEnv(env, "region") ?? "us-east-1";
|
|
38
|
+
validateRegion(region);
|
|
39
|
+
const endpoint = normalizeEndpoint(readEnv(env, "endpoint"));
|
|
40
|
+
const forcePathStyle = parseBoolean(readEnv(env, "forcePathStyle"), false);
|
|
41
|
+
const accessKeyId = readEnv(env, "accessKeyId");
|
|
42
|
+
const secretAccessKey = readEnv(env, "secretAccessKey");
|
|
43
|
+
const sessionToken = readEnv(env, "sessionToken");
|
|
44
|
+
if (Boolean(accessKeyId) !== Boolean(secretAccessKey)) {
|
|
45
|
+
throw new Error(`${INSTRUCTIONS_S3_ENV.accessKeyId} and ${INSTRUCTIONS_S3_ENV.secretAccessKey} must be configured together`);
|
|
46
|
+
}
|
|
47
|
+
if (sessionToken && (!accessKeyId || !secretAccessKey)) {
|
|
48
|
+
throw new Error(`${INSTRUCTIONS_S3_ENV.sessionToken} requires a complete static credential pair`);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
provider: "s3",
|
|
52
|
+
bucket,
|
|
53
|
+
prefix,
|
|
54
|
+
region,
|
|
55
|
+
...endpoint ? { endpoint } : {},
|
|
56
|
+
forcePathStyle,
|
|
57
|
+
...accessKeyId && secretAccessKey ? {
|
|
58
|
+
credentials: {
|
|
59
|
+
accessKeyId,
|
|
60
|
+
secretAccessKey,
|
|
61
|
+
...sessionToken ? { sessionToken } : {}
|
|
62
|
+
}
|
|
63
|
+
} : {}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function normalizeInstructionsS3Prefix(value) {
|
|
67
|
+
const trimmed = value.trim();
|
|
68
|
+
if (!trimmed || CONTROL_CHARACTERS.test(trimmed) || trimmed.includes("\\")) {
|
|
69
|
+
throw new Error("Instructions S3 prefix is invalid");
|
|
70
|
+
}
|
|
71
|
+
const withoutEdges = trimmed.replace(/^\/+|\/+$/g, "");
|
|
72
|
+
if (!withoutEdges || withoutEdges.includes("//")) {
|
|
73
|
+
throw new Error("Instructions S3 prefix is invalid");
|
|
74
|
+
}
|
|
75
|
+
const segments = withoutEdges.split("/");
|
|
76
|
+
for (const segment of segments) {
|
|
77
|
+
let decoded;
|
|
78
|
+
try {
|
|
79
|
+
decoded = decodeURIComponent(segment);
|
|
80
|
+
} catch {
|
|
81
|
+
throw new Error("Instructions S3 prefix contains invalid percent encoding");
|
|
82
|
+
}
|
|
83
|
+
if (!decoded || decoded === "." || decoded === ".." || decoded.includes("/") || decoded.includes("\\") || CONTROL_CHARACTERS.test(decoded)) {
|
|
84
|
+
throw new Error("Instructions S3 prefix contains an unsafe path segment");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return `${segments.join("/")}/`;
|
|
88
|
+
}
|
|
89
|
+
function readEnv(env, key) {
|
|
90
|
+
const canonical = INSTRUCTIONS_S3_ENV[key];
|
|
91
|
+
if (Object.prototype.hasOwnProperty.call(env, canonical))
|
|
92
|
+
return clean(env[canonical]);
|
|
93
|
+
return clean(env[INSTRUCTIONS_S3_ALIAS_ENV[key]]);
|
|
94
|
+
}
|
|
95
|
+
function clean(value) {
|
|
96
|
+
const trimmed = value?.trim();
|
|
97
|
+
return trimmed ? trimmed : undefined;
|
|
98
|
+
}
|
|
99
|
+
function parseBoolean(value, fallback) {
|
|
100
|
+
if (!value)
|
|
101
|
+
return fallback;
|
|
102
|
+
switch (value.toLowerCase()) {
|
|
103
|
+
case "1":
|
|
104
|
+
case "true":
|
|
105
|
+
case "yes":
|
|
106
|
+
case "on":
|
|
107
|
+
return true;
|
|
108
|
+
case "0":
|
|
109
|
+
case "false":
|
|
110
|
+
case "no":
|
|
111
|
+
case "off":
|
|
112
|
+
return false;
|
|
113
|
+
default:
|
|
114
|
+
throw new Error("Instructions S3 boolean setting is invalid");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function validateBucket(bucket) {
|
|
118
|
+
if (bucket.length < 3 || bucket.length > 63 || !BUCKET_PATTERN.test(bucket) || bucket.includes("..") || bucket.includes(".-") || bucket.includes("-.") || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(bucket)) {
|
|
119
|
+
throw new Error("Instructions S3 bucket is invalid");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function validateRegion(region) {
|
|
123
|
+
if (!REGION_PATTERN.test(region))
|
|
124
|
+
throw new Error("Instructions AWS region is invalid");
|
|
125
|
+
}
|
|
126
|
+
function normalizeEndpoint(value) {
|
|
127
|
+
if (!value)
|
|
128
|
+
return;
|
|
129
|
+
let endpoint;
|
|
130
|
+
try {
|
|
131
|
+
endpoint = new URL(value);
|
|
132
|
+
} catch {
|
|
133
|
+
throw new Error("Instructions S3 endpoint is invalid");
|
|
134
|
+
}
|
|
135
|
+
if (endpoint.username || endpoint.password || endpoint.search || endpoint.hash) {
|
|
136
|
+
throw new Error("Instructions S3 endpoint must not contain credentials, query parameters, or fragments");
|
|
137
|
+
}
|
|
138
|
+
if (endpoint.pathname !== "/") {
|
|
139
|
+
throw new Error("Instructions S3 endpoint must be an origin without a path");
|
|
140
|
+
}
|
|
141
|
+
const localHttp = endpoint.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(endpoint.hostname);
|
|
142
|
+
if (endpoint.protocol !== "https:" && !localHttp) {
|
|
143
|
+
throw new Error("Instructions S3 endpoint must use HTTPS (HTTP is allowed only for loopback development)");
|
|
144
|
+
}
|
|
145
|
+
return endpoint.origin;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export { INSTRUCTIONS_S3_ENV, INSTRUCTIONS_S3_ALIAS_ENV, loadInstructionsS3Config, normalizeInstructionsS3Prefix };
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
isTemplate,
|
|
16
16
|
renderTemplate,
|
|
17
17
|
renderTemplatePreview
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-3djthcm6.js";
|
|
19
19
|
import {
|
|
20
20
|
__export,
|
|
21
21
|
__require
|
|
@@ -203,6 +203,7 @@ import { randomUUID } from "crypto";
|
|
|
203
203
|
// src/lib/compact-output.ts
|
|
204
204
|
var DEFAULT_LIST_LIMIT = 20;
|
|
205
205
|
var MAX_LIST_LIMIT = 100;
|
|
206
|
+
var MAX_LIST_CURSOR = 1e5;
|
|
206
207
|
function parseLimit(value, fallback = DEFAULT_LIST_LIMIT, max = MAX_LIST_LIMIT) {
|
|
207
208
|
const parsed = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
208
209
|
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
@@ -213,7 +214,7 @@ function parseCursor(value) {
|
|
|
213
214
|
const parsed = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
214
215
|
if (!Number.isFinite(parsed) || parsed < 0)
|
|
215
216
|
return 0;
|
|
216
|
-
return Math.floor(parsed);
|
|
217
|
+
return Math.min(Math.floor(parsed), MAX_LIST_CURSOR);
|
|
217
218
|
}
|
|
218
219
|
function paginate(items, opts = {}) {
|
|
219
220
|
const limit = parseLimit(opts.limit, opts.defaultLimit ?? DEFAULT_LIST_LIMIT, opts.maxLimit ?? MAX_LIST_LIMIT);
|
|
@@ -243,28 +244,6 @@ function truncateText(value, max = 80) {
|
|
|
243
244
|
return text.slice(0, max);
|
|
244
245
|
return `${text.slice(0, max - 3)}...`;
|
|
245
246
|
}
|
|
246
|
-
function summarizeConfig(config, opts = {}) {
|
|
247
|
-
const summary = {
|
|
248
|
-
id: config.id,
|
|
249
|
-
slug: config.slug,
|
|
250
|
-
name: config.name,
|
|
251
|
-
category: config.category,
|
|
252
|
-
agent: config.agent,
|
|
253
|
-
kind: config.kind,
|
|
254
|
-
format: config.format,
|
|
255
|
-
target_path: config.target_path,
|
|
256
|
-
output_count: config.outputs.length,
|
|
257
|
-
version: config.version,
|
|
258
|
-
is_template: config.is_template
|
|
259
|
-
};
|
|
260
|
-
if (opts.verbose) {
|
|
261
|
-
summary.updated_at = config.updated_at;
|
|
262
|
-
summary.description = config.description;
|
|
263
|
-
summary.tags = config.tags;
|
|
264
|
-
summary.outputs = config.outputs;
|
|
265
|
-
}
|
|
266
|
-
return summary;
|
|
267
|
-
}
|
|
268
247
|
function summarizeProfile(profile, opts = {}) {
|
|
269
248
|
const selectorCount = (profile.selectors.os?.length ?? 0) + (profile.selectors.arch?.length ?? 0) + (profile.selectors.hostnames?.length ?? 0);
|
|
270
249
|
const summary = {
|
|
@@ -720,7 +699,7 @@ function optionalString(value, label) {
|
|
|
720
699
|
return requiredString(value, label);
|
|
721
700
|
}
|
|
722
701
|
|
|
723
|
-
//
|
|
702
|
+
// ../../node_modules/.bun/@hasna+contracts@1.0.2+e8014c875821e0be/node_modules/@hasna/contracts/dist/client/transport.js
|
|
724
703
|
import { createRequire } from "module";
|
|
725
704
|
function envToken(name) {
|
|
726
705
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -754,7 +733,7 @@ var AUTHORITY_OVERRIDE_HEADERS = new Set([
|
|
|
754
733
|
"x-original-host"
|
|
755
734
|
]);
|
|
756
735
|
|
|
757
|
-
//
|
|
736
|
+
// ../../node_modules/.bun/@hasna+contracts@1.0.2+e8014c875821e0be/node_modules/@hasna/contracts/dist/client/storage.js
|
|
758
737
|
import { isIP } from "net";
|
|
759
738
|
import { spawnSync } from "child_process";
|
|
760
739
|
import { closeSync, fstatSync, openSync, readFileSync } from "fs";
|
|
@@ -2032,11 +2011,11 @@ function announceLocalInstructionsMode(write = (line) => process.stderr.write(`$
|
|
|
2032
2011
|
}
|
|
2033
2012
|
|
|
2034
2013
|
// src/data/config-store.ts
|
|
2035
|
-
function parseBoundedPagePayload(value, label) {
|
|
2014
|
+
function parseBoundedPagePayload(value, label, expected) {
|
|
2036
2015
|
const page = value;
|
|
2037
2016
|
const consumed = Number(page?.cursor) + (page?.items?.length ?? 0);
|
|
2038
2017
|
const complete = Boolean(page && Number.isSafeInteger(page.total) && consumed >= Number(page.total));
|
|
2039
|
-
if (!page || !Array.isArray(page.items) || !Number.isSafeInteger(page.total) || Number(page.total) < 0 || !Number.isSafeInteger(page.limit) || Number(page.limit) < 1 || !Number.isSafeInteger(page.cursor) || Number(page.cursor) < 0 || page.items.length > Number(page.limit) || typeof page.has_more !== "boolean" || typeof page.complete !== "boolean" || page.truncated !== false || page.next_cursor !== null && !Number.isSafeInteger(page.next_cursor) || page.complete !== complete || page.has_more !== !complete || page.next_cursor !== (complete ? null : consumed)) {
|
|
2018
|
+
if (!page || !Array.isArray(page.items) || !Number.isSafeInteger(page.total) || Number(page.total) < 0 || !Number.isSafeInteger(page.limit) || Number(page.limit) < 1 || !Number.isSafeInteger(page.cursor) || Number(page.cursor) < 0 || page.items.length > Number(page.limit) || typeof page.has_more !== "boolean" || typeof page.complete !== "boolean" || page.truncated !== false || page.next_cursor !== null && !Number.isSafeInteger(page.next_cursor) || page.complete !== complete || page.has_more !== !complete || page.next_cursor !== (complete ? null : consumed) || expected !== undefined && Number(page.cursor) !== expected.cursor) {
|
|
2040
2019
|
throw new Error(`${label} returned an invalid or truncated bounded-read envelope`);
|
|
2041
2020
|
}
|
|
2042
2021
|
return {
|
|
@@ -2048,7 +2027,7 @@ function parseBoundedOrLegacyPage(value, legacyItems, options, label) {
|
|
|
2048
2027
|
if (value && typeof value === "object") {
|
|
2049
2028
|
const candidate = value;
|
|
2050
2029
|
if ("items" in candidate || "total" in candidate || "complete" in candidate || "truncated" in candidate || "next_cursor" in candidate) {
|
|
2051
|
-
return parseBoundedPagePayload(value, label);
|
|
2030
|
+
return parseBoundedPagePayload(value, label, normalizeBoundedReadOptions(options));
|
|
2052
2031
|
}
|
|
2053
2032
|
}
|
|
2054
2033
|
if (!Array.isArray(legacyItems)) {
|
|
@@ -2058,13 +2037,85 @@ function parseBoundedOrLegacyPage(value, legacyItems, options, label) {
|
|
|
2058
2037
|
const page = boundedReadPage(legacyItems.slice(normalized.cursor, normalized.cursor + normalized.limit), legacyItems.length, normalized);
|
|
2059
2038
|
return { ...page, source_bounded: false };
|
|
2060
2039
|
}
|
|
2040
|
+
function projectBoundedPage(page, project) {
|
|
2041
|
+
return {
|
|
2042
|
+
items: page.items.map(project),
|
|
2043
|
+
total: page.total,
|
|
2044
|
+
limit: page.limit,
|
|
2045
|
+
cursor: page.cursor,
|
|
2046
|
+
next_cursor: page.next_cursor,
|
|
2047
|
+
has_more: page.has_more,
|
|
2048
|
+
complete: page.complete,
|
|
2049
|
+
truncated: page.truncated,
|
|
2050
|
+
source_bounded: page.source_bounded
|
|
2051
|
+
};
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
class CollectionChangedWhilePagingError extends Error {
|
|
2055
|
+
constructor(label, detail) {
|
|
2056
|
+
super(`${label} changed while paging: ${detail}`);
|
|
2057
|
+
this.name = "CollectionChangedWhilePagingError";
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
var COLLECTION_READ_ATTEMPTS = 2;
|
|
2061
|
+
async function aggregateBoundedCollection(label, readPage, identity, options = {}) {
|
|
2062
|
+
let lastError = null;
|
|
2063
|
+
for (let attempt = 0;attempt < COLLECTION_READ_ATTEMPTS; attempt += 1) {
|
|
2064
|
+
try {
|
|
2065
|
+
const items = [];
|
|
2066
|
+
const seen = new Set;
|
|
2067
|
+
let expectedTotal = null;
|
|
2068
|
+
let cursor = 0;
|
|
2069
|
+
let previousIdentity = null;
|
|
2070
|
+
while (true) {
|
|
2071
|
+
const page = await readPage(cursor);
|
|
2072
|
+
if (page.cursor !== cursor) {
|
|
2073
|
+
throw new CollectionChangedWhilePagingError(label, `server returned cursor ${page.cursor} for requested cursor ${cursor}`);
|
|
2074
|
+
}
|
|
2075
|
+
if (expectedTotal === null)
|
|
2076
|
+
expectedTotal = page.total;
|
|
2077
|
+
else if (page.total !== expectedTotal) {
|
|
2078
|
+
throw new CollectionChangedWhilePagingError(label, `total changed from ${expectedTotal} to ${page.total}`);
|
|
2079
|
+
}
|
|
2080
|
+
for (const item of page.items) {
|
|
2081
|
+
const key = identity(item);
|
|
2082
|
+
if (!key)
|
|
2083
|
+
throw new CollectionChangedWhilePagingError(label, "an item had no stable identity");
|
|
2084
|
+
if (seen.has(key))
|
|
2085
|
+
throw new CollectionChangedWhilePagingError(label, `duplicate identity ${key}`);
|
|
2086
|
+
if (options.requireAscendingIdentity && page.source_bounded && previousIdentity !== null && key <= previousIdentity) {
|
|
2087
|
+
throw new CollectionChangedWhilePagingError(label, `identity order was not strictly increasing at ${key}`);
|
|
2088
|
+
}
|
|
2089
|
+
seen.add(key);
|
|
2090
|
+
previousIdentity = key;
|
|
2091
|
+
items.push(item);
|
|
2092
|
+
}
|
|
2093
|
+
if (page.complete) {
|
|
2094
|
+
if (items.length !== expectedTotal) {
|
|
2095
|
+
throw new CollectionChangedWhilePagingError(label, `received ${items.length} unique rows for total ${expectedTotal}`);
|
|
2096
|
+
}
|
|
2097
|
+
return items;
|
|
2098
|
+
}
|
|
2099
|
+
if (page.next_cursor === null || page.next_cursor <= cursor) {
|
|
2100
|
+
throw new CollectionChangedWhilePagingError(label, `cursor did not advance from ${cursor}`);
|
|
2101
|
+
}
|
|
2102
|
+
cursor = page.next_cursor;
|
|
2103
|
+
}
|
|
2104
|
+
} catch (error) {
|
|
2105
|
+
if (!(error instanceof CollectionChangedWhilePagingError))
|
|
2106
|
+
throw error;
|
|
2107
|
+
lastError = error;
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
throw lastError ?? new CollectionChangedWhilePagingError(label, "read did not stabilize");
|
|
2111
|
+
}
|
|
2061
2112
|
function isNotFoundHttpError2(err) {
|
|
2062
2113
|
return typeof err === "object" && err !== null && err.name === "HasnaHttpError" && err.status === 404;
|
|
2063
2114
|
}
|
|
2064
2115
|
var localStoreModulePromise = null;
|
|
2065
2116
|
function localStoreModule() {
|
|
2066
2117
|
if (!localStoreModulePromise)
|
|
2067
|
-
localStoreModulePromise = import("./local-
|
|
2118
|
+
localStoreModulePromise = import("./local-0a9gja58.js");
|
|
2068
2119
|
return localStoreModulePromise;
|
|
2069
2120
|
}
|
|
2070
2121
|
|
|
@@ -2078,6 +2129,15 @@ class LocalConfigStore {
|
|
|
2078
2129
|
async listConfigs(filter) {
|
|
2079
2130
|
return (await localStoreModule()).listConfigs(filter, this.db);
|
|
2080
2131
|
}
|
|
2132
|
+
async listConfigsPage(filter = {}, options = {}) {
|
|
2133
|
+
return (await localStoreModule()).listConfigsPage(filter, options, this.db);
|
|
2134
|
+
}
|
|
2135
|
+
async listConfigIdentitiesPage(filter = {}, options = {}) {
|
|
2136
|
+
return (await localStoreModule()).listConfigIdentitiesPage(filter, options, this.db);
|
|
2137
|
+
}
|
|
2138
|
+
async listConfigSummariesPage(filter = {}, options = {}) {
|
|
2139
|
+
return (await localStoreModule()).listConfigSummariesPage(filter, options, this.db);
|
|
2140
|
+
}
|
|
2081
2141
|
async getConfig(idOrSlug) {
|
|
2082
2142
|
return (await localStoreModule()).getConfig(idOrSlug, this.db);
|
|
2083
2143
|
}
|
|
@@ -2112,15 +2172,7 @@ class LocalConfigStore {
|
|
|
2112
2172
|
return (await localStoreModule()).pruneSnapshots(configId, keep, this.db);
|
|
2113
2173
|
}
|
|
2114
2174
|
async listProfiles() {
|
|
2115
|
-
|
|
2116
|
-
let cursor = 0;
|
|
2117
|
-
while (true) {
|
|
2118
|
-
const page = await this.listProfilesPage({ limit: 100, cursor });
|
|
2119
|
-
profiles.push(...page.items);
|
|
2120
|
-
if (page.complete)
|
|
2121
|
-
return profiles;
|
|
2122
|
-
cursor = page.next_cursor;
|
|
2123
|
-
}
|
|
2175
|
+
return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id);
|
|
2124
2176
|
}
|
|
2125
2177
|
async listProfilesPage(options = {}) {
|
|
2126
2178
|
return (await localStoreModule()).listProfilesPage(options, this.db);
|
|
@@ -2129,15 +2181,7 @@ class LocalConfigStore {
|
|
|
2129
2181
|
return (await localStoreModule()).getProfile(idOrSlug, this.db);
|
|
2130
2182
|
}
|
|
2131
2183
|
async getProfileConfigs(idOrSlug) {
|
|
2132
|
-
|
|
2133
|
-
let cursor = 0;
|
|
2134
|
-
while (true) {
|
|
2135
|
-
const page = await this.getProfileConfigsPage(idOrSlug, { limit: 100, cursor });
|
|
2136
|
-
configs.push(...page.items);
|
|
2137
|
-
if (page.complete)
|
|
2138
|
-
return configs;
|
|
2139
|
-
cursor = page.next_cursor;
|
|
2140
|
-
}
|
|
2184
|
+
return aggregateBoundedCollection("profile membership", (cursor) => this.getProfileConfigsPage(idOrSlug, { limit: 100, cursor }), (config) => config.id);
|
|
2141
2185
|
}
|
|
2142
2186
|
async getProfileConfigsPage(idOrSlug, options = {}) {
|
|
2143
2187
|
return (await localStoreModule()).getProfileConfigsPage(idOrSlug, options, this.db);
|
|
@@ -2197,6 +2241,43 @@ class LocalConfigStore {
|
|
|
2197
2241
|
(await localStoreModule()).resetLocalDatabase();
|
|
2198
2242
|
}
|
|
2199
2243
|
}
|
|
2244
|
+
function toConfigIdentity(value) {
|
|
2245
|
+
const record = value && typeof value === "object" ? value : {};
|
|
2246
|
+
return {
|
|
2247
|
+
id: String(record.id ?? ""),
|
|
2248
|
+
name: String(record.name ?? ""),
|
|
2249
|
+
slug: String(record.slug ?? ""),
|
|
2250
|
+
kind: String(record.kind ?? ""),
|
|
2251
|
+
category: String(record.category ?? ""),
|
|
2252
|
+
agent: String(record.agent ?? ""),
|
|
2253
|
+
format: String(record.format ?? ""),
|
|
2254
|
+
is_template: Boolean(record.is_template),
|
|
2255
|
+
version: Number(record.version ?? 0),
|
|
2256
|
+
created_at: String(record.created_at ?? ""),
|
|
2257
|
+
updated_at: String(record.updated_at ?? ""),
|
|
2258
|
+
synced_at: record.synced_at == null ? null : String(record.synced_at)
|
|
2259
|
+
};
|
|
2260
|
+
}
|
|
2261
|
+
function toConfigSummary(value) {
|
|
2262
|
+
const record = value && typeof value === "object" ? value : {};
|
|
2263
|
+
const outputs = Array.isArray(record.outputs) ? record.outputs : [];
|
|
2264
|
+
return {
|
|
2265
|
+
id: String(record.id ?? ""),
|
|
2266
|
+
slug: String(record.slug ?? ""),
|
|
2267
|
+
name: String(record.name ?? ""),
|
|
2268
|
+
category: String(record.category ?? ""),
|
|
2269
|
+
agent: String(record.agent ?? ""),
|
|
2270
|
+
kind: String(record.kind ?? ""),
|
|
2271
|
+
format: String(record.format ?? ""),
|
|
2272
|
+
target_path: record.target_path == null ? null : String(record.target_path),
|
|
2273
|
+
output_count: Number(record.output_count ?? outputs.length),
|
|
2274
|
+
version: Number(record.version ?? 0),
|
|
2275
|
+
is_template: Boolean(record.is_template),
|
|
2276
|
+
...record.updated_at !== undefined ? { updated_at: String(record.updated_at) } : {},
|
|
2277
|
+
...record.description !== undefined ? { description: record.description == null ? null : String(record.description) } : {},
|
|
2278
|
+
...Array.isArray(record.tags) ? { tags: record.tags.map(String) } : {}
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2200
2281
|
|
|
2201
2282
|
class CloudConfigStore {
|
|
2202
2283
|
mode = "api";
|
|
@@ -2218,7 +2299,8 @@ class CloudConfigStore {
|
|
|
2218
2299
|
throw err;
|
|
2219
2300
|
}
|
|
2220
2301
|
}
|
|
2221
|
-
async
|
|
2302
|
+
async listConfigsPage(filter = {}, options = {}) {
|
|
2303
|
+
const normalized = normalizeBoundedReadOptions(options);
|
|
2222
2304
|
const params = new URLSearchParams;
|
|
2223
2305
|
if (filter.category)
|
|
2224
2306
|
params.set("category", filter.category);
|
|
@@ -2228,16 +2310,75 @@ class CloudConfigStore {
|
|
|
2228
2310
|
params.set("kind", filter.kind);
|
|
2229
2311
|
if (filter.search)
|
|
2230
2312
|
params.set("search", filter.search);
|
|
2231
|
-
const
|
|
2232
|
-
|
|
2233
|
-
|
|
2313
|
+
for (const tag of filter.tags ?? [])
|
|
2314
|
+
params.append("tag", tag);
|
|
2315
|
+
params.set("limit", String(normalized.limit));
|
|
2316
|
+
params.set("cursor", String(normalized.cursor));
|
|
2317
|
+
const { data } = await this.request("GET", `/configs?${params.toString()}`);
|
|
2318
|
+
return parseBoundedOrLegacyPage(data, data?.configs, normalized, "config list");
|
|
2319
|
+
}
|
|
2320
|
+
async listConfigIdentitiesPage(filter = {}, options = {}) {
|
|
2321
|
+
const normalized = normalizeBoundedReadOptions(options);
|
|
2322
|
+
const params = new URLSearchParams;
|
|
2323
|
+
if (filter.category)
|
|
2324
|
+
params.set("category", filter.category);
|
|
2325
|
+
if (filter.agent)
|
|
2326
|
+
params.set("agent", filter.agent);
|
|
2327
|
+
if (filter.kind)
|
|
2328
|
+
params.set("kind", filter.kind);
|
|
2329
|
+
if (filter.search)
|
|
2330
|
+
params.set("search", filter.search);
|
|
2331
|
+
for (const tag of filter.tags ?? [])
|
|
2332
|
+
params.append("tag", tag);
|
|
2333
|
+
params.set("view", "identity");
|
|
2334
|
+
params.set("limit", String(normalized.limit));
|
|
2335
|
+
params.set("cursor", String(normalized.cursor));
|
|
2336
|
+
const { data } = await this.request("GET", `/configs?${params.toString()}`);
|
|
2337
|
+
const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config identity list");
|
|
2338
|
+
if (page.items.some((item) => {
|
|
2339
|
+
const record = item && typeof item === "object" ? item : {};
|
|
2340
|
+
return ["content", "target_path", "outputs", "description", "tags"].some((field) => Object.prototype.hasOwnProperty.call(record, field));
|
|
2341
|
+
})) {
|
|
2342
|
+
throw new Error("Instructions /v1 config identity projection is unavailable; deploy the identity endpoint before using compact lists");
|
|
2343
|
+
}
|
|
2344
|
+
return projectBoundedPage(page, toConfigIdentity);
|
|
2345
|
+
}
|
|
2346
|
+
async listConfigSummariesPage(filter = {}, options = {}) {
|
|
2347
|
+
const normalized = normalizeBoundedReadOptions(options);
|
|
2348
|
+
const params = new URLSearchParams;
|
|
2349
|
+
if (filter.category)
|
|
2350
|
+
params.set("category", filter.category);
|
|
2351
|
+
if (filter.agent)
|
|
2352
|
+
params.set("agent", filter.agent);
|
|
2353
|
+
if (filter.kind)
|
|
2354
|
+
params.set("kind", filter.kind);
|
|
2355
|
+
if (filter.search)
|
|
2356
|
+
params.set("search", filter.search);
|
|
2357
|
+
for (const tag of filter.tags ?? [])
|
|
2358
|
+
params.append("tag", tag);
|
|
2359
|
+
params.set("view", "summary");
|
|
2360
|
+
params.set("limit", String(normalized.limit));
|
|
2361
|
+
params.set("cursor", String(normalized.cursor));
|
|
2362
|
+
const { data } = await this.request("GET", `/configs?${params.toString()}`);
|
|
2363
|
+
const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config summary list");
|
|
2364
|
+
if (page.items.some((item) => {
|
|
2365
|
+
const record = item && typeof item === "object" ? item : {};
|
|
2366
|
+
return Object.prototype.hasOwnProperty.call(record, "content") || Object.prototype.hasOwnProperty.call(record, "outputs");
|
|
2367
|
+
})) {
|
|
2368
|
+
throw new Error("Instructions /v1 config summary projection is unavailable; deploy the summary endpoint before using summary lists");
|
|
2369
|
+
}
|
|
2370
|
+
return projectBoundedPage(page, toConfigSummary);
|
|
2371
|
+
}
|
|
2372
|
+
async listConfigs(filter = {}) {
|
|
2373
|
+
const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPage(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
|
|
2374
|
+
let filtered = configs;
|
|
2234
2375
|
if (filter.tags && filter.tags.length > 0) {
|
|
2235
|
-
|
|
2376
|
+
filtered = filtered.filter((config) => filter.tags.every((tag) => config.tags.includes(tag)));
|
|
2236
2377
|
}
|
|
2237
2378
|
if (filter.is_template !== undefined) {
|
|
2238
|
-
|
|
2379
|
+
filtered = filtered.filter((config) => config.is_template === filter.is_template);
|
|
2239
2380
|
}
|
|
2240
|
-
return
|
|
2381
|
+
return filtered;
|
|
2241
2382
|
}
|
|
2242
2383
|
async getConfig(idOrSlug) {
|
|
2243
2384
|
const { status, data } = await this.request("GET", `/configs/${encodeURIComponent(idOrSlug)}`, undefined, { allow404: true });
|
|
@@ -2268,8 +2409,11 @@ class CloudConfigStore {
|
|
|
2268
2409
|
return data ?? { total: 0 };
|
|
2269
2410
|
}
|
|
2270
2411
|
async listSnapshots(configId) {
|
|
2271
|
-
|
|
2272
|
-
|
|
2412
|
+
return aggregateBoundedCollection("snapshot list", async (cursor) => {
|
|
2413
|
+
const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
|
|
2414
|
+
const { data } = await this.request("GET", `/configs/${encodeURIComponent(configId)}/snapshots?limit=${normalized.limit}&cursor=${normalized.cursor}`);
|
|
2415
|
+
return parseBoundedOrLegacyPage(data, data?.snapshots, normalized, "snapshot list");
|
|
2416
|
+
}, (snapshot) => snapshot.id);
|
|
2273
2417
|
}
|
|
2274
2418
|
async getSnapshot(id) {
|
|
2275
2419
|
const { status, data } = await this.request("GET", `/snapshots/${encodeURIComponent(id)}`, undefined, { allow404: true });
|
|
@@ -2292,15 +2436,7 @@ class CloudConfigStore {
|
|
|
2292
2436
|
return data?.pruned ?? 0;
|
|
2293
2437
|
}
|
|
2294
2438
|
async listProfiles() {
|
|
2295
|
-
|
|
2296
|
-
let cursor = 0;
|
|
2297
|
-
while (true) {
|
|
2298
|
-
const page = await this.listProfilesPage({ limit: 100, cursor });
|
|
2299
|
-
profiles.push(...page.items);
|
|
2300
|
-
if (page.complete)
|
|
2301
|
-
return profiles;
|
|
2302
|
-
cursor = page.next_cursor;
|
|
2303
|
-
}
|
|
2439
|
+
return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id);
|
|
2304
2440
|
}
|
|
2305
2441
|
async listProfilesPage(options = {}) {
|
|
2306
2442
|
const normalized = normalizeBoundedReadOptions(options);
|
|
@@ -2324,15 +2460,7 @@ class CloudConfigStore {
|
|
|
2324
2460
|
return profile;
|
|
2325
2461
|
}
|
|
2326
2462
|
async getProfileConfigs(idOrSlug) {
|
|
2327
|
-
|
|
2328
|
-
let cursor = 0;
|
|
2329
|
-
while (true) {
|
|
2330
|
-
const page = await this.getProfileConfigsPage(idOrSlug, { limit: 100, cursor });
|
|
2331
|
-
configs.push(...page.items);
|
|
2332
|
-
if (page.complete)
|
|
2333
|
-
return configs;
|
|
2334
|
-
cursor = page.next_cursor;
|
|
2335
|
-
}
|
|
2463
|
+
return aggregateBoundedCollection("profile membership", (cursor) => this.getProfileConfigsPage(idOrSlug, { limit: 100, cursor }), (config) => config.id);
|
|
2336
2464
|
}
|
|
2337
2465
|
async getProfileConfigsPage(idOrSlug, options = {}) {
|
|
2338
2466
|
const normalized = normalizeBoundedReadOptions(options);
|
|
@@ -2346,20 +2474,26 @@ class CloudConfigStore {
|
|
|
2346
2474
|
return parseBoundedOrLegacyPage(data.configs, data.profile.configs, normalized, "profile membership");
|
|
2347
2475
|
}
|
|
2348
2476
|
async getProfileConfigBindings(idOrSlug) {
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
const
|
|
2352
|
-
const
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2477
|
+
let routeMissing = false;
|
|
2478
|
+
const bindings = await aggregateBoundedCollection("profile config bindings", async (cursor) => {
|
|
2479
|
+
const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
|
|
2480
|
+
const { status, data } = await this.requestProfileRoute(idOrSlug, (profileId) => `/profiles/${encodeURIComponent(profileId)}/bindings?limit=${normalized.limit}&cursor=${normalized.cursor}`, (value) => Boolean(value && (Array.isArray(value.bindings) || Array.isArray(value.items))));
|
|
2481
|
+
if (status === 404) {
|
|
2482
|
+
routeMissing = true;
|
|
2483
|
+
return { ...boundedReadPage([], 0, normalized), source_bounded: false };
|
|
2484
|
+
}
|
|
2485
|
+
return parseBoundedOrLegacyPage(data, data?.bindings, normalized, "profile config bindings");
|
|
2486
|
+
}, (binding) => `${binding.profile_id}\x00${binding.config_id}`);
|
|
2487
|
+
if (!routeMissing)
|
|
2488
|
+
return bindings;
|
|
2489
|
+
const profile = await this.getProfile(idOrSlug);
|
|
2490
|
+
const configs = await this.getProfileConfigs(idOrSlug);
|
|
2491
|
+
return configs.map((config, sort_order) => ({
|
|
2492
|
+
profile_id: profile.id,
|
|
2493
|
+
config_id: config.id,
|
|
2494
|
+
sort_order,
|
|
2495
|
+
binding: legacyProfileConfigBinding()
|
|
2496
|
+
}));
|
|
2363
2497
|
}
|
|
2364
2498
|
async requestProfileRoute(idOrSlug, pathForId, isUsable) {
|
|
2365
2499
|
const attempted = new Set;
|
|
@@ -2417,14 +2551,20 @@ class CloudConfigStore {
|
|
|
2417
2551
|
await this.request("DELETE", `/profiles/${encodeURIComponent(profileIdOrSlug)}/configs/${encodeURIComponent(configId)}`, undefined, { allow404: true });
|
|
2418
2552
|
}
|
|
2419
2553
|
async getProfileAssetBindings(profileIdOrSlug) {
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2554
|
+
let routeMissing = false;
|
|
2555
|
+
const assets = await aggregateBoundedCollection("profile asset bindings", async (cursor) => {
|
|
2556
|
+
const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
|
|
2557
|
+
const { status, data } = await this.requestProfileRoute(profileIdOrSlug, (profileId) => `/profiles/${encodeURIComponent(profileId)}/assets?limit=${normalized.limit}&cursor=${normalized.cursor}`, (value) => Boolean(value && (Array.isArray(value.assets) || Array.isArray(value.items))));
|
|
2558
|
+
if (status === 404) {
|
|
2559
|
+
routeMissing = true;
|
|
2560
|
+
return { ...boundedReadPage([], 0, normalized), source_bounded: false };
|
|
2561
|
+
}
|
|
2562
|
+
return parseBoundedOrLegacyPage(data, data?.assets, normalized, "profile asset bindings");
|
|
2563
|
+
}, (asset) => `${asset.profile_id}\x00${asset.binding.assetKey}`);
|
|
2564
|
+
if (!routeMissing)
|
|
2565
|
+
return assets;
|
|
2566
|
+
await this.getProfile(profileIdOrSlug);
|
|
2567
|
+
return [];
|
|
2428
2568
|
}
|
|
2429
2569
|
async addAssetToProfile(profileIdOrSlug, sourceConfigId, binding) {
|
|
2430
2570
|
const { data } = await this.request("POST", `/profiles/${encodeURIComponent(profileIdOrSlug)}/assets`, { source_config_id: sourceConfigId, binding }, { idempotent: true });
|
|
@@ -2494,8 +2634,11 @@ class CloudConfigStore {
|
|
|
2494
2634
|
await this.request("POST", "/machines/applied", { hostname });
|
|
2495
2635
|
}
|
|
2496
2636
|
async listMachines() {
|
|
2497
|
-
|
|
2498
|
-
|
|
2637
|
+
return aggregateBoundedCollection("machine list", async (cursor) => {
|
|
2638
|
+
const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
|
|
2639
|
+
const { data } = await this.request("GET", `/machines?limit=${normalized.limit}&cursor=${normalized.cursor}`);
|
|
2640
|
+
return parseBoundedOrLegacyPage(data, data?.machines, normalized, "machine list");
|
|
2641
|
+
}, (machine) => machine.id, { requireAscendingIdentity: true });
|
|
2499
2642
|
}
|
|
2500
2643
|
async sendFeedback(input) {
|
|
2501
2644
|
await this.request("POST", "/feedback", {
|
|
@@ -7245,4 +7388,4 @@ function renderMachineAwareContentPreview(content, variables) {
|
|
|
7245
7388
|
return isTemplate(content) ? renderTemplatePreview(content, variables) : { content, unresolved: [] };
|
|
7246
7389
|
}
|
|
7247
7390
|
|
|
7248
|
-
export { pagedPayload,
|
|
7391
|
+
export { pagedPayload, summarizeProfile, summarizeApplyResult, normalizeBoundedReadOptions, boundedReadPage, SESSION_RENDER_SCHEMA, SESSION_RENDER_MANIFEST_RELATIVE_PATH, isRetiredOrUnsupportedConfigAgent, retiredOrUnsupportedAgentReason, applyTransform, normalizeProfileAssetBinding, isCursorGlobalAuthorityPath, stampCursorGlobalAuthorityMarker, getReportedDbPath, getRawStoreRoot, ANTIGRAVITY_RULE_FILE_CHAR_LIMIT, SESSION_RENDERER_OWNER_ID, SESSION_RENDER_OWNED_CONFIG_TARGETS, SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS, legacyProfileConfigBinding, normalizeProfileConfigBinding, hasInstructionsEnvAuthorityIntent, normalizeOsFamily, detectMachineContext, machineContextToVariables, resolveProfileVariables, templateizeMachineContent, renderMachineAwareContentPreview, resolveConfigStore };
|