@okrlinkhub/agent-factory 2.0.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -0
- package/dist/client/index.d.ts +11 -7
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +6 -1
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/component.d.ts +5 -2
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/identity.d.ts +6 -6
- package/dist/component/pushing.d.ts +40 -40
- package/dist/component/queue.d.ts +93 -90
- package/dist/component/queue.d.ts.map +1 -1
- package/dist/component/queue.js +71 -47
- package/dist/component/queue.js.map +1 -1
- package/dist/component/scheduler.d.ts +23 -23
- package/dist/component/schema.d.ts +53 -37
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +5 -1
- package/dist/component/schema.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +7 -1
- package/src/component/_generated/component.ts +1 -2
- package/src/component/queue.ts +104 -49
- package/src/component/schema.ts +7 -1
package/dist/component/queue.js
CHANGED
|
@@ -138,7 +138,6 @@ const globalSkillManifestItemValidator = v.object({
|
|
|
138
138
|
version: v.string(),
|
|
139
139
|
moduleFormat: globalSkillModuleFormatValidator,
|
|
140
140
|
entryPoint: v.string(),
|
|
141
|
-
sourceJs: v.string(),
|
|
142
141
|
sha256: v.string(),
|
|
143
142
|
skillDirName: v.string(),
|
|
144
143
|
files: v.array(globalSkillManifestFileValidator),
|
|
@@ -587,7 +586,7 @@ export const deployGlobalSkill = mutation({
|
|
|
587
586
|
displayName: v.optional(v.string()),
|
|
588
587
|
description: v.optional(v.string()),
|
|
589
588
|
version: v.string(),
|
|
590
|
-
|
|
589
|
+
files: v.array(globalSkillManifestFileValidator),
|
|
591
590
|
entryPoint: v.optional(v.string()),
|
|
592
591
|
moduleFormat: v.optional(globalSkillModuleFormatValidator),
|
|
593
592
|
releaseChannel: v.optional(globalSkillReleaseChannelValidator),
|
|
@@ -611,23 +610,17 @@ export const deployGlobalSkill = mutation({
|
|
|
611
610
|
const releaseChannel = args.releaseChannel ?? "stable";
|
|
612
611
|
const moduleFormat = args.moduleFormat ?? "esm";
|
|
613
612
|
const actor = args.actor?.trim() || "system";
|
|
614
|
-
const
|
|
613
|
+
const files = await normalizeGlobalSkillBundleFiles(args.files, moduleFormat);
|
|
615
614
|
if (!/^[a-z0-9][a-z0-9-_]{1,127}$/.test(slug)) {
|
|
616
615
|
throw new Error("Invalid skill slug. Use lowercase letters, numbers, '-' and '_'.");
|
|
617
616
|
}
|
|
618
617
|
if (!/^\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?$/.test(version)) {
|
|
619
618
|
throw new Error("Invalid skill version. Use semantic versioning format.");
|
|
620
619
|
}
|
|
621
|
-
if (sourceJs.length < 16) {
|
|
622
|
-
throw new Error("Skill source is too short.");
|
|
623
|
-
}
|
|
624
|
-
if (sourceJs.length > 200_000) {
|
|
625
|
-
throw new Error("Skill source too large (max 200KB).");
|
|
626
|
-
}
|
|
627
620
|
if (!entryPoint) {
|
|
628
621
|
throw new Error("entryPoint is required.");
|
|
629
622
|
}
|
|
630
|
-
const sha256 = await
|
|
623
|
+
const sha256 = await computeGlobalSkillBundleSha256(files);
|
|
631
624
|
const existingSkill = await ctx.db
|
|
632
625
|
.query("globalSkills")
|
|
633
626
|
.withIndex("by_slug", (q) => q.eq("slug", slug))
|
|
@@ -663,14 +656,16 @@ export const deployGlobalSkill = mutation({
|
|
|
663
656
|
version,
|
|
664
657
|
moduleFormat,
|
|
665
658
|
entryPoint,
|
|
666
|
-
|
|
659
|
+
files,
|
|
667
660
|
sha256,
|
|
668
661
|
createdBy: actor,
|
|
669
662
|
createdAt: nowMs,
|
|
670
663
|
});
|
|
671
664
|
}
|
|
672
|
-
else if (existingVersion.sha256 !== sha256
|
|
673
|
-
|
|
665
|
+
else if (existingVersion.sha256 !== sha256 ||
|
|
666
|
+
existingVersion.moduleFormat !== moduleFormat ||
|
|
667
|
+
existingVersion.entryPoint !== entryPoint) {
|
|
668
|
+
throw new Error(`Skill ${slug}@${version} already exists with a different bundle.`);
|
|
674
669
|
}
|
|
675
670
|
const activeReleases = await ctx.db
|
|
676
671
|
.query("globalSkillReleases")
|
|
@@ -805,7 +800,7 @@ export const getWorkerGlobalSkillsManifest = query({
|
|
|
805
800
|
version: version.version,
|
|
806
801
|
moduleFormat: version.moduleFormat,
|
|
807
802
|
entryPoint: version.entryPoint,
|
|
808
|
-
|
|
803
|
+
files: version.files,
|
|
809
804
|
sha256: version.sha256,
|
|
810
805
|
});
|
|
811
806
|
manifestSkills.push({
|
|
@@ -813,7 +808,6 @@ export const getWorkerGlobalSkillsManifest = query({
|
|
|
813
808
|
version: version.version,
|
|
814
809
|
moduleFormat: version.moduleFormat,
|
|
815
810
|
entryPoint: version.entryPoint,
|
|
816
|
-
sourceJs: version.sourceJs,
|
|
817
811
|
sha256: version.sha256,
|
|
818
812
|
skillDirName: materializedSkill.skillDirName,
|
|
819
813
|
files: materializedSkill.files,
|
|
@@ -825,7 +819,11 @@ export const getWorkerGlobalSkillsManifest = query({
|
|
|
825
819
|
return a.version.localeCompare(b.version);
|
|
826
820
|
});
|
|
827
821
|
const fingerprintSeed = manifestSkills
|
|
828
|
-
.map((row) => `${row.slug}@${row.version}:${row.sha256}
|
|
822
|
+
.map((row) => `${row.slug}@${row.version}:${row.sha256}:${row.files
|
|
823
|
+
.filter((file) => file.path !== ".af-global-skill.json")
|
|
824
|
+
.map((file) => `${file.path}:${file.sha256}`)
|
|
825
|
+
.sort()
|
|
826
|
+
.join(",")}`)
|
|
829
827
|
.join("|");
|
|
830
828
|
const manifestVersion = await computeSha256Hex(fingerprintSeed || "empty");
|
|
831
829
|
return {
|
|
@@ -2632,26 +2630,11 @@ function inferMimeTypeFromFilePath(filePath) {
|
|
|
2632
2630
|
}
|
|
2633
2631
|
async function buildGlobalSkillMaterialization(skill) {
|
|
2634
2632
|
const skillDirName = normalizeGlobalSkillDirName(skill.slug);
|
|
2635
|
-
const
|
|
2636
|
-
const
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
`description: Global skill ${skill.slug}@${skill.version} provisioned by agent-factory.`,
|
|
2641
|
-
"---",
|
|
2642
|
-
"",
|
|
2643
|
-
"# Global Skill",
|
|
2644
|
-
"",
|
|
2645
|
-
"This skill is generated automatically from agent-factory globalSkills.",
|
|
2646
|
-
"",
|
|
2647
|
-
`- slug: ${skill.slug}`,
|
|
2648
|
-
`- version: ${skill.version}`,
|
|
2649
|
-
`- entryPoint: ${skill.entryPoint}`,
|
|
2650
|
-
`- moduleFormat: ${skill.moduleFormat}`,
|
|
2651
|
-
"",
|
|
2652
|
-
"Do not edit manually.",
|
|
2653
|
-
"",
|
|
2654
|
-
].join("\n");
|
|
2633
|
+
const bundleFiles = await normalizeGlobalSkillBundleFiles(skill.files, skill.moduleFormat);
|
|
2634
|
+
const bundleSha256 = await computeGlobalSkillBundleSha256(bundleFiles);
|
|
2635
|
+
if (bundleSha256 !== skill.sha256) {
|
|
2636
|
+
throw new Error(`Global skill bundle checksum mismatch for ${skill.slug}@${skill.version}.`);
|
|
2637
|
+
}
|
|
2655
2638
|
const markerJson = `${JSON.stringify({
|
|
2656
2639
|
slug: skill.slug,
|
|
2657
2640
|
version: skill.version,
|
|
@@ -2659,19 +2642,9 @@ async function buildGlobalSkillMaterialization(skill) {
|
|
|
2659
2642
|
managedBy: "agent-factory",
|
|
2660
2643
|
entryPoint: skill.entryPoint,
|
|
2661
2644
|
moduleFormat: skill.moduleFormat,
|
|
2662
|
-
generatedAt: Date.now(),
|
|
2663
2645
|
}, null, 2)}\n`;
|
|
2664
2646
|
const files = [
|
|
2665
|
-
|
|
2666
|
-
path: "SKILL.md",
|
|
2667
|
-
content: `${skillMd}\n`,
|
|
2668
|
-
sha256: await computeSha256Hex(`${skillMd}\n`),
|
|
2669
|
-
},
|
|
2670
|
-
{
|
|
2671
|
-
path: scriptRelativePath,
|
|
2672
|
-
content: `${skill.sourceJs.trimEnd()}\n`,
|
|
2673
|
-
sha256: await computeSha256Hex(`${skill.sourceJs.trimEnd()}\n`),
|
|
2674
|
-
},
|
|
2647
|
+
...bundleFiles,
|
|
2675
2648
|
{
|
|
2676
2649
|
path: ".af-global-skill.json",
|
|
2677
2650
|
content: markerJson,
|
|
@@ -2680,10 +2653,61 @@ async function buildGlobalSkillMaterialization(skill) {
|
|
|
2680
2653
|
];
|
|
2681
2654
|
return { skillDirName, files };
|
|
2682
2655
|
}
|
|
2656
|
+
async function normalizeGlobalSkillBundleFiles(rawFiles, moduleFormat) {
|
|
2657
|
+
if (!Array.isArray(rawFiles) || rawFiles.length === 0) {
|
|
2658
|
+
throw new Error("Global skill bundle must contain at least one file.");
|
|
2659
|
+
}
|
|
2660
|
+
const byPath = new Map();
|
|
2661
|
+
let totalBytes = 0;
|
|
2662
|
+
for (const rawFile of rawFiles) {
|
|
2663
|
+
const path = normalizeRelativePath(rawFile.path);
|
|
2664
|
+
if (path === ".af-global-skill.json") {
|
|
2665
|
+
throw new Error("Bundle files must not include .af-global-skill.json.");
|
|
2666
|
+
}
|
|
2667
|
+
if (byPath.has(path)) {
|
|
2668
|
+
throw new Error(`Duplicate bundle file path: ${path}`);
|
|
2669
|
+
}
|
|
2670
|
+
const content = typeof rawFile.content === "string" ? rawFile.content : "";
|
|
2671
|
+
totalBytes += new TextEncoder().encode(content).length;
|
|
2672
|
+
if (totalBytes > 200_000) {
|
|
2673
|
+
throw new Error("Global skill bundle too large (max 200KB).");
|
|
2674
|
+
}
|
|
2675
|
+
const sha256 = typeof rawFile.sha256 === "string" ? rawFile.sha256.trim() : "";
|
|
2676
|
+
if (!sha256) {
|
|
2677
|
+
throw new Error(`Missing bundle checksum for ${path}.`);
|
|
2678
|
+
}
|
|
2679
|
+
const computedSha = await computeSha256Hex(content);
|
|
2680
|
+
if (computedSha !== sha256) {
|
|
2681
|
+
throw new Error(`Global skill checksum mismatch for ${path}.`);
|
|
2682
|
+
}
|
|
2683
|
+
byPath.set(path, { path, content, sha256 });
|
|
2684
|
+
}
|
|
2685
|
+
const entryScriptPath = `scripts/index.${moduleFormat === "cjs" ? "cjs" : "mjs"}`;
|
|
2686
|
+
if (!byPath.has("SKILL.md")) {
|
|
2687
|
+
throw new Error("Global skill bundle must include SKILL.md.");
|
|
2688
|
+
}
|
|
2689
|
+
if (!byPath.has(entryScriptPath)) {
|
|
2690
|
+
throw new Error(`Global skill bundle must include ${entryScriptPath}.`);
|
|
2691
|
+
}
|
|
2692
|
+
return [...byPath.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
2693
|
+
}
|
|
2694
|
+
async function computeGlobalSkillBundleSha256(files) {
|
|
2695
|
+
const fingerprint = files
|
|
2696
|
+
.map((file) => `${file.path}\n${file.sha256}\n${file.content}`)
|
|
2697
|
+
.join("\n---\n");
|
|
2698
|
+
return await computeSha256Hex(fingerprint);
|
|
2699
|
+
}
|
|
2683
2700
|
function normalizeGlobalSkillDirName(slug) {
|
|
2684
2701
|
const normalized = slug.trim().toLowerCase().replace(/[^a-z0-9-_]/g, "-");
|
|
2685
2702
|
return normalized.length > 0 ? normalized : "unnamed-skill";
|
|
2686
2703
|
}
|
|
2704
|
+
function normalizeRelativePath(value) {
|
|
2705
|
+
const normalized = String(value || "").replaceAll("\\", "/").replace(/^\/+/, "");
|
|
2706
|
+
if (!normalized || normalized === "." || normalized.includes("../")) {
|
|
2707
|
+
throw new Error(`invalid_relative_path:${value}`);
|
|
2708
|
+
}
|
|
2709
|
+
return normalized;
|
|
2710
|
+
}
|
|
2687
2711
|
function getBridgeSecretRefsForProfile(agentKey, bridgeConfig) {
|
|
2688
2712
|
if (!bridgeConfig?.enabled) {
|
|
2689
2713
|
return [];
|