@odla-ai/cli 0.25.20 → 0.25.21
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 +12 -0
- package/dist/bin.cjs +733 -616
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-ONETPJFW.js → chunk-L2NG4UR4.js} +734 -617
- package/dist/chunk-L2NG4UR4.js.map +1 -0
- package/dist/index.cjs +733 -616
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ONETPJFW.js.map +0 -1
|
@@ -17,22 +17,22 @@ function readJsonFile(path) {
|
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
function writePrivateJson(path,
|
|
21
|
-
writePrivateText(path, `${JSON.stringify(
|
|
20
|
+
function writePrivateJson(path, value2) {
|
|
21
|
+
writePrivateText(path, `${JSON.stringify(value2, null, 2)}
|
|
22
22
|
`);
|
|
23
23
|
}
|
|
24
24
|
function readCredentials(path) {
|
|
25
25
|
if (!existsSync(path)) return null;
|
|
26
|
-
let
|
|
26
|
+
let value2;
|
|
27
27
|
try {
|
|
28
|
-
|
|
28
|
+
value2 = JSON.parse(readFileSync(path, "utf8"));
|
|
29
29
|
} catch {
|
|
30
30
|
throw new Error(`credentials file ${path} is not valid JSON; fix or remove it before provisioning`);
|
|
31
31
|
}
|
|
32
|
-
if (!
|
|
32
|
+
if (!value2 || typeof value2 !== "object" || typeof value2.appId !== "string" || !value2.envs || typeof value2.envs !== "object") {
|
|
33
33
|
throw new Error(`credentials file ${path} has an invalid shape; fix or remove it before provisioning`);
|
|
34
34
|
}
|
|
35
|
-
return
|
|
35
|
+
return value2;
|
|
36
36
|
}
|
|
37
37
|
function mergeCredential(current, update) {
|
|
38
38
|
const next = current ?? {
|
|
@@ -366,8 +366,8 @@ function stillPending(pending, email) {
|
|
|
366
366
|
{ retryable: true }
|
|
367
367
|
);
|
|
368
368
|
}
|
|
369
|
-
function handshakeEmail(
|
|
370
|
-
const email = (
|
|
369
|
+
function handshakeEmail(value2, cached) {
|
|
370
|
+
const email = (value2 ?? process4.env.ODLA_USER_EMAIL ?? cached ?? "").trim().toLowerCase();
|
|
371
371
|
if (email.length > 254 || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
372
372
|
throw new Error("a fresh odla handshake requires --email <account> or ODLA_USER_EMAIL");
|
|
373
373
|
}
|
|
@@ -391,10 +391,10 @@ function handshakeUrl(platformUrl, userCode) {
|
|
|
391
391
|
url.searchParams.set("code", userCode);
|
|
392
392
|
return url.toString();
|
|
393
393
|
}
|
|
394
|
-
function platformAudience(
|
|
394
|
+
function platformAudience(value2) {
|
|
395
395
|
let url;
|
|
396
396
|
try {
|
|
397
|
-
url = new URL(
|
|
397
|
+
url = new URL(value2);
|
|
398
398
|
} catch {
|
|
399
399
|
throw new Error("platform must be an absolute URL");
|
|
400
400
|
}
|
|
@@ -436,6 +436,7 @@ function audienceBoundEnvToken(token, platform) {
|
|
|
436
436
|
return token;
|
|
437
437
|
}
|
|
438
438
|
var SCOPE_PURPOSE = {
|
|
439
|
+
"platform:status:read": "read the platform fleet health and deployment snapshot",
|
|
439
440
|
"platform:runbook:write": "add or edit odla's operational runbooks",
|
|
440
441
|
"platform:ai:policy:write": "change System AI model routing",
|
|
441
442
|
"platform:ai:policy:read": "read System AI model routing",
|
|
@@ -499,11 +500,11 @@ var SYSTEM_AI_PURPOSES = [
|
|
|
499
500
|
"security.validation",
|
|
500
501
|
"runbook.answer"
|
|
501
502
|
];
|
|
502
|
-
function requireSystemAiPurpose(
|
|
503
|
-
if (!SYSTEM_AI_PURPOSES.includes(
|
|
503
|
+
function requireSystemAiPurpose(value2) {
|
|
504
|
+
if (!SYSTEM_AI_PURPOSES.includes(value2)) {
|
|
504
505
|
throw new Error(`purpose must be one of: ${SYSTEM_AI_PURPOSES.join(", ")}`);
|
|
505
506
|
}
|
|
506
|
-
return
|
|
507
|
+
return value2;
|
|
507
508
|
}
|
|
508
509
|
|
|
509
510
|
// src/admin-ai.ts
|
|
@@ -514,22 +515,22 @@ import process6 from "process";
|
|
|
514
515
|
var MAX_BYTES = 64 * 1024;
|
|
515
516
|
async function secretInputValue(options, kind = "credential") {
|
|
516
517
|
if (options.fromEnv && options.stdin) throw new Error("choose exactly one of --from-env or --stdin");
|
|
517
|
-
let
|
|
518
|
-
if (options.fromEnv)
|
|
519
|
-
else if (options.stdin)
|
|
518
|
+
let value2;
|
|
519
|
+
if (options.fromEnv) value2 = process6.env[options.fromEnv];
|
|
520
|
+
else if (options.stdin) value2 = await (options.readStdin ?? (() => readSecretStream(kind)))();
|
|
520
521
|
else throw new Error(`${kind} input required: use --from-env <NAME> or --stdin; values are never accepted as arguments`);
|
|
521
|
-
|
|
522
|
-
if (!
|
|
523
|
-
if (new TextEncoder().encode(
|
|
524
|
-
return
|
|
522
|
+
value2 = value2?.replace(/[\r\n]+$/, "");
|
|
523
|
+
if (!value2) throw new Error(options.fromEnv ? `environment variable ${options.fromEnv} is empty or unset` : `stdin ${kind} is empty`);
|
|
524
|
+
if (new TextEncoder().encode(value2).byteLength > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
|
|
525
|
+
return value2;
|
|
525
526
|
}
|
|
526
527
|
async function readSecretStream(kind, stream = process6.stdin) {
|
|
527
|
-
let
|
|
528
|
+
let value2 = "";
|
|
528
529
|
for await (const chunk of stream) {
|
|
529
|
-
|
|
530
|
-
if (
|
|
530
|
+
value2 += String(chunk);
|
|
531
|
+
if (value2.length > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
|
|
531
532
|
}
|
|
532
|
-
return
|
|
533
|
+
return value2;
|
|
533
534
|
}
|
|
534
535
|
|
|
535
536
|
// src/admin-ai-audit.ts
|
|
@@ -579,13 +580,13 @@ function apiError(status, body) {
|
|
|
579
580
|
const message2 = error && typeof error.message === "string" ? error.message : isRecord(body) && typeof body.message === "string" ? body.message : "request failed";
|
|
580
581
|
return `read System AI admin changes failed (${status}): ${message2}`;
|
|
581
582
|
}
|
|
582
|
-
function timestamp(
|
|
583
|
-
if (typeof
|
|
584
|
-
const date = new Date(
|
|
583
|
+
function timestamp(value2) {
|
|
584
|
+
if (typeof value2 !== "number" || !Number.isFinite(value2)) return String(value2 ?? "");
|
|
585
|
+
const date = new Date(value2);
|
|
585
586
|
return Number.isFinite(date.valueOf()) ? date.toISOString() : "";
|
|
586
587
|
}
|
|
587
|
-
function isRecord(
|
|
588
|
-
return Boolean(
|
|
588
|
+
function isRecord(value2) {
|
|
589
|
+
return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
|
|
589
590
|
}
|
|
590
591
|
|
|
591
592
|
// src/admin-ai-usage.ts
|
|
@@ -607,11 +608,11 @@ async function readAdminAiUsage(request2) {
|
|
|
607
608
|
if (request2.json) request2.stdout.log(JSON.stringify(body, null, 2));
|
|
608
609
|
else printUsage(body, request2.stdout);
|
|
609
610
|
}
|
|
610
|
-
function usageLimit(
|
|
611
|
-
if (!Number.isSafeInteger(
|
|
611
|
+
function usageLimit(value2) {
|
|
612
|
+
if (!Number.isSafeInteger(value2) || value2 < 1 || value2 > 500) {
|
|
612
613
|
throw new Error("usage limit must be an integer from 1 to 500");
|
|
613
614
|
}
|
|
614
|
-
return
|
|
615
|
+
return value2;
|
|
615
616
|
}
|
|
616
617
|
function printUsage(body, out) {
|
|
617
618
|
const aggregates = isRecord2(body) && isRecord2(body.aggregates) && Array.isArray(body.aggregates.byStatus) ? body.aggregates.byStatus.filter(isRecord2) : [];
|
|
@@ -647,15 +648,15 @@ when app/env run actor purpose/role route / policy tokens cost status`);
|
|
|
647
648
|
].join(" "));
|
|
648
649
|
}
|
|
649
650
|
}
|
|
650
|
-
function numeric(
|
|
651
|
-
return typeof
|
|
651
|
+
function numeric(value2) {
|
|
652
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? value2 : 0;
|
|
652
653
|
}
|
|
653
|
-
function formatMicrousd(
|
|
654
|
-
return typeof
|
|
654
|
+
function formatMicrousd(value2) {
|
|
655
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? `$${(value2 / 1e6).toFixed(6)}` : "unpriced";
|
|
655
656
|
}
|
|
656
|
-
function timestamp2(
|
|
657
|
-
if (typeof
|
|
658
|
-
const date = new Date(
|
|
657
|
+
function timestamp2(value2) {
|
|
658
|
+
if (typeof value2 !== "number" || !Number.isFinite(value2)) return String(value2 ?? "");
|
|
659
|
+
const date = new Date(value2);
|
|
659
660
|
return Number.isFinite(date.valueOf()) ? date.toISOString() : "";
|
|
660
661
|
}
|
|
661
662
|
async function responseBody2(res) {
|
|
@@ -672,8 +673,8 @@ function apiError2(action, status, body) {
|
|
|
672
673
|
const message2 = error && typeof error.message === "string" ? error.message : isRecord2(body) && typeof body.message === "string" ? body.message : "request failed";
|
|
673
674
|
return `${action} failed (${status}): ${message2}`;
|
|
674
675
|
}
|
|
675
|
-
function isRecord2(
|
|
676
|
-
return Boolean(
|
|
676
|
+
function isRecord2(value2) {
|
|
677
|
+
return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
|
|
677
678
|
}
|
|
678
679
|
|
|
679
680
|
// src/admin-ai.ts
|
|
@@ -718,11 +719,11 @@ async function adminAi(options) {
|
|
|
718
719
|
}
|
|
719
720
|
if (options.action === "credential-set") {
|
|
720
721
|
const provider = requireProvider(options.credentialProvider);
|
|
721
|
-
const
|
|
722
|
+
const value2 = await secretInputValue(options);
|
|
722
723
|
const res2 = await doFetch(`${platform}/registry/platform/ai-credentials/${encodeURIComponent(provider)}`, {
|
|
723
724
|
method: "PUT",
|
|
724
725
|
headers,
|
|
725
|
-
body: JSON.stringify({ value })
|
|
726
|
+
body: JSON.stringify({ value: value2 })
|
|
726
727
|
});
|
|
727
728
|
const body2 = await responseBody3(res2);
|
|
728
729
|
if (!res2.ok) throw new Error(apiError3(`store ${provider} platform credential`, res2.status, body2));
|
|
@@ -822,11 +823,11 @@ async function adminAi(options) {
|
|
|
822
823
|
const policy = isRecord3(response2) && isRecord3(response2.policy) ? response2.policy : isRecord3(response2) ? response2 : {};
|
|
823
824
|
out.log(options.json ? JSON.stringify({ policy }, null, 2) : `updated ${purpose}: ${String(policy.provider ?? "unchanged")}/${String(policy.model ?? "unchanged")}`);
|
|
824
825
|
}
|
|
825
|
-
function requireProvider(
|
|
826
|
-
if (
|
|
826
|
+
function requireProvider(value2) {
|
|
827
|
+
if (value2 !== "anthropic" && value2 !== "openai" && value2 !== "google") {
|
|
827
828
|
throw new Error("provider must be one of: anthropic, openai, google");
|
|
828
829
|
}
|
|
829
|
-
return
|
|
830
|
+
return value2;
|
|
830
831
|
}
|
|
831
832
|
function policyArray(body) {
|
|
832
833
|
if (isRecord3(body) && Array.isArray(body.policies)) return body.policies.filter(isRecord3);
|
|
@@ -837,7 +838,7 @@ function catalogModels(body) {
|
|
|
837
838
|
if (!isRecord3(body) || !isRecord3(body.catalog) || !Array.isArray(body.catalog.models)) {
|
|
838
839
|
throw new Error("platform returned an invalid System AI model catalog");
|
|
839
840
|
}
|
|
840
|
-
return body.catalog.models.filter((
|
|
841
|
+
return body.catalog.models.filter((value2) => isRecord3(value2) && typeof value2.id === "string" && typeof value2.provider === "string");
|
|
841
842
|
}
|
|
842
843
|
async function responseBody3(res) {
|
|
843
844
|
const text = await res.text();
|
|
@@ -853,8 +854,8 @@ function apiError3(action, status, body) {
|
|
|
853
854
|
const message2 = error && typeof error.message === "string" ? error.message : isRecord3(body) && typeof body.message === "string" ? body.message : "request failed";
|
|
854
855
|
return `${action} failed (${status}): ${message2}`;
|
|
855
856
|
}
|
|
856
|
-
function isRecord3(
|
|
857
|
-
return Boolean(
|
|
857
|
+
function isRecord3(value2) {
|
|
858
|
+
return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
|
|
858
859
|
}
|
|
859
860
|
|
|
860
861
|
// src/config.ts
|
|
@@ -916,17 +917,17 @@ function validateProbes(integration, at) {
|
|
|
916
917
|
}
|
|
917
918
|
}
|
|
918
919
|
}
|
|
919
|
-
function isRecord4(
|
|
920
|
-
return
|
|
920
|
+
function isRecord4(value2) {
|
|
921
|
+
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
921
922
|
}
|
|
922
|
-
function safeText(
|
|
923
|
-
return typeof
|
|
923
|
+
function safeText(value2, max) {
|
|
924
|
+
return typeof value2 === "string" && value2.trim().length > 0 && value2.length <= max && !/[\u0000-\u001f\u007f]/.test(value2);
|
|
924
925
|
}
|
|
925
|
-
function safeProbePath(
|
|
926
|
-
return typeof
|
|
926
|
+
function safeProbePath(value2) {
|
|
927
|
+
return typeof value2 === "string" && /^\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/.test(value2);
|
|
927
928
|
}
|
|
928
|
-
function validId(
|
|
929
|
-
return typeof
|
|
929
|
+
function validId(value2) {
|
|
930
|
+
return typeof value2 === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value2);
|
|
930
931
|
}
|
|
931
932
|
function unique(values) {
|
|
932
933
|
return [...new Set(values.filter(Boolean))];
|
|
@@ -968,10 +969,10 @@ async function loadProjectConfig(configPath = "odla.config.mjs") {
|
|
|
968
969
|
local
|
|
969
970
|
};
|
|
970
971
|
}
|
|
971
|
-
async function resolveDataExport(cfg,
|
|
972
|
-
if (
|
|
973
|
-
if (typeof
|
|
974
|
-
const target = isAbsolute2(
|
|
972
|
+
async function resolveDataExport(cfg, value2, names) {
|
|
973
|
+
if (value2 === void 0 || value2 === null || value2 === false) return void 0;
|
|
974
|
+
if (typeof value2 !== "string") return value2;
|
|
975
|
+
const target = isAbsolute2(value2) ? value2 : resolve2(cfg.rootDir, value2);
|
|
975
976
|
if (target.endsWith(".json")) {
|
|
976
977
|
return JSON.parse(readFileSync2(target, "utf8"));
|
|
977
978
|
}
|
|
@@ -980,7 +981,7 @@ async function resolveDataExport(cfg, value, names) {
|
|
|
980
981
|
if (mod[name] !== void 0) return mod[name];
|
|
981
982
|
}
|
|
982
983
|
if (mod.default !== void 0) return mod.default;
|
|
983
|
-
throw new Error(`${
|
|
984
|
+
throw new Error(`${value2} did not export ${names.join(", ")} or default`);
|
|
984
985
|
}
|
|
985
986
|
function buildPlan(cfg) {
|
|
986
987
|
const integrationSchema = cfg.integrations?.some((integration) => integration.schema) ?? false;
|
|
@@ -1014,9 +1015,9 @@ function calendarServiceConfig(cfg, env) {
|
|
|
1014
1015
|
};
|
|
1015
1016
|
}
|
|
1016
1017
|
function calendarBookingPageUrl(cfg, env) {
|
|
1017
|
-
const
|
|
1018
|
-
if (
|
|
1019
|
-
return new URL(
|
|
1018
|
+
const value2 = cfg.calendar?.google.bookingPageUrl?.[env];
|
|
1019
|
+
if (value2 === void 0 || value2 === null) return value2;
|
|
1020
|
+
return new URL(value2).toString();
|
|
1020
1021
|
}
|
|
1021
1022
|
function rulesFromSchema(schema) {
|
|
1022
1023
|
const entities = serializedEntities(schema);
|
|
@@ -1030,10 +1031,10 @@ function serializedEntities(schema) {
|
|
|
1030
1031
|
if (!entities || typeof entities !== "object" || Array.isArray(entities)) return [];
|
|
1031
1032
|
return Object.keys(entities);
|
|
1032
1033
|
}
|
|
1033
|
-
function envValue(
|
|
1034
|
-
if (!
|
|
1035
|
-
if (
|
|
1036
|
-
return
|
|
1034
|
+
function envValue(value2) {
|
|
1035
|
+
if (!value2) return void 0;
|
|
1036
|
+
if (value2.startsWith("$")) return process.env[value2.slice(1)];
|
|
1037
|
+
return value2;
|
|
1037
1038
|
}
|
|
1038
1039
|
function validateRawConfig(raw, path) {
|
|
1039
1040
|
if (!raw || typeof raw !== "object") throw new Error(`${path} must export an object`);
|
|
@@ -1089,8 +1090,8 @@ function validateCalendarConfig(cfg, envs, services, path) {
|
|
|
1089
1090
|
if (!isRecord5(google.bookingCalendar)) throw new Error(`${path}: calendar.google.bookingCalendar must map env names to one calendar id`);
|
|
1090
1091
|
const unknownBookingEnv = Object.keys(google.bookingCalendar).find((env) => !envs.includes(env));
|
|
1091
1092
|
if (unknownBookingEnv) throw new Error(`${path}: calendar.google.bookingCalendar.${unknownBookingEnv} is not in config envs`);
|
|
1092
|
-
for (const [env,
|
|
1093
|
-
if (!safeText2(
|
|
1093
|
+
for (const [env, value2] of Object.entries(google.bookingCalendar)) {
|
|
1094
|
+
if (!safeText2(value2, 1024)) {
|
|
1094
1095
|
throw new Error(`${path}: calendar.google.bookingCalendar.${env} must be a calendar id`);
|
|
1095
1096
|
}
|
|
1096
1097
|
}
|
|
@@ -1099,8 +1100,8 @@ function validateCalendarConfig(cfg, envs, services, path) {
|
|
|
1099
1100
|
if (!isRecord5(google.bookingPageUrl)) throw new Error(`${path}: calendar.google.bookingPageUrl must map env names to HTTPS URLs or null`);
|
|
1100
1101
|
const unknownBookingEnv = Object.keys(google.bookingPageUrl).find((env) => !envs.includes(env));
|
|
1101
1102
|
if (unknownBookingEnv) throw new Error(`${path}: calendar.google.bookingPageUrl.${unknownBookingEnv} is not in config envs`);
|
|
1102
|
-
for (const [env,
|
|
1103
|
-
if (
|
|
1103
|
+
for (const [env, value2] of Object.entries(google.bookingPageUrl)) {
|
|
1104
|
+
if (value2 !== null && !safeHttpsUrl(value2)) {
|
|
1104
1105
|
throw new Error(`${path}: calendar.google.bookingPageUrl.${env} must be an HTTPS URL without credentials or fragment`);
|
|
1105
1106
|
}
|
|
1106
1107
|
}
|
|
@@ -1119,37 +1120,37 @@ function validateServices(services, path) {
|
|
|
1119
1120
|
}
|
|
1120
1121
|
}
|
|
1121
1122
|
}
|
|
1122
|
-
function assertOnly(
|
|
1123
|
-
const extra = Object.keys(
|
|
1123
|
+
function assertOnly(value2, allowed, label) {
|
|
1124
|
+
const extra = Object.keys(value2).find((key) => !allowed.includes(key));
|
|
1124
1125
|
if (extra) throw new Error(`${label}.${extra} is not supported`);
|
|
1125
1126
|
}
|
|
1126
|
-
function isRecord5(
|
|
1127
|
-
return
|
|
1127
|
+
function isRecord5(value2) {
|
|
1128
|
+
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
1128
1129
|
}
|
|
1129
|
-
function safeText2(
|
|
1130
|
-
return typeof
|
|
1130
|
+
function safeText2(value2, max) {
|
|
1131
|
+
return typeof value2 === "string" && value2.trim().length > 0 && value2.length <= max && !/[\u0000-\u001f\u007f]/.test(value2);
|
|
1131
1132
|
}
|
|
1132
|
-
function safeHttpsUrl(
|
|
1133
|
-
if (typeof
|
|
1133
|
+
function safeHttpsUrl(value2) {
|
|
1134
|
+
if (typeof value2 !== "string" || value2.length > 2048) return false;
|
|
1134
1135
|
try {
|
|
1135
|
-
const url = new URL(
|
|
1136
|
+
const url = new URL(value2);
|
|
1136
1137
|
return url.protocol === "https:" && !url.username && !url.password && !url.hash;
|
|
1137
1138
|
} catch {
|
|
1138
1139
|
return false;
|
|
1139
1140
|
}
|
|
1140
1141
|
}
|
|
1141
|
-
function validId2(
|
|
1142
|
-
return typeof
|
|
1142
|
+
function validId2(value2) {
|
|
1143
|
+
return typeof value2 === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value2);
|
|
1143
1144
|
}
|
|
1144
1145
|
async function loadConfigModule(path) {
|
|
1145
1146
|
if (path.endsWith(".json")) return JSON.parse(readFileSync2(path, "utf8"));
|
|
1146
1147
|
const mod = await import(`${pathToFileURL(path).href}?t=${Date.now()}`);
|
|
1147
|
-
const
|
|
1148
|
-
if (typeof
|
|
1149
|
-
return
|
|
1148
|
+
const value2 = mod.default ?? mod.config;
|
|
1149
|
+
if (typeof value2 === "function") return await value2();
|
|
1150
|
+
return value2;
|
|
1150
1151
|
}
|
|
1151
|
-
function trimSlash(
|
|
1152
|
-
return
|
|
1152
|
+
function trimSlash(value2) {
|
|
1153
|
+
return value2.replace(/\/+$/, "");
|
|
1153
1154
|
}
|
|
1154
1155
|
function unique2(values) {
|
|
1155
1156
|
return [...new Set(values.filter(Boolean))];
|
|
@@ -1165,44 +1166,44 @@ var REPLACEMENTS = [
|
|
|
1165
1166
|
[/\b(ghp|gho|github_pat)_[A-Za-z0-9_]+/g, "$1_[redacted]"],
|
|
1166
1167
|
[/\bAKIA[A-Z0-9]{12,}/g, "AKIA[redacted]"]
|
|
1167
1168
|
];
|
|
1168
|
-
function redactSecrets(
|
|
1169
|
-
let result =
|
|
1169
|
+
function redactSecrets(value2) {
|
|
1170
|
+
let result = value2;
|
|
1170
1171
|
for (const [pattern, replacement] of REPLACEMENTS) result = result.replace(pattern, replacement);
|
|
1171
1172
|
return result;
|
|
1172
1173
|
}
|
|
1173
1174
|
function redactingOutput(output) {
|
|
1174
|
-
const redactArgs = (args) => args.map((
|
|
1175
|
+
const redactArgs = (args) => args.map((value2) => redactOutputValue(value2, /* @__PURE__ */ new WeakMap()));
|
|
1175
1176
|
return {
|
|
1176
1177
|
log: (...args) => output.log(...redactArgs(args)),
|
|
1177
1178
|
error: (...args) => output.error(...redactArgs(args))
|
|
1178
1179
|
};
|
|
1179
1180
|
}
|
|
1180
|
-
function redactOutputValue(
|
|
1181
|
-
if (typeof
|
|
1182
|
-
if (
|
|
1183
|
-
const redacted = new Error(redactSecrets(
|
|
1184
|
-
redacted.name =
|
|
1185
|
-
if (
|
|
1181
|
+
function redactOutputValue(value2, seen) {
|
|
1182
|
+
if (typeof value2 === "string") return redactSecrets(value2);
|
|
1183
|
+
if (value2 instanceof Error) {
|
|
1184
|
+
const redacted = new Error(redactSecrets(value2.message));
|
|
1185
|
+
redacted.name = value2.name;
|
|
1186
|
+
if (value2.stack) redacted.stack = redactSecrets(value2.stack);
|
|
1186
1187
|
return redacted;
|
|
1187
1188
|
}
|
|
1188
|
-
if (!
|
|
1189
|
-
const prior = seen.get(
|
|
1189
|
+
if (!value2 || typeof value2 !== "object") return value2;
|
|
1190
|
+
const prior = seen.get(value2);
|
|
1190
1191
|
if (prior) return prior;
|
|
1191
|
-
if (Array.isArray(
|
|
1192
|
+
if (Array.isArray(value2)) {
|
|
1192
1193
|
const next2 = [];
|
|
1193
|
-
seen.set(
|
|
1194
|
-
for (const item of
|
|
1194
|
+
seen.set(value2, next2);
|
|
1195
|
+
for (const item of value2) next2.push(redactOutputValue(item, seen));
|
|
1195
1196
|
return next2;
|
|
1196
1197
|
}
|
|
1197
|
-
const prototype = Object.getPrototypeOf(
|
|
1198
|
-
if (prototype !== Object.prototype && prototype !== null) return
|
|
1198
|
+
const prototype = Object.getPrototypeOf(value2);
|
|
1199
|
+
if (prototype !== Object.prototype && prototype !== null) return value2;
|
|
1199
1200
|
const next = {};
|
|
1200
|
-
seen.set(
|
|
1201
|
-
for (const [key, item] of Object.entries(
|
|
1201
|
+
seen.set(value2, next);
|
|
1202
|
+
for (const [key, item] of Object.entries(value2)) next[key] = redactOutputValue(item, seen);
|
|
1202
1203
|
return next;
|
|
1203
1204
|
}
|
|
1204
|
-
function looksSecret(
|
|
1205
|
-
return redactSecrets(
|
|
1205
|
+
function looksSecret(value2) {
|
|
1206
|
+
return redactSecrets(value2) !== value2 || value2.includes("-----BEGIN");
|
|
1206
1207
|
}
|
|
1207
1208
|
|
|
1208
1209
|
// src/calendar-errors.ts
|
|
@@ -1244,9 +1245,9 @@ async function readCalendarStatus(ctx) {
|
|
|
1244
1245
|
}
|
|
1245
1246
|
async function discoverGoogleCalendars(ctx) {
|
|
1246
1247
|
const raw = await calendarJson(ctx, "/calendars", {});
|
|
1247
|
-
const
|
|
1248
|
-
if (!
|
|
1249
|
-
return
|
|
1248
|
+
const value2 = record(raw);
|
|
1249
|
+
if (!value2 || !Array.isArray(value2.calendars)) throw new Error("calendar discovery returned an invalid response");
|
|
1250
|
+
return value2.calendars.map((item, index) => {
|
|
1250
1251
|
const calendar = record(item);
|
|
1251
1252
|
const id = textField(calendar?.id, 1024);
|
|
1252
1253
|
if (!calendar || !id) throw new Error(`calendar discovery returned an invalid calendar at index ${index}`);
|
|
@@ -1268,10 +1269,10 @@ async function applyCalendarSettings(ctx, bookingPageUrl) {
|
|
|
1268
1269
|
}
|
|
1269
1270
|
async function startCalendarConnection(ctx) {
|
|
1270
1271
|
const raw = await calendarJson(ctx, "/google/connect", { method: "POST", body: "{}" });
|
|
1271
|
-
const
|
|
1272
|
-
const attemptId = textField(
|
|
1273
|
-
const consentUrl = textField(
|
|
1274
|
-
const expiresAt = timestamp3(
|
|
1272
|
+
const value2 = wrapped(raw, "attempt");
|
|
1273
|
+
const attemptId = textField(value2.attemptId, 180);
|
|
1274
|
+
const consentUrl = textField(value2.consentUrl, 4096);
|
|
1275
|
+
const expiresAt = timestamp3(value2.expiresAt);
|
|
1275
1276
|
if (!attemptId || !consentUrl || expiresAt === void 0) throw new Error("calendar connect returned an invalid attempt");
|
|
1276
1277
|
return { attemptId, consentUrl, expiresAt };
|
|
1277
1278
|
}
|
|
@@ -1289,42 +1290,42 @@ async function requestCalendarDisconnect(ctx) {
|
|
|
1289
1290
|
}
|
|
1290
1291
|
function parseCalendarStatus(raw, env) {
|
|
1291
1292
|
const outer = wrapped(raw, "calendar");
|
|
1292
|
-
const
|
|
1293
|
-
const connection = record(
|
|
1294
|
-
const config = record(
|
|
1293
|
+
const value2 = record(outer.attempt) ?? record(outer.status) ?? outer;
|
|
1294
|
+
const connection = record(value2.connection) ?? {};
|
|
1295
|
+
const config = record(value2.config) ?? record(outer.config) ?? {};
|
|
1295
1296
|
const googleConfig = record(config.google) ?? config;
|
|
1296
|
-
const stateValue = calendarState(
|
|
1297
|
+
const stateValue = calendarState(value2.status ?? value2.state ?? connection.status ?? connection.state);
|
|
1297
1298
|
if (!stateValue) {
|
|
1298
1299
|
throw new Error("calendar status returned an invalid connection state");
|
|
1299
1300
|
}
|
|
1300
|
-
const providerValue =
|
|
1301
|
+
const providerValue = value2.provider ?? connection.provider ?? config.provider ?? (config.google ? "google" : void 0);
|
|
1301
1302
|
if (providerValue !== void 0 && providerValue !== null && providerValue !== "google") {
|
|
1302
1303
|
throw new Error("calendar status returned an unsupported provider");
|
|
1303
1304
|
}
|
|
1304
|
-
const accessValue =
|
|
1305
|
+
const accessValue = value2.access ?? connection.access ?? config.access ?? googleConfig.access;
|
|
1305
1306
|
if (accessValue !== void 0 && accessValue !== "book" && accessValue !== "read") {
|
|
1306
1307
|
throw new Error("calendar status returned unsupported access");
|
|
1307
1308
|
}
|
|
1308
|
-
const errorValue = record(
|
|
1309
|
-
const errorCode = textField(
|
|
1310
|
-
const bookingPageValue = Object.hasOwn(
|
|
1311
|
-
const connected = typeof (
|
|
1312
|
-
const bookingCalendarId = textField(
|
|
1309
|
+
const errorValue = record(value2.error) ?? record(connection.error);
|
|
1310
|
+
const errorCode = textField(value2.lastErrorCode, 128);
|
|
1311
|
+
const bookingPageValue = Object.hasOwn(value2, "bookingPageUrl") ? value2.bookingPageUrl : Object.hasOwn(config, "bookingPageUrl") ? config.bookingPageUrl : googleConfig.bookingPageUrl;
|
|
1312
|
+
const connected = typeof (value2.connected ?? connection.connected) === "boolean" ? Boolean(value2.connected ?? connection.connected) : ["healthy", "degraded"].includes(stateValue);
|
|
1313
|
+
const bookingCalendarId = textField(value2.bookingCalendarId ?? config.bookingCalendarId, 1024);
|
|
1313
1314
|
return {
|
|
1314
1315
|
env,
|
|
1315
|
-
enabled: typeof
|
|
1316
|
+
enabled: typeof value2.enabled === "boolean" ? value2.enabled : true,
|
|
1316
1317
|
connected,
|
|
1317
|
-
writable: typeof
|
|
1318
|
+
writable: typeof value2.writable === "boolean" ? value2.writable : stateValue === "healthy",
|
|
1318
1319
|
provider: providerValue === "google" ? "google" : null,
|
|
1319
1320
|
status: stateValue,
|
|
1320
1321
|
...accessValue !== void 0 ? { access: "book" } : {},
|
|
1321
1322
|
...bookingCalendarId ? { bookingCalendarId } : {},
|
|
1322
1323
|
calendars: calendarIds(
|
|
1323
|
-
|
|
1324
|
+
value2.availabilityCalendars ?? config.availabilityCalendars ?? value2.configuredCalendars ?? value2.calendars ?? config.calendars ?? googleConfig.calendars
|
|
1324
1325
|
),
|
|
1325
1326
|
...optionalNullableUrl("bookingPageUrl", bookingPageValue),
|
|
1326
|
-
grantedScopes: stringList(
|
|
1327
|
-
...optionalText("attemptId",
|
|
1327
|
+
grantedScopes: stringList(value2.grantedScopes ?? connection.grantedScopes ?? connection.scopes),
|
|
1328
|
+
...optionalText("attemptId", value2.attemptId ?? connection.attemptId, 180),
|
|
1328
1329
|
...errorValue || errorCode ? { error: {
|
|
1329
1330
|
...textField(errorValue?.code, 128) ? { code: textField(errorValue?.code, 128) } : {},
|
|
1330
1331
|
...textField(errorValue?.message, 500) ? { message: textField(errorValue?.message, 500) } : {},
|
|
@@ -1332,9 +1333,9 @@ function parseCalendarStatus(raw, env) {
|
|
|
1332
1333
|
} } : {}
|
|
1333
1334
|
};
|
|
1334
1335
|
}
|
|
1335
|
-
function calendarState(
|
|
1336
|
-
if (typeof
|
|
1337
|
-
if (CALENDAR_STATES.includes(
|
|
1336
|
+
function calendarState(value2) {
|
|
1337
|
+
if (typeof value2 !== "string") return null;
|
|
1338
|
+
if (CALENDAR_STATES.includes(value2)) return value2;
|
|
1338
1339
|
const legacy = {
|
|
1339
1340
|
disabled: "not_connected",
|
|
1340
1341
|
disconnected: "disconnected",
|
|
@@ -1345,7 +1346,7 @@ function calendarState(value) {
|
|
|
1345
1346
|
ready: "healthy",
|
|
1346
1347
|
error: "failed"
|
|
1347
1348
|
};
|
|
1348
|
-
return legacy[
|
|
1349
|
+
return legacy[value2] ?? null;
|
|
1349
1350
|
}
|
|
1350
1351
|
async function calendarJson(ctx, suffix, init) {
|
|
1351
1352
|
const platform = platformAudience(ctx.platform);
|
|
@@ -1379,50 +1380,50 @@ function wrapped(raw, key) {
|
|
|
1379
1380
|
if (!outer) throw new Error("calendar returned an invalid response");
|
|
1380
1381
|
return record(outer[key]) ?? outer;
|
|
1381
1382
|
}
|
|
1382
|
-
function record(
|
|
1383
|
-
return
|
|
1383
|
+
function record(value2) {
|
|
1384
|
+
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
|
|
1384
1385
|
}
|
|
1385
|
-
function textField(
|
|
1386
|
-
return typeof
|
|
1386
|
+
function textField(value2, max) {
|
|
1387
|
+
return typeof value2 === "string" && value2.length > 0 && value2.length <= max && !/[\u0000-\u001f\u007f]/.test(value2) ? value2 : void 0;
|
|
1387
1388
|
}
|
|
1388
|
-
function stringList(
|
|
1389
|
-
return Array.isArray(
|
|
1389
|
+
function stringList(value2) {
|
|
1390
|
+
return Array.isArray(value2) ? [...new Set(value2.filter((item) => !!textField(item, 4096)))] : [];
|
|
1390
1391
|
}
|
|
1391
|
-
function calendarIds(
|
|
1392
|
-
if (!Array.isArray(
|
|
1393
|
-
return [...new Set(
|
|
1392
|
+
function calendarIds(value2) {
|
|
1393
|
+
if (!Array.isArray(value2)) return [];
|
|
1394
|
+
return [...new Set(value2.flatMap((item) => {
|
|
1394
1395
|
if (typeof item === "string") return textField(item, 4096) ? [item] : [];
|
|
1395
1396
|
const calendar = record(item);
|
|
1396
1397
|
const id = textField(calendar?.id, 4096);
|
|
1397
1398
|
return id && calendar?.selected !== false ? [id] : [];
|
|
1398
1399
|
}))];
|
|
1399
1400
|
}
|
|
1400
|
-
function timestamp3(
|
|
1401
|
-
if (typeof
|
|
1402
|
-
if (typeof
|
|
1403
|
-
const parsed = Date.parse(
|
|
1401
|
+
function timestamp3(value2) {
|
|
1402
|
+
if (typeof value2 === "number" && Number.isFinite(value2) && value2 >= 0) return value2;
|
|
1403
|
+
if (typeof value2 === "string") {
|
|
1404
|
+
const parsed = Date.parse(value2);
|
|
1404
1405
|
if (Number.isFinite(parsed)) return parsed;
|
|
1405
1406
|
}
|
|
1406
1407
|
return void 0;
|
|
1407
1408
|
}
|
|
1408
|
-
function optionalText(key,
|
|
1409
|
-
const parsed = textField(
|
|
1409
|
+
function optionalText(key, value2, max) {
|
|
1410
|
+
const parsed = textField(value2, max);
|
|
1410
1411
|
return parsed ? { [key]: parsed } : {};
|
|
1411
1412
|
}
|
|
1412
|
-
function optionalNullableUrl(key,
|
|
1413
|
-
if (
|
|
1414
|
-
const parsed = textField(
|
|
1413
|
+
function optionalNullableUrl(key, value2) {
|
|
1414
|
+
if (value2 === null) return { [key]: null };
|
|
1415
|
+
const parsed = textField(value2, 4096);
|
|
1415
1416
|
return parsed ? { [key]: parsed } : {};
|
|
1416
1417
|
}
|
|
1417
|
-
function identifier(
|
|
1418
|
-
if (typeof
|
|
1419
|
-
return
|
|
1418
|
+
function identifier(value2, name) {
|
|
1419
|
+
if (typeof value2 !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,179}$/.test(value2)) throw new Error(`${name} is invalid`);
|
|
1420
|
+
return value2;
|
|
1420
1421
|
}
|
|
1421
|
-
function credential(
|
|
1422
|
-
if (typeof
|
|
1422
|
+
function credential(value2) {
|
|
1423
|
+
if (typeof value2 !== "string" || value2.length < 8 || value2.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value2)) {
|
|
1423
1424
|
throw new Error("calendar requires an odla developer token");
|
|
1424
1425
|
}
|
|
1425
|
-
return
|
|
1426
|
+
return value2;
|
|
1426
1427
|
}
|
|
1427
1428
|
|
|
1428
1429
|
// src/calendar-poll.ts
|
|
@@ -1583,11 +1584,11 @@ async function connectWithContext(ctx, options) {
|
|
|
1583
1584
|
}
|
|
1584
1585
|
throw new Error('Google Calendar consent timed out; run "odla-ai calendar status" and retry connect');
|
|
1585
1586
|
}
|
|
1586
|
-
function trustedCalendarConsentUrl(platform,
|
|
1587
|
+
function trustedCalendarConsentUrl(platform, value2) {
|
|
1587
1588
|
const origin = platformAudience(platform);
|
|
1588
1589
|
let url;
|
|
1589
1590
|
try {
|
|
1590
|
-
url =
|
|
1591
|
+
url = value2.startsWith("/") ? new URL(value2, origin) : new URL(value2);
|
|
1591
1592
|
} catch {
|
|
1592
1593
|
throw new Error("odla.ai returned an invalid calendar consent URL");
|
|
1593
1594
|
}
|
|
@@ -1598,9 +1599,9 @@ function trustedCalendarConsentUrl(platform, value) {
|
|
|
1598
1599
|
}
|
|
1599
1600
|
return url.toString();
|
|
1600
1601
|
}
|
|
1601
|
-
function pollTimeout(
|
|
1602
|
-
if (!Number.isSafeInteger(
|
|
1603
|
-
return
|
|
1602
|
+
function pollTimeout(value2 = 10 * 6e4) {
|
|
1603
|
+
if (!Number.isSafeInteger(value2) || value2 < 1e3 || value2 > 60 * 6e4) throw new Error("calendar poll timeout must be 1000-3600000ms");
|
|
1604
|
+
return value2;
|
|
1604
1605
|
}
|
|
1605
1606
|
function productionConsent(env, yes, action) {
|
|
1606
1607
|
if ((env === "prod" || env === "production") && !yes) throw new Error(`refusing to ${action} for "${env}" without --yes`);
|
|
@@ -1632,6 +1633,7 @@ var CAPABILITIES = {
|
|
|
1632
1633
|
"validate integration contracts offline and smoke-test a provisioned db environment plus anonymous capability routes",
|
|
1633
1634
|
"save and explicitly select non-secret named operator contexts with isolated credential caches; resolve and explain platform, app, environment, and credential provenance without authenticating; then run PM, Discussions, o11y, runbook, and identity operations outside a project checkout",
|
|
1634
1635
|
"read one versioned o11y status envelope spanning application RED, exact Worker versions and Cloudflare colos observed in traffic, current live-sync freshness/load, the protected commit-to-visible canary, collector ingest/scheduler trust, provider-owned runtime metrics, account-scoped Durable Object, D1, and R2 evidence under odla-db, and a bounded machine verdict",
|
|
1636
|
+
"read one canonical platform fleet snapshot over private service bindings, including release identities, probe latency, Cloudflare load/runtime freshness, explicit unknowns, and stable next actions through a read-only capability",
|
|
1635
1637
|
"inspect durable agent wakeups as a versioned JSON envelope and explicitly requeue one dead-lettered job with a scoped environment credential",
|
|
1636
1638
|
"run app-attributed hosted security discovery and independent validation without provider keys",
|
|
1637
1639
|
"connect/revoke source-read-only GitHub sources and drive commit-pinned hosted security jobs without PATs or provider keys",
|
|
@@ -1815,8 +1817,8 @@ function wranglerWarnings(rootDir) {
|
|
|
1815
1817
|
}
|
|
1816
1818
|
const vars = block.vars;
|
|
1817
1819
|
if (vars && typeof vars === "object") {
|
|
1818
|
-
for (const [name,
|
|
1819
|
-
if (name === "ODLA_API_KEY" || name === "ODLA_O11Y_TOKEN" || typeof
|
|
1820
|
+
for (const [name, value2] of Object.entries(vars)) {
|
|
1821
|
+
if (name === "ODLA_API_KEY" || name === "ODLA_O11Y_TOKEN" || typeof value2 === "string" && looksSecret(value2)) {
|
|
1820
1822
|
warnings.push(`wrangler ${label}vars.${name} looks like a secret \u2014 use "odla-ai secrets push" / wrangler secret put, never vars`);
|
|
1821
1823
|
}
|
|
1822
1824
|
}
|
|
@@ -1984,27 +1986,27 @@ function isUniqueAttr(schema, ns, attr) {
|
|
|
1984
1986
|
const definition = entity.attrs[attr];
|
|
1985
1987
|
return isRecord6(definition) && definition.unique === true;
|
|
1986
1988
|
}
|
|
1987
|
-
function normalizeSchema(
|
|
1988
|
-
if (
|
|
1989
|
-
if (!isRecord6(
|
|
1989
|
+
function normalizeSchema(value2) {
|
|
1990
|
+
if (value2 === void 0 || value2 === null) return { entities: {}, links: {} };
|
|
1991
|
+
if (!isRecord6(value2) || !isRecord6(value2.entities)) {
|
|
1990
1992
|
throw new Error("db schema must be a serialized schema object with an entities map");
|
|
1991
1993
|
}
|
|
1992
|
-
if (
|
|
1994
|
+
if (value2.links !== void 0 && !isRecord6(value2.links)) throw new Error("db schema links must be an object");
|
|
1993
1995
|
return {
|
|
1994
|
-
entities: { ...
|
|
1995
|
-
links: { ...
|
|
1996
|
+
entities: { ...value2.entities },
|
|
1997
|
+
links: { ...value2.links ?? {} }
|
|
1996
1998
|
};
|
|
1997
1999
|
}
|
|
1998
2000
|
function mergeMap(target, fragment, label) {
|
|
1999
|
-
for (const [name,
|
|
2000
|
-
if (Object.hasOwn(target, name) && !isDeepStrictEqual(target[name],
|
|
2001
|
+
for (const [name, value2] of Object.entries(fragment)) {
|
|
2002
|
+
if (Object.hasOwn(target, name) && !isDeepStrictEqual(target[name], value2)) {
|
|
2001
2003
|
throw new Error(`${label} "${name}" conflicts with an existing definition`);
|
|
2002
2004
|
}
|
|
2003
|
-
target[name] =
|
|
2005
|
+
target[name] = value2;
|
|
2004
2006
|
}
|
|
2005
2007
|
}
|
|
2006
|
-
function isRecord6(
|
|
2007
|
-
return
|
|
2008
|
+
function isRecord6(value2) {
|
|
2009
|
+
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
2008
2010
|
}
|
|
2009
2011
|
|
|
2010
2012
|
// src/doctor.ts
|
|
@@ -2045,9 +2047,9 @@ async function doctor(options) {
|
|
|
2045
2047
|
warnings.push(...integrationWarnings(database.integrations, schema, rules));
|
|
2046
2048
|
if (cfg.services.includes("ai") && !cfg.ai?.provider) warnings.push("ai service is enabled but ai.provider is not set");
|
|
2047
2049
|
if (cfg.auth?.clerk) {
|
|
2048
|
-
for (const [env,
|
|
2049
|
-
if (typeof
|
|
2050
|
-
warnings.push(`auth.clerk.${env} references unset env var ${
|
|
2050
|
+
for (const [env, value2] of Object.entries(cfg.auth.clerk)) {
|
|
2051
|
+
if (typeof value2 === "string" && value2.startsWith("$") && !process.env[value2.slice(1)]) {
|
|
2052
|
+
warnings.push(`auth.clerk.${env} references unset env var ${value2}`);
|
|
2051
2053
|
}
|
|
2052
2054
|
}
|
|
2053
2055
|
}
|
|
@@ -2301,38 +2303,38 @@ async function secretsSet(options) {
|
|
|
2301
2303
|
if (name.startsWith("$")) {
|
|
2302
2304
|
throw new Error('"$"-prefixed vault names are platform-reserved; for the Clerk secret key use "odla-ai secrets set-clerk-key"');
|
|
2303
2305
|
}
|
|
2304
|
-
const { cfg, tenantId, value, doFetch, out } = await resolveVaultWrite(options);
|
|
2306
|
+
const { cfg, tenantId, value: value2, doFetch, out } = await resolveVaultWrite(options);
|
|
2305
2307
|
const token = await getDeveloperToken(cfg, options, doFetch, out);
|
|
2306
2308
|
try {
|
|
2307
|
-
await putSecret({ endpoint: cfg.dbEndpoint, token, fetch: doFetch }, tenantId, name,
|
|
2309
|
+
await putSecret({ endpoint: cfg.dbEndpoint, token, fetch: doFetch }, tenantId, name, value2);
|
|
2308
2310
|
} catch (err) {
|
|
2309
|
-
throw new Error(scrubValue(err instanceof Error ? err.message : String(err),
|
|
2311
|
+
throw new Error(scrubValue(err instanceof Error ? err.message : String(err), value2));
|
|
2310
2312
|
}
|
|
2311
2313
|
out.log(`${name} stored in the ${tenantId} vault (write-only; the value was never echoed and cannot be read back here)`);
|
|
2312
2314
|
}
|
|
2313
2315
|
async function secretsSetClerkKey(options) {
|
|
2314
|
-
const { cfg, tenantId, value, doFetch, out } = await resolveVaultWrite(options);
|
|
2315
|
-
if (!
|
|
2316
|
-
if (
|
|
2316
|
+
const { cfg, tenantId, value: value2, doFetch, out } = await resolveVaultWrite(options);
|
|
2317
|
+
if (!value2.startsWith("sk_")) throw new Error("the Clerk secret key must start with sk_ (sk_test_\u2026 or sk_live_\u2026)");
|
|
2318
|
+
if (value2.startsWith("sk_test_") && PROD_ENV_NAMES2.has(options.env)) {
|
|
2317
2319
|
throw new Error(`refusing to store an sk_test_ Clerk key for "${options.env}" \u2014 use the production instance's sk_live_ key`);
|
|
2318
2320
|
}
|
|
2319
|
-
if (
|
|
2321
|
+
if (value2.startsWith("sk_live_") && !PROD_ENV_NAMES2.has(options.env) && !options.yes) {
|
|
2320
2322
|
throw new Error(`refusing to store an sk_live_ Clerk key for "${options.env}" without --yes (live users would sync into a non-prod tenant)`);
|
|
2321
2323
|
}
|
|
2322
2324
|
const token = await getDeveloperToken(cfg, options, doFetch, out);
|
|
2323
2325
|
const res = await doFetch(`${cfg.dbEndpoint}/admin/apps/${encodeURIComponent(tenantId)}/clerk-secret`, {
|
|
2324
2326
|
method: "POST",
|
|
2325
2327
|
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
2326
|
-
body: JSON.stringify({ value })
|
|
2328
|
+
body: JSON.stringify({ value: value2 })
|
|
2327
2329
|
});
|
|
2328
2330
|
if (!res.ok) {
|
|
2329
|
-
const text = scrubValue((await res.text().catch(() => "")).slice(0, 300),
|
|
2331
|
+
const text = scrubValue((await res.text().catch(() => "")).slice(0, 300), value2);
|
|
2330
2332
|
throw new Error(`store Clerk secret key failed (${res.status}): ${text || "request failed"}`);
|
|
2331
2333
|
}
|
|
2332
2334
|
out.log(`Clerk secret key stored for ${tenantId} ($clerk_secret, reserved + write-only; the value was never echoed)`);
|
|
2333
2335
|
}
|
|
2334
|
-
function scrubValue(text,
|
|
2335
|
-
return redactSecrets(text).split(
|
|
2336
|
+
function scrubValue(text, value2) {
|
|
2337
|
+
return redactSecrets(text).split(value2).join("[value redacted]");
|
|
2336
2338
|
}
|
|
2337
2339
|
async function resolveVaultWrite(options) {
|
|
2338
2340
|
const out = options.stdout ?? console;
|
|
@@ -2344,8 +2346,8 @@ async function resolveVaultWrite(options) {
|
|
|
2344
2346
|
if (PROD_ENV_NAMES2.has(options.env) && !options.yes) {
|
|
2345
2347
|
throw new Error(`refusing to store a secret for "${options.env}" without --yes`);
|
|
2346
2348
|
}
|
|
2347
|
-
const
|
|
2348
|
-
return { cfg, tenantId: tenantIdFor(cfg.app.id, options.env), value, doFetch, out };
|
|
2349
|
+
const value2 = await secretInputValue(options, "secret");
|
|
2350
|
+
return { cfg, tenantId: tenantIdFor(cfg.app.id, options.env), value: value2, doFetch, out };
|
|
2349
2351
|
}
|
|
2350
2352
|
|
|
2351
2353
|
// src/skill.ts
|
|
@@ -2786,31 +2788,31 @@ async function requestHostedSecurityJson(options, path, init, action) {
|
|
|
2786
2788
|
}
|
|
2787
2789
|
return body;
|
|
2788
2790
|
}
|
|
2789
|
-
function hostedIdentifier(
|
|
2790
|
-
const result = optionalHostedText(
|
|
2791
|
+
function hostedIdentifier(value2, name) {
|
|
2792
|
+
const result = optionalHostedText(value2, name, 180);
|
|
2791
2793
|
if (!result || !/^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(result)) {
|
|
2792
2794
|
throw new Error(`${name} is invalid`);
|
|
2793
2795
|
}
|
|
2794
2796
|
return result;
|
|
2795
2797
|
}
|
|
2796
|
-
function positivePolicyVersion(
|
|
2797
|
-
if (!Number.isSafeInteger(
|
|
2798
|
+
function positivePolicyVersion(value2, name) {
|
|
2799
|
+
if (!Number.isSafeInteger(value2) || value2 < 1) {
|
|
2798
2800
|
throw new Error(`${name} is invalid`);
|
|
2799
2801
|
}
|
|
2800
|
-
return
|
|
2802
|
+
return value2;
|
|
2801
2803
|
}
|
|
2802
|
-
function optionalHostedText(
|
|
2803
|
-
if (
|
|
2804
|
-
if (typeof
|
|
2804
|
+
function optionalHostedText(value2, name, maxLength) {
|
|
2805
|
+
if (value2 === void 0 || value2 === null || value2 === "") return void 0;
|
|
2806
|
+
if (typeof value2 !== "string" || value2.length > maxLength || /[\u0000-\u001f\u007f]/.test(value2)) {
|
|
2805
2807
|
throw new Error(`${name} is invalid`);
|
|
2806
2808
|
}
|
|
2807
|
-
return
|
|
2809
|
+
return value2;
|
|
2808
2810
|
}
|
|
2809
|
-
function githubRepositoryName(
|
|
2810
|
-
if (typeof
|
|
2811
|
+
function githubRepositoryName(value2) {
|
|
2812
|
+
if (typeof value2 !== "string" || value2.length > 201) {
|
|
2811
2813
|
throw new Error("repository must be owner/name");
|
|
2812
2814
|
}
|
|
2813
|
-
const parts =
|
|
2815
|
+
const parts = value2.split("/");
|
|
2814
2816
|
const owner = parts[0] ?? "";
|
|
2815
2817
|
const name = (parts[1] ?? "").replace(/\.git$/i, "");
|
|
2816
2818
|
if (parts.length !== 2 || !/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,98}[A-Za-z0-9])?$/.test(owner) || !/^[A-Za-z0-9_.-]{1,100}$/.test(name) || name === "." || name === "..") {
|
|
@@ -2818,10 +2820,10 @@ function githubRepositoryName(value) {
|
|
|
2818
2820
|
}
|
|
2819
2821
|
return `${owner}/${name}`;
|
|
2820
2822
|
}
|
|
2821
|
-
function trustedGitHubInstallUrl(
|
|
2823
|
+
function trustedGitHubInstallUrl(value2) {
|
|
2822
2824
|
let url;
|
|
2823
2825
|
try {
|
|
2824
|
-
url = new URL(
|
|
2826
|
+
url = new URL(value2);
|
|
2825
2827
|
} catch {
|
|
2826
2828
|
throw new Error("odla.ai returned an invalid GitHub installation URL");
|
|
2827
2829
|
}
|
|
@@ -2830,17 +2832,17 @@ function trustedGitHubInstallUrl(value) {
|
|
|
2830
2832
|
}
|
|
2831
2833
|
return url.toString();
|
|
2832
2834
|
}
|
|
2833
|
-
function hostedPollInterval(
|
|
2834
|
-
if (!Number.isSafeInteger(
|
|
2835
|
+
function hostedPollInterval(value2 = 2e3) {
|
|
2836
|
+
if (!Number.isSafeInteger(value2) || value2 < 100 || value2 > 3e4) {
|
|
2835
2837
|
throw new Error("poll interval must be 100-30000ms");
|
|
2836
2838
|
}
|
|
2837
|
-
return
|
|
2839
|
+
return value2;
|
|
2838
2840
|
}
|
|
2839
|
-
function hostedPollTimeout(
|
|
2840
|
-
if (!Number.isSafeInteger(
|
|
2841
|
+
function hostedPollTimeout(value2 = 10 * 6e4) {
|
|
2842
|
+
if (!Number.isSafeInteger(value2) || value2 < 1e3 || value2 > 60 * 6e4) {
|
|
2841
2843
|
throw new Error("poll timeout must be 1000-3600000ms");
|
|
2842
2844
|
}
|
|
2843
|
-
return
|
|
2845
|
+
return value2;
|
|
2844
2846
|
}
|
|
2845
2847
|
async function waitForHostedPoll(milliseconds, signal) {
|
|
2846
2848
|
if (signal?.aborted) throw signal.reason ?? new DOMException("aborted", "AbortError");
|
|
@@ -2852,16 +2854,16 @@ async function waitForHostedPoll(milliseconds, signal) {
|
|
|
2852
2854
|
}, { once: true });
|
|
2853
2855
|
});
|
|
2854
2856
|
}
|
|
2855
|
-
function isValidHostedSecurityPlan(
|
|
2856
|
-
if (!
|
|
2857
|
+
function isValidHostedSecurityPlan(value2, env) {
|
|
2858
|
+
if (!value2 || value2.env !== env || !/^sha256:[a-f0-9]{64}$/.test(value2.planDigest) || value2.consentContract !== "odla.hosted-security-consent.v1" || value2.reportProjection !== "odla.hosted-security-report.v1" || value2.redactionContract !== "odla.best-effort-credential-pattern-redaction.v1" || typeof value2.promptBundle !== "string" || value2.promptBundle.length < 1 || value2.promptBundle.length > 100 || typeof value2.ready !== "boolean" || typeof value2.independent !== "boolean" || value2.sourceDisclosure !== "redacted" || value2.targetExecution !== false || !Number.isSafeInteger(value2.reportRetentionDays) || value2.reportRetentionDays < 1) return false;
|
|
2857
2859
|
const validRoute = (route2, purpose) => !!route2 && route2.purpose === purpose && typeof route2.enabled === "boolean" && typeof route2.credentialReady === "boolean" && typeof route2.provider === "string" && route2.provider.length > 0 && route2.provider.length <= 100 && typeof route2.model === "string" && route2.model.length > 0 && route2.model.length <= 200 && Number.isSafeInteger(route2.policyVersion) && route2.policyVersion >= 1 && Number.isSafeInteger(route2.maxCallsPerRun) && route2.maxCallsPerRun >= 1 && Number.isSafeInteger(route2.maxInputBytes) && route2.maxInputBytes >= 1 && Number.isSafeInteger(route2.maxOutputTokens) && route2.maxOutputTokens >= 1;
|
|
2858
|
-
return validRoute(
|
|
2860
|
+
return validRoute(value2.routes?.discovery, "security.discovery") && validRoute(value2.routes?.validation, "security.validation");
|
|
2859
2861
|
}
|
|
2860
|
-
function hostedSecurityCredential(
|
|
2861
|
-
if (typeof
|
|
2862
|
+
function hostedSecurityCredential(value2) {
|
|
2863
|
+
if (typeof value2 !== "string" || value2.length < 8 || value2.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value2)) {
|
|
2862
2864
|
throw new Error("Hosted security requires an injected odla developer token");
|
|
2863
2865
|
}
|
|
2864
|
-
return
|
|
2866
|
+
return value2;
|
|
2865
2867
|
}
|
|
2866
2868
|
|
|
2867
2869
|
// src/security-hosted-github.ts
|
|
@@ -3089,24 +3091,24 @@ var CONTROL = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/;
|
|
|
3089
3091
|
var HarnessProtocolError = class extends Error {
|
|
3090
3092
|
name = "HarnessProtocolError";
|
|
3091
3093
|
};
|
|
3092
|
-
function record2(
|
|
3093
|
-
return
|
|
3094
|
+
function record2(value2) {
|
|
3095
|
+
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
|
|
3094
3096
|
}
|
|
3095
|
-
function boundedText(
|
|
3096
|
-
if (typeof
|
|
3097
|
+
function boundedText(value2, label, max) {
|
|
3098
|
+
if (typeof value2 !== "string" || !value2 || value2.length > max || CONTROL.test(value2)) {
|
|
3097
3099
|
throw new HarnessProtocolError(`${label} must be a non-empty string of at most ${max} characters`);
|
|
3098
3100
|
}
|
|
3099
|
-
return
|
|
3101
|
+
return value2;
|
|
3100
3102
|
}
|
|
3101
3103
|
function parseAgentOutput(line) {
|
|
3102
3104
|
if (Buffer.byteLength(line, "utf8") > 1e6) throw new HarnessProtocolError("agent message exceeds 1 MB");
|
|
3103
|
-
let
|
|
3105
|
+
let value2;
|
|
3104
3106
|
try {
|
|
3105
|
-
|
|
3107
|
+
value2 = JSON.parse(line);
|
|
3106
3108
|
} catch {
|
|
3107
3109
|
throw new HarnessProtocolError("agent emitted invalid JSON");
|
|
3108
3110
|
}
|
|
3109
|
-
const message2 = record2(
|
|
3111
|
+
const message2 = record2(value2);
|
|
3110
3112
|
if (!message2 || message2.protocolVersion !== HARNESS_PROTOCOL_VERSION) {
|
|
3111
3113
|
throw new HarnessProtocolError(`agent protocolVersion must be ${HARNESS_PROTOCOL_VERSION}`);
|
|
3112
3114
|
}
|
|
@@ -3415,7 +3417,7 @@ async function gitOutput(cwd, args, maxBytes) {
|
|
|
3415
3417
|
else stdout.push(chunk);
|
|
3416
3418
|
});
|
|
3417
3419
|
child.stderr.on("data", (chunk) => {
|
|
3418
|
-
if (stderr.reduce((sum,
|
|
3420
|
+
if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
|
|
3419
3421
|
});
|
|
3420
3422
|
const code = await new Promise((accept, reject) => {
|
|
3421
3423
|
child.once("error", reject);
|
|
@@ -3436,7 +3438,7 @@ async function gitBlobs(cwd, entries, maxBytes) {
|
|
|
3436
3438
|
else stdout.push(chunk);
|
|
3437
3439
|
});
|
|
3438
3440
|
child.stderr.on("data", (chunk) => {
|
|
3439
|
-
if (stderr.reduce((sum,
|
|
3441
|
+
if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
|
|
3440
3442
|
});
|
|
3441
3443
|
child.stdin.end(`${entries.map((entry) => entry.hash).join("\n")}
|
|
3442
3444
|
`);
|
|
@@ -3474,8 +3476,8 @@ async function materializeGitTree(source, commitSha, options = {}) {
|
|
|
3474
3476
|
const maxFiles = options.maxFiles ?? 2e4;
|
|
3475
3477
|
const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
|
|
3476
3478
|
const inventory = (await gitOutput(sourceDir, ["ls-tree", "-rz", commitSha], 16 * 1024 * 1024)).toString("utf8").split("\0").filter(Boolean);
|
|
3477
|
-
const entries = inventory.flatMap((
|
|
3478
|
-
const match = /^(100644|100755) blob ([0-9a-f]{40,64})\t([\s\S]+)$/.exec(
|
|
3479
|
+
const entries = inventory.flatMap((record8) => {
|
|
3480
|
+
const match = /^(100644|100755) blob ([0-9a-f]{40,64})\t([\s\S]+)$/.exec(record8);
|
|
3479
3481
|
return match && allowedWorkspacePath(match[3]) ? [{ mode: match[1], hash: match[2], path: match[3] }] : [];
|
|
3480
3482
|
});
|
|
3481
3483
|
if (entries.length > maxFiles) throw new Error(`workspace exceeds ${maxFiles} files`);
|
|
@@ -3550,7 +3552,7 @@ async function gitSourceFiles(sourceDir, maxFiles, maxBytes) {
|
|
|
3550
3552
|
else stdout.push(chunk);
|
|
3551
3553
|
});
|
|
3552
3554
|
child.stderr.on("data", (chunk) => {
|
|
3553
|
-
if (stderr.reduce((sum,
|
|
3555
|
+
if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
|
|
3554
3556
|
});
|
|
3555
3557
|
const code = await new Promise((accept, reject) => {
|
|
3556
3558
|
child.once("error", reject);
|
|
@@ -3610,7 +3612,7 @@ async function captureGitDiff(root, maxBytes) {
|
|
|
3610
3612
|
else stdout.push(chunk);
|
|
3611
3613
|
});
|
|
3612
3614
|
child.stderr.on("data", (chunk) => {
|
|
3613
|
-
if (stderr.reduce((sum,
|
|
3615
|
+
if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
|
|
3614
3616
|
});
|
|
3615
3617
|
const code = await new Promise((accept, reject) => {
|
|
3616
3618
|
child.once("error", reject);
|
|
@@ -3697,34 +3699,34 @@ var CamelError = class extends Error {
|
|
|
3697
3699
|
};
|
|
3698
3700
|
|
|
3699
3701
|
// ../camel/dist/chunk-L5DYU2E2.js
|
|
3700
|
-
function canonicalJson(
|
|
3701
|
-
return JSON.stringify(normalize(
|
|
3702
|
+
function canonicalJson(value2) {
|
|
3703
|
+
return JSON.stringify(normalize(value2));
|
|
3702
3704
|
}
|
|
3703
|
-
async function sha256Hex(
|
|
3704
|
-
const bytes = typeof
|
|
3705
|
+
async function sha256Hex(value2) {
|
|
3706
|
+
const bytes = typeof value2 === "string" ? new TextEncoder().encode(value2) : value2;
|
|
3705
3707
|
const digest = await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes).buffer);
|
|
3706
3708
|
return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3707
3709
|
}
|
|
3708
|
-
function utf8Length(
|
|
3709
|
-
if (typeof
|
|
3710
|
-
if (
|
|
3710
|
+
function utf8Length(value2) {
|
|
3711
|
+
if (typeof value2 === "string") return new TextEncoder().encode(value2).byteLength;
|
|
3712
|
+
if (value2 instanceof Uint8Array) return value2.byteLength;
|
|
3711
3713
|
try {
|
|
3712
|
-
return new TextEncoder().encode(canonicalJson(
|
|
3714
|
+
return new TextEncoder().encode(canonicalJson(value2)).byteLength;
|
|
3713
3715
|
} catch {
|
|
3714
3716
|
throw new CamelError("conversion_rejected", "Unsafe input could not be canonically measured.");
|
|
3715
3717
|
}
|
|
3716
3718
|
}
|
|
3717
|
-
function normalize(
|
|
3718
|
-
if (
|
|
3719
|
-
if (typeof
|
|
3720
|
-
if (!Number.isFinite(
|
|
3721
|
-
return
|
|
3719
|
+
function normalize(value2) {
|
|
3720
|
+
if (value2 === null || typeof value2 === "string" || typeof value2 === "boolean") return value2;
|
|
3721
|
+
if (typeof value2 === "number") {
|
|
3722
|
+
if (!Number.isFinite(value2)) throw new CamelError("state_conflict", "Canonical JSON rejects non-finite numbers.");
|
|
3723
|
+
return value2;
|
|
3722
3724
|
}
|
|
3723
|
-
if (Array.isArray(
|
|
3724
|
-
if (
|
|
3725
|
-
if (typeof
|
|
3726
|
-
const
|
|
3727
|
-
return Object.fromEntries(Object.keys(
|
|
3725
|
+
if (Array.isArray(value2)) return value2.map(normalize);
|
|
3726
|
+
if (value2 instanceof Uint8Array) return { $bytes: [...value2] };
|
|
3727
|
+
if (typeof value2 === "object") {
|
|
3728
|
+
const record8 = value2;
|
|
3729
|
+
return Object.fromEntries(Object.keys(record8).filter((key) => record8[key] !== void 0).sort().map((key) => [key, normalize(record8[key])]));
|
|
3728
3730
|
}
|
|
3729
3731
|
throw new CamelError("state_conflict", "Canonical JSON rejects unsupported values.");
|
|
3730
3732
|
}
|
|
@@ -3733,10 +3735,10 @@ function canRead(readers, readerId) {
|
|
|
3733
3735
|
}
|
|
3734
3736
|
function dependenciesOf(values, influence = "data") {
|
|
3735
3737
|
const result = [];
|
|
3736
|
-
for (const
|
|
3737
|
-
result.push(...
|
|
3738
|
-
for (const ref of
|
|
3739
|
-
result.push({ ref, influence, promptSafetyAtUse:
|
|
3738
|
+
for (const value2 of values) {
|
|
3739
|
+
result.push(...value2.label.dependencies);
|
|
3740
|
+
for (const ref of value2.label.provenance) {
|
|
3741
|
+
result.push({ ref, influence, promptSafetyAtUse: value2.label.promptSafety });
|
|
3740
3742
|
}
|
|
3741
3743
|
}
|
|
3742
3744
|
const unique3 = /* @__PURE__ */ new Map();
|
|
@@ -3747,32 +3749,32 @@ function dependenciesOf(values, influence = "data") {
|
|
|
3747
3749
|
// ../camel/dist/chunk-S7EVNA2U.js
|
|
3748
3750
|
var camelValueBrand = /* @__PURE__ */ Symbol("@odla-ai/camel/value");
|
|
3749
3751
|
var authenticCamelValues = /* @__PURE__ */ new WeakSet();
|
|
3750
|
-
function isCamelValue(
|
|
3751
|
-
return typeof
|
|
3752
|
+
function isCamelValue(value2) {
|
|
3753
|
+
return typeof value2 === "object" && value2 !== null && authenticCamelValues.has(value2);
|
|
3752
3754
|
}
|
|
3753
|
-
function isSafe(
|
|
3754
|
-
return isCamelValue(
|
|
3755
|
+
function isSafe(value2) {
|
|
3756
|
+
return isCamelValue(value2) && value2.label.promptSafety === "safe";
|
|
3755
3757
|
}
|
|
3756
|
-
function isUnsafe(
|
|
3757
|
-
return isCamelValue(
|
|
3758
|
+
function isUnsafe(value2) {
|
|
3759
|
+
return isCamelValue(value2) && value2.label.promptSafety === "unsafe";
|
|
3758
3760
|
}
|
|
3759
|
-
function createSafeInternal(
|
|
3760
|
-
return createValue(
|
|
3761
|
+
function createSafeInternal(value2, safeBasis, metadata2) {
|
|
3762
|
+
return createValue(value2, {
|
|
3761
3763
|
schemaVersion: 1,
|
|
3762
3764
|
promptSafety: "safe",
|
|
3763
3765
|
safeBasis,
|
|
3764
3766
|
...copyMetadata(metadata2)
|
|
3765
3767
|
});
|
|
3766
3768
|
}
|
|
3767
|
-
function createUnsafeInternal(
|
|
3768
|
-
return createValue(
|
|
3769
|
+
function createUnsafeInternal(value2, metadata2) {
|
|
3770
|
+
return createValue(value2, {
|
|
3769
3771
|
schemaVersion: 1,
|
|
3770
3772
|
promptSafety: "unsafe",
|
|
3771
3773
|
...copyMetadata(metadata2)
|
|
3772
3774
|
});
|
|
3773
3775
|
}
|
|
3774
|
-
function createValue(
|
|
3775
|
-
const result = { value, label: Object.freeze(label) };
|
|
3776
|
+
function createValue(value2, label) {
|
|
3777
|
+
const result = { value: value2, label: Object.freeze(label) };
|
|
3776
3778
|
Object.defineProperty(result, camelValueBrand, { value: label.promptSafety, enumerable: false });
|
|
3777
3779
|
authenticCamelValues.add(result);
|
|
3778
3780
|
return Object.freeze(result);
|
|
@@ -3878,8 +3880,8 @@ async function createCodePortableCheckpoint(input) {
|
|
|
3878
3880
|
const checkpointDigest = `sha256:${await sha256Hex(canonicalJson(fields))}`;
|
|
3879
3881
|
return freeze({ ...fields, patch: input.patch, checkpointDigest });
|
|
3880
3882
|
}
|
|
3881
|
-
async function verifyCodePortableCheckpoint(
|
|
3882
|
-
const input = object(
|
|
3883
|
+
async function verifyCodePortableCheckpoint(value2) {
|
|
3884
|
+
const input = object(value2, "checkpoint");
|
|
3883
3885
|
exact2(input, ["schemaVersion", "baseCommitSha", "patch", "patchDigest", "state", "stateDigest", "checkpointDigest"]);
|
|
3884
3886
|
if (input.schemaVersion !== 1 || typeof input.baseCommitSha !== "string" || typeof input.patch !== "string" || typeof input.patchDigest !== "string" || typeof input.stateDigest !== "string" || typeof input.checkpointDigest !== "string") {
|
|
3885
3887
|
throw invalid2("Portable checkpoint fields are malformed.");
|
|
@@ -3894,8 +3896,8 @@ async function verifyCodePortableCheckpoint(value) {
|
|
|
3894
3896
|
}
|
|
3895
3897
|
return created;
|
|
3896
3898
|
}
|
|
3897
|
-
function normalizeState(
|
|
3898
|
-
const state2 = object(
|
|
3899
|
+
function normalizeState(value2) {
|
|
3900
|
+
const state2 = object(value2, "state");
|
|
3899
3901
|
exact2(state2, [
|
|
3900
3902
|
"planCursor",
|
|
3901
3903
|
"conversationRefs",
|
|
@@ -3953,30 +3955,30 @@ function validateBaseAndPatch(baseCommitSha, patch2) {
|
|
|
3953
3955
|
throw invalid2("Portable checkpoint base or patch is malformed or outside its bounds.");
|
|
3954
3956
|
}
|
|
3955
3957
|
}
|
|
3956
|
-
function strings(
|
|
3957
|
-
if (!Array.isArray(
|
|
3958
|
+
function strings(value2, name, pattern, maximum, sort) {
|
|
3959
|
+
if (!Array.isArray(value2) || value2.length > maximum || value2.some((item) => typeof item !== "string" || !pattern.test(item)) || new Set(value2).size !== value2.length) {
|
|
3958
3960
|
throw invalid2(`Portable checkpoint ${name} is malformed or outside its bounds.`);
|
|
3959
3961
|
}
|
|
3960
|
-
const result = [...
|
|
3962
|
+
const result = [...value2];
|
|
3961
3963
|
return sort ? result.sort() : result;
|
|
3962
3964
|
}
|
|
3963
|
-
function object(
|
|
3964
|
-
if (!
|
|
3965
|
-
return
|
|
3965
|
+
function object(value2, name) {
|
|
3966
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) throw invalid2(`Portable ${name} must be an object.`);
|
|
3967
|
+
return value2;
|
|
3966
3968
|
}
|
|
3967
|
-
function exact2(
|
|
3968
|
-
if (Object.keys(
|
|
3969
|
+
function exact2(value2, keys) {
|
|
3970
|
+
if (Object.keys(value2).some((key) => !keys.includes(key)) || keys.some((key) => !(key in value2))) {
|
|
3969
3971
|
throw invalid2("Portable checkpoint contains missing or unsupported fields.");
|
|
3970
3972
|
}
|
|
3971
3973
|
}
|
|
3972
|
-
function freeze(
|
|
3974
|
+
function freeze(value2) {
|
|
3973
3975
|
return Object.freeze({
|
|
3974
|
-
...
|
|
3976
|
+
...value2,
|
|
3975
3977
|
state: Object.freeze({
|
|
3976
|
-
...
|
|
3977
|
-
conversationRefs: Object.freeze([...
|
|
3978
|
-
completedEffects: Object.freeze(
|
|
3979
|
-
unresolvedApprovals: Object.freeze([...
|
|
3978
|
+
...value2.state,
|
|
3979
|
+
conversationRefs: Object.freeze([...value2.state.conversationRefs]),
|
|
3980
|
+
completedEffects: Object.freeze(value2.state.completedEffects.map((item) => Object.freeze({ ...item }))),
|
|
3981
|
+
unresolvedApprovals: Object.freeze([...value2.state.unresolvedApprovals])
|
|
3980
3982
|
})
|
|
3981
3983
|
});
|
|
3982
3984
|
}
|
|
@@ -4067,61 +4069,61 @@ async function createConversionRegistry(config) {
|
|
|
4067
4069
|
if (utf8Length(source.value) > policy.maximumSourceBytes) throw new CamelError("limit_exceeded", "Unsafe conversion input exceeds its byte bound.");
|
|
4068
4070
|
return policy;
|
|
4069
4071
|
};
|
|
4070
|
-
const emit3 = (source, policy,
|
|
4072
|
+
const emit3 = (source, policy, value2) => convert(source, policy, value2, outputCounts);
|
|
4071
4073
|
const operations = Object.freeze({
|
|
4072
|
-
boolean: async (
|
|
4073
|
-
const policy = checked(
|
|
4074
|
-
return emit3(
|
|
4074
|
+
boolean: async (value2, id) => {
|
|
4075
|
+
const policy = checked(value2, id, "boolean");
|
|
4076
|
+
return emit3(value2, policy, requireBoolean(value2.value));
|
|
4075
4077
|
},
|
|
4076
|
-
integer: async (
|
|
4077
|
-
const policy = checked(
|
|
4078
|
-
return emit3(
|
|
4078
|
+
integer: async (value2, id) => {
|
|
4079
|
+
const policy = checked(value2, id, "integer");
|
|
4080
|
+
return emit3(value2, policy, boundedInteger(value2.value, policy.output));
|
|
4079
4081
|
},
|
|
4080
|
-
finiteNumber: async (
|
|
4081
|
-
const policy = checked(
|
|
4082
|
-
return emit3(
|
|
4082
|
+
finiteNumber: async (value2, id) => {
|
|
4083
|
+
const policy = checked(value2, id, "finite_number");
|
|
4084
|
+
return emit3(value2, policy, boundedNumber(value2.value, policy.output));
|
|
4083
4085
|
},
|
|
4084
|
-
enum: async (
|
|
4085
|
-
const policy = checked(
|
|
4086
|
-
return emit3(
|
|
4086
|
+
enum: async (value2, id) => {
|
|
4087
|
+
const policy = checked(value2, id, "enum");
|
|
4088
|
+
return emit3(value2, policy, enumMember(value2.value, policy.output));
|
|
4087
4089
|
},
|
|
4088
|
-
date: async (
|
|
4089
|
-
const policy = checked(
|
|
4090
|
-
return emit3(
|
|
4090
|
+
date: async (value2, id) => {
|
|
4091
|
+
const policy = checked(value2, id, "date");
|
|
4092
|
+
return emit3(value2, policy, canonicalDate(value2.value, policy.output));
|
|
4091
4093
|
},
|
|
4092
|
-
registeredId: async (
|
|
4093
|
-
const policy = checked(
|
|
4094
|
+
registeredId: async (value2, id) => {
|
|
4095
|
+
const policy = checked(value2, id, "registered_id");
|
|
4094
4096
|
const registry = config.registeredIds?.[policy.output.registryId];
|
|
4095
|
-
const output = typeof
|
|
4097
|
+
const output = typeof value2.value === "string" ? registry?.values[value2.value] : void 0;
|
|
4096
4098
|
if (!output) throw new CamelError("conversion_rejected", "Registered-ID conversion rejected the candidate.");
|
|
4097
|
-
return emit3(
|
|
4099
|
+
return emit3(value2, policy, output);
|
|
4098
4100
|
},
|
|
4099
|
-
digest: async (
|
|
4100
|
-
const policy = checked(
|
|
4101
|
-
if (!(
|
|
4102
|
-
return emit3(
|
|
4101
|
+
digest: async (value2, id) => {
|
|
4102
|
+
const policy = checked(value2, id, "digest");
|
|
4103
|
+
if (!(value2.value instanceof Uint8Array)) throw new CamelError("conversion_rejected", "Digest conversion requires bytes.");
|
|
4104
|
+
return emit3(value2, policy, await sha256Hex(value2.value));
|
|
4103
4105
|
},
|
|
4104
|
-
measure: async (
|
|
4105
|
-
const policy = checked(
|
|
4106
|
-
const measured = measure(
|
|
4107
|
-
return emit3(
|
|
4106
|
+
measure: async (value2, metric, id) => {
|
|
4107
|
+
const policy = checked(value2, id, "integer");
|
|
4108
|
+
const measured = measure(value2.value, metric);
|
|
4109
|
+
return emit3(value2, policy, boundedInteger(measured, policy.output));
|
|
4108
4110
|
},
|
|
4109
|
-
test: async (
|
|
4110
|
-
const policy = checked(
|
|
4111
|
+
test: async (value2, predicateId, id) => {
|
|
4112
|
+
const policy = checked(value2, id, "boolean");
|
|
4111
4113
|
const predicate = config.predicates?.[predicateId];
|
|
4112
4114
|
if (!predicate) throw new CamelError("conversion_rejected", "Predicate is not registered.");
|
|
4113
|
-
return emit3(
|
|
4115
|
+
return emit3(value2, policy, evaluatePredicate(value2.value, predicate, config.registeredIds));
|
|
4114
4116
|
}
|
|
4115
4117
|
});
|
|
4116
4118
|
return Object.freeze({ operations, policy: (id) => policies.get(id) ?? missingPolicy() });
|
|
4117
4119
|
}
|
|
4118
|
-
async function convert(source, policy,
|
|
4120
|
+
async function convert(source, policy, value2, counts) {
|
|
4119
4121
|
const sourceKey = sourceIdentity(source);
|
|
4120
4122
|
const countKey = `${policy.conversionId}\0${sourceKey}`;
|
|
4121
4123
|
const count = counts.get(countKey) ?? 0;
|
|
4122
4124
|
if (count >= policy.maximumOutputsPerArtifact) throw new CamelError("limit_exceeded", "Conversion output count exceeds its per-source bound.");
|
|
4123
4125
|
counts.set(countKey, count + 1);
|
|
4124
|
-
return createSafeInternal(
|
|
4126
|
+
return createSafeInternal(value2, "atomic_conversion", {
|
|
4125
4127
|
readers: source.label.readers,
|
|
4126
4128
|
provenance: [...source.label.provenance, { kind: "converter", id: policy.conversionId, digest: policy.digest }],
|
|
4127
4129
|
dependencies: dependenciesOf([source])
|
|
@@ -4133,49 +4135,49 @@ function validatePolicyShape(policy) {
|
|
|
4133
4135
|
const output = policy.output;
|
|
4134
4136
|
if ((output.kind === "integer" || output.kind === "finite_number") && (!Number.isFinite(output.minimum) || !Number.isFinite(output.maximum) || output.minimum > output.maximum)) throw new CamelError("state_conflict", "Numeric conversion bounds are invalid.");
|
|
4135
4137
|
if (output.kind === "finite_number" && (!Number.isSafeInteger(output.maximumDecimalPlaces) || output.maximumDecimalPlaces < 0 || output.maximumDecimalPlaces > 15)) throw new CamelError("state_conflict", "Decimal-place bound is invalid.");
|
|
4136
|
-
if (output.kind === "enum" && (output.values.length === 0 || output.values.some((
|
|
4138
|
+
if (output.kind === "enum" && (output.values.length === 0 || output.values.some((value2) => typeof value2 !== "string" || !value2) || new Set(output.values).size !== output.values.length)) throw new CamelError("state_conflict", "Enum conversion members must be unique and non-empty.");
|
|
4137
4139
|
if (output.kind === "registered_id" && (!output.registryId || !output.registryDigest)) throw new CamelError("state_conflict", "Registered-ID conversion identity is invalid.");
|
|
4138
4140
|
if (output.kind === "date" && output.format !== "date" && output.format !== "rfc3339") throw new CamelError("state_conflict", "Date conversion format is invalid.");
|
|
4139
4141
|
if (output.kind === "digest" && output.algorithm !== "sha256") throw new CamelError("state_conflict", "Digest conversion algorithm is invalid.");
|
|
4140
4142
|
}
|
|
4141
|
-
function requireBoolean(
|
|
4142
|
-
if (typeof
|
|
4143
|
-
return
|
|
4143
|
+
function requireBoolean(value2) {
|
|
4144
|
+
if (typeof value2 !== "boolean") throw new CamelError("conversion_rejected", "Boolean conversion requires a structured boolean.");
|
|
4145
|
+
return value2;
|
|
4144
4146
|
}
|
|
4145
|
-
function boundedInteger(
|
|
4146
|
-
if (spec.kind !== "integer" || typeof
|
|
4147
|
-
return
|
|
4147
|
+
function boundedInteger(value2, spec) {
|
|
4148
|
+
if (spec.kind !== "integer" || typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 < spec.minimum || value2 > spec.maximum) throw new CamelError("conversion_rejected", "Integer conversion rejected the structured value.");
|
|
4149
|
+
return value2;
|
|
4148
4150
|
}
|
|
4149
|
-
function boundedNumber(
|
|
4150
|
-
if (spec.kind !== "finite_number" || typeof
|
|
4151
|
-
const text = String(
|
|
4151
|
+
function boundedNumber(value2, spec) {
|
|
4152
|
+
if (spec.kind !== "finite_number" || typeof value2 !== "number" || !Number.isFinite(value2) || value2 < spec.minimum || value2 > spec.maximum) throw new CamelError("conversion_rejected", "Finite-number conversion rejected the structured value.");
|
|
4153
|
+
const text = String(value2);
|
|
4152
4154
|
if (/e/i.test(text) || (text.split(".")[1]?.length ?? 0) > spec.maximumDecimalPlaces) throw new CamelError("conversion_rejected", "Finite-number conversion rejected a non-canonical decimal.");
|
|
4153
|
-
return
|
|
4155
|
+
return value2;
|
|
4154
4156
|
}
|
|
4155
|
-
function enumMember(
|
|
4156
|
-
if (spec.kind !== "enum" || typeof
|
|
4157
|
-
const member = spec.caseSensitive ? spec.values.find((item) => item ===
|
|
4157
|
+
function enumMember(value2, spec) {
|
|
4158
|
+
if (spec.kind !== "enum" || typeof value2 !== "string") throw new CamelError("conversion_rejected", "Enum conversion requires a structured string member.");
|
|
4159
|
+
const member = spec.caseSensitive ? spec.values.find((item) => item === value2) : spec.values.find((item) => item.toLocaleLowerCase("en-US") === value2.toLocaleLowerCase("en-US"));
|
|
4158
4160
|
if (member === void 0) throw new CamelError("conversion_rejected", "Enum conversion rejected a non-member.");
|
|
4159
4161
|
return member;
|
|
4160
4162
|
}
|
|
4161
|
-
function canonicalDate(
|
|
4162
|
-
if (spec.kind !== "date" || typeof
|
|
4163
|
+
function canonicalDate(value2, spec) {
|
|
4164
|
+
if (spec.kind !== "date" || typeof value2 !== "string") throw new CamelError("conversion_rejected", "Date conversion requires a canonical structured string.");
|
|
4163
4165
|
const pattern = spec.format === "date" ? /^\d{4}-\d{2}-\d{2}$/ : /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
4164
|
-
const instant = Date.parse(spec.format === "date" ? `${
|
|
4165
|
-
if (!pattern.test(
|
|
4166
|
-
if (spec.earliest &&
|
|
4167
|
-
return
|
|
4168
|
-
}
|
|
4169
|
-
function measure(
|
|
4170
|
-
if (metric === "byte_length" && (typeof
|
|
4171
|
-
if (metric === "codepoint_length" && typeof
|
|
4172
|
-
if (metric === "item_count" && Array.isArray(
|
|
4166
|
+
const instant = Date.parse(spec.format === "date" ? `${value2}T00:00:00Z` : value2);
|
|
4167
|
+
if (!pattern.test(value2) || !Number.isFinite(instant) || spec.format === "date" && new Date(instant).toISOString().slice(0, 10) !== value2) throw new CamelError("conversion_rejected", "Date conversion rejected a non-canonical value.");
|
|
4168
|
+
if (spec.earliest && value2 < spec.earliest || spec.latest && value2 > spec.latest) throw new CamelError("conversion_rejected", "Date conversion rejected an out-of-range value.");
|
|
4169
|
+
return value2;
|
|
4170
|
+
}
|
|
4171
|
+
function measure(value2, metric) {
|
|
4172
|
+
if (metric === "byte_length" && (typeof value2 === "string" || value2 instanceof Uint8Array)) return utf8Length(value2);
|
|
4173
|
+
if (metric === "codepoint_length" && typeof value2 === "string") return [...value2].length;
|
|
4174
|
+
if (metric === "item_count" && Array.isArray(value2)) return value2.length;
|
|
4173
4175
|
throw new CamelError("conversion_rejected", "Measurement input does not match the registered metric.");
|
|
4174
4176
|
}
|
|
4175
|
-
function evaluatePredicate(
|
|
4176
|
-
if (predicate.kind === "has_fields") return typeof
|
|
4177
|
-
if (predicate.kind === "registered_id") return typeof
|
|
4178
|
-
const actual =
|
|
4177
|
+
function evaluatePredicate(value2, predicate, registries) {
|
|
4178
|
+
if (predicate.kind === "has_fields") return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && predicate.fields.every((field) => Object.hasOwn(value2, field));
|
|
4179
|
+
if (predicate.kind === "registered_id") return typeof value2 === "string" && registries?.[predicate.registryId]?.values[value2] !== void 0;
|
|
4180
|
+
const actual = value2 === null ? "null" : Array.isArray(value2) ? "array" : typeof value2;
|
|
4179
4181
|
return actual === predicate.valueType;
|
|
4180
4182
|
}
|
|
4181
4183
|
function sourceIdentity(source) {
|
|
@@ -4198,17 +4200,17 @@ function createCamelIngress(constants2 = []) {
|
|
|
4198
4200
|
byId.set(item.id, item);
|
|
4199
4201
|
}
|
|
4200
4202
|
const ingress = {
|
|
4201
|
-
userInstruction: (
|
|
4202
|
-
systemPolicy: (
|
|
4203
|
+
userInstruction: (value2, input) => createSafeInternal(value2, "user_instruction", metadata("user_instruction", input.id, input.readers)),
|
|
4204
|
+
systemPolicy: (value2, input) => createSafeInternal(value2, "system_policy", metadata("system_policy", input.id, input.readers)),
|
|
4203
4205
|
control: (id) => {
|
|
4204
4206
|
const item = byId.get(id);
|
|
4205
4207
|
if (!item) throw new CamelError("permission_denied", "Unknown control constant.");
|
|
4206
4208
|
return createSafeInternal(item.value, "harness_constant", metadata("harness", id, item.readers));
|
|
4207
4209
|
},
|
|
4208
|
-
external: (
|
|
4209
|
-
quarantinedOutput: (
|
|
4210
|
+
external: (value2, label) => createUnsafeInternal(value2, label),
|
|
4211
|
+
quarantinedOutput: (value2, input) => {
|
|
4210
4212
|
if (!input.runId) throw new CamelError("state_conflict", "Quarantined run IDs must be non-empty.");
|
|
4211
|
-
return createUnsafeInternal(
|
|
4213
|
+
return createUnsafeInternal(value2, {
|
|
4212
4214
|
readers: input.readers,
|
|
4213
4215
|
dependencies: input.dependencies,
|
|
4214
4216
|
provenance: [{ kind: "quarantined_llm", id: input.runId, digest: input.digest }]
|
|
@@ -4217,15 +4219,15 @@ function createCamelIngress(constants2 = []) {
|
|
|
4217
4219
|
};
|
|
4218
4220
|
return Object.freeze(ingress);
|
|
4219
4221
|
}
|
|
4220
|
-
function assertNoUnsafeConstant(
|
|
4221
|
-
if (typeof
|
|
4222
|
-
seen.add(
|
|
4223
|
-
if (isCamelValue(
|
|
4224
|
-
if (isUnsafe(
|
|
4225
|
-
assertNoUnsafeConstant(
|
|
4222
|
+
function assertNoUnsafeConstant(value2, seen = /* @__PURE__ */ new WeakSet()) {
|
|
4223
|
+
if (typeof value2 !== "object" || value2 === null || seen.has(value2)) return;
|
|
4224
|
+
seen.add(value2);
|
|
4225
|
+
if (isCamelValue(value2)) {
|
|
4226
|
+
if (isUnsafe(value2)) throw new CamelError("unsafe_privileged_flow", "Control constants cannot contain Prompt-Unsafe values.");
|
|
4227
|
+
assertNoUnsafeConstant(value2.value, seen);
|
|
4226
4228
|
return;
|
|
4227
4229
|
}
|
|
4228
|
-
for (const child of Object.values(
|
|
4230
|
+
for (const child of Object.values(value2)) assertNoUnsafeConstant(child, seen);
|
|
4229
4231
|
}
|
|
4230
4232
|
function metadata(kind, id, readers) {
|
|
4231
4233
|
if (!id) throw new CamelError("state_conflict", "Provenance IDs must be non-empty.");
|
|
@@ -4256,7 +4258,7 @@ async function evaluate(input, registries, approvals) {
|
|
|
4256
4258
|
if (invalid3) return deny(invalid3);
|
|
4257
4259
|
if (arg.role === "selector" && !isSafe(arg.value)) confined.add(arg.value);
|
|
4258
4260
|
}
|
|
4259
|
-
if (input.controlDependencies.some((
|
|
4261
|
+
if (input.controlDependencies.some((value2) => !isSafe(value2) && !confined.has(value2))) return deny("unsafe_control_dependency");
|
|
4260
4262
|
if (confined.size > 0) {
|
|
4261
4263
|
const fixed = input.tool.unsafeSelectorPolicy?.fixedProviderIds ?? [];
|
|
4262
4264
|
const destinations = Object.values(input.args).filter((arg) => arg.role === "destination");
|
|
@@ -4283,29 +4285,29 @@ async function validateArgument(path, arg, tool, registries) {
|
|
|
4283
4285
|
if (!isSafe(arg.value)) return "unsafe_destination_argument";
|
|
4284
4286
|
if (!isControlOwned(arg.value)) return "destination_not_control_owned";
|
|
4285
4287
|
const registry = registries[arg.registryId];
|
|
4286
|
-
const validValues = registry && registry.values.length > 0 && registry.values.every((
|
|
4288
|
+
const validValues = registry && registry.values.length > 0 && registry.values.every((value2) => typeof value2 === "string" && value2.length > 0) && new Set(registry.values).size === registry.values.length;
|
|
4287
4289
|
if (!registry || !validValues || registry.digest !== arg.registryDigest || await destinationRegistryDigest(registry.values) !== registry.digest || !registry.values.includes(arg.value.value)) return "destination_not_registered";
|
|
4288
4290
|
}
|
|
4289
4291
|
if (arg.role === "selector" && !isSafe(arg.value)) return validateUnsafeSelector(path, arg.value, tool);
|
|
4290
4292
|
return void 0;
|
|
4291
4293
|
}
|
|
4292
|
-
function isControlOwned(
|
|
4293
|
-
return
|
|
4294
|
+
function isControlOwned(value2) {
|
|
4295
|
+
return value2.label.safeBasis === "system_policy" || value2.label.safeBasis === "harness_constant";
|
|
4294
4296
|
}
|
|
4295
4297
|
function copyRegistries(registries) {
|
|
4296
4298
|
return Object.freeze(Object.fromEntries(Object.entries(registries).map(([id, registry]) => [id, Object.freeze({ digest: registry.digest, values: Object.freeze([...registry.values]) })])));
|
|
4297
4299
|
}
|
|
4298
|
-
function validateUnsafeSelector(path,
|
|
4300
|
+
function validateUnsafeSelector(path, value2, tool) {
|
|
4299
4301
|
const policy = tool.unsafeSelectorPolicy;
|
|
4300
4302
|
if (!policy || policy.effect !== tool.effect || !policy.selectorPaths.includes(path)) return "unsafe_selector_not_confined";
|
|
4301
4303
|
if (!policy.fixedDestination || !policy.unsafeOutput || policy.fixedProviderIds.length === 0) return "unsafe_selector_not_confined";
|
|
4302
4304
|
if (![policy.maximumCalls, policy.maximumResultsPerCall, policy.maximumOutputBytes, policy.maximumSelectorBytes].every((bound) => Number.isSafeInteger(bound) && bound > 0)) return "unsafe_selector_not_confined";
|
|
4303
|
-
if (utf8Length(
|
|
4304
|
-
if (typeof
|
|
4305
|
+
if (utf8Length(value2.value) > policy.maximumSelectorBytes) return "unsafe_selector_too_large";
|
|
4306
|
+
if (typeof value2.value === "string" && looksLikeDestination(value2.value)) return "unsafe_selector_is_destination";
|
|
4305
4307
|
return void 0;
|
|
4306
4308
|
}
|
|
4307
|
-
function looksLikeDestination(
|
|
4308
|
-
const text =
|
|
4309
|
+
function looksLikeDestination(value2) {
|
|
4310
|
+
const text = value2.trim();
|
|
4309
4311
|
return /^(?:[a-z][a-z0-9+.-]*:\/\/|\/|\\\\)/i.test(text) || /^[\w.-]+\.[a-z]{2,}(?:[/:]|$)/i.test(text);
|
|
4310
4312
|
}
|
|
4311
4313
|
|
|
@@ -4391,9 +4393,9 @@ var CodeRuntimeReconciler = class {
|
|
|
4391
4393
|
}
|
|
4392
4394
|
}
|
|
4393
4395
|
};
|
|
4394
|
-
function retryableControlFailure(
|
|
4395
|
-
if (!
|
|
4396
|
-
const failure =
|
|
4396
|
+
function retryableControlFailure(value2) {
|
|
4397
|
+
if (!value2 || typeof value2 !== "object") return false;
|
|
4398
|
+
const failure = value2;
|
|
4397
4399
|
if (failure.code === "invalid_response" || typeof failure.status !== "number") return false;
|
|
4398
4400
|
return failure.status === 408 || failure.status === 425 || failure.status === 429 || failure.status >= 500;
|
|
4399
4401
|
}
|
|
@@ -4445,16 +4447,16 @@ function createCodeRuntimeControlClient(options) {
|
|
|
4445
4447
|
if (options.signal?.aborted) throw cause;
|
|
4446
4448
|
throw new CodeRuntimeControlError("Code runtime control plane is unavailable", 503, "transport_unavailable");
|
|
4447
4449
|
}
|
|
4448
|
-
const
|
|
4450
|
+
const value2 = await response2.json().catch(() => null);
|
|
4449
4451
|
if (!response2.ok) {
|
|
4450
|
-
const problem = record3(record3(
|
|
4452
|
+
const problem = record3(record3(value2)?.error);
|
|
4451
4453
|
throw new CodeRuntimeControlError(
|
|
4452
4454
|
typeof problem?.message === "string" ? problem.message : `Code runtime request failed (${response2.status})`,
|
|
4453
4455
|
response2.status,
|
|
4454
4456
|
typeof problem?.code === "string" ? problem.code : void 0
|
|
4455
4457
|
);
|
|
4456
4458
|
}
|
|
4457
|
-
return
|
|
4459
|
+
return value2;
|
|
4458
4460
|
};
|
|
4459
4461
|
return {
|
|
4460
4462
|
heartbeat: async (version, capabilities) => {
|
|
@@ -4469,15 +4471,15 @@ function createCodeRuntimeControlClient(options) {
|
|
|
4469
4471
|
await call2(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/source`, {})
|
|
4470
4472
|
),
|
|
4471
4473
|
infer: async (sessionId, inference) => {
|
|
4472
|
-
const
|
|
4474
|
+
const value2 = record3(await call2(
|
|
4473
4475
|
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/inference`,
|
|
4474
4476
|
inference,
|
|
4475
4477
|
modelRequestTimeoutMs
|
|
4476
4478
|
));
|
|
4477
|
-
if (!
|
|
4479
|
+
if (!value2 || value2.requestId !== inference.requestId || !record3(value2.response) || !record3(value2.receipt)) {
|
|
4478
4480
|
throw new CodeRuntimeControlError("invalid Code inference response", 502, "invalid_response");
|
|
4479
4481
|
}
|
|
4480
|
-
return
|
|
4482
|
+
return value2;
|
|
4481
4483
|
},
|
|
4482
4484
|
review: async (sessionId, review) => parseReview(
|
|
4483
4485
|
await call2(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/review`, review, modelRequestTimeoutMs)
|
|
@@ -4502,8 +4504,8 @@ function createCodeRuntimeControlClient(options) {
|
|
|
4502
4504
|
}
|
|
4503
4505
|
};
|
|
4504
4506
|
}
|
|
4505
|
-
function validatedEndpoint(
|
|
4506
|
-
const endpoint =
|
|
4507
|
+
function validatedEndpoint(value2) {
|
|
4508
|
+
const endpoint = value2.replace(/\/+$/, "");
|
|
4507
4509
|
let url;
|
|
4508
4510
|
try {
|
|
4509
4511
|
url = new URL(endpoint);
|
|
@@ -4516,9 +4518,9 @@ function validatedEndpoint(value) {
|
|
|
4516
4518
|
}
|
|
4517
4519
|
return endpoint;
|
|
4518
4520
|
}
|
|
4519
|
-
function validSessionId(
|
|
4520
|
-
if (!/^csess_[0-9a-f]{32}$/.test(
|
|
4521
|
-
return
|
|
4521
|
+
function validSessionId(value2) {
|
|
4522
|
+
if (!/^csess_[0-9a-f]{32}$/.test(value2)) throw new TypeError("invalid Code session id");
|
|
4523
|
+
return value2;
|
|
4522
4524
|
}
|
|
4523
4525
|
function validateHeartbeat(version, capabilities) {
|
|
4524
4526
|
if (!version.trim() || version.length > 80) throw new TypeError("runtimeVersion is required and at most 80 characters");
|
|
@@ -4531,8 +4533,8 @@ function validateHeartbeat(version, capabilities) {
|
|
|
4531
4533
|
throw new TypeError("runtime resources must be positive integers");
|
|
4532
4534
|
}
|
|
4533
4535
|
}
|
|
4534
|
-
function parseSnapshot(
|
|
4535
|
-
const root = record3(
|
|
4536
|
+
function parseSnapshot(value2) {
|
|
4537
|
+
const root = record3(value2);
|
|
4536
4538
|
const host = record3(root?.host);
|
|
4537
4539
|
if (!host || typeof host.hostId !== "string" || typeof host.runtimeVersion !== "string" || !Number.isSafeInteger(host.lastSeenAt) || host.revokedAt !== null || !Array.isArray(root?.bindings) || root.bindings.length > 1024 || !Array.isArray(root?.commands) || root.commands.length > 64) throw invalid("heartbeat");
|
|
4538
4540
|
const bindingIds = /* @__PURE__ */ new Set();
|
|
@@ -4557,11 +4559,11 @@ function parseSnapshot(value) {
|
|
|
4557
4559
|
});
|
|
4558
4560
|
return { host, bindings, commands };
|
|
4559
4561
|
}
|
|
4560
|
-
async function parseSource(
|
|
4561
|
-
const snapshot = record3(record3(
|
|
4562
|
+
async function parseSource(value2) {
|
|
4563
|
+
const snapshot = record3(record3(value2)?.snapshot);
|
|
4562
4564
|
if (!snapshot || typeof snapshot.repository !== "string" || typeof snapshot.commitSha !== "string" || typeof snapshot.treeDigest !== "string" || !Array.isArray(snapshot.files)) throw invalid("source");
|
|
4563
|
-
const files = snapshot.files.map((
|
|
4564
|
-
const file = record3(
|
|
4565
|
+
const files = snapshot.files.map((value22) => {
|
|
4566
|
+
const file = record3(value22);
|
|
4565
4567
|
if (!file || typeof file.path !== "string" || typeof file.content !== "string") throw invalid("source file");
|
|
4566
4568
|
return { path: file.path, content: file.content };
|
|
4567
4569
|
});
|
|
@@ -4588,19 +4590,19 @@ async function parseSource(value) {
|
|
|
4588
4590
|
if (digest !== snapshot.treeDigest) throw invalid("source digest");
|
|
4589
4591
|
return { ...source, treeDigest: digest, ...references.length ? { references } : {} };
|
|
4590
4592
|
}
|
|
4591
|
-
function parseReview(
|
|
4592
|
-
const review = record3(record3(
|
|
4593
|
+
function parseReview(value2) {
|
|
4594
|
+
const review = record3(record3(value2)?.review);
|
|
4593
4595
|
if (!review || !["approved", "rejected"].includes(String(review.verdict)) || typeof review.reviewDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(review.reviewDigest) || typeof review.provider !== "string" || !review.provider || typeof review.model !== "string" || !review.model || !Number.isSafeInteger(review.policyVersion) || Number(review.policyVersion) < 1) throw invalid("review");
|
|
4594
4596
|
return review;
|
|
4595
4597
|
}
|
|
4596
|
-
function parseCandidate(
|
|
4597
|
-
const candidate = record3(record3(
|
|
4598
|
+
function parseCandidate(value2) {
|
|
4599
|
+
const candidate = record3(record3(value2)?.candidate);
|
|
4598
4600
|
if (!candidate || typeof candidate.candidateId !== "string" || !/^ccand_[0-9a-f]{32}$/.test(candidate.candidateId) || !["submitted", "approved", "published", "failed"].includes(String(candidate.status))) {
|
|
4599
4601
|
throw invalid("candidate");
|
|
4600
4602
|
}
|
|
4601
4603
|
return { candidateId: candidate.candidateId, status: candidate.status };
|
|
4602
4604
|
}
|
|
4603
|
-
var record3 = (
|
|
4605
|
+
var record3 = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
|
|
4604
4606
|
var invalid = (part) => new CodeRuntimeControlError(`invalid Code runtime ${part} response`, 502, "invalid_response");
|
|
4605
4607
|
var RESERVED = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_modules", "dist", "coverage"]);
|
|
4606
4608
|
var SECRET = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
|
|
@@ -4634,8 +4636,8 @@ function validateCodePatch(patch2, maxBytes) {
|
|
|
4634
4636
|
if (!paths.length || new Set(paths).size !== paths.length) throw new TypeError("patch has no diffs or repeats a path");
|
|
4635
4637
|
return paths;
|
|
4636
4638
|
}
|
|
4637
|
-
function validHeaderPath(
|
|
4638
|
-
return
|
|
4639
|
+
function validHeaderPath(value2, path, prefix) {
|
|
4640
|
+
return value2 === "/dev/null" || value2 === `${prefix}/${path}`;
|
|
4639
4641
|
}
|
|
4640
4642
|
function validateRelativePath(path) {
|
|
4641
4643
|
const parts = path.split("/");
|
|
@@ -4781,8 +4783,8 @@ function assertCodeBuildRecipe(recipe2) {
|
|
|
4781
4783
|
throw new TypeError("build recipe is malformed or exceeds its control bounds");
|
|
4782
4784
|
}
|
|
4783
4785
|
}
|
|
4784
|
-
function parseMemory(
|
|
4785
|
-
const match = /^([1-9][0-9]{0,4})([kmg])$/.exec(
|
|
4786
|
+
function parseMemory(value2) {
|
|
4787
|
+
const match = /^([1-9][0-9]{0,4})([kmg])$/.exec(value2.toLowerCase());
|
|
4786
4788
|
if (!match?.[1] || !match[2]) return 0;
|
|
4787
4789
|
const scale = match[2] === "k" ? 1024 : match[2] === "m" ? 1024 ** 2 : 1024 ** 3;
|
|
4788
4790
|
return Number(match[1]) * scale;
|
|
@@ -5017,14 +5019,14 @@ function normalizedRecipe(recipe2) {
|
|
|
5017
5019
|
expectedArtifacts: [...recipe2.expectedArtifacts ?? []].sort((left, right) => left.id.localeCompare(right.id)).map((artifact) => ({ id: artifact.id, path: artifact.path, maximumBytes: artifact.maximumBytes }))
|
|
5018
5020
|
};
|
|
5019
5021
|
}
|
|
5020
|
-
function digestJson(
|
|
5021
|
-
return digestBytes(JSON.stringify(
|
|
5022
|
+
function digestJson(value2) {
|
|
5023
|
+
return digestBytes(JSON.stringify(value2));
|
|
5022
5024
|
}
|
|
5023
|
-
function digestBytes(
|
|
5024
|
-
return `sha256:${createHash22("sha256").update(
|
|
5025
|
+
function digestBytes(value2) {
|
|
5026
|
+
return `sha256:${createHash22("sha256").update(value2).digest("hex")}`;
|
|
5025
5027
|
}
|
|
5026
|
-
function integer(
|
|
5027
|
-
return Number.isSafeInteger(
|
|
5028
|
+
function integer(value2, minimum, maximum) {
|
|
5029
|
+
return Number.isSafeInteger(value2) && value2 >= minimum && value2 <= maximum;
|
|
5028
5030
|
}
|
|
5029
5031
|
async function prepareRuntimeCheckpoint(input) {
|
|
5030
5032
|
const patch2 = await input.workspace.patch(256 * 1024);
|
|
@@ -5077,7 +5079,7 @@ async function prepareRuntimeCheckpoint(input) {
|
|
|
5077
5079
|
});
|
|
5078
5080
|
return { checkpoint, verification, review, note };
|
|
5079
5081
|
}
|
|
5080
|
-
var message = (
|
|
5082
|
+
var message = (value2) => (value2 instanceof Error ? value2.message : String(value2)).slice(0, 500);
|
|
5081
5083
|
var CodeRuntimeCheckpointManager = class {
|
|
5082
5084
|
constructor(options) {
|
|
5083
5085
|
this.options = options;
|
|
@@ -5271,7 +5273,7 @@ async function conversionPolicy(id, output) {
|
|
|
5271
5273
|
return { ...definition, digest: await conversionPolicyDigest(definition) };
|
|
5272
5274
|
}
|
|
5273
5275
|
async function registeredPolicy(id, registryId, values) {
|
|
5274
|
-
const mapping = Object.fromEntries(values.map((
|
|
5276
|
+
const mapping = Object.fromEntries(values.map((value2) => [value2, value2]));
|
|
5275
5277
|
return conversionPolicy(id, {
|
|
5276
5278
|
kind: "registered_id",
|
|
5277
5279
|
registryId,
|
|
@@ -5280,7 +5282,7 @@ async function registeredPolicy(id, registryId, values) {
|
|
|
5280
5282
|
}
|
|
5281
5283
|
async function conversionRegistry(policies, values) {
|
|
5282
5284
|
const registeredIds = Object.fromEntries(await Promise.all(Object.entries(values).map(async ([id, entries]) => {
|
|
5283
|
-
const mapping = Object.fromEntries(entries.map((
|
|
5285
|
+
const mapping = Object.fromEntries(entries.map((value2) => [value2, value2]));
|
|
5284
5286
|
return [id, { values: mapping, digest: await registeredIdRegistryDigest(mapping) }];
|
|
5285
5287
|
})));
|
|
5286
5288
|
return createConversionRegistry({ policies, registeredIds });
|
|
@@ -5304,8 +5306,8 @@ async function environment(input, options, tool) {
|
|
|
5304
5306
|
};
|
|
5305
5307
|
return { ingress, policy, fixedArgs, reader: ingress.control("reader"), runId: `${input.request.requestId}:${tool}` };
|
|
5306
5308
|
}
|
|
5307
|
-
function unsafe(base,
|
|
5308
|
-
return base.ingress.quarantinedOutput(
|
|
5309
|
+
function unsafe(base, value2, field) {
|
|
5310
|
+
return base.ingress.quarantinedOutput(value2, {
|
|
5309
5311
|
readers: base.reader.label.readers,
|
|
5310
5312
|
runId: `${base.runId}:${field}`
|
|
5311
5313
|
});
|
|
@@ -5385,14 +5387,14 @@ async function read(context, request2, options, policy) {
|
|
|
5385
5387
|
}
|
|
5386
5388
|
async function patch(context, request2, options, policy) {
|
|
5387
5389
|
exactKeys(request2.input, ["patch"]);
|
|
5388
|
-
const
|
|
5389
|
-
const paths = validateCodePatch(
|
|
5390
|
+
const value2 = stringField(request2.input, "patch");
|
|
5391
|
+
const paths = validateCodePatch(value2, options.maxPatchBytes ?? 256 * 1024);
|
|
5390
5392
|
if (paths.some((path) => options.readOnlyPrefixes?.some((prefix) => path === prefix || path.startsWith(`${prefix}/`)))) {
|
|
5391
5393
|
throw new TypeError("patch targets a read-only reference source");
|
|
5392
5394
|
}
|
|
5393
|
-
const allowed = await policy.patch(policyContext(context, request2, options, { patch:
|
|
5395
|
+
const allowed = await policy.patch(policyContext(context, request2, options, { patch: value2 }));
|
|
5394
5396
|
if (!allowed) return response(request2, false, "tool denied by CaMeL policy");
|
|
5395
|
-
await applyCodePatch(context.workspaceDir,
|
|
5397
|
+
await applyCodePatch(context.workspaceDir, value2, paths);
|
|
5396
5398
|
return response(request2, true, `Applied patch to ${paths.length} file(s).`, { paths });
|
|
5397
5399
|
}
|
|
5398
5400
|
async function recipe(context, request2, options, recipes, policy) {
|
|
@@ -5483,14 +5485,14 @@ function exactKeys(input, allowed) {
|
|
|
5483
5485
|
if (Object.keys(input).some((key) => !allowed.includes(key))) throw new TypeError("tool input contains an unsupported field");
|
|
5484
5486
|
}
|
|
5485
5487
|
function stringField(input, name) {
|
|
5486
|
-
const
|
|
5487
|
-
if (typeof
|
|
5488
|
-
return
|
|
5488
|
+
const value2 = input[name];
|
|
5489
|
+
if (typeof value2 !== "string" || !value2) throw new TypeError(`${name} must be a non-empty string`);
|
|
5490
|
+
return value2;
|
|
5489
5491
|
}
|
|
5490
|
-
function optionalInteger(
|
|
5491
|
-
if (
|
|
5492
|
-
if (!Number.isSafeInteger(
|
|
5493
|
-
return
|
|
5492
|
+
function optionalInteger(value2) {
|
|
5493
|
+
if (value2 === void 0) return void 0;
|
|
5494
|
+
if (!Number.isSafeInteger(value2) || value2 < 1) throw new TypeError("line bounds must be positive integers");
|
|
5495
|
+
return value2;
|
|
5494
5496
|
}
|
|
5495
5497
|
function response(request2, ok, content2, details) {
|
|
5496
5498
|
return { requestId: request2.requestId, ok, content: content2, ...details ? { details } : {} };
|
|
@@ -5536,9 +5538,9 @@ function codeLocalSource(payload) {
|
|
|
5536
5538
|
return source;
|
|
5537
5539
|
}
|
|
5538
5540
|
function codeCheckpointPayload(payload) {
|
|
5539
|
-
const
|
|
5540
|
-
if (!
|
|
5541
|
-
return
|
|
5541
|
+
const value2 = payload.checkpoint;
|
|
5542
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) throw new TypeError("resume checkpoint is missing");
|
|
5543
|
+
return value2;
|
|
5542
5544
|
}
|
|
5543
5545
|
function fakeCodeLease(command, metadata2) {
|
|
5544
5546
|
return {
|
|
@@ -5562,7 +5564,7 @@ function fakeCodeLease(command, metadata2) {
|
|
|
5562
5564
|
}
|
|
5563
5565
|
};
|
|
5564
5566
|
}
|
|
5565
|
-
var record22 = (
|
|
5567
|
+
var record22 = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
|
|
5566
5568
|
var SOURCE_LIMITS = { maxFiles: 2e4, maxBytes: 512 * 1024 * 1024 };
|
|
5567
5569
|
async function prepareRuntimeLocalSource(input) {
|
|
5568
5570
|
const { command, descriptor: descriptor2, available, repository, baseCommitSha, resume } = input;
|
|
@@ -5652,24 +5654,24 @@ async function appendCodeRuntimeEvent(control, command, event, refs) {
|
|
|
5652
5654
|
const bounded = event.type === "message" ? { ...event, body: event.body.trim().slice(0, 2e4) || `${event.actor} event` } : event;
|
|
5653
5655
|
await control.appendSessionEvent(command.sessionId, eventId, bounded);
|
|
5654
5656
|
}
|
|
5655
|
-
var digestRuntimeValue = (
|
|
5656
|
-
var runtimeErrorMessage = (
|
|
5657
|
-
var runtimeRecord = (
|
|
5658
|
-
var safeRuntimeJson = (
|
|
5657
|
+
var digestRuntimeValue = (value2) => `sha256:${createHash3("sha256").update(value2).digest("hex")}`;
|
|
5658
|
+
var runtimeErrorMessage = (value2) => value2 instanceof Error ? value2.message : String(value2);
|
|
5659
|
+
var runtimeRecord = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
|
|
5660
|
+
var safeRuntimeJson = (value2) => {
|
|
5659
5661
|
try {
|
|
5660
|
-
return JSON.stringify(
|
|
5662
|
+
return JSON.stringify(value2).slice(0, 1e4);
|
|
5661
5663
|
} catch {
|
|
5662
5664
|
return "[event]";
|
|
5663
5665
|
}
|
|
5664
5666
|
};
|
|
5665
|
-
function runtimeResultText(
|
|
5666
|
-
const record32 = runtimeRecord(
|
|
5667
|
+
function runtimeResultText(value2) {
|
|
5668
|
+
const record32 = runtimeRecord(value2);
|
|
5667
5669
|
if (record32 && typeof record32.text === "string") return record32.text.slice(0, 2e4);
|
|
5668
5670
|
if (record32 && typeof record32.error === "string") return `Pi failed: ${record32.error.slice(0, 19989)}`;
|
|
5669
5671
|
return null;
|
|
5670
5672
|
}
|
|
5671
|
-
function runtimeResultError(
|
|
5672
|
-
const record32 = runtimeRecord(
|
|
5673
|
+
function runtimeResultError(value2) {
|
|
5674
|
+
const record32 = runtimeRecord(value2);
|
|
5673
5675
|
return record32 && typeof record32.error === "string" && record32.error.trim() ? record32.error.trim().slice(0, 2e3) : null;
|
|
5674
5676
|
}
|
|
5675
5677
|
var CodePiRuntimeEngine = class {
|
|
@@ -5943,14 +5945,14 @@ var CodePiRuntimeEngine = class {
|
|
|
5943
5945
|
this.#active.delete(command.sessionId);
|
|
5944
5946
|
return result;
|
|
5945
5947
|
}
|
|
5946
|
-
async #failure(command, active,
|
|
5947
|
-
active.failure =
|
|
5948
|
+
async #failure(command, active, value2) {
|
|
5949
|
+
active.failure = value2.slice(0, 2e3);
|
|
5948
5950
|
if (active.acknowledged) {
|
|
5949
5951
|
await this.options.control.reportSessionFailure(command.sessionId, active.failure).catch(() => void 0);
|
|
5950
5952
|
}
|
|
5951
5953
|
}
|
|
5952
|
-
async #diagnostic(command, active,
|
|
5953
|
-
const detail =
|
|
5954
|
+
async #diagnostic(command, active, value2) {
|
|
5955
|
+
const detail = value2.trim().slice(0, 2e3) || "Pi runtime failed";
|
|
5954
5956
|
this.options.onDiagnostic?.(detail);
|
|
5955
5957
|
await this.#event(
|
|
5956
5958
|
command,
|
|
@@ -6035,6 +6037,7 @@ Usage:
|
|
|
6035
6037
|
odla-ai context save <name> [--platform <url>] [--app <id>] [--env <name>] [--json]
|
|
6036
6038
|
odla-ai context remove <name> --yes [--json]
|
|
6037
6039
|
odla-ai o11y status [--app <id>] [--context <name>] [--platform https://odla.ai] [--env prod] [--minutes 60] [--json]
|
|
6040
|
+
odla-ai platform status [--context <name>] [--platform https://odla.ai] [--email <odla-account>] [--json]
|
|
6038
6041
|
odla-ai whoami [--context <name>] [--platform https://odla.ai] [--json]
|
|
6039
6042
|
odla-ai runbook ask "<question>" [--app <id>] [--all] [--json]
|
|
6040
6043
|
odla-ai runbook search "<question>" [--app <id>] [--all] [--limit <n>] [--json]
|
|
@@ -6159,6 +6162,8 @@ Commands:
|
|
|
6159
6162
|
canary, collector ingest/scheduler trust, Cloudflare-owned
|
|
6160
6163
|
runtime metrics, and a machine verdict.
|
|
6161
6164
|
--json keeps auth progress on stderr for unattended agents.
|
|
6165
|
+
platform Read canonical fleet health, releases, provider load/freshness,
|
|
6166
|
+
explicit unknowns, and next actions through a read-only grant.
|
|
6162
6167
|
provision Register services, compose integrations, persist credentials, optionally push secrets.
|
|
6163
6168
|
smoke Verify credentials, public-config, composed schema, db aggregate, and integration probes.
|
|
6164
6169
|
skill Same installer; --agent accepts all, claude, codex, cursor,
|
|
@@ -6259,17 +6264,17 @@ async function prepareCodeLocalSource(cwd, repository, readHead = readGitHead) {
|
|
|
6259
6264
|
}
|
|
6260
6265
|
}
|
|
6261
6266
|
async function readGitHead(cwd) {
|
|
6262
|
-
const
|
|
6267
|
+
const value2 = await new Promise((accept, reject) => {
|
|
6263
6268
|
execFile3("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8", maxBuffer: 16384 }, (error, stdout) => {
|
|
6264
6269
|
if (error) reject(new Error("code connect requires a Git checkout with an initial commit"));
|
|
6265
6270
|
else accept(stdout.trim());
|
|
6266
6271
|
});
|
|
6267
6272
|
});
|
|
6268
|
-
if (!/^[0-9a-f]{40}$/.test(
|
|
6269
|
-
return
|
|
6273
|
+
if (!/^[0-9a-f]{40}$/.test(value2)) throw new Error("code connect could not resolve the checkout HEAD commit");
|
|
6274
|
+
return value2;
|
|
6270
6275
|
}
|
|
6271
|
-
function digestText(
|
|
6272
|
-
return `sha256:${createHash4("sha256").update(
|
|
6276
|
+
function digestText(value2) {
|
|
6277
|
+
return `sha256:${createHash4("sha256").update(value2).digest("hex")}`;
|
|
6273
6278
|
}
|
|
6274
6279
|
|
|
6275
6280
|
// src/code-connect.ts
|
|
@@ -6433,8 +6438,8 @@ async function runCodeRuntime(input) {
|
|
|
6433
6438
|
for (const [name, handler] of handlers) process.removeListener(name, handler);
|
|
6434
6439
|
}
|
|
6435
6440
|
}
|
|
6436
|
-
function parseConnection(
|
|
6437
|
-
const root = record4(
|
|
6441
|
+
function parseConnection(value2, appId, appEnv) {
|
|
6442
|
+
const root = record4(value2);
|
|
6438
6443
|
const host = record4(root?.host);
|
|
6439
6444
|
const offer = record4(root?.offer);
|
|
6440
6445
|
const binding = record4(root?.binding);
|
|
@@ -6443,12 +6448,12 @@ function parseConnection(value, appId, appEnv) {
|
|
|
6443
6448
|
}
|
|
6444
6449
|
return root;
|
|
6445
6450
|
}
|
|
6446
|
-
function apiFailure(action, status,
|
|
6447
|
-
const message2 = record4(record4(
|
|
6451
|
+
function apiFailure(action, status, value2) {
|
|
6452
|
+
const message2 = record4(record4(value2)?.error)?.message;
|
|
6448
6453
|
return `${action} failed (${status})${typeof message2 === "string" ? `: ${message2}` : ""}`;
|
|
6449
6454
|
}
|
|
6450
|
-
function record4(
|
|
6451
|
-
return
|
|
6455
|
+
function record4(value2) {
|
|
6456
|
+
return value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
|
|
6452
6457
|
}
|
|
6453
6458
|
|
|
6454
6459
|
// src/provision.ts
|
|
@@ -6497,8 +6502,8 @@ async function postJson2(doFetch, url, bearer, body) {
|
|
|
6497
6502
|
if (!res.ok) throw new Error(`${new URL(url).pathname} failed: ${res.status} ${await responseText(res)}`);
|
|
6498
6503
|
return res.json().catch(() => ({}));
|
|
6499
6504
|
}
|
|
6500
|
-
function isRecord7(
|
|
6501
|
-
return
|
|
6505
|
+
function isRecord7(value2) {
|
|
6506
|
+
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
6502
6507
|
}
|
|
6503
6508
|
async function responseText(res) {
|
|
6504
6509
|
try {
|
|
@@ -6631,14 +6636,14 @@ async function postJson3(doFetch, url, bearer, body) {
|
|
|
6631
6636
|
});
|
|
6632
6637
|
if (!res.ok) throw new Error(`${new URL(url).pathname} failed: ${res.status} ${await safeText5(res)}`);
|
|
6633
6638
|
}
|
|
6634
|
-
function normalizeClerkConfig(
|
|
6635
|
-
if (!
|
|
6636
|
-
if (typeof
|
|
6637
|
-
const publishableKey2 = envValue(
|
|
6639
|
+
function normalizeClerkConfig(value2) {
|
|
6640
|
+
if (!value2) return null;
|
|
6641
|
+
if (typeof value2 === "string") {
|
|
6642
|
+
const publishableKey2 = envValue(value2);
|
|
6638
6643
|
return publishableKey2 ? { publishableKey: publishableKey2 } : null;
|
|
6639
6644
|
}
|
|
6640
|
-
if (typeof
|
|
6641
|
-
const cfg =
|
|
6645
|
+
if (typeof value2 !== "object") return null;
|
|
6646
|
+
const cfg = value2;
|
|
6642
6647
|
const publishableKey = envValue(cfg.publishableKey);
|
|
6643
6648
|
return publishableKey ? { publishableKey, ...cfg.audience ? { audience: cfg.audience } : {}, ...cfg.mode ? { mode: cfg.mode } : {} } : null;
|
|
6644
6649
|
}
|
|
@@ -6911,6 +6916,7 @@ var COMMAND_SURFACE = {
|
|
|
6911
6916
|
help: {},
|
|
6912
6917
|
init: {},
|
|
6913
6918
|
o11y: { status: {} },
|
|
6919
|
+
platform: { status: {} },
|
|
6914
6920
|
pm: {
|
|
6915
6921
|
...PM_ENTITIES,
|
|
6916
6922
|
handoff: {}
|
|
@@ -7078,13 +7084,13 @@ function selectEnv(requested, declared, configPath, rootDir) {
|
|
|
7078
7084
|
return env;
|
|
7079
7085
|
}
|
|
7080
7086
|
async function injectedToken(options, request2) {
|
|
7081
|
-
const
|
|
7082
|
-
if (typeof
|
|
7087
|
+
const value2 = options.token ?? await options.getToken?.(Object.freeze({ ...request2 }));
|
|
7088
|
+
if (typeof value2 !== "string" || value2.length < 8 || value2.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value2)) {
|
|
7083
7089
|
throw new Error(
|
|
7084
7090
|
request2.selfAudit ? "Self-audit requires an injected, scoped platform security token" : "Hosted security requires an injected app developer token or getToken callback"
|
|
7085
7091
|
);
|
|
7086
7092
|
}
|
|
7087
|
-
return
|
|
7093
|
+
return value2;
|
|
7088
7094
|
}
|
|
7089
7095
|
function profileFor(name, maxHuntTasks) {
|
|
7090
7096
|
const profile = name === "odla" ? odlaProfile() : name === "cloudflare-app" ? cloudflareAppProfile() : name === "generic" ? genericProfile() : void 0;
|
|
@@ -7130,8 +7136,8 @@ async function getHostedSecurityIntent(options) {
|
|
|
7130
7136
|
}
|
|
7131
7137
|
return response2;
|
|
7132
7138
|
}
|
|
7133
|
-
function isValidIntent(
|
|
7134
|
-
return !!
|
|
7139
|
+
function isValidIntent(value2, expected) {
|
|
7140
|
+
return !!value2 && value2.executionContract === "odla.hosted-security-execution-consent.v1" && /^sha256:[a-f0-9]{64}$/.test(value2.executionDigest) && /^sha256:[a-f0-9]{64}$/.test(value2.planDigest) && value2.appId === expected.appId && value2.env === expected.env && value2.sourceId === expected.sourceId && typeof value2.repository === "string" && value2.repository.length > 2 && value2.repository.length <= 201 && typeof value2.defaultBranch === "string" && value2.defaultBranch.length > 0 && value2.defaultBranch.length <= 255 && typeof value2.requestedRef === "string" && value2.requestedRef.length > 0 && value2.requestedRef.length <= 255 && !/[\u0000-\u001f\u007f]/.test(value2.requestedRef) && ["odla", "cloudflare-app", "generic"].includes(value2.profile) && value2.sourceDisclosure === "redacted";
|
|
7135
7141
|
}
|
|
7136
7142
|
|
|
7137
7143
|
// src/security-hosted-jobs.ts
|
|
@@ -7257,17 +7263,17 @@ function hostedJobPath(appIdInput, jobIdInput) {
|
|
|
7257
7263
|
const jobId = hostedIdentifier(jobIdInput, "jobId");
|
|
7258
7264
|
return `/registry/apps/${encodeURIComponent(appId)}/security/jobs/${encodeURIComponent(jobId)}`;
|
|
7259
7265
|
}
|
|
7260
|
-
function securityPlanDigest(
|
|
7261
|
-
if (!/^sha256:[a-f0-9]{64}$/.test(
|
|
7266
|
+
function securityPlanDigest(value2) {
|
|
7267
|
+
if (!/^sha256:[a-f0-9]{64}$/.test(value2)) {
|
|
7262
7268
|
throw new Error("expected plan digest must be a sha256 digest from security plan");
|
|
7263
7269
|
}
|
|
7264
|
-
return
|
|
7270
|
+
return value2;
|
|
7265
7271
|
}
|
|
7266
|
-
function securityExecutionDigest(
|
|
7267
|
-
if (!/^sha256:[a-f0-9]{64}$/.test(
|
|
7272
|
+
function securityExecutionDigest(value2) {
|
|
7273
|
+
if (!/^sha256:[a-f0-9]{64}$/.test(value2)) {
|
|
7268
7274
|
throw new Error("expected execution digest must be a sha256 digest from security intent");
|
|
7269
7275
|
}
|
|
7270
|
-
return
|
|
7276
|
+
return value2;
|
|
7271
7277
|
}
|
|
7272
7278
|
|
|
7273
7279
|
// src/argv.ts
|
|
@@ -7291,10 +7297,10 @@ function parseArgv(argv) {
|
|
|
7291
7297
|
addOption(options, rawName, arg.slice(eq + 1));
|
|
7292
7298
|
continue;
|
|
7293
7299
|
}
|
|
7294
|
-
const
|
|
7295
|
-
if (
|
|
7300
|
+
const value2 = argv[i + 1];
|
|
7301
|
+
if (value2 !== void 0 && !value2.startsWith("--")) {
|
|
7296
7302
|
i++;
|
|
7297
|
-
addOption(options, rawName,
|
|
7303
|
+
addOption(options, rawName, value2);
|
|
7298
7304
|
} else {
|
|
7299
7305
|
addOption(options, rawName, true);
|
|
7300
7306
|
}
|
|
@@ -7310,39 +7316,39 @@ function assertArgs(parsed, allowedOptions2, maxPositionals) {
|
|
|
7310
7316
|
throw new Error(`unexpected argument "${parsed.positionals[maxPositionals]}"; run "odla-ai help"`);
|
|
7311
7317
|
}
|
|
7312
7318
|
}
|
|
7313
|
-
function requiredString(
|
|
7314
|
-
const result = stringOpt(
|
|
7319
|
+
function requiredString(value2, name) {
|
|
7320
|
+
const result = stringOpt(value2);
|
|
7315
7321
|
if (!result) throw new Error(`${name} is required`);
|
|
7316
7322
|
return result;
|
|
7317
7323
|
}
|
|
7318
|
-
function stringOpt(
|
|
7319
|
-
if (typeof
|
|
7320
|
-
if (Array.isArray(
|
|
7324
|
+
function stringOpt(value2) {
|
|
7325
|
+
if (typeof value2 === "string") return value2;
|
|
7326
|
+
if (Array.isArray(value2)) return value2[value2.length - 1];
|
|
7321
7327
|
return void 0;
|
|
7322
7328
|
}
|
|
7323
|
-
function listOpt(
|
|
7324
|
-
if (
|
|
7325
|
-
const values = Array.isArray(
|
|
7329
|
+
function listOpt(value2) {
|
|
7330
|
+
if (value2 === void 0 || typeof value2 === "boolean") return void 0;
|
|
7331
|
+
const values = Array.isArray(value2) ? value2 : [value2];
|
|
7326
7332
|
return values.flatMap((item) => item.split(",")).map((item) => item.trim()).filter(Boolean);
|
|
7327
7333
|
}
|
|
7328
|
-
function boolOpt(
|
|
7329
|
-
if (typeof
|
|
7330
|
-
if (typeof
|
|
7331
|
-
if (
|
|
7334
|
+
function boolOpt(value2) {
|
|
7335
|
+
if (typeof value2 === "boolean") return value2;
|
|
7336
|
+
if (typeof value2 === "string" && (value2 === "true" || value2 === "false")) return value2 === "true";
|
|
7337
|
+
if (value2 === void 0) return void 0;
|
|
7332
7338
|
throw new Error("boolean option must be true or false");
|
|
7333
7339
|
}
|
|
7334
|
-
function numberOpt(
|
|
7335
|
-
if (
|
|
7336
|
-
const raw = stringOpt(
|
|
7340
|
+
function numberOpt(value2, flag) {
|
|
7341
|
+
if (value2 === void 0) return void 0;
|
|
7342
|
+
const raw = stringOpt(value2);
|
|
7337
7343
|
const parsed = raw === void 0 ? Number.NaN : Number(raw);
|
|
7338
7344
|
if (!Number.isSafeInteger(parsed) || parsed < 1) throw new Error(`${flag} requires a positive integer`);
|
|
7339
7345
|
return parsed;
|
|
7340
7346
|
}
|
|
7341
|
-
function addOption(options, name,
|
|
7347
|
+
function addOption(options, name, value2) {
|
|
7342
7348
|
const current = options[name];
|
|
7343
|
-
if (current === void 0) options[name] =
|
|
7344
|
-
else if (Array.isArray(current)) current.push(String(
|
|
7345
|
-
else options[name] = [String(current), String(
|
|
7349
|
+
if (current === void 0) options[name] = value2;
|
|
7350
|
+
else if (Array.isArray(current)) current.push(String(value2));
|
|
7351
|
+
else options[name] = [String(current), String(value2)];
|
|
7346
7352
|
}
|
|
7347
7353
|
|
|
7348
7354
|
// src/operator-context.ts
|
|
@@ -7370,8 +7376,8 @@ function resolveOperatorProfile(parsed) {
|
|
|
7370
7376
|
}
|
|
7371
7377
|
assertOperatorName(name, "context");
|
|
7372
7378
|
const profiles = readOperatorProfiles(file);
|
|
7373
|
-
const
|
|
7374
|
-
if (!
|
|
7379
|
+
const value2 = Object.hasOwn(profiles, name) ? profiles[name] : void 0;
|
|
7380
|
+
if (!value2) {
|
|
7375
7381
|
throw new Error(
|
|
7376
7382
|
`operator context "${name}" not found in ${file}; run "odla-ai context list" or save it first`
|
|
7377
7383
|
);
|
|
@@ -7380,7 +7386,7 @@ function resolveOperatorProfile(parsed) {
|
|
|
7380
7386
|
name,
|
|
7381
7387
|
source: fromFlag ? "flag" : "environment",
|
|
7382
7388
|
file,
|
|
7383
|
-
value
|
|
7389
|
+
value: value2
|
|
7384
7390
|
};
|
|
7385
7391
|
}
|
|
7386
7392
|
function listOperatorProfiles(file = operatorProfileFile()) {
|
|
@@ -7408,8 +7414,8 @@ function operatorCredentialFiles(selection) {
|
|
|
7408
7414
|
scoped: join9(base, "admin-token.local.json")
|
|
7409
7415
|
};
|
|
7410
7416
|
}
|
|
7411
|
-
function assertOperatorName(
|
|
7412
|
-
if (!/^[a-z0-9][a-z0-9-]*$/.test(
|
|
7417
|
+
function assertOperatorName(value2, label) {
|
|
7418
|
+
if (!/^[a-z0-9][a-z0-9-]*$/.test(value2)) {
|
|
7413
7419
|
throw new Error(
|
|
7414
7420
|
`${label} must contain lowercase letters, numbers, and hyphens`
|
|
7415
7421
|
);
|
|
@@ -7435,22 +7441,22 @@ function readOperatorProfiles(file) {
|
|
|
7435
7441
|
);
|
|
7436
7442
|
}
|
|
7437
7443
|
const profiles = emptyProfiles();
|
|
7438
|
-
for (const [name,
|
|
7444
|
+
for (const [name, value2] of Object.entries(
|
|
7439
7445
|
raw.profiles
|
|
7440
7446
|
)) {
|
|
7441
7447
|
assertOperatorName(name, "context");
|
|
7442
|
-
profiles[name] = validateProfile(
|
|
7448
|
+
profiles[name] = validateProfile(value2, `operator context "${name}"`);
|
|
7443
7449
|
}
|
|
7444
7450
|
return profiles;
|
|
7445
7451
|
}
|
|
7446
7452
|
function emptyProfiles() {
|
|
7447
7453
|
return /* @__PURE__ */ Object.create(null);
|
|
7448
7454
|
}
|
|
7449
|
-
function validateProfile(
|
|
7450
|
-
if (!
|
|
7455
|
+
function validateProfile(value2, label) {
|
|
7456
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) {
|
|
7451
7457
|
throw new Error(`${label} has an invalid shape`);
|
|
7452
7458
|
}
|
|
7453
|
-
const unknown = Object.keys(
|
|
7459
|
+
const unknown = Object.keys(value2).filter(
|
|
7454
7460
|
(key) => !["platform", "app", "environment"].includes(key)
|
|
7455
7461
|
);
|
|
7456
7462
|
if (unknown.length > 0) {
|
|
@@ -7458,7 +7464,7 @@ function validateProfile(value, label) {
|
|
|
7458
7464
|
`${label} contains unsupported field(s): ${unknown.sort().join(", ")}; contexts store scope metadata only, never credentials`
|
|
7459
7465
|
);
|
|
7460
7466
|
}
|
|
7461
|
-
const candidate =
|
|
7467
|
+
const candidate = value2;
|
|
7462
7468
|
if (typeof candidate.platform !== "string") {
|
|
7463
7469
|
throw new Error(`${label} needs an absolute platform URL`);
|
|
7464
7470
|
}
|
|
@@ -7473,8 +7479,8 @@ function validateProfile(value, label) {
|
|
|
7473
7479
|
...environment2 ? { environment: environment2 } : {}
|
|
7474
7480
|
};
|
|
7475
7481
|
}
|
|
7476
|
-
function clean(
|
|
7477
|
-
const normalized =
|
|
7482
|
+
function clean(value2) {
|
|
7483
|
+
const normalized = value2?.trim();
|
|
7478
7484
|
return normalized || void 0;
|
|
7479
7485
|
}
|
|
7480
7486
|
|
|
@@ -7567,8 +7573,8 @@ async function resolveOperatorContext(parsed, options = {}) {
|
|
|
7567
7573
|
}
|
|
7568
7574
|
};
|
|
7569
7575
|
}
|
|
7570
|
-
function clean2(
|
|
7571
|
-
const normalized =
|
|
7576
|
+
function clean2(value2) {
|
|
7577
|
+
const normalized = value2?.trim();
|
|
7572
7578
|
return normalized || void 0;
|
|
7573
7579
|
}
|
|
7574
7580
|
|
|
@@ -8257,10 +8263,10 @@ function harnessList(parsed) {
|
|
|
8257
8263
|
];
|
|
8258
8264
|
return selected.length ? selected : ["all"];
|
|
8259
8265
|
}
|
|
8260
|
-
function harnessOption(
|
|
8261
|
-
if (
|
|
8262
|
-
if (typeof
|
|
8263
|
-
const raw = Array.isArray(
|
|
8266
|
+
function harnessOption(value2, flag) {
|
|
8267
|
+
if (value2 === void 0) return [];
|
|
8268
|
+
if (typeof value2 === "boolean") throw new Error(`${flag} requires a harness name`);
|
|
8269
|
+
const raw = Array.isArray(value2) ? value2 : [value2];
|
|
8264
8270
|
const parts = raw.flatMap((item) => item.split(","));
|
|
8265
8271
|
if (parts.some((item) => !item.trim())) {
|
|
8266
8272
|
throw new Error(`${flag} requires a harness name`);
|
|
@@ -8429,8 +8435,8 @@ function developerTokenStatus(context, parsed, now = Date.now()) {
|
|
|
8429
8435
|
cacheStatus
|
|
8430
8436
|
};
|
|
8431
8437
|
}
|
|
8432
|
-
function clean3(
|
|
8433
|
-
const normalized =
|
|
8438
|
+
function clean3(value2) {
|
|
8439
|
+
const normalized = value2?.trim();
|
|
8434
8440
|
return normalized || void 0;
|
|
8435
8441
|
}
|
|
8436
8442
|
|
|
@@ -8579,8 +8585,8 @@ async function request(ctx, method, path, body) {
|
|
|
8579
8585
|
throw new Error(`discuss ${method} ${path} failed: ${data.error ?? `registry returned ${res.status}`}`);
|
|
8580
8586
|
return data;
|
|
8581
8587
|
}
|
|
8582
|
-
function emit(ctx,
|
|
8583
|
-
if (ctx.json) ctx.out.log(JSON.stringify(
|
|
8588
|
+
function emit(ctx, value2, human) {
|
|
8589
|
+
if (ctx.json) ctx.out.log(JSON.stringify(value2, null, 2));
|
|
8584
8590
|
else human();
|
|
8585
8591
|
}
|
|
8586
8592
|
var state = (topic) => topic.resolved ? "resolved" : "open";
|
|
@@ -8625,8 +8631,8 @@ async function discussList(ctx, parsed) {
|
|
|
8625
8631
|
["limit", "limit"],
|
|
8626
8632
|
["offset", "offset"]
|
|
8627
8633
|
]) {
|
|
8628
|
-
const
|
|
8629
|
-
if (
|
|
8634
|
+
const value2 = stringOpt(parsed.options[flag]);
|
|
8635
|
+
if (value2) query.set(param, value2);
|
|
8630
8636
|
}
|
|
8631
8637
|
const qs = query.toString();
|
|
8632
8638
|
const page = await request(ctx, "GET", `/topics${qs ? `?${qs}` : ""}`);
|
|
@@ -8823,11 +8829,11 @@ var MAX_CONSECUTIVE_FAILURES = 5;
|
|
|
8823
8829
|
var MAX_BACKOFF_MS = 3e4;
|
|
8824
8830
|
function numberOpt2(parsed, flag, fallback) {
|
|
8825
8831
|
const raw = stringOpt(parsed.options[flag]);
|
|
8826
|
-
const
|
|
8827
|
-
return Number.isFinite(
|
|
8832
|
+
const value2 = raw == null ? NaN : Number(raw);
|
|
8833
|
+
return Number.isFinite(value2) && value2 > 0 ? value2 : fallback;
|
|
8828
8834
|
}
|
|
8829
|
-
function jsonl(ctx, parsed,
|
|
8830
|
-
if (parsed.options.jsonl === true) ctx.out.log(JSON.stringify({ v: 1, ...
|
|
8835
|
+
function jsonl(ctx, parsed, value2) {
|
|
8836
|
+
if (parsed.options.jsonl === true) ctx.out.log(JSON.stringify({ v: 1, ...value2 }));
|
|
8831
8837
|
}
|
|
8832
8838
|
async function discussWatch(ctx, topicId, parsed) {
|
|
8833
8839
|
if (ctx.json && parsed.options.jsonl === true) throw new Error("--json and --jsonl cannot be combined");
|
|
@@ -9089,13 +9095,13 @@ async function pmRequest(ctx, method, path, body) {
|
|
|
9089
9095
|
function collectFields(parsed, allowClear) {
|
|
9090
9096
|
const out = {};
|
|
9091
9097
|
for (const [flag, spec] of Object.entries(FIELD_MAP)) {
|
|
9092
|
-
const
|
|
9093
|
-
if (
|
|
9094
|
-
if (
|
|
9098
|
+
const value2 = parsed.options[flag];
|
|
9099
|
+
if (value2 === void 0 || value2 === true) continue;
|
|
9100
|
+
if (value2 === false) {
|
|
9095
9101
|
if (allowClear) out[spec.key] = null;
|
|
9096
9102
|
continue;
|
|
9097
9103
|
}
|
|
9098
|
-
const text = stringOpt(
|
|
9104
|
+
const text = stringOpt(value2);
|
|
9099
9105
|
out[spec.key] = spec.num ? Number(text) : text;
|
|
9100
9106
|
}
|
|
9101
9107
|
return out;
|
|
@@ -9116,8 +9122,8 @@ function statusCol(entity, r) {
|
|
|
9116
9122
|
function printRecord(ctx, entity, r) {
|
|
9117
9123
|
ctx.out.log(`${r.id} [${statusCol(entity, r)}] ${r.appId} ${r.title ?? ""}`);
|
|
9118
9124
|
}
|
|
9119
|
-
function emit2(ctx,
|
|
9120
|
-
if (ctx.json) ctx.out.log(JSON.stringify(
|
|
9125
|
+
function emit2(ctx, value2, human) {
|
|
9126
|
+
if (ctx.json) ctx.out.log(JSON.stringify(value2, null, 2));
|
|
9121
9127
|
else human();
|
|
9122
9128
|
}
|
|
9123
9129
|
async function pmList(ctx, entity, parsed) {
|
|
@@ -9163,8 +9169,8 @@ async function pmAdd(ctx, entity, parsed) {
|
|
|
9163
9169
|
emit2(ctx, res, () => ctx.out.log(`created ${entity} ${res.id}`));
|
|
9164
9170
|
}
|
|
9165
9171
|
async function pmGet(ctx, entity, id) {
|
|
9166
|
-
const { record:
|
|
9167
|
-
emit2(ctx,
|
|
9172
|
+
const { record: record8 } = await pmRequest(ctx, "GET", `/${entity}/${encodeURIComponent(id)}`);
|
|
9173
|
+
emit2(ctx, record8, () => printRecord(ctx, entity, record8));
|
|
9168
9174
|
}
|
|
9169
9175
|
async function pmSet(ctx, entity, id, parsed) {
|
|
9170
9176
|
const patch2 = collectEntityFields(entity, parsed, true);
|
|
@@ -9209,9 +9215,9 @@ async function pmHandoff(ctx, parsed) {
|
|
|
9209
9215
|
]);
|
|
9210
9216
|
const handoff = {
|
|
9211
9217
|
appId,
|
|
9212
|
-
unmetGoals: goals.filter((
|
|
9213
|
-
activeTasks: tasks.filter((
|
|
9214
|
-
openBugs: bugs.filter((
|
|
9218
|
+
unmetGoals: goals.filter((record8) => record8.status !== "met"),
|
|
9219
|
+
activeTasks: tasks.filter((record8) => record8.column !== "done"),
|
|
9220
|
+
openBugs: bugs.filter((record8) => record8.status !== "fixed" && record8.status !== "wontfix")
|
|
9215
9221
|
};
|
|
9216
9222
|
const result = {
|
|
9217
9223
|
...handoff,
|
|
@@ -9230,10 +9236,10 @@ async function pmHandoff(ctx, parsed) {
|
|
|
9230
9236
|
]) {
|
|
9231
9237
|
ctx.out.log(`${label}:`);
|
|
9232
9238
|
if (!records.length) ctx.out.log("- (none)");
|
|
9233
|
-
else for (const
|
|
9239
|
+
else for (const record8 of records) printRecord(
|
|
9234
9240
|
ctx,
|
|
9235
9241
|
label === "unmet goals" ? "goal" : label === "active tasks" ? "task" : "bug",
|
|
9236
|
-
|
|
9242
|
+
record8
|
|
9237
9243
|
);
|
|
9238
9244
|
}
|
|
9239
9245
|
});
|
|
@@ -9381,6 +9387,113 @@ async function pmCommand(parsed, deps = {}) {
|
|
|
9381
9387
|
}
|
|
9382
9388
|
}
|
|
9383
9389
|
|
|
9390
|
+
// src/platform-output.ts
|
|
9391
|
+
function printPlatformStatus(status, out) {
|
|
9392
|
+
out.log(`platform ${status.verdict.status} ${status.observedAt}`);
|
|
9393
|
+
out.log(
|
|
9394
|
+
`fleet ${status.summary.healthy}/${status.summary.services} healthy ${status.summary.required} required ${status.summary.unreachable} unreachable ${status.summary.notConfigured} not configured`
|
|
9395
|
+
);
|
|
9396
|
+
out.log(`catalog ${status.catalog.revision}`);
|
|
9397
|
+
out.log(
|
|
9398
|
+
"service required health probe ms version provider age requests errors cpu p99 us wall p99 us"
|
|
9399
|
+
);
|
|
9400
|
+
for (const service of status.services) {
|
|
9401
|
+
const metrics = service.provider.metrics;
|
|
9402
|
+
out.log([
|
|
9403
|
+
service.id,
|
|
9404
|
+
service.required ? "yes" : "no",
|
|
9405
|
+
service.health.status,
|
|
9406
|
+
value(service.health.latencyMs),
|
|
9407
|
+
service.release.observedVersionId ?? "unknown",
|
|
9408
|
+
service.provider.status,
|
|
9409
|
+
age(service.provider.ageMs),
|
|
9410
|
+
value(metrics?.requests),
|
|
9411
|
+
value(metrics?.errors),
|
|
9412
|
+
value(metrics?.cpuTimeP99),
|
|
9413
|
+
value(metrics?.wallTimeP99)
|
|
9414
|
+
].join(" "));
|
|
9415
|
+
}
|
|
9416
|
+
if (status.verdict.reasons.length) {
|
|
9417
|
+
out.log(`reasons ${status.verdict.reasons.join(", ")}`);
|
|
9418
|
+
}
|
|
9419
|
+
for (const action of status.nextActions) {
|
|
9420
|
+
out.log(`next ${action.service} ${action.code} ${action.message}`);
|
|
9421
|
+
}
|
|
9422
|
+
}
|
|
9423
|
+
function value(input) {
|
|
9424
|
+
return input === null || input === void 0 ? "unknown" : String(input);
|
|
9425
|
+
}
|
|
9426
|
+
function age(input) {
|
|
9427
|
+
if (input === null) return "unknown";
|
|
9428
|
+
if (input < 1e3) return `${input}ms`;
|
|
9429
|
+
if (input < 6e4) return `${Math.round(input / 1e3)}s`;
|
|
9430
|
+
return `${Math.round(input / 6e4)}m`;
|
|
9431
|
+
}
|
|
9432
|
+
|
|
9433
|
+
// src/platform-command.ts
|
|
9434
|
+
async function platformCommand(parsed, deps = {}) {
|
|
9435
|
+
assertArgs(
|
|
9436
|
+
parsed,
|
|
9437
|
+
["config", "context", "platform", "token", "email", "open", "json"],
|
|
9438
|
+
2
|
|
9439
|
+
);
|
|
9440
|
+
const action = parsed.positionals[1];
|
|
9441
|
+
if (action !== "status") {
|
|
9442
|
+
throw new Error(
|
|
9443
|
+
`unknown platform action "${action ?? ""}". Try "odla-ai platform status --json".`
|
|
9444
|
+
);
|
|
9445
|
+
}
|
|
9446
|
+
const context = await resolveOperatorContext(parsed, {
|
|
9447
|
+
allowMissingConfig: true
|
|
9448
|
+
});
|
|
9449
|
+
const platform = context.platform.value;
|
|
9450
|
+
const doFetch = deps.fetch ?? fetch;
|
|
9451
|
+
const out = deps.stdout ?? console;
|
|
9452
|
+
const token = await resolveAdminPlatformToken({
|
|
9453
|
+
platform,
|
|
9454
|
+
scope: "platform:status:read",
|
|
9455
|
+
token: stringOpt(parsed.options.token),
|
|
9456
|
+
tokenFile: context.credentials.scopedTokenFile,
|
|
9457
|
+
email: stringOpt(parsed.options.email),
|
|
9458
|
+
open: parsed.options.open === false ? false : parsed.options.open === true ? true : void 0,
|
|
9459
|
+
fetch: doFetch,
|
|
9460
|
+
stdout: out,
|
|
9461
|
+
openApprovalUrl: deps.openUrl,
|
|
9462
|
+
label: "odla CLI (platform fleet status)"
|
|
9463
|
+
});
|
|
9464
|
+
const response2 = await doFetch(`${platform}/registry/platform/status`, {
|
|
9465
|
+
headers: { authorization: `Bearer ${token}` }
|
|
9466
|
+
});
|
|
9467
|
+
const body = await response2.json().catch(() => null);
|
|
9468
|
+
if (!response2.ok) {
|
|
9469
|
+
throw new Error(
|
|
9470
|
+
`read platform status failed (HTTP ${response2.status}): ${apiMessage(body)}`
|
|
9471
|
+
);
|
|
9472
|
+
}
|
|
9473
|
+
if (!isPlatformStatus(body)) {
|
|
9474
|
+
throw new Error("platform returned an invalid odla.platform-status/v1 envelope");
|
|
9475
|
+
}
|
|
9476
|
+
if (parsed.options.json === true) {
|
|
9477
|
+
out.log(JSON.stringify(body, null, 2));
|
|
9478
|
+
} else {
|
|
9479
|
+
printPlatformStatus(body, out);
|
|
9480
|
+
}
|
|
9481
|
+
}
|
|
9482
|
+
function isPlatformStatus(value2) {
|
|
9483
|
+
if (!record5(value2) || value2.schemaVersion !== "odla.platform-status/v1") return false;
|
|
9484
|
+
if (!record5(value2.verdict) || !Array.isArray(value2.verdict.reasons)) return false;
|
|
9485
|
+
if (!record5(value2.catalog) || !record5(value2.summary)) return false;
|
|
9486
|
+
return Array.isArray(value2.services) && Array.isArray(value2.nextActions);
|
|
9487
|
+
}
|
|
9488
|
+
function apiMessage(value2) {
|
|
9489
|
+
if (!record5(value2)) return "request failed";
|
|
9490
|
+
const error = record5(value2.error) ? value2.error : value2;
|
|
9491
|
+
return typeof error.message === "string" ? error.message : typeof error.code === "string" ? error.code : "request failed";
|
|
9492
|
+
}
|
|
9493
|
+
function record5(value2) {
|
|
9494
|
+
return !!value2 && typeof value2 === "object" && !Array.isArray(value2);
|
|
9495
|
+
}
|
|
9496
|
+
|
|
9384
9497
|
// src/o11y-verdict.ts
|
|
9385
9498
|
function statusVerdict(reads) {
|
|
9386
9499
|
const reasons = [];
|
|
@@ -9418,7 +9531,7 @@ function statusVerdict(reads) {
|
|
|
9418
9531
|
severity: "degraded"
|
|
9419
9532
|
});
|
|
9420
9533
|
}
|
|
9421
|
-
const performance =
|
|
9534
|
+
const performance = record6(reads.liveSync.body.performance) ? reads.liveSync.body.performance : null;
|
|
9422
9535
|
if (performance?.status === "unavailable") {
|
|
9423
9536
|
reasons.push({
|
|
9424
9537
|
source: "liveSync",
|
|
@@ -9499,11 +9612,11 @@ function statusVerdict(reads) {
|
|
|
9499
9612
|
reasons
|
|
9500
9613
|
};
|
|
9501
9614
|
}
|
|
9502
|
-
function
|
|
9503
|
-
return Boolean(
|
|
9615
|
+
function record6(value2) {
|
|
9616
|
+
return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
|
|
9504
9617
|
}
|
|
9505
|
-
function numeric2(
|
|
9506
|
-
return typeof
|
|
9618
|
+
function numeric2(value2) {
|
|
9619
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? value2 : 0;
|
|
9507
9620
|
}
|
|
9508
9621
|
function collectorReason(read3, fallback) {
|
|
9509
9622
|
const reasons = read3.body.reasons;
|
|
@@ -9527,7 +9640,7 @@ function printO11yStatus(status, out) {
|
|
|
9527
9640
|
out.log(
|
|
9528
9641
|
`o11y status ${status.scope.appId}/${status.scope.env} (${status.scope.minutes}m)`
|
|
9529
9642
|
);
|
|
9530
|
-
const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(
|
|
9643
|
+
const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(record7) : [];
|
|
9531
9644
|
const requests = routes.reduce(
|
|
9532
9645
|
(total, row) => total + numeric3(row.requests),
|
|
9533
9646
|
0
|
|
@@ -9539,39 +9652,39 @@ function printO11yStatus(status, out) {
|
|
|
9539
9652
|
out.log(
|
|
9540
9653
|
`application ${status.application.httpStatus} ${requests} requests ${errors} errors`
|
|
9541
9654
|
);
|
|
9542
|
-
const versions = Array.isArray(status.applicationVersions.body.rows) ? status.applicationVersions.body.rows.filter(
|
|
9655
|
+
const versions = Array.isArray(status.applicationVersions.body.rows) ? status.applicationVersions.body.rows.filter(record7) : [];
|
|
9543
9656
|
out.log(
|
|
9544
9657
|
`application-versions ${status.applicationVersions.httpStatus} ${versions.length ? versions.slice(0, 5).map(
|
|
9545
9658
|
(row) => `${String(row.value || "(unattributed)")}:${numeric3(row.requests)}`
|
|
9546
9659
|
).join(", ") : "none observed"}`
|
|
9547
9660
|
);
|
|
9548
9661
|
out.log(liveSyncLine(status.liveSync));
|
|
9549
|
-
const canaryDurations =
|
|
9662
|
+
const canaryDurations = record7(status.canary.body.durationsMs) ? status.canary.body.durationsMs : {};
|
|
9550
9663
|
out.log(
|
|
9551
9664
|
`canary ${status.canary.httpStatus} ${String(status.canary.body.status ?? status.canary.body.error ?? "unavailable")} ${optionalNumeric(canaryDurations.publishToVisibleMs)} publish-to-visible`
|
|
9552
9665
|
);
|
|
9553
|
-
const collectorIngest =
|
|
9554
|
-
const collectorStorage =
|
|
9666
|
+
const collectorIngest = record7(status.collector.body.ingest) ? status.collector.body.ingest : {};
|
|
9667
|
+
const collectorStorage = record7(collectorIngest.storage) ? collectorIngest.storage : {};
|
|
9555
9668
|
out.log(
|
|
9556
9669
|
`collector ${status.collector.httpStatus} ${String(status.collector.body.status ?? status.collector.body.error ?? "unavailable")} ${numeric3(collectorStorage.affectedPoints)} affected points`
|
|
9557
9670
|
);
|
|
9558
|
-
const providerMetrics =
|
|
9559
|
-
const providerCapacity =
|
|
9560
|
-
const workerMemory =
|
|
9671
|
+
const providerMetrics = record7(status.provider.body.metrics) ? status.provider.body.metrics : {};
|
|
9672
|
+
const providerCapacity = record7(status.provider.body.capacity) ? status.provider.body.capacity : {};
|
|
9673
|
+
const workerMemory = record7(providerCapacity.memory) ? providerCapacity.memory : {};
|
|
9561
9674
|
out.log(
|
|
9562
9675
|
`cloudflare ${status.provider.httpStatus} ${String(status.provider.body.status ?? status.provider.body.error ?? "unavailable")} ${numeric3(providerMetrics.requests)} invocations ${numeric3(providerMetrics.errors)} runtime errors ${optionalBytes(workerMemory.headroomBytes)} isolate memory headroom`
|
|
9563
9676
|
);
|
|
9564
9677
|
for (const line of providerCapacityLines(status.providerCapacity)) {
|
|
9565
9678
|
out.log(line);
|
|
9566
9679
|
}
|
|
9567
|
-
const coverage =
|
|
9568
|
-
const coverageCounts =
|
|
9569
|
-
const coverageBudget =
|
|
9680
|
+
const coverage = record7(status.providerReconciliation.body.comparison) ? status.providerReconciliation.body.comparison : {};
|
|
9681
|
+
const coverageCounts = record7(status.providerReconciliation.body.counts) ? status.providerReconciliation.body.counts : {};
|
|
9682
|
+
const coverageBudget = record7(status.providerReconciliation.body.budget) ? status.providerReconciliation.body.budget : {};
|
|
9570
9683
|
out.log(
|
|
9571
9684
|
`request-coverage ${status.providerReconciliation.httpStatus} ${String(status.providerReconciliation.body.status ?? status.providerReconciliation.body.error ?? "unavailable")} ${optionalPercent(coverage.applicationCoverage)} application/provider ${numeric3(coverageCounts.applicationRequests)}/${numeric3(coverageCounts.providerRequests)} requests \xB1${optionalPercent(coverageBudget.maxRelativeError)} budget`
|
|
9572
9685
|
);
|
|
9573
9686
|
const providerPoints = Array.isArray(status.providerHistory.body.points) ? status.providerHistory.body.points.length : 0;
|
|
9574
|
-
const providerFreshness =
|
|
9687
|
+
const providerFreshness = record7(status.providerHistory.body.freshness) ? status.providerHistory.body.freshness : {};
|
|
9575
9688
|
out.log(
|
|
9576
9689
|
`cloudflare-history ${status.providerHistory.httpStatus} ${String(status.providerHistory.body.status ?? status.providerHistory.body.error ?? "unavailable")} ${providerPoints} snapshots ${optionalAge(providerFreshness.ageMs)} old`
|
|
9577
9690
|
);
|
|
@@ -9580,17 +9693,17 @@ function printO11yStatus(status, out) {
|
|
|
9580
9693
|
);
|
|
9581
9694
|
}
|
|
9582
9695
|
function providerCapacityLines(read3) {
|
|
9583
|
-
const resources =
|
|
9584
|
-
const durableObjects =
|
|
9585
|
-
const periodic =
|
|
9586
|
-
const storage =
|
|
9587
|
-
const d1 =
|
|
9588
|
-
const d1Activity =
|
|
9589
|
-
const d1Storage =
|
|
9590
|
-
const d1Latency =
|
|
9591
|
-
const r2 =
|
|
9592
|
-
const r2Operations =
|
|
9593
|
-
const r2Storage =
|
|
9696
|
+
const resources = record7(read3.body.resources) ? read3.body.resources : {};
|
|
9697
|
+
const durableObjects = record7(resources.durableObjects) ? resources.durableObjects : {};
|
|
9698
|
+
const periodic = record7(durableObjects.periodic) ? durableObjects.periodic : {};
|
|
9699
|
+
const storage = record7(durableObjects.sqliteStorage) ? durableObjects.sqliteStorage : {};
|
|
9700
|
+
const d1 = record7(resources.d1) ? resources.d1 : {};
|
|
9701
|
+
const d1Activity = record7(d1.activity) ? d1.activity : {};
|
|
9702
|
+
const d1Storage = record7(d1.storage) ? d1.storage : {};
|
|
9703
|
+
const d1Latency = record7(d1Activity.latency) ? d1Activity.latency : {};
|
|
9704
|
+
const r2 = record7(resources.r2) ? resources.r2 : {};
|
|
9705
|
+
const r2Operations = record7(r2.operations) ? r2.operations : {};
|
|
9706
|
+
const r2Storage = record7(r2.storage) ? r2.storage : {};
|
|
9594
9707
|
const status = String(
|
|
9595
9708
|
read3.body.status ?? read3.body.error ?? "unavailable"
|
|
9596
9709
|
);
|
|
@@ -9601,42 +9714,42 @@ function providerCapacityLines(read3) {
|
|
|
9601
9714
|
];
|
|
9602
9715
|
}
|
|
9603
9716
|
function liveSyncLine(read3) {
|
|
9604
|
-
const performance =
|
|
9605
|
-
const commitToSend =
|
|
9717
|
+
const performance = record7(read3.body.performance) ? read3.body.performance : {};
|
|
9718
|
+
const commitToSend = record7(performance.commitToSend) ? performance.commitToSend : {};
|
|
9606
9719
|
return `live-sync ${read3.httpStatus} ${String(read3.body.status ?? read3.body.error ?? "unavailable")} ${numeric3(read3.body.activeConnections)} active ${optionalNumeric(commitToSend.p95)} commit-to-send p95 ${numeric3(performance.sendFailures)} send failures`;
|
|
9607
9720
|
}
|
|
9608
|
-
function
|
|
9609
|
-
return Boolean(
|
|
9721
|
+
function record7(value2) {
|
|
9722
|
+
return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
|
|
9610
9723
|
}
|
|
9611
|
-
function numeric3(
|
|
9612
|
-
return typeof
|
|
9724
|
+
function numeric3(value2) {
|
|
9725
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? value2 : 0;
|
|
9613
9726
|
}
|
|
9614
|
-
function optionalNumeric(
|
|
9615
|
-
return typeof
|
|
9727
|
+
function optionalNumeric(value2) {
|
|
9728
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? `${value2} ms` : "\u2014";
|
|
9616
9729
|
}
|
|
9617
|
-
function optionalAge(
|
|
9618
|
-
if (typeof
|
|
9619
|
-
return `${Math.max(0, Math.round(
|
|
9730
|
+
function optionalAge(value2) {
|
|
9731
|
+
if (typeof value2 !== "number" || !Number.isFinite(value2)) return "unknown";
|
|
9732
|
+
return `${Math.max(0, Math.round(value2 / 1e3))}s`;
|
|
9620
9733
|
}
|
|
9621
|
-
function optionalPercent(
|
|
9622
|
-
return typeof
|
|
9734
|
+
function optionalPercent(value2) {
|
|
9735
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? `${Math.round(value2 * 100)}%` : "\u2014";
|
|
9623
9736
|
}
|
|
9624
|
-
function optionalBytes(
|
|
9625
|
-
if (typeof
|
|
9626
|
-
if (
|
|
9627
|
-
return `${(
|
|
9737
|
+
function optionalBytes(value2) {
|
|
9738
|
+
if (typeof value2 !== "number" || !Number.isFinite(value2)) return "\u2014";
|
|
9739
|
+
if (value2 >= 1024 * 1024 * 1024) {
|
|
9740
|
+
return `${(value2 / (1024 * 1024 * 1024)).toFixed(2)} GiB`;
|
|
9628
9741
|
}
|
|
9629
|
-
if (
|
|
9630
|
-
return `${(
|
|
9742
|
+
if (value2 >= 1024 * 1024) {
|
|
9743
|
+
return `${(value2 / (1024 * 1024)).toFixed(1)} MiB`;
|
|
9631
9744
|
}
|
|
9632
|
-
if (
|
|
9633
|
-
return `${Math.round(
|
|
9745
|
+
if (value2 >= 1024) return `${(value2 / 1024).toFixed(1)} KiB`;
|
|
9746
|
+
return `${Math.round(value2)} B`;
|
|
9634
9747
|
}
|
|
9635
|
-
function optionalCount(
|
|
9636
|
-
return typeof
|
|
9748
|
+
function optionalCount(value2, unit) {
|
|
9749
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? `${value2} ${unit}` : `\u2014 ${unit}`;
|
|
9637
9750
|
}
|
|
9638
|
-
function optionalAgeSeconds(
|
|
9639
|
-
return typeof
|
|
9751
|
+
function optionalAgeSeconds(value2) {
|
|
9752
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? `${Math.max(0, Math.round(value2))}s` : "unknown";
|
|
9640
9753
|
}
|
|
9641
9754
|
|
|
9642
9755
|
// src/o11y-command.ts
|
|
@@ -9766,11 +9879,11 @@ async function o11yCommand(parsed, deps = {}) {
|
|
|
9766
9879
|
}
|
|
9767
9880
|
printO11yStatus(status, out);
|
|
9768
9881
|
}
|
|
9769
|
-
function statusMinutes(
|
|
9770
|
-
if (!Number.isSafeInteger(
|
|
9882
|
+
function statusMinutes(value2) {
|
|
9883
|
+
if (!Number.isSafeInteger(value2) || value2 < 1 || value2 > 7 * 24 * 60) {
|
|
9771
9884
|
throw new Error("--minutes must be an integer from 1 to 10080");
|
|
9772
9885
|
}
|
|
9773
|
-
return
|
|
9886
|
+
return value2;
|
|
9774
9887
|
}
|
|
9775
9888
|
async function read2(url, headers, doFetch) {
|
|
9776
9889
|
const response2 = await doFetch(url, { headers });
|
|
@@ -9778,8 +9891,8 @@ async function read2(url, headers, doFetch) {
|
|
|
9778
9891
|
let body = {};
|
|
9779
9892
|
if (text) {
|
|
9780
9893
|
try {
|
|
9781
|
-
const
|
|
9782
|
-
body =
|
|
9894
|
+
const value2 = JSON.parse(text);
|
|
9895
|
+
body = value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : { value: value2 };
|
|
9783
9896
|
} catch {
|
|
9784
9897
|
body = { message: text.slice(0, 300) };
|
|
9785
9898
|
}
|
|
@@ -9796,7 +9909,7 @@ function recordInvocation(parsed) {
|
|
|
9796
9909
|
try {
|
|
9797
9910
|
const entry = {
|
|
9798
9911
|
path: invocationPath(parsed.positionals),
|
|
9799
|
-
options: Object.entries(parsed.options).map(([name,
|
|
9912
|
+
options: Object.entries(parsed.options).map(([name, value2]) => value2 === false ? `no-${name}` : name).sort()
|
|
9800
9913
|
};
|
|
9801
9914
|
if (!entry.path.length) return;
|
|
9802
9915
|
appendFileSync(file, `${JSON.stringify(entry)}
|
|
@@ -9810,10 +9923,10 @@ import { readFileSync as readFileSync9 } from "fs";
|
|
|
9810
9923
|
|
|
9811
9924
|
// src/runbook-requires.ts
|
|
9812
9925
|
var SPEC = /^(@?[\w./-]+?)@(\d+\.\d+\.\d+(?:[\w.-]*)?)$/;
|
|
9813
|
-
function parseRequires(
|
|
9814
|
-
if (!
|
|
9926
|
+
function parseRequires(value2) {
|
|
9927
|
+
if (!value2) return [];
|
|
9815
9928
|
const out = [];
|
|
9816
|
-
for (const token of
|
|
9929
|
+
for (const token of value2.split(/[\s,]+/).filter(Boolean)) {
|
|
9817
9930
|
const match = SPEC.exec(token);
|
|
9818
9931
|
if (match?.[1] && match[2]) out.push({ name: match[1], min: match[2] });
|
|
9819
9932
|
}
|
|
@@ -9989,9 +10102,9 @@ function parseRunbook(text, slug) {
|
|
|
9989
10102
|
for (const line of fm[1].split(/\r?\n/)) {
|
|
9990
10103
|
const pair = /^(\w+)\s*:\s*(.+)$/.exec(line.trim());
|
|
9991
10104
|
if (!pair) continue;
|
|
9992
|
-
const
|
|
9993
|
-
if (pair[1] === "summary") meta.summary =
|
|
9994
|
-
if (pair[1] === "tags") meta.tags =
|
|
10105
|
+
const value2 = pair[2].trim().replace(/^["']|["']$/g, "");
|
|
10106
|
+
if (pair[1] === "summary") meta.summary = value2;
|
|
10107
|
+
if (pair[1] === "tags") meta.tags = value2.replace(/^\[|\]$/g, "").trim();
|
|
9995
10108
|
}
|
|
9996
10109
|
}
|
|
9997
10110
|
const lines = rest.split("\n");
|
|
@@ -10108,7 +10221,7 @@ var NOISE = /* @__PURE__ */ new Set([
|
|
|
10108
10221
|
"and",
|
|
10109
10222
|
"for"
|
|
10110
10223
|
]);
|
|
10111
|
-
var words = (
|
|
10224
|
+
var words = (value2) => value2.replace(/^@[\w-]+\//, "").split(/[^A-Za-z0-9]+/).filter((w) => w.length > 1 && !NOISE.has(w.toLowerCase()));
|
|
10112
10225
|
function namedExports(clause) {
|
|
10113
10226
|
return clause.split(",").map((part) => part.trim().split(/\s+as\s+/)[0]?.trim() ?? "").filter((name) => /^[A-Za-z_$][\w$]*$/.test(name) && name !== "type");
|
|
10114
10227
|
}
|
|
@@ -10461,8 +10574,8 @@ import process13 from "process";
|
|
|
10461
10574
|
var EDITOR_ENV = ["ODLA_EDITOR", "VISUAL", "EDITOR"];
|
|
10462
10575
|
function resolveEditor(env = process13.env) {
|
|
10463
10576
|
for (const name of EDITOR_ENV) {
|
|
10464
|
-
const
|
|
10465
|
-
if (
|
|
10577
|
+
const value2 = env[name];
|
|
10578
|
+
if (value2 && value2.trim()) return value2.trim();
|
|
10466
10579
|
}
|
|
10467
10580
|
return null;
|
|
10468
10581
|
}
|
|
@@ -10727,9 +10840,9 @@ async function runbookCommand(parsed, deps = {}) {
|
|
|
10727
10840
|
});
|
|
10728
10841
|
}
|
|
10729
10842
|
case "visibility": {
|
|
10730
|
-
const
|
|
10731
|
-
if (!
|
|
10732
|
-
return runbookVisibility(ctx, requireSlug(slug, "visibility"),
|
|
10843
|
+
const value2 = parsed.positionals[3] ?? stringOpt(parsed.options.visibility);
|
|
10844
|
+
if (!value2) throw new Error('"runbook visibility" needs operator|admin, e.g. "runbook visibility release operator"');
|
|
10845
|
+
return runbookVisibility(ctx, requireSlug(slug, "visibility"), value2);
|
|
10733
10846
|
}
|
|
10734
10847
|
case "publish":
|
|
10735
10848
|
return runbookStatus(ctx, requireSlug(slug, "publish"), "published");
|
|
@@ -10785,13 +10898,13 @@ async function interactiveConfirmation(message2, dependencies) {
|
|
|
10785
10898
|
}
|
|
10786
10899
|
}
|
|
10787
10900
|
function requiredSecurityPositional(parsed, index, label) {
|
|
10788
|
-
const
|
|
10789
|
-
if (!
|
|
10790
|
-
return
|
|
10901
|
+
const value2 = parsed.positionals[index];
|
|
10902
|
+
if (!value2) throw new Error(`${label} is required`);
|
|
10903
|
+
return value2;
|
|
10791
10904
|
}
|
|
10792
|
-
function securityProfile(
|
|
10793
|
-
if (
|
|
10794
|
-
if (
|
|
10905
|
+
function securityProfile(value2) {
|
|
10906
|
+
if (value2 === void 0) return void 0;
|
|
10907
|
+
if (value2 === "odla" || value2 === "cloudflare-app" || value2 === "generic") return value2;
|
|
10795
10908
|
throw new Error("--profile must be odla, cloudflare-app, or generic");
|
|
10796
10909
|
}
|
|
10797
10910
|
|
|
@@ -10892,9 +11005,9 @@ function routeLabel(route2) {
|
|
|
10892
11005
|
return `${route2.provider}/${route2.model}${route2.policyVersion ? ` policy v${route2.policyVersion}` : ""}`;
|
|
10893
11006
|
}
|
|
10894
11007
|
var HOSTED_SEVERITIES = ["informational", "low", "medium", "high", "critical"];
|
|
10895
|
-
function hostedSeverity(
|
|
10896
|
-
if (HOSTED_SEVERITIES.includes(
|
|
10897
|
-
return
|
|
11008
|
+
function hostedSeverity(value2, flag) {
|
|
11009
|
+
if (HOSTED_SEVERITIES.includes(value2)) {
|
|
11010
|
+
return value2;
|
|
10898
11011
|
}
|
|
10899
11012
|
throw new Error(`${flag} must be informational, low, medium, high, or critical`);
|
|
10900
11013
|
}
|
|
@@ -10961,7 +11074,7 @@ async function runSourceSecurityCommand(parsed, dependencies, sourceId) {
|
|
|
10961
11074
|
...context,
|
|
10962
11075
|
jobId: job.jobId,
|
|
10963
11076
|
wait: dependencies.pollWait,
|
|
10964
|
-
onUpdate: parsed.options.json === true ? void 0 : (
|
|
11077
|
+
onUpdate: parsed.options.json === true ? void 0 : (value2) => printHostedJob(context.stdout, value2, context.platform, context.appId)
|
|
10965
11078
|
}) : job;
|
|
10966
11079
|
if (!follow) {
|
|
10967
11080
|
if (parsed.options.json === true) {
|
|
@@ -11061,9 +11174,9 @@ function enforceLocalGate(report4, parsed) {
|
|
|
11061
11174
|
throw new Error(`hosted security gate failed: ${confirmed.length} confirmed >= ${failOn}; ${leads.length} leads >= ${failOnCandidates ?? "disabled"}${incomplete ? "; coverage incomplete" : ""}`);
|
|
11062
11175
|
}
|
|
11063
11176
|
}
|
|
11064
|
-
function severityOpt(
|
|
11065
|
-
if (["informational", "low", "medium", "high", "critical"].includes(
|
|
11066
|
-
return
|
|
11177
|
+
function severityOpt(value2, flag) {
|
|
11178
|
+
if (["informational", "low", "medium", "high", "critical"].includes(value2)) {
|
|
11179
|
+
return value2;
|
|
11067
11180
|
}
|
|
11068
11181
|
throw new Error(`${flag} must be informational, low, medium, high, or critical`);
|
|
11069
11182
|
}
|
|
@@ -11171,7 +11284,7 @@ async function securityStatus(parsed, dependencies) {
|
|
|
11171
11284
|
...context,
|
|
11172
11285
|
jobId,
|
|
11173
11286
|
wait: dependencies.pollWait,
|
|
11174
|
-
onUpdate: parsed.options.json === true ? void 0 : (
|
|
11287
|
+
onUpdate: parsed.options.json === true ? void 0 : (value2) => printHostedJob(context.stdout, value2, context.platform, context.appId)
|
|
11175
11288
|
}) : await getHostedSecurityJob({ ...context, jobId });
|
|
11176
11289
|
if (parsed.options.json === true) context.stdout.log(JSON.stringify(job, null, 2));
|
|
11177
11290
|
else if (parsed.options.follow !== true) {
|
|
@@ -11255,6 +11368,10 @@ async function runCli(argv = process.argv.slice(2), dependencies = {}) {
|
|
|
11255
11368
|
await o11yCommand(parsed, runtime);
|
|
11256
11369
|
return;
|
|
11257
11370
|
}
|
|
11371
|
+
if (command === "platform") {
|
|
11372
|
+
await platformCommand(parsed, runtime);
|
|
11373
|
+
return;
|
|
11374
|
+
}
|
|
11258
11375
|
if (command === "provision") {
|
|
11259
11376
|
await provisionCommand(parsed, runtime);
|
|
11260
11377
|
return;
|
|
@@ -11374,4 +11491,4 @@ export {
|
|
|
11374
11491
|
exitCodeFor,
|
|
11375
11492
|
runCli
|
|
11376
11493
|
};
|
|
11377
|
-
//# sourceMappingURL=chunk-
|
|
11494
|
+
//# sourceMappingURL=chunk-L2NG4UR4.js.map
|