@jini-ai/agent-plugins 0.4.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.
Files changed (100) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/LICENSE +201 -0
  3. package/README.md +261 -0
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.js +2 -0
  6. package/dist/lifecycle/activation.d.ts +177 -0
  7. package/dist/lifecycle/activation.js +874 -0
  8. package/dist/lifecycle/bundled-digests.d.ts +27 -0
  9. package/dist/lifecycle/bundled-digests.js +149 -0
  10. package/dist/lifecycle/bundled-source-archive.d.ts +13 -0
  11. package/dist/lifecycle/bundled-source-archive.js +96 -0
  12. package/dist/lifecycle/capability-projection.d.ts +11 -0
  13. package/dist/lifecycle/capability-projection.js +60 -0
  14. package/dist/lifecycle/fetch-archive.d.ts +88 -0
  15. package/dist/lifecycle/fetch-archive.js +215 -0
  16. package/dist/lifecycle/index.d.ts +174 -0
  17. package/dist/lifecycle/index.js +94 -0
  18. package/dist/lifecycle/install-from-url.d.ts +78 -0
  19. package/dist/lifecycle/install-from-url.js +73 -0
  20. package/dist/lifecycle/install.d.ts +52 -0
  21. package/dist/lifecycle/install.js +286 -0
  22. package/dist/lifecycle/layout.d.ts +20 -0
  23. package/dist/lifecycle/layout.js +30 -0
  24. package/dist/lifecycle/manifest.d.ts +214 -0
  25. package/dist/lifecycle/manifest.js +409 -0
  26. package/dist/lifecycle/mcp-provisioning.d.ts +20 -0
  27. package/dist/lifecycle/mcp-provisioning.js +14 -0
  28. package/dist/lifecycle/node.d.ts +11 -0
  29. package/dist/lifecycle/node.js +34 -0
  30. package/dist/lifecycle/package-paths.d.ts +12 -0
  31. package/dist/lifecycle/package-paths.js +74 -0
  32. package/dist/lifecycle/ports.d.ts +81 -0
  33. package/dist/lifecycle/ports.js +2 -0
  34. package/dist/lifecycle/resolve-agent-plugin-refs.d.ts +18 -0
  35. package/dist/lifecycle/resolve-agent-plugin-refs.js +143 -0
  36. package/dist/lifecycle/retire-bundled.d.ts +36 -0
  37. package/dist/lifecycle/retire-bundled.js +69 -0
  38. package/dist/lifecycle/search.d.ts +23 -0
  39. package/dist/lifecycle/search.js +50 -0
  40. package/dist/lifecycle/seed-bundled.d.ts +29 -0
  41. package/dist/lifecycle/seed-bundled.js +118 -0
  42. package/dist/lifecycle/set-enabled.d.ts +21 -0
  43. package/dist/lifecycle/set-enabled.js +39 -0
  44. package/dist/lifecycle/trusted-plugin-files.d.ts +29 -0
  45. package/dist/lifecycle/trusted-plugin-files.js +82 -0
  46. package/dist/lifecycle/types.d.ts +20 -0
  47. package/dist/lifecycle/types.js +2 -0
  48. package/dist/lifecycle/uninstall.d.ts +41 -0
  49. package/dist/lifecycle/uninstall.js +148 -0
  50. package/dist/lifecycle/yauzl-archive-reader.d.ts +62 -0
  51. package/dist/lifecycle/yauzl-archive-reader.js +73 -0
  52. package/dist/manifest.d.ts +68 -0
  53. package/dist/manifest.js +38 -0
  54. package/package.json +92 -0
  55. package/ui-ux-design/com.anthropic.claude-code/hooks/hooks.json +4 -0
  56. package/ui-ux-design/mcp.json +4 -0
  57. package/ui-ux-design/plugin.json +5 -0
  58. package/ui-ux-design/skills/frontend-accessibility/SKILL.md +60 -0
  59. package/ui-ux-design/skills/gstack-design/SKILL.md +53 -0
  60. package/ui-ux-design/skills/gstack-design/references/consultation.md +30 -0
  61. package/ui-ux-design/skills/gstack-design/references/html.md +29 -0
  62. package/ui-ux-design/skills/gstack-design/references/review.md +28 -0
  63. package/ui-ux-design/skills/gstack-design/references/shotgun.md +33 -0
  64. package/ui-ux-design/skills/gstack-design/references/upstream-notes.md +23 -0
  65. package/ui-ux-design/skills/interface-design/ORIGINAL.md +16 -0
  66. package/ui-ux-design/skills/interface-design/SKILL.md +41 -0
  67. package/ui-ux-design/skills/interface-design/references/commands/audit.md +40 -0
  68. package/ui-ux-design/skills/interface-design/references/commands/critique.md +21 -0
  69. package/ui-ux-design/skills/interface-design/references/commands/extract.md +34 -0
  70. package/ui-ux-design/skills/interface-design/references/commands/init.md +31 -0
  71. package/ui-ux-design/skills/interface-design/references/commands/status.md +22 -0
  72. package/ui-ux-design/skills/interface-design/references/examples/system-precision.md +29 -0
  73. package/ui-ux-design/skills/interface-design/references/examples/system-warmth.md +29 -0
  74. package/ui-ux-design/skills/interface-design/references/system-template.md +57 -0
  75. package/ui-ux-design/skills/shadcn-ui/README.md +244 -0
  76. package/ui-ux-design/skills/shadcn-ui/SKILL.md +326 -0
  77. package/ui-ux-design/skills/shadcn-ui/examples/auth-layout.tsx +177 -0
  78. package/ui-ux-design/skills/shadcn-ui/examples/data-table.tsx +313 -0
  79. package/ui-ux-design/skills/shadcn-ui/examples/form-pattern.tsx +177 -0
  80. package/ui-ux-design/skills/shadcn-ui/resources/component-catalog.md +481 -0
  81. package/ui-ux-design/skills/shadcn-ui/resources/customization-guide.md +516 -0
  82. package/ui-ux-design/skills/shadcn-ui/resources/migration-guide.md +463 -0
  83. package/ui-ux-design/skills/shadcn-ui/resources/setup-guide.md +412 -0
  84. package/ui-ux-design/skills/shadcn-ui/scripts/verify-setup.sh +134 -0
  85. package/ui-ux-design/skills/ui-ux-design/SKILL.md +77 -0
  86. package/ui-ux-design/skills/ui-ux-design/references/brand-and-voice.md +72 -0
  87. package/ui-ux-design/skills/ui-ux-design/references/components-and-states.md +107 -0
  88. package/ui-ux-design/skills/ui-ux-design/references/delight-and-motion.md +65 -0
  89. package/ui-ux-design/skills/ui-ux-design/references/foundations.md +144 -0
  90. package/ui-ux-design/skills/ui-ux-design/references/inclusive-ai-imagery.md +57 -0
  91. package/ui-ux-design/skills/ui-ux-design/references/kole-jain-uiux-concepts.md +102 -0
  92. package/ui-ux-design/skills/ui-ux-design/references/openai-frontend-skill.md +139 -0
  93. package/ui-ux-design/skills/ui-ux-design/references/premium-ui.md +63 -0
  94. package/ui-ux-design/skills/ui-ux-design/references/research-and-validation.md +78 -0
  95. package/ui-ux-design/skills/ui-ux-design/references/sam-crawford-premium-websites.md +93 -0
  96. package/ui-ux-design/skills/ui-ux-design/references/self-made-web-designer-core-skills.md +123 -0
  97. package/ui-ux-design/skills/ui-ux-design/references/visual-storytelling.md +57 -0
  98. package/ui-ux-design/skills/vercel-web-design-guidelines/SKILL.md +39 -0
  99. package/ui-ux-design/skills/web-compliance/SKILL.md +129 -0
  100. package/ui-ux-design/skills/web-compliance/references/audit-evidence.md +59 -0
@@ -0,0 +1,18 @@
1
+ import type { AgentPluginDeliveryMode, InstalledAgentPlugin } from "./types.js";
2
+ import type { AgentPluginWorkspaceLayout } from "./layout.js";
3
+ import type { AgentPluginLifecyclePorts } from "./ports.js";
4
+ export type { AgentPluginDeliveryMode } from "./types.js";
5
+ export type ResolveAgentPluginRefsResult = {
6
+ readonly ok: true;
7
+ readonly promptPrefix: string;
8
+ } | {
9
+ readonly ok: false;
10
+ readonly reason: string;
11
+ };
12
+ /** Internal composition; one state/queue instance per injected host context. */
13
+ export declare function createResolveAgentPluginRefsModule(ports: AgentPluginLifecyclePorts): {
14
+ resolveAgentPluginRefs: (pluginRefIds: readonly string[], workspaceLayout: Pick<AgentPluginWorkspaceLayout, "packages" | "root">, deliveryMode?: AgentPluginDeliveryMode) => Promise<ResolveAgentPluginRefsResult>;
15
+ listInstalledPlugins: (packagesDir: string) => Promise<readonly InstalledAgentPlugin[]>;
16
+ isInstalledDigestPresent: (packagesDir: string, archiveDigest: string) => Promise<boolean>;
17
+ };
18
+ //# sourceMappingURL=resolve-agent-plugin-refs.d.ts.map
@@ -0,0 +1,143 @@
1
+ /** Extracted from the host plugin lifecycle. Effects are supplied per host context. */
2
+ import path from "node:path";
3
+ import {} from "./activation.js";
4
+ import { createActivationModule } from "./activation.js";
5
+ import {} from "./bundled-digests.js";
6
+ import { createBundledDigestsModule } from "./bundled-digests.js";
7
+ import { createInstallModule } from "./install.js";
8
+ import { createCapabilityProjectionModule } from "./capability-projection.js";
9
+ function buildModule(ports) {
10
+ const readdir = ports.filesystem.readdir.bind(ports.filesystem);
11
+ const stat = ports.filesystem.stat.bind(ports.filesystem);
12
+ const { resolveAgentPluginActivation } = createActivationModule(ports);
13
+ const { preferBundledAgentPluginDigests, readBundledAgentPluginDigests } = createBundledDigestsModule(ports);
14
+ const { indexInstalledRoot } = createInstallModule(ports);
15
+ const { readInstalledSkillMarkdown } = createCapabilityProjectionModule(ports);
16
+ const SHA256_DIGEST_DIRNAME_PATTERN = /^[a-f0-9]{64}$/;
17
+ function resolveAgentPluginDeliveryMode() { return ports.deliveryMode; }
18
+ async function resolveAgentPluginRefs(pluginRefIds, workspaceLayout, deliveryMode = resolveAgentPluginDeliveryMode()) {
19
+ if (pluginRefIds.length === 0)
20
+ return { ok: true, promptPrefix: "" };
21
+ const bundledDigests = await readBundledAgentPluginDigests(workspaceLayout.root);
22
+ const sections = [];
23
+ for (const pluginRefId of pluginRefIds) {
24
+ const refusal = activationRefusal(pluginRefId, await resolveAgentPluginActivation(workspaceLayout.root, pluginRefId));
25
+ if (refusal !== undefined)
26
+ return { ok: false, reason: refusal };
27
+ const resolved = await resolveOnePluginRef(pluginRefId, workspaceLayout.packages, deliveryMode, bundledDigests);
28
+ if (!resolved.ok)
29
+ return resolved;
30
+ sections.push(resolved.section);
31
+ }
32
+ return { ok: true, promptPrefix: sections.join("\n\n") };
33
+ }
34
+ function activationRefusal(pluginRefId, verdict) {
35
+ if (verdict.verdict === "active")
36
+ return undefined;
37
+ if (verdict.verdict === "undetermined") {
38
+ return (`Agent Plugin '${pluginRefId}' was not loaded: this workspace's activation record could not be read, so whether ` +
39
+ `it is enabled cannot be confirmed (${verdict.reason}). Nothing was injected; repair activations.json and start the run again.`);
40
+ }
41
+ return (`Agent Plugin '${pluginRefId}' is installed in this workspace but is not enabled — it ships with ${ports.productName} and ` +
42
+ "stays inactive until an operator turns it on. Enable it before pinning it to a run.");
43
+ }
44
+ async function listInstalledPlugins(packagesDir) {
45
+ let entries;
46
+ try {
47
+ entries = await readdir(packagesDir);
48
+ }
49
+ catch (error) {
50
+ if (isEnoent(error))
51
+ return [];
52
+ throw error;
53
+ }
54
+ const installed = [];
55
+ for (const digest of entries) {
56
+ if (!SHA256_DIGEST_DIRNAME_PATTERN.test(digest))
57
+ continue;
58
+ try {
59
+ installed.push(await indexInstalledRoot(path.join(packagesDir, digest), digest));
60
+ }
61
+ catch {
62
+ }
63
+ }
64
+ return installed;
65
+ }
66
+ async function isInstalledDigestPresent(packagesDir, archiveDigest) {
67
+ if (!SHA256_DIGEST_DIRNAME_PATTERN.test(archiveDigest))
68
+ return false;
69
+ try {
70
+ return (await stat(path.join(packagesDir, archiveDigest))).isDirectory();
71
+ }
72
+ catch {
73
+ return false;
74
+ }
75
+ }
76
+ function isEnoent(error) {
77
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
78
+ }
79
+ async function resolveOnePluginRef(pluginRefId, packagesDir, deliveryMode, bundledDigests) {
80
+ const installed = preferBundledAgentPluginDigests(await listInstalledPlugins(packagesDir), bundledDigests);
81
+ const matches = installed.filter((plugin) => plugin.pluginId === pluginRefId);
82
+ if (matches.length === 0) {
83
+ return {
84
+ ok: false,
85
+ reason: `Agent Plugin '${pluginRefId}' is not installed in this workspace — pinned by the composer but not found under any installed package`,
86
+ };
87
+ }
88
+ if (matches.length > 1) {
89
+ const digests = matches.map((plugin) => plugin.archiveDigest).sort();
90
+ return {
91
+ ok: false,
92
+ reason: `Agent Plugin '${pluginRefId}' matches ${matches.length} installed packages (digests: ${digests.join(", ")}) — refusing to guess which one to use`,
93
+ };
94
+ }
95
+ const plugin = matches[0];
96
+ const skillPath = `skills/${pluginRefId}/SKILL.md`;
97
+ if (deliveryMode === "pointer")
98
+ return buildPointerSection(pluginRefId, plugin);
99
+ let skillMarkdown;
100
+ try {
101
+ skillMarkdown = await readInstalledSkillMarkdown(plugin.packageRoot, skillPath);
102
+ }
103
+ catch (error) {
104
+ const message = error instanceof Error ? error.message : String(error);
105
+ return {
106
+ ok: false,
107
+ reason: `Agent Plugin '${pluginRefId}' has no readable '${skillPath}' in its installed package: ${message}`,
108
+ };
109
+ }
110
+ const otherFiles = plugin.files
111
+ .filter((file) => file !== skillPath)
112
+ .map((file) => path.join(plugin.packageRoot, file));
113
+ const inventory = otherFiles.length > 0
114
+ ? `\n\nThe SKILL.md above is this Agent Plugin's own instructions — follow them, including any files it directs you to load before starting work. Every other file in the installed package is listed below by absolute path and is readable now:\n${otherFiles.map((file) => `- ${file}`).join("\n")}`
115
+ : "";
116
+ return {
117
+ ok: true,
118
+ section: `<<AGENT_PLUGIN pluginId="${pluginRefId}">>\n${skillMarkdown}${inventory}\n<</AGENT_PLUGIN>>`,
119
+ };
120
+ }
121
+ function buildPointerSection(pluginRefId, plugin) {
122
+ if (!plugin.skills.some((skill) => skill.name === pluginRefId)) {
123
+ return {
124
+ ok: false,
125
+ reason: `Agent Plugin '${pluginRefId}' has no readable 'skills/${pluginRefId}/SKILL.md' in its installed package: no such skill folder`,
126
+ };
127
+ }
128
+ const body = ports.formatPluginToolPointer({ pluginId: pluginRefId });
129
+ return { ok: true, section: `<<AGENT_PLUGIN pluginId="${pluginRefId}">>\n${body}\n<</AGENT_PLUGIN>>` };
130
+ }
131
+ return { resolveAgentPluginRefs, listInstalledPlugins, isInstalledDigestPresent };
132
+ }
133
+ const instances = new WeakMap();
134
+ /** Internal composition; one state/queue instance per injected host context. */
135
+ export function createResolveAgentPluginRefsModule(ports) {
136
+ let instance = instances.get(ports);
137
+ if (!instance) {
138
+ instance = buildModule(ports);
139
+ instances.set(ports, instance);
140
+ }
141
+ return instance;
142
+ }
143
+ //# sourceMappingURL=resolve-agent-plugin-refs.js.map
@@ -0,0 +1,36 @@
1
+ /** Extracted from the host plugin lifecycle. Effects are supplied per host context. */
2
+ import { type BundledAgentPluginEnableOutcome } from "./activation.js";
3
+ import type { AgentPluginLayout } from "./layout.js";
4
+ import type { AgentPluginLifecyclePorts } from "./ports.js";
5
+ export type RetiredAgentPluginSuccessorOutcome = BundledAgentPluginEnableOutcome | "not-needed";
6
+ export type RetiredAgentPluginOutcome = {
7
+ readonly pluginId: string;
8
+ readonly successorId: string;
9
+ readonly status: "absent";
10
+ } | {
11
+ readonly pluginId: string;
12
+ readonly successorId: string;
13
+ readonly status: "retired";
14
+ readonly removedDigests: readonly string[];
15
+ readonly activationRemoved: boolean;
16
+ readonly ledgerEntryRemoved: boolean;
17
+ readonly successor: RetiredAgentPluginSuccessorOutcome;
18
+ } | {
19
+ readonly pluginId: string;
20
+ readonly successorId: string;
21
+ readonly status: "failed";
22
+ readonly reason: string;
23
+ };
24
+ export interface RetireBundledAgentPluginsRequired {
25
+ readonly layout: AgentPluginLayout;
26
+ readonly workspaceId: string;
27
+ }
28
+ export interface RetireBundledAgentPluginsOptional {
29
+ readonly retired?: (ReadonlyMap<string, string>) | undefined;
30
+ readonly now?: ((required: Record<string, never>) => Date) | undefined;
31
+ }
32
+ /** Internal composition; one state/queue instance per injected host context. */
33
+ export declare function createRetireBundledModule(ports: AgentPluginLifecyclePorts): {
34
+ retireBundledAgentPlugins: (required: RetireBundledAgentPluginsRequired, optional?: RetireBundledAgentPluginsOptional) => Promise<readonly RetiredAgentPluginOutcome[]>;
35
+ };
36
+ //# sourceMappingURL=retire-bundled.d.ts.map
@@ -0,0 +1,69 @@
1
+ /** Extracted from the host plugin lifecycle. Effects are supplied per host context. */
2
+ import {} from "./activation.js";
3
+ import { createActivationModule } from "./activation.js";
4
+ import { createBundledDigestsModule } from "./bundled-digests.js";
5
+ import { createResolveAgentPluginRefsModule } from "./resolve-agent-plugin-refs.js";
6
+ import { createUninstallModule } from "./uninstall.js";
7
+ function buildModule(ports) {
8
+ const { deleteAgentPluginActivation, enableBundledAgentPluginUnlessOperatorDisabled, readAgentPluginActivations, resolveAgentPluginActivation } = createActivationModule(ports);
9
+ const { removeBundledAgentPluginDigest } = createBundledDigestsModule(ports);
10
+ const { listInstalledPlugins } = createResolveAgentPluginRefsModule(ports);
11
+ const { uninstallAgentPlugin } = createUninstallModule(ports);
12
+ async function retireBundledAgentPlugins(required, optional = {}) {
13
+ const outcomes = [];
14
+ for (const [pluginId, successorId] of optional.retired ?? ports.retiredBundledPlugins) {
15
+ try {
16
+ outcomes.push(await retireOne(required, optional, pluginId, successorId));
17
+ }
18
+ catch (error) {
19
+ outcomes.push({ pluginId, successorId, status: "failed", reason: error instanceof Error ? error.message : String(error) });
20
+ }
21
+ }
22
+ return outcomes;
23
+ }
24
+ async function retireOne(required, optional, pluginId, successorId) {
25
+ const workspaceLayout = required.layout.forWorkspace({ workspaceId: required.workspaceId });
26
+ const workspaceRoot = workspaceLayout.root;
27
+ const verdict = await resolveAgentPluginActivation(workspaceRoot, pluginId);
28
+ if (verdict.verdict === "undetermined") {
29
+ return { pluginId, successorId, status: "failed", reason: `cannot tell whether '${pluginId}' was enabled: ${verdict.reason}` };
30
+ }
31
+ const installed = (await listInstalledPlugins(workspaceLayout.packages)).filter((plugin) => plugin.pluginId === pluginId);
32
+ const hasRecord = Object.hasOwn((await readAgentPluginActivations(workspaceRoot)).plugins, pluginId);
33
+ if (installed.length === 0 && !hasRecord) {
34
+ const ledgerEntryRemoved = await removeBundledAgentPluginDigest({ workspaceRoot, pluginId });
35
+ if (!ledgerEntryRemoved)
36
+ return { pluginId, successorId, status: "absent" };
37
+ return { pluginId, successorId, status: "retired", removedDigests: [], activationRemoved: false, ledgerEntryRemoved, successor: "not-needed" };
38
+ }
39
+ const successor = verdict.verdict === "active"
40
+ ? await enableBundledAgentPluginUnlessOperatorDisabled({
41
+ workspaceRoot,
42
+ pluginId: successorId,
43
+ actor: `system:retire-${pluginId}`,
44
+ ...(optional.now !== undefined ? { now: optional.now } : {}),
45
+ })
46
+ : "not-needed";
47
+ let removedDigests = [];
48
+ if (installed.length > 0) {
49
+ removedDigests = (await uninstallAgentPlugin({ layout: required.layout, workspaceId: required.workspaceId, pluginId }, { retiredBundled: true })).removedDigests;
50
+ }
51
+ else {
52
+ await deleteAgentPluginActivation({ workspaceRoot, pluginId });
53
+ }
54
+ const ledgerEntryRemoved = await removeBundledAgentPluginDigest({ workspaceRoot, pluginId });
55
+ return { pluginId, successorId, status: "retired", removedDigests, activationRemoved: hasRecord, ledgerEntryRemoved, successor };
56
+ }
57
+ return { retireBundledAgentPlugins };
58
+ }
59
+ const instances = new WeakMap();
60
+ /** Internal composition; one state/queue instance per injected host context. */
61
+ export function createRetireBundledModule(ports) {
62
+ let instance = instances.get(ports);
63
+ if (!instance) {
64
+ instance = buildModule(ports);
65
+ instances.set(ports, instance);
66
+ }
67
+ return instance;
68
+ }
69
+ //# sourceMappingURL=retire-bundled.js.map
@@ -0,0 +1,23 @@
1
+ /** Extracted from the host plugin lifecycle. Effects are supplied per host context. */
2
+ import type { AgentPluginLifecyclePorts } from "./ports.js";
3
+ export interface AgentPluginSearchSkill {
4
+ readonly name: string;
5
+ readonly summary: string;
6
+ }
7
+ export interface AgentPluginSearchCandidate {
8
+ readonly pluginId: string;
9
+ readonly version?: (string) | undefined;
10
+ readonly description?: (string) | undefined;
11
+ readonly keywords: readonly string[];
12
+ readonly enabled: boolean;
13
+ readonly skills: readonly AgentPluginSearchSkill[];
14
+ readonly mcpServerIds: readonly string[];
15
+ }
16
+ export interface AgentPluginSearchMatch extends AgentPluginSearchCandidate {
17
+ readonly score: number;
18
+ }
19
+ /** Internal composition; one state/queue instance per injected host context. */
20
+ export declare function createSearchModule(ports: AgentPluginLifecyclePorts): {
21
+ rankInstalledAgentPlugins: (query: string, candidates: readonly AgentPluginSearchCandidate[], limit: number) => readonly AgentPluginSearchMatch[];
22
+ };
23
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1,50 @@
1
+ /** Extracted from the host plugin lifecycle. Effects are supplied per host context. */
2
+ function buildModule(ports) {
3
+ const ID_FIELD_WEIGHT = 5;
4
+ const KEYWORD_FIELD_WEIGHT = 4;
5
+ const DESCRIPTION_FIELD_WEIGHT = 2;
6
+ const SKILL_FIELD_WEIGHT = 1;
7
+ function tokenize(query) {
8
+ return query
9
+ .toLowerCase()
10
+ .split(/\s+/)
11
+ .filter((term) => term.length > 0);
12
+ }
13
+ function fieldHaystacks(candidate) {
14
+ return [
15
+ { text: candidate.pluginId.toLowerCase(), weight: ID_FIELD_WEIGHT },
16
+ { text: candidate.keywords.join(" ").toLowerCase(), weight: KEYWORD_FIELD_WEIGHT },
17
+ { text: (candidate.description ?? "").toLowerCase(), weight: DESCRIPTION_FIELD_WEIGHT },
18
+ {
19
+ text: candidate.skills.map((skill) => `${skill.name} ${skill.summary}`).join(" ").toLowerCase(),
20
+ weight: SKILL_FIELD_WEIGHT,
21
+ },
22
+ ];
23
+ }
24
+ function scoreCandidate(candidate, terms) {
25
+ const haystacks = fieldHaystacks(candidate);
26
+ return terms.reduce((total, term) => total + haystacks.reduce((fieldTotal, haystack) => (haystack.text.includes(term) ? fieldTotal + haystack.weight : fieldTotal), 0), 0);
27
+ }
28
+ function rankInstalledAgentPlugins(query, candidates, limit) {
29
+ const terms = tokenize(query);
30
+ if (terms.length === 0)
31
+ return [];
32
+ return candidates
33
+ .map((candidate) => ({ ...candidate, score: scoreCandidate(candidate, terms) }))
34
+ .filter((match) => match.score > 0)
35
+ .sort((a, b) => b.score - a.score)
36
+ .slice(0, Math.max(limit, 0));
37
+ }
38
+ return { rankInstalledAgentPlugins };
39
+ }
40
+ const instances = new WeakMap();
41
+ /** Internal composition; one state/queue instance per injected host context. */
42
+ export function createSearchModule(ports) {
43
+ let instance = instances.get(ports);
44
+ if (!instance) {
45
+ instance = buildModule(ports);
46
+ instances.set(ports, instance);
47
+ }
48
+ return instance;
49
+ }
50
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1,29 @@
1
+ import type { AgentPluginLayout } from "./layout.js";
2
+ import { type RetiredAgentPluginOutcome } from "./retire-bundled.js";
3
+ import type { AgentPluginLifecyclePorts } from "./ports.js";
4
+ export type SeededAgentPluginOutcome = {
5
+ readonly pluginId: string;
6
+ readonly status: "seeded";
7
+ readonly archiveDigest: string;
8
+ readonly activationRecorded: boolean;
9
+ } | {
10
+ readonly pluginId: string;
11
+ readonly status: "failed";
12
+ readonly reason: string;
13
+ };
14
+ export interface SeedBundledAgentPluginsResult {
15
+ readonly sourceRoot: string;
16
+ readonly outcomes: readonly SeededAgentPluginOutcome[];
17
+ readonly ledgerFailure?: (string) | undefined;
18
+ readonly retirements: readonly RetiredAgentPluginOutcome[];
19
+ }
20
+ export interface SeedBundledAgentPluginsRequired {
21
+ readonly layout: AgentPluginLayout;
22
+ readonly workspaceId: string;
23
+ readonly sourceRoot: string;
24
+ }
25
+ /** Internal composition; one state/queue instance per injected host context. */
26
+ export declare function createSeedBundledModule(ports: AgentPluginLifecyclePorts): {
27
+ seedBundledAgentPlugins: (required: SeedBundledAgentPluginsRequired) => Promise<SeedBundledAgentPluginsResult>;
28
+ };
29
+ //# sourceMappingURL=seed-bundled.d.ts.map
@@ -0,0 +1,118 @@
1
+ import path from "node:path";
2
+ import { createActivationModule } from "./activation.js";
3
+ import { createBundledDigestsModule } from "./bundled-digests.js";
4
+ import { createBundledSourceArchiveModule } from "./bundled-source-archive.js";
5
+ import { createInstallModule } from "./install.js";
6
+ import {} from "./retire-bundled.js";
7
+ import { createRetireBundledModule } from "./retire-bundled.js";
8
+ function buildModule(ports) {
9
+ const readdir = ports.filesystem.readdir.bind(ports.filesystem);
10
+ const stat = ports.filesystem.stat.bind(ports.filesystem);
11
+ const { assertAgentPluginActivationsWritable, recordBundledAgentPluginIfAbsent } = createActivationModule(ports);
12
+ const { recordBundledAgentPluginDigests } = createBundledDigestsModule(ports);
13
+ const { createBundledSourceArchiveReader, packAgentPluginDirectory } = createBundledSourceArchiveModule(ports);
14
+ const { installAgentPlugin } = createInstallModule(ports);
15
+ const { retireBundledAgentPlugins } = createRetireBundledModule(ports);
16
+ async function seedBundledAgentPlugins(required) {
17
+ const { layout, workspaceId, sourceRoot } = required;
18
+ const pluginDirNames = await listBundledPluginDirs(sourceRoot);
19
+ const refusal = await activationsRefusal(layout, workspaceId);
20
+ if (refusal !== undefined) {
21
+ return {
22
+ sourceRoot,
23
+ outcomes: pluginDirNames.map((dirName) => ({ pluginId: dirName, status: "failed", reason: refusal })),
24
+ retirements: [],
25
+ };
26
+ }
27
+ const outcomes = [];
28
+ for (const dirName of pluginDirNames) {
29
+ outcomes.push(await seedOne({ layout, workspaceId, sourceDir: path.join(sourceRoot, dirName), dirName }));
30
+ }
31
+ const ledgerFailure = await recordSeededDigests(layout.forWorkspace({ workspaceId }).root, outcomes);
32
+ const retirements = await retireBundledAgentPlugins({ layout, workspaceId });
33
+ return { sourceRoot, outcomes, retirements, ...(ledgerFailure !== undefined ? { ledgerFailure } : {}) };
34
+ }
35
+ async function recordSeededDigests(workspaceRoot, outcomes) {
36
+ try {
37
+ await recordBundledAgentPluginDigests({
38
+ workspaceRoot,
39
+ seeded: outcomes.flatMap((outcome) => outcome.status === "seeded" ? [{ pluginId: outcome.pluginId, archiveDigest: outcome.archiveDigest }] : []),
40
+ });
41
+ return undefined;
42
+ }
43
+ catch (error) {
44
+ return error instanceof Error ? error.message : String(error);
45
+ }
46
+ }
47
+ async function activationsRefusal(layout, workspaceId) {
48
+ try {
49
+ await assertAgentPluginActivationsWritable(layout.forWorkspace({ workspaceId }).root);
50
+ return undefined;
51
+ }
52
+ catch (error) {
53
+ return error instanceof Error ? error.message : String(error);
54
+ }
55
+ }
56
+ async function seedOne(args) {
57
+ try {
58
+ const packed = await packAgentPluginDirectory(args.sourceDir);
59
+ const installed = await installAgentPlugin({
60
+ archive: packed.bytes,
61
+ expectedSha256: packed.sha256,
62
+ archiveReader: createBundledSourceArchiveReader(),
63
+ layout: args.layout,
64
+ workspaceId: args.workspaceId,
65
+ });
66
+ const { recorded } = await recordBundledAgentPluginIfAbsent({ workspaceRoot: args.layout.forWorkspace({ workspaceId: args.workspaceId }).root, pluginId: installed.pluginId }, { enabled: ports.seededEnabledPluginIds.has(installed.pluginId) });
67
+ return {
68
+ pluginId: installed.pluginId,
69
+ status: "seeded",
70
+ archiveDigest: installed.archiveDigest,
71
+ activationRecorded: recorded,
72
+ };
73
+ }
74
+ catch (error) {
75
+ return {
76
+ pluginId: args.dirName,
77
+ status: "failed",
78
+ reason: error instanceof Error ? error.message : String(error),
79
+ };
80
+ }
81
+ }
82
+ async function listBundledPluginDirs(sourceRoot) {
83
+ let entries;
84
+ try {
85
+ entries = await readdir(sourceRoot, { withFileTypes: true });
86
+ }
87
+ catch {
88
+ return [];
89
+ }
90
+ const dirs = [];
91
+ for (const entry of entries) {
92
+ if (!entry.isDirectory())
93
+ continue;
94
+ if (ports.retiredBundledPlugins.has(entry.name))
95
+ continue;
96
+ try {
97
+ const manifest = await stat(path.join(sourceRoot, entry.name, "plugin.json"));
98
+ if (manifest.isFile())
99
+ dirs.push(entry.name);
100
+ }
101
+ catch {
102
+ }
103
+ }
104
+ return dirs.sort();
105
+ }
106
+ return { seedBundledAgentPlugins };
107
+ }
108
+ const instances = new WeakMap();
109
+ /** Internal composition; one state/queue instance per injected host context. */
110
+ export function createSeedBundledModule(ports) {
111
+ let instance = instances.get(ports);
112
+ if (!instance) {
113
+ instance = buildModule(ports);
114
+ instances.set(ports, instance);
115
+ }
116
+ return instance;
117
+ }
118
+ //# sourceMappingURL=seed-bundled.js.map
@@ -0,0 +1,21 @@
1
+ import type { AgentPluginLifecyclePorts } from "./ports.js";
2
+ export declare class AgentPluginNotInstalledError extends Error {
3
+ constructor({ pluginId }: {
4
+ readonly pluginId: string;
5
+ });
6
+ }
7
+ export interface SetAgentPluginEnabledInput {
8
+ readonly workspaceId: string;
9
+ readonly pluginId: string;
10
+ readonly enabled: boolean;
11
+ readonly actor: string;
12
+ }
13
+ export interface SetAgentPluginEnabledResult {
14
+ readonly pluginId: string;
15
+ readonly enabled: boolean;
16
+ }
17
+ /** Internal composition; one state/queue instance per injected host context. */
18
+ export declare function createSetEnabledModule(ports: AgentPluginLifecyclePorts): {
19
+ setAgentPluginEnabled: (input: SetAgentPluginEnabledInput) => Promise<SetAgentPluginEnabledResult>;
20
+ };
21
+ //# sourceMappingURL=set-enabled.d.ts.map
@@ -0,0 +1,39 @@
1
+ /** Extracted from the host plugin lifecycle. Effects are supplied per host context. */
2
+ import { createActivationModule } from "./activation.js";
3
+ import { createResolveAgentPluginRefsModule } from "./resolve-agent-plugin-refs.js";
4
+ export class AgentPluginNotInstalledError extends Error {
5
+ constructor({ pluginId }) {
6
+ super(`agent plugin '${pluginId}' is not installed in this workspace`);
7
+ this.name = "AgentPluginNotInstalledError";
8
+ }
9
+ }
10
+ function buildModule(ports) {
11
+ const { setAgentPluginActivation } = createActivationModule(ports);
12
+ const { listInstalledPlugins } = createResolveAgentPluginRefsModule(ports);
13
+ async function setAgentPluginEnabled(input) {
14
+ const workspaceLayout = ports.layout.forWorkspace({ workspaceId: input.workspaceId });
15
+ const installed = await listInstalledPlugins(workspaceLayout.packages);
16
+ if (!installed.some((plugin) => plugin.pluginId === input.pluginId)) {
17
+ throw new AgentPluginNotInstalledError({ pluginId: input.pluginId });
18
+ }
19
+ const written = await setAgentPluginActivation({
20
+ workspaceRoot: workspaceLayout.root,
21
+ pluginId: input.pluginId,
22
+ enabled: input.enabled,
23
+ actor: input.actor,
24
+ });
25
+ return { pluginId: input.pluginId, enabled: written.plugins[input.pluginId]?.enabled ?? input.enabled };
26
+ }
27
+ return { setAgentPluginEnabled };
28
+ }
29
+ const instances = new WeakMap();
30
+ /** Internal composition; one state/queue instance per injected host context. */
31
+ export function createSetEnabledModule(ports) {
32
+ let instance = instances.get(ports);
33
+ if (!instance) {
34
+ instance = buildModule(ports);
35
+ instances.set(ports, instance);
36
+ }
37
+ return instance;
38
+ }
39
+ //# sourceMappingURL=set-enabled.js.map
@@ -0,0 +1,29 @@
1
+ import type { AgentPluginLifecyclePorts } from "./ports.js";
2
+ export interface TrustedPluginPackage {
3
+ readonly pluginId: string;
4
+ readonly packageRoot: string;
5
+ }
6
+ export interface TrustedPluginPackagesQuery {
7
+ readonly workspaceId: string;
8
+ readonly filename: string;
9
+ readonly contribution: string;
10
+ readonly requireActive: boolean;
11
+ readonly orderByPluginId?: (boolean) | undefined;
12
+ readonly onInactive?: ((required: {
13
+ readonly plugin: TrustedPluginPackage;
14
+ }) => Promise<void>) | undefined;
15
+ }
16
+ export type TrustedPluginVerdict = {
17
+ readonly trusted: TrustedPluginPackage;
18
+ } | {
19
+ readonly refusal: string;
20
+ };
21
+ /** Internal composition; one state/queue instance per injected host context. */
22
+ export declare function createTrustedPluginFilesModule(ports: AgentPluginLifecyclePorts): {
23
+ findTrustedPluginPackages: (query: TrustedPluginPackagesQuery) => Promise<readonly TrustedPluginVerdict[]>;
24
+ readTrustedPluginFile: (plugin: TrustedPluginPackage, filename: string) => Promise<string>;
25
+ importContainedModule: (plugin: TrustedPluginPackage, modulePath: string) => Promise<{
26
+ readonly exported: unknown;
27
+ } | string>;
28
+ };
29
+ //# sourceMappingURL=trusted-plugin-files.d.ts.map
@@ -0,0 +1,82 @@
1
+ /** Extracted from the host plugin lifecycle. Effects are supplied per host context. */
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ import { createActivationModule } from "./activation.js";
5
+ import { createBundledDigestsModule } from "./bundled-digests.js";
6
+ import { PackagePathViolation } from "./package-paths.js";
7
+ import { createPackagePathsModule } from "./package-paths.js";
8
+ import { createResolveAgentPluginRefsModule } from "./resolve-agent-plugin-refs.js";
9
+ function buildModule(ports) {
10
+ const readFile = ports.filesystem.readFile.bind(ports.filesystem);
11
+ const { resolveAgentPluginActivation } = createActivationModule(ports);
12
+ const { preferBundledAgentPluginDigests, readBundledAgentPluginDigests } = createBundledDigestsModule(ports);
13
+ const { assertContainedOnDisk } = createPackagePathsModule(ports);
14
+ const { listInstalledPlugins } = createResolveAgentPluginRefsModule(ports);
15
+ async function findTrustedPluginPackages(query) {
16
+ const layout = ports.layout.forWorkspace({ workspaceId: query.workspaceId });
17
+ const bundled = await readBundledAgentPluginDigests(layout.root);
18
+ const preferred = preferBundledAgentPluginDigests(await listInstalledPlugins(layout.packages), bundled);
19
+ const installed = query.orderByPluginId ? [...preferred].sort((a, b) => a.pluginId.localeCompare(b.pluginId)) : preferred;
20
+ const verdicts = [];
21
+ for (const plugin of installed) {
22
+ if (!plugin.files.includes(query.filename))
23
+ continue;
24
+ const refusal = await trustRefusal(query, plugin, bundled.get(plugin.pluginId), layout.root);
25
+ const trusted = { pluginId: plugin.pluginId, packageRoot: plugin.packageRoot };
26
+ if (refusal === null)
27
+ verdicts.push({ trusted });
28
+ else if (refusal === "inactive")
29
+ await query.onInactive?.({ plugin: trusted });
30
+ else
31
+ verdicts.push({ refusal: `${query.contribution} from '${plugin.pluginId}' were not loaded: ${refusal}` });
32
+ }
33
+ return verdicts;
34
+ }
35
+ async function trustRefusal(query, plugin, bundledDigest, workspaceRoot) {
36
+ if (query.requireActive) {
37
+ const activation = await resolveAgentPluginActivation(workspaceRoot, plugin.pluginId);
38
+ if (activation.verdict === "inactive")
39
+ return "inactive";
40
+ if (activation.verdict === "undetermined")
41
+ return `its activation could not be read (${activation.reason})`;
42
+ }
43
+ if (bundledDigest !== plugin.archiveDigest) {
44
+ return `only plugins shipped with ${ports.productName} may add ${query.contribution} (installed digest ${plugin.archiveDigest.slice(0, 12)} is not the one this build shipped)`;
45
+ }
46
+ return null;
47
+ }
48
+ async function readTrustedPluginFile(plugin, filename) {
49
+ const absolute = await assertContainedOnDisk(plugin.packageRoot, filename);
50
+ return readFile(absolute, "utf8");
51
+ }
52
+ async function importContainedModule(plugin, modulePath) {
53
+ let resolved;
54
+ try {
55
+ resolved = await assertContainedOnDisk(plugin.packageRoot, modulePath);
56
+ }
57
+ catch (error) {
58
+ if (error instanceof PackagePathViolation)
59
+ return `module path '${modulePath}' escapes the plugin root`;
60
+ throw error;
61
+ }
62
+ try {
63
+ const imported = (await import(pathToFileURL(resolved).href));
64
+ return { exported: imported.default };
65
+ }
66
+ catch (error) {
67
+ return error instanceof Error ? error.message : String(error);
68
+ }
69
+ }
70
+ return { findTrustedPluginPackages, readTrustedPluginFile, importContainedModule };
71
+ }
72
+ const instances = new WeakMap();
73
+ /** Internal composition; one state/queue instance per injected host context. */
74
+ export function createTrustedPluginFilesModule(ports) {
75
+ let instance = instances.get(ports);
76
+ if (!instance) {
77
+ instance = buildModule(ports);
78
+ instances.set(ports, instance);
79
+ }
80
+ return instance;
81
+ }
82
+ //# sourceMappingURL=trusted-plugin-files.js.map