holycodex 0.15.0 → 0.15.1-dev.35.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/assets/plugin/hooks/hooks.json +17 -0
- package/dist/assets/plugin/hooks/version.ts +54 -0
- package/dist/assets/plugin/plugin.json +27 -32
- package/dist/assets/plugin/skills/writing-for-agents/SKILL.md +20 -4
- package/dist/{binary-DYvVDqZ5.js → binary-BCtnZPMA.js} +438 -285
- package/dist/binary-K1P4tTUI.js +3 -0
- package/dist/index.js +4 -4
- package/dist/{src-DamQOFzF.js → src-BmUZJGuC.js} +338 -254
- package/dist/src-BrjytttX.js +3 -0
- package/package.json +4 -4
- package/dist/assets/plugin/hooks/manifest.json +0 -11
- package/dist/binary-DODC08JV.js +0 -3
- package/dist/src-BOQ_ib7j.js +0 -3
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as DelegationModeSchema, $t as runSync, At as decodeUnknownEither, B as resolvePlanSelection, Bt as pattern, Ct as Number$, Dt as Union, Et as Struct, Ft as maxItems, G as parseCapabilityResultV2, Gt as async, H as SpecialistOutcomeSchema, Ht as is, It as maxLength, J as canonicalIdentityUtf8, Jt as mapError$3, K as parseCliEnvelope, Kt as fail, Lt as minItems, Mt as greaterThan, Nt as greaterThanOrEqualTo, Ot as Unknown, P as WorkflowRuntimeError, Pt as int, Q as sha256DomainDigest, Qt as runPromise, R as lookupPlan, Rt as minLength, S as isWorkflowFailure, St as Null, Tt as String$, U as SpecialistOutcomeV2Schema, Ut as _void, V as SPECIALIST_OUTCOME_VERSION, Vt as positive, W as normalizeSpecialistOutcome, Wt as acquireRelease, X as canonicalJsonUtf8, Xt as provide$2, Y as canonicalJson, Yt as orElseSucceed, Z as domainSeparatedSha256, Zt as raceFirst, _t as resolveOptionalCapabilitySelections, a as runExecutionPlan, an as fromEffect, at as RouteKeySchema, bt as Boolean$, c as loadNativeWorkflowSource, cn as scoped$1, ct as createProjectId, d as CompileOptionsSchema, dn as isLeft, dt as CAPABILITY_REGISTRY, en as scoped$2, et as EffortSchema, fn as isRight, ft as CapabilityNameSchema, gt as pluginIdsForOptionalCapabilities, h as hydrateWorkflowPlanIR, ht as migrateOptionalCapabilitySelections, i as makeCapacityService, in as try_, it as RoleTaskSchema, jt as filter, kt as declare, ln as succeed$1, lt as createSha256Digest, mn as STATE_SCHEMA_EPOCH, mt as capabilityHealth, n as evaluateWorkflowCompatibility, nn as sync, nt as RoleSchema, on as mapError$2, ot as ServiceTierSchema, p as compileWorkflow, pn as CLI_SCHEMA_VERSION, pt as OPTIONAL_CAPABILITY_NAMES, q as specialistOutcomeFromCapabilityResult, qt as gen, rn as tryPromise, rt as RoleSkillProfileSchema, sn as provide$1, st as lookupRoleDefinition, tn as succeed$2, tt as PlanNameSchema, un as Tag, ut as createTrustId, vt as decodeUnknown, wt as Record, xt as Literal, yt as Array$, z as lookupRoute, zt as optional } from "./src-BmUZJGuC.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { copyFile, cp, link, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
5
5
|
import { basename, delimiter, dirname, extname, isAbsolute, join, posix, relative, resolve, sep, win32 } from "node:path";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
|
-
import {
|
|
8
|
-
import { createHash } from "node:crypto";
|
|
9
|
-
import { homedir, tmpdir } from "node:os";
|
|
7
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
8
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
10
9
|
import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
10
|
+
import { homedir, tmpdir } from "node:os";
|
|
11
11
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
12
12
|
import { connect } from "node:net";
|
|
13
13
|
import { execPath } from "node:process";
|
|
@@ -159,6 +159,7 @@ const VALUE_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
159
159
|
"scope",
|
|
160
160
|
"run-id",
|
|
161
161
|
"session-id",
|
|
162
|
+
"name",
|
|
162
163
|
"official-plugin",
|
|
163
164
|
"task",
|
|
164
165
|
"autonomy",
|
|
@@ -307,6 +308,14 @@ function positionalRange(command) {
|
|
|
307
308
|
min: 1,
|
|
308
309
|
max: 2
|
|
309
310
|
};
|
|
311
|
+
case "workflow create": return {
|
|
312
|
+
min: 1,
|
|
313
|
+
max: 2
|
|
314
|
+
};
|
|
315
|
+
case "workflow check": return {
|
|
316
|
+
min: 1,
|
|
317
|
+
max: 1
|
|
318
|
+
};
|
|
310
319
|
case "workflow show":
|
|
311
320
|
case "workflow inspect":
|
|
312
321
|
case "workflow pause":
|
|
@@ -398,6 +407,14 @@ function commandOptions(command) {
|
|
|
398
407
|
"trusted",
|
|
399
408
|
"compat-quickjs"
|
|
400
409
|
]);
|
|
410
|
+
case "workflow create": return /* @__PURE__ */ new Set([
|
|
411
|
+
...common,
|
|
412
|
+
"name",
|
|
413
|
+
"session-id",
|
|
414
|
+
"trusted",
|
|
415
|
+
"task"
|
|
416
|
+
]);
|
|
417
|
+
case "workflow check": return /* @__PURE__ */ new Set([...common, "trusted"]);
|
|
401
418
|
case "workflow resume": return /* @__PURE__ */ new Set([
|
|
402
419
|
...common,
|
|
403
420
|
"trusted",
|
|
@@ -441,7 +458,6 @@ function optionalChoiceOptions() {
|
|
|
441
458
|
const VERSION_PATTERN = /^0\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/u;
|
|
442
459
|
const EPOCH_PATTERN = /^[a-z][a-z0-9._:-]{0,63}$/u;
|
|
443
460
|
const PLUGIN_NAME_PATTERN = /^[a-z][a-z0-9._-]{1,63}$/u;
|
|
444
|
-
const SKILL_NAME_PATTERN = /^[a-z][a-z0-9-]{0,63}$/u;
|
|
445
461
|
const DIGEST_PATTERN = /^[0-9a-f]{64}$/u;
|
|
446
462
|
const SOURCE_MANIFEST_PATH = ".codex-plugin/plugin.json";
|
|
447
463
|
const PAYLOAD_MANIFEST_PATH = ".codex-plugin/payload.json";
|
|
@@ -600,7 +616,6 @@ function comparePathText(left, right) {
|
|
|
600
616
|
//#endregion
|
|
601
617
|
//#region packages/plugin/src/schemas.ts
|
|
602
618
|
const PluginNameSchema$1 = String$.pipe(pattern(PLUGIN_NAME_PATTERN));
|
|
603
|
-
const SkillNameSchema = String$.pipe(pattern(SKILL_NAME_PATTERN));
|
|
604
619
|
const VersionSchema$1 = String$.pipe(pattern(VERSION_PATTERN));
|
|
605
620
|
const SchemaEpochSchema = String$.pipe(pattern(EPOCH_PATTERN));
|
|
606
621
|
const DigestSchema$2 = String$.pipe(pattern(DIGEST_PATTERN));
|
|
@@ -613,9 +628,21 @@ const PathSchema = String$.pipe(filter((value) => {
|
|
|
613
628
|
}
|
|
614
629
|
}));
|
|
615
630
|
const DescriptionSchema = String$.pipe(filter((value) => value.length > 0 && value.length <= 300));
|
|
616
|
-
const
|
|
617
|
-
const
|
|
618
|
-
|
|
631
|
+
const SkillRootSchema = Literal("skills", "./skills", "skills/");
|
|
632
|
+
const AuthorSchema = Struct({
|
|
633
|
+
name: String$.pipe(minLength(1)),
|
|
634
|
+
email: optional(String$),
|
|
635
|
+
url: optional(String$)
|
|
636
|
+
});
|
|
637
|
+
const InterfaceSchema = Struct({
|
|
638
|
+
displayName: String$.pipe(minLength(1)),
|
|
639
|
+
shortDescription: String$.pipe(minLength(1)),
|
|
640
|
+
longDescription: String$.pipe(minLength(1)),
|
|
641
|
+
developerName: String$.pipe(minLength(1)),
|
|
642
|
+
category: String$.pipe(minLength(1)),
|
|
643
|
+
capabilities: Array$(String$.pipe(minLength(1))),
|
|
644
|
+
defaultPrompt: Array$(String$.pipe(minLength(1)))
|
|
645
|
+
});
|
|
619
646
|
const PonytailMetadataSchema = Struct({
|
|
620
647
|
name: Literal("ponytail"),
|
|
621
648
|
version: Literal("4.9.0"),
|
|
@@ -630,24 +657,27 @@ const PonytailMetadataSchema = Struct({
|
|
|
630
657
|
});
|
|
631
658
|
const SourceManifestSchema = Struct({
|
|
632
659
|
name: PluginNameSchema$1,
|
|
660
|
+
version: VersionSchema$1,
|
|
633
661
|
description: DescriptionSchema,
|
|
662
|
+
author: AuthorSchema,
|
|
663
|
+
homepage: optional(String$),
|
|
664
|
+
repository: optional(String$),
|
|
634
665
|
license: optional(String$),
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
rules: optional(CapabilityAssetPathsSchema),
|
|
639
|
-
compaction: optional(CapabilityAssetPathsSchema)
|
|
666
|
+
keywords: optional(Array$(String$.pipe(minLength(1)))),
|
|
667
|
+
skills: SkillRootSchema,
|
|
668
|
+
interface: InterfaceSchema
|
|
640
669
|
});
|
|
641
670
|
const GeneratedManifestSchema = Struct({
|
|
642
671
|
name: PluginNameSchema$1,
|
|
643
672
|
version: VersionSchema$1,
|
|
644
673
|
description: DescriptionSchema,
|
|
674
|
+
author: AuthorSchema,
|
|
675
|
+
homepage: optional(String$),
|
|
676
|
+
repository: optional(String$),
|
|
645
677
|
license: optional(String$),
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
rules: optional(CapabilityAssetPathsSchema),
|
|
650
|
-
compaction: optional(CapabilityAssetPathsSchema)
|
|
678
|
+
keywords: optional(Array$(String$.pipe(minLength(1)))),
|
|
679
|
+
skills: SkillRootSchema,
|
|
680
|
+
interface: InterfaceSchema
|
|
651
681
|
});
|
|
652
682
|
const PayloadFileSchema = Struct({
|
|
653
683
|
path: PathSchema,
|
|
@@ -705,6 +735,7 @@ async function readSourceManifest(root) {
|
|
|
705
735
|
const parsed = decodeSchema(SourceManifestSchema, input);
|
|
706
736
|
if (parsed === void 0) throw pluginError("manifest_invalid", "The source plugin manifest is invalid.", { summary: "Effect Schema rejected the source manifest." });
|
|
707
737
|
if (containsMcpDeclaration(input)) throw pluginError("manifest_invalid", "Plugin source manifests cannot declare external servers.");
|
|
738
|
+
if (typeof input === "object" && input !== null && !Array.isArray(input) && Object.keys(input).some((key) => !OFFICIAL_MANIFEST_KEYS.has(key))) throw pluginError("manifest_invalid", "The source plugin manifest contains unsupported fields.");
|
|
708
739
|
validateManifestDeclarations(parsed);
|
|
709
740
|
return parsed;
|
|
710
741
|
}
|
|
@@ -739,41 +770,37 @@ async function readPayloadManifest(root) {
|
|
|
739
770
|
return parsed;
|
|
740
771
|
}
|
|
741
772
|
function validateManifestDeclarations(manifest) {
|
|
742
|
-
|
|
743
|
-
const assets = manifest.assets ?? [];
|
|
744
|
-
const hooks = manifest.hooks ?? [];
|
|
745
|
-
const rules = manifest.rules ?? [];
|
|
746
|
-
const compaction = manifest.compaction ?? [];
|
|
747
|
-
const declared = [
|
|
748
|
-
...assets,
|
|
749
|
-
...hooks,
|
|
750
|
-
...rules,
|
|
751
|
-
...compaction
|
|
752
|
-
];
|
|
753
|
-
if (new Set(skills).size !== skills.length || new Set(declared).size !== declared.length) throw pluginError("manifest_invalid", "Manifest asset declarations must be unique.");
|
|
754
|
-
const seen = /* @__PURE__ */ new Set();
|
|
755
|
-
for (const asset of declared) {
|
|
756
|
-
const normalized = normalizeRelativePath(asset);
|
|
757
|
-
if (normalized === ".codex-plugin/plugin.json" || normalized === ".codex-plugin/payload.json") throw pluginError("manifest_invalid", "Generated metadata paths are reserved.", { path: normalized });
|
|
758
|
-
if (seen.has(normalized)) throw pluginError("manifest_invalid", "Manifest asset declarations must be canonical.", { path: normalized });
|
|
759
|
-
seen.add(normalized);
|
|
760
|
-
}
|
|
773
|
+
if (manifest.skills !== "skills" && manifest.skills !== "./skills" && manifest.skills !== "skills/") throw pluginError("manifest_invalid", "The plugin skills path must resolve to `skills`.");
|
|
761
774
|
}
|
|
762
|
-
function declaredSourcePaths(
|
|
775
|
+
function declaredSourcePaths(_manifest, candidates = []) {
|
|
763
776
|
const paths = /* @__PURE__ */ new Set([SOURCE_MANIFEST_PATH]);
|
|
764
|
-
for (const
|
|
765
|
-
|
|
766
|
-
paths.add(
|
|
767
|
-
|
|
768
|
-
}
|
|
769
|
-
for (const path of [
|
|
770
|
-
...manifest.assets ?? [],
|
|
771
|
-
...manifest.hooks ?? [],
|
|
772
|
-
...manifest.rules ?? [],
|
|
773
|
-
...manifest.compaction ?? []
|
|
774
|
-
]) paths.add(normalizeRelativePath(path));
|
|
777
|
+
for (const candidate of candidates) {
|
|
778
|
+
const normalized = normalizeRelativePath(candidate);
|
|
779
|
+
if (isPayloadAssetPath(normalized)) paths.add(normalized);
|
|
780
|
+
}
|
|
775
781
|
return paths;
|
|
776
782
|
}
|
|
783
|
+
const OFFICIAL_MANIFEST_KEYS = /* @__PURE__ */ new Set([
|
|
784
|
+
"name",
|
|
785
|
+
"version",
|
|
786
|
+
"description",
|
|
787
|
+
"author",
|
|
788
|
+
"homepage",
|
|
789
|
+
"repository",
|
|
790
|
+
"license",
|
|
791
|
+
"keywords",
|
|
792
|
+
"skills",
|
|
793
|
+
"interface"
|
|
794
|
+
]);
|
|
795
|
+
function isPayloadAssetPath(path) {
|
|
796
|
+
return [
|
|
797
|
+
"agents/",
|
|
798
|
+
"skills/",
|
|
799
|
+
"hooks/",
|
|
800
|
+
"rules/",
|
|
801
|
+
"compaction/"
|
|
802
|
+
].some((prefix) => path.startsWith(prefix));
|
|
803
|
+
}
|
|
777
804
|
function isUsableDirectoryText(value) {
|
|
778
805
|
return value.length > 0 && !value.includes("\0");
|
|
779
806
|
}
|
|
@@ -794,7 +821,7 @@ async function verifyPayload(input) {
|
|
|
794
821
|
const generatedManifest = await readGeneratedManifest(root);
|
|
795
822
|
if (generatedManifest.version !== payloadManifest.version) throw pluginError("payload_invalid", "Generated metadata versions do not match.");
|
|
796
823
|
if (payloadManifest.identity.epoch !== payloadManifest.schema_epoch) throw pluginError("payload_invalid", "Payload identity epoch does not match metadata.");
|
|
797
|
-
const declaredPaths = [...declaredSourcePaths(generatedManifest)].sort(comparePathText);
|
|
824
|
+
const declaredPaths = [...declaredSourcePaths(generatedManifest, payloadManifest.files.map((file) => file.path))].sort(comparePathText);
|
|
798
825
|
const manifestPaths = payloadManifest.files.map((file) => file.path);
|
|
799
826
|
if (declaredPaths.length !== manifestPaths.length || declaredPaths.some((path, index) => path !== manifestPaths[index])) throw pluginError("payload_invalid", "Generated metadata and the payload file manifest disagree.");
|
|
800
827
|
const expectedPaths = /* @__PURE__ */ new Set([...payloadManifest.files.map((file) => file.path), PAYLOAD_MANIFEST_PATH]);
|
|
@@ -814,7 +841,7 @@ async function verifyPayload(input) {
|
|
|
814
841
|
if (bytes.byteLength > 1048576 || totalSize > 8388608) throw pluginError("payload_invalid", "The payload exceeds the size limit.");
|
|
815
842
|
fileBytes.set(file.path, bytes);
|
|
816
843
|
}
|
|
817
|
-
if (
|
|
844
|
+
if (payloadManifest.files.some((file) => file.path === "skills/ponytail/SKILL.md")) await verifyPonytailMetadata(async (path) => {
|
|
818
845
|
const bytes = fileBytes.get(path);
|
|
819
846
|
if (bytes === void 0) throw pluginError("payload_invalid", "A Ponytail metadata input is missing.", { path });
|
|
820
847
|
return bytes;
|
|
@@ -896,11 +923,13 @@ async function validateSource(input = pluginSourceRoot) {
|
|
|
896
923
|
const walkedFiles = [];
|
|
897
924
|
await walkSource(root, "", walkedFiles);
|
|
898
925
|
const manifest = await readSourceManifest(root);
|
|
899
|
-
const declaredPaths = declaredSourcePaths(manifest);
|
|
926
|
+
const declaredPaths = declaredSourcePaths(manifest, walkedFiles);
|
|
900
927
|
const walkedSet = new Set(walkedFiles);
|
|
928
|
+
const skillDirectories = new Set(walkedFiles.map((path) => /^skills\/([^/]+)\//u.exec(path)?.[1]).filter((name) => name !== void 0));
|
|
929
|
+
for (const skill of skillDirectories) if (!walkedSet.has(`skills/${skill}/SKILL.md`)) throw pluginError("source_invalid", "A skill directory is missing SKILL.md.", { skill });
|
|
901
930
|
for (const declaredPath of declaredPaths) if (!walkedSet.has(declaredPath)) throw pluginError("source_invalid", "A manifest-declared asset is missing.", { path: declaredPath });
|
|
902
931
|
for (const walkedPath of walkedFiles) if (!declaredPaths.has(walkedPath)) throw pluginError("source_invalid", "The plugin source contains an undeclared file.", { path: walkedPath });
|
|
903
|
-
if (
|
|
932
|
+
if (walkedFiles.includes("skills/ponytail/SKILL.md")) await verifyPonytailMetadata((path) => readSourceFile(root, path), "source_invalid");
|
|
904
933
|
const files = [];
|
|
905
934
|
let totalSize = 0;
|
|
906
935
|
for (const path of [...walkedSet].sort()) {
|
|
@@ -958,14 +987,17 @@ function createGeneratedManifest(source, version) {
|
|
|
958
987
|
const manifest = {
|
|
959
988
|
name: source.name,
|
|
960
989
|
version,
|
|
961
|
-
description: source.description
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
990
|
+
description: source.description,
|
|
991
|
+
author: source.author,
|
|
992
|
+
skills: source.skills,
|
|
993
|
+
interface: source.interface
|
|
994
|
+
};
|
|
995
|
+
for (const key of [
|
|
996
|
+
"license",
|
|
997
|
+
"homepage",
|
|
998
|
+
"repository",
|
|
999
|
+
"keywords"
|
|
1000
|
+
]) if (source[key] !== void 0) manifest[key] = source[key];
|
|
969
1001
|
const parsed = decodeSchema(GeneratedManifestSchema, manifest);
|
|
970
1002
|
if (parsed === void 0) throw pluginError("manifest_invalid", "Generated plugin metadata is invalid.", { summary: "Effect Schema rejected the generated plugin metadata." });
|
|
971
1003
|
return parsed;
|
|
@@ -2220,6 +2252,9 @@ const SemanticAssignmentPacketSchema = Struct({
|
|
|
2220
2252
|
security: SecurityPolicySchema,
|
|
2221
2253
|
compatibility: CompatibilityPacketSchema,
|
|
2222
2254
|
skill_profile: Union(RoleSkillProfileSchema, Null),
|
|
2255
|
+
/** Runtime metadata supplied by the host; never hardcode release or platform values here. */
|
|
2256
|
+
canonical_version: optional(TextSchema),
|
|
2257
|
+
platform: optional(Literal("win32", "posix")),
|
|
2223
2258
|
capability_input: optional(JsonObjectSchema$2),
|
|
2224
2259
|
retained_context: optional(RetainedContextSchema)
|
|
2225
2260
|
});
|
|
@@ -2239,8 +2274,10 @@ function compileSpecialistAssignment(packet) {
|
|
|
2239
2274
|
`Assignment ID: ${packet.assignment.id}`,
|
|
2240
2275
|
`Objective: ${packet.assignment.objective}`,
|
|
2241
2276
|
`Role/task: ${packet.assignment.role_task.role}/${packet.assignment.role_task.task}`,
|
|
2277
|
+
...packet.canonical_version === void 0 ? [] : [`Canonical version: ${packet.canonical_version}`],
|
|
2242
2278
|
`Authority: ${packet.assignment.authority}`
|
|
2243
2279
|
];
|
|
2280
|
+
if (packet.platform === "win32") lines.push("Use C:/Program Files/Git/bin/bash.exe for every shell command.");
|
|
2244
2281
|
const retained = completeRetainedContext(packet.retained_context);
|
|
2245
2282
|
if (packet.skill_profile !== null && retained === void 0) {
|
|
2246
2283
|
lines.push(`Skill reference: ${packet.skill_profile.reference}`);
|
|
@@ -2256,7 +2293,7 @@ function compileSpecialistAssignment(packet) {
|
|
|
2256
2293
|
if (value !== void 0 && value.length > 0) lines.push(`${label}: ${value.join("; ")}`);
|
|
2257
2294
|
}
|
|
2258
2295
|
lines.push(`Outcome protocol: ${SPECIALIST_OUTCOME_VERSION}; terminal shapes: completed {protocol_version,route,evidence,status,summary}; blocked {protocol_version,route,evidence,status,reason,needs_root_decision}; partial {protocol_version,route,evidence,status,summary,completed,remaining,needs_root_decision}; failed {protocol_version,route,evidence,status,error}.`);
|
|
2259
|
-
lines.push("Boundary:
|
|
2296
|
+
lines.push("Boundary: Stay within the assigned scope and return material choices to Root.");
|
|
2260
2297
|
return lines.join("\n");
|
|
2261
2298
|
}
|
|
2262
2299
|
const ExecutionBackendSchema = Literal("app-server-v1-fallback", "app-server-v2", "host-capability");
|
|
@@ -5508,11 +5545,11 @@ function executeCodexOperation(context, definition, pending, active, input) {
|
|
|
5508
5545
|
},
|
|
5509
5546
|
input: {
|
|
5510
5547
|
name: "json",
|
|
5511
|
-
decode: (value) => value
|
|
5548
|
+
decode: (value) => asJsonValue(value, "operation input")
|
|
5512
5549
|
},
|
|
5513
5550
|
output: {
|
|
5514
5551
|
name: "json",
|
|
5515
|
-
decode: (value) => value
|
|
5552
|
+
decode: (value) => asJsonValue(value, "operation output")
|
|
5516
5553
|
},
|
|
5517
5554
|
metadata: { id: input.operationId },
|
|
5518
5555
|
route: input.route
|
|
@@ -5521,7 +5558,7 @@ function executeCodexOperation(context, definition, pending, active, input) {
|
|
|
5521
5558
|
if (codex === void 0) return fail(workflowFailure("execution", "The workflow host Codex AgentExecution capability is unavailable."));
|
|
5522
5559
|
return gen(function* () {
|
|
5523
5560
|
const route = yield* resolvePlanRoute(definition, input.route);
|
|
5524
|
-
const packet = yield* makeSemanticPacket(definition, pending, assignment, route);
|
|
5561
|
+
const packet = yield* makeSemanticPacket(context, definition, pending, assignment, route);
|
|
5525
5562
|
return (yield* validateSemanticOutcome(yield* codex.execute(packet).pipe(mapError$3((cause) => codexFailure(cause, assignment))), assignment, roleTaskForRoute(route))).outcome;
|
|
5526
5563
|
});
|
|
5527
5564
|
}
|
|
@@ -5537,7 +5574,7 @@ function executeCodexAssignment(context, definition, pending, active, agent, ass
|
|
|
5537
5574
|
} catch (cause) {
|
|
5538
5575
|
return yield* fail(workflowFailure(cause instanceof CostAccountingError ? cause.code : "estimate_unavailable", "The workflow assignment has no conservative pricing estimate.", { cause }));
|
|
5539
5576
|
}
|
|
5540
|
-
const packet = yield* makeSemanticPacket(definition, pending, assignment, routeDefinition);
|
|
5577
|
+
const packet = yield* makeSemanticPacket(context, definition, pending, assignment, routeDefinition);
|
|
5541
5578
|
const normalizedInput = normalizeSemanticAssignment(packet);
|
|
5542
5579
|
const authorityDigest = yield* tryPromise({
|
|
5543
5580
|
try: () => authorityScopeDigest(packet.assignment.authority, packet.assignment.scope),
|
|
@@ -5666,7 +5703,7 @@ function resolvePlanRoute(definition, route) {
|
|
|
5666
5703
|
const selected = lookupRoute(definition.identity.plan, route);
|
|
5667
5704
|
return selected.ok ? succeed$2(selected.value) : fail(workflowFailure("validation", "The assignment route is unavailable."));
|
|
5668
5705
|
}
|
|
5669
|
-
function makeSemanticPacket(definition, pending, assignment, route, retainedContext) {
|
|
5706
|
+
function makeSemanticPacket(context, definition, pending, assignment, route, retainedContext) {
|
|
5670
5707
|
return try_({
|
|
5671
5708
|
try: () => {
|
|
5672
5709
|
const payload = asJsonValue(assignment.payload, "workflow assignment payload");
|
|
@@ -5732,6 +5769,8 @@ function makeSemanticPacket(definition, pending, assignment, route, retainedCont
|
|
|
5732
5769
|
prefer_multi_agent_v2: false,
|
|
5733
5770
|
require_multi_agent_v2: false
|
|
5734
5771
|
},
|
|
5772
|
+
...context.canonicalVersion === void 0 ? {} : { canonical_version: context.canonicalVersion },
|
|
5773
|
+
platform: context.platform,
|
|
5735
5774
|
skill_profile: role.skill_profile,
|
|
5736
5775
|
...capability === void 0 ? {} : { capability_input: options },
|
|
5737
5776
|
...retainedContext === void 0 ? {} : { retained_context: retainedContext }
|
|
@@ -5819,7 +5858,7 @@ function roleTaskForRoute(route) {
|
|
|
5819
5858
|
function readFanOut(assignment) {
|
|
5820
5859
|
const payload = assignment.payload;
|
|
5821
5860
|
if (typeof payload === "object" && payload !== null && !Array.isArray(payload)) {
|
|
5822
|
-
const options = "options" in payload ? payload
|
|
5861
|
+
const options = "options" in payload ? payload["options"] : void 0;
|
|
5823
5862
|
if (typeof options === "object" && options !== null && !Array.isArray(options)) return optionInteger(jsonObject(options, "assignment options"), "fan_out", 1);
|
|
5824
5863
|
}
|
|
5825
5864
|
return 1;
|
|
@@ -6512,11 +6551,11 @@ async function handleOperation(context, definition, plan, active, operation) {
|
|
|
6512
6551
|
},
|
|
6513
6552
|
input: {
|
|
6514
6553
|
name: "json",
|
|
6515
|
-
decode: (value) => value
|
|
6554
|
+
decode: (value) => asJsonValue(value, "operation input")
|
|
6516
6555
|
},
|
|
6517
6556
|
output: {
|
|
6518
6557
|
name: "json",
|
|
6519
|
-
decode: (value) => value
|
|
6558
|
+
decode: (value) => asJsonValue(value, "operation output")
|
|
6520
6559
|
},
|
|
6521
6560
|
metadata: { id: operationId },
|
|
6522
6561
|
route
|
|
@@ -6981,6 +7020,8 @@ var WorkflowHost = class {
|
|
|
6981
7020
|
approvalPolicy: assertIdentifier(options.approvalPolicy ?? "never", "approval policy"),
|
|
6982
7021
|
sandboxPolicy: assertIdentifier(options.sandboxPolicy, "sandbox policy"),
|
|
6983
7022
|
codexCapabilityDigest: assertDigest(options.codexCapabilityDigest, "Codex capability digest"),
|
|
7023
|
+
canonicalVersion: options.canonicalVersion,
|
|
7024
|
+
platform: options.platform ?? "posix",
|
|
6984
7025
|
telemetry: options.telemetry,
|
|
6985
7026
|
refinementsEnabled: options.refinementsEnabled ?? false,
|
|
6986
7027
|
pending: /* @__PURE__ */ new Map(),
|
|
@@ -7143,7 +7184,7 @@ function resolveInstallerPaths(options = {}, environment = process.env) {
|
|
|
7143
7184
|
payloadRoot: marketplacePlugins,
|
|
7144
7185
|
stagingRoot: join(safeMarketplaceRoot, "plugins", ".holycodex-staging"),
|
|
7145
7186
|
runsRoot: join(stateRoot, "runs"),
|
|
7146
|
-
generatedWorkflowsRoot: join(
|
|
7187
|
+
generatedWorkflowsRoot: join(safeCodexHome, "workflows")
|
|
7147
7188
|
};
|
|
7148
7189
|
}
|
|
7149
7190
|
var PathBoundaryError = class extends Error {
|
|
@@ -7370,12 +7411,23 @@ var LockError = class extends Error {
|
|
|
7370
7411
|
//#endregion
|
|
7371
7412
|
//#region packages/cli/src/marketplace.ts
|
|
7372
7413
|
const MarketplaceSchema = JsonObjectSchema$3;
|
|
7373
|
-
const MarketplaceEntrySchema =
|
|
7414
|
+
const MarketplaceEntrySchema = declare((value) => {
|
|
7415
|
+
const parsed = decodeSchema$1(JsonObjectSchema$3, value);
|
|
7416
|
+
return parsed !== void 0 && typeof parsed["name"] === "string";
|
|
7417
|
+
});
|
|
7418
|
+
const MarketplaceNameSchema = Literal("holycodex");
|
|
7374
7419
|
const MANAGED_MARKETPLACE_OWNER = "holycodex";
|
|
7375
7420
|
const MANAGED_MARKETPLACE_CATEGORY = "Development";
|
|
7376
7421
|
const MANAGED_INSTALL_POLICY = "AVAILABLE";
|
|
7377
7422
|
const MANAGED_AUTH_POLICY = "ON_INSTALL";
|
|
7378
7423
|
async function readMarketplace(path) {
|
|
7424
|
+
return (await readMarketplaceInternal(path, false)).document;
|
|
7425
|
+
}
|
|
7426
|
+
/** Reads the official document and repairs only the previous HolyCodex shape in memory. */
|
|
7427
|
+
async function readMarketplaceForInstall(path) {
|
|
7428
|
+
return await readMarketplaceInternal(path, true);
|
|
7429
|
+
}
|
|
7430
|
+
async function readMarketplaceInternal(path, allowLegacyRepair) {
|
|
7379
7431
|
await assertNoSymlink(path).catch((error) => {
|
|
7380
7432
|
if (!isFsCode(error, "ENOENT")) throw error;
|
|
7381
7433
|
});
|
|
@@ -7384,18 +7436,88 @@ async function readMarketplace(path) {
|
|
|
7384
7436
|
document = await readJsonObject(path);
|
|
7385
7437
|
} catch (error) {
|
|
7386
7438
|
if (!isFsCode(error, "ENOENT")) throw error;
|
|
7387
|
-
return {
|
|
7439
|
+
return {
|
|
7440
|
+
document: emptyMarketplace(),
|
|
7441
|
+
repaired: false
|
|
7442
|
+
};
|
|
7388
7443
|
}
|
|
7389
7444
|
const parsed = decodeSchema$1(MarketplaceSchema, document);
|
|
7390
|
-
if (parsed
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7445
|
+
if (parsed !== void 0) {
|
|
7446
|
+
const official = parseOfficialMarketplace(parsed);
|
|
7447
|
+
if (official !== void 0) return {
|
|
7448
|
+
document: official,
|
|
7449
|
+
repaired: false
|
|
7450
|
+
};
|
|
7451
|
+
}
|
|
7452
|
+
if (allowLegacyRepair) {
|
|
7453
|
+
const repaired = repairLegacyMarketplace(document);
|
|
7454
|
+
if (repaired !== void 0) return {
|
|
7455
|
+
document: repaired,
|
|
7456
|
+
repaired: true
|
|
7457
|
+
};
|
|
7458
|
+
}
|
|
7459
|
+
throw new MarketplaceError("marketplace_invalid", "The marketplace file is not a valid Codex marketplace.");
|
|
7460
|
+
}
|
|
7461
|
+
function parseOfficialMarketplace(document) {
|
|
7462
|
+
if (decodeSchema$1(MarketplaceNameSchema, document["name"]) === void 0) return void 0;
|
|
7463
|
+
const rawPlugins = document["plugins"];
|
|
7464
|
+
if (!Array.isArray(rawPlugins)) return void 0;
|
|
7465
|
+
const plugins = [];
|
|
7466
|
+
for (const item of rawPlugins) {
|
|
7467
|
+
const plugin = decodeSchema$1(MarketplaceEntrySchema, item);
|
|
7468
|
+
if (plugin === void 0) return void 0;
|
|
7469
|
+
plugins.push(plugin);
|
|
7470
|
+
}
|
|
7471
|
+
return {
|
|
7472
|
+
...document,
|
|
7473
|
+
name: MANAGED_MARKETPLACE_OWNER,
|
|
7474
|
+
plugins
|
|
7475
|
+
};
|
|
7476
|
+
}
|
|
7477
|
+
function repairLegacyMarketplace(document) {
|
|
7478
|
+
const rawPlugins = document["plugins"];
|
|
7479
|
+
if (!Array.isArray(rawPlugins)) return void 0;
|
|
7480
|
+
const plugins = [];
|
|
7481
|
+
for (const item of rawPlugins) {
|
|
7482
|
+
if (!isJsonObject$1(item)) return void 0;
|
|
7483
|
+
if (isLegacyManagedEntry(item)) {
|
|
7484
|
+
const source = item["source"];
|
|
7485
|
+
if (typeof source !== "string" || source.length === 0) return void 0;
|
|
7486
|
+
plugins.push(repairLegacyEntry(item));
|
|
7487
|
+
} else plugins.push(item);
|
|
7488
|
+
}
|
|
7394
7489
|
return {
|
|
7395
|
-
...
|
|
7490
|
+
...document,
|
|
7491
|
+
name: MANAGED_MARKETPLACE_OWNER,
|
|
7492
|
+
interface: isJsonObject$1(document["interface"]) ? document["interface"] : { displayName: "HolyCodex" },
|
|
7396
7493
|
plugins
|
|
7397
7494
|
};
|
|
7398
7495
|
}
|
|
7496
|
+
function repairLegacyEntry(entry) {
|
|
7497
|
+
const source = entry["source"];
|
|
7498
|
+
return {
|
|
7499
|
+
name: MANAGED_MARKETPLACE_OWNER,
|
|
7500
|
+
source: {
|
|
7501
|
+
source: "local",
|
|
7502
|
+
path: typeof source === "string" ? source : ""
|
|
7503
|
+
},
|
|
7504
|
+
policy: {
|
|
7505
|
+
installation: MANAGED_INSTALL_POLICY,
|
|
7506
|
+
authentication: MANAGED_AUTH_POLICY
|
|
7507
|
+
},
|
|
7508
|
+
category: MANAGED_MARKETPLACE_CATEGORY
|
|
7509
|
+
};
|
|
7510
|
+
}
|
|
7511
|
+
function isLegacyManagedEntry(value) {
|
|
7512
|
+
return isJsonObject$1(value) && (value["name"] === "holycodex" || isJsonObject$1(value["owner"]) && value["owner"]["name"] === "holycodex");
|
|
7513
|
+
}
|
|
7514
|
+
function emptyMarketplace() {
|
|
7515
|
+
return {
|
|
7516
|
+
name: MANAGED_MARKETPLACE_OWNER,
|
|
7517
|
+
interface: { displayName: "HolyCodex" },
|
|
7518
|
+
plugins: []
|
|
7519
|
+
};
|
|
7520
|
+
}
|
|
7399
7521
|
async function writeMarketplace(path, document) {
|
|
7400
7522
|
await ensureOwnedDirectory(dirname(path));
|
|
7401
7523
|
await writeAtomicJson(path, document);
|
|
@@ -7403,21 +7525,15 @@ async function writeMarketplace(path, document) {
|
|
|
7403
7525
|
function managedMarketplaceEntry(record) {
|
|
7404
7526
|
return {
|
|
7405
7527
|
name: "holycodex",
|
|
7406
|
-
source:
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
install: MANAGED_INSTALL_POLICY,
|
|
7410
|
-
auth: MANAGED_AUTH_POLICY,
|
|
7411
|
-
owner: {
|
|
7412
|
-
name: MANAGED_MARKETPLACE_OWNER,
|
|
7413
|
-
schema: record.schema_epoch
|
|
7528
|
+
source: {
|
|
7529
|
+
source: "local",
|
|
7530
|
+
path: record.relative_path
|
|
7414
7531
|
},
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
} }
|
|
7532
|
+
policy: {
|
|
7533
|
+
installation: MANAGED_INSTALL_POLICY,
|
|
7534
|
+
authentication: MANAGED_AUTH_POLICY
|
|
7535
|
+
},
|
|
7536
|
+
category: MANAGED_MARKETPLACE_CATEGORY
|
|
7421
7537
|
};
|
|
7422
7538
|
}
|
|
7423
7539
|
function marketplaceWithManagedEntry(document, record) {
|
|
@@ -7454,12 +7570,8 @@ function pickManagedFields(entry) {
|
|
|
7454
7570
|
for (const key of [
|
|
7455
7571
|
"name",
|
|
7456
7572
|
"source",
|
|
7457
|
-
"
|
|
7458
|
-
"category"
|
|
7459
|
-
"install",
|
|
7460
|
-
"auth",
|
|
7461
|
-
"owner",
|
|
7462
|
-
"cache"
|
|
7573
|
+
"policy",
|
|
7574
|
+
"category"
|
|
7463
7575
|
]) {
|
|
7464
7576
|
const value = entry[key];
|
|
7465
7577
|
if (value !== void 0) result[key] = value;
|
|
@@ -8262,9 +8374,13 @@ async function installHolyCodex(request = {}, options = {}, environment = proces
|
|
|
8262
8374
|
try {
|
|
8263
8375
|
await writeAtomicJson(paths.activeRecord, asJsonValue$1(record));
|
|
8264
8376
|
await appendJournal(paths, runId, "active-written", { artifact_id: artifactId }, now);
|
|
8265
|
-
const
|
|
8377
|
+
const marketplace = await readMarketplaceForInstall(paths.marketplaceFile);
|
|
8378
|
+
const nextMarketplace = marketplaceWithManagedEntry(marketplace.document, record);
|
|
8266
8379
|
await writeMarketplace(paths.marketplaceFile, nextMarketplace);
|
|
8267
|
-
await appendJournal(paths, runId, "marketplace-written", {
|
|
8380
|
+
await appendJournal(paths, runId, "marketplace-written", {
|
|
8381
|
+
artifact_id: artifactId,
|
|
8382
|
+
legacy_repaired: marketplace.repaired ? 1 : 0
|
|
8383
|
+
}, now);
|
|
8268
8384
|
await verifyActivation(paths, record);
|
|
8269
8385
|
await appendJournal(paths, runId, "activation-verified", { artifact_id: artifactId }, now);
|
|
8270
8386
|
} catch (error) {
|
|
@@ -8758,7 +8874,7 @@ async function runManagedProcess(input, runtime = defaultManagedProcessRuntime)
|
|
|
8758
8874
|
if (validated.stdin === void 0) childStdin.end();
|
|
8759
8875
|
else childStdin.end(validated.stdin);
|
|
8760
8876
|
} catch (error) {
|
|
8761
|
-
finish(null, null, errorMessage
|
|
8877
|
+
finish(null, null, errorMessage(error), errorCode(error));
|
|
8762
8878
|
}
|
|
8763
8879
|
});
|
|
8764
8880
|
}
|
|
@@ -8847,7 +8963,7 @@ function processErrorResult(error) {
|
|
|
8847
8963
|
timedOut: false,
|
|
8848
8964
|
aborted: false,
|
|
8849
8965
|
outputTruncated: false,
|
|
8850
|
-
error: errorMessage
|
|
8966
|
+
error: errorMessage(error),
|
|
8851
8967
|
...errorCode(error) === void 0 ? {} : { errorCode: errorCode(error) }
|
|
8852
8968
|
};
|
|
8853
8969
|
}
|
|
@@ -8894,7 +9010,7 @@ function emptyOutput() {
|
|
|
8894
9010
|
function outputText(state) {
|
|
8895
9011
|
return state.truncated ? `${state.head}${TRUNCATED_MARKER}${state.tail}` : state.head;
|
|
8896
9012
|
}
|
|
8897
|
-
function errorMessage
|
|
9013
|
+
function errorMessage(error) {
|
|
8898
9014
|
return error instanceof Error ? error.message : String(error);
|
|
8899
9015
|
}
|
|
8900
9016
|
function errorCode(error) {
|
|
@@ -9378,7 +9494,7 @@ const GENERATED_WORKFLOW_MAX_SESSION_ID_BYTES = 96;
|
|
|
9378
9494
|
const GENERATED_WORKFLOW_MAX_NAME_BYTES = 64;
|
|
9379
9495
|
const SafeSegmentSchema = String$.pipe(pattern(/^[A-Za-z0-9][A-Za-z0-9._-]{0,95}$/u));
|
|
9380
9496
|
const SafeWorkflowNameSchema = String$.pipe(pattern(/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u));
|
|
9381
|
-
const ShortHashSchema = String$.pipe(pattern(/^[0-9a-f]{
|
|
9497
|
+
const ShortHashSchema = String$.pipe(pattern(/^[0-9a-f]{4}$/u));
|
|
9382
9498
|
const NativeWorkflowIdentitySchema = Struct({
|
|
9383
9499
|
source_sha256: DigestSchema$3,
|
|
9384
9500
|
ir_sha256: DigestSchema$3,
|
|
@@ -9432,46 +9548,55 @@ var GeneratedWorkflowStore = class {
|
|
|
9432
9548
|
await this.ensureOwnedDirectory(sessionDirectory);
|
|
9433
9549
|
await this.assertCaseSafeDirectory(sessionDirectory, name);
|
|
9434
9550
|
const sourceSha256 = sha256(bytes);
|
|
9435
|
-
const shortHash = await shortWorkflowHash(ownerSessionId, name, sourceSha256);
|
|
9436
|
-
const fileName = `${name}-${shortHash}.ts`;
|
|
9437
|
-
const sourcePath = join(sessionDirectory, fileName);
|
|
9438
|
-
const metadataPath = `${sourcePath}.metadata.json`;
|
|
9439
|
-
const existing = await this.readMetadataIfPresent(metadataPath);
|
|
9440
9551
|
const now = this.now();
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
const
|
|
9444
|
-
|
|
9552
|
+
for (let attempt = 0; attempt < 16; attempt += 1) {
|
|
9553
|
+
const shortHash = await shortWorkflowHash(ownerSessionId, name, sourceSha256, attempt);
|
|
9554
|
+
const fileName = `${name}-${shortHash}.ts`;
|
|
9555
|
+
const sourcePath = join(sessionDirectory, fileName);
|
|
9556
|
+
const metadataPath = `${sourcePath}.metadata.json`;
|
|
9557
|
+
const existing = await this.readMetadataIfPresent(metadataPath);
|
|
9558
|
+
if (existing !== void 0) {
|
|
9559
|
+
const existingBytes = await this.readOwnedBytes(sourcePath);
|
|
9560
|
+
if (sha256(existingBytes) !== sourceSha256) continue;
|
|
9561
|
+
if (existing.owner_session_id !== ownerSessionId || existing.safe_name !== name || existing.short_hash !== shortHash || existing.source_path !== sourcePath) throw new GeneratedWorkflowStoreError("collision", "The generated workflow name collides with different persisted metadata.");
|
|
9562
|
+
return {
|
|
9563
|
+
metadata: await this.writeMetadata({
|
|
9564
|
+
...existing,
|
|
9565
|
+
last_access_at: now.toISOString(),
|
|
9566
|
+
expires_at: new Date(now.getTime() + this.ttlMs).toISOString(),
|
|
9567
|
+
active: true
|
|
9568
|
+
}),
|
|
9569
|
+
source: new TextDecoder().decode(existingBytes)
|
|
9570
|
+
};
|
|
9571
|
+
}
|
|
9572
|
+
try {
|
|
9573
|
+
await this.readOwnedBytes(sourcePath);
|
|
9574
|
+
continue;
|
|
9575
|
+
} catch (error) {
|
|
9576
|
+
if (!isMissingPath(error)) throw error;
|
|
9577
|
+
}
|
|
9578
|
+
await this.writeAtomicBytes(sourcePath, bytes);
|
|
9579
|
+
const metadata = await this.writeMetadata({
|
|
9580
|
+
schema_epoch: GENERATED_WORKFLOW_SCHEMA_EPOCH,
|
|
9581
|
+
naming_version: GENERATED_WORKFLOW_NAMING_VERSION,
|
|
9582
|
+
owner_session_id: ownerSessionId,
|
|
9583
|
+
safe_name: name,
|
|
9584
|
+
short_hash: shortHash,
|
|
9585
|
+
source_sha256: sourceSha256,
|
|
9586
|
+
source_path: sourcePath,
|
|
9587
|
+
created_at: now.toISOString(),
|
|
9588
|
+
last_access_at: now.toISOString(),
|
|
9589
|
+
expires_at: new Date(now.getTime() + this.ttlMs).toISOString(),
|
|
9590
|
+
active: true
|
|
9591
|
+
});
|
|
9592
|
+
const verified = await this.readOwnedBytes(sourcePath);
|
|
9593
|
+
if (sha256(verified) !== sourceSha256) throw new GeneratedWorkflowStoreError("integrity_uncertain", "The generated workflow failed post-write digest verification.");
|
|
9445
9594
|
return {
|
|
9446
|
-
metadata
|
|
9447
|
-
|
|
9448
|
-
last_access_at: now.toISOString(),
|
|
9449
|
-
expires_at: new Date(now.getTime() + this.ttlMs).toISOString(),
|
|
9450
|
-
active: true
|
|
9451
|
-
}),
|
|
9452
|
-
source: new TextDecoder().decode(existingBytes)
|
|
9595
|
+
metadata,
|
|
9596
|
+
source: new TextDecoder().decode(verified)
|
|
9453
9597
|
};
|
|
9454
9598
|
}
|
|
9455
|
-
|
|
9456
|
-
const metadata = await this.writeMetadata({
|
|
9457
|
-
schema_epoch: GENERATED_WORKFLOW_SCHEMA_EPOCH,
|
|
9458
|
-
naming_version: GENERATED_WORKFLOW_NAMING_VERSION,
|
|
9459
|
-
owner_session_id: ownerSessionId,
|
|
9460
|
-
safe_name: name,
|
|
9461
|
-
short_hash: shortHash,
|
|
9462
|
-
source_sha256: sourceSha256,
|
|
9463
|
-
source_path: sourcePath,
|
|
9464
|
-
created_at: now.toISOString(),
|
|
9465
|
-
last_access_at: now.toISOString(),
|
|
9466
|
-
expires_at: new Date(now.getTime() + this.ttlMs).toISOString(),
|
|
9467
|
-
active: true
|
|
9468
|
-
});
|
|
9469
|
-
const verified = await this.readOwnedBytes(sourcePath);
|
|
9470
|
-
if (sha256(verified) !== sourceSha256) throw new GeneratedWorkflowStoreError("integrity_uncertain", "The generated workflow failed post-write digest verification.");
|
|
9471
|
-
return {
|
|
9472
|
-
metadata,
|
|
9473
|
-
source: new TextDecoder().decode(verified)
|
|
9474
|
-
};
|
|
9599
|
+
throw new GeneratedWorkflowStoreError("collision", "The generated workflow short hash collided with different source bytes.");
|
|
9475
9600
|
}
|
|
9476
9601
|
async read(sourcePath) {
|
|
9477
9602
|
const normalized = this.assertOwnedSourcePath(sourcePath);
|
|
@@ -9505,7 +9630,7 @@ var GeneratedWorkflowStore = class {
|
|
|
9505
9630
|
const directory = join(this.root, ownerSessionId);
|
|
9506
9631
|
await this.assertOwnedPath(directory, true);
|
|
9507
9632
|
const entries = await this.readOwnedDirectory(directory).catch((error) => {
|
|
9508
|
-
if (
|
|
9633
|
+
if (isMissingPath(error)) return [];
|
|
9509
9634
|
throw error;
|
|
9510
9635
|
});
|
|
9511
9636
|
for (const entry of entries) {
|
|
@@ -9532,7 +9657,7 @@ var GeneratedWorkflowStore = class {
|
|
|
9532
9657
|
await this.assertTree(directory);
|
|
9533
9658
|
await this.requireBoundary().removeOwnedDirectory(this.root, directory);
|
|
9534
9659
|
} catch (error) {
|
|
9535
|
-
if (
|
|
9660
|
+
if (isMissingPath(error)) return;
|
|
9536
9661
|
if (error instanceof GeneratedWorkflowStoreError) throw error;
|
|
9537
9662
|
throw new GeneratedWorkflowStoreError("storage_failure", "The generated workflow session could not be removed.", error);
|
|
9538
9663
|
}
|
|
@@ -9548,7 +9673,7 @@ var GeneratedWorkflowStore = class {
|
|
|
9548
9673
|
await this.assertOwnedPath(directory, false);
|
|
9549
9674
|
return true;
|
|
9550
9675
|
} catch (error) {
|
|
9551
|
-
if (
|
|
9676
|
+
if (isMissingPath(error)) return false;
|
|
9552
9677
|
throw error;
|
|
9553
9678
|
}
|
|
9554
9679
|
}
|
|
@@ -9587,7 +9712,7 @@ var GeneratedWorkflowStore = class {
|
|
|
9587
9712
|
if (!preview) await this.requireBoundary().removeOwnedDirectory(this.root, directory);
|
|
9588
9713
|
removed.push(directory);
|
|
9589
9714
|
} catch (error) {
|
|
9590
|
-
if (
|
|
9715
|
+
if (isMissingPath(error)) continue;
|
|
9591
9716
|
uncertain.push(directory);
|
|
9592
9717
|
}
|
|
9593
9718
|
}
|
|
@@ -9644,7 +9769,7 @@ var GeneratedWorkflowStore = class {
|
|
|
9644
9769
|
try {
|
|
9645
9770
|
return await this.readMetadata(path);
|
|
9646
9771
|
} catch (error) {
|
|
9647
|
-
if (
|
|
9772
|
+
if (isMissingPath(error)) return void 0;
|
|
9648
9773
|
throw error;
|
|
9649
9774
|
}
|
|
9650
9775
|
}
|
|
@@ -9654,7 +9779,7 @@ var GeneratedWorkflowStore = class {
|
|
|
9654
9779
|
try {
|
|
9655
9780
|
parsed = JSON.parse(new TextDecoder().decode(await this.requireBoundary().readOwnedFile(this.root, path)));
|
|
9656
9781
|
} catch (error) {
|
|
9657
|
-
if (
|
|
9782
|
+
if (isMissingPath(error)) throw error;
|
|
9658
9783
|
throw new GeneratedWorkflowStoreError("malformed_metadata", "Generated workflow metadata is not valid JSON.", error);
|
|
9659
9784
|
}
|
|
9660
9785
|
const metadata = decodeSchema$1(GeneratedWorkflowMetadataSchema, parsed);
|
|
@@ -9720,16 +9845,15 @@ function assertSafeWorkflowName(value) {
|
|
|
9720
9845
|
if (parsed === void 0 || value === "." || value === "..") throw new GeneratedWorkflowStoreError("invalid_name", "The generated workflow name is not filesystem-safe.");
|
|
9721
9846
|
return parsed;
|
|
9722
9847
|
}
|
|
9723
|
-
async function shortWorkflowHash(sessionId, safeName, sourceSha256) {
|
|
9848
|
+
async function shortWorkflowHash(sessionId, safeName, sourceSha256, attempt = 0) {
|
|
9724
9849
|
assertSafeSessionId(sessionId);
|
|
9725
9850
|
assertSafeWorkflowName(safeName);
|
|
9726
9851
|
if (decodeSchema$1(DigestSchema$3, sourceSha256) === void 0) throw new GeneratedWorkflowStoreError("invalid_input", "The source digest is invalid.");
|
|
9727
|
-
|
|
9728
|
-
|
|
9729
|
-
|
|
9730
|
-
|
|
9731
|
-
|
|
9732
|
-
}))])).slice(0, 16);
|
|
9852
|
+
if (!Number.isSafeInteger(attempt) || attempt < 0 || attempt > 15) throw new GeneratedWorkflowStoreError("invalid_input", "The workflow hash attempt is invalid.");
|
|
9853
|
+
return randomBytes(2).toString("hex");
|
|
9854
|
+
}
|
|
9855
|
+
function isMissingPath(error) {
|
|
9856
|
+
return isFsCode(error, "ENOENT") || isFsCode(error, "not_found");
|
|
9733
9857
|
}
|
|
9734
9858
|
function sha256(bytes) {
|
|
9735
9859
|
return createHash("sha256").update(bytes).digest("hex");
|
|
@@ -9997,7 +10121,7 @@ async function cleanupHolyCodexUnlocked(scope, options, input, paths) {
|
|
|
9997
10121
|
const target = join(paths.generatedWorkflowsRoot, sessionId);
|
|
9998
10122
|
if (!pathWithin(paths.generatedWorkflowsRoot, target)) throw new CleanupError("cleanup_failed", "The workflow session path escaped the owned root.");
|
|
9999
10123
|
try {
|
|
10000
|
-
const store = new GeneratedWorkflowStore(paths.
|
|
10124
|
+
const store = new GeneratedWorkflowStore(paths.codexHome, {
|
|
10001
10125
|
now: () => now,
|
|
10002
10126
|
...options.generatedWorkflowBoundary === void 0 ? {} : { boundary: options.generatedWorkflowBoundary }
|
|
10003
10127
|
});
|
|
@@ -10063,10 +10187,7 @@ async function cleanupHolyCodexUnlocked(scope, options, input, paths) {
|
|
|
10063
10187
|
reasons
|
|
10064
10188
|
};
|
|
10065
10189
|
}
|
|
10066
|
-
const marketplace = await readMarketplace(paths.marketplaceFile)
|
|
10067
|
-
if (isFsCode(error, "ENOENT")) return { plugins: [] };
|
|
10068
|
-
throw error;
|
|
10069
|
-
});
|
|
10190
|
+
const marketplace = await readMarketplace(paths.marketplaceFile);
|
|
10070
10191
|
const managed = active ? findManagedEntry(marketplace) : void 0;
|
|
10071
10192
|
if (active && managed && managedEntryMatches(managed, active)) {
|
|
10072
10193
|
const next = {
|
|
@@ -10096,7 +10217,7 @@ async function cleanupHolyCodexUnlocked(scope, options, input, paths) {
|
|
|
10096
10217
|
}
|
|
10097
10218
|
async function removeExpiredGeneratedWorkflows(paths, preview, removed, preserved, now, cutoff, boundary) {
|
|
10098
10219
|
try {
|
|
10099
|
-
const result = await new GeneratedWorkflowStore(paths.
|
|
10220
|
+
const result = await new GeneratedWorkflowStore(paths.codexHome, {
|
|
10100
10221
|
now: () => now,
|
|
10101
10222
|
ttlMs: Math.max(1, now.getTime() - cutoff),
|
|
10102
10223
|
...boundary === void 0 ? {} : { boundary }
|
|
@@ -13517,9 +13638,8 @@ var GitBashError = class extends Error {
|
|
|
13517
13638
|
//#endregion
|
|
13518
13639
|
//#region packages/git-bash/src/git-bash-resolver.ts
|
|
13519
13640
|
const GIT_BASH_ENV_KEY = "HOLYCODEX_GIT_BASH_PATH";
|
|
13520
|
-
const
|
|
13521
|
-
const
|
|
13522
|
-
const DEFAULT_INSTALL_HINT = `Git Bash required. Install: winget install --id Git.Git -e --source winget\nCustom path: set ${GIT_BASH_ENV_KEY}=C:\\path\\to\\bash.exe`;
|
|
13641
|
+
const GIT_BASH_EXECUTABLE_PATH = "C:\\Program Files\\Git\\bin\\bash.exe";
|
|
13642
|
+
const DEFAULT_INSTALL_HINT = `Git Bash is required at ${GIT_BASH_EXECUTABLE_PATH}. Install: winget install --id Git.Git -e --source winget`;
|
|
13523
13643
|
const EnvironmentShapeSchema$1 = Record({
|
|
13524
13644
|
key: String$,
|
|
13525
13645
|
value: Unknown
|
|
@@ -13537,54 +13657,22 @@ function resolveGitBash(input) {
|
|
|
13537
13657
|
if (configured !== void 0 && configured.length > 0) {
|
|
13538
13658
|
checkedPaths.push(configured);
|
|
13539
13659
|
const normalized = normalizeGitBashExecutablePath(configured, input.platform);
|
|
13540
|
-
if (normalized !== null && available(input, configured, normalized)) return found(normalized, "env", checkedPaths);
|
|
13660
|
+
if (normalized !== null && isRequiredGitBashExecutablePath(normalized, input.platform) && available(input, configured, normalized)) return found(normalized, "env", checkedPaths);
|
|
13541
13661
|
return missing(checkedPaths, `${GIT_BASH_ENV_KEY} is configured but invalid or unavailable; refusing fallback.\n${DEFAULT_INSTALL_HINT}`);
|
|
13542
13662
|
}
|
|
13543
|
-
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
}, {
|
|
13547
|
-
path: PROGRAM_FILES_X86_GIT_BASH,
|
|
13548
|
-
source: "program-files-x86"
|
|
13549
|
-
}];
|
|
13550
|
-
for (const candidate of fixedCandidates) {
|
|
13551
|
-
checkedPaths.push(candidate.path);
|
|
13552
|
-
const normalized = normalizeGitBashExecutablePath(candidate.path, input.platform);
|
|
13553
|
-
if (normalized !== null && available(input, candidate.path, normalized)) return found(normalized, candidate.source, checkedPaths);
|
|
13554
|
-
}
|
|
13555
|
-
let pathCandidates;
|
|
13556
|
-
try {
|
|
13557
|
-
pathCandidates = validateWhereOutput(input.where("bash"));
|
|
13558
|
-
} catch (error) {
|
|
13559
|
-
return missing(checkedPaths, `${DEFAULT_INSTALL_HINT}\nPATH lookup failed: ${errorMessage(error)}`);
|
|
13560
|
-
}
|
|
13561
|
-
const seen = /* @__PURE__ */ new Set();
|
|
13562
|
-
for (const raw of pathCandidates) {
|
|
13563
|
-
const candidate = raw.trim();
|
|
13564
|
-
if (candidate.length === 0) continue;
|
|
13565
|
-
checkedPaths.push(candidate);
|
|
13566
|
-
const normalized = normalizeGitBashExecutablePath(candidate, input.platform);
|
|
13567
|
-
if (normalized === null) continue;
|
|
13568
|
-
const key = normalized.toLowerCase();
|
|
13569
|
-
if (seen.has(key)) continue;
|
|
13570
|
-
seen.add(key);
|
|
13571
|
-
if (available(input, candidate, normalized)) return found(normalized, "path", checkedPaths);
|
|
13572
|
-
}
|
|
13663
|
+
checkedPaths.push(GIT_BASH_EXECUTABLE_PATH);
|
|
13664
|
+
const normalized = normalizeGitBashExecutablePath(GIT_BASH_EXECUTABLE_PATH, input.platform);
|
|
13665
|
+
if (normalized !== null && available(input, "C:\\Program Files\\Git\\bin\\bash.exe", normalized)) return found(normalized, "program-files", checkedPaths);
|
|
13573
13666
|
return missing(checkedPaths);
|
|
13574
13667
|
}
|
|
13575
13668
|
/** Resolves Git Bash using the current process and injectable platform seams. */
|
|
13576
13669
|
function resolveGitBashForCurrentProcess(input = {}) {
|
|
13577
|
-
const platform = input.platform ?? process.platform;
|
|
13578
|
-
const environment = input.env ?? process.env;
|
|
13579
13670
|
return resolveGitBash({
|
|
13580
|
-
platform,
|
|
13581
|
-
env:
|
|
13671
|
+
platform: input.platform ?? process.platform,
|
|
13672
|
+
env: input.env ?? process.env,
|
|
13582
13673
|
exists: input.exists ?? defaultExists,
|
|
13583
13674
|
inspect: input.inspect ?? (input.exists === void 0 ? defaultInspect : (path) => safeExists(input.exists, path) ? "file" : "missing"),
|
|
13584
|
-
where: input.where ?? ((
|
|
13585
|
-
if (platform !== "win32") return [];
|
|
13586
|
-
return whereGitBash(command, environment);
|
|
13587
|
-
})
|
|
13675
|
+
where: input.where ?? (() => [])
|
|
13588
13676
|
});
|
|
13589
13677
|
}
|
|
13590
13678
|
/** Normalizes and validates an explicit Git Bash executable path without resolving links. */
|
|
@@ -13600,6 +13688,11 @@ function normalizeGitBashExecutablePath(value, platform) {
|
|
|
13600
13688
|
if (platform === "win32" && isRejectedWindowsAlias(normalized)) return null;
|
|
13601
13689
|
return normalized;
|
|
13602
13690
|
}
|
|
13691
|
+
function isRequiredGitBashExecutablePath(path, platform) {
|
|
13692
|
+
const normalized = normalizeGitBashExecutablePath(path, platform);
|
|
13693
|
+
if (normalized === null) return false;
|
|
13694
|
+
return platform !== "win32" || normalized.toLowerCase() === "C:\\Program Files\\Git\\bin\\bash.exe".toLowerCase();
|
|
13695
|
+
}
|
|
13603
13696
|
/** Checks a candidate without following symbolic links or reparse aliases. */
|
|
13604
13697
|
function isSafeGitBashExecutablePath(path) {
|
|
13605
13698
|
try {
|
|
@@ -13623,11 +13716,6 @@ function validateResolverInput(input) {
|
|
|
13623
13716
|
}
|
|
13624
13717
|
return Object.freeze(environment);
|
|
13625
13718
|
}
|
|
13626
|
-
function validateWhereOutput(value) {
|
|
13627
|
-
const decoded = decodeUnknownEither(Array$(String$), { onExcessProperty: "error" })(value);
|
|
13628
|
-
if (isLeft(decoded)) throw new GitBashError("unavailable", "The Windows PATH lookup returned invalid candidates.", {}, { cause: decoded.left });
|
|
13629
|
-
return decoded.right;
|
|
13630
|
-
}
|
|
13631
13719
|
function available(input, raw, normalized) {
|
|
13632
13720
|
if ((input.inspect === void 0 ? "file" : safeInspect(input.inspect, normalized)) !== "file") return false;
|
|
13633
13721
|
return safeExists(input.exists, normalized) || raw !== normalized && safeExists(input.exists, raw);
|
|
@@ -13652,32 +13740,6 @@ function defaultExists(path) {
|
|
|
13652
13740
|
function defaultInspect(path) {
|
|
13653
13741
|
return isSafeGitBashExecutablePath(path) ? "file" : "missing";
|
|
13654
13742
|
}
|
|
13655
|
-
function whereGitBash(command, environment) {
|
|
13656
|
-
try {
|
|
13657
|
-
const output = execFileSync("where.exe", [command], {
|
|
13658
|
-
encoding: "utf8",
|
|
13659
|
-
windowsHide: true,
|
|
13660
|
-
env: whereEnvironment(environment)
|
|
13661
|
-
});
|
|
13662
|
-
return String(output).split(/\r?\n/u).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
13663
|
-
} catch {
|
|
13664
|
-
return [];
|
|
13665
|
-
}
|
|
13666
|
-
}
|
|
13667
|
-
function whereEnvironment(input) {
|
|
13668
|
-
const entries = Object.entries(input);
|
|
13669
|
-
const exactPath = entries.find(([key, value]) => key === "PATH" && value !== void 0);
|
|
13670
|
-
const fallbackPath = [...entries].reverse().find(([key, value]) => key.toLowerCase() === "path" && value !== void 0);
|
|
13671
|
-
const pathEntry = exactPath ?? fallbackPath;
|
|
13672
|
-
const environment = {};
|
|
13673
|
-
for (const [key, value] of entries) {
|
|
13674
|
-
const normalizedKey = key.toLowerCase();
|
|
13675
|
-
if (normalizedKey === "path" || normalizedKey === "original_path" || value === void 0) continue;
|
|
13676
|
-
environment[key] = value;
|
|
13677
|
-
}
|
|
13678
|
-
if (pathEntry !== void 0) environment["PATH"] = pathEntry[1];
|
|
13679
|
-
return environment;
|
|
13680
|
-
}
|
|
13681
13743
|
function isRejectedWindowsAlias(path) {
|
|
13682
13744
|
const normalized = path.toLowerCase().replaceAll("/", "\\");
|
|
13683
13745
|
return normalized.includes("\\windows\\system32\\") || normalized.split("\\").includes("windowsapps");
|
|
@@ -13697,9 +13759,6 @@ function missing(checkedPaths, installHint = DEFAULT_INSTALL_HINT) {
|
|
|
13697
13759
|
installHint
|
|
13698
13760
|
});
|
|
13699
13761
|
}
|
|
13700
|
-
function errorMessage(error) {
|
|
13701
|
-
return error instanceof Error ? error.message : String(error);
|
|
13702
|
-
}
|
|
13703
13762
|
//#endregion
|
|
13704
13763
|
//#region packages/git-bash/src/runner.ts
|
|
13705
13764
|
const DEFAULT_MAX_OUTPUT_CHARS = 262144;
|
|
@@ -13721,6 +13780,7 @@ async function runGitBashCommand(input) {
|
|
|
13721
13780
|
const validated = validateRunInput(input);
|
|
13722
13781
|
const normalizedBashPath = normalizeGitBashExecutablePath(validated.bashPath, platform);
|
|
13723
13782
|
if (normalizedBashPath === null) throw new GitBashError("invalid_input", "Git Bash executable path must be absolute, traversal-free, and name bash.");
|
|
13783
|
+
if (!isRequiredGitBashExecutablePath(normalizedBashPath, platform)) throw new GitBashError("invalid_input", "Windows Git Bash must be C:/Program Files/Git/bin/bash.exe.");
|
|
13724
13784
|
const safeExecutable = validated.isSafeExecutable ?? isSafeGitBashExecutablePath;
|
|
13725
13785
|
let executableIsSafe = false;
|
|
13726
13786
|
try {
|
|
@@ -13815,12 +13875,37 @@ function isAbortSignal(value) {
|
|
|
13815
13875
|
//#region packages/cli/src/workflow.ts
|
|
13816
13876
|
const MAX_WORKFLOW_SOURCE_BYTES = 1048576;
|
|
13817
13877
|
async function executeWorkflowCommand(parsed, context) {
|
|
13818
|
-
const service = context.workflowService ?? await createDefaultWorkflowService(context, parsed);
|
|
13878
|
+
const service = parsed.command === "workflow create" || parsed.command === "workflow check" ? context.workflowService ?? {} : context.workflowService ?? await createDefaultWorkflowService(context, parsed);
|
|
13819
13879
|
switch (parsed.command) {
|
|
13880
|
+
case "workflow create": {
|
|
13881
|
+
const source = await readWorkflowSource(parsed.positionals[0] ?? "", parsed.positionals[1], parsed, context);
|
|
13882
|
+
(await loadNativeWorkflowSource({ source: source.source })).dispose();
|
|
13883
|
+
const sessionId = optionString$1(parsed, "session-id") ?? context.workflowSessionId;
|
|
13884
|
+
const name = optionString$1(parsed, "name") ?? context.workflowName;
|
|
13885
|
+
const materialized = await materializeGeneratedWorkflow(source, {
|
|
13886
|
+
...context,
|
|
13887
|
+
...sessionId === void 0 ? {} : { workflowSessionId: sessionId },
|
|
13888
|
+
...name === void 0 ? {} : { workflowName: name }
|
|
13889
|
+
});
|
|
13890
|
+
await materialized.store.setSessionActivity(materialized.sessionId, false);
|
|
13891
|
+
return asJsonValue$1((await materialized.store.read(materialized.source.path ?? "")).metadata);
|
|
13892
|
+
}
|
|
13893
|
+
case "workflow check": {
|
|
13894
|
+
const source = await readWorkflowSource(parsed.positionals[0] ?? "", void 0, parsed, context);
|
|
13895
|
+
const workflow = await loadNativeWorkflow(source);
|
|
13896
|
+
try {
|
|
13897
|
+
return asJsonValue$1({
|
|
13898
|
+
valid: true,
|
|
13899
|
+
execution_mode: "native",
|
|
13900
|
+
source_path: source.path
|
|
13901
|
+
});
|
|
13902
|
+
} finally {
|
|
13903
|
+
workflow.dispose();
|
|
13904
|
+
}
|
|
13905
|
+
}
|
|
13820
13906
|
case "workflow run": {
|
|
13821
13907
|
let workflow = await readWorkflowSource(parsed.positionals[0] ?? "", parsed.positionals[1], parsed, context);
|
|
13822
|
-
const
|
|
13823
|
-
const nativeRequested = context.workflowService === void 0 && !compatibility;
|
|
13908
|
+
const nativeRequested = context.workflowService === void 0;
|
|
13824
13909
|
const generatedStore = context.workflowService === void 0 && workflow.path === null ? await materializeGeneratedWorkflow(workflow, context) : void 0;
|
|
13825
13910
|
if (generatedStore !== void 0) workflow = generatedStore.source;
|
|
13826
13911
|
let nativeWorkflow;
|
|
@@ -13848,8 +13933,7 @@ async function executeWorkflowCommand(parsed, context) {
|
|
|
13848
13933
|
source: workflow.source,
|
|
13849
13934
|
args: workflow.args,
|
|
13850
13935
|
...generatedStore === void 0 || workflow.path === null ? {} : { sourcePath: workflow.path },
|
|
13851
|
-
...nativeWorkflow === void 0 ? {} : { workflow: nativeWorkflow }
|
|
13852
|
-
...compatibility ? { compatibility: true } : {}
|
|
13936
|
+
...nativeWorkflow === void 0 ? {} : { workflow: nativeWorkflow }
|
|
13853
13937
|
}));
|
|
13854
13938
|
} finally {
|
|
13855
13939
|
nativeWorkflow?.dispose();
|
|
@@ -13863,8 +13947,7 @@ async function executeWorkflowCommand(parsed, context) {
|
|
|
13863
13947
|
const runId = requiredPosition(parsed, 0, "run id");
|
|
13864
13948
|
let workflow = await readWorkflowSource(requiredPosition(parsed, 1, "workflow source"), parsed.positionals[2], parsed, context);
|
|
13865
13949
|
await assertResumeInputIdentity(service, runId, workflow);
|
|
13866
|
-
const
|
|
13867
|
-
const nativeRequested = context.workflowService === void 0 && !compatibility;
|
|
13950
|
+
const nativeRequested = context.workflowService === void 0;
|
|
13868
13951
|
const generatedStore = context.workflowService === void 0 && workflow.path === null ? await materializeGeneratedWorkflow(workflow, context) : void 0;
|
|
13869
13952
|
if (generatedStore !== void 0) workflow = generatedStore.source;
|
|
13870
13953
|
let nativeWorkflow;
|
|
@@ -13876,8 +13959,7 @@ async function executeWorkflowCommand(parsed, context) {
|
|
|
13876
13959
|
source: workflow.source,
|
|
13877
13960
|
args: workflow.args,
|
|
13878
13961
|
...generatedStore === void 0 || workflow.path === null ? {} : { sourcePath: workflow.path },
|
|
13879
|
-
...nativeWorkflow === void 0 ? {} : { workflow: nativeWorkflow }
|
|
13880
|
-
...compatibility ? { compatibility: true } : {}
|
|
13962
|
+
...nativeWorkflow === void 0 ? {} : { workflow: nativeWorkflow }
|
|
13881
13963
|
}));
|
|
13882
13964
|
} finally {
|
|
13883
13965
|
nativeWorkflow?.dispose();
|
|
@@ -13890,8 +13972,7 @@ async function executeWorkflowCommand(parsed, context) {
|
|
|
13890
13972
|
return asJsonValue$1(await requireCapability(service.continuation, "continuation")({
|
|
13891
13973
|
runId,
|
|
13892
13974
|
source: workflow.source,
|
|
13893
|
-
args: workflow.args
|
|
13894
|
-
...parsed.options["compat-quickjs"] === true ? { compatibility: true } : {}
|
|
13975
|
+
args: workflow.args
|
|
13895
13976
|
}));
|
|
13896
13977
|
}
|
|
13897
13978
|
case "workflow goal": return asJsonValue$1(await requireCapability(service.goal, "goal")(requiredPosition(parsed, 0, "run id"), requiredPosition(parsed, 1, "goal summary")));
|
|
@@ -13936,7 +14017,7 @@ async function readWorkflowSource(reference, argumentText, parsed, context) {
|
|
|
13936
14017
|
}
|
|
13937
14018
|
if (reference.length === 0 || extname(reference) !== ".ts") throw new WorkflowCommandError("invalid_argument", "Workflow source must be a TypeScript file or stdin.");
|
|
13938
14019
|
const path = resolve(context.cwd ?? process.cwd(), reference);
|
|
13939
|
-
const generatedStore = new GeneratedWorkflowStore(resolveWorkflowInstallerPaths(context.installer, context.env).
|
|
14020
|
+
const generatedStore = new GeneratedWorkflowStore(resolveWorkflowInstallerPaths(context.installer, context.env).codexHome, {
|
|
13940
14021
|
...context.now === void 0 ? {} : { now: context.now },
|
|
13941
14022
|
...context.generatedWorkflowBoundary === void 0 ? {} : { boundary: context.generatedWorkflowBoundary }
|
|
13942
14023
|
});
|
|
@@ -13966,7 +14047,7 @@ async function readWorkflowSource(reference, argumentText, parsed, context) {
|
|
|
13966
14047
|
}
|
|
13967
14048
|
/** Load a file-backed native workflow through the bounded runtime source boundary. */
|
|
13968
14049
|
async function loadNativeWorkflow(source) {
|
|
13969
|
-
if (source.path === null) throw new WorkflowCommandError("invalid_argument", "
|
|
14050
|
+
if (source.path === null) throw new WorkflowCommandError("invalid_argument", "Workflows require a trusted TypeScript file; use workflow create for generated sources.");
|
|
13970
14051
|
try {
|
|
13971
14052
|
return await loadNativeWorkflowSource({ source: source.source });
|
|
13972
14053
|
} catch (error) {
|
|
@@ -13987,7 +14068,7 @@ function defaultObjective(path, reference) {
|
|
|
13987
14068
|
async function materializeGeneratedWorkflow(source, context) {
|
|
13988
14069
|
const sessionId = context.workflowSessionId;
|
|
13989
14070
|
if (sessionId === void 0) throw new WorkflowCommandError("invalid_argument", "Generated workflow storage requires an explicit caller session identity.");
|
|
13990
|
-
const store = new GeneratedWorkflowStore(resolveWorkflowInstallerPaths(context.installer, context.env).
|
|
14071
|
+
const store = new GeneratedWorkflowStore(resolveWorkflowInstallerPaths(context.installer, context.env).codexHome, {
|
|
13991
14072
|
...context.now === void 0 ? {} : { now: context.now },
|
|
13992
14073
|
...context.generatedWorkflowBoundary === void 0 ? {} : { boundary: context.generatedWorkflowBoundary }
|
|
13993
14074
|
});
|
|
@@ -14080,7 +14161,9 @@ async function createDefaultWorkflowService(context, parsed) {
|
|
|
14080
14161
|
maxCalls: planDefinition.value.budget.maxCalls,
|
|
14081
14162
|
costMax: planDefinition.value.budget.costMax
|
|
14082
14163
|
},
|
|
14083
|
-
refinementsEnabled: true
|
|
14164
|
+
refinementsEnabled: true,
|
|
14165
|
+
canonicalVersion: await readCanonicalVersion(),
|
|
14166
|
+
platform: process.platform === "win32" ? "win32" : "posix"
|
|
14084
14167
|
});
|
|
14085
14168
|
return {
|
|
14086
14169
|
create: async (input) => await host.create({
|
|
@@ -14111,22 +14194,28 @@ async function createDefaultWorkflowService(context, parsed) {
|
|
|
14111
14194
|
stop: async (runId) => await host.stop(runId),
|
|
14112
14195
|
stopAgent: async (runId, callId) => await host.stopAgent(runId, callId),
|
|
14113
14196
|
save: async (scope, name, source) => await saveWorkflow(stateRoot, scope, name, source, cwd, context.now ?? (() => /* @__PURE__ */ new Date())),
|
|
14114
|
-
invoke: async (scope, name, args,
|
|
14197
|
+
invoke: async (scope, name, args, _compatibilityAlias = false) => {
|
|
14115
14198
|
const saved = await readSavedWorkflow(stateRoot, scope, name, cwd);
|
|
14116
|
-
|
|
14117
|
-
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14122
|
-
|
|
14123
|
-
|
|
14124
|
-
|
|
14125
|
-
|
|
14126
|
-
|
|
14127
|
-
|
|
14128
|
-
|
|
14129
|
-
|
|
14199
|
+
const workflow = await loadNativeWorkflowSource({ source: saved.source });
|
|
14200
|
+
try {
|
|
14201
|
+
const created = await host.create({
|
|
14202
|
+
source: saved.source,
|
|
14203
|
+
args,
|
|
14204
|
+
objective: `workflow:${saved.name}`,
|
|
14205
|
+
plan,
|
|
14206
|
+
serviceTier,
|
|
14207
|
+
expectedConcurrency: maxSubagents,
|
|
14208
|
+
workflow
|
|
14209
|
+
});
|
|
14210
|
+
return asJsonValue$1(await host.run({
|
|
14211
|
+
runId: created.run_id,
|
|
14212
|
+
source: saved.source,
|
|
14213
|
+
args,
|
|
14214
|
+
workflow
|
|
14215
|
+
}));
|
|
14216
|
+
} finally {
|
|
14217
|
+
workflow.dispose();
|
|
14218
|
+
}
|
|
14130
14219
|
},
|
|
14131
14220
|
refinements: {
|
|
14132
14221
|
list: async () => await listRefinements(stateRoot),
|
|
@@ -14145,10 +14234,7 @@ async function createDefaultWorkflowService(context, parsed) {
|
|
|
14145
14234
|
};
|
|
14146
14235
|
}
|
|
14147
14236
|
function resolveWorkflowInstallerPaths(installer, environment) {
|
|
14148
|
-
return resolveInstallerPaths(
|
|
14149
|
-
codexHome: installer?.paths?.codexHome ?? environment?.["CODEX_HOME"] ?? resolve(process.cwd(), ".codex"),
|
|
14150
|
-
marketplaceRoot: installer?.paths?.marketplaceRoot ?? environment?.["HOLYCODEX_MARKETPLACE_ROOT"] ?? resolve(process.cwd(), ".marketplace")
|
|
14151
|
-
} }, environment);
|
|
14237
|
+
return resolveInstallerPaths(installer, environment);
|
|
14152
14238
|
}
|
|
14153
14239
|
async function invokeWorkflowCapability(capability, options, context) {
|
|
14154
14240
|
if (decodeSchema$1(CapabilityNameSchema, capability) === void 0) throw new WorkflowCommandError("invalid_argument", "The capability name is invalid.");
|
|
@@ -14809,10 +14895,9 @@ Options:
|
|
|
14809
14895
|
--json Emit one validated JSON envelope.
|
|
14810
14896
|
--no-tui Disable prompts and interactive UI behavior.
|
|
14811
14897
|
|
|
14812
|
-
Workflow execution
|
|
14813
|
-
trusted TypeScript file must export a default workflow.wait(...) value.
|
|
14814
|
-
|
|
14815
|
-
stdin requires that flag and an explicit --task objective.
|
|
14898
|
+
Workflow execution uses one capability-denied QuickJS TypeScript evaluator. A
|
|
14899
|
+
trusted TypeScript file must export a default workflow.wait(...) value. Use
|
|
14900
|
+
workflow create for generated sources; stdin requires an explicit --task objective.
|
|
14816
14901
|
|
|
14817
14902
|
Optional Work, Web, Security, Computer Use, LSP, LSP setup, and Git Bash
|
|
14818
14903
|
providers are independently capability-gated. Missing providers fail closed;
|
|
@@ -14822,6 +14907,8 @@ const WORKFLOW_HELP = `Workflow commands
|
|
|
14822
14907
|
|
|
14823
14908
|
Usage:
|
|
14824
14909
|
holycodex workflow run <file.ts|-> [args.json] [options]
|
|
14910
|
+
holycodex workflow create <file.ts|-> [args.json] [--name <name>] [--session-id <id>]
|
|
14911
|
+
holycodex workflow check <file.ts> [options]
|
|
14825
14912
|
holycodex workflow list [options]
|
|
14826
14913
|
holycodex workflow show <run-id> [options]
|
|
14827
14914
|
holycodex workflow inspect <run-id> [--follow] [options]
|
|
@@ -14841,12 +14928,12 @@ Options:
|
|
|
14841
14928
|
--autonomy <mode> Select manual, assisted, or autonomous execution.
|
|
14842
14929
|
--max-subagents <n> Bound specialist concurrency.
|
|
14843
14930
|
--trusted Assert the caller has established project trust.
|
|
14844
|
-
--compat-quickjs
|
|
14845
|
-
--task <objective> Required
|
|
14931
|
+
--compat-quickjs Deprecated one-release alias; the same evaluator is used.
|
|
14932
|
+
--task <objective> Required when workflow source is read from stdin.
|
|
14846
14933
|
--json, --no-tui Select machine/non-interactive output behavior.
|
|
14847
14934
|
|
|
14848
|
-
|
|
14849
|
-
|
|
14935
|
+
Workflow files must export a default workflow.wait(...) value. workflow check
|
|
14936
|
+
performs type, import, schema, and security validation without host effects.
|
|
14850
14937
|
`;
|
|
14851
14938
|
const INSTALL_HELP = `Install HolyCodex into the owned scope.
|
|
14852
14939
|
|
|
@@ -14883,6 +14970,8 @@ function helpText(topic) {
|
|
|
14883
14970
|
case "version": return VERSION_HELP;
|
|
14884
14971
|
case "workflow":
|
|
14885
14972
|
case "workflow run":
|
|
14973
|
+
case "workflow create":
|
|
14974
|
+
case "workflow check":
|
|
14886
14975
|
case "workflow list":
|
|
14887
14976
|
case "workflow show":
|
|
14888
14977
|
case "workflow inspect":
|
|
@@ -15263,14 +15352,68 @@ function isJsonObject(value) {
|
|
|
15263
15352
|
}
|
|
15264
15353
|
function emitProgress(context, json, message) {
|
|
15265
15354
|
if (json || parsedVerbose(context) === false) return;
|
|
15266
|
-
context.io?.writeStderr?.(`${message
|
|
15355
|
+
context.io?.writeStderr?.(`${renderProgress(message, {
|
|
15356
|
+
stderrIsTTY: context.io?.stderrIsTTY,
|
|
15357
|
+
env: context.env
|
|
15358
|
+
})}\n`);
|
|
15267
15359
|
}
|
|
15268
15360
|
function parsedVerbose(context) {
|
|
15269
15361
|
return context.io?.stderrIsTTY === true || context.io?.stderrIsTTY === void 0;
|
|
15270
15362
|
}
|
|
15271
|
-
function renderHuman(result) {
|
|
15272
|
-
|
|
15273
|
-
|
|
15363
|
+
function renderHuman(result, options = {}) {
|
|
15364
|
+
const color = colorEnabled(options);
|
|
15365
|
+
if (result.envelope.ok) return `${paint("✔", "green", color)} ${result.envelope.command}\n${renderData(result.envelope.data, color)}`;
|
|
15366
|
+
const error = result.envelope.error;
|
|
15367
|
+
const hint = actionableHint(error.code, result.envelope.command);
|
|
15368
|
+
return [
|
|
15369
|
+
`${paint("✖", "red", color)} ${result.envelope.command}`,
|
|
15370
|
+
` ${paint(error.code, "red", color)}: ${error.message}`,
|
|
15371
|
+
...renderDetails(error.details, color),
|
|
15372
|
+
...hint === void 0 ? [] : [` hint: ${hint}`],
|
|
15373
|
+
""
|
|
15374
|
+
].join("\n");
|
|
15375
|
+
}
|
|
15376
|
+
function renderProgress(message, options = {}) {
|
|
15377
|
+
return `${paint("•", "cyan", colorEnabled({
|
|
15378
|
+
...options,
|
|
15379
|
+
stream: "stderr"
|
|
15380
|
+
}))} ${message}`;
|
|
15381
|
+
}
|
|
15382
|
+
function renderData(data, color) {
|
|
15383
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) return ` ${paint(formatValue(data), "dim", color)}\n`;
|
|
15384
|
+
const entries = Object.entries(data);
|
|
15385
|
+
if (entries.length === 0) return "";
|
|
15386
|
+
const width = Math.max(...entries.map(([key]) => key.length));
|
|
15387
|
+
return `${entries.map(([key, value]) => ` ${key.padEnd(width)}: ${formatValue(value)}`).join("\n")}\n`;
|
|
15388
|
+
}
|
|
15389
|
+
function renderDetails(details, color) {
|
|
15390
|
+
return Object.entries(details).map(([key, value]) => ` ${key}: ${paint(formatValue(value), "dim", color)}`);
|
|
15391
|
+
}
|
|
15392
|
+
function formatValue(value) {
|
|
15393
|
+
if (typeof value === "string") return value;
|
|
15394
|
+
if (value === null || typeof value === "number" || typeof value === "boolean") return String(value);
|
|
15395
|
+
return JSON.stringify(value);
|
|
15396
|
+
}
|
|
15397
|
+
function actionableHint(code, command) {
|
|
15398
|
+
if (code === "invalid_argument" || code === "unknown_command") return `holycodex ${command.split(" ")[0] ?? "help"} --help`;
|
|
15399
|
+
if (code === "non_tty_confirmation_required") return "rerun with --yes or use an interactive terminal";
|
|
15400
|
+
if (code === "capability_denied") return "run `holycodex doctor` to inspect capability availability";
|
|
15401
|
+
}
|
|
15402
|
+
function colorEnabled(options) {
|
|
15403
|
+
const env = options.env ?? {};
|
|
15404
|
+
if (env["NO_COLOR"] !== void 0 || env["TERM"] === "dumb") return false;
|
|
15405
|
+
if (env["FORCE_COLOR"] !== void 0 && env["FORCE_COLOR"] !== "0") return true;
|
|
15406
|
+
if (env["CI"] !== void 0 && env["CI"] !== "false") return false;
|
|
15407
|
+
return (options.stream === "stderr" ? options.stderrIsTTY : options.stdoutIsTTY) === true;
|
|
15408
|
+
}
|
|
15409
|
+
function paint(value, color, enabled) {
|
|
15410
|
+
if (!enabled) return value;
|
|
15411
|
+
return `\u001b[${{
|
|
15412
|
+
red: "31",
|
|
15413
|
+
green: "32",
|
|
15414
|
+
cyan: "36",
|
|
15415
|
+
dim: "2"
|
|
15416
|
+
}[color]}m${value}\u001b[0m`;
|
|
15274
15417
|
}
|
|
15275
15418
|
var CliCommandError = class extends Error {
|
|
15276
15419
|
code;
|
|
@@ -15305,8 +15448,18 @@ async function runBinary(argv = Bun.argv.slice(2), binaryIo = processIo()) {
|
|
|
15305
15448
|
if (helpRequested(argv) && !jsonRequested(argv)) context.io?.writeStdout?.(helpText(helpTopic(argv)));
|
|
15306
15449
|
else if (argv[0] === "help" && !jsonRequested(argv)) context.io?.writeStdout?.(helpText(helpTopic(argv)));
|
|
15307
15450
|
else if (jsonRequested(argv)) context.io?.writeStdout?.(`${JSON.stringify(result.envelope)}\n`);
|
|
15308
|
-
else if (result.envelope.ok) context.io?.writeStdout?.(renderHuman(result
|
|
15309
|
-
|
|
15451
|
+
else if (result.envelope.ok) context.io?.writeStdout?.(renderHuman(result, {
|
|
15452
|
+
stdoutIsTTY: context.io?.stdoutIsTTY,
|
|
15453
|
+
stderrIsTTY: context.io?.stderrIsTTY,
|
|
15454
|
+
env: context.env,
|
|
15455
|
+
stream: "stdout"
|
|
15456
|
+
}));
|
|
15457
|
+
else context.io?.writeStderr?.(renderHuman(result, {
|
|
15458
|
+
stdoutIsTTY: context.io?.stderrIsTTY,
|
|
15459
|
+
stderrIsTTY: context.io?.stderrIsTTY,
|
|
15460
|
+
env: context.env,
|
|
15461
|
+
stream: "stderr"
|
|
15462
|
+
}));
|
|
15310
15463
|
return result.exitCode;
|
|
15311
15464
|
}
|
|
15312
15465
|
function processIo() {
|
|
@@ -15331,4 +15484,4 @@ async function* stdinChunks() {
|
|
|
15331
15484
|
if (tail.length > 0) yield tail;
|
|
15332
15485
|
}
|
|
15333
15486
|
//#endregion
|
|
15334
|
-
export {
|
|
15487
|
+
export { writeMarketplace as $, InstallerError as A, RefinementStoreError as B, GENERATED_WORKFLOW_NAMING_VERSION as C, assertSafeSessionId as D, GeneratedWorkflowStoreError as E, MIGRATED_STATE_NAME as F, readCanonicalBaseVersion as G, CodexOfficialPluginManager as H, MIGRATION_RECORD_NAME as I, MarketplaceError as J, readCanonicalVersion as K, inspectLegacyState as L, readActiveInstallRecord as M, verifyActivation as N, assertSafeWorkflowName as O, LEGACY_SCHEMA_EPOCH as P, readMarketplaceForInstall as Q, migrateLegacyState as R, GENERATED_WORKFLOW_MAX_SOURCE_BYTES as S, GeneratedWorkflowStore as T, OfficialPluginManagerError as U, WorkflowStoreError as V, publicManifestPath as W, managedMarketplaceEntry as X, managedEntryMatches as Y, readMarketplace as Z, cleanupHolyCodex as _, runCli as a, pathWithin as at, GENERATED_WORKFLOW_MAX_NAME_BYTES as b, helpTopic as c, parseArgv as ct, executeWorkflowCommand as d, InstallRecordSchema as dt, LockError as et, invokeWorkflowCapability as f, CleanupError as g, readWorkflowSource as h, renderProgress as i, assertRootText as it, installHolyCodex as j, shortWorkflowHash as k, WorkflowCommandError as l, CapabilityInstallStateSchema as lt, optionalArgs as m, executeCommand as n, PathBoundaryError as nt, helpRequested as o, resolveInstallerPaths as ot, loadNativeWorkflow as p, updateCanonicalVersion as q, renderHuman as r, STATE_SCHEMA as rt, helpText as s, ArgumentError as st, runBinary as t, acquireInstallLock as tt, createDefaultWorkflowService as u, CapabilityStateRecordSchema as ut, doctorHolyCodex as v, GENERATED_WORKFLOW_SCHEMA_EPOCH as w, GENERATED_WORKFLOW_MAX_SESSION_ID_BYTES as x, GENERATED_WORKFLOW_DEFAULT_TTL_MS as y, readMigratedInstallerSelections as z };
|