@agentxm/workspace-state 0.28.4-bootstrap.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/LICENSE +110 -0
- package/README.md +11 -0
- package/dist/src/index.d.ts +72 -0
- package/dist/src/index.js +88 -0
- package/dist/src/knowledge/discovery-config.d.ts +12 -0
- package/dist/src/knowledge/discovery-config.js +9 -0
- package/dist/src/lockfile/accepted-registry-version.d.ts +12 -0
- package/dist/src/lockfile/accepted-registry-version.js +13 -0
- package/dist/src/lockfile/entry-fields.d.ts +189 -0
- package/dist/src/lockfile/entry-fields.js +89 -0
- package/dist/src/lockfile/errors.d.ts +48 -0
- package/dist/src/lockfile/errors.js +27 -0
- package/dist/src/lockfile/index.d.ts +18 -0
- package/dist/src/lockfile/index.js +16 -0
- package/dist/src/lockfile/lockfile.d.ts +2255 -0
- package/dist/src/lockfile/lockfile.js +235 -0
- package/dist/src/lockfile/resolved-version.d.ts +4 -0
- package/dist/src/lockfile/resolved-version.js +7 -0
- package/dist/src/lockfile/schema.d.ts +3062 -0
- package/dist/src/lockfile/schema.js +406 -0
- package/dist/src/schema/index.d.ts +3 -0
- package/dist/src/schema/index.js +2 -0
- package/dist/src/schema/read-and-validate-json-file.d.ts +20 -0
- package/dist/src/schema/read-and-validate-json-file.js +85 -0
- package/dist/src/schema/types.d.ts +26 -0
- package/dist/src/schema/types.js +2 -0
- package/dist/src/settings/errors.d.ts +22 -0
- package/dist/src/settings/errors.js +15 -0
- package/dist/src/settings/format-preserving-json.d.ts +40 -0
- package/dist/src/settings/format-preserving-json.js +80 -0
- package/dist/src/settings/index.d.ts +15 -0
- package/dist/src/settings/index.js +14 -0
- package/dist/src/settings/schema.d.ts +687 -0
- package/dist/src/settings/schema.js +977 -0
- package/dist/src/settings/settings.d.ts +38 -0
- package/dist/src/settings/settings.js +213 -0
- package/dist/src/testing.d.ts +17 -0
- package/dist/src/testing.js +17 -0
- package/dist/src/utils/atomic-write.d.ts +67 -0
- package/dist/src/utils/atomic-write.js +71 -0
- package/dist/src/utils/environment.d.ts +16 -0
- package/dist/src/utils/environment.js +19 -0
- package/dist/src/utils/path-safety.d.ts +25 -0
- package/dist/src/utils/path-safety.js +34 -0
- package/dist/src/utils/resolve-parent-symlinks.d.ts +16 -0
- package/dist/src/utils/resolve-parent-symlinks.js +36 -0
- package/dist/src/workspace/accepted-canonical-ref.d.ts +58 -0
- package/dist/src/workspace/accepted-canonical-ref.js +229 -0
- package/dist/src/workspace/artifact-change.d.ts +14 -0
- package/dist/src/workspace/artifact-change.js +18 -0
- package/dist/src/workspace/canonical-observation.d.ts +39 -0
- package/dist/src/workspace/canonical-observation.js +307 -0
- package/dist/src/workspace/configured-agent-outcome.d.ts +22 -0
- package/dist/src/workspace/configured-agent-outcome.js +33 -0
- package/dist/src/workspace/configured-agent-outcomes-provider.d.ts +50 -0
- package/dist/src/workspace/configured-agent-outcomes-provider.js +26 -0
- package/dist/src/workspace/configured-agent-outcomes.d.ts +48 -0
- package/dist/src/workspace/configured-agent-outcomes.js +113 -0
- package/dist/src/workspace/configured-entry-resolution/types.d.ts +32 -0
- package/dist/src/workspace/configured-entry-resolution/types.js +2 -0
- package/dist/src/workspace/configured-entry-resolution/workspace-ref.d.ts +32 -0
- package/dist/src/workspace/configured-entry-resolution/workspace-ref.js +176 -0
- package/dist/src/workspace/constants.d.ts +6 -0
- package/dist/src/workspace/constants.js +6 -0
- package/dist/src/workspace/create-symlink.d.ts +26 -0
- package/dist/src/workspace/create-symlink.js +87 -0
- package/dist/src/workspace/desired-pack-lock.d.ts +18 -0
- package/dist/src/workspace/desired-pack-lock.js +132 -0
- package/dist/src/workspace/desired-state-enabled.d.ts +18 -0
- package/dist/src/workspace/desired-state-enabled.js +16 -0
- package/dist/src/workspace/desired-state-graph.d.ts +114 -0
- package/dist/src/workspace/desired-state-graph.js +384 -0
- package/dist/src/workspace/desired-state-problem-text.d.ts +6 -0
- package/dist/src/workspace/desired-state-problem-text.js +27 -0
- package/dist/src/workspace/errors.d.ts +184 -0
- package/dist/src/workspace/errors.js +79 -0
- package/dist/src/workspace/extension-name.d.ts +28 -0
- package/dist/src/workspace/extension-name.js +66 -0
- package/dist/src/workspace/extension-paths.d.ts +82 -0
- package/dist/src/workspace/extension-paths.js +172 -0
- package/dist/src/workspace/footprint-recorder.d.ts +30 -0
- package/dist/src/workspace/footprint-recorder.js +32 -0
- package/dist/src/workspace/layout.d.ts +43 -0
- package/dist/src/workspace/layout.js +164 -0
- package/dist/src/workspace/lock-entry-to-ref.d.ts +40 -0
- package/dist/src/workspace/lock-entry-to-ref.js +433 -0
- package/dist/src/workspace/lock-entry-to-source-params.d.ts +26 -0
- package/dist/src/workspace/lock-entry-to-source-params.js +81 -0
- package/dist/src/workspace/locked-entries.d.ts +30 -0
- package/dist/src/workspace/locked-entries.js +34 -0
- package/dist/src/workspace/materialized-file-target.d.ts +14 -0
- package/dist/src/workspace/materialized-file-target.js +14 -0
- package/dist/src/workspace/materialized-tree.d.ts +23 -0
- package/dist/src/workspace/materialized-tree.js +90 -0
- package/dist/src/workspace/mcp-entry-semantics.d.ts +31 -0
- package/dist/src/workspace/mcp-entry-semantics.js +60 -0
- package/dist/src/workspace/observed-installed.d.ts +9 -0
- package/dist/src/workspace/observed-installed.js +9 -0
- package/dist/src/workspace/pack-manifest-content-identity.d.ts +12 -0
- package/dist/src/workspace/pack-manifest-content-identity.js +20 -0
- package/dist/src/workspace/pack-paths.d.ts +24 -0
- package/dist/src/workspace/pack-paths.js +16 -0
- package/dist/src/workspace/package-hash.d.ts +25 -0
- package/dist/src/workspace/package-hash.js +45 -0
- package/dist/src/workspace/paths.d.ts +24 -0
- package/dist/src/workspace/paths.js +52 -0
- package/dist/src/workspace/read-model/__fixtures__/builder.d.ts +199 -0
- package/dist/src/workspace/read-model/__fixtures__/builder.js +588 -0
- package/dist/src/workspace/read-model/__fixtures__/decoders.d.ts +15 -0
- package/dist/src/workspace/read-model/__fixtures__/decoders.js +15 -0
- package/dist/src/workspace/read-model/__fixtures__/occurrences.d.ts +72 -0
- package/dist/src/workspace/read-model/__fixtures__/occurrences.js +134 -0
- package/dist/src/workspace/read-model/__fixtures__/scenario-harness.d.ts +99 -0
- package/dist/src/workspace/read-model/__fixtures__/scenario-harness.js +142 -0
- package/dist/src/workspace/read-model/__fixtures__/test-layer.d.ts +60 -0
- package/dist/src/workspace/read-model/__fixtures__/test-layer.js +57 -0
- package/dist/src/workspace/read-model/agent-presence.d.ts +32 -0
- package/dist/src/workspace/read-model/agent-presence.js +21 -0
- package/dist/src/workspace/read-model/agent-root-resolver.d.ts +38 -0
- package/dist/src/workspace/read-model/agent-root-resolver.js +35 -0
- package/dist/src/workspace/read-model/agents/index.d.ts +38 -0
- package/dist/src/workspace/read-model/agents/index.js +45 -0
- package/dist/src/workspace/read-model/agents/shared.d.ts +27 -0
- package/dist/src/workspace/read-model/agents/shared.js +63 -0
- package/dist/src/workspace/read-model/agents/types.d.ts +133 -0
- package/dist/src/workspace/read-model/agents/types.js +51 -0
- package/dist/src/workspace/read-model/diagnostics.d.ts +18 -0
- package/dist/src/workspace/read-model/diagnostics.js +14 -0
- package/dist/src/workspace/read-model/discovery/index.d.ts +5 -0
- package/dist/src/workspace/read-model/discovery/index.js +5 -0
- package/dist/src/workspace/read-model/discovery/plugin-manifests.d.ts +16 -0
- package/dist/src/workspace/read-model/discovery/plugin-manifests.js +168 -0
- package/dist/src/workspace/read-model/discovery/skills.d.ts +58 -0
- package/dist/src/workspace/read-model/discovery/skills.js +263 -0
- package/dist/src/workspace/read-model/discovery/subagents.d.ts +37 -0
- package/dist/src/workspace/read-model/discovery/subagents.js +48 -0
- package/dist/src/workspace/read-model/errors.d.ts +93 -0
- package/dist/src/workspace/read-model/errors.js +30 -0
- package/dist/src/workspace/read-model/extensions/actual-helpers.d.ts +4 -0
- package/dist/src/workspace/read-model/extensions/actual-helpers.js +4 -0
- package/dist/src/workspace/read-model/extensions/hook.d.ts +104 -0
- package/dist/src/workspace/read-model/extensions/hook.js +119 -0
- package/dist/src/workspace/read-model/extensions/index.d.ts +19 -0
- package/dist/src/workspace/read-model/extensions/index.js +43 -0
- package/dist/src/workspace/read-model/extensions/indexByName.d.ts +31 -0
- package/dist/src/workspace/read-model/extensions/indexByName.js +30 -0
- package/dist/src/workspace/read-model/extensions/inventory.d.ts +99 -0
- package/dist/src/workspace/read-model/extensions/inventory.js +111 -0
- package/dist/src/workspace/read-model/extensions/knowledge.d.ts +101 -0
- package/dist/src/workspace/read-model/extensions/knowledge.js +121 -0
- package/dist/src/workspace/read-model/extensions/mcp-server.d.ts +106 -0
- package/dist/src/workspace/read-model/extensions/mcp-server.js +122 -0
- package/dist/src/workspace/read-model/extensions/pack.d.ts +104 -0
- package/dist/src/workspace/read-model/extensions/pack.js +123 -0
- package/dist/src/workspace/read-model/extensions/package-root.d.ts +39 -0
- package/dist/src/workspace/read-model/extensions/package-root.js +48 -0
- package/dist/src/workspace/read-model/extensions/projection.d.ts +137 -0
- package/dist/src/workspace/read-model/extensions/projection.js +180 -0
- package/dist/src/workspace/read-model/extensions/rule.d.ts +104 -0
- package/dist/src/workspace/read-model/extensions/rule.js +113 -0
- package/dist/src/workspace/read-model/extensions/skill.d.ts +170 -0
- package/dist/src/workspace/read-model/extensions/skill.js +148 -0
- package/dist/src/workspace/read-model/extensions/subagent.d.ts +97 -0
- package/dist/src/workspace/read-model/extensions/subagent.js +120 -0
- package/dist/src/workspace/read-model/scanners/agent-dir.d.ts +49 -0
- package/dist/src/workspace/read-model/scanners/agent-dir.js +180 -0
- package/dist/src/workspace/read-model/scanners/agent-root.d.ts +73 -0
- package/dist/src/workspace/read-model/scanners/agent-root.js +148 -0
- package/dist/src/workspace/read-model/scanners/agent-settings.d.ts +43 -0
- package/dist/src/workspace/read-model/scanners/agent-settings.js +54 -0
- package/dist/src/workspace/read-model/scanners/canonical-extensions.d.ts +48 -0
- package/dist/src/workspace/read-model/scanners/canonical-extensions.js +237 -0
- package/dist/src/workspace/read-model/scanners/fs-helpers.d.ts +63 -0
- package/dist/src/workspace/read-model/scanners/fs-helpers.js +106 -0
- package/dist/src/workspace/read-model/scanners/index.d.ts +15 -0
- package/dist/src/workspace/read-model/scanners/index.js +34 -0
- package/dist/src/workspace/read-model/scanners/mcp-config.d.ts +47 -0
- package/dist/src/workspace/read-model/scanners/mcp-config.js +212 -0
- package/dist/src/workspace/read-model/scanners/types.d.ts +170 -0
- package/dist/src/workspace/read-model/scanners/types.js +86 -0
- package/dist/src/workspace/read-model/service.d.ts +103 -0
- package/dist/src/workspace/read-model/service.js +391 -0
- package/dist/src/workspace/read-model/state.d.ts +35 -0
- package/dist/src/workspace/read-model/state.js +97 -0
- package/dist/src/workspace/read-model/types.d.ts +75 -0
- package/dist/src/workspace/read-model/types.js +26 -0
- package/dist/src/workspace/read-model-record-readers.d.ts +34 -0
- package/dist/src/workspace/read-model-record-readers.js +467 -0
- package/dist/src/workspace/read-model-record-rows.d.ts +45 -0
- package/dist/src/workspace/read-model-record-rows.js +33 -0
- package/dist/src/workspace/read-model-record-types.d.ts +45 -0
- package/dist/src/workspace/read-model-record-types.js +13 -0
- package/dist/src/workspace/remove-if-exists.d.ts +13 -0
- package/dist/src/workspace/remove-if-exists.js +26 -0
- package/dist/src/workspace/rendered-files.d.ts +53 -0
- package/dist/src/workspace/rendered-files.js +50 -0
- package/dist/src/workspace/scope-refusal.d.ts +26 -0
- package/dist/src/workspace/scope-refusal.js +29 -0
- package/dist/src/workspace/service-interface.d.ts +479 -0
- package/dist/src/workspace/service-interface.js +27 -0
- package/dist/src/workspace/service.d.ts +1665 -0
- package/dist/src/workspace/service.js +1263 -0
- package/dist/src/workspace/setup-scope-support.d.ts +27 -0
- package/dist/src/workspace/setup-scope-support.js +299 -0
- package/dist/src/workspace/skill-paths.d.ts +33 -0
- package/dist/src/workspace/skill-paths.js +14 -0
- package/dist/src/workspace/source-metadata.d.ts +7 -0
- package/dist/src/workspace/source-metadata.js +10 -0
- package/dist/src/workspace/source-to-lock-entry.d.ts +32 -0
- package/dist/src/workspace/source-to-lock-entry.js +68 -0
- package/dist/src/workspace/test-stubs.d.ts +144 -0
- package/dist/src/workspace/test-stubs.js +412 -0
- package/dist/src/workspace/transaction.d.ts +218 -0
- package/dist/src/workspace/transaction.js +177 -0
- package/package.json +57 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog-derived agent projections and the scoped agent read-model API.
|
|
3
|
+
*
|
|
4
|
+
* All agents share the same declared, actual, and detected projectors. The
|
|
5
|
+
* canonical capability catalog carries genuine per-agent variance, so adding
|
|
6
|
+
* an agent does not require a placeholder module or registry edit here.
|
|
7
|
+
*/
|
|
8
|
+
import * as Array from "effect/Array";
|
|
9
|
+
import * as Effect from "effect/Effect";
|
|
10
|
+
import * as Option from "effect/Option";
|
|
11
|
+
import { AGENTS } from "@agentxm/extension-model/unstable/agents/registry";
|
|
12
|
+
import { AGENT_IDS, CONFIGURABLE_AGENT_IDS, isConfigurableAgentId, } from "@agentxm/extension-model/unstable/agents/types";
|
|
13
|
+
import { defineAgentModule, } from "./types.js";
|
|
14
|
+
export { defineAgentModule } from "./types.js";
|
|
15
|
+
/** Every configurable catalog agent, in canonical order. */
|
|
16
|
+
export const registeredAgentModules = CONFIGURABLE_AGENT_IDS.map((agentId) => defineAgentModule({ agentId, descriptor: AGENTS[agentId] }));
|
|
17
|
+
/** Build the common projector module for one catalog agent. */
|
|
18
|
+
export const getAgentModule = (id) => defineAgentModule({ agentId: id, descriptor: AGENTS[id] });
|
|
19
|
+
const isAgentId = (id) => Object.hasOwn(AGENTS, id);
|
|
20
|
+
/** Build the agent portion of a scoped workspace read model. */
|
|
21
|
+
export const makeScopedAgentsApi = (deps) => {
|
|
22
|
+
const { scope, settings, presence, observations } = deps;
|
|
23
|
+
const declared = (id) => isConfigurableAgentId(id)
|
|
24
|
+
? settings.pipe(Effect.map((decoded) => getAgentModule(id).declared(scope, decoded)))
|
|
25
|
+
: Effect.succeed(Option.none());
|
|
26
|
+
const actual = (id) => isConfigurableAgentId(id)
|
|
27
|
+
? observations.pipe(Effect.map((obs) => getAgentModule(id).actual(scope, obs)))
|
|
28
|
+
: Effect.succeed(Option.none());
|
|
29
|
+
const detected = Effect.all([
|
|
30
|
+
Effect.result(settings).pipe(Effect.map((settingsResult) => settingsResult._tag === "Failure"
|
|
31
|
+
? Option.none()
|
|
32
|
+
: settingsResult.success)),
|
|
33
|
+
presence,
|
|
34
|
+
observations,
|
|
35
|
+
]).pipe(Effect.map(([decoded, presentAgentIds, obs]) => Array.getSomes(registeredAgentModules.map((module) => module.detected(scope, module.declared(scope, decoded), presentAgentIds.has(module.agentId), module.actual(scope, obs))))));
|
|
36
|
+
return {
|
|
37
|
+
list: Effect.succeed(AGENT_IDS),
|
|
38
|
+
known: Effect.succeed(AGENT_IDS.map((id) => AGENTS[id])),
|
|
39
|
+
byId: (id) => (isAgentId(id) ? Option.some(AGENTS[id]) : Option.none()),
|
|
40
|
+
declared,
|
|
41
|
+
actual,
|
|
42
|
+
detected,
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared default projectors used by every per-agent module.
|
|
3
|
+
*
|
|
4
|
+
* The default behavior captures the v1 contract:
|
|
5
|
+
*
|
|
6
|
+
* - `defaultDeclared(agentId, scope, settings)` — returns
|
|
7
|
+
* `Option.some(DeclaredAgent)` iff the decoded settings list the agent in
|
|
8
|
+
* its `agents` array. Pure function over already-decoded settings.
|
|
9
|
+
* - `defaultActual(agentId, scope, observations)` — returns
|
|
10
|
+
* `Option.some(ActualAgent)` iff at least one scanner observation refers to
|
|
11
|
+
* the agent. Combines agent-dir, agent-settings, and per-agent MCP-config
|
|
12
|
+
* evidence.
|
|
13
|
+
* - `defaultDetected(agentId, scope, declared, actual)` — combines the two
|
|
14
|
+
* into a `DetectedAgent` when at least one is present; returns
|
|
15
|
+
* `Option.none()` when both are absent (no evidence either way).
|
|
16
|
+
*
|
|
17
|
+
* Per-agent modules override these only if their native config requires
|
|
18
|
+
* agent-specific evidence rules. v1 modules all reuse these defaults.
|
|
19
|
+
*/
|
|
20
|
+
import * as Option from "effect/Option";
|
|
21
|
+
import type { AgentId } from "@agentxm/extension-model/unstable/agents/types";
|
|
22
|
+
import type { Scope } from "../types.js";
|
|
23
|
+
import type { ActualAgent, AgentScannerObservations, DeclaredAgent, DeclaredSettingsShape, DetectedAgent } from "./types.js";
|
|
24
|
+
export declare const defaultDeclared: (agentId: AgentId, scope: Scope, settings: Option.Option<DeclaredSettingsShape>) => Option.Option<DeclaredAgent>;
|
|
25
|
+
export declare const defaultActual: (agentId: AgentId, scope: Scope, observations: AgentScannerObservations) => Option.Option<ActualAgent>;
|
|
26
|
+
export declare const defaultDetected: (agentId: AgentId, scope: Scope, declared: Option.Option<DeclaredAgent>, present: boolean, actual: Option.Option<ActualAgent>) => Option.Option<DetectedAgent>;
|
|
27
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared default projectors used by every per-agent module.
|
|
3
|
+
*
|
|
4
|
+
* The default behavior captures the v1 contract:
|
|
5
|
+
*
|
|
6
|
+
* - `defaultDeclared(agentId, scope, settings)` — returns
|
|
7
|
+
* `Option.some(DeclaredAgent)` iff the decoded settings list the agent in
|
|
8
|
+
* its `agents` array. Pure function over already-decoded settings.
|
|
9
|
+
* - `defaultActual(agentId, scope, observations)` — returns
|
|
10
|
+
* `Option.some(ActualAgent)` iff at least one scanner observation refers to
|
|
11
|
+
* the agent. Combines agent-dir, agent-settings, and per-agent MCP-config
|
|
12
|
+
* evidence.
|
|
13
|
+
* - `defaultDetected(agentId, scope, declared, actual)` — combines the two
|
|
14
|
+
* into a `DetectedAgent` when at least one is present; returns
|
|
15
|
+
* `Option.none()` when both are absent (no evidence either way).
|
|
16
|
+
*
|
|
17
|
+
* Per-agent modules override these only if their native config requires
|
|
18
|
+
* agent-specific evidence rules. v1 modules all reuse these defaults.
|
|
19
|
+
*/
|
|
20
|
+
import * as Option from "effect/Option";
|
|
21
|
+
export const defaultDeclared = (agentId, scope, settings) => {
|
|
22
|
+
if (Option.isNone(settings))
|
|
23
|
+
return Option.none();
|
|
24
|
+
const declaredAgents = settings.value.agents ?? [];
|
|
25
|
+
if (!declaredAgents.includes(agentId))
|
|
26
|
+
return Option.none();
|
|
27
|
+
return Option.some({ scope, agentId });
|
|
28
|
+
};
|
|
29
|
+
export const defaultActual = (agentId, scope, observations) => {
|
|
30
|
+
const agentDir = observations.agentDir.filter((occ) => occ.agentId === agentId &&
|
|
31
|
+
(occ.readPathStatus === undefined || occ.readPathStatus === "primary"));
|
|
32
|
+
const agentSettings = observations.agentSettings.filter((occ) => occ.agentId === agentId);
|
|
33
|
+
const mcpConfig = observations.mcpConfig.filter((occ) => occ.surface._tag === "agent" && occ.surface.agentId === agentId);
|
|
34
|
+
if (agentDir.length === 0 && agentSettings.length === 0 && mcpConfig.length === 0) {
|
|
35
|
+
return Option.none();
|
|
36
|
+
}
|
|
37
|
+
return Option.some({
|
|
38
|
+
scope,
|
|
39
|
+
agentId,
|
|
40
|
+
agentDirOccurrences: agentDir,
|
|
41
|
+
agentSettingsOccurrences: agentSettings,
|
|
42
|
+
mcpConfigOccurrences: mcpConfig,
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
export const defaultDetected = (agentId, scope, declared, present, actual) => {
|
|
46
|
+
const isDeclared = Option.isSome(declared);
|
|
47
|
+
const status = isDeclared && present
|
|
48
|
+
? Option.some("managed-and-present")
|
|
49
|
+
: isDeclared
|
|
50
|
+
? Option.some("managed-not-present")
|
|
51
|
+
: present
|
|
52
|
+
? Option.some("unmanaged-present")
|
|
53
|
+
: Option.none();
|
|
54
|
+
return Option.map(status, (s) => ({
|
|
55
|
+
scope,
|
|
56
|
+
agentId,
|
|
57
|
+
status: s,
|
|
58
|
+
present,
|
|
59
|
+
declared,
|
|
60
|
+
actual,
|
|
61
|
+
}));
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared agent projection types used by the generated module registry.
|
|
3
|
+
*
|
|
4
|
+
* Per Decision 3 (agents have declared + actual only; no resolved layer) and
|
|
5
|
+
* Decision 4 (per-subject modules carry the genuine variance) of the
|
|
6
|
+
* workspace read-model design:
|
|
7
|
+
*
|
|
8
|
+
* - `DeclaredAgent` / `ActualAgent` / `DetectedAgent` are the per-agent
|
|
9
|
+
* payload shapes the projectors return through `Option`.
|
|
10
|
+
* - `AgentModule<TId>` is the common projector contract generated from the
|
|
11
|
+
* canonical agent catalog.
|
|
12
|
+
* - `AgentScannerObservations` is the input projector helpers consume from the
|
|
13
|
+
* live composition (Phase 9). It carries the agent-specific slice of scanner
|
|
14
|
+
* outputs — directly observable evidence that this agent has any presence in
|
|
15
|
+
* the workspace.
|
|
16
|
+
*
|
|
17
|
+
* `AgentSubjectType` mirrors `scanners/types.ts#AgentDirSubjectType` so the
|
|
18
|
+
* agent registry barrel does not need to import scanner types at runtime.
|
|
19
|
+
*/
|
|
20
|
+
import type * as Option from "effect/Option";
|
|
21
|
+
import type { AgentDescriptor, AgentId } from "@agentxm/extension-model/unstable/agents/types";
|
|
22
|
+
import type { AgentDirOccurrence, AgentSettingsOccurrence, McpConfigOccurrence } from "../scanners/types.js";
|
|
23
|
+
import type { Scope } from "../types.js";
|
|
24
|
+
/**
|
|
25
|
+
* Subject types renderable into per-agent directories. Mirrors the
|
|
26
|
+
* `AgentDirSubjectType` discriminator on the agent-dir scanner. Per-agent
|
|
27
|
+
* modules expose the subjects they support so the registry barrel can answer
|
|
28
|
+
* "which subjects does this agent render?" without re-scanning the agent
|
|
29
|
+
* registry.
|
|
30
|
+
*/
|
|
31
|
+
export type AgentSubjectType = "skill" | "subagent";
|
|
32
|
+
/**
|
|
33
|
+
* Settings-derived declaration of an agent for a given scope. Produced by the
|
|
34
|
+
* per-agent `declared(scope, settings)` projector when the scope's
|
|
35
|
+
* `axm.json` lists the agent in its `agents` array.
|
|
36
|
+
*/
|
|
37
|
+
export interface DeclaredAgent {
|
|
38
|
+
readonly scope: Scope;
|
|
39
|
+
readonly agentId: AgentId;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Observable per-agent evidence collected from scanner outputs. An agent is
|
|
43
|
+
* "actual present" in a scope if at least one scanner observation refers to
|
|
44
|
+
* that agent — agent-dir occurrences for any subject, an agent-settings file,
|
|
45
|
+
* or an agent MCP config. The projector collects the underlying observations
|
|
46
|
+
* so consumers can render diagnostic detail.
|
|
47
|
+
*
|
|
48
|
+
* The actual layer NEVER fails (Decision 1).
|
|
49
|
+
*/
|
|
50
|
+
export interface ActualAgent {
|
|
51
|
+
readonly scope: Scope;
|
|
52
|
+
readonly agentId: AgentId;
|
|
53
|
+
readonly agentDirOccurrences: ReadonlyArray<AgentDirOccurrence>;
|
|
54
|
+
readonly agentSettingsOccurrences: ReadonlyArray<AgentSettingsOccurrence>;
|
|
55
|
+
readonly mcpConfigOccurrences: ReadonlyArray<McpConfigOccurrence>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Classification of an agent by combining declared + actual evidence. The
|
|
59
|
+
* three values mirror today's "managed agent" / "unmanaged agent" / "missing"
|
|
60
|
+
* classifications used by `axm setup` and lint diagnostics.
|
|
61
|
+
*
|
|
62
|
+
* - `managed-and-present` — settings declares the agent AND scanners observed
|
|
63
|
+
* evidence in the workspace.
|
|
64
|
+
* - `managed-not-present` — settings declares the agent BUT no scanners
|
|
65
|
+
* observed evidence.
|
|
66
|
+
* - `unmanaged-present` — scanners observed evidence BUT settings does not
|
|
67
|
+
* declare the agent.
|
|
68
|
+
*
|
|
69
|
+
* Agents that are neither declared nor present are NOT included in the
|
|
70
|
+
* `detected` projection — there is nothing to surface for an agent the user
|
|
71
|
+
* has not interacted with.
|
|
72
|
+
*/
|
|
73
|
+
export type DetectionStatus = "managed-and-present" | "managed-not-present" | "unmanaged-present";
|
|
74
|
+
export interface DetectedAgent {
|
|
75
|
+
readonly scope: Scope;
|
|
76
|
+
readonly agentId: AgentId;
|
|
77
|
+
readonly status: DetectionStatus;
|
|
78
|
+
readonly present: boolean;
|
|
79
|
+
readonly declared: Option.Option<DeclaredAgent>;
|
|
80
|
+
readonly actual: Option.Option<ActualAgent>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Pre-filtered scanner observations for one agent. Phase 9's live composition
|
|
84
|
+
* narrows scanner outputs by `agentId` once and threads the result into each
|
|
85
|
+
* per-agent module's `actual` projector.
|
|
86
|
+
*
|
|
87
|
+
* Each array is the (possibly empty) sequence of observations for this agent
|
|
88
|
+
* within the same scope. Per design Decision 5, the actual layer concatenates
|
|
89
|
+
* scanner outputs — duplicates of the same physical occurrence are collapsed
|
|
90
|
+
* upstream by the scanner-occurrence-identity helper.
|
|
91
|
+
*/
|
|
92
|
+
export interface AgentScannerObservations {
|
|
93
|
+
readonly agentDir: ReadonlyArray<AgentDirOccurrence>;
|
|
94
|
+
readonly agentSettings: ReadonlyArray<AgentSettingsOccurrence>;
|
|
95
|
+
readonly mcpConfig: ReadonlyArray<McpConfigOccurrence>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Subset of decoded `axm.json` the agent `declared` projectors need.
|
|
99
|
+
* Phase 8 modules accept this narrowed shape so they can be unit-tested
|
|
100
|
+
* without depending on the full Settings schema.
|
|
101
|
+
*/
|
|
102
|
+
export interface DeclaredSettingsShape {
|
|
103
|
+
readonly agents?: ReadonlyArray<AgentId>;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Common projector contract for one catalog agent. Agent-specific native
|
|
107
|
+
* configuration belongs in the capability catalog, not phantom read-model
|
|
108
|
+
* types.
|
|
109
|
+
*/
|
|
110
|
+
export interface AgentModule<TId extends AgentId = AgentId> {
|
|
111
|
+
readonly agentId: TId;
|
|
112
|
+
readonly subjects: ReadonlyArray<AgentSubjectType>;
|
|
113
|
+
readonly declared: (scope: Scope, settings: Option.Option<DeclaredSettingsShape>) => Option.Option<DeclaredAgent>;
|
|
114
|
+
readonly actual: (scope: Scope, observations: AgentScannerObservations) => Option.Option<ActualAgent>;
|
|
115
|
+
readonly detected: (scope: Scope, declared: Option.Option<DeclaredAgent>, present: boolean, actual: Option.Option<ActualAgent>) => Option.Option<DetectedAgent>;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Inputs to `defineAgentModule`. The factory derives `subjects` from the
|
|
119
|
+
* descriptor so registration does not repeat scanner-relevant subject data.
|
|
120
|
+
*/
|
|
121
|
+
export interface DefineAgentModuleInput<TId extends AgentId> {
|
|
122
|
+
readonly agentId: TId;
|
|
123
|
+
readonly descriptor: AgentDescriptor;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Build a complete `AgentModule` for `agentId`. The projectors call the v1
|
|
127
|
+
* `defaultDeclared` / `defaultActual` / `defaultDetected` helpers from
|
|
128
|
+
* `shared.ts`. `subjects` is derived from `descriptor`.
|
|
129
|
+
*
|
|
130
|
+
* The registry creates these modules directly from the canonical catalog.
|
|
131
|
+
*/
|
|
132
|
+
export declare const defineAgentModule: <TId extends AgentId>(input: DefineAgentModuleInput<TId>) => AgentModule<TId>;
|
|
133
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared agent projection types used by the generated module registry.
|
|
3
|
+
*
|
|
4
|
+
* Per Decision 3 (agents have declared + actual only; no resolved layer) and
|
|
5
|
+
* Decision 4 (per-subject modules carry the genuine variance) of the
|
|
6
|
+
* workspace read-model design:
|
|
7
|
+
*
|
|
8
|
+
* - `DeclaredAgent` / `ActualAgent` / `DetectedAgent` are the per-agent
|
|
9
|
+
* payload shapes the projectors return through `Option`.
|
|
10
|
+
* - `AgentModule<TId>` is the common projector contract generated from the
|
|
11
|
+
* canonical agent catalog.
|
|
12
|
+
* - `AgentScannerObservations` is the input projector helpers consume from the
|
|
13
|
+
* live composition (Phase 9). It carries the agent-specific slice of scanner
|
|
14
|
+
* outputs — directly observable evidence that this agent has any presence in
|
|
15
|
+
* the workspace.
|
|
16
|
+
*
|
|
17
|
+
* `AgentSubjectType` mirrors `scanners/types.ts#AgentDirSubjectType` so the
|
|
18
|
+
* agent registry barrel does not need to import scanner types at runtime.
|
|
19
|
+
*/
|
|
20
|
+
import { defaultActual, defaultDeclared, defaultDetected } from "./shared.js";
|
|
21
|
+
/**
|
|
22
|
+
* Derive the subjects the agent renders into per-agent directories from its
|
|
23
|
+
* descriptor.
|
|
24
|
+
*/
|
|
25
|
+
const subjectsFromDescriptor = (descriptor) => {
|
|
26
|
+
const out = [];
|
|
27
|
+
if (descriptor.skills !== undefined)
|
|
28
|
+
out.push("skill");
|
|
29
|
+
if (descriptor.subagents !== undefined)
|
|
30
|
+
out.push("subagent");
|
|
31
|
+
return out;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Build a complete `AgentModule` for `agentId`. The projectors call the v1
|
|
35
|
+
* `defaultDeclared` / `defaultActual` / `defaultDetected` helpers from
|
|
36
|
+
* `shared.ts`. `subjects` is derived from `descriptor`.
|
|
37
|
+
*
|
|
38
|
+
* The registry creates these modules directly from the canonical catalog.
|
|
39
|
+
*/
|
|
40
|
+
export const defineAgentModule = (input) => {
|
|
41
|
+
const { agentId, descriptor } = input;
|
|
42
|
+
const subjects = subjectsFromDescriptor(descriptor);
|
|
43
|
+
return {
|
|
44
|
+
agentId,
|
|
45
|
+
subjects,
|
|
46
|
+
declared: (scope, settings) => defaultDeclared(agentId, scope, settings),
|
|
47
|
+
actual: (scope, observations) => defaultActual(agentId, scope, observations),
|
|
48
|
+
detected: (scope, declared, present, actual) => defaultDetected(agentId, scope, declared, present, actual),
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Per-scope append-only diagnostics buffer for settings/lockfile/scanner warnings. */
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Ref from "effect/Ref";
|
|
4
|
+
/** A degraded-state observation surfaced through a scoped diagnostics buffer. */
|
|
5
|
+
export interface Warning {
|
|
6
|
+
readonly source: "settings" | "lockfile" | "scanner";
|
|
7
|
+
readonly message: string;
|
|
8
|
+
readonly path?: string;
|
|
9
|
+
readonly code?: string;
|
|
10
|
+
}
|
|
11
|
+
/** Append-only, snapshot-readable warning buffer for one scoped workspace read model. */
|
|
12
|
+
export interface Diagnostics {
|
|
13
|
+
readonly append: (warning: Warning) => Effect.Effect<void>;
|
|
14
|
+
readonly snapshot: Effect.Effect<ReadonlyArray<Warning>>;
|
|
15
|
+
}
|
|
16
|
+
/** Build a `Diagnostics` helper around a caller-owned `Ref<ReadonlyArray<Warning>>`. */
|
|
17
|
+
export declare const makeDiagnostics: (ref: Ref.Ref<ReadonlyArray<Warning>>) => Diagnostics;
|
|
18
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Per-scope append-only diagnostics buffer for settings/lockfile/scanner warnings. */
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Ref from "effect/Ref";
|
|
4
|
+
/** Build a `Diagnostics` helper around a caller-owned `Ref<ReadonlyArray<Warning>>`. */
|
|
5
|
+
export const makeDiagnostics = (ref) => ({
|
|
6
|
+
append: Effect.fn("workspace.read-model.diagnostics.append")(function* (warning) {
|
|
7
|
+
yield* Ref.update(ref, (current) => [...current, warning]);
|
|
8
|
+
}),
|
|
9
|
+
snapshot: Effect.gen(function* () {
|
|
10
|
+
const current = yield* Ref.get(ref);
|
|
11
|
+
return current;
|
|
12
|
+
}).pipe(Effect.withSpan("workspace.read-model.diagnostics.snapshot")),
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Discovery helpers that operate on arbitrary source directories. */
|
|
2
|
+
export { getPriorityDirectories, skillsInDir, type DiscoveredSkill, type DiscoveryOptions, } from "./skills.js";
|
|
3
|
+
export { parsePluginManifests } from "./plugin-manifests.js";
|
|
4
|
+
export { scanAgentSubagentFiles, scanAllSubagentFiles, type AgentSubagentSummary, type DetectedSubagentFile, } from "./subagents.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Discovery helpers that operate on arbitrary source directories. */
|
|
2
|
+
export { getPriorityDirectories, skillsInDir, } from "./skills.js";
|
|
3
|
+
export { parsePluginManifests } from "./plugin-manifests.js";
|
|
4
|
+
export { scanAgentSubagentFiles, scanAllSubagentFiles, } from "./subagents.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin manifest parsing for skill discovery.
|
|
3
|
+
*
|
|
4
|
+
* Parses .claude-plugin/marketplace.json and .claude-plugin/plugin.json
|
|
5
|
+
* to discover explicitly declared skill directories.
|
|
6
|
+
*/
|
|
7
|
+
import * as FileSystem from "effect/FileSystem";
|
|
8
|
+
import * as Path from "effect/Path";
|
|
9
|
+
import * as Effect from "effect/Effect";
|
|
10
|
+
/**
|
|
11
|
+
* Parse plugin manifests and return validated skill parent directories.
|
|
12
|
+
* All paths are validated to be within basePath.
|
|
13
|
+
* Errors are silently skipped (returns empty array on failure).
|
|
14
|
+
*/
|
|
15
|
+
export declare const parsePluginManifests: (basePath: string) => Effect.Effect<ReadonlyArray<string>, never, FileSystem.FileSystem | Path.Path>;
|
|
16
|
+
//# sourceMappingURL=plugin-manifests.d.ts.map
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin manifest parsing for skill discovery.
|
|
3
|
+
*
|
|
4
|
+
* Parses .claude-plugin/marketplace.json and .claude-plugin/plugin.json
|
|
5
|
+
* to discover explicitly declared skill directories.
|
|
6
|
+
*/
|
|
7
|
+
import * as FileSystem from "effect/FileSystem";
|
|
8
|
+
import * as Path from "effect/Path";
|
|
9
|
+
import * as Array from "effect/Array";
|
|
10
|
+
import * as Effect from "effect/Effect";
|
|
11
|
+
import * as Option from "effect/Option";
|
|
12
|
+
import * as Result from "effect/Result";
|
|
13
|
+
import * as Schema from "effect/Schema";
|
|
14
|
+
// -----------------------------------------------------------------------------
|
|
15
|
+
// Path Validation
|
|
16
|
+
// -----------------------------------------------------------------------------
|
|
17
|
+
const RelativeManifestPathSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((input) => {
|
|
18
|
+
if (!input.startsWith("./"))
|
|
19
|
+
return "Expected a relative manifest path starting with ./";
|
|
20
|
+
if (input.includes(".."))
|
|
21
|
+
return "Manifest paths must not contain .. segments";
|
|
22
|
+
return undefined;
|
|
23
|
+
})));
|
|
24
|
+
const decodeRelativeManifestPath = Schema.decodeUnknownResult(RelativeManifestPathSchema);
|
|
25
|
+
/**
|
|
26
|
+
* Validate a raw skill path from a manifest.
|
|
27
|
+
* Must start with `./`, must not contain `..`, and must resolve within basePath.
|
|
28
|
+
* Returns the parent directory of the skill path on success.
|
|
29
|
+
*/
|
|
30
|
+
const validatePath = (rawPath, basePath, path) => {
|
|
31
|
+
if (Result.isFailure(decodeRelativeManifestPath(rawPath)))
|
|
32
|
+
return Option.none();
|
|
33
|
+
// Resolve and check within basePath
|
|
34
|
+
const resolved = path.resolve(basePath, rawPath);
|
|
35
|
+
const normalizedBase = path.resolve(basePath);
|
|
36
|
+
if (!resolved.startsWith(normalizedBase + path.sep) && resolved !== normalizedBase) {
|
|
37
|
+
return Option.none();
|
|
38
|
+
}
|
|
39
|
+
// Return parent directory of the skill path
|
|
40
|
+
return Option.some(path.dirname(resolved));
|
|
41
|
+
};
|
|
42
|
+
// -----------------------------------------------------------------------------
|
|
43
|
+
// Manifest Parsers
|
|
44
|
+
// -----------------------------------------------------------------------------
|
|
45
|
+
const MarketplacePlugin = Schema.Struct({
|
|
46
|
+
source: Schema.optional(Schema.Unknown),
|
|
47
|
+
skills: Schema.optional(Schema.Array(Schema.String)),
|
|
48
|
+
});
|
|
49
|
+
const MarketplaceManifest = Schema.Struct({
|
|
50
|
+
metadata: Schema.optional(Schema.Struct({ pluginRoot: Schema.optional(Schema.String) })),
|
|
51
|
+
plugins: Schema.Array(MarketplacePlugin),
|
|
52
|
+
});
|
|
53
|
+
const PluginManifest = Schema.Struct({
|
|
54
|
+
skills: Schema.Array(Schema.String),
|
|
55
|
+
});
|
|
56
|
+
/**
|
|
57
|
+
* Read a file and parse as JSON, returning None on any failure.
|
|
58
|
+
*/
|
|
59
|
+
const readDecodedJsonFile = (filePath, schema) => Effect.gen(function* () {
|
|
60
|
+
const fs = yield* FileSystem.FileSystem;
|
|
61
|
+
const content = yield* fs.readFileString(filePath).pipe(Effect.option);
|
|
62
|
+
if (Option.isNone(content))
|
|
63
|
+
return Option.none();
|
|
64
|
+
const decode = Schema.decodeUnknownSync(Schema.fromJsonString(schema));
|
|
65
|
+
return yield* Effect.sync(() => {
|
|
66
|
+
try {
|
|
67
|
+
return Option.some(decode(content.value));
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return Option.none();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* Validate a directory path from a manifest (not a skill path — no dirname).
|
|
76
|
+
* Must start with `./`, must not contain `..`, and must resolve within basePath.
|
|
77
|
+
* Returns the resolved directory path on success.
|
|
78
|
+
*/
|
|
79
|
+
const validateDirPath = (rawPath, basePath, path) => {
|
|
80
|
+
if (Result.isFailure(decodeRelativeManifestPath(rawPath)))
|
|
81
|
+
return Option.none();
|
|
82
|
+
const resolved = path.resolve(basePath, rawPath);
|
|
83
|
+
const normalizedBase = path.resolve(basePath);
|
|
84
|
+
if (!resolved.startsWith(normalizedBase + path.sep) && resolved !== normalizedBase) {
|
|
85
|
+
return Option.none();
|
|
86
|
+
}
|
|
87
|
+
return Option.some(resolved);
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Resolve a plugin's base directory from its source field and pluginRoot.
|
|
91
|
+
* - string source: must start with `./`, resolve relative to basePath + pluginRoot
|
|
92
|
+
* - omitted source: resolve to basePath + pluginRoot (or basePath if no pluginRoot)
|
|
93
|
+
* - object source: skip (remote plugin)
|
|
94
|
+
*/
|
|
95
|
+
const resolvePluginBase = (source, basePath, pluginRoot, path) => {
|
|
96
|
+
const rootBase = pluginRoot ? path.resolve(basePath, pluginRoot) : path.resolve(basePath);
|
|
97
|
+
// Object source → skip plugin
|
|
98
|
+
if (typeof source === "object" && source !== null)
|
|
99
|
+
return Option.none();
|
|
100
|
+
if (typeof source === "string") {
|
|
101
|
+
return validateDirPath(source, rootBase, path);
|
|
102
|
+
}
|
|
103
|
+
// Omitted source → root-level plugin
|
|
104
|
+
return Option.some(rootBase);
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Parse .claude-plugin/marketplace.json and return validated skill parent directories.
|
|
108
|
+
*
|
|
109
|
+
* Supports metadata.pluginRoot, per-plugin source (string/omitted/object),
|
|
110
|
+
* per-plugin skills array, and conventional {pluginBase}/skills/ directory.
|
|
111
|
+
*/
|
|
112
|
+
const parseMarketplaceJson = (basePath) => Effect.gen(function* () {
|
|
113
|
+
const path = yield* Path.Path;
|
|
114
|
+
const manifestPath = path.join(basePath, ".claude-plugin", "marketplace.json");
|
|
115
|
+
const data = yield* readDecodedJsonFile(manifestPath, MarketplaceManifest);
|
|
116
|
+
if (Option.isNone(data))
|
|
117
|
+
return [];
|
|
118
|
+
const pluginRoot = data.value.metadata?.pluginRoot;
|
|
119
|
+
if (pluginRoot !== undefined && Result.isFailure(decodeRelativeManifestPath(pluginRoot))) {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
return data.value.plugins.flatMap((plugin) => {
|
|
123
|
+
const pluginBase = resolvePluginBase(plugin.source, basePath, pluginRoot, path);
|
|
124
|
+
if (Option.isNone(pluginBase))
|
|
125
|
+
return [];
|
|
126
|
+
// Conventional {pluginBase}/skills/ always added
|
|
127
|
+
const conventional = [path.join(pluginBase.value, "skills")];
|
|
128
|
+
// Explicit skill paths transformed via dirname
|
|
129
|
+
const explicit = (plugin.skills ?? []).flatMap((skillPath) => {
|
|
130
|
+
const validated = validatePath(skillPath, pluginBase.value, path);
|
|
131
|
+
return Option.isSome(validated) ? [validated.value] : [];
|
|
132
|
+
});
|
|
133
|
+
return [...conventional, ...explicit];
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
/**
|
|
137
|
+
* Parse .claude-plugin/plugin.json and return validated skill parent directories.
|
|
138
|
+
*
|
|
139
|
+
* Expected shape: { skills: string[] }
|
|
140
|
+
*/
|
|
141
|
+
const parsePluginJson = (basePath) => Effect.gen(function* () {
|
|
142
|
+
const path = yield* Path.Path;
|
|
143
|
+
const manifestPath = path.join(basePath, ".claude-plugin", "plugin.json");
|
|
144
|
+
const data = yield* readDecodedJsonFile(manifestPath, PluginManifest);
|
|
145
|
+
if (Option.isNone(data))
|
|
146
|
+
return [];
|
|
147
|
+
const validatedPaths = [];
|
|
148
|
+
for (const skillPath of data.value.skills) {
|
|
149
|
+
const validated = validatePath(skillPath, basePath, path);
|
|
150
|
+
if (Option.isSome(validated)) {
|
|
151
|
+
validatedPaths.push(validated.value);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return validatedPaths;
|
|
155
|
+
});
|
|
156
|
+
// -----------------------------------------------------------------------------
|
|
157
|
+
// Public API
|
|
158
|
+
// -----------------------------------------------------------------------------
|
|
159
|
+
/**
|
|
160
|
+
* Parse plugin manifests and return validated skill parent directories.
|
|
161
|
+
* All paths are validated to be within basePath.
|
|
162
|
+
* Errors are silently skipped (returns empty array on failure).
|
|
163
|
+
*/
|
|
164
|
+
export const parsePluginManifests = (basePath) => Effect.gen(function* () {
|
|
165
|
+
const [marketplaceDirs, pluginDirs] = yield* Effect.all([parseMarketplaceJson(basePath), parsePluginJson(basePath)], { concurrency: "unbounded" });
|
|
166
|
+
return Array.dedupe([...marketplaceDirs, ...pluginDirs]);
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=plugin-manifests.js.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill discovery algorithm (3-phase: direct match, priority scan, recursive fallback).
|
|
3
|
+
*
|
|
4
|
+
* The `skillsInDir` function is used by source providers (local, git-hosting)
|
|
5
|
+
* to discover skills within a directory structure.
|
|
6
|
+
*
|
|
7
|
+
* @experimental This API is unstable and may change without notice.
|
|
8
|
+
*/
|
|
9
|
+
import * as FileSystem from "effect/FileSystem";
|
|
10
|
+
import * as Path from "effect/Path";
|
|
11
|
+
import type { Skill } from "@agentxm/registry-protocol/unstable/content/skill-types";
|
|
12
|
+
import * as Effect from "effect/Effect";
|
|
13
|
+
import * as Option from "effect/Option";
|
|
14
|
+
import { SkillDiscoveryRootInvalid } from "../errors.js";
|
|
15
|
+
/**
|
|
16
|
+
* A discovered skill — intermediate result from directory scanning.
|
|
17
|
+
*
|
|
18
|
+
* Does not carry source, version, or gitTreeSha — the caller (provider)
|
|
19
|
+
* enriches with those after discovery.
|
|
20
|
+
*/
|
|
21
|
+
export interface DiscoveredSkill {
|
|
22
|
+
readonly type: "skill";
|
|
23
|
+
readonly skill: Skill;
|
|
24
|
+
/** file:// URL to the skill directory */
|
|
25
|
+
readonly location: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Options controlling discovery behavior.
|
|
29
|
+
*/
|
|
30
|
+
export interface DiscoveryOptions {
|
|
31
|
+
/** Exhaustive recursive search even if root skill found */
|
|
32
|
+
readonly fullDepth: boolean;
|
|
33
|
+
/** Include skills with metadata.internal: "true" */
|
|
34
|
+
readonly includeInternal: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Derive the full Phase 2 priority directory list.
|
|
38
|
+
*
|
|
39
|
+
* Composition:
|
|
40
|
+
* 1. `.` (searchPath root) — always first, highest priority
|
|
41
|
+
* 2. Non-agent static dirs: skills, skills/.curated, skills/.experimental, skills/.system
|
|
42
|
+
* 3. Agent dirs: unique primary and additional read paths from the AgentDescriptor registry
|
|
43
|
+
*/
|
|
44
|
+
export declare const getPriorityDirectories: () => ReadonlyArray<string>;
|
|
45
|
+
/**
|
|
46
|
+
* Discover skills in a directory using a 3-phase algorithm:
|
|
47
|
+
*
|
|
48
|
+
* Phase 1 — Direct match: check if search root itself contains SKILL.md
|
|
49
|
+
* Phase 2 — Priority directory scan: scan well-known directories one level deep
|
|
50
|
+
* Phase 3 — Recursive fallback: bounded DFS when prior phases find nothing or fullDepth is true
|
|
51
|
+
*
|
|
52
|
+
* Skills are deduplicated by name (first-found wins). Internal skills are
|
|
53
|
+
* filtered unless opted in.
|
|
54
|
+
*
|
|
55
|
+
* @experimental This API is unstable and may change without notice.
|
|
56
|
+
*/
|
|
57
|
+
export declare const skillsInDir: (basePath: string, subPath: Option.Option<string>, options: DiscoveryOptions) => Effect.Effect<ReadonlyArray<DiscoveredSkill>, SkillDiscoveryRootInvalid, FileSystem.FileSystem | Path.Path>;
|
|
58
|
+
//# sourceMappingURL=skills.d.ts.map
|