@hasna/instructions 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -6
- package/dist/chunks/{apply-ynfn1av7.js → apply-7svah2qm.js} +5 -3
- package/dist/chunks/{apply-sfzja1f3.js → apply-jp13sa1e.js} +6 -3
- package/dist/chunks/database-wstmr56z.js +23 -0
- package/dist/chunks/{index-85n5wnd8.js → index-1cnyjnd7.js} +5 -7
- package/dist/chunks/{index-pkscjnj5.js → index-3djthcm6.js} +0 -1
- package/dist/chunks/{index-v7dkb384.js → index-4pfq42t5.js} +129 -77
- package/dist/chunks/index-5d7zdftc.js +186 -0
- package/dist/chunks/{index-1hpwskwd.js → index-7m4j8a33.js} +205 -329
- package/dist/chunks/index-8rb7ng2y.js +148 -0
- package/dist/chunks/index-arrrx0ed.js +344 -0
- package/dist/chunks/{index-9p9gn7gh.js → index-bzyxvwcd.js} +5 -7
- package/dist/chunks/index-fpeyzn3n.js +186 -0
- package/dist/chunks/{index-axhwg61p.js → index-fwbs6tma.js} +15 -4
- package/dist/chunks/index-n3fjspr0.js +119 -0
- package/dist/chunks/{index-e9epbsvs.js → index-z3ma4aqk.js} +15 -4
- package/dist/chunks/legacy-store-migration-z2m5yzyk.js +322 -0
- package/dist/chunks/{local-a9nen65z.js → local-5wvv5xv3.js} +2 -2
- package/dist/chunks/{local-0d8qrc92.js → local-zxa5dpf4.js} +13 -188
- package/dist/chunks/s3-backup-n2z4fwyh.js +240 -0
- package/dist/chunks/s3-config-hhght91k.js +14 -0
- package/dist/chunks/s3-object-store-90tgbh6k.js +14 -0
- package/dist/chunks/{sync-m46fc257.js → sync-2075deve.js} +5 -4
- package/dist/chunks/{sync-vy1yjvs6.js → sync-r8t7zsp3.js} +4 -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 +1011 -247
- package/dist/data/config-store.d.ts +1 -0
- package/dist/data/config-store.d.ts.map +1 -1
- package/dist/index.js +840 -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 +1 -0
- 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 +31 -20
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +205 -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 +57 -0
- package/dist/sdk/v1-client.d.ts.map +1 -0
- package/dist/sdk/v1.generated.d.ts +212 -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 +1180 -432
- package/dist/server/openapi.d.ts +1264 -92
- 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 +57 -1
- 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 +725 -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 +65 -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 +22 -11
- package/assets/skills/inbox/SKILL.md +0 -86
|
@@ -15,7 +15,14 @@ import {
|
|
|
15
15
|
isTemplate,
|
|
16
16
|
renderTemplate,
|
|
17
17
|
renderTemplatePreview
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-n3fjspr0.js";
|
|
19
|
+
import {
|
|
20
|
+
INSTRUCTIONS_LOCAL_OPT_IN_ENV_KEYS,
|
|
21
|
+
clientTransportEnvKeys,
|
|
22
|
+
instructionsLocalModeNotice,
|
|
23
|
+
instructionsResolverInputs,
|
|
24
|
+
selectsInstructionsLocalStore
|
|
25
|
+
} from "./index-fpeyzn3n.js";
|
|
19
26
|
import {
|
|
20
27
|
__export,
|
|
21
28
|
__require
|
|
@@ -24,6 +31,7 @@ import {
|
|
|
24
31
|
// src/lib/compact-output.ts
|
|
25
32
|
var DEFAULT_LIST_LIMIT = 20;
|
|
26
33
|
var MAX_LIST_LIMIT = 100;
|
|
34
|
+
var MAX_LIST_CURSOR = 1e5;
|
|
27
35
|
function parseLimit(value, fallback = DEFAULT_LIST_LIMIT, max = MAX_LIST_LIMIT) {
|
|
28
36
|
const parsed = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
29
37
|
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
@@ -34,7 +42,7 @@ function parseCursor(value) {
|
|
|
34
42
|
const parsed = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
35
43
|
if (!Number.isFinite(parsed) || parsed < 0)
|
|
36
44
|
return 0;
|
|
37
|
-
return Math.floor(parsed);
|
|
45
|
+
return Math.min(Math.floor(parsed), MAX_LIST_CURSOR);
|
|
38
46
|
}
|
|
39
47
|
function paginate(items, opts = {}) {
|
|
40
48
|
const limit = parseLimit(opts.limit, opts.defaultLimit ?? DEFAULT_LIST_LIMIT, opts.maxLimit ?? MAX_LIST_LIMIT);
|
|
@@ -110,9 +118,9 @@ import { createHash as createHash6 } from "crypto";
|
|
|
110
118
|
|
|
111
119
|
// src/lib/session-render.ts
|
|
112
120
|
import { createHash as createHash5 } from "crypto";
|
|
113
|
-
import { existsSync as
|
|
114
|
-
import { homedir as
|
|
115
|
-
import { basename as basename4, dirname as dirname4, extname as extname2, isAbsolute as isAbsolute3, join as
|
|
121
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, realpathSync as realpathSync2, statSync as statSync3 } from "fs";
|
|
122
|
+
import { homedir as homedir4 } from "os";
|
|
123
|
+
import { basename as basename4, dirname as dirname4, extname as extname2, isAbsolute as isAbsolute3, join as join5, parse as parse2, posix as posix2, relative as relative2, resolve as resolve6 } from "path";
|
|
116
124
|
|
|
117
125
|
// src/lib/codewith-shared-todos-storage-standard.ts
|
|
118
126
|
var CODEWITH_SHARED_TODOS_STORAGE_STANDARD_SLUG = "codewith-shared-todos-storage-standard";
|
|
@@ -8161,105 +8169,6 @@ function detectClaudeAuthorityConflicts(targetHome, ownedAuthorities = []) {
|
|
|
8161
8169
|
reason: knownLegacy ? "Claude target contains unmanaged legacy AGENTS.md with no-worktree directives; migrate or remove it through an owned authority path before applying." : "Claude target contains unmanaged AGENTS.md with unknown authority content; refusing to guess whether it conflicts with the managed Claude render."
|
|
8162
8170
|
}];
|
|
8163
8171
|
}
|
|
8164
|
-
// src/lib/raw-store-root.ts
|
|
8165
|
-
import { resolve as resolve7 } from "path";
|
|
8166
|
-
|
|
8167
|
-
// src/lib/app-home.ts
|
|
8168
|
-
import { existsSync as existsSync4 } from "fs";
|
|
8169
|
-
import { homedir as homedir4 } from "os";
|
|
8170
|
-
import { join as join5, resolve as resolve6 } from "path";
|
|
8171
|
-
import { homedir as pathsResolverHomedir2 } from "os";
|
|
8172
|
-
import { join as pathsResolverJoin2 } from "path";
|
|
8173
|
-
var PATHS_RESOLVER_KIND_ENV2 = {
|
|
8174
|
-
config: "HASNA_CONFIG_HOME",
|
|
8175
|
-
data: "HASNA_DATA_HOME",
|
|
8176
|
-
state: "HASNA_STATE_HOME",
|
|
8177
|
-
cache: "HASNA_CACHE_HOME"
|
|
8178
|
-
};
|
|
8179
|
-
var PATHS_RESOLVER_APP_SLUG_RE2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
8180
|
-
function pathsResolverAssertApp2(app) {
|
|
8181
|
-
if (typeof app !== "string" || app.length === 0) {
|
|
8182
|
-
throw new TypeError("paths: app must be a non-empty string");
|
|
8183
|
-
}
|
|
8184
|
-
if (!PATHS_RESOLVER_APP_SLUG_RE2.test(app)) {
|
|
8185
|
-
throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
|
|
8186
|
-
}
|
|
8187
|
-
}
|
|
8188
|
-
function pathsResolverAssertKind2(kind) {
|
|
8189
|
-
if (!Object.keys(PATHS_RESOLVER_KIND_ENV2).includes(kind)) {
|
|
8190
|
-
throw new TypeError(`paths: invalid path kind "${kind}" \u2014 expected one of ${Object.keys(PATHS_RESOLVER_KIND_ENV2).join(", ")}`);
|
|
8191
|
-
}
|
|
8192
|
-
}
|
|
8193
|
-
function pathsResolverBaseDir2(kind, options) {
|
|
8194
|
-
pathsResolverAssertKind2(kind);
|
|
8195
|
-
const env = options.env ?? process.env;
|
|
8196
|
-
const override = env[PATHS_RESOLVER_KIND_ENV2[kind]];
|
|
8197
|
-
if (typeof override === "string" && override.length > 0)
|
|
8198
|
-
return override;
|
|
8199
|
-
const home = options.home ?? pathsResolverHomedir2();
|
|
8200
|
-
const platform = options.platform ?? process.platform;
|
|
8201
|
-
if (platform === "darwin") {
|
|
8202
|
-
switch (kind) {
|
|
8203
|
-
case "config":
|
|
8204
|
-
case "data":
|
|
8205
|
-
return pathsResolverJoin2(home, "Library", "Application Support", "Hasna");
|
|
8206
|
-
case "cache":
|
|
8207
|
-
return pathsResolverJoin2(home, "Library", "Caches", "Hasna");
|
|
8208
|
-
case "state":
|
|
8209
|
-
return pathsResolverJoin2(home, "Library", "Logs", "Hasna");
|
|
8210
|
-
}
|
|
8211
|
-
}
|
|
8212
|
-
switch (kind) {
|
|
8213
|
-
case "config":
|
|
8214
|
-
return pathsResolverJoin2(home, ".config", "hasna");
|
|
8215
|
-
case "data":
|
|
8216
|
-
return pathsResolverJoin2(home, ".local", "share", "hasna");
|
|
8217
|
-
case "state":
|
|
8218
|
-
return pathsResolverJoin2(home, ".local", "state", "hasna");
|
|
8219
|
-
case "cache":
|
|
8220
|
-
return pathsResolverJoin2(home, ".cache", "hasna");
|
|
8221
|
-
}
|
|
8222
|
-
}
|
|
8223
|
-
function pathsResolverResolve2(kind, options) {
|
|
8224
|
-
pathsResolverAssertApp2(options.app);
|
|
8225
|
-
const appSegment = options.internal === true ? pathsResolverJoin2("internal", options.app) : options.app;
|
|
8226
|
-
return pathsResolverJoin2(pathsResolverBaseDir2(kind, options), appSegment);
|
|
8227
|
-
}
|
|
8228
|
-
function configDir(options) {
|
|
8229
|
-
return pathsResolverResolve2("config", options);
|
|
8230
|
-
}
|
|
8231
|
-
var HASNA_CONFIGS_HOME_ENV = "HASNA_CONFIGS_HOME";
|
|
8232
|
-
function homeDir3(env = process.env) {
|
|
8233
|
-
return env["HOME"] || env["USERPROFILE"] || homedir4();
|
|
8234
|
-
}
|
|
8235
|
-
function legacyStoreHome(env = process.env) {
|
|
8236
|
-
return resolve6(join5(homeDir3(env), ".hasna", "instructions"));
|
|
8237
|
-
}
|
|
8238
|
-
function resolverStoreHome(env = process.env) {
|
|
8239
|
-
return configDir({ app: "configs", env, home: env.HOME || env.USERPROFILE || homedir4() });
|
|
8240
|
-
}
|
|
8241
|
-
function adoptResolverStoreHome(resolved, env = process.env) {
|
|
8242
|
-
const override = env.HASNA_CONFIG_HOME;
|
|
8243
|
-
if (typeof override === "string" && override.trim().length > 0)
|
|
8244
|
-
return true;
|
|
8245
|
-
return existsSync4(join5(resolved, "instructions.db"));
|
|
8246
|
-
}
|
|
8247
|
-
function exactStoreHome(env = process.env) {
|
|
8248
|
-
const v = env[HASNA_CONFIGS_HOME_ENV];
|
|
8249
|
-
return v && v.trim() ? v.trim() : undefined;
|
|
8250
|
-
}
|
|
8251
|
-
function getConfigsStoreHome(env = process.env) {
|
|
8252
|
-
const exact = exactStoreHome(env);
|
|
8253
|
-
if (exact)
|
|
8254
|
-
return resolve6(exact);
|
|
8255
|
-
const resolved = resolverStoreHome(env);
|
|
8256
|
-
return adoptResolverStoreHome(resolved, env) ? resolve6(resolved) : legacyStoreHome(env);
|
|
8257
|
-
}
|
|
8258
|
-
|
|
8259
|
-
// src/lib/raw-store-root.ts
|
|
8260
|
-
function getRawStoreRoot(env = process.env) {
|
|
8261
|
-
return resolve7(getConfigsStoreHome(env));
|
|
8262
|
-
}
|
|
8263
8172
|
|
|
8264
8173
|
// src/lib/session-render.ts
|
|
8265
8174
|
var ANTIGRAVITY_RULE_FILE_CHAR_LIMIT = 12000;
|
|
@@ -8542,13 +8451,13 @@ function yamlQuote2(value) {
|
|
|
8542
8451
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
8543
8452
|
}
|
|
8544
8453
|
function defaultTargetHome(tool, profile, sessionId) {
|
|
8545
|
-
const home = process.env["HOME"] ||
|
|
8546
|
-
return
|
|
8454
|
+
const home = process.env["HOME"] || homedir4();
|
|
8455
|
+
return join5(home, ".hasna", "accounts", "profiles", tool, slug(profile));
|
|
8547
8456
|
}
|
|
8548
8457
|
function joinTarget(targetHome, relativePath) {
|
|
8549
8458
|
const safeTargetHome = assertSafeTargetRoot(targetHome);
|
|
8550
8459
|
const safeRelativePath2 = assertSafeRelativePath(relativePath);
|
|
8551
|
-
return
|
|
8460
|
+
return join5(safeTargetHome, ...safeRelativePath2.split("/"));
|
|
8552
8461
|
}
|
|
8553
8462
|
function makeFile(targetHome, relativePath, role, content, sourceIds) {
|
|
8554
8463
|
const safeTargetHome = assertSafeTargetRoot(targetHome);
|
|
@@ -9118,7 +9027,7 @@ function buildOpenCodeFiles(targetHome, adapter, profile, sources, providerConfi
|
|
|
9118
9027
|
...sources.flatMap((source) => source.resolvedRules.map((rule) => rule.id))
|
|
9119
9028
|
]);
|
|
9120
9029
|
const existingConfigPath = joinTarget(targetHome, adapter.configFile);
|
|
9121
|
-
const selectedConfig =
|
|
9030
|
+
const selectedConfig = existsSync4(existingConfigPath) ? readOpenCodeConfig(readFileSync4(existingConfigPath, "utf8"), existingConfigPath) : providerConfig ? readOpenCodeConfig(providerConfig.content, providerConfig.sourceId) : {};
|
|
9122
9031
|
const preservedInstructions = normalizeOpenCodeInstructions(selectedConfig["instructions"]).filter((path) => !pathIsManagedOpenCodeInstruction(path, adapter.managedDir));
|
|
9123
9032
|
const config = {
|
|
9124
9033
|
...selectedConfig,
|
|
@@ -9321,7 +9230,7 @@ function adapterFor(input) {
|
|
|
9321
9230
|
return gatedNativeImports ? CODEWITH_NATIVE_ADAPTER : CODEWITH_FLATTENED_ADAPTER;
|
|
9322
9231
|
}
|
|
9323
9232
|
function getHomeDir() {
|
|
9324
|
-
return process.env["CONFIGS_HOME"] || process.env["HOME"] ||
|
|
9233
|
+
return process.env["CONFIGS_HOME"] || process.env["HOME"] || homedir4();
|
|
9325
9234
|
}
|
|
9326
9235
|
function cleanSessionPathInput(path) {
|
|
9327
9236
|
const trimmed = path.trim();
|
|
@@ -9336,16 +9245,16 @@ function resolveSessionPath(path) {
|
|
|
9336
9245
|
throw new Error("Session render path cannot be empty.");
|
|
9337
9246
|
const home = getHomeDir();
|
|
9338
9247
|
if (cleaned === "~")
|
|
9339
|
-
return
|
|
9248
|
+
return resolve6(home);
|
|
9340
9249
|
if (cleaned.startsWith("~/"))
|
|
9341
|
-
return
|
|
9250
|
+
return resolve6(home, cleaned.slice(2));
|
|
9342
9251
|
if (cleaned === "{{HOME}}" || cleaned === "${HOME}")
|
|
9343
|
-
return
|
|
9252
|
+
return resolve6(home);
|
|
9344
9253
|
if (cleaned.startsWith("{{HOME}}/"))
|
|
9345
|
-
return
|
|
9254
|
+
return resolve6(home, cleaned.slice("{{HOME}}/".length));
|
|
9346
9255
|
if (cleaned.startsWith("${HOME}/"))
|
|
9347
|
-
return
|
|
9348
|
-
return
|
|
9256
|
+
return resolve6(home, cleaned.slice("${HOME}/".length));
|
|
9257
|
+
return resolve6(cleaned);
|
|
9349
9258
|
}
|
|
9350
9259
|
function assertSafeRelativePath(relativePath) {
|
|
9351
9260
|
if (!relativePath.trim())
|
|
@@ -9361,7 +9270,7 @@ function assertSafeRelativePath(relativePath) {
|
|
|
9361
9270
|
function assertSafeTargetRoot(targetHome) {
|
|
9362
9271
|
if (!isAbsolute3(targetHome))
|
|
9363
9272
|
throw new Error(`Session render target must be an absolute path: ${targetHome}`);
|
|
9364
|
-
const normalized =
|
|
9273
|
+
const normalized = resolve6(targetHome);
|
|
9365
9274
|
if (normalized === parse2(normalized).root) {
|
|
9366
9275
|
throw new Error(`Session render target cannot be the filesystem root: ${targetHome}`);
|
|
9367
9276
|
}
|
|
@@ -9596,7 +9505,7 @@ function planSessionRender(input) {
|
|
|
9596
9505
|
sourceId: input.providerConfig.sourceId,
|
|
9597
9506
|
selectedPayloadSha256: sha2565(input.providerConfig.content),
|
|
9598
9507
|
renderedPayloadSha256: files.find((file) => file.relativePath === adapter.configFile)?.sha256 ?? sha2565(input.providerConfig.content),
|
|
9599
|
-
selected: !
|
|
9508
|
+
selected: !existsSync4(joinTarget(targetHome, adapter.configFile))
|
|
9600
9509
|
}
|
|
9601
9510
|
} : {},
|
|
9602
9511
|
...projectContext ? {
|
|
@@ -9879,7 +9788,7 @@ ${item.content.trimEnd()}`).join(`
|
|
|
9879
9788
|
}
|
|
9880
9789
|
function readIdentitySourcePath(sourcePath, baseDir, sourceId) {
|
|
9881
9790
|
const resolvedPath = resolveIdentitySourcePath(sourcePath.path, baseDir, sourceId);
|
|
9882
|
-
if (!
|
|
9791
|
+
if (!existsSync4(resolvedPath)) {
|
|
9883
9792
|
if (sourcePath.required) {
|
|
9884
9793
|
throw new Error(`Required identity instruction source path not found for ${sourceId}: ${sourcePath.path}`);
|
|
9885
9794
|
}
|
|
@@ -9902,8 +9811,8 @@ function resolveIdentitySourcePath(path, baseDir, sourceId) {
|
|
|
9902
9811
|
throw new Error(`Identity instruction source path cannot be empty for ${sourceId}.`);
|
|
9903
9812
|
if (cleaned.includes("\\"))
|
|
9904
9813
|
throw new Error(`Identity instruction source path must use POSIX separators for ${sourceId}: ${path}`);
|
|
9905
|
-
const resolvedPath = isAbsolute3(cleaned) ?
|
|
9906
|
-
if (!pathIsInside(resolvedPath,
|
|
9814
|
+
const resolvedPath = isAbsolute3(cleaned) ? resolve6(cleaned) : resolve6(baseDir, cleaned);
|
|
9815
|
+
if (!pathIsInside(resolvedPath, resolve6(baseDir))) {
|
|
9907
9816
|
throw new Error(`Identity instruction source path escapes export directory for ${sourceId}: ${path}`);
|
|
9908
9817
|
}
|
|
9909
9818
|
return resolvedPath;
|
|
@@ -10559,12 +10468,18 @@ function deepFreeze2(value) {
|
|
|
10559
10468
|
return Object.freeze(value);
|
|
10560
10469
|
}
|
|
10561
10470
|
|
|
10562
|
-
//
|
|
10471
|
+
// ../../node_modules/.bun/@hasna+contracts@1.0.2+e8014c875821e0be/node_modules/@hasna/contracts/dist/client/storage.js
|
|
10472
|
+
import { isIP } from "net";
|
|
10473
|
+
import { spawnSync } from "child_process";
|
|
10474
|
+
import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readFileSync as readFileSync5 } from "fs";
|
|
10475
|
+
import { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } from "constants";
|
|
10563
10476
|
import { createRequire } from "module";
|
|
10477
|
+
import { hostname as osHostname } from "os";
|
|
10478
|
+
import { isAbsolute as isAbsolute4, join as join6 } from "path";
|
|
10564
10479
|
function envToken(name) {
|
|
10565
10480
|
return name.toUpperCase().replace(/-/g, "_");
|
|
10566
10481
|
}
|
|
10567
|
-
function
|
|
10482
|
+
function clientTransportEnvKeys2(name) {
|
|
10568
10483
|
const envSegment = envToken(name);
|
|
10569
10484
|
return {
|
|
10570
10485
|
apiUrlKeys: [`HASNA_${envSegment}_API_URL`, `${envSegment}_API_URL`],
|
|
@@ -10578,46 +10493,6 @@ var CREDENTIAL_PROFILE_ENV_KEY = "HASNA_PROFILE";
|
|
|
10578
10493
|
function credentialPointerEnvKey(name) {
|
|
10579
10494
|
return `HASNA_${envToken(name)}_API_KEY_REF`;
|
|
10580
10495
|
}
|
|
10581
|
-
var MAX_CREDENTIAL_FILE_BYTES = 64 * 1024;
|
|
10582
|
-
var INSPECT_CUSTOM = Symbol.for("nodejs.util.inspect.custom");
|
|
10583
|
-
var CREDENTIAL_SEAL = Symbol.for("hasna:contracts:sealedCredential");
|
|
10584
|
-
var AMBIENT_ENVIRONMENT = Symbol.for("hasna:contracts:ambientClientEnvironment");
|
|
10585
|
-
var SECRETS_PACKAGE_SPECIFIER = "@hasna/" + "secrets";
|
|
10586
|
-
var requireSecretsSdk = createRequire(import.meta.url);
|
|
10587
|
-
var IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
10588
|
-
var AUTHORITY_OVERRIDE_HEADERS = new Set([
|
|
10589
|
-
"host",
|
|
10590
|
-
":authority",
|
|
10591
|
-
"forwarded",
|
|
10592
|
-
"x-forwarded-host",
|
|
10593
|
-
"x-original-host"
|
|
10594
|
-
]);
|
|
10595
|
-
|
|
10596
|
-
// ../contracts/dist/client/storage.js
|
|
10597
|
-
import { isIP } from "net";
|
|
10598
|
-
import { spawnSync } from "child_process";
|
|
10599
|
-
import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readFileSync as readFileSync5 } from "fs";
|
|
10600
|
-
import { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } from "constants";
|
|
10601
|
-
import { createRequire as createRequire2 } from "module";
|
|
10602
|
-
import { hostname as osHostname } from "os";
|
|
10603
|
-
import { isAbsolute as isAbsolute4, join as join7 } from "path";
|
|
10604
|
-
function envToken2(name) {
|
|
10605
|
-
return name.toUpperCase().replace(/-/g, "_");
|
|
10606
|
-
}
|
|
10607
|
-
function clientTransportEnvKeys2(name) {
|
|
10608
|
-
const envSegment = envToken2(name);
|
|
10609
|
-
return {
|
|
10610
|
-
apiUrlKeys: [`HASNA_${envSegment}_API_URL`, `${envSegment}_API_URL`],
|
|
10611
|
-
apiKeyKeys: [`HASNA_${envSegment}_API_KEY`, `${envSegment}_API_KEY`]
|
|
10612
|
-
};
|
|
10613
|
-
}
|
|
10614
|
-
function credentialOverrideEnvKey2(name) {
|
|
10615
|
-
return `HASNA_${envToken2(name)}_API_KEY_OVERRIDE`;
|
|
10616
|
-
}
|
|
10617
|
-
var CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE";
|
|
10618
|
-
function credentialPointerEnvKey2(name) {
|
|
10619
|
-
return `HASNA_${envToken2(name)}_API_KEY_REF`;
|
|
10620
|
-
}
|
|
10621
10496
|
|
|
10622
10497
|
class CredentialResolutionError extends Error {
|
|
10623
10498
|
appName;
|
|
@@ -10648,12 +10523,12 @@ var KEYCHAIN_SECURITY_BIN = "/usr/bin/security";
|
|
|
10648
10523
|
var KEYCHAIN_SERVICE_PREFIX = "hasna.credentials";
|
|
10649
10524
|
var KEYCHAIN_ITEM_NOT_FOUND_STATUS = 44;
|
|
10650
10525
|
var KEYCHAIN_SPAWN_TIMEOUT_MS = 1e4;
|
|
10651
|
-
var
|
|
10526
|
+
var MAX_CREDENTIAL_FILE_BYTES = 64 * 1024;
|
|
10652
10527
|
var SAFE_APP_SLUG = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
10653
10528
|
var SAFE_PROFILE = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
10654
10529
|
var ILLEGAL_IN_HEADER_VALUE = /[^\t\x20-\x7e]/;
|
|
10655
10530
|
var VAULT_POINTER_SHAPE = /^[a-z0-9][a-z0-9-]*(?:\/[a-z0-9][a-z0-9-_.]*){2,}$/;
|
|
10656
|
-
function
|
|
10531
|
+
function homeDir3(env) {
|
|
10657
10532
|
const home = env.HOME?.trim();
|
|
10658
10533
|
return home ? home : null;
|
|
10659
10534
|
}
|
|
@@ -10665,15 +10540,15 @@ function hasnaHomeDir(env) {
|
|
|
10665
10540
|
const override = absoluteOverride(env, HASNA_HOME_ENV_KEY);
|
|
10666
10541
|
if (override)
|
|
10667
10542
|
return override;
|
|
10668
|
-
const home =
|
|
10669
|
-
return home ?
|
|
10543
|
+
const home = homeDir3(env);
|
|
10544
|
+
return home ? join6(home, HASNA_HOME_DIR) : null;
|
|
10670
10545
|
}
|
|
10671
10546
|
function appConfigDir(name, env) {
|
|
10672
10547
|
const configRoot = absoluteOverride(env, HASNA_CONFIG_HOME_ENV_KEY);
|
|
10673
10548
|
if (configRoot)
|
|
10674
|
-
return
|
|
10549
|
+
return join6(configRoot, name);
|
|
10675
10550
|
const root = hasnaHomeDir(env);
|
|
10676
|
-
return root ?
|
|
10551
|
+
return root ? join6(root, name, CONFIG_SUBDIR) : null;
|
|
10677
10552
|
}
|
|
10678
10553
|
function credentialDiskSourceList(name, env, profile = null) {
|
|
10679
10554
|
if (!SAFE_APP_SLUG.test(name))
|
|
@@ -10682,7 +10557,7 @@ function credentialDiskSourceList(name, env, profile = null) {
|
|
|
10682
10557
|
if (!directory)
|
|
10683
10558
|
return [];
|
|
10684
10559
|
const file = profile ? `${CREDENTIALS_FILE}-${profile}` : CREDENTIALS_FILE;
|
|
10685
|
-
return [{ path:
|
|
10560
|
+
return [{ path: join6(directory, file), tier: "disk" }];
|
|
10686
10561
|
}
|
|
10687
10562
|
function credentialDiskSources(name, env) {
|
|
10688
10563
|
return credentialDiskSourceList(name, env, null).map((s) => s.path);
|
|
@@ -10755,7 +10630,7 @@ function readAppConfigFile(path) {
|
|
|
10755
10630
|
const uid = process.getuid?.() ?? process.geteuid?.();
|
|
10756
10631
|
if (uid !== undefined && before.uid !== uid)
|
|
10757
10632
|
unsafe("the file is not owned by the current user");
|
|
10758
|
-
if (before.size >
|
|
10633
|
+
if (before.size > MAX_CREDENTIAL_FILE_BYTES)
|
|
10759
10634
|
unsafe("the file exceeds the size limit");
|
|
10760
10635
|
const bytes = readFileSync5(fd);
|
|
10761
10636
|
const after = fstatSync2(fd);
|
|
@@ -10810,14 +10685,14 @@ function appConfigDiskValue(name, env, keys) {
|
|
|
10810
10685
|
}
|
|
10811
10686
|
function assertUsableCredential(appName, source, value) {
|
|
10812
10687
|
if (VAULT_POINTER_SHAPE.test(value)) {
|
|
10813
|
-
throw new CredentialResolutionError(appName, `The credential from ${source} looks like a secrets-vault pointer (a path-shaped reference like ` + `'namespace/app/live/api_key'). A vault path is NEVER accepted as a literal API key. ` + `Use ${
|
|
10688
|
+
throw new CredentialResolutionError(appName, `The credential from ${source} looks like a secrets-vault pointer (a path-shaped reference like ` + `'namespace/app/live/api_key'). A vault path is NEVER accepted as a literal API key. ` + `Use ${credentialPointerEnvKey(appName)} to resolve the key through the vault, or provide the actual key value.`, [source]);
|
|
10814
10689
|
}
|
|
10815
10690
|
if (!ILLEGAL_IN_HEADER_VALUE.test(value))
|
|
10816
10691
|
return;
|
|
10817
10692
|
throw new CredentialResolutionError(appName, `The credential from ${source} contains characters that cannot be sent in an HTTP header ` + `(a control character or non-ASCII byte). A file written with CR-only line endings is the usual ` + `cause. Rewrite that credential file with one LF-terminated KEY=value line. ` + `The value is not shown here, and is deliberately never logged.`, [source]);
|
|
10818
10693
|
}
|
|
10819
|
-
var
|
|
10820
|
-
var
|
|
10694
|
+
var INSPECT_CUSTOM = Symbol.for("nodejs.util.inspect.custom");
|
|
10695
|
+
var CREDENTIAL_SEAL = Symbol.for("hasna:contracts:sealedCredential");
|
|
10821
10696
|
var CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider";
|
|
10822
10697
|
function sealCredential(fields) {
|
|
10823
10698
|
const { apiKey } = fields;
|
|
@@ -10843,13 +10718,13 @@ function sealCredential(fields) {
|
|
|
10843
10718
|
configurable: false
|
|
10844
10719
|
});
|
|
10845
10720
|
}
|
|
10846
|
-
Object.defineProperty(sealed,
|
|
10721
|
+
Object.defineProperty(sealed, INSPECT_CUSTOM, {
|
|
10847
10722
|
value: () => ({ ...visible, apiKey: "[redacted]" }),
|
|
10848
10723
|
enumerable: false,
|
|
10849
10724
|
writable: false,
|
|
10850
10725
|
configurable: false
|
|
10851
10726
|
});
|
|
10852
|
-
Object.defineProperty(sealed,
|
|
10727
|
+
Object.defineProperty(sealed, CREDENTIAL_SEAL, {
|
|
10853
10728
|
value: true,
|
|
10854
10729
|
enumerable: false,
|
|
10855
10730
|
writable: false,
|
|
@@ -10858,7 +10733,7 @@ function sealCredential(fields) {
|
|
|
10858
10733
|
return Object.freeze(sealed);
|
|
10859
10734
|
}
|
|
10860
10735
|
function isSealedCredential(credential) {
|
|
10861
|
-
return credential[
|
|
10736
|
+
return credential[CREDENTIAL_SEAL] === true;
|
|
10862
10737
|
}
|
|
10863
10738
|
function explicitCredential(appName, apiKey) {
|
|
10864
10739
|
const source = "explicit apiKey option";
|
|
@@ -10905,9 +10780,9 @@ function firstEnvValue(env, keys) {
|
|
|
10905
10780
|
}
|
|
10906
10781
|
return null;
|
|
10907
10782
|
}
|
|
10908
|
-
var
|
|
10783
|
+
var AMBIENT_ENVIRONMENT = Symbol.for("hasna:contracts:ambientClientEnvironment");
|
|
10909
10784
|
function isAmbientEnvironment(env) {
|
|
10910
|
-
return env === process.env || env[
|
|
10785
|
+
return env === process.env || env[AMBIENT_ENVIRONMENT] === true;
|
|
10911
10786
|
}
|
|
10912
10787
|
function defaultKeychainRunner(argv) {
|
|
10913
10788
|
const result = spawnSync(KEYCHAIN_SECURITY_BIN, [...argv], {
|
|
@@ -10980,9 +10855,9 @@ function snapshotClientEnvironment(name, env) {
|
|
|
10980
10855
|
for (const key of [
|
|
10981
10856
|
...keys.apiUrlKeys,
|
|
10982
10857
|
...keys.apiKeyKeys,
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10858
|
+
credentialOverrideEnvKey(name),
|
|
10859
|
+
credentialPointerEnvKey(name),
|
|
10860
|
+
CREDENTIAL_PROFILE_ENV_KEY,
|
|
10986
10861
|
"HOME",
|
|
10987
10862
|
HASNA_HOME_ENV_KEY,
|
|
10988
10863
|
HASNA_CONFIG_HOME_ENV_KEY,
|
|
@@ -11001,7 +10876,7 @@ function snapshotClientEnvironment(name, env) {
|
|
|
11001
10876
|
snapshot[key] = descriptor.value;
|
|
11002
10877
|
}
|
|
11003
10878
|
if (ambient) {
|
|
11004
|
-
Object.defineProperty(snapshot,
|
|
10879
|
+
Object.defineProperty(snapshot, AMBIENT_ENVIRONMENT, {
|
|
11005
10880
|
value: true,
|
|
11006
10881
|
enumerable: false,
|
|
11007
10882
|
writable: false,
|
|
@@ -11029,7 +10904,7 @@ function resolveCredential(name, env, options = {}) {
|
|
|
11029
10904
|
warning: null
|
|
11030
10905
|
});
|
|
11031
10906
|
}
|
|
11032
|
-
const overrideKeyName =
|
|
10907
|
+
const overrideKeyName = credentialOverrideEnvKey(name);
|
|
11033
10908
|
const overrideRaw = Object.prototype.hasOwnProperty.call(env, overrideKeyName) ? env[overrideKeyName] : undefined;
|
|
11034
10909
|
if (overrideRaw !== undefined) {
|
|
11035
10910
|
const override = overrideRaw.trim();
|
|
@@ -11046,7 +10921,7 @@ function resolveCredential(name, env, options = {}) {
|
|
|
11046
10921
|
warning: null
|
|
11047
10922
|
});
|
|
11048
10923
|
}
|
|
11049
|
-
const pointerKeyName =
|
|
10924
|
+
const pointerKeyName = credentialPointerEnvKey(name);
|
|
11050
10925
|
const pointerRaw = Object.prototype.hasOwnProperty.call(env, pointerKeyName) ? env[pointerKeyName] : undefined;
|
|
11051
10926
|
if (pointerRaw !== undefined) {
|
|
11052
10927
|
const pointer = pointerRaw.trim();
|
|
@@ -11069,13 +10944,13 @@ function resolveCredential(name, env, options = {}) {
|
|
|
11069
10944
|
if (options.profile !== undefined && !options.profile.trim()) {
|
|
11070
10945
|
throw new CredentialResolutionError(name, "The explicit profile argument is blank; an explicit identity selection never falls through.", ["explicit profile argument"]);
|
|
11071
10946
|
}
|
|
11072
|
-
const profileRaw = Object.prototype.hasOwnProperty.call(env,
|
|
10947
|
+
const profileRaw = Object.prototype.hasOwnProperty.call(env, CREDENTIAL_PROFILE_ENV_KEY) ? env[CREDENTIAL_PROFILE_ENV_KEY] : undefined;
|
|
11073
10948
|
if (profileRaw !== undefined && !profileRaw.trim()) {
|
|
11074
|
-
throw new CredentialResolutionError(name, `${
|
|
10949
|
+
throw new CredentialResolutionError(name, `${CREDENTIAL_PROFILE_ENV_KEY} is set but blank.`, [CREDENTIAL_PROFILE_ENV_KEY]);
|
|
11075
10950
|
}
|
|
11076
10951
|
const profile = options.profile?.trim() || profileRaw?.trim();
|
|
11077
10952
|
if (profile) {
|
|
11078
|
-
const profileSource = options.profile?.trim() ? "explicit profile argument" :
|
|
10953
|
+
const profileSource = options.profile?.trim() ? "explicit profile argument" : CREDENTIAL_PROFILE_ENV_KEY;
|
|
11079
10954
|
if (!SAFE_PROFILE.test(profile)) {
|
|
11080
10955
|
throw new CredentialResolutionError(name, `Profile name from ${profileSource} is not usable in a path. ` + `Use letters, digits, dot, dash, or underscore.`, [profileSource]);
|
|
11081
10956
|
}
|
|
@@ -11094,7 +10969,7 @@ function resolveCredential(name, env, options = {}) {
|
|
|
11094
10969
|
});
|
|
11095
10970
|
}
|
|
11096
10971
|
}
|
|
11097
|
-
throw new CredentialResolutionError(name, `Profile '${profile}' (from ${profileSource}) has no ${apiKeyKeys[0]} for '${name}'. ` + `Looked in: ${paths.join(", ") || "<no HOME in this environment>"}. ` + `A profile names WHICH identity to use, so it is never resolved around \u2014 ` + `create the profile's credential file or unset ${
|
|
10972
|
+
throw new CredentialResolutionError(name, `Profile '${profile}' (from ${profileSource}) has no ${apiKeyKeys[0]} for '${name}'. ` + `Looked in: ${paths.join(", ") || "<no HOME in this environment>"}. ` + `A profile names WHICH identity to use, so it is never resolved around \u2014 ` + `create the profile's credential file or unset ${CREDENTIAL_PROFILE_ENV_KEY}.`, paths);
|
|
11098
10973
|
}
|
|
11099
10974
|
const definedEnvEntries = apiKeyKeys.filter((key) => Object.prototype.hasOwnProperty.call(env, key) && env[key] !== undefined).map((key) => ({ key, value: String(env[key]).trim() }));
|
|
11100
10975
|
const blankEnv = definedEnvEntries.find((entry) => entry.value.length === 0);
|
|
@@ -11150,8 +11025,8 @@ function resolveCredential(name, env, options = {}) {
|
|
|
11150
11025
|
}
|
|
11151
11026
|
return null;
|
|
11152
11027
|
}
|
|
11153
|
-
var
|
|
11154
|
-
var
|
|
11028
|
+
var SECRETS_PACKAGE_SPECIFIER = "@hasna/" + "secrets";
|
|
11029
|
+
var requireSecretsSdk = createRequire(import.meta.url);
|
|
11155
11030
|
async function completePointerCredential(name, pointerResolution, env = process.env) {
|
|
11156
11031
|
const vaultKey = pointerResolution.pointerVaultKey;
|
|
11157
11032
|
const pointerEnvKey = pointerResolution.source;
|
|
@@ -11160,7 +11035,7 @@ async function completePointerCredential(name, pointerResolution, env = process.
|
|
|
11160
11035
|
}
|
|
11161
11036
|
let secretsSdk;
|
|
11162
11037
|
try {
|
|
11163
|
-
secretsSdk =
|
|
11038
|
+
secretsSdk = requireSecretsSdk(SECRETS_PACKAGE_SPECIFIER);
|
|
11164
11039
|
} catch {
|
|
11165
11040
|
throw new CredentialResolutionError(name, `${pointerEnvKey} names vault item '${vaultKey}', but the secrets SDK (@hasna/secrets) is not installed ` + `in this process. A vault pointer is TERMINAL: install @hasna/secrets to resolve it, or unset ${pointerEnvKey}.`, [pointerEnvKey]);
|
|
11166
11041
|
}
|
|
@@ -11457,8 +11332,8 @@ function authFailureGuidance(credential) {
|
|
|
11457
11332
|
return `${origin}, which was re-read from disk on this very call \u2014 so a stale shell is NOT the cause here. ` + `The stored credential is genuinely being rejected: rotate it, or re-run the fleet key distribution ` + `so this machine gets the current key.`;
|
|
11458
11333
|
}
|
|
11459
11334
|
var DEFAULT_RETRY_STATUSES = [408, 425, 429, 500, 502, 503, 504];
|
|
11460
|
-
var
|
|
11461
|
-
var
|
|
11335
|
+
var IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
11336
|
+
var AUTHORITY_OVERRIDE_HEADERS = new Set([
|
|
11462
11337
|
"host",
|
|
11463
11338
|
":authority",
|
|
11464
11339
|
"forwarded",
|
|
@@ -11468,7 +11343,7 @@ var AUTHORITY_OVERRIDE_HEADERS2 = new Set([
|
|
|
11468
11343
|
function assertNoAuthorityOverrideHeaders(headers, source) {
|
|
11469
11344
|
if (!headers)
|
|
11470
11345
|
return;
|
|
11471
|
-
const forbidden = Object.keys(headers).find((name) =>
|
|
11346
|
+
const forbidden = Object.keys(headers).find((name) => AUTHORITY_OVERRIDE_HEADERS.has(name.trim().toLowerCase()));
|
|
11472
11347
|
if (forbidden) {
|
|
11473
11348
|
throw new Error(`Authenticated ${source} headers must not set authority header '${forbidden}'.`);
|
|
11474
11349
|
}
|
|
@@ -11494,7 +11369,7 @@ function appendQuery(path, query) {
|
|
|
11494
11369
|
return path;
|
|
11495
11370
|
return `${path}${path.includes("?") ? "&" : "?"}${qs}`;
|
|
11496
11371
|
}
|
|
11497
|
-
var defaultSleep = (ms) => new Promise((
|
|
11372
|
+
var defaultSleep = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
11498
11373
|
function createHasnaHttpTransportInternal(options, requestBindingProvider) {
|
|
11499
11374
|
const fetchImpl = options.fetchImpl ?? ((input, init) => fetch(input, init));
|
|
11500
11375
|
const base = toV1BaseUrl(options.baseUrl);
|
|
@@ -11602,7 +11477,7 @@ function createHasnaHttpTransportInternal(options, requestBindingProvider) {
|
|
|
11602
11477
|
const upper = method.toUpperCase();
|
|
11603
11478
|
const rel = appendQuery(path.startsWith("/") ? path : `/${path}`, opts.query);
|
|
11604
11479
|
const retry = resolveRetry(opts.retry);
|
|
11605
|
-
const methodRetryable =
|
|
11480
|
+
const methodRetryable = IDEMPOTENT_METHODS.has(upper) || Boolean(opts.idempotencyKey);
|
|
11606
11481
|
const maxAttempts = retry && methodRetryable ? retry.retries + 1 : 1;
|
|
11607
11482
|
const binding = requestBindingProvider ? await requestBindingProvider() : {
|
|
11608
11483
|
baseUrl: base,
|
|
@@ -11779,56 +11654,6 @@ function resolveStorageClient(name, env = process.env, overrides) {
|
|
|
11779
11654
|
return { transport: "http", client: createHasnaStorageClient(name, wired.client) };
|
|
11780
11655
|
}
|
|
11781
11656
|
|
|
11782
|
-
// src/lib/local-opt-in.ts
|
|
11783
|
-
var INSTRUCTIONS_LOCAL_OPT_IN_ENV_KEYS = ["HASNA_INSTRUCTIONS_LOCAL"];
|
|
11784
|
-
function instructionsLocalModeNotice() {
|
|
11785
|
-
return `instructions: local mode \u2014 ${INSTRUCTIONS_LOCAL_OPT_IN_ENV_KEYS[0]}=1 selects the on-box SQLite store, ` + `and no hosted authority was configured. Set HASNA_INSTRUCTIONS_API_KEY (or add the Keychain item ` + `hasna.credentials.instructions.api-key, or write ~/.hasna/instructions/config/credentials) to go hosted.`;
|
|
11786
|
-
}
|
|
11787
|
-
function isInstructionsLocalOptIn(env = process.env) {
|
|
11788
|
-
return INSTRUCTIONS_LOCAL_OPT_IN_ENV_KEYS.some((key) => (env[key] ?? "").trim() === "1");
|
|
11789
|
-
}
|
|
11790
|
-
function instructionsAuthorityEnvKeys() {
|
|
11791
|
-
const keys = clientTransportEnvKeys("instructions");
|
|
11792
|
-
return [
|
|
11793
|
-
...keys.apiUrlKeys,
|
|
11794
|
-
...keys.apiKeyKeys,
|
|
11795
|
-
credentialOverrideEnvKey("instructions"),
|
|
11796
|
-
credentialPointerEnvKey("instructions"),
|
|
11797
|
-
CREDENTIAL_PROFILE_ENV_KEY
|
|
11798
|
-
];
|
|
11799
|
-
}
|
|
11800
|
-
function hasInstructionsEnvAuthorityIntent(env = process.env) {
|
|
11801
|
-
return instructionsAuthorityEnvKeys().some((key) => (env[key] ?? "").trim() !== "");
|
|
11802
|
-
}
|
|
11803
|
-
function selectsInstructionsLocalStore(env = process.env) {
|
|
11804
|
-
return !hasInstructionsEnvAuthorityIntent(env) && isInstructionsLocalOptIn(env);
|
|
11805
|
-
}
|
|
11806
|
-
function instructionsResolverEnv(env) {
|
|
11807
|
-
const blanks = instructionsAuthorityEnvKeys().filter((key) => (key in env) && (env[key] ?? "").trim() === "");
|
|
11808
|
-
if (blanks.length === 0)
|
|
11809
|
-
return env;
|
|
11810
|
-
const next = { ...env };
|
|
11811
|
-
for (const key of blanks)
|
|
11812
|
-
delete next[key];
|
|
11813
|
-
return next;
|
|
11814
|
-
}
|
|
11815
|
-
var CONTRACTS_AMBIENT_ENVIRONMENT = Symbol.for("hasna:contracts:ambientClientEnvironment");
|
|
11816
|
-
function isAmbientInstructionsEnv(env) {
|
|
11817
|
-
if (typeof process !== "undefined" && env === process.env)
|
|
11818
|
-
return true;
|
|
11819
|
-
return env[CONTRACTS_AMBIENT_ENVIRONMENT] === true;
|
|
11820
|
-
}
|
|
11821
|
-
function instructionsResolverInputs(env, credentials = {}) {
|
|
11822
|
-
const normalised = instructionsResolverEnv(env);
|
|
11823
|
-
if (normalised === env)
|
|
11824
|
-
return { env: normalised, credentials };
|
|
11825
|
-
const keychain = { ...credentials.keychain };
|
|
11826
|
-
if (keychain.enabled === undefined && keychain.run === undefined) {
|
|
11827
|
-
keychain.enabled = isAmbientInstructionsEnv(env);
|
|
11828
|
-
}
|
|
11829
|
-
return { env: normalised, credentials: { ...credentials, keychain } };
|
|
11830
|
-
}
|
|
11831
|
-
|
|
11832
11657
|
// src/lib/transport-resolver.ts
|
|
11833
11658
|
var INSTRUCTIONS_APP = "instructions";
|
|
11834
11659
|
var INSTRUCTIONS_LOCAL_OPT_IN_ENV = INSTRUCTIONS_LOCAL_OPT_IN_ENV_KEYS[0];
|
|
@@ -11871,11 +11696,11 @@ function announceLocalInstructionsMode(write = (line) => process.stderr.write(`$
|
|
|
11871
11696
|
}
|
|
11872
11697
|
|
|
11873
11698
|
// src/data/config-store.ts
|
|
11874
|
-
function parseBoundedPagePayload(value, label) {
|
|
11699
|
+
function parseBoundedPagePayload(value, label, expected) {
|
|
11875
11700
|
const page = value;
|
|
11876
11701
|
const consumed = Number(page?.cursor) + (page?.items?.length ?? 0);
|
|
11877
11702
|
const complete = Boolean(page && Number.isSafeInteger(page.total) && consumed >= Number(page.total));
|
|
11878
|
-
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)) {
|
|
11703
|
+
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) {
|
|
11879
11704
|
throw new Error(`${label} returned an invalid or truncated bounded-read envelope`);
|
|
11880
11705
|
}
|
|
11881
11706
|
return {
|
|
@@ -11887,7 +11712,7 @@ function parseBoundedOrLegacyPage(value, legacyItems, options, label) {
|
|
|
11887
11712
|
if (value && typeof value === "object") {
|
|
11888
11713
|
const candidate = value;
|
|
11889
11714
|
if ("items" in candidate || "total" in candidate || "complete" in candidate || "truncated" in candidate || "next_cursor" in candidate) {
|
|
11890
|
-
return parseBoundedPagePayload(value, label);
|
|
11715
|
+
return parseBoundedPagePayload(value, label, normalizeBoundedReadOptions(options));
|
|
11891
11716
|
}
|
|
11892
11717
|
}
|
|
11893
11718
|
if (!Array.isArray(legacyItems)) {
|
|
@@ -11897,6 +11722,65 @@ function parseBoundedOrLegacyPage(value, legacyItems, options, label) {
|
|
|
11897
11722
|
const page = boundedReadPage(legacyItems.slice(normalized.cursor, normalized.cursor + normalized.limit), legacyItems.length, normalized);
|
|
11898
11723
|
return { ...page, source_bounded: false };
|
|
11899
11724
|
}
|
|
11725
|
+
|
|
11726
|
+
class CollectionChangedWhilePagingError extends Error {
|
|
11727
|
+
constructor(label, detail) {
|
|
11728
|
+
super(`${label} changed while paging: ${detail}`);
|
|
11729
|
+
this.name = "CollectionChangedWhilePagingError";
|
|
11730
|
+
}
|
|
11731
|
+
}
|
|
11732
|
+
var COLLECTION_READ_ATTEMPTS = 2;
|
|
11733
|
+
async function aggregateBoundedCollection(label, readPage, identity, options = {}) {
|
|
11734
|
+
let lastError = null;
|
|
11735
|
+
for (let attempt = 0;attempt < COLLECTION_READ_ATTEMPTS; attempt += 1) {
|
|
11736
|
+
try {
|
|
11737
|
+
const items = [];
|
|
11738
|
+
const seen = new Set;
|
|
11739
|
+
let expectedTotal = null;
|
|
11740
|
+
let cursor = 0;
|
|
11741
|
+
let previousIdentity = null;
|
|
11742
|
+
while (true) {
|
|
11743
|
+
const page = await readPage(cursor);
|
|
11744
|
+
if (page.cursor !== cursor) {
|
|
11745
|
+
throw new CollectionChangedWhilePagingError(label, `server returned cursor ${page.cursor} for requested cursor ${cursor}`);
|
|
11746
|
+
}
|
|
11747
|
+
if (expectedTotal === null)
|
|
11748
|
+
expectedTotal = page.total;
|
|
11749
|
+
else if (page.total !== expectedTotal) {
|
|
11750
|
+
throw new CollectionChangedWhilePagingError(label, `total changed from ${expectedTotal} to ${page.total}`);
|
|
11751
|
+
}
|
|
11752
|
+
for (const item of page.items) {
|
|
11753
|
+
const key = identity(item);
|
|
11754
|
+
if (!key)
|
|
11755
|
+
throw new CollectionChangedWhilePagingError(label, "an item had no stable identity");
|
|
11756
|
+
if (seen.has(key))
|
|
11757
|
+
throw new CollectionChangedWhilePagingError(label, `duplicate identity ${key}`);
|
|
11758
|
+
if (options.requireAscendingIdentity && page.source_bounded && previousIdentity !== null && key <= previousIdentity) {
|
|
11759
|
+
throw new CollectionChangedWhilePagingError(label, `identity order was not strictly increasing at ${key}`);
|
|
11760
|
+
}
|
|
11761
|
+
seen.add(key);
|
|
11762
|
+
previousIdentity = key;
|
|
11763
|
+
items.push(item);
|
|
11764
|
+
}
|
|
11765
|
+
if (page.complete) {
|
|
11766
|
+
if (items.length !== expectedTotal) {
|
|
11767
|
+
throw new CollectionChangedWhilePagingError(label, `received ${items.length} unique rows for total ${expectedTotal}`);
|
|
11768
|
+
}
|
|
11769
|
+
return items;
|
|
11770
|
+
}
|
|
11771
|
+
if (page.next_cursor === null || page.next_cursor <= cursor) {
|
|
11772
|
+
throw new CollectionChangedWhilePagingError(label, `cursor did not advance from ${cursor}`);
|
|
11773
|
+
}
|
|
11774
|
+
cursor = page.next_cursor;
|
|
11775
|
+
}
|
|
11776
|
+
} catch (error) {
|
|
11777
|
+
if (!(error instanceof CollectionChangedWhilePagingError))
|
|
11778
|
+
throw error;
|
|
11779
|
+
lastError = error;
|
|
11780
|
+
}
|
|
11781
|
+
}
|
|
11782
|
+
throw lastError ?? new CollectionChangedWhilePagingError(label, "read did not stabilize");
|
|
11783
|
+
}
|
|
11900
11784
|
var LOCAL_OPT_IN_ENV = INSTRUCTIONS_LOCAL_OPT_IN_ENV;
|
|
11901
11785
|
function isCloudAuthError(err) {
|
|
11902
11786
|
return typeof err === "object" && err !== null && err.name === "HasnaHttpError" && (err.status === 401 || err.status === 403);
|
|
@@ -11922,7 +11806,7 @@ function formatCliError(err, env = process.env) {
|
|
|
11922
11806
|
var localStoreModulePromise = null;
|
|
11923
11807
|
function localStoreModule() {
|
|
11924
11808
|
if (!localStoreModulePromise)
|
|
11925
|
-
localStoreModulePromise = import("./local-
|
|
11809
|
+
localStoreModulePromise = import("./local-zxa5dpf4.js");
|
|
11926
11810
|
return localStoreModulePromise;
|
|
11927
11811
|
}
|
|
11928
11812
|
|
|
@@ -11970,15 +11854,7 @@ class LocalConfigStore {
|
|
|
11970
11854
|
return (await localStoreModule()).pruneSnapshots(configId, keep, this.db);
|
|
11971
11855
|
}
|
|
11972
11856
|
async listProfiles() {
|
|
11973
|
-
|
|
11974
|
-
let cursor = 0;
|
|
11975
|
-
while (true) {
|
|
11976
|
-
const page = await this.listProfilesPage({ limit: 100, cursor });
|
|
11977
|
-
profiles.push(...page.items);
|
|
11978
|
-
if (page.complete)
|
|
11979
|
-
return profiles;
|
|
11980
|
-
cursor = page.next_cursor;
|
|
11981
|
-
}
|
|
11857
|
+
return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id);
|
|
11982
11858
|
}
|
|
11983
11859
|
async listProfilesPage(options = {}) {
|
|
11984
11860
|
return (await localStoreModule()).listProfilesPage(options, this.db);
|
|
@@ -11987,15 +11863,7 @@ class LocalConfigStore {
|
|
|
11987
11863
|
return (await localStoreModule()).getProfile(idOrSlug, this.db);
|
|
11988
11864
|
}
|
|
11989
11865
|
async getProfileConfigs(idOrSlug) {
|
|
11990
|
-
|
|
11991
|
-
let cursor = 0;
|
|
11992
|
-
while (true) {
|
|
11993
|
-
const page = await this.getProfileConfigsPage(idOrSlug, { limit: 100, cursor });
|
|
11994
|
-
configs.push(...page.items);
|
|
11995
|
-
if (page.complete)
|
|
11996
|
-
return configs;
|
|
11997
|
-
cursor = page.next_cursor;
|
|
11998
|
-
}
|
|
11866
|
+
return aggregateBoundedCollection("profile membership", (cursor) => this.getProfileConfigsPage(idOrSlug, { limit: 100, cursor }), (config) => config.id);
|
|
11999
11867
|
}
|
|
12000
11868
|
async getProfileConfigsPage(idOrSlug, options = {}) {
|
|
12001
11869
|
return (await localStoreModule()).getProfileConfigsPage(idOrSlug, options, this.db);
|
|
@@ -12076,7 +11944,8 @@ class CloudConfigStore {
|
|
|
12076
11944
|
throw err;
|
|
12077
11945
|
}
|
|
12078
11946
|
}
|
|
12079
|
-
async
|
|
11947
|
+
async listConfigsPageRemote(filter, options) {
|
|
11948
|
+
const normalized = normalizeBoundedReadOptions(options);
|
|
12080
11949
|
const params = new URLSearchParams;
|
|
12081
11950
|
if (filter.category)
|
|
12082
11951
|
params.set("category", filter.category);
|
|
@@ -12086,16 +11955,21 @@ class CloudConfigStore {
|
|
|
12086
11955
|
params.set("kind", filter.kind);
|
|
12087
11956
|
if (filter.search)
|
|
12088
11957
|
params.set("search", filter.search);
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
11958
|
+
params.set("limit", String(normalized.limit));
|
|
11959
|
+
params.set("cursor", String(normalized.cursor));
|
|
11960
|
+
const { data } = await this.request("GET", `/configs?${params.toString()}`);
|
|
11961
|
+
return parseBoundedOrLegacyPage(data, data?.configs, normalized, "config list");
|
|
11962
|
+
}
|
|
11963
|
+
async listConfigs(filter = {}) {
|
|
11964
|
+
const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPageRemote(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
|
|
11965
|
+
let filtered = configs;
|
|
12092
11966
|
if (filter.tags && filter.tags.length > 0) {
|
|
12093
|
-
|
|
11967
|
+
filtered = filtered.filter((config) => filter.tags.every((tag) => config.tags.includes(tag)));
|
|
12094
11968
|
}
|
|
12095
11969
|
if (filter.is_template !== undefined) {
|
|
12096
|
-
|
|
11970
|
+
filtered = filtered.filter((config) => config.is_template === filter.is_template);
|
|
12097
11971
|
}
|
|
12098
|
-
return
|
|
11972
|
+
return filtered;
|
|
12099
11973
|
}
|
|
12100
11974
|
async getConfig(idOrSlug) {
|
|
12101
11975
|
const { status, data } = await this.request("GET", `/configs/${encodeURIComponent(idOrSlug)}`, undefined, { allow404: true });
|
|
@@ -12126,8 +12000,11 @@ class CloudConfigStore {
|
|
|
12126
12000
|
return data ?? { total: 0 };
|
|
12127
12001
|
}
|
|
12128
12002
|
async listSnapshots(configId) {
|
|
12129
|
-
|
|
12130
|
-
|
|
12003
|
+
return aggregateBoundedCollection("snapshot list", async (cursor) => {
|
|
12004
|
+
const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
|
|
12005
|
+
const { data } = await this.request("GET", `/configs/${encodeURIComponent(configId)}/snapshots?limit=${normalized.limit}&cursor=${normalized.cursor}`);
|
|
12006
|
+
return parseBoundedOrLegacyPage(data, data?.snapshots, normalized, "snapshot list");
|
|
12007
|
+
}, (snapshot) => snapshot.id);
|
|
12131
12008
|
}
|
|
12132
12009
|
async getSnapshot(id) {
|
|
12133
12010
|
const { status, data } = await this.request("GET", `/snapshots/${encodeURIComponent(id)}`, undefined, { allow404: true });
|
|
@@ -12150,15 +12027,7 @@ class CloudConfigStore {
|
|
|
12150
12027
|
return data?.pruned ?? 0;
|
|
12151
12028
|
}
|
|
12152
12029
|
async listProfiles() {
|
|
12153
|
-
|
|
12154
|
-
let cursor = 0;
|
|
12155
|
-
while (true) {
|
|
12156
|
-
const page = await this.listProfilesPage({ limit: 100, cursor });
|
|
12157
|
-
profiles.push(...page.items);
|
|
12158
|
-
if (page.complete)
|
|
12159
|
-
return profiles;
|
|
12160
|
-
cursor = page.next_cursor;
|
|
12161
|
-
}
|
|
12030
|
+
return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id, { requireAscendingIdentity: true });
|
|
12162
12031
|
}
|
|
12163
12032
|
async listProfilesPage(options = {}) {
|
|
12164
12033
|
const normalized = normalizeBoundedReadOptions(options);
|
|
@@ -12182,15 +12051,7 @@ class CloudConfigStore {
|
|
|
12182
12051
|
return profile;
|
|
12183
12052
|
}
|
|
12184
12053
|
async getProfileConfigs(idOrSlug) {
|
|
12185
|
-
|
|
12186
|
-
let cursor = 0;
|
|
12187
|
-
while (true) {
|
|
12188
|
-
const page = await this.getProfileConfigsPage(idOrSlug, { limit: 100, cursor });
|
|
12189
|
-
configs.push(...page.items);
|
|
12190
|
-
if (page.complete)
|
|
12191
|
-
return configs;
|
|
12192
|
-
cursor = page.next_cursor;
|
|
12193
|
-
}
|
|
12054
|
+
return aggregateBoundedCollection("profile membership", (cursor) => this.getProfileConfigsPage(idOrSlug, { limit: 100, cursor }), (config) => config.id);
|
|
12194
12055
|
}
|
|
12195
12056
|
async getProfileConfigsPage(idOrSlug, options = {}) {
|
|
12196
12057
|
const normalized = normalizeBoundedReadOptions(options);
|
|
@@ -12204,20 +12065,26 @@ class CloudConfigStore {
|
|
|
12204
12065
|
return parseBoundedOrLegacyPage(data.configs, data.profile.configs, normalized, "profile membership");
|
|
12205
12066
|
}
|
|
12206
12067
|
async getProfileConfigBindings(idOrSlug) {
|
|
12207
|
-
|
|
12208
|
-
|
|
12209
|
-
const
|
|
12210
|
-
const
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
|
|
12068
|
+
let routeMissing = false;
|
|
12069
|
+
const bindings = await aggregateBoundedCollection("profile config bindings", async (cursor) => {
|
|
12070
|
+
const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
|
|
12071
|
+
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))));
|
|
12072
|
+
if (status === 404) {
|
|
12073
|
+
routeMissing = true;
|
|
12074
|
+
return { ...boundedReadPage([], 0, normalized), source_bounded: false };
|
|
12075
|
+
}
|
|
12076
|
+
return parseBoundedOrLegacyPage(data, data?.bindings, normalized, "profile config bindings");
|
|
12077
|
+
}, (binding) => `${binding.profile_id}\x00${binding.config_id}`);
|
|
12078
|
+
if (!routeMissing)
|
|
12079
|
+
return bindings;
|
|
12080
|
+
const profile = await this.getProfile(idOrSlug);
|
|
12081
|
+
const configs = await this.getProfileConfigs(idOrSlug);
|
|
12082
|
+
return configs.map((config, sort_order) => ({
|
|
12083
|
+
profile_id: profile.id,
|
|
12084
|
+
config_id: config.id,
|
|
12085
|
+
sort_order,
|
|
12086
|
+
binding: legacyProfileConfigBinding()
|
|
12087
|
+
}));
|
|
12221
12088
|
}
|
|
12222
12089
|
async requestProfileRoute(idOrSlug, pathForId, isUsable) {
|
|
12223
12090
|
const attempted = new Set;
|
|
@@ -12275,14 +12142,20 @@ class CloudConfigStore {
|
|
|
12275
12142
|
await this.request("DELETE", `/profiles/${encodeURIComponent(profileIdOrSlug)}/configs/${encodeURIComponent(configId)}`, undefined, { allow404: true });
|
|
12276
12143
|
}
|
|
12277
12144
|
async getProfileAssetBindings(profileIdOrSlug) {
|
|
12278
|
-
|
|
12279
|
-
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
|
|
12285
|
-
|
|
12145
|
+
let routeMissing = false;
|
|
12146
|
+
const assets = await aggregateBoundedCollection("profile asset bindings", async (cursor) => {
|
|
12147
|
+
const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
|
|
12148
|
+
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))));
|
|
12149
|
+
if (status === 404) {
|
|
12150
|
+
routeMissing = true;
|
|
12151
|
+
return { ...boundedReadPage([], 0, normalized), source_bounded: false };
|
|
12152
|
+
}
|
|
12153
|
+
return parseBoundedOrLegacyPage(data, data?.assets, normalized, "profile asset bindings");
|
|
12154
|
+
}, (asset) => `${asset.profile_id}\x00${asset.binding.assetKey}`);
|
|
12155
|
+
if (!routeMissing)
|
|
12156
|
+
return assets;
|
|
12157
|
+
await this.getProfile(profileIdOrSlug);
|
|
12158
|
+
return [];
|
|
12286
12159
|
}
|
|
12287
12160
|
async addAssetToProfile(profileIdOrSlug, sourceConfigId, binding) {
|
|
12288
12161
|
const { data } = await this.request("POST", `/profiles/${encodeURIComponent(profileIdOrSlug)}/assets`, { source_config_id: sourceConfigId, binding }, { idempotent: true });
|
|
@@ -12352,8 +12225,11 @@ class CloudConfigStore {
|
|
|
12352
12225
|
await this.request("POST", "/machines/applied", { hostname });
|
|
12353
12226
|
}
|
|
12354
12227
|
async listMachines() {
|
|
12355
|
-
|
|
12356
|
-
|
|
12228
|
+
return aggregateBoundedCollection("machine list", async (cursor) => {
|
|
12229
|
+
const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
|
|
12230
|
+
const { data } = await this.request("GET", `/machines?limit=${normalized.limit}&cursor=${normalized.cursor}`);
|
|
12231
|
+
return parseBoundedOrLegacyPage(data, data?.machines, normalized, "machine list");
|
|
12232
|
+
}, (machine) => machine.id, { requireAscendingIdentity: true });
|
|
12357
12233
|
}
|
|
12358
12234
|
async sendFeedback(input) {
|
|
12359
12235
|
await this.request("POST", "/feedback", {
|
|
@@ -12603,9 +12479,9 @@ async function ensureGlobalAgentRulesStandardConfig(store = resolveConfigStore()
|
|
|
12603
12479
|
}
|
|
12604
12480
|
|
|
12605
12481
|
// src/lib/machine.ts
|
|
12606
|
-
import { arch as currentArch, homedir as
|
|
12607
|
-
import { existsSync as
|
|
12608
|
-
import { join as
|
|
12482
|
+
import { arch as currentArch, homedir as homedir5, hostname as currentHostname, type as currentOsType } from "os";
|
|
12483
|
+
import { existsSync as existsSync5 } from "fs";
|
|
12484
|
+
import { join as join7 } from "path";
|
|
12609
12485
|
var BREW_BUN_PATH = "/opt/homebrew/bin/bun";
|
|
12610
12486
|
function normalizeOsFamily(os) {
|
|
12611
12487
|
const value = (os ?? "").trim().toLowerCase();
|
|
@@ -12618,11 +12494,11 @@ function normalizeOsFamily(os) {
|
|
|
12618
12494
|
return value || "unknown";
|
|
12619
12495
|
}
|
|
12620
12496
|
function detectMachineContext(overrides = {}) {
|
|
12621
|
-
const
|
|
12497
|
+
const homeDir4 = overrides.home_dir ?? process.env["CONFIGS_HOME"] ?? process.env["HOME"] ?? homedir5();
|
|
12622
12498
|
const os = overrides.os ?? currentOsType();
|
|
12623
12499
|
const osFamily = normalizeOsFamily(os);
|
|
12624
|
-
const bunBinDir = overrides.bun_bin_dir ??
|
|
12625
|
-
const defaultBunPath = osFamily === "macos" &&
|
|
12500
|
+
const bunBinDir = overrides.bun_bin_dir ?? join7(homeDir4, ".bun", "bin");
|
|
12501
|
+
const defaultBunPath = osFamily === "macos" && existsSync5(BREW_BUN_PATH) ? BREW_BUN_PATH : join7(bunBinDir, "bun");
|
|
12626
12502
|
return {
|
|
12627
12503
|
id: "current-machine",
|
|
12628
12504
|
hostname: overrides.hostname ?? currentHostname(),
|
|
@@ -12631,11 +12507,11 @@ function detectMachineContext(overrides = {}) {
|
|
|
12631
12507
|
last_applied_at: null,
|
|
12632
12508
|
created_at: "",
|
|
12633
12509
|
os_family: osFamily,
|
|
12634
|
-
home_dir:
|
|
12635
|
-
workspace_root: overrides.workspace_root ??
|
|
12510
|
+
home_dir: homeDir4,
|
|
12511
|
+
workspace_root: overrides.workspace_root ?? join7(homeDir4, osFamily === "macos" ? "Workspace" : "workspace"),
|
|
12636
12512
|
bun_bin_dir: bunBinDir,
|
|
12637
12513
|
bun_path: overrides.bun_path ?? defaultBunPath,
|
|
12638
|
-
path_prefix: overrides.path_prefix ?? (osFamily === "macos" ? `${
|
|
12514
|
+
path_prefix: overrides.path_prefix ?? (osFamily === "macos" ? `${join7("/opt", "homebrew", "bin")}:${bunBinDir}` : bunBinDir)
|
|
12639
12515
|
};
|
|
12640
12516
|
}
|
|
12641
12517
|
function machineContextToVariables(machine) {
|
|
@@ -12699,4 +12575,4 @@ function renderMachineAwareContentPreview(content, variables) {
|
|
|
12699
12575
|
return isTemplate(content) ? renderTemplatePreview(content, variables) : { content, unresolved: [] };
|
|
12700
12576
|
}
|
|
12701
12577
|
|
|
12702
|
-
export { DEFAULT_LIST_LIMIT, parseLimit, paginate, truncateText, truncateMiddle, normalizeBoundedReadOptions, boundedReadPage, ensureGlobalAgentRulesStandardConfig, ensureCodewithSharedTodosStorageStandardConfig, redactFormatForTarget, redactContent, scanSecrets, isSecretVarName, SESSION_RENDER_MANAGED_MARKER, SESSION_RENDER_SCHEMA, SESSION_RENDER_MANIFEST_RELATIVE_PATH, SESSION_INSTRUCTION_LAYERS, getSessionRenderSnapshotDir, sessionRenderSnapshotWorkspaceRoot, PROJECT_CONTEXT_MAX_INPUT_BYTES, SESSION_MANAGED_INPUT_MAX_BYTES, ProjectContextError, parseProjectContextBundle, planProjectContext, observeProjectContextSessionGuard, withProjectContextSessionGuard, applyProjectContext, writeProjectContextCoordinatedFile, removeProjectContextCoordinatedFile, isRetiredOrUnsupportedConfigAgent, retiredOrUnsupportedAgentReason, applyTransform, normalizeProfileAssetBinding, observeCursorGlobalAuthorityAtPath, isCursorGlobalAuthorityPath, stampCursorGlobalAuthorityMarker, detectCursorAuthorityConflicts, detectClaudeAuthorityConflicts,
|
|
12578
|
+
export { DEFAULT_LIST_LIMIT, parseLimit, paginate, truncateText, truncateMiddle, normalizeBoundedReadOptions, boundedReadPage, ensureGlobalAgentRulesStandardConfig, ensureCodewithSharedTodosStorageStandardConfig, redactFormatForTarget, redactContent, scanSecrets, isSecretVarName, SESSION_RENDER_MANAGED_MARKER, SESSION_RENDER_SCHEMA, SESSION_RENDER_MANIFEST_RELATIVE_PATH, SESSION_INSTRUCTION_LAYERS, getSessionRenderSnapshotDir, sessionRenderSnapshotWorkspaceRoot, PROJECT_CONTEXT_MAX_INPUT_BYTES, SESSION_MANAGED_INPUT_MAX_BYTES, ProjectContextError, parseProjectContextBundle, planProjectContext, observeProjectContextSessionGuard, withProjectContextSessionGuard, applyProjectContext, writeProjectContextCoordinatedFile, removeProjectContextCoordinatedFile, isRetiredOrUnsupportedConfigAgent, retiredOrUnsupportedAgentReason, applyTransform, normalizeProfileAssetBinding, observeCursorGlobalAuthorityAtPath, isCursorGlobalAuthorityPath, stampCursorGlobalAuthorityMarker, detectCursorAuthorityConflicts, detectClaudeAuthorityConflicts, ANTIGRAVITY_RULE_FILE_CHAR_LIMIT, SESSION_RENDERER_OWNER_ID, SESSION_RENDER_TOOLS, SESSION_RENDER_OWNED_CONFIG_TARGETS, SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS, normalizeSessionInstructionSourceId, resolveSessionPath, planSessionRender, sourceFromFilePath, sourceFromConfig, sourcesFromIdentityExport, legacyProfileConfigBinding, normalizeProfileConfigBinding, planProfileSessionRender, normalizeOsFamily, detectMachineContext, machineContextToVariables, resolveProfileVariables, templateizeMachineContent, renderMachineAwareContentPreview, formatCliError, CloudConfigStore, resolveConfigStore };
|