@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,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill subject module: declared/resolved/actual payload types, scanner
|
|
3
|
+
* composition, and projections via the shared `projectInstalledExtensions`
|
|
4
|
+
* helper.
|
|
5
|
+
*
|
|
6
|
+
* Per Decision 4 (single service + per-subject modules) and Decision 9
|
|
7
|
+
* (read-model rows) of the workspace read-model design, this module owns:
|
|
8
|
+
*
|
|
9
|
+
* - the subject-specific declared/resolved/actual payload types
|
|
10
|
+
* (`DeclaredSkills`, `ResolvedSkills`, `ActualSkills`);
|
|
11
|
+
* - the subject-specific origin union (`SkillDetectionOrigin`) and
|
|
12
|
+
* skill-specific facts (`contentRoot`, `sourcePath`, `packageRoot`,
|
|
13
|
+
* `hasSkillMd`, `hasSkillJson`);
|
|
14
|
+
* - scanner composition (canonical-extensions + agent-dir × skill-rendering
|
|
15
|
+
* agents);
|
|
16
|
+
* - the `installed` / `active` / `unmanaged` projections, wired
|
|
17
|
+
* through the helper with a skill-specific `SubjectPolicy`.
|
|
18
|
+
*
|
|
19
|
+
* The factory `makeSkillExtensionsApi(deps)` returns a `SkillExtensionsApi`
|
|
20
|
+
* with cells whose public types are dependency-closed. Phase 9 composes the
|
|
21
|
+
* factory inputs (`loaders`, `scanners`, `installedPacks`, `diagnostics`)
|
|
22
|
+
* inside `WorkspaceReadModelLive`.
|
|
23
|
+
*/
|
|
24
|
+
import * as Effect from "effect/Effect";
|
|
25
|
+
import * as Option from "effect/Option";
|
|
26
|
+
import type { AgentId } from "@agentxm/extension-model/unstable/agents/types";
|
|
27
|
+
import { type ExtensionName } from "@agentxm/extension-model/unstable/extensions/common";
|
|
28
|
+
import type { Lockfile, SkillLockEntry } from "../../../lockfile/schema.js";
|
|
29
|
+
import type { Settings, SkillEntry } from "../../../settings/schema.js";
|
|
30
|
+
import type { Diagnostics } from "../diagnostics.js";
|
|
31
|
+
import type { LockfileReadError, SettingsReadError } from "../errors.js";
|
|
32
|
+
import type { AgentDirOccurrence, CanonicalExtensionOccurrence } from "../scanners/types.js";
|
|
33
|
+
import type { ActivationState, ExtensionKey, InstallationOrigin, InstalledPackRef, Scope } from "../types.js";
|
|
34
|
+
/**
|
|
35
|
+
* Subject-specific origin discriminator for an `ActualSkill`. Mirrors the spec
|
|
36
|
+
* scenarios that distinguish canonical AXM, external AXM, and agent-rendered
|
|
37
|
+
* skill directories.
|
|
38
|
+
*/
|
|
39
|
+
export type SkillDetectionOrigin = {
|
|
40
|
+
readonly _tag: "canonical-axm-skill";
|
|
41
|
+
} | {
|
|
42
|
+
readonly _tag: "external-axm-skill";
|
|
43
|
+
} | {
|
|
44
|
+
readonly _tag: "agent-skill-dir";
|
|
45
|
+
readonly agentId: AgentId;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* One declared skill entry. Wraps the raw settings entry without re-shaping
|
|
49
|
+
* fields; `name` is lifted out for ergonomic lookup.
|
|
50
|
+
*/
|
|
51
|
+
export interface DeclaredSkill {
|
|
52
|
+
readonly name: ExtensionName;
|
|
53
|
+
readonly entry: SkillEntry;
|
|
54
|
+
}
|
|
55
|
+
/** Decoded skills declared in `axm.json`. */
|
|
56
|
+
export type DeclaredSkills = ReadonlyArray<DeclaredSkill>;
|
|
57
|
+
/** One resolved skill entry from the lockfile, wrapping the raw lock entry. */
|
|
58
|
+
export interface ResolvedSkill {
|
|
59
|
+
readonly name: ExtensionName;
|
|
60
|
+
readonly lockEntry: SkillLockEntry;
|
|
61
|
+
}
|
|
62
|
+
/** Decoded skills resolved in the lockfile. */
|
|
63
|
+
export type ResolvedSkills = ReadonlyArray<ResolvedSkill>;
|
|
64
|
+
/**
|
|
65
|
+
* One observable skill materialization. Carries the subject-specific origin
|
|
66
|
+
* plus skill-specific facts:
|
|
67
|
+
*
|
|
68
|
+
* - `contentRoot` — the directory containing the rendered skill (the same
|
|
69
|
+
* value as the underlying scanner's `contentLocation`);
|
|
70
|
+
* - `sourcePath` — absolute path to the canonical content file inside
|
|
71
|
+
* `contentRoot` (`SKILL.md`); equal to `null` if the file does not exist;
|
|
72
|
+
* - `packageRoot` — for canonical/external AXM, the registry-publish package
|
|
73
|
+
* root (parent of `src/<name>/`); `null` for agent-rendered skills;
|
|
74
|
+
* - `hasSkillMd` — convenience boolean derived from `sourcePath`;
|
|
75
|
+
* - `hasSkillJson` — placeholder for the optional `skill.json` companion file
|
|
76
|
+
* (left `false` in v1; Phase 9 wiring will flip when `agent-settings` or a
|
|
77
|
+
* future scanner detects it).
|
|
78
|
+
*/
|
|
79
|
+
export interface ActualSkill {
|
|
80
|
+
readonly key: ExtensionKey<"skill">;
|
|
81
|
+
readonly origin: SkillDetectionOrigin;
|
|
82
|
+
readonly contentRoot: string;
|
|
83
|
+
readonly sourcePath: string | null;
|
|
84
|
+
readonly packageRoot: string | null;
|
|
85
|
+
readonly hasSkillMd: boolean;
|
|
86
|
+
readonly hasSkillJson: boolean;
|
|
87
|
+
}
|
|
88
|
+
/** Actual skills payload — array of observed materialization occurrences. */
|
|
89
|
+
export type ActualSkills = ReadonlyArray<ActualSkill>;
|
|
90
|
+
/** Pack-member entry for a skill: per Decision 9 it is the resolved member. */
|
|
91
|
+
export interface SkillPackMember {
|
|
92
|
+
readonly name: ExtensionName;
|
|
93
|
+
readonly providingPack: InstalledPackRef;
|
|
94
|
+
}
|
|
95
|
+
/** Installed skill row. */
|
|
96
|
+
export interface InstalledSkill {
|
|
97
|
+
readonly key: ExtensionKey<"skill">;
|
|
98
|
+
readonly installationOrigin: InstallationOrigin<DeclaredSkill, SkillPackMember>;
|
|
99
|
+
readonly activation: ActivationState;
|
|
100
|
+
readonly resolved: Option.Option<ResolvedSkill>;
|
|
101
|
+
readonly actual: ReadonlyArray<ActualSkill>;
|
|
102
|
+
readonly providingPacks: ReadonlyArray<InstalledPackRef>;
|
|
103
|
+
}
|
|
104
|
+
/** Unmanaged skill row — one actual occurrence not attached to an installed row. */
|
|
105
|
+
export interface UnmanagedSkill {
|
|
106
|
+
readonly key: ExtensionKey<"skill">;
|
|
107
|
+
readonly actual: ActualSkill;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Cached source loaders the factory captures. `Effect.cached` is applied at
|
|
111
|
+
* the loader site (Phase 4); the helper just consumes whatever shape the
|
|
112
|
+
* caller passes in.
|
|
113
|
+
*/
|
|
114
|
+
export interface SkillScopedLoaders {
|
|
115
|
+
readonly settings: Effect.Effect<Option.Option<Settings>, SettingsReadError>;
|
|
116
|
+
readonly lockfile: Effect.Effect<Option.Option<Lockfile>, LockfileReadError>;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Cached scanner outputs the factory captures. The factory composes
|
|
120
|
+
* canonical-extensions + agent-dir occurrences into the actual skill array.
|
|
121
|
+
*/
|
|
122
|
+
export interface SkillScanners {
|
|
123
|
+
readonly canonical: Effect.Effect<ReadonlyArray<CanonicalExtensionOccurrence>>;
|
|
124
|
+
readonly agentDir: Effect.Effect<ReadonlyArray<AgentDirOccurrence>>;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* One installed-pack entry consumed by the projection. Pack-resolved member
|
|
128
|
+
* groups are read from the **installed pack manifest** in Phase 9; for unit
|
|
129
|
+
* tests the caller passes a synthetic shape.
|
|
130
|
+
*/
|
|
131
|
+
export interface InstalledPackForSkills {
|
|
132
|
+
readonly ref: InstalledPackRef;
|
|
133
|
+
readonly skills: ReadonlyArray<SkillPackMember>;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Inputs `makeSkillExtensionsApi` captures.
|
|
137
|
+
*/
|
|
138
|
+
export interface SkillExtensionsApiDeps {
|
|
139
|
+
readonly scope: Scope;
|
|
140
|
+
readonly loaders: SkillScopedLoaders;
|
|
141
|
+
readonly scanners: SkillScanners;
|
|
142
|
+
readonly installedPacks: Effect.Effect<ReadonlyArray<InstalledPackForSkills>, SettingsReadError | LockfileReadError>;
|
|
143
|
+
readonly diagnostics: Diagnostics;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Public skill API exposed by `ctx.scope(scope).skills`. Cells are
|
|
147
|
+
* dependency-closed and never carry `FileSystem | Path` requirements.
|
|
148
|
+
*/
|
|
149
|
+
export interface SkillExtensionsApi {
|
|
150
|
+
readonly declared: Effect.Effect<Option.Option<DeclaredSkills>, SettingsReadError>;
|
|
151
|
+
readonly resolved: Effect.Effect<Option.Option<ResolvedSkills>, LockfileReadError>;
|
|
152
|
+
readonly actual: Effect.Effect<ActualSkills>;
|
|
153
|
+
readonly installed: Effect.Effect<ReadonlyArray<InstalledSkill>, SettingsReadError | LockfileReadError>;
|
|
154
|
+
readonly byName: (name: string) => Effect.Effect<Option.Option<InstalledSkill>, SettingsReadError | LockfileReadError>;
|
|
155
|
+
readonly declaredByName: (name: string) => Effect.Effect<Option.Option<DeclaredSkill>, SettingsReadError>;
|
|
156
|
+
readonly active: Effect.Effect<ReadonlyArray<InstalledSkill>, SettingsReadError | LockfileReadError>;
|
|
157
|
+
readonly unmanaged: Effect.Effect<ReadonlyArray<UnmanagedSkill>, SettingsReadError | LockfileReadError>;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Build the skill subject API over the captured loaders, scanners, and pack
|
|
161
|
+
* set.
|
|
162
|
+
*
|
|
163
|
+
* Returns an `Effect` because the projection cell is wrapped in
|
|
164
|
+
* `Effect.cached` so all four derived cells (`installed` / `active` /
|
|
165
|
+
* `unmanaged`) share a single in-flight execution and the
|
|
166
|
+
* projection — including its diagnostic side effects — runs at most once per
|
|
167
|
+
* scope, mirroring the `state.ts` loader pattern.
|
|
168
|
+
*/
|
|
169
|
+
export declare const makeSkillExtensionsApi: (deps: SkillExtensionsApiDeps) => Effect.Effect<SkillExtensionsApi>;
|
|
170
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill subject module: declared/resolved/actual payload types, scanner
|
|
3
|
+
* composition, and projections via the shared `projectInstalledExtensions`
|
|
4
|
+
* helper.
|
|
5
|
+
*
|
|
6
|
+
* Per Decision 4 (single service + per-subject modules) and Decision 9
|
|
7
|
+
* (read-model rows) of the workspace read-model design, this module owns:
|
|
8
|
+
*
|
|
9
|
+
* - the subject-specific declared/resolved/actual payload types
|
|
10
|
+
* (`DeclaredSkills`, `ResolvedSkills`, `ActualSkills`);
|
|
11
|
+
* - the subject-specific origin union (`SkillDetectionOrigin`) and
|
|
12
|
+
* skill-specific facts (`contentRoot`, `sourcePath`, `packageRoot`,
|
|
13
|
+
* `hasSkillMd`, `hasSkillJson`);
|
|
14
|
+
* - scanner composition (canonical-extensions + agent-dir × skill-rendering
|
|
15
|
+
* agents);
|
|
16
|
+
* - the `installed` / `active` / `unmanaged` projections, wired
|
|
17
|
+
* through the helper with a skill-specific `SubjectPolicy`.
|
|
18
|
+
*
|
|
19
|
+
* The factory `makeSkillExtensionsApi(deps)` returns a `SkillExtensionsApi`
|
|
20
|
+
* with cells whose public types are dependency-closed. Phase 9 composes the
|
|
21
|
+
* factory inputs (`loaders`, `scanners`, `installedPacks`, `diagnostics`)
|
|
22
|
+
* inside `WorkspaceReadModelLive`.
|
|
23
|
+
*/
|
|
24
|
+
import * as Effect from "effect/Effect";
|
|
25
|
+
import * as Option from "effect/Option";
|
|
26
|
+
import { decodeExtensionNameSync, } from "@agentxm/extension-model/unstable/extensions/common";
|
|
27
|
+
import { filterMapOccurrences } from "./actual-helpers.js";
|
|
28
|
+
import { canonicalAxmPackageRoot } from "./package-root.js";
|
|
29
|
+
import { makeProjectedSubjectCells, projectInstalledExtensions, } from "./projection.js";
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Helpers — declared / resolved / actual normalization
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
const declaredFromSettings = (settings) => {
|
|
34
|
+
if (settings.skills === undefined)
|
|
35
|
+
return [];
|
|
36
|
+
return Object.entries(settings.skills).map(([name, entry]) => ({
|
|
37
|
+
name: decodeExtensionNameSync(name),
|
|
38
|
+
entry,
|
|
39
|
+
}));
|
|
40
|
+
};
|
|
41
|
+
const resolvedFromLockfile = (lockfile) => {
|
|
42
|
+
if (lockfile.skills === undefined)
|
|
43
|
+
return [];
|
|
44
|
+
return Object.entries(lockfile.skills).map(([name, lockEntry]) => ({
|
|
45
|
+
name: decodeExtensionNameSync(name),
|
|
46
|
+
lockEntry,
|
|
47
|
+
}));
|
|
48
|
+
};
|
|
49
|
+
const canonicalToActualSkill = (occ, scope) => {
|
|
50
|
+
const isExternal = occ.origin === "external-axm";
|
|
51
|
+
// canonical-axm contentLocation ends in `<package>/src` for authored and
|
|
52
|
+
// owner-qualified packages; external-axm contentLocation is the legacy
|
|
53
|
+
// user-scope external package root.
|
|
54
|
+
const packageRoot = canonicalAxmPackageRoot(occ);
|
|
55
|
+
return {
|
|
56
|
+
key: { scope, type: "skill", name: occ.name },
|
|
57
|
+
origin: isExternal ? { _tag: "external-axm-skill" } : { _tag: "canonical-axm-skill" },
|
|
58
|
+
contentRoot: occ.contentLocation,
|
|
59
|
+
sourcePath: Option.getOrNull(occ.subjectFile),
|
|
60
|
+
packageRoot,
|
|
61
|
+
hasSkillMd: occ.subjectFileExists,
|
|
62
|
+
// Scanner does not probe `skill.json` yet; keep `false` until a future
|
|
63
|
+
// scanner emission carries it.
|
|
64
|
+
hasSkillJson: false,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
const agentDirToActualSkill = (occ, scope) => ({
|
|
68
|
+
key: { scope, type: "skill", name: occ.name },
|
|
69
|
+
origin: { _tag: "agent-skill-dir", agentId: occ.agentId },
|
|
70
|
+
contentRoot: occ.contentLocation,
|
|
71
|
+
sourcePath: Option.getOrNull(occ.subjectFile),
|
|
72
|
+
packageRoot: null,
|
|
73
|
+
hasSkillMd: occ.subjectFileExists,
|
|
74
|
+
// Scanner does not probe `skill.json` yet; keep `false` until a future
|
|
75
|
+
// scanner emission carries it.
|
|
76
|
+
hasSkillJson: false,
|
|
77
|
+
});
|
|
78
|
+
const simpleName = (name) => name;
|
|
79
|
+
const orphanResolvedWarning = (name) => ({
|
|
80
|
+
source: "lockfile",
|
|
81
|
+
message: `skill: lockfile entry "${name}" has no matching declared or pack-member home`,
|
|
82
|
+
code: "orphan-resolved",
|
|
83
|
+
});
|
|
84
|
+
const skillPolicy = (scope) => ({
|
|
85
|
+
declaredEntries: (declared) => declared,
|
|
86
|
+
declaredName: (entry) => entry.name,
|
|
87
|
+
declaredActivation: (entry) => (entry.entry.enabled ? "enabled" : "disabled"),
|
|
88
|
+
resolvedEntries: (resolved) => resolved,
|
|
89
|
+
resolvedName: (entry) => simpleName(entry.name),
|
|
90
|
+
actualEntries: (actual) => actual,
|
|
91
|
+
actualName: (entry) => entry.key.name,
|
|
92
|
+
packMemberName: (member) => simpleName(member.name),
|
|
93
|
+
packMemberActivation: () => "enabled",
|
|
94
|
+
attachActualToInstalled: (name, actual) => actual.filter((a) => a.key.name === name),
|
|
95
|
+
notClaimedBySubjectPolicy: () => true,
|
|
96
|
+
buildInstalledRow: (input) => ({
|
|
97
|
+
key: { scope, type: "skill", name: input.name },
|
|
98
|
+
installationOrigin: input.installationOrigin,
|
|
99
|
+
activation: input.activation,
|
|
100
|
+
resolved: input.resolved,
|
|
101
|
+
actual: input.actual,
|
|
102
|
+
providingPacks: input.providingPacks,
|
|
103
|
+
}),
|
|
104
|
+
buildUnmanagedRow: (entry) => ({
|
|
105
|
+
key: { scope, type: "skill", name: entry.key.name },
|
|
106
|
+
actual: entry,
|
|
107
|
+
}),
|
|
108
|
+
resolvedOrphanWarning: orphanResolvedWarning,
|
|
109
|
+
});
|
|
110
|
+
/**
|
|
111
|
+
* Build the skill subject API over the captured loaders, scanners, and pack
|
|
112
|
+
* set.
|
|
113
|
+
*
|
|
114
|
+
* Returns an `Effect` because the projection cell is wrapped in
|
|
115
|
+
* `Effect.cached` so all four derived cells (`installed` / `active` /
|
|
116
|
+
* `unmanaged`) share a single in-flight execution and the
|
|
117
|
+
* projection — including its diagnostic side effects — runs at most once per
|
|
118
|
+
* scope, mirroring the `state.ts` loader pattern.
|
|
119
|
+
*/
|
|
120
|
+
export const makeSkillExtensionsApi = (deps) => Effect.gen(function* () {
|
|
121
|
+
const { scope, loaders, scanners, installedPacks, diagnostics } = deps;
|
|
122
|
+
const declared = loaders.settings.pipe(Effect.map((opt) => Option.map(opt, (settings) => declaredFromSettings(settings))));
|
|
123
|
+
const resolved = loaders.lockfile.pipe(Effect.map((opt) => Option.map(opt, (lockfile) => resolvedFromLockfile(lockfile))));
|
|
124
|
+
const actual = Effect.gen(function* () {
|
|
125
|
+
const canonical = yield* scanners.canonical;
|
|
126
|
+
const agentDir = yield* scanners.agentDir;
|
|
127
|
+
const fromCanonical = filterMapOccurrences(canonical, "skill", (occ) => canonicalToActualSkill(occ, scope));
|
|
128
|
+
const fromAgentDir = filterMapOccurrences(agentDir, "skill", (occ) => agentDirToActualSkill(occ, scope));
|
|
129
|
+
return [...fromCanonical, ...fromAgentDir];
|
|
130
|
+
});
|
|
131
|
+
const project = yield* Effect.cached(projectInstalledExtensions({
|
|
132
|
+
declared,
|
|
133
|
+
resolved,
|
|
134
|
+
actual,
|
|
135
|
+
installedPacks: installedPacks.pipe(Effect.map((packs) => packs.map((p) => ({ ref: p.ref, members: p.skills })))),
|
|
136
|
+
packMembers: (pack) => pack.members,
|
|
137
|
+
packRef: (pack) => pack.ref,
|
|
138
|
+
policy: skillPolicy(scope),
|
|
139
|
+
diagnostics,
|
|
140
|
+
}));
|
|
141
|
+
return makeProjectedSubjectCells({
|
|
142
|
+
declared,
|
|
143
|
+
resolved,
|
|
144
|
+
actual,
|
|
145
|
+
project,
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagent subject module: declared/resolved/actual payloads, scanner
|
|
3
|
+
* composition (canonical-extensions + agent-dir × subagent-rendering agents),
|
|
4
|
+
* and projections via the shared helper.
|
|
5
|
+
*
|
|
6
|
+
* Activation comes from the declared `enabled` flag, mirroring skills and
|
|
7
|
+
* commands. Single-file subagent surfaces (e.g., `roo`'s `.roomodes`) emit
|
|
8
|
+
* one occurrence per file path; the file itself is the materialization.
|
|
9
|
+
*/
|
|
10
|
+
import * as Effect from "effect/Effect";
|
|
11
|
+
import * as Option from "effect/Option";
|
|
12
|
+
import type { AgentId } from "@agentxm/extension-model/unstable/agents/types";
|
|
13
|
+
import { type ExtensionName } from "@agentxm/extension-model/unstable/extensions/common";
|
|
14
|
+
import type { Lockfile, SubagentLockEntry } from "../../../lockfile/schema.js";
|
|
15
|
+
import type { Settings, SubagentEntry } from "../../../settings/schema.js";
|
|
16
|
+
import type { Diagnostics } from "../diagnostics.js";
|
|
17
|
+
import type { LockfileReadError, SettingsReadError } from "../errors.js";
|
|
18
|
+
import type { AgentDirOccurrence, CanonicalExtensionOccurrence } from "../scanners/types.js";
|
|
19
|
+
import type { ActivationState, ExtensionKey, InstallationOrigin, InstalledPackRef, Scope } from "../types.js";
|
|
20
|
+
export type SubagentDetectionOrigin = {
|
|
21
|
+
readonly _tag: "canonical-axm-subagent";
|
|
22
|
+
} | {
|
|
23
|
+
readonly _tag: "external-axm-subagent";
|
|
24
|
+
} | {
|
|
25
|
+
readonly _tag: "agent-subagent-dir";
|
|
26
|
+
readonly agentId: AgentId;
|
|
27
|
+
};
|
|
28
|
+
export interface DeclaredSubagent {
|
|
29
|
+
readonly name: ExtensionName;
|
|
30
|
+
readonly entry: SubagentEntry;
|
|
31
|
+
}
|
|
32
|
+
export type DeclaredSubagents = ReadonlyArray<DeclaredSubagent>;
|
|
33
|
+
export interface ResolvedSubagent {
|
|
34
|
+
readonly name: ExtensionName;
|
|
35
|
+
readonly lockEntry: SubagentLockEntry;
|
|
36
|
+
}
|
|
37
|
+
export type ResolvedSubagents = ReadonlyArray<ResolvedSubagent>;
|
|
38
|
+
export interface ActualSubagent {
|
|
39
|
+
readonly key: ExtensionKey<"subagent">;
|
|
40
|
+
readonly origin: SubagentDetectionOrigin;
|
|
41
|
+
readonly contentRoot: string;
|
|
42
|
+
readonly sourcePath: string | null;
|
|
43
|
+
readonly packageRoot: string | null;
|
|
44
|
+
}
|
|
45
|
+
export type ActualSubagents = ReadonlyArray<ActualSubagent>;
|
|
46
|
+
export interface SubagentPackMember {
|
|
47
|
+
readonly name: ExtensionName;
|
|
48
|
+
readonly providingPack: InstalledPackRef;
|
|
49
|
+
}
|
|
50
|
+
export interface InstalledSubagent {
|
|
51
|
+
readonly key: ExtensionKey<"subagent">;
|
|
52
|
+
readonly installationOrigin: InstallationOrigin<DeclaredSubagent, SubagentPackMember>;
|
|
53
|
+
readonly activation: ActivationState;
|
|
54
|
+
readonly resolved: Option.Option<ResolvedSubagent>;
|
|
55
|
+
readonly actual: ReadonlyArray<ActualSubagent>;
|
|
56
|
+
readonly providingPacks: ReadonlyArray<InstalledPackRef>;
|
|
57
|
+
}
|
|
58
|
+
export interface UnmanagedSubagent {
|
|
59
|
+
readonly key: ExtensionKey<"subagent">;
|
|
60
|
+
readonly actual: ActualSubagent;
|
|
61
|
+
}
|
|
62
|
+
export interface SubagentScopedLoaders {
|
|
63
|
+
readonly settings: Effect.Effect<Option.Option<Settings>, SettingsReadError>;
|
|
64
|
+
readonly lockfile: Effect.Effect<Option.Option<Lockfile>, LockfileReadError>;
|
|
65
|
+
}
|
|
66
|
+
export interface SubagentScanners {
|
|
67
|
+
readonly canonical: Effect.Effect<ReadonlyArray<CanonicalExtensionOccurrence>>;
|
|
68
|
+
readonly agentDir: Effect.Effect<ReadonlyArray<AgentDirOccurrence>>;
|
|
69
|
+
}
|
|
70
|
+
export interface InstalledPackForSubagents {
|
|
71
|
+
readonly ref: InstalledPackRef;
|
|
72
|
+
readonly subagents: ReadonlyArray<SubagentPackMember>;
|
|
73
|
+
}
|
|
74
|
+
export interface SubagentExtensionsApiDeps {
|
|
75
|
+
readonly scope: Scope;
|
|
76
|
+
readonly loaders: SubagentScopedLoaders;
|
|
77
|
+
readonly scanners: SubagentScanners;
|
|
78
|
+
readonly installedPacks: Effect.Effect<ReadonlyArray<InstalledPackForSubagents>, SettingsReadError | LockfileReadError>;
|
|
79
|
+
readonly diagnostics: Diagnostics;
|
|
80
|
+
}
|
|
81
|
+
export interface SubagentExtensionsApi {
|
|
82
|
+
readonly declared: Effect.Effect<Option.Option<DeclaredSubagents>, SettingsReadError>;
|
|
83
|
+
readonly resolved: Effect.Effect<Option.Option<ResolvedSubagents>, LockfileReadError>;
|
|
84
|
+
readonly actual: Effect.Effect<ActualSubagents>;
|
|
85
|
+
readonly installed: Effect.Effect<ReadonlyArray<InstalledSubagent>, SettingsReadError | LockfileReadError>;
|
|
86
|
+
readonly byName: (name: string) => Effect.Effect<Option.Option<InstalledSubagent>, SettingsReadError | LockfileReadError>;
|
|
87
|
+
readonly declaredByName: (name: string) => Effect.Effect<Option.Option<DeclaredSubagent>, SettingsReadError>;
|
|
88
|
+
readonly active: Effect.Effect<ReadonlyArray<InstalledSubagent>, SettingsReadError | LockfileReadError>;
|
|
89
|
+
readonly unmanaged: Effect.Effect<ReadonlyArray<UnmanagedSubagent>, SettingsReadError | LockfileReadError>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build the subagent subject API. Returns an `Effect` because the projection
|
|
93
|
+
* cell is wrapped in `Effect.cached` so the four derived cells share one
|
|
94
|
+
* in-flight execution per scope, mirroring `state.ts`.
|
|
95
|
+
*/
|
|
96
|
+
export declare const makeSubagentExtensionsApi: (deps: SubagentExtensionsApiDeps) => Effect.Effect<SubagentExtensionsApi>;
|
|
97
|
+
//# sourceMappingURL=subagent.d.ts.map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagent subject module: declared/resolved/actual payloads, scanner
|
|
3
|
+
* composition (canonical-extensions + agent-dir × subagent-rendering agents),
|
|
4
|
+
* and projections via the shared helper.
|
|
5
|
+
*
|
|
6
|
+
* Activation comes from the declared `enabled` flag, mirroring skills and
|
|
7
|
+
* commands. Single-file subagent surfaces (e.g., `roo`'s `.roomodes`) emit
|
|
8
|
+
* one occurrence per file path; the file itself is the materialization.
|
|
9
|
+
*/
|
|
10
|
+
import * as Effect from "effect/Effect";
|
|
11
|
+
import * as Option from "effect/Option";
|
|
12
|
+
import { decodeExtensionNameSync, } from "@agentxm/extension-model/unstable/extensions/common";
|
|
13
|
+
import { filterMapOccurrences } from "./actual-helpers.js";
|
|
14
|
+
import { canonicalAxmPackageRoot } from "./package-root.js";
|
|
15
|
+
import { makeProjectedSubjectCells, projectInstalledExtensions, } from "./projection.js";
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Helpers
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
const declaredFromSettings = (settings) => {
|
|
20
|
+
if (settings.subagents === undefined)
|
|
21
|
+
return [];
|
|
22
|
+
return Object.entries(settings.subagents).map(([name, entry]) => ({
|
|
23
|
+
name: decodeExtensionNameSync(name),
|
|
24
|
+
entry,
|
|
25
|
+
}));
|
|
26
|
+
};
|
|
27
|
+
const resolvedFromLockfile = (lockfile) => {
|
|
28
|
+
if (lockfile.subagents === undefined)
|
|
29
|
+
return [];
|
|
30
|
+
return Object.entries(lockfile.subagents).map(([name, lockEntry]) => ({
|
|
31
|
+
name: decodeExtensionNameSync(name),
|
|
32
|
+
lockEntry,
|
|
33
|
+
}));
|
|
34
|
+
};
|
|
35
|
+
const canonicalToActual = (occ, scope) => {
|
|
36
|
+
const isExternal = occ.origin === "external-axm";
|
|
37
|
+
const packageRoot = canonicalAxmPackageRoot(occ);
|
|
38
|
+
return {
|
|
39
|
+
key: { scope, type: "subagent", name: occ.name },
|
|
40
|
+
origin: isExternal ? { _tag: "external-axm-subagent" } : { _tag: "canonical-axm-subagent" },
|
|
41
|
+
contentRoot: occ.contentLocation,
|
|
42
|
+
sourcePath: Option.getOrNull(occ.subjectFile),
|
|
43
|
+
packageRoot,
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
const agentDirToActual = (occ, scope) => ({
|
|
47
|
+
key: { scope, type: "subagent", name: occ.name },
|
|
48
|
+
origin: { _tag: "agent-subagent-dir", agentId: occ.agentId },
|
|
49
|
+
contentRoot: occ.contentLocation,
|
|
50
|
+
// For directory-style subagents the scanner emits `<dir>/${name}.md`; for
|
|
51
|
+
// single-file surfaces (e.g., `.roomodes`) the scanner emits the file path
|
|
52
|
+
// itself. Either way `subjectFile` is `Some` for agent-dir subagent occs.
|
|
53
|
+
sourcePath: Option.getOrNull(occ.subjectFile),
|
|
54
|
+
packageRoot: null,
|
|
55
|
+
});
|
|
56
|
+
const orphanResolvedWarning = (name) => ({
|
|
57
|
+
source: "lockfile",
|
|
58
|
+
message: `subagent: lockfile entry "${name}" has no matching declared or pack-member home`,
|
|
59
|
+
code: "orphan-resolved",
|
|
60
|
+
});
|
|
61
|
+
const subagentPolicy = (scope) => ({
|
|
62
|
+
declaredEntries: (d) => d,
|
|
63
|
+
declaredName: (e) => e.name,
|
|
64
|
+
declaredActivation: (e) => (e.entry.enabled ? "enabled" : "disabled"),
|
|
65
|
+
resolvedEntries: (r) => r,
|
|
66
|
+
resolvedName: (e) => e.name,
|
|
67
|
+
actualEntries: (a) => a,
|
|
68
|
+
actualName: (e) => e.key.name,
|
|
69
|
+
packMemberName: (m) => m.name,
|
|
70
|
+
packMemberActivation: () => "enabled",
|
|
71
|
+
attachActualToInstalled: (name, actual) => actual.filter((a) => a.key.name === name),
|
|
72
|
+
notClaimedBySubjectPolicy: () => true,
|
|
73
|
+
buildInstalledRow: (input) => ({
|
|
74
|
+
key: { scope, type: "subagent", name: input.name },
|
|
75
|
+
installationOrigin: input.installationOrigin,
|
|
76
|
+
activation: input.activation,
|
|
77
|
+
resolved: input.resolved,
|
|
78
|
+
actual: input.actual,
|
|
79
|
+
providingPacks: input.providingPacks,
|
|
80
|
+
}),
|
|
81
|
+
buildUnmanagedRow: (entry) => ({
|
|
82
|
+
key: { scope, type: "subagent", name: entry.key.name },
|
|
83
|
+
actual: entry,
|
|
84
|
+
}),
|
|
85
|
+
resolvedOrphanWarning: orphanResolvedWarning,
|
|
86
|
+
});
|
|
87
|
+
/**
|
|
88
|
+
* Build the subagent subject API. Returns an `Effect` because the projection
|
|
89
|
+
* cell is wrapped in `Effect.cached` so the four derived cells share one
|
|
90
|
+
* in-flight execution per scope, mirroring `state.ts`.
|
|
91
|
+
*/
|
|
92
|
+
export const makeSubagentExtensionsApi = (deps) => Effect.gen(function* () {
|
|
93
|
+
const { scope, loaders, scanners, installedPacks, diagnostics } = deps;
|
|
94
|
+
const declared = loaders.settings.pipe(Effect.map((opt) => Option.map(opt, declaredFromSettings)));
|
|
95
|
+
const resolved = loaders.lockfile.pipe(Effect.map((opt) => Option.map(opt, resolvedFromLockfile)));
|
|
96
|
+
const actual = Effect.gen(function* () {
|
|
97
|
+
const canonical = yield* scanners.canonical;
|
|
98
|
+
const agentDir = yield* scanners.agentDir;
|
|
99
|
+
const fromCanonical = filterMapOccurrences(canonical, "subagent", (occ) => canonicalToActual(occ, scope));
|
|
100
|
+
const fromAgentDir = filterMapOccurrences(agentDir, "subagent", (occ) => agentDirToActual(occ, scope));
|
|
101
|
+
return [...fromCanonical, ...fromAgentDir];
|
|
102
|
+
});
|
|
103
|
+
const project = yield* Effect.cached(projectInstalledExtensions({
|
|
104
|
+
declared,
|
|
105
|
+
resolved,
|
|
106
|
+
actual,
|
|
107
|
+
installedPacks: installedPacks.pipe(Effect.map((packs) => packs.map((p) => ({ ref: p.ref, members: p.subagents })))),
|
|
108
|
+
packMembers: (pack) => pack.members,
|
|
109
|
+
packRef: (pack) => pack.ref,
|
|
110
|
+
policy: subagentPolicy(scope),
|
|
111
|
+
diagnostics,
|
|
112
|
+
}));
|
|
113
|
+
return makeProjectedSubjectCells({
|
|
114
|
+
declared,
|
|
115
|
+
resolved,
|
|
116
|
+
actual,
|
|
117
|
+
project,
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
//# sourceMappingURL=subagent.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-directory scanner: enumerates per-agent skill and subagent
|
|
3
|
+
* directories declared by the existing `AgentRegistry`. Each occurrence
|
|
4
|
+
* carries an `agent-dir` discriminator parameterized by `agentId` and the
|
|
5
|
+
* subject `type`.
|
|
6
|
+
*
|
|
7
|
+
* Subject coverage in v1:
|
|
8
|
+
*
|
|
9
|
+
* - skill — every agent with a non-empty `agent.skills.dir`.
|
|
10
|
+
* - subagent — every agent with `agent.subagents?.dir`. Single-file
|
|
11
|
+
* subagent surfaces (`isFile === true`, e.g., `roo`'s `.roomodes`) emit one
|
|
12
|
+
* occurrence per file path; the file itself is the materialization.
|
|
13
|
+
*
|
|
14
|
+
* Rules: no agent in the v1 `AgentRegistry` exposes a rules directory, so the
|
|
15
|
+
* scanner emits no rule occurrences.
|
|
16
|
+
*
|
|
17
|
+
* Each occurrence carries structural fields the subject modules need for
|
|
18
|
+
* cross-platform path handling — `pathSegments` (the absolute path split via
|
|
19
|
+
* the `Path` service) and `subjectFile` (the canonical primary file inside
|
|
20
|
+
* the subject directory) — plus a probed `subjectFileExists` flag so subject
|
|
21
|
+
* modules do not hardcode presence.
|
|
22
|
+
*
|
|
23
|
+
* Per Decision 5, scanner output is occurrence-shaped. The public effect
|
|
24
|
+
* carries no `FileSystem | Path` requirement; per-file partial failures
|
|
25
|
+
* publish diagnostic warnings rather than failing the cell.
|
|
26
|
+
*
|
|
27
|
+
* The scanner avoids `fs.stat` and uses only `fs.exists` / `fs.readDirectory`
|
|
28
|
+
* so it remains compatible with the fixture builder's in-memory `FileSystem`.
|
|
29
|
+
*/
|
|
30
|
+
import * as Effect from "effect/Effect";
|
|
31
|
+
import type * as FileSystem from "effect/FileSystem";
|
|
32
|
+
import type * as Path from "effect/Path";
|
|
33
|
+
import type { AgentDescriptor, AgentId } from "@agentxm/extension-model/unstable/agents/types";
|
|
34
|
+
import type { Diagnostics } from "../diagnostics.js";
|
|
35
|
+
import type { Scope } from "../types.js";
|
|
36
|
+
import type { AgentDirOccurrence } from "./types.js";
|
|
37
|
+
export interface AgentDirScannerDeps {
|
|
38
|
+
readonly fs: FileSystem.FileSystem;
|
|
39
|
+
readonly path: Path.Path;
|
|
40
|
+
readonly workspaceRoot: string;
|
|
41
|
+
readonly scope: Scope;
|
|
42
|
+
readonly diagnostics: Diagnostics;
|
|
43
|
+
readonly agentRegistry?: Readonly<Partial<Record<AgentId, AgentDescriptor>>>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Closure helper: returns the dependency-closed scanner effect.
|
|
47
|
+
*/
|
|
48
|
+
export declare const makeAgentDirScanner: (deps: AgentDirScannerDeps) => Effect.Effect<ReadonlyArray<AgentDirOccurrence>>;
|
|
49
|
+
//# sourceMappingURL=agent-dir.d.ts.map
|