@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,121 @@
1
+ /**
2
+ * Knowledge subject module: declared/resolved/actual payloads, scanner
3
+ * composition, and projections via the shared helper.
4
+ *
5
+ * Declared bundles come from `settings.knowledge`; resolved bundles come from
6
+ * `axm-lock.yaml` `knowledge`. Actual occurrences come exclusively from the
7
+ * canonical-extensions scanner (`type === "knowledge"`), which enumerates
8
+ * project-authored `knowledge/<name>/src`, project-acquired
9
+ * `agent_extensions/<source>/<source-full-name>`, and user-scope packages.
10
+ *
11
+ * Knowledge installs also write two derived artifacts — the `.axm/knowledge/index.md`
12
+ * catalog and the discovery region inside the agent instructions file. Both live
13
+ * outside canonical package roots, so the canonical scanner never sees them and they
14
+ * cannot become occurrences; `actual` is therefore scoped to the materialized
15
+ * bundle package directory by construction.
16
+ *
17
+ * Pack-resolved Knowledge members participate in the same direct-over-pack
18
+ * projection as every other extension type.
19
+ */
20
+ import * as Effect from "effect/Effect";
21
+ import * as Option from "effect/Option";
22
+ import { decodeExtensionNameSync, } from "@agentxm/extension-model/unstable/extensions/common";
23
+ import { filterMapOccurrences } from "./actual-helpers.js";
24
+ import { canonicalAxmPackageRoot } from "./package-root.js";
25
+ import { makeProjectedSubjectCells, projectInstalledExtensions, } from "./projection.js";
26
+ // ---------------------------------------------------------------------------
27
+ // Helpers
28
+ // ---------------------------------------------------------------------------
29
+ const canonicalToActual = (occ, scope) => {
30
+ const isExternal = occ.origin === "external-axm";
31
+ const packageRoot = canonicalAxmPackageRoot(occ);
32
+ return {
33
+ key: { scope, type: "knowledge", name: occ.name },
34
+ origin: isExternal ? { _tag: "external-axm-knowledge" } : { _tag: "canonical-axm-knowledge" },
35
+ contentRoot: occ.contentLocation,
36
+ packageRoot,
37
+ };
38
+ };
39
+ const declaredFromSettings = (settings) => {
40
+ if (settings.knowledge === undefined)
41
+ return [];
42
+ return Object.entries(settings.knowledge).map(([name, entry]) => ({
43
+ name: decodeExtensionNameSync(name),
44
+ entry,
45
+ }));
46
+ };
47
+ const resolvedFromLockfile = (lockfile) => {
48
+ if (lockfile.knowledge === undefined)
49
+ return [];
50
+ return Object.entries(lockfile.knowledge).map(([name, lockEntry]) => ({
51
+ name: decodeExtensionNameSync(name),
52
+ lockEntry,
53
+ }));
54
+ };
55
+ const orphanResolvedWarning = (name) => ({
56
+ source: "lockfile",
57
+ message: `knowledge: lockfile entry "${name}" has no matching declared or pack-member home`,
58
+ code: "orphan-resolved",
59
+ });
60
+ const knowledgePolicy = (scope) => ({
61
+ declaredEntries: (d) => d,
62
+ declaredName: (entry) => entry.name,
63
+ declaredActivation: (entry) => (entry.entry.enabled === false ? "disabled" : "enabled"),
64
+ resolvedEntries: (r) => r,
65
+ resolvedName: (entry) => entry.name,
66
+ actualEntries: (a) => a,
67
+ actualName: (e) => e.key.name,
68
+ packMemberName: (member) => member.name,
69
+ packMemberActivation: () => "enabled",
70
+ attachActualToInstalled: (name, actual) => actual.filter((a) => a.key.name === name),
71
+ notClaimedBySubjectPolicy: () => true,
72
+ buildInstalledRow: (input) => ({
73
+ key: { scope, type: "knowledge", name: input.name },
74
+ installationOrigin: input.installationOrigin,
75
+ activation: input.activation,
76
+ resolved: input.resolved,
77
+ actual: input.actual,
78
+ providingPacks: input.providingPacks,
79
+ }),
80
+ buildUnmanagedRow: (entry) => ({
81
+ key: { scope, type: "knowledge", name: entry.key.name },
82
+ actual: entry,
83
+ }),
84
+ resolvedOrphanWarning: orphanResolvedWarning,
85
+ });
86
+ /**
87
+ * Build the knowledge subject API. Returns an `Effect` because the projection
88
+ * cell is wrapped in `Effect.cached` so the four derived cells share one
89
+ * in-flight execution per scope, mirroring `state.ts`.
90
+ */
91
+ export const makeKnowledgeExtensionsApi = (deps) => Effect.gen(function* () {
92
+ const { scope, scanners, diagnostics } = deps;
93
+ const declared = deps.loaders.settings.pipe(Effect.map((opt) => Option.map(opt, declaredFromSettings)));
94
+ const resolved = deps.loaders.lockfile.pipe(Effect.map((opt) => Option.map(opt, resolvedFromLockfile)));
95
+ const actual = Effect.gen(function* () {
96
+ const canonical = yield* scanners.canonical;
97
+ return filterMapOccurrences(canonical, "knowledge", (occ) => canonicalToActual(occ, scope));
98
+ });
99
+ const project = yield* Effect.cached(projectInstalledExtensions({
100
+ declared,
101
+ resolved,
102
+ actual,
103
+ installedPacks: deps.installedPacks,
104
+ packMembers: (pack) => pack.knowledge,
105
+ packRef: (pack) => pack.ref,
106
+ policy: knowledgePolicy(scope),
107
+ diagnostics,
108
+ }));
109
+ return {
110
+ ...makeProjectedSubjectCells({
111
+ declared,
112
+ resolved,
113
+ actual,
114
+ project,
115
+ }),
116
+ declared,
117
+ resolved,
118
+ actual,
119
+ };
120
+ });
121
+ //# sourceMappingURL=knowledge.js.map
@@ -0,0 +1,106 @@
1
+ /**
2
+ * MCP server subject module: declared/resolved/actual payloads, scanner
3
+ * composition (canonical-extensions + mcp-config(workspace) + mcp-config(agent)),
4
+ * and projections via the shared helper.
5
+ *
6
+ * MCP servers carry a declared `enabled` flag in settings. Disabled servers
7
+ * remain installed on disk and in the lockfile but are removed from agent
8
+ * configs unless the target agent has a native enabled toggle.
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, McpServerLockEntry } from "../../../lockfile/schema.js";
15
+ import type { McpServerEntry, Settings } from "../../../settings/schema.js";
16
+ import type { Diagnostics } from "../diagnostics.js";
17
+ import type { LockfileReadError, SettingsReadError } from "../errors.js";
18
+ import type { CanonicalExtensionOccurrence, McpConfigOccurrence } from "../scanners/types.js";
19
+ import type { ActivationState, ExtensionKey, InstallationOrigin, InstalledPackRef, Scope } from "../types.js";
20
+ export type McpServerDetectionOrigin = {
21
+ readonly _tag: "canonical-axm-mcp-server";
22
+ } | {
23
+ readonly _tag: "external-axm-mcp-server";
24
+ } | {
25
+ readonly _tag: "workspace-mcp-config";
26
+ } | {
27
+ readonly _tag: "agent-mcp-config";
28
+ readonly agentId: AgentId;
29
+ };
30
+ export interface DeclaredMcpServer {
31
+ readonly name: ExtensionName;
32
+ readonly entry: McpServerEntry;
33
+ }
34
+ export type DeclaredMcpServers = ReadonlyArray<DeclaredMcpServer>;
35
+ export interface ResolvedMcpServer {
36
+ readonly name: ExtensionName;
37
+ readonly lockEntry: McpServerLockEntry;
38
+ }
39
+ export type ResolvedMcpServers = ReadonlyArray<ResolvedMcpServer>;
40
+ /**
41
+ * One observable MCP server materialization. `configFile` is the absolute
42
+ * path to the config file containing the server entry (workspace `.mcp.json`
43
+ * or an agent-native MCP config). For canonical/external AXM occurrences,
44
+ * `configFile` is null and `contentRoot` carries the package directory.
45
+ */
46
+ export interface ActualMcpServer {
47
+ readonly key: ExtensionKey<"mcp-server">;
48
+ readonly origin: McpServerDetectionOrigin;
49
+ readonly contentRoot: string | null;
50
+ readonly packageRoot: string | null;
51
+ readonly configFile: string | null;
52
+ readonly config: Readonly<Record<string, unknown>> | null;
53
+ }
54
+ export type ActualMcpServers = ReadonlyArray<ActualMcpServer>;
55
+ export interface McpServerPackMember {
56
+ readonly name: ExtensionName;
57
+ readonly providingPack: InstalledPackRef;
58
+ }
59
+ export interface InstalledMcpServer {
60
+ readonly key: ExtensionKey<"mcp-server">;
61
+ readonly installationOrigin: InstallationOrigin<DeclaredMcpServer, McpServerPackMember>;
62
+ readonly activation: ActivationState;
63
+ readonly resolved: Option.Option<ResolvedMcpServer>;
64
+ readonly actual: ReadonlyArray<ActualMcpServer>;
65
+ readonly providingPacks: ReadonlyArray<InstalledPackRef>;
66
+ }
67
+ export interface UnmanagedMcpServer {
68
+ readonly key: ExtensionKey<"mcp-server">;
69
+ readonly actual: ActualMcpServer;
70
+ }
71
+ export interface McpServerScopedLoaders {
72
+ readonly settings: Effect.Effect<Option.Option<Settings>, SettingsReadError>;
73
+ readonly lockfile: Effect.Effect<Option.Option<Lockfile>, LockfileReadError>;
74
+ }
75
+ export interface McpServerScanners {
76
+ readonly canonical: Effect.Effect<ReadonlyArray<CanonicalExtensionOccurrence>>;
77
+ readonly mcpConfig: Effect.Effect<ReadonlyArray<McpConfigOccurrence>>;
78
+ }
79
+ export interface InstalledPackForMcpServers {
80
+ readonly ref: InstalledPackRef;
81
+ readonly mcpServers: ReadonlyArray<McpServerPackMember>;
82
+ }
83
+ export interface McpServerExtensionsApiDeps {
84
+ readonly scope: Scope;
85
+ readonly loaders: McpServerScopedLoaders;
86
+ readonly scanners: McpServerScanners;
87
+ readonly installedPacks: Effect.Effect<ReadonlyArray<InstalledPackForMcpServers>, SettingsReadError | LockfileReadError>;
88
+ readonly diagnostics: Diagnostics;
89
+ }
90
+ export interface McpServerExtensionsApi {
91
+ readonly declared: Effect.Effect<Option.Option<DeclaredMcpServers>, SettingsReadError>;
92
+ readonly resolved: Effect.Effect<Option.Option<ResolvedMcpServers>, LockfileReadError>;
93
+ readonly actual: Effect.Effect<ActualMcpServers>;
94
+ readonly installed: Effect.Effect<ReadonlyArray<InstalledMcpServer>, SettingsReadError | LockfileReadError>;
95
+ readonly byName: (name: string) => Effect.Effect<Option.Option<InstalledMcpServer>, SettingsReadError | LockfileReadError>;
96
+ readonly declaredByName: (name: string) => Effect.Effect<Option.Option<DeclaredMcpServer>, SettingsReadError>;
97
+ readonly active: Effect.Effect<ReadonlyArray<InstalledMcpServer>, SettingsReadError | LockfileReadError>;
98
+ readonly unmanaged: Effect.Effect<ReadonlyArray<UnmanagedMcpServer>, SettingsReadError | LockfileReadError>;
99
+ }
100
+ /**
101
+ * Build the MCP server subject API. Returns an `Effect` because the
102
+ * projection cell is wrapped in `Effect.cached` so the four derived cells
103
+ * share one in-flight execution per scope, mirroring `state.ts`.
104
+ */
105
+ export declare const makeMcpServerExtensionsApi: (deps: McpServerExtensionsApiDeps) => Effect.Effect<McpServerExtensionsApi>;
106
+ //# sourceMappingURL=mcp-server.d.ts.map
@@ -0,0 +1,122 @@
1
+ /**
2
+ * MCP server subject module: declared/resolved/actual payloads, scanner
3
+ * composition (canonical-extensions + mcp-config(workspace) + mcp-config(agent)),
4
+ * and projections via the shared helper.
5
+ *
6
+ * MCP servers carry a declared `enabled` flag in settings. Disabled servers
7
+ * remain installed on disk and in the lockfile but are removed from agent
8
+ * configs unless the target agent has a native enabled toggle.
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.mcpServers === undefined)
21
+ return [];
22
+ return Object.entries(settings.mcpServers).map(([name, entry]) => ({
23
+ name: decodeExtensionNameSync(name),
24
+ entry,
25
+ }));
26
+ };
27
+ const resolvedFromLockfile = (lockfile) => {
28
+ if (lockfile.mcpServers === undefined)
29
+ return [];
30
+ return Object.entries(lockfile.mcpServers).map(([name, lockEntry]) => ({
31
+ name: decodeExtensionNameSync(name),
32
+ lockEntry,
33
+ }));
34
+ };
35
+ const canonicalToActual = (occ, scope) => {
36
+ const packageRoot = canonicalAxmPackageRoot(occ);
37
+ return {
38
+ key: { scope, type: "mcp-server", name: occ.name },
39
+ origin: occ.origin === "canonical-axm"
40
+ ? { _tag: "canonical-axm-mcp-server" }
41
+ : { _tag: "external-axm-mcp-server" },
42
+ contentRoot: occ.contentLocation,
43
+ packageRoot,
44
+ configFile: null,
45
+ config: null,
46
+ };
47
+ };
48
+ const mcpConfigToActual = (occ, scope) => ({
49
+ key: { scope, type: "mcp-server", name: occ.name },
50
+ origin: occ.surface._tag === "shared"
51
+ ? { _tag: "workspace-mcp-config" }
52
+ : { _tag: "agent-mcp-config", agentId: occ.surface.agentId },
53
+ contentRoot: null,
54
+ packageRoot: null,
55
+ configFile: occ.contentLocation,
56
+ config: occ.config,
57
+ });
58
+ const orphanResolvedWarning = (name) => ({
59
+ source: "lockfile",
60
+ message: `mcp-server: lockfile entry "${name}" has no matching declared or pack-member home`,
61
+ code: "orphan-resolved",
62
+ });
63
+ const mcpServerPolicy = (scope) => ({
64
+ declaredEntries: (d) => d,
65
+ declaredName: (e) => e.name,
66
+ declaredActivation: (entry) => (entry.entry.enabled ? "enabled" : "disabled"),
67
+ resolvedEntries: (r) => r,
68
+ resolvedName: (e) => e.name,
69
+ actualEntries: (a) => a,
70
+ actualName: (e) => e.key.name,
71
+ packMemberName: (m) => m.name,
72
+ packMemberActivation: () => "enabled",
73
+ attachActualToInstalled: (name, actual) => actual.filter((a) => a.key.name === name),
74
+ notClaimedBySubjectPolicy: () => true,
75
+ buildInstalledRow: (input) => ({
76
+ key: { scope, type: "mcp-server", name: input.name },
77
+ installationOrigin: input.installationOrigin,
78
+ activation: input.activation,
79
+ resolved: input.resolved,
80
+ actual: input.actual,
81
+ providingPacks: input.providingPacks,
82
+ }),
83
+ buildUnmanagedRow: (entry) => ({
84
+ key: { scope, type: "mcp-server", name: entry.key.name },
85
+ actual: entry,
86
+ }),
87
+ resolvedOrphanWarning: orphanResolvedWarning,
88
+ });
89
+ /**
90
+ * Build the MCP server subject API. Returns an `Effect` because the
91
+ * projection cell is wrapped in `Effect.cached` so the four derived cells
92
+ * share one in-flight execution per scope, mirroring `state.ts`.
93
+ */
94
+ export const makeMcpServerExtensionsApi = (deps) => Effect.gen(function* () {
95
+ const { scope, loaders, scanners, installedPacks, diagnostics } = deps;
96
+ const declared = loaders.settings.pipe(Effect.map((opt) => Option.map(opt, declaredFromSettings)));
97
+ const resolved = loaders.lockfile.pipe(Effect.map((opt) => Option.map(opt, resolvedFromLockfile)));
98
+ const actual = Effect.gen(function* () {
99
+ const canonical = yield* scanners.canonical;
100
+ const mcpConfig = yield* scanners.mcpConfig;
101
+ const fromCanonical = filterMapOccurrences(canonical, "mcp-server", (occ) => canonicalToActual(occ, scope));
102
+ const fromMcpConfig = mcpConfig.map((occ) => mcpConfigToActual(occ, scope));
103
+ return [...fromCanonical, ...fromMcpConfig];
104
+ });
105
+ const project = yield* Effect.cached(projectInstalledExtensions({
106
+ declared,
107
+ resolved,
108
+ actual,
109
+ installedPacks: installedPacks.pipe(Effect.map((packs) => packs.map((p) => ({ ref: p.ref, members: p.mcpServers })))),
110
+ packMembers: (pack) => pack.members,
111
+ packRef: (pack) => pack.ref,
112
+ policy: mcpServerPolicy(scope),
113
+ diagnostics,
114
+ }));
115
+ return makeProjectedSubjectCells({
116
+ declared,
117
+ resolved,
118
+ actual,
119
+ project,
120
+ });
121
+ });
122
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Pack subject module: declared/resolved/actual payloads, scanner composition,
3
+ * and **direct-only** installed projections via the shared helper.
4
+ *
5
+ * Per Decision 9 of the workspace read-model design: packs cannot be members of
6
+ * other packs. The pack subject's own `installed` projection therefore passes
7
+ * an empty installed-pack set into the projection helper, so no pack-member
8
+ * row is ever produced for a pack. Direct pack declarations remain the only
9
+ * way a pack appears in `installed`.
10
+ *
11
+ * Other subjects derive Pack membership from the authored `pack.json`
12
+ * manifest. The lock entry carries only accepted external resolution.
13
+ *
14
+ * Pack activation follows its declared settings entry. Disabled packs retain
15
+ * their declaration, lock data, and canonical content while leaving the
16
+ * active projection.
17
+ */
18
+ import * as Effect from "effect/Effect";
19
+ import * as Option from "effect/Option";
20
+ import { type ExtensionName } from "@agentxm/extension-model/unstable/extensions/common";
21
+ import type { PackLockEntry, Lockfile } from "../../../lockfile/schema.js";
22
+ import type { PackEntry, Settings } from "../../../settings/schema.js";
23
+ import type { Diagnostics } from "../diagnostics.js";
24
+ import type { LockfileReadError, SettingsReadError } from "../errors.js";
25
+ import type { CanonicalExtensionOccurrence } from "../scanners/types.js";
26
+ import type { ActivationState, ExtensionKey, InstallationOrigin, InstalledPackRef, Scope } from "../types.js";
27
+ export type PackDetectionOrigin = {
28
+ readonly _tag: "canonical-axm-pack";
29
+ } | {
30
+ readonly _tag: "external-axm-pack";
31
+ };
32
+ export interface DeclaredPack {
33
+ readonly name: ExtensionName;
34
+ readonly entry: PackEntry;
35
+ }
36
+ export type DeclaredPacks = ReadonlyArray<DeclaredPack>;
37
+ /** Resolved Pack carrying the accepted external-resolution row verbatim. */
38
+ export interface ResolvedPack {
39
+ readonly keyName: string;
40
+ readonly name: ExtensionName;
41
+ readonly lockEntry: PackLockEntry;
42
+ }
43
+ export type ResolvedPacks = ReadonlyArray<ResolvedPack>;
44
+ export interface ActualPack {
45
+ readonly key: ExtensionKey<"pack">;
46
+ readonly origin: PackDetectionOrigin;
47
+ readonly contentRoot: string;
48
+ readonly packageRoot: string | null;
49
+ }
50
+ export type ActualPacks = ReadonlyArray<ActualPack>;
51
+ /**
52
+ * Pack member entry carrying enough info to identify the source pack. Pack
53
+ * subjects do not produce member rows (packs are not pack members), but the
54
+ * shared projection helper still type-parameters its pack-member type, so we
55
+ * supply a never-instantiated placeholder.
56
+ */
57
+ export type PackPackMember = never;
58
+ /**
59
+ * Installed pack row. The installation origin union is widened only to
60
+ * `direct` because packs cannot be pack members. Generic consumers reading
61
+ * `installationOrigin._tag` always observe `"direct"` on a pack row.
62
+ */
63
+ export interface InstalledPack {
64
+ readonly key: ExtensionKey<"pack">;
65
+ readonly installationOrigin: InstallationOrigin<DeclaredPack, PackPackMember>;
66
+ readonly activation: ActivationState;
67
+ readonly resolved: Option.Option<ResolvedPack>;
68
+ readonly actual: ReadonlyArray<ActualPack>;
69
+ readonly providingPacks: ReadonlyArray<InstalledPackRef>;
70
+ }
71
+ export interface UnmanagedPack {
72
+ readonly key: ExtensionKey<"pack">;
73
+ readonly actual: ActualPack;
74
+ }
75
+ export interface PackScopedLoaders {
76
+ readonly settings: Effect.Effect<Option.Option<Settings>, SettingsReadError>;
77
+ readonly lockfile: Effect.Effect<Option.Option<Lockfile>, LockfileReadError>;
78
+ }
79
+ export interface PackScanners {
80
+ readonly canonical: Effect.Effect<ReadonlyArray<CanonicalExtensionOccurrence>>;
81
+ }
82
+ export interface PackExtensionsApiDeps {
83
+ readonly scope: Scope;
84
+ readonly loaders: PackScopedLoaders;
85
+ readonly scanners: PackScanners;
86
+ readonly diagnostics: Diagnostics;
87
+ }
88
+ export interface PackExtensionsApi {
89
+ readonly declared: Effect.Effect<Option.Option<DeclaredPacks>, SettingsReadError>;
90
+ readonly resolved: Effect.Effect<Option.Option<ResolvedPacks>, LockfileReadError>;
91
+ readonly actual: Effect.Effect<ActualPacks>;
92
+ readonly installed: Effect.Effect<ReadonlyArray<InstalledPack>, SettingsReadError | LockfileReadError>;
93
+ readonly byName: (name: string) => Effect.Effect<Option.Option<InstalledPack>, SettingsReadError | LockfileReadError>;
94
+ readonly declaredByName: (name: string) => Effect.Effect<Option.Option<DeclaredPack>, SettingsReadError>;
95
+ readonly active: Effect.Effect<ReadonlyArray<InstalledPack>, SettingsReadError | LockfileReadError>;
96
+ readonly unmanaged: Effect.Effect<ReadonlyArray<UnmanagedPack>, SettingsReadError | LockfileReadError>;
97
+ }
98
+ /**
99
+ * Build the pack subject API. Returns an `Effect` because the projection
100
+ * cell is wrapped in `Effect.cached` so the four derived cells share one
101
+ * in-flight execution per scope, mirroring `state.ts`.
102
+ */
103
+ export declare const makePackExtensionsApi: (deps: PackExtensionsApiDeps) => Effect.Effect<PackExtensionsApi>;
104
+ //# sourceMappingURL=pack.d.ts.map
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Pack subject module: declared/resolved/actual payloads, scanner composition,
3
+ * and **direct-only** installed projections via the shared helper.
4
+ *
5
+ * Per Decision 9 of the workspace read-model design: packs cannot be members of
6
+ * other packs. The pack subject's own `installed` projection therefore passes
7
+ * an empty installed-pack set into the projection helper, so no pack-member
8
+ * row is ever produced for a pack. Direct pack declarations remain the only
9
+ * way a pack appears in `installed`.
10
+ *
11
+ * Other subjects derive Pack membership from the authored `pack.json`
12
+ * manifest. The lock entry carries only accepted external resolution.
13
+ *
14
+ * Pack activation follows its declared settings entry. Disabled packs retain
15
+ * their declaration, lock data, and canonical content while leaving the
16
+ * active projection.
17
+ */
18
+ import * as Effect from "effect/Effect";
19
+ import * as Option from "effect/Option";
20
+ import { decodeExtensionNameSync, parseExtensionFqnParts, } from "@agentxm/extension-model/unstable/extensions/common";
21
+ import { filterMapOccurrences } from "./actual-helpers.js";
22
+ import { canonicalAxmPackageRoot } from "./package-root.js";
23
+ import { makeProjectedSubjectCells, projectInstalledExtensions, } from "./projection.js";
24
+ // ---------------------------------------------------------------------------
25
+ // Helpers
26
+ // ---------------------------------------------------------------------------
27
+ const declaredFromSettings = (settings) => {
28
+ if (settings.packs === undefined)
29
+ return [];
30
+ return Object.entries(settings.packs).map(([name, entry]) => ({
31
+ name: decodeExtensionNameSync(name),
32
+ entry,
33
+ }));
34
+ };
35
+ const resolvedFromLockfile = (lockfile) => {
36
+ if (lockfile.packs === undefined)
37
+ return [];
38
+ return Object.entries(lockfile.packs).map(([keyName, lockEntry]) => {
39
+ const parsed = parseExtensionFqnParts(keyName);
40
+ return {
41
+ keyName,
42
+ name: parsed?.name ?? decodeExtensionNameSync(keyName),
43
+ lockEntry,
44
+ };
45
+ });
46
+ };
47
+ const canonicalToActual = (occ, scope) => {
48
+ const isExternal = occ.origin === "external-axm";
49
+ const packageRoot = canonicalAxmPackageRoot(occ);
50
+ return {
51
+ key: { scope, type: "pack", name: occ.name },
52
+ origin: isExternal ? { _tag: "external-axm-pack" } : { _tag: "canonical-axm-pack" },
53
+ contentRoot: occ.contentLocation,
54
+ packageRoot,
55
+ };
56
+ };
57
+ const orphanResolvedWarning = (name) => ({
58
+ source: "lockfile",
59
+ message: `pack: lockfile entry "${name}" has no matching declared pack`,
60
+ code: "orphan-resolved",
61
+ });
62
+ const packPolicy = (scope) => ({
63
+ declaredEntries: (d) => d,
64
+ declaredName: (e) => e.name,
65
+ declaredActivation: (entry) => (entry.entry.enabled ? "enabled" : "disabled"),
66
+ resolvedEntries: (r) => r,
67
+ resolvedName: (e) => e.name,
68
+ actualEntries: (a) => a,
69
+ actualName: (e) => e.key.name,
70
+ // Pack-member callbacks are unreachable: the subject passes an empty
71
+ // installed-pack set into the projection helper, so the helper never
72
+ // invokes these. The functions still need to satisfy the types.
73
+ packMemberName: (member) => member,
74
+ packMemberActivation: () => "enabled",
75
+ attachActualToInstalled: (name, actual) => actual.filter((a) => a.key.name === name),
76
+ notClaimedBySubjectPolicy: () => true,
77
+ buildInstalledRow: (input) => ({
78
+ key: { scope, type: "pack", name: input.name },
79
+ installationOrigin: input.installationOrigin,
80
+ activation: input.activation,
81
+ resolved: input.resolved,
82
+ actual: input.actual,
83
+ providingPacks: input.providingPacks,
84
+ }),
85
+ buildUnmanagedRow: (entry) => ({
86
+ key: { scope, type: "pack", name: entry.key.name },
87
+ actual: entry,
88
+ }),
89
+ resolvedOrphanWarning: orphanResolvedWarning,
90
+ });
91
+ /**
92
+ * Build the pack 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 const makePackExtensionsApi = (deps) => Effect.gen(function* () {
97
+ const { scope, loaders, scanners, diagnostics } = deps;
98
+ const declared = loaders.settings.pipe(Effect.map((opt) => Option.map(opt, declaredFromSettings)));
99
+ const resolved = loaders.lockfile.pipe(Effect.map((opt) => Option.map(opt, resolvedFromLockfile)));
100
+ const actual = Effect.gen(function* () {
101
+ const canonical = yield* scanners.canonical;
102
+ return filterMapOccurrences(canonical, "pack", (occ) => canonicalToActual(occ, scope));
103
+ });
104
+ // Packs can't be pack members — pass an empty installed-pack set.
105
+ const installedPacks = Effect.succeed([]);
106
+ const project = yield* Effect.cached(projectInstalledExtensions({
107
+ declared,
108
+ resolved,
109
+ actual,
110
+ installedPacks,
111
+ packMembers: (pack) => pack.members,
112
+ packRef: (pack) => pack.ref,
113
+ policy: packPolicy(scope),
114
+ diagnostics,
115
+ }));
116
+ return makeProjectedSubjectCells({
117
+ declared,
118
+ resolved,
119
+ actual,
120
+ project,
121
+ });
122
+ });
123
+ //# sourceMappingURL=pack.js.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Internal helper for computing ancestor paths from scanner-emitted
3
+ * `pathSegments` + `contentLocation` without re-introducing a `Path` service
4
+ * dependency in subject modules.
5
+ *
6
+ * The canonical-extensions scanner already splits `contentLocation` into
7
+ * `pathSegments` via the `Path` service. This helper inverts that: it derives
8
+ * the platform separator from the relationship between the segments and the
9
+ * original string, then joins a prefix back to a path.
10
+ *
11
+ * Why this exists: subject modules need `packageRoot` (the parent or
12
+ * grandparent directory of `contentLocation`). They never see the `Path`
13
+ * service — that lives at the live-layer construction boundary. The scanner's
14
+ * `pathSegments` field carries enough structure to reconstruct any ancestor.
15
+ *
16
+ * Cross-platform behavior:
17
+ *
18
+ * - POSIX `/ws/agent_extensions/agentxm/@o/skills/x/src` →
19
+ * `pathSegments = ["", "ws", "agent_extensions", "agentxm", "@o", "skills", "x", "src"]`.
20
+ * Dropping the trailing `src` segment yields the package root
21
+ * `/ws/agent_extensions/agentxm/@o/skills/x`.
22
+ * - Windows `C:\\ws\\agent_extensions\\agentxm\\@o\\skills\\x\\src` →
23
+ * `pathSegments = ["C:", "ws", "agent_extensions", "agentxm", "@o", "skills", "x", "src"]`.
24
+ * `pathSegments[0]` is `"C:"` (length 2); the separator is
25
+ * `contentLocation.charAt(2) = "\\"`. Joining yields
26
+ * `C:\\ws\\agent_extensions\\agentxm\\@o\\skills`.
27
+ */
28
+ /**
29
+ * Drop the trailing `count` segments from `pathSegments` and rejoin the
30
+ * remainder with the separator inferred from `contentLocation`. Returns the
31
+ * empty string if all segments would be dropped.
32
+ */
33
+ export declare const stripTrailingSegments: (pathSegments: ReadonlyArray<string>, contentLocation: string, count: number) => string;
34
+ export declare const canonicalAxmPackageRoot: (occ: {
35
+ readonly origin: "canonical-axm" | "external-axm";
36
+ readonly pathSegments: ReadonlyArray<string>;
37
+ readonly contentLocation: string;
38
+ }) => string;
39
+ //# sourceMappingURL=package-root.d.ts.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Internal helper for computing ancestor paths from scanner-emitted
3
+ * `pathSegments` + `contentLocation` without re-introducing a `Path` service
4
+ * dependency in subject modules.
5
+ *
6
+ * The canonical-extensions scanner already splits `contentLocation` into
7
+ * `pathSegments` via the `Path` service. This helper inverts that: it derives
8
+ * the platform separator from the relationship between the segments and the
9
+ * original string, then joins a prefix back to a path.
10
+ *
11
+ * Why this exists: subject modules need `packageRoot` (the parent or
12
+ * grandparent directory of `contentLocation`). They never see the `Path`
13
+ * service — that lives at the live-layer construction boundary. The scanner's
14
+ * `pathSegments` field carries enough structure to reconstruct any ancestor.
15
+ *
16
+ * Cross-platform behavior:
17
+ *
18
+ * - POSIX `/ws/agent_extensions/agentxm/@o/skills/x/src` →
19
+ * `pathSegments = ["", "ws", "agent_extensions", "agentxm", "@o", "skills", "x", "src"]`.
20
+ * Dropping the trailing `src` segment yields the package root
21
+ * `/ws/agent_extensions/agentxm/@o/skills/x`.
22
+ * - Windows `C:\\ws\\agent_extensions\\agentxm\\@o\\skills\\x\\src` →
23
+ * `pathSegments = ["C:", "ws", "agent_extensions", "agentxm", "@o", "skills", "x", "src"]`.
24
+ * `pathSegments[0]` is `"C:"` (length 2); the separator is
25
+ * `contentLocation.charAt(2) = "\\"`. Joining yields
26
+ * `C:\\ws\\agent_extensions\\agentxm\\@o\\skills`.
27
+ */
28
+ /**
29
+ * Drop the trailing `count` segments from `pathSegments` and rejoin the
30
+ * remainder with the separator inferred from `contentLocation`. Returns the
31
+ * empty string if all segments would be dropped.
32
+ */
33
+ export const stripTrailingSegments = (pathSegments, contentLocation, count) => {
34
+ if (pathSegments.length <= count)
35
+ return "";
36
+ const sep = contentLocation.charAt(pathSegments[0]?.length ?? 0);
37
+ return pathSegments.slice(0, pathSegments.length - count).join(sep);
38
+ };
39
+ export const canonicalAxmPackageRoot = (occ) => {
40
+ if (occ.origin === "external-axm")
41
+ return occ.contentLocation;
42
+ const last = occ.pathSegments.at(-1);
43
+ if (last === "src") {
44
+ return stripTrailingSegments(occ.pathSegments, occ.contentLocation, 1);
45
+ }
46
+ return occ.contentLocation;
47
+ };
48
+ //# sourceMappingURL=package-root.js.map