@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.
Files changed (215) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +11 -0
  3. package/dist/src/index.d.ts +72 -0
  4. package/dist/src/index.js +88 -0
  5. package/dist/src/knowledge/discovery-config.d.ts +12 -0
  6. package/dist/src/knowledge/discovery-config.js +9 -0
  7. package/dist/src/lockfile/accepted-registry-version.d.ts +12 -0
  8. package/dist/src/lockfile/accepted-registry-version.js +13 -0
  9. package/dist/src/lockfile/entry-fields.d.ts +189 -0
  10. package/dist/src/lockfile/entry-fields.js +89 -0
  11. package/dist/src/lockfile/errors.d.ts +48 -0
  12. package/dist/src/lockfile/errors.js +27 -0
  13. package/dist/src/lockfile/index.d.ts +18 -0
  14. package/dist/src/lockfile/index.js +16 -0
  15. package/dist/src/lockfile/lockfile.d.ts +2255 -0
  16. package/dist/src/lockfile/lockfile.js +235 -0
  17. package/dist/src/lockfile/resolved-version.d.ts +4 -0
  18. package/dist/src/lockfile/resolved-version.js +7 -0
  19. package/dist/src/lockfile/schema.d.ts +3062 -0
  20. package/dist/src/lockfile/schema.js +406 -0
  21. package/dist/src/schema/index.d.ts +3 -0
  22. package/dist/src/schema/index.js +2 -0
  23. package/dist/src/schema/read-and-validate-json-file.d.ts +20 -0
  24. package/dist/src/schema/read-and-validate-json-file.js +85 -0
  25. package/dist/src/schema/types.d.ts +26 -0
  26. package/dist/src/schema/types.js +2 -0
  27. package/dist/src/settings/errors.d.ts +22 -0
  28. package/dist/src/settings/errors.js +15 -0
  29. package/dist/src/settings/format-preserving-json.d.ts +40 -0
  30. package/dist/src/settings/format-preserving-json.js +80 -0
  31. package/dist/src/settings/index.d.ts +15 -0
  32. package/dist/src/settings/index.js +14 -0
  33. package/dist/src/settings/schema.d.ts +687 -0
  34. package/dist/src/settings/schema.js +977 -0
  35. package/dist/src/settings/settings.d.ts +38 -0
  36. package/dist/src/settings/settings.js +213 -0
  37. package/dist/src/testing.d.ts +17 -0
  38. package/dist/src/testing.js +17 -0
  39. package/dist/src/utils/atomic-write.d.ts +67 -0
  40. package/dist/src/utils/atomic-write.js +71 -0
  41. package/dist/src/utils/environment.d.ts +16 -0
  42. package/dist/src/utils/environment.js +19 -0
  43. package/dist/src/utils/path-safety.d.ts +25 -0
  44. package/dist/src/utils/path-safety.js +34 -0
  45. package/dist/src/utils/resolve-parent-symlinks.d.ts +16 -0
  46. package/dist/src/utils/resolve-parent-symlinks.js +36 -0
  47. package/dist/src/workspace/accepted-canonical-ref.d.ts +58 -0
  48. package/dist/src/workspace/accepted-canonical-ref.js +229 -0
  49. package/dist/src/workspace/artifact-change.d.ts +14 -0
  50. package/dist/src/workspace/artifact-change.js +18 -0
  51. package/dist/src/workspace/canonical-observation.d.ts +39 -0
  52. package/dist/src/workspace/canonical-observation.js +307 -0
  53. package/dist/src/workspace/configured-agent-outcome.d.ts +22 -0
  54. package/dist/src/workspace/configured-agent-outcome.js +33 -0
  55. package/dist/src/workspace/configured-agent-outcomes-provider.d.ts +50 -0
  56. package/dist/src/workspace/configured-agent-outcomes-provider.js +26 -0
  57. package/dist/src/workspace/configured-agent-outcomes.d.ts +48 -0
  58. package/dist/src/workspace/configured-agent-outcomes.js +113 -0
  59. package/dist/src/workspace/configured-entry-resolution/types.d.ts +32 -0
  60. package/dist/src/workspace/configured-entry-resolution/types.js +2 -0
  61. package/dist/src/workspace/configured-entry-resolution/workspace-ref.d.ts +32 -0
  62. package/dist/src/workspace/configured-entry-resolution/workspace-ref.js +176 -0
  63. package/dist/src/workspace/constants.d.ts +6 -0
  64. package/dist/src/workspace/constants.js +6 -0
  65. package/dist/src/workspace/create-symlink.d.ts +26 -0
  66. package/dist/src/workspace/create-symlink.js +87 -0
  67. package/dist/src/workspace/desired-pack-lock.d.ts +18 -0
  68. package/dist/src/workspace/desired-pack-lock.js +132 -0
  69. package/dist/src/workspace/desired-state-enabled.d.ts +18 -0
  70. package/dist/src/workspace/desired-state-enabled.js +16 -0
  71. package/dist/src/workspace/desired-state-graph.d.ts +114 -0
  72. package/dist/src/workspace/desired-state-graph.js +384 -0
  73. package/dist/src/workspace/desired-state-problem-text.d.ts +6 -0
  74. package/dist/src/workspace/desired-state-problem-text.js +27 -0
  75. package/dist/src/workspace/errors.d.ts +184 -0
  76. package/dist/src/workspace/errors.js +79 -0
  77. package/dist/src/workspace/extension-name.d.ts +28 -0
  78. package/dist/src/workspace/extension-name.js +66 -0
  79. package/dist/src/workspace/extension-paths.d.ts +82 -0
  80. package/dist/src/workspace/extension-paths.js +172 -0
  81. package/dist/src/workspace/footprint-recorder.d.ts +30 -0
  82. package/dist/src/workspace/footprint-recorder.js +32 -0
  83. package/dist/src/workspace/layout.d.ts +43 -0
  84. package/dist/src/workspace/layout.js +164 -0
  85. package/dist/src/workspace/lock-entry-to-ref.d.ts +40 -0
  86. package/dist/src/workspace/lock-entry-to-ref.js +433 -0
  87. package/dist/src/workspace/lock-entry-to-source-params.d.ts +26 -0
  88. package/dist/src/workspace/lock-entry-to-source-params.js +81 -0
  89. package/dist/src/workspace/locked-entries.d.ts +30 -0
  90. package/dist/src/workspace/locked-entries.js +34 -0
  91. package/dist/src/workspace/materialized-file-target.d.ts +14 -0
  92. package/dist/src/workspace/materialized-file-target.js +14 -0
  93. package/dist/src/workspace/materialized-tree.d.ts +23 -0
  94. package/dist/src/workspace/materialized-tree.js +90 -0
  95. package/dist/src/workspace/mcp-entry-semantics.d.ts +31 -0
  96. package/dist/src/workspace/mcp-entry-semantics.js +60 -0
  97. package/dist/src/workspace/observed-installed.d.ts +9 -0
  98. package/dist/src/workspace/observed-installed.js +9 -0
  99. package/dist/src/workspace/pack-manifest-content-identity.d.ts +12 -0
  100. package/dist/src/workspace/pack-manifest-content-identity.js +20 -0
  101. package/dist/src/workspace/pack-paths.d.ts +24 -0
  102. package/dist/src/workspace/pack-paths.js +16 -0
  103. package/dist/src/workspace/package-hash.d.ts +25 -0
  104. package/dist/src/workspace/package-hash.js +45 -0
  105. package/dist/src/workspace/paths.d.ts +24 -0
  106. package/dist/src/workspace/paths.js +52 -0
  107. package/dist/src/workspace/read-model/__fixtures__/builder.d.ts +199 -0
  108. package/dist/src/workspace/read-model/__fixtures__/builder.js +588 -0
  109. package/dist/src/workspace/read-model/__fixtures__/decoders.d.ts +15 -0
  110. package/dist/src/workspace/read-model/__fixtures__/decoders.js +15 -0
  111. package/dist/src/workspace/read-model/__fixtures__/occurrences.d.ts +72 -0
  112. package/dist/src/workspace/read-model/__fixtures__/occurrences.js +134 -0
  113. package/dist/src/workspace/read-model/__fixtures__/scenario-harness.d.ts +99 -0
  114. package/dist/src/workspace/read-model/__fixtures__/scenario-harness.js +142 -0
  115. package/dist/src/workspace/read-model/__fixtures__/test-layer.d.ts +60 -0
  116. package/dist/src/workspace/read-model/__fixtures__/test-layer.js +57 -0
  117. package/dist/src/workspace/read-model/agent-presence.d.ts +32 -0
  118. package/dist/src/workspace/read-model/agent-presence.js +21 -0
  119. package/dist/src/workspace/read-model/agent-root-resolver.d.ts +38 -0
  120. package/dist/src/workspace/read-model/agent-root-resolver.js +35 -0
  121. package/dist/src/workspace/read-model/agents/index.d.ts +38 -0
  122. package/dist/src/workspace/read-model/agents/index.js +45 -0
  123. package/dist/src/workspace/read-model/agents/shared.d.ts +27 -0
  124. package/dist/src/workspace/read-model/agents/shared.js +63 -0
  125. package/dist/src/workspace/read-model/agents/types.d.ts +133 -0
  126. package/dist/src/workspace/read-model/agents/types.js +51 -0
  127. package/dist/src/workspace/read-model/diagnostics.d.ts +18 -0
  128. package/dist/src/workspace/read-model/diagnostics.js +14 -0
  129. package/dist/src/workspace/read-model/discovery/index.d.ts +5 -0
  130. package/dist/src/workspace/read-model/discovery/index.js +5 -0
  131. package/dist/src/workspace/read-model/discovery/plugin-manifests.d.ts +16 -0
  132. package/dist/src/workspace/read-model/discovery/plugin-manifests.js +168 -0
  133. package/dist/src/workspace/read-model/discovery/skills.d.ts +58 -0
  134. package/dist/src/workspace/read-model/discovery/skills.js +263 -0
  135. package/dist/src/workspace/read-model/discovery/subagents.d.ts +37 -0
  136. package/dist/src/workspace/read-model/discovery/subagents.js +48 -0
  137. package/dist/src/workspace/read-model/errors.d.ts +93 -0
  138. package/dist/src/workspace/read-model/errors.js +30 -0
  139. package/dist/src/workspace/read-model/extensions/actual-helpers.d.ts +4 -0
  140. package/dist/src/workspace/read-model/extensions/actual-helpers.js +4 -0
  141. package/dist/src/workspace/read-model/extensions/hook.d.ts +104 -0
  142. package/dist/src/workspace/read-model/extensions/hook.js +119 -0
  143. package/dist/src/workspace/read-model/extensions/index.d.ts +19 -0
  144. package/dist/src/workspace/read-model/extensions/index.js +43 -0
  145. package/dist/src/workspace/read-model/extensions/indexByName.d.ts +31 -0
  146. package/dist/src/workspace/read-model/extensions/indexByName.js +30 -0
  147. package/dist/src/workspace/read-model/extensions/inventory.d.ts +99 -0
  148. package/dist/src/workspace/read-model/extensions/inventory.js +111 -0
  149. package/dist/src/workspace/read-model/extensions/knowledge.d.ts +101 -0
  150. package/dist/src/workspace/read-model/extensions/knowledge.js +121 -0
  151. package/dist/src/workspace/read-model/extensions/mcp-server.d.ts +106 -0
  152. package/dist/src/workspace/read-model/extensions/mcp-server.js +122 -0
  153. package/dist/src/workspace/read-model/extensions/pack.d.ts +104 -0
  154. package/dist/src/workspace/read-model/extensions/pack.js +123 -0
  155. package/dist/src/workspace/read-model/extensions/package-root.d.ts +39 -0
  156. package/dist/src/workspace/read-model/extensions/package-root.js +48 -0
  157. package/dist/src/workspace/read-model/extensions/projection.d.ts +137 -0
  158. package/dist/src/workspace/read-model/extensions/projection.js +180 -0
  159. package/dist/src/workspace/read-model/extensions/rule.d.ts +104 -0
  160. package/dist/src/workspace/read-model/extensions/rule.js +113 -0
  161. package/dist/src/workspace/read-model/extensions/skill.d.ts +170 -0
  162. package/dist/src/workspace/read-model/extensions/skill.js +148 -0
  163. package/dist/src/workspace/read-model/extensions/subagent.d.ts +97 -0
  164. package/dist/src/workspace/read-model/extensions/subagent.js +120 -0
  165. package/dist/src/workspace/read-model/scanners/agent-dir.d.ts +49 -0
  166. package/dist/src/workspace/read-model/scanners/agent-dir.js +180 -0
  167. package/dist/src/workspace/read-model/scanners/agent-root.d.ts +73 -0
  168. package/dist/src/workspace/read-model/scanners/agent-root.js +148 -0
  169. package/dist/src/workspace/read-model/scanners/agent-settings.d.ts +43 -0
  170. package/dist/src/workspace/read-model/scanners/agent-settings.js +54 -0
  171. package/dist/src/workspace/read-model/scanners/canonical-extensions.d.ts +48 -0
  172. package/dist/src/workspace/read-model/scanners/canonical-extensions.js +237 -0
  173. package/dist/src/workspace/read-model/scanners/fs-helpers.d.ts +63 -0
  174. package/dist/src/workspace/read-model/scanners/fs-helpers.js +106 -0
  175. package/dist/src/workspace/read-model/scanners/index.d.ts +15 -0
  176. package/dist/src/workspace/read-model/scanners/index.js +34 -0
  177. package/dist/src/workspace/read-model/scanners/mcp-config.d.ts +47 -0
  178. package/dist/src/workspace/read-model/scanners/mcp-config.js +212 -0
  179. package/dist/src/workspace/read-model/scanners/types.d.ts +170 -0
  180. package/dist/src/workspace/read-model/scanners/types.js +86 -0
  181. package/dist/src/workspace/read-model/service.d.ts +103 -0
  182. package/dist/src/workspace/read-model/service.js +391 -0
  183. package/dist/src/workspace/read-model/state.d.ts +35 -0
  184. package/dist/src/workspace/read-model/state.js +97 -0
  185. package/dist/src/workspace/read-model/types.d.ts +75 -0
  186. package/dist/src/workspace/read-model/types.js +26 -0
  187. package/dist/src/workspace/read-model-record-readers.d.ts +34 -0
  188. package/dist/src/workspace/read-model-record-readers.js +467 -0
  189. package/dist/src/workspace/read-model-record-rows.d.ts +45 -0
  190. package/dist/src/workspace/read-model-record-rows.js +33 -0
  191. package/dist/src/workspace/read-model-record-types.d.ts +45 -0
  192. package/dist/src/workspace/read-model-record-types.js +13 -0
  193. package/dist/src/workspace/remove-if-exists.d.ts +13 -0
  194. package/dist/src/workspace/remove-if-exists.js +26 -0
  195. package/dist/src/workspace/rendered-files.d.ts +53 -0
  196. package/dist/src/workspace/rendered-files.js +50 -0
  197. package/dist/src/workspace/scope-refusal.d.ts +26 -0
  198. package/dist/src/workspace/scope-refusal.js +29 -0
  199. package/dist/src/workspace/service-interface.d.ts +479 -0
  200. package/dist/src/workspace/service-interface.js +27 -0
  201. package/dist/src/workspace/service.d.ts +1665 -0
  202. package/dist/src/workspace/service.js +1263 -0
  203. package/dist/src/workspace/setup-scope-support.d.ts +27 -0
  204. package/dist/src/workspace/setup-scope-support.js +299 -0
  205. package/dist/src/workspace/skill-paths.d.ts +33 -0
  206. package/dist/src/workspace/skill-paths.js +14 -0
  207. package/dist/src/workspace/source-metadata.d.ts +7 -0
  208. package/dist/src/workspace/source-metadata.js +10 -0
  209. package/dist/src/workspace/source-to-lock-entry.d.ts +32 -0
  210. package/dist/src/workspace/source-to-lock-entry.js +68 -0
  211. package/dist/src/workspace/test-stubs.d.ts +144 -0
  212. package/dist/src/workspace/test-stubs.js +412 -0
  213. package/dist/src/workspace/transaction.d.ts +218 -0
  214. package/dist/src/workspace/transaction.js +177 -0
  215. package/package.json +57 -0
@@ -0,0 +1,467 @@
1
+ /**
2
+ * Read-model record readers.
3
+ *
4
+ * Centralizes read-model record projection over `WorkspaceReadModel` subject
5
+ * rows.
6
+ */
7
+ import * as Effect from "effect/Effect";
8
+ import * as Option from "effect/Option";
9
+ import { installableExtensionTypes, } from "@agentxm/extension-model/unstable/extensions/installable-types";
10
+ import { isAxmManagedMcpEntry, isMcpServerApplicableToAgent } from "./mcp-entry-semantics.js";
11
+ import { createDefaultSettings } from "../settings/index.js";
12
+ import { configuredAgentLifecycleOutcomes } from "./configured-agent-outcomes.js";
13
+ import { projectExtensionInventory, } from "./read-model/extensions/inventory.js";
14
+ import { deriveSourceMetaFromLockType } from "./source-metadata.js";
15
+ export const makeReadModelRecordReaders = (args) => {
16
+ const packagingKindForSource = (type, source) => {
17
+ if (type === "pack")
18
+ return "native";
19
+ if (type === "skill") {
20
+ return source.includes("/skills/") || source.startsWith("@") ? "native" : "non-native";
21
+ }
22
+ return source.includes("/") && source.startsWith("@") ? "native" : "non-native";
23
+ };
24
+ const packagingKindForResolved = (resolved, type, source) => Option.match(resolved, {
25
+ onNone: () => packagingKindForSource(type, source),
26
+ onSome: (row) => deriveSourceMetaFromLockType(row.lockEntry.type).packagingKind,
27
+ });
28
+ const stringProperty = (value, property) => {
29
+ if (typeof value !== "object" || value === null)
30
+ return null;
31
+ const candidate = property === "_tag"
32
+ ? "_tag" in value
33
+ ? value._tag
34
+ : undefined
35
+ : property === "agentId"
36
+ ? "agentId" in value
37
+ ? value.agentId
38
+ : undefined
39
+ : property === "packageRoot"
40
+ ? "packageRoot" in value
41
+ ? value.packageRoot
42
+ : undefined
43
+ : property === "contentRoot"
44
+ ? "contentRoot" in value
45
+ ? value.contentRoot
46
+ : undefined
47
+ : "configFile" in value
48
+ ? value.configFile
49
+ : undefined;
50
+ return typeof candidate === "string" ? candidate : null;
51
+ };
52
+ const observationFromActual = (actual) => {
53
+ if (typeof actual !== "object" || actual === null) {
54
+ return { agents: [], origins: [], paths: [] };
55
+ }
56
+ const origin = "origin" in actual ? actual.origin : undefined;
57
+ const originTag = stringProperty(origin, "_tag");
58
+ const agentId = stringProperty(origin, "agentId");
59
+ const packageRoot = stringProperty(actual, "packageRoot");
60
+ const contentRoot = stringProperty(actual, "contentRoot");
61
+ const configFile = stringProperty(actual, "configFile");
62
+ const actualPath = packageRoot ?? contentRoot ?? configFile;
63
+ return {
64
+ agents: agentId === null ? [] : [agentId],
65
+ origins: originTag === null ? [] : [originTag],
66
+ paths: actualPath === null ? [] : [args.path.relative(args.baseDir, actualPath)],
67
+ };
68
+ };
69
+ const mergeObservations = (actuals) => ({
70
+ agents: actuals.flatMap((actual) => observationFromActual(actual).agents),
71
+ origins: actuals.flatMap((actual) => observationFromActual(actual).origins),
72
+ paths: actuals.flatMap((actual) => observationFromActual(actual).paths),
73
+ });
74
+ const lifecycleCandidateFromInstalled = (row, defaultAgents) => {
75
+ const observations = mergeObservations(row.actual);
76
+ const observedAgents = observations.agents;
77
+ return {
78
+ key: row.key,
79
+ lifecycle: row.installationOrigin._tag === "direct" ? "configured" : "implicit",
80
+ enabled: row.activation === "enabled",
81
+ installed: row.actual.length > 0,
82
+ agents: observedAgents.length === 0 ? defaultAgents : observedAgents,
83
+ origins: observations.origins,
84
+ paths: observations.paths,
85
+ };
86
+ };
87
+ const lifecycleCandidateFromUnmanaged = (row) => ({
88
+ key: row.key,
89
+ lifecycle: "unmanaged",
90
+ enabled: null,
91
+ installed: true,
92
+ ...observationFromActual(row.actual),
93
+ });
94
+ const desiredPackMemberNames = (graph, type) => [
95
+ ...new Set(graph.nodes
96
+ .filter((node) => node.type === type && node.origins.some((origin) => origin.type === "pack"))
97
+ .map((node) => node.name)),
98
+ ].sort();
99
+ const getDesiredPackMemberNames = (type) => type === "pack"
100
+ ? Effect.succeed([])
101
+ : args
102
+ .getDesiredStateGraph()
103
+ .pipe(Effect.map((graph) => desiredPackMemberNames(graph, type)));
104
+ const packMemberToImplicit = (type, name) => ({
105
+ type,
106
+ name,
107
+ source: Option.none(),
108
+ enabled: true,
109
+ packagingKind: "native",
110
+ lifecycle: "implicit",
111
+ });
112
+ const installedRowToReadModelRecordRow = (type, row) => {
113
+ if (row.installationOrigin._tag === "direct") {
114
+ const source = row.installationOrigin.declared.entry.source;
115
+ const common = {
116
+ type,
117
+ name: row.key.name,
118
+ enabled: row.activation === "enabled",
119
+ ...(row.installationOrigin.declared.entry.origin === undefined
120
+ ? {}
121
+ : { origin: row.installationOrigin.declared.entry.origin }),
122
+ lifecycle: "configured",
123
+ };
124
+ return source === undefined
125
+ ? { ...common, authority: "inline", packagingKind: "non-native" }
126
+ : {
127
+ ...common,
128
+ source,
129
+ packagingKind: packagingKindForResolved(row.resolved, type, source),
130
+ };
131
+ }
132
+ return packMemberToImplicit(type, row.key.name);
133
+ };
134
+ const unmanagedRowToReadModelRecordRow = (type, row) => ({
135
+ type,
136
+ name: row.key.name,
137
+ source: Option.none(),
138
+ enabled: true,
139
+ packagingKind: type === "pack" ? "native" : "non-native",
140
+ locations: typeof row.actual.packageRoot === "string"
141
+ ? [args.path.relative(args.baseDir, row.actual.packageRoot)]
142
+ : typeof row.actual.contentRoot === "string"
143
+ ? [args.path.relative(args.baseDir, row.actual.contentRoot)]
144
+ : typeof row.actual.configFile === "string"
145
+ ? [args.path.relative(args.baseDir, row.actual.configFile)]
146
+ : [],
147
+ agents: observationFromActual(row.actual).agents,
148
+ ownershipEvidence: row.actual.config !== undefined &&
149
+ row.actual.config !== null &&
150
+ isAxmManagedMcpEntry(row.actual.config)
151
+ ? ["x-axm:managed-entry"]
152
+ : [],
153
+ lifecycle: "unmanaged",
154
+ });
155
+ const collectReadModelRecordRows = (input) => {
156
+ const desiredPackMembers = new Set(input.packMemberNames);
157
+ const acceptedInstalled = input.installed.filter((row) => row.installationOrigin._tag === "direct" || desiredPackMembers.has(row.key.name));
158
+ const installedNames = new Set(acceptedInstalled.map((row) => row.key.name));
159
+ const implicitRows = input.packMemberNames
160
+ .filter((name) => !installedNames.has(name))
161
+ .map((name) => packMemberToImplicit(input.type, name));
162
+ const stalePackActuals = input.installed
163
+ .filter((row) => row.installationOrigin._tag === "pack-member" && !desiredPackMembers.has(row.key.name))
164
+ .flatMap((row) => row.actual.map((actual) => ({ key: row.key, actual })));
165
+ return [
166
+ ...acceptedInstalled.map((row) => installedRowToReadModelRecordRow(input.type, row)),
167
+ ...implicitRows,
168
+ ...[...input.unmanaged, ...stalePackActuals]
169
+ .filter((row) => !desiredPackMembers.has(row.key.name))
170
+ .map((row) => unmanagedRowToReadModelRecordRow(input.type, row)),
171
+ ];
172
+ };
173
+ const getReadModelRecordRows = (type) => Effect.gen(function* () {
174
+ const packMemberNames = yield* getDesiredPackMemberNames(type);
175
+ return yield* args.readScopedContext((scoped) => Effect.gen(function* () {
176
+ switch (type) {
177
+ case "skill": {
178
+ const installed = yield* scoped.skills.installed;
179
+ const unmanaged = yield* scoped.skills.unmanaged;
180
+ return collectReadModelRecordRows({
181
+ type,
182
+ installed,
183
+ unmanaged,
184
+ packMemberNames,
185
+ });
186
+ }
187
+ case "mcp-server": {
188
+ const installed = yield* scoped.mcpServers.installed;
189
+ const unmanaged = yield* scoped.mcpServers.unmanaged;
190
+ return collectReadModelRecordRows({
191
+ type,
192
+ installed,
193
+ unmanaged,
194
+ packMemberNames,
195
+ });
196
+ }
197
+ case "pack": {
198
+ const installed = yield* scoped.packs.installed;
199
+ const unmanaged = yield* scoped.packs.unmanaged;
200
+ return collectReadModelRecordRows({
201
+ type,
202
+ installed,
203
+ unmanaged,
204
+ packMemberNames,
205
+ });
206
+ }
207
+ case "subagent": {
208
+ const installed = yield* scoped.subagents.installed;
209
+ const unmanaged = yield* scoped.subagents.unmanaged;
210
+ return collectReadModelRecordRows({
211
+ type,
212
+ installed,
213
+ unmanaged,
214
+ packMemberNames,
215
+ });
216
+ }
217
+ case "rule": {
218
+ const installed = yield* scoped.rules.installed;
219
+ const unmanaged = yield* scoped.rules.unmanaged;
220
+ return collectReadModelRecordRows({
221
+ type,
222
+ installed,
223
+ unmanaged,
224
+ packMemberNames,
225
+ });
226
+ }
227
+ case "hook": {
228
+ const installed = yield* scoped.hooks.installed;
229
+ const unmanaged = yield* scoped.hooks.unmanaged;
230
+ return collectReadModelRecordRows({
231
+ type,
232
+ installed,
233
+ unmanaged,
234
+ packMemberNames,
235
+ });
236
+ }
237
+ case "knowledge": {
238
+ const installed = yield* scoped.knowledge.installed;
239
+ const unmanaged = yield* scoped.knowledge.unmanaged;
240
+ return collectReadModelRecordRows({
241
+ type,
242
+ installed,
243
+ unmanaged,
244
+ packMemberNames,
245
+ });
246
+ }
247
+ }
248
+ }));
249
+ });
250
+ const projectStandardInventory = (input) => {
251
+ const desiredPackMembers = new Set(input.packMemberNames);
252
+ const acceptedInstalled = input.installed.filter((row) => row.installationOrigin._tag === "direct" || desiredPackMembers.has(row.key.name));
253
+ const installedNames = new Set(acceptedInstalled.map((row) => row.key.name));
254
+ const desiredUnmanaged = input.unmanaged.filter((row) => desiredPackMembers.has(row.key.name));
255
+ const desiredUnmanagedNames = new Set(desiredUnmanaged.map((row) => row.key.name));
256
+ const implicitMissing = input.packMemberNames
257
+ .filter((name) => !installedNames.has(name) && !desiredUnmanagedNames.has(name))
258
+ .map((name) => ({
259
+ key: {
260
+ scope: input.scope,
261
+ type: input.type,
262
+ name,
263
+ },
264
+ lifecycle: "implicit",
265
+ enabled: true,
266
+ installed: false,
267
+ agents: input.configuredAgents,
268
+ origins: [],
269
+ paths: [],
270
+ }));
271
+ const implicitObserved = desiredUnmanaged.map((row) => ({
272
+ ...lifecycleCandidateFromUnmanaged(row),
273
+ lifecycle: "implicit",
274
+ enabled: true,
275
+ }));
276
+ const stalePackActuals = input.installed
277
+ .filter((row) => row.installationOrigin._tag === "pack-member" && !desiredPackMembers.has(row.key.name))
278
+ .flatMap((row) => row.actual.map((actual) => ({ key: row.key, actual })));
279
+ return projectExtensionInventory({
280
+ lifecycle: [
281
+ ...acceptedInstalled.map((row) => lifecycleCandidateFromInstalled(row, input.configuredAgents)),
282
+ ...implicitObserved,
283
+ ...implicitMissing,
284
+ ...input.unmanaged
285
+ .filter((row) => !desiredPackMembers.has(row.key.name))
286
+ .map(lifecycleCandidateFromUnmanaged),
287
+ ...stalePackActuals.map(lifecycleCandidateFromUnmanaged),
288
+ ],
289
+ agents: input.agents,
290
+ });
291
+ };
292
+ const getExtensionInventory = (type, options) => Effect.gen(function* () {
293
+ const packMemberNames = yield* getDesiredPackMemberNames(type);
294
+ return yield* args.readScopedContext((scoped) => Effect.gen(function* () {
295
+ const settingsOption = yield* scoped.state.settings;
296
+ const settings = Option.getOrElse(settingsOption, () => createDefaultSettings());
297
+ const agents = options.agents ?? [];
298
+ const configuredAgents = settings.agents ?? [];
299
+ const finalizeInventory = (inventory) => {
300
+ const withOutcomes = inventory.items.map((row) => {
301
+ const mcpEntry = row.type === "mcp-server" ? settings.mcpServers?.[row.name] : undefined;
302
+ return {
303
+ ...row,
304
+ agentOutcomes: row.classification.lifecycle === "unmanaged"
305
+ ? []
306
+ : configuredAgentLifecycleOutcomes({
307
+ type: row.type,
308
+ name: row.name,
309
+ agentIds: configuredAgents,
310
+ scope: row.scope,
311
+ state: "current",
312
+ targetState: row.enabled === false ? "disabled" : "enabled",
313
+ installed: row.installed,
314
+ observedAgentIds: row.agents,
315
+ ...(mcpEntry === undefined
316
+ ? {}
317
+ : {
318
+ applicableAgentIds: configuredAgents.filter((agentId) => isMcpServerApplicableToAgent(mcpEntry, agentId)),
319
+ }),
320
+ }),
321
+ };
322
+ });
323
+ const items = withOutcomes.filter((row) => agents.length === 0 ||
324
+ agents.some((agentId) => row.agents.includes(agentId) ||
325
+ row.agentOutcomes.some((outcome) => outcome.agentId === agentId)));
326
+ return {
327
+ items,
328
+ count: items.length,
329
+ configuredCount: items.filter((item) => item.classification.lifecycle === "configured").length,
330
+ implicitCount: items.filter((item) => item.classification.lifecycle === "implicit")
331
+ .length,
332
+ installedCount: items.filter((item) => item.installed).length,
333
+ unmanagedCount: items.filter((item) => item.classification.lifecycle === "unmanaged")
334
+ .length,
335
+ };
336
+ };
337
+ switch (type) {
338
+ case "skill": {
339
+ const installed = yield* scoped.skills.installed;
340
+ const resolved = yield* scoped.skills.resolved;
341
+ const unmanaged = yield* scoped.skills.unmanaged;
342
+ return finalizeInventory(projectStandardInventory({
343
+ scope: scoped.scope,
344
+ type,
345
+ installed,
346
+ resolved: Option.getOrElse(resolved, () => []),
347
+ unmanaged,
348
+ agents: [],
349
+ configuredAgents,
350
+ packMemberNames,
351
+ }));
352
+ }
353
+ case "mcp-server": {
354
+ const installed = yield* scoped.mcpServers.installed;
355
+ const resolved = yield* scoped.mcpServers.resolved;
356
+ const unmanaged = yield* scoped.mcpServers.unmanaged;
357
+ return finalizeInventory(projectStandardInventory({
358
+ scope: scoped.scope,
359
+ type,
360
+ installed,
361
+ resolved: Option.getOrElse(resolved, () => []),
362
+ unmanaged,
363
+ agents: [],
364
+ configuredAgents,
365
+ packMemberNames,
366
+ }));
367
+ }
368
+ case "subagent": {
369
+ const installed = yield* scoped.subagents.installed;
370
+ const resolved = yield* scoped.subagents.resolved;
371
+ const unmanaged = yield* scoped.subagents.unmanaged;
372
+ return finalizeInventory(projectStandardInventory({
373
+ scope: scoped.scope,
374
+ type,
375
+ installed,
376
+ resolved: Option.getOrElse(resolved, () => []),
377
+ unmanaged,
378
+ agents: [],
379
+ configuredAgents,
380
+ packMemberNames,
381
+ }));
382
+ }
383
+ case "pack": {
384
+ const installed = yield* scoped.packs.installed;
385
+ const resolved = yield* scoped.packs.resolved;
386
+ const unmanaged = yield* scoped.packs.unmanaged;
387
+ return finalizeInventory(projectStandardInventory({
388
+ scope: scoped.scope,
389
+ type,
390
+ installed,
391
+ resolved: Option.getOrElse(resolved, () => []),
392
+ unmanaged,
393
+ agents: [],
394
+ configuredAgents,
395
+ packMemberNames,
396
+ }));
397
+ }
398
+ case "rule": {
399
+ const installed = yield* scoped.rules.installed;
400
+ const resolved = yield* scoped.rules.resolved;
401
+ const unmanaged = yield* scoped.rules.unmanaged;
402
+ return finalizeInventory(projectStandardInventory({
403
+ scope: scoped.scope,
404
+ type,
405
+ installed,
406
+ resolved: Option.getOrElse(resolved, () => []),
407
+ unmanaged,
408
+ agents: [],
409
+ configuredAgents,
410
+ packMemberNames,
411
+ }));
412
+ }
413
+ case "hook": {
414
+ const installed = yield* scoped.hooks.installed;
415
+ const resolved = yield* scoped.hooks.resolved;
416
+ const unmanaged = yield* scoped.hooks.unmanaged;
417
+ return finalizeInventory(projectStandardInventory({
418
+ scope: scoped.scope,
419
+ type,
420
+ installed,
421
+ resolved: Option.getOrElse(resolved, () => []),
422
+ unmanaged,
423
+ agents: [],
424
+ configuredAgents,
425
+ packMemberNames,
426
+ }));
427
+ }
428
+ case "knowledge": {
429
+ const installed = yield* scoped.knowledge.installed;
430
+ const resolved = yield* scoped.knowledge.resolved;
431
+ const unmanaged = yield* scoped.knowledge.unmanaged;
432
+ return finalizeInventory(projectStandardInventory({
433
+ scope: scoped.scope,
434
+ type,
435
+ installed,
436
+ resolved: Option.getOrElse(resolved, () => []),
437
+ unmanaged,
438
+ agents: [],
439
+ configuredAgents,
440
+ packMemberNames,
441
+ }));
442
+ }
443
+ }
444
+ }));
445
+ });
446
+ const getInventory = (options) => Effect.gen(function* () {
447
+ const types = options.type === undefined ? installableExtensionTypes : [options.type];
448
+ const inventories = yield* Effect.forEach(types, (type) => getExtensionInventory(type, {}), {
449
+ concurrency: "unbounded",
450
+ });
451
+ const items = inventories
452
+ .flatMap((inventory) => inventory.items)
453
+ .sort((left, right) => left.type === right.type
454
+ ? left.name.localeCompare(right.name)
455
+ : left.type.localeCompare(right.type));
456
+ return {
457
+ items,
458
+ count: items.length,
459
+ configuredCount: inventories.reduce((total, inventory) => total + inventory.configuredCount, 0),
460
+ implicitCount: inventories.reduce((total, inventory) => total + inventory.implicitCount, 0),
461
+ installedCount: inventories.reduce((total, inventory) => total + inventory.installedCount, 0),
462
+ unmanagedCount: inventories.reduce((total, inventory) => total + inventory.unmanagedCount, 0),
463
+ };
464
+ });
465
+ return { getInventory, getReadModelRecordRows, getExtensionInventory };
466
+ };
467
+ //# sourceMappingURL=read-model-record-readers.js.map
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Lifecycle views over `ReadModelRecordRow`.
3
+ *
4
+ * `WorkspaceReadModelRecords.rows(type)` returns every row the read model
5
+ * projects for one extension type, tagged with its lifecycle. Callers that
6
+ * previously reached for a per-type accessor (`getConfiguredSkills`,
7
+ * `getInstalledPacks`, …) narrow the same rows here instead, so a new
8
+ * extension type needs no new accessor.
9
+ *
10
+ * @internal
11
+ */
12
+ import type * as Record from "effect/Record";
13
+ import type { ReadModelRecordRow } from "./read-model-record-types.js";
14
+ /** A row declared in `axm.json`, carrying a concrete source string. */
15
+ export type ConfiguredRecordRow = Extract<ReadModelRecordRow, {
16
+ lifecycle: "configured";
17
+ }>;
18
+ /** A row installed indirectly — a pack member or a lockfile-only entry. */
19
+ export type ImplicitRecordRow = Extract<ReadModelRecordRow, {
20
+ lifecycle: "implicit";
21
+ }>;
22
+ /** A row observed on disk that no settings or lockfile entry claims. */
23
+ export type UnmanagedRecordRow = Extract<ReadModelRecordRow, {
24
+ lifecycle: "unmanaged";
25
+ }>;
26
+ /** Configured plus implicit — everything the workspace considers installed. */
27
+ export type InstalledRecordRow = ConfiguredRecordRow | ImplicitRecordRow;
28
+ export declare const isConfiguredRecordRow: (row: ReadModelRecordRow) => row is ConfiguredRecordRow;
29
+ export declare const isUnmanagedRecordRow: (row: ReadModelRecordRow) => row is UnmanagedRecordRow;
30
+ export declare const isInstalledRecordRow: (row: ReadModelRecordRow) => row is InstalledRecordRow;
31
+ export declare const configuredRecordRows: (rows: ReadonlyArray<ReadModelRecordRow>) => ReadonlyArray<ConfiguredRecordRow>;
32
+ export declare const unmanagedRecordRows: (rows: ReadonlyArray<ReadModelRecordRow>) => ReadonlyArray<UnmanagedRecordRow>;
33
+ export declare const installedRecordRows: (rows: ReadonlyArray<ReadModelRecordRow>) => ReadonlyArray<InstalledRecordRow>;
34
+ /**
35
+ * Index rows by workspace name. Later rows win, matching the projection order
36
+ * where a direct declaration is emitted before any implicit or unmanaged row
37
+ * for the same name.
38
+ */
39
+ export declare const recordRowsByName: <R extends {
40
+ readonly name: string;
41
+ }>(rows: ReadonlyArray<R>) => Record.ReadonlyRecord<string, R>;
42
+ export declare const configuredRowsByName: (rows: ReadonlyArray<ReadModelRecordRow>) => Record.ReadonlyRecord<string, ConfiguredRecordRow>;
43
+ export declare const installedRowsByName: (rows: ReadonlyArray<ReadModelRecordRow>) => Record.ReadonlyRecord<string, InstalledRecordRow>;
44
+ export declare const unmanagedRowsByName: (rows: ReadonlyArray<ReadModelRecordRow>) => Record.ReadonlyRecord<string, UnmanagedRecordRow>;
45
+ //# sourceMappingURL=read-model-record-rows.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Lifecycle views over `ReadModelRecordRow`.
3
+ *
4
+ * `WorkspaceReadModelRecords.rows(type)` returns every row the read model
5
+ * projects for one extension type, tagged with its lifecycle. Callers that
6
+ * previously reached for a per-type accessor (`getConfiguredSkills`,
7
+ * `getInstalledPacks`, …) narrow the same rows here instead, so a new
8
+ * extension type needs no new accessor.
9
+ *
10
+ * @internal
11
+ */
12
+ export const isConfiguredRecordRow = (row) => row.lifecycle === "configured";
13
+ export const isUnmanagedRecordRow = (row) => row.lifecycle === "unmanaged";
14
+ export const isInstalledRecordRow = (row) => row.lifecycle !== "unmanaged";
15
+ export const configuredRecordRows = (rows) => rows.filter(isConfiguredRecordRow);
16
+ export const unmanagedRecordRows = (rows) => rows.filter(isUnmanagedRecordRow);
17
+ export const installedRecordRows = (rows) => rows.filter(isInstalledRecordRow);
18
+ /**
19
+ * Index rows by workspace name. Later rows win, matching the projection order
20
+ * where a direct declaration is emitted before any implicit or unmanaged row
21
+ * for the same name.
22
+ */
23
+ export const recordRowsByName = (rows) => {
24
+ const result = {};
25
+ for (const row of rows) {
26
+ result[row.name] = row;
27
+ }
28
+ return result;
29
+ };
30
+ export const configuredRowsByName = (rows) => recordRowsByName(configuredRecordRows(rows));
31
+ export const installedRowsByName = (rows) => recordRowsByName(installedRecordRows(rows));
32
+ export const unmanagedRowsByName = (rows) => recordRowsByName(unmanagedRecordRows(rows));
33
+ //# sourceMappingURL=read-model-record-rows.js.map
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Read-model record row shape returned by `WorkspaceReadModelRecords.rows`.
3
+ *
4
+ * One row union covers every extension type; the `lifecycle` discriminant
5
+ * carries whether the row is declared in settings (`configured`), installed
6
+ * indirectly through a pack or lockfile entry (`implicit`), or observed on
7
+ * disk without a claim (`unmanaged`). Narrowing helpers live in
8
+ * `read-model-record-rows.ts`.
9
+ *
10
+ * @internal
11
+ */
12
+ import type * as Option from "effect/Option";
13
+ export type PackagingKind = "native" | "non-native";
14
+ export type ReadModelRecordRow = ({
15
+ readonly type: string;
16
+ readonly name: string;
17
+ readonly enabled: boolean;
18
+ readonly origin?: "bundled";
19
+ readonly packagingKind: PackagingKind;
20
+ readonly lifecycle: "configured";
21
+ } & ({
22
+ readonly authority?: "sourced";
23
+ readonly source: string;
24
+ } | {
25
+ readonly authority: "inline";
26
+ readonly source?: undefined;
27
+ })) | {
28
+ readonly type: string;
29
+ readonly name: string;
30
+ readonly source: Option.Option<string>;
31
+ readonly enabled: true;
32
+ readonly packagingKind: PackagingKind;
33
+ readonly lifecycle: "implicit";
34
+ } | {
35
+ readonly type: string;
36
+ readonly name: string;
37
+ readonly source: Option.Option<string>;
38
+ readonly enabled: true;
39
+ readonly packagingKind: PackagingKind;
40
+ readonly locations: ReadonlyArray<string>;
41
+ readonly agents: ReadonlyArray<string>;
42
+ readonly ownershipEvidence: ReadonlyArray<string>;
43
+ readonly lifecycle: "unmanaged";
44
+ };
45
+ //# sourceMappingURL=read-model-record-types.d.ts.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Read-model record row shape returned by `WorkspaceReadModelRecords.rows`.
3
+ *
4
+ * One row union covers every extension type; the `lifecycle` discriminant
5
+ * carries whether the row is declared in settings (`configured`), installed
6
+ * indirectly through a pack or lockfile entry (`implicit`), or observed on
7
+ * disk without a claim (`unmanaged`). Narrowing helpers live in
8
+ * `read-model-record-rows.ts`.
9
+ *
10
+ * @internal
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=read-model-record-types.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Transaction-aware removal of canonical extension paths.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ */
6
+ import * as FileSystem from "effect/FileSystem";
7
+ import * as Effect from "effect/Effect";
8
+ import { CanonicalPathRemovalError } from "./errors.js";
9
+ /**
10
+ * Remove a directory if it exists.
11
+ */
12
+ export declare const removeIfExists: (fsService: FileSystem.FileSystem, dirPath: string) => Effect.Effect<void, import("./transaction.js").WorkspaceSnapshotError | CanonicalPathRemovalError, never>;
13
+ //# sourceMappingURL=remove-if-exists.d.ts.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Transaction-aware removal of canonical extension paths.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ */
6
+ import * as FileSystem from "effect/FileSystem";
7
+ import * as Effect from "effect/Effect";
8
+ import { CanonicalPathRemovalError } from "./errors.js";
9
+ import { protectWorkspacePath } from "./transaction.js";
10
+ import { recordFootprint } from "./footprint-recorder.js";
11
+ /**
12
+ * Remove a directory if it exists.
13
+ */
14
+ export const removeIfExists = (fsService, dirPath) => Effect.gen(function* () {
15
+ const exists = yield* fsService
16
+ .exists(dirPath)
17
+ .pipe(Effect.mapError((cause) => new CanonicalPathRemovalError({ path: dirPath, step: "inspect", cause })));
18
+ if (!exists)
19
+ return;
20
+ yield* protectWorkspacePath(dirPath);
21
+ yield* fsService
22
+ .remove(dirPath, { recursive: true })
23
+ .pipe(Effect.mapError((cause) => new CanonicalPathRemovalError({ path: dirPath, step: "remove", cause })));
24
+ yield* recordFootprint({ path: dirPath, change: "removed" });
25
+ });
26
+ //# sourceMappingURL=remove-if-exists.js.map