@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,391 @@
|
|
|
1
|
+
/** Per-scope read-only workspace model factory and configuration. */
|
|
2
|
+
import * as Brand from "effect/Brand";
|
|
3
|
+
import * as ServiceMap from "effect/Context";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as FileSystem from "effect/FileSystem";
|
|
6
|
+
import * as Option from "effect/Option";
|
|
7
|
+
import * as Path from "effect/Path";
|
|
8
|
+
import * as Ref from "effect/Ref";
|
|
9
|
+
import * as Result from "effect/Result";
|
|
10
|
+
import * as Schema from "effect/Schema";
|
|
11
|
+
import { AgentPresenceProbe } from "./agent-presence.js";
|
|
12
|
+
import { AGENTS } from "@agentxm/extension-model/unstable/agents/registry";
|
|
13
|
+
import { parseExtensionFqnParts, } from "@agentxm/extension-model/unstable/extensions/common";
|
|
14
|
+
import {} from "@agentxm/extension-model/unstable/extensions/handle";
|
|
15
|
+
import { PACK_MANIFEST_FILENAME, PackManifestSchema, } from "@agentxm/extension-model/unstable/packs/manifest-schema";
|
|
16
|
+
import { makeAbsolutePath } from "@agentxm/extension-model/unstable/path-types";
|
|
17
|
+
import { resolveProjectWorkspaceLayout, resolveProjectWorkspaceStatePaths, resolveUserWorkspaceLayout, } from "../layout.js";
|
|
18
|
+
import { AgentRootResolver } from "./agent-root-resolver.js";
|
|
19
|
+
import { makeScopedAgentsApi } from "./agents/index.js";
|
|
20
|
+
import {} from "./agents/types.js";
|
|
21
|
+
import { makeDiagnostics } from "./diagnostics.js";
|
|
22
|
+
import { WorkspaceRootEscape, } from "./errors.js";
|
|
23
|
+
import { makeHookExtensionsApi, makeKnowledgeExtensionsApi, makeMcpServerExtensionsApi, makePackExtensionsApi, makeRuleExtensionsApi, makeSkillExtensionsApi, makeSubagentExtensionsApi, } from "./extensions/index.js";
|
|
24
|
+
import { makeAgentDirScanner, makeAgentSettingsScanner, makeCanonicalExtensionsScanner, makeMcpConfigScanner, } from "./scanners/index.js";
|
|
25
|
+
import { makeScopedStateApi } from "./state.js";
|
|
26
|
+
/**
|
|
27
|
+
* The read-model family that carries each catalog extension type, or `null`
|
|
28
|
+
* where no family exists yet.
|
|
29
|
+
*
|
|
30
|
+
* Total by construction: a new extension type fails compile here until its
|
|
31
|
+
* read-model coverage is decided. The parity conformance suite reads this map
|
|
32
|
+
* to check the read-model obligation, and every `null` must be matched by a
|
|
33
|
+
* ledger row.
|
|
34
|
+
*
|
|
35
|
+
* @experimental This API is unstable and may change without notice.
|
|
36
|
+
*/
|
|
37
|
+
export const READ_MODEL_EXTENSION_FAMILY_BY_TYPE = {
|
|
38
|
+
skill: "skills",
|
|
39
|
+
"mcp-server": "mcpServers",
|
|
40
|
+
subagent: "subagents",
|
|
41
|
+
rule: "rules",
|
|
42
|
+
hook: "hooks",
|
|
43
|
+
knowledge: "knowledge",
|
|
44
|
+
};
|
|
45
|
+
/** Service tag for the {@link WorkspaceReadModelConfigService} the factory requires. */
|
|
46
|
+
export class WorkspaceReadModelConfig extends ServiceMap.Service()("@agentxm/workspace-state/workspace/read-model/service/WorkspaceReadModelConfig") {
|
|
47
|
+
}
|
|
48
|
+
const ResolvedWorkspaceRoot = Brand.nominal();
|
|
49
|
+
/** Resolve and validate a workspace root resides within `allowedRoot`. */
|
|
50
|
+
const validateRoot = (pathSvc, candidate, allowedRoot) => Effect.gen(function* () {
|
|
51
|
+
const resolved = pathSvc.resolve(candidate);
|
|
52
|
+
const resolvedAllowed = pathSvc.resolve(allowedRoot);
|
|
53
|
+
if (resolved === resolvedAllowed)
|
|
54
|
+
return ResolvedWorkspaceRoot(resolved);
|
|
55
|
+
const relative = pathSvc.relative(resolvedAllowed, resolved);
|
|
56
|
+
if (relative !== "" && (relative.startsWith("..") || pathSvc.isAbsolute(relative))) {
|
|
57
|
+
return yield* new WorkspaceRootEscape({
|
|
58
|
+
workspaceRoot: candidate,
|
|
59
|
+
allowedRoot,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return ResolvedWorkspaceRoot(resolved);
|
|
63
|
+
});
|
|
64
|
+
const buildScope = Effect.fn("workspace.read-model.build-scope")(function* (deps) {
|
|
65
|
+
const { scope, fs, path, workspaceRoot, settingsPath, lockfilePath, rootResolverState, diagnosticsRef, } = deps;
|
|
66
|
+
// Diagnostics buffer (Ref provided by the factory so collision warnings
|
|
67
|
+
// detected by the resolver layer can be pre-seeded for the project scope).
|
|
68
|
+
const diagnostics = makeDiagnostics(diagnosticsRef);
|
|
69
|
+
// Cached state-source cells: settings/settingsRaw + lockfile/lockfileRaw.
|
|
70
|
+
const loaders = yield* makeScopedStateApi(scope, {
|
|
71
|
+
fs,
|
|
72
|
+
path,
|
|
73
|
+
settingsPath,
|
|
74
|
+
lockfilePath,
|
|
75
|
+
});
|
|
76
|
+
const settingsResult = yield* Effect.result(loaders.settings);
|
|
77
|
+
const layoutSettings = Result.isSuccess(settingsResult)
|
|
78
|
+
? Option.getOrElse(settingsResult.success, () => ({}))
|
|
79
|
+
: {};
|
|
80
|
+
const resolveLayout = () => scope === "project"
|
|
81
|
+
? resolveProjectWorkspaceLayout(makeAbsolutePath(path, workspaceRoot), layoutSettings).pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path.Path, path))
|
|
82
|
+
: resolveUserWorkspaceLayout(makeAbsolutePath(path, workspaceRoot), layoutSettings).pipe(Effect.provideService(Path.Path, path));
|
|
83
|
+
const layoutResult = yield* Effect.result(resolveLayout());
|
|
84
|
+
if (Result.isFailure(layoutResult)) {
|
|
85
|
+
yield* diagnostics.append({
|
|
86
|
+
source: "scanner",
|
|
87
|
+
message: `workspace-layout: ${layoutResult.failure.message}`,
|
|
88
|
+
code: "scanner-io",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// Scanner cells — eagerly enumerate the closed scanner key set.
|
|
92
|
+
const canonicalScanner = yield* Effect.cached(Result.isFailure(layoutResult)
|
|
93
|
+
? Effect.succeed([])
|
|
94
|
+
: makeCanonicalExtensionsScanner({
|
|
95
|
+
fs,
|
|
96
|
+
path,
|
|
97
|
+
workspaceRoot,
|
|
98
|
+
diagnostics,
|
|
99
|
+
layout: layoutResult.success,
|
|
100
|
+
}));
|
|
101
|
+
const agentDirScanner = yield* Effect.cached(makeAgentDirScanner({
|
|
102
|
+
fs,
|
|
103
|
+
path,
|
|
104
|
+
workspaceRoot,
|
|
105
|
+
scope,
|
|
106
|
+
diagnostics,
|
|
107
|
+
agentRegistry: AGENTS,
|
|
108
|
+
}));
|
|
109
|
+
const mcpConfigScanner = yield* Effect.cached(makeMcpConfigScanner({
|
|
110
|
+
fs,
|
|
111
|
+
path,
|
|
112
|
+
workspaceRoot,
|
|
113
|
+
scope,
|
|
114
|
+
diagnostics,
|
|
115
|
+
agentRegistry: AGENTS,
|
|
116
|
+
}));
|
|
117
|
+
const agentSettingsScanner = yield* Effect.cached(makeAgentSettingsScanner({
|
|
118
|
+
fs,
|
|
119
|
+
path,
|
|
120
|
+
workspaceRoot,
|
|
121
|
+
scope,
|
|
122
|
+
diagnostics,
|
|
123
|
+
agentRegistry: AGENTS,
|
|
124
|
+
rootResolverState,
|
|
125
|
+
}));
|
|
126
|
+
// Build the pack subject first; per-subject pack-member input derives from it.
|
|
127
|
+
const packsApi = yield* makePackExtensionsApi({
|
|
128
|
+
scope,
|
|
129
|
+
loaders,
|
|
130
|
+
scanners: { canonical: canonicalScanner },
|
|
131
|
+
diagnostics,
|
|
132
|
+
});
|
|
133
|
+
// Cache the authored-manifest membership rollup once per scope; shared
|
|
134
|
+
// across subjects. Lock rows authorize external Pack resolution but never
|
|
135
|
+
// provide membership.
|
|
136
|
+
const installedPackMembers = yield* Effect.cached(Effect.gen(function* () {
|
|
137
|
+
const active = yield* packsApi.active;
|
|
138
|
+
return yield* Effect.forEach(active, (row) => {
|
|
139
|
+
const packageRoot = row.actual.flatMap((actual) => actual.packageRoot === null ? [] : [actual.packageRoot])[0];
|
|
140
|
+
const empty = {
|
|
141
|
+
key: row.key,
|
|
142
|
+
skills: [],
|
|
143
|
+
mcpServers: [],
|
|
144
|
+
subagents: [],
|
|
145
|
+
rules: [],
|
|
146
|
+
hooks: [],
|
|
147
|
+
knowledge: [],
|
|
148
|
+
};
|
|
149
|
+
if (packageRoot === undefined)
|
|
150
|
+
return Effect.succeed(empty);
|
|
151
|
+
const manifestPath = path.join(packageRoot, PACK_MANIFEST_FILENAME);
|
|
152
|
+
return Effect.gen(function* () {
|
|
153
|
+
const contents = yield* fs.readFileString(manifestPath);
|
|
154
|
+
const parsedResult = Result.try({
|
|
155
|
+
try: () => JSON.parse(contents),
|
|
156
|
+
catch: () => "invalid-pack-manifest-json",
|
|
157
|
+
});
|
|
158
|
+
if (Result.isFailure(parsedResult)) {
|
|
159
|
+
return yield* Effect.fail(parsedResult.failure);
|
|
160
|
+
}
|
|
161
|
+
const manifest = yield* Schema.decodeUnknownEffect(PackManifestSchema)(parsedResult.success);
|
|
162
|
+
const members = {
|
|
163
|
+
skill: [],
|
|
164
|
+
"mcp-server": [],
|
|
165
|
+
subagent: [],
|
|
166
|
+
rule: [],
|
|
167
|
+
hook: [],
|
|
168
|
+
knowledge: [],
|
|
169
|
+
};
|
|
170
|
+
for (const fqn of Object.keys(manifest.dependencies)) {
|
|
171
|
+
const member = parseExtensionFqnParts(fqn);
|
|
172
|
+
if (member !== undefined && member.type !== "pack") {
|
|
173
|
+
members[member.type].push(member.name);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
key: row.key,
|
|
178
|
+
skills: members.skill,
|
|
179
|
+
mcpServers: members["mcp-server"],
|
|
180
|
+
subagents: members.subagent,
|
|
181
|
+
rules: members.rule,
|
|
182
|
+
hooks: members.hook,
|
|
183
|
+
knowledge: members.knowledge,
|
|
184
|
+
};
|
|
185
|
+
}).pipe(Effect.result, Effect.flatMap((result) => Result.isSuccess(result)
|
|
186
|
+
? Effect.succeed(result.success)
|
|
187
|
+
: diagnostics
|
|
188
|
+
.append({
|
|
189
|
+
source: "scanner",
|
|
190
|
+
path: manifestPath,
|
|
191
|
+
code: "pack-manifest-invalid",
|
|
192
|
+
message: `pack: unable to read authored membership from ${manifestPath}`,
|
|
193
|
+
})
|
|
194
|
+
.pipe(Effect.as(empty))));
|
|
195
|
+
});
|
|
196
|
+
}));
|
|
197
|
+
const skillsInstalledPacks = installedPackMembers.pipe(Effect.map((packs) => packs.map((p) => ({
|
|
198
|
+
ref: { key: p.key },
|
|
199
|
+
skills: p.skills.map((name) => ({
|
|
200
|
+
name,
|
|
201
|
+
providingPack: { key: p.key },
|
|
202
|
+
})),
|
|
203
|
+
}))));
|
|
204
|
+
const mcpServersInstalledPacks = installedPackMembers.pipe(Effect.map((packs) => packs.map((p) => ({
|
|
205
|
+
ref: { key: p.key },
|
|
206
|
+
mcpServers: p.mcpServers.map((name) => ({
|
|
207
|
+
name,
|
|
208
|
+
providingPack: { key: p.key },
|
|
209
|
+
})),
|
|
210
|
+
}))));
|
|
211
|
+
const subagentsInstalledPacks = installedPackMembers.pipe(Effect.map((packs) => packs.map((p) => ({
|
|
212
|
+
ref: { key: p.key },
|
|
213
|
+
subagents: p.subagents.map((name) => ({
|
|
214
|
+
name,
|
|
215
|
+
providingPack: { key: p.key },
|
|
216
|
+
})),
|
|
217
|
+
}))));
|
|
218
|
+
const rulesInstalledPacks = installedPackMembers.pipe(Effect.map((packs) => packs.map((p) => ({
|
|
219
|
+
ref: { key: p.key },
|
|
220
|
+
rules: p.rules.map((name) => ({
|
|
221
|
+
name,
|
|
222
|
+
providingPack: { key: p.key },
|
|
223
|
+
})),
|
|
224
|
+
}))));
|
|
225
|
+
const hooksInstalledPacks = installedPackMembers.pipe(Effect.map((packs) => packs.map((p) => ({
|
|
226
|
+
ref: { key: p.key },
|
|
227
|
+
hooks: p.hooks.map((name) => ({
|
|
228
|
+
name,
|
|
229
|
+
providingPack: { key: p.key },
|
|
230
|
+
})),
|
|
231
|
+
}))));
|
|
232
|
+
const knowledgeInstalledPacks = installedPackMembers.pipe(Effect.map((packs) => packs.map((p) => ({
|
|
233
|
+
ref: { key: p.key },
|
|
234
|
+
knowledge: p.knowledge.map((name) => ({
|
|
235
|
+
name,
|
|
236
|
+
providingPack: { key: p.key },
|
|
237
|
+
})),
|
|
238
|
+
}))));
|
|
239
|
+
const skills = yield* makeSkillExtensionsApi({
|
|
240
|
+
scope,
|
|
241
|
+
loaders,
|
|
242
|
+
scanners: { canonical: canonicalScanner, agentDir: agentDirScanner },
|
|
243
|
+
installedPacks: skillsInstalledPacks,
|
|
244
|
+
diagnostics,
|
|
245
|
+
});
|
|
246
|
+
const mcpServers = yield* makeMcpServerExtensionsApi({
|
|
247
|
+
scope,
|
|
248
|
+
loaders,
|
|
249
|
+
scanners: { canonical: canonicalScanner, mcpConfig: mcpConfigScanner },
|
|
250
|
+
installedPacks: mcpServersInstalledPacks,
|
|
251
|
+
diagnostics,
|
|
252
|
+
});
|
|
253
|
+
const subagents = yield* makeSubagentExtensionsApi({
|
|
254
|
+
scope,
|
|
255
|
+
loaders,
|
|
256
|
+
scanners: { canonical: canonicalScanner, agentDir: agentDirScanner },
|
|
257
|
+
installedPacks: subagentsInstalledPacks,
|
|
258
|
+
diagnostics,
|
|
259
|
+
});
|
|
260
|
+
const rules = yield* makeRuleExtensionsApi({
|
|
261
|
+
scope,
|
|
262
|
+
loaders,
|
|
263
|
+
scanners: { canonical: canonicalScanner },
|
|
264
|
+
installedPacks: rulesInstalledPacks,
|
|
265
|
+
diagnostics,
|
|
266
|
+
});
|
|
267
|
+
const hooks = yield* makeHookExtensionsApi({
|
|
268
|
+
scope,
|
|
269
|
+
loaders,
|
|
270
|
+
scanners: { canonical: canonicalScanner },
|
|
271
|
+
installedPacks: hooksInstalledPacks,
|
|
272
|
+
diagnostics,
|
|
273
|
+
});
|
|
274
|
+
const knowledge = yield* makeKnowledgeExtensionsApi({
|
|
275
|
+
scope,
|
|
276
|
+
loaders,
|
|
277
|
+
scanners: { canonical: canonicalScanner },
|
|
278
|
+
installedPacks: knowledgeInstalledPacks,
|
|
279
|
+
diagnostics,
|
|
280
|
+
});
|
|
281
|
+
// Cached fold of the three scanner cells into the shape agents expects.
|
|
282
|
+
const observations = yield* Effect.cached(Effect.gen(function* () {
|
|
283
|
+
const agentDir = yield* agentDirScanner;
|
|
284
|
+
const agentSettings = yield* agentSettingsScanner;
|
|
285
|
+
const mcpConfig = yield* mcpConfigScanner;
|
|
286
|
+
return { agentDir, agentSettings, mcpConfig };
|
|
287
|
+
}));
|
|
288
|
+
// Project settings into the narrowed `DeclaredSettingsShape` agents needs.
|
|
289
|
+
const agentsSettings = loaders.settings.pipe(Effect.map((opt) => Option.map(opt, (settings) => ({
|
|
290
|
+
agents: settings.agents ?? [],
|
|
291
|
+
}))));
|
|
292
|
+
const presenceProbe = yield* Effect.serviceOption(AgentPresenceProbe);
|
|
293
|
+
const presence = yield* Effect.cached(Option.match(presenceProbe, {
|
|
294
|
+
onNone: () => Effect.succeed(new Set()),
|
|
295
|
+
onSome: (probe) => probe.detect(workspaceRoot, scope).pipe(Effect.map((detected) => new Set(detected)), Effect.catch((error) => diagnostics
|
|
296
|
+
.append({
|
|
297
|
+
source: "scanner",
|
|
298
|
+
message: `agent-presence: structured detection failed: ${error.message}`,
|
|
299
|
+
code: "scanner-io",
|
|
300
|
+
})
|
|
301
|
+
.pipe(Effect.map(() => new Set())))),
|
|
302
|
+
}));
|
|
303
|
+
const agents = makeScopedAgentsApi({
|
|
304
|
+
scope,
|
|
305
|
+
settings: agentsSettings,
|
|
306
|
+
presence,
|
|
307
|
+
observations,
|
|
308
|
+
});
|
|
309
|
+
// Source-host views over the cached settings loader.
|
|
310
|
+
const emptySources = [];
|
|
311
|
+
const declaredSourceHosts = loaders.settings.pipe(Effect.map((opt) => Option.match(opt, {
|
|
312
|
+
onNone: () => emptySources,
|
|
313
|
+
onSome: (settings) => settings.sources ?? emptySources,
|
|
314
|
+
})));
|
|
315
|
+
const sourceHosts = {
|
|
316
|
+
declared: declaredSourceHosts,
|
|
317
|
+
effective: declaredSourceHosts,
|
|
318
|
+
registryHosts: declaredSourceHosts.pipe(Effect.map((all) => all.filter((s) => s.type === "registry"))),
|
|
319
|
+
byName: (name) => declaredSourceHosts.pipe(Effect.map((all) => Option.fromUndefinedOr(all.find((s) => s.name === name)))),
|
|
320
|
+
};
|
|
321
|
+
// Owner view over the cached settings loader.
|
|
322
|
+
const owner = loaders.settings.pipe(Effect.map((opt) => Option.flatMap(opt, (settings) => Option.fromUndefinedOr(settings.owner))));
|
|
323
|
+
// Raw-bytes accessor reads from the cached raw cell; absent (`Option.none`)
|
|
324
|
+
// is distinct from unreadable (IO error in the channel).
|
|
325
|
+
const raw = (source) => source === "settings" ? loaders.settingsRaw : loaders.lockfileRaw;
|
|
326
|
+
const state = {
|
|
327
|
+
settings: loaders.settings,
|
|
328
|
+
lockfile: loaders.lockfile,
|
|
329
|
+
raw,
|
|
330
|
+
};
|
|
331
|
+
return {
|
|
332
|
+
scope,
|
|
333
|
+
skills,
|
|
334
|
+
mcpServers,
|
|
335
|
+
subagents,
|
|
336
|
+
rules,
|
|
337
|
+
hooks,
|
|
338
|
+
knowledge,
|
|
339
|
+
packs: packsApi,
|
|
340
|
+
agents,
|
|
341
|
+
state,
|
|
342
|
+
sourceHosts,
|
|
343
|
+
owner,
|
|
344
|
+
diagnostics: diagnostics.snapshot,
|
|
345
|
+
canonicalExtensions: canonicalScanner,
|
|
346
|
+
};
|
|
347
|
+
});
|
|
348
|
+
// ---------------------------------------------------------------------------
|
|
349
|
+
// Per-scope factory
|
|
350
|
+
// ---------------------------------------------------------------------------
|
|
351
|
+
/**
|
|
352
|
+
* Build a {@link WorkspaceReadModel} for the requested scope.
|
|
353
|
+
*
|
|
354
|
+
* Each invocation produces a fresh instance with its own cached cells; call
|
|
355
|
+
* once at the command boundary and pass the value inward. Callers that need
|
|
356
|
+
* both scopes invoke the factory twice.
|
|
357
|
+
*
|
|
358
|
+
* Cross-scope state (the agent-root resolver and its collision warnings) is
|
|
359
|
+
* supplied by {@link AgentRootResolver}, which must be provided in the
|
|
360
|
+
* environment so the same warnings flow into every scope built against the
|
|
361
|
+
* same layer.
|
|
362
|
+
*/
|
|
363
|
+
export const makeWorkspaceReadModel = (scope) => Effect.gen(function* () {
|
|
364
|
+
const fs = yield* FileSystem.FileSystem;
|
|
365
|
+
const pathSvc = yield* Path.Path;
|
|
366
|
+
const config = yield* WorkspaceReadModelConfig;
|
|
367
|
+
const resolver = yield* AgentRootResolver;
|
|
368
|
+
// Validate roots eagerly — the only path that surfaces `WorkspaceRootEscape`.
|
|
369
|
+
const projectRootResolved = yield* validateRoot(pathSvc, config.projectRoot, config.allowedRoot);
|
|
370
|
+
const userHomeResolved = yield* validateRoot(pathSvc, config.userHome, config.allowedRoot);
|
|
371
|
+
// Workspace path layout per scope.
|
|
372
|
+
const workspaceRoot = scope === "project" ? projectRootResolved : userHomeResolved;
|
|
373
|
+
const projectPaths = resolveProjectWorkspaceStatePaths(pathSvc, config.projectRoot);
|
|
374
|
+
const userLayout = yield* resolveUserWorkspaceLayout(makeAbsolutePath(pathSvc, userHomeResolved)).pipe(Effect.provideService(Path.Path, pathSvc));
|
|
375
|
+
const settingsPath = scope === "project" ? projectPaths.settingsPath : userLayout.settingsPath;
|
|
376
|
+
const lockfilePath = scope === "project" ? projectPaths.lockPath : userLayout.lockPath;
|
|
377
|
+
// Pre-seed agent-root collision warnings into the project scope only;
|
|
378
|
+
// the user scope receives a clean buffer.
|
|
379
|
+
const diagnosticsRef = yield* Ref.make(scope === "project" ? resolver.collisionWarnings : []);
|
|
380
|
+
return yield* buildScope({
|
|
381
|
+
scope,
|
|
382
|
+
fs,
|
|
383
|
+
path: pathSvc,
|
|
384
|
+
workspaceRoot,
|
|
385
|
+
settingsPath,
|
|
386
|
+
lockfilePath,
|
|
387
|
+
rootResolverState: resolver.state,
|
|
388
|
+
diagnosticsRef,
|
|
389
|
+
});
|
|
390
|
+
}).pipe(Effect.withSpan("workspace.read-model.make"));
|
|
391
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Cached scoped state-source loaders for `axm.json` and `axm-lock.yaml`. */
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import type * as FileSystem from "effect/FileSystem";
|
|
4
|
+
import * as Option from "effect/Option";
|
|
5
|
+
import type * as Path from "effect/Path";
|
|
6
|
+
import { type Lockfile } from "../../lockfile/schema.js";
|
|
7
|
+
import { type Settings } from "../../settings/schema.js";
|
|
8
|
+
import { LockfileIoError, type LockfileReadError, SettingsIoError, type SettingsReadError } from "./errors.js";
|
|
9
|
+
import type { Scope } from "./types.js";
|
|
10
|
+
/** Decoded `axm.json` payload exposed by the settings cell. */
|
|
11
|
+
export type DecodedSettings = Settings;
|
|
12
|
+
/** Decoded `axm-lock.yaml` payload exposed by the lockfile cell. */
|
|
13
|
+
export type DecodedLockfile = Lockfile;
|
|
14
|
+
/** Raw bytes of a workspace source file (path + literal content). */
|
|
15
|
+
export interface RawSourceBytes {
|
|
16
|
+
readonly path: string;
|
|
17
|
+
readonly bytes: string;
|
|
18
|
+
}
|
|
19
|
+
/** Cached decoded settings/lockfile cells plus their raw-bytes siblings. */
|
|
20
|
+
export interface ScopedStateLoaders {
|
|
21
|
+
readonly settings: Effect.Effect<Option.Option<DecodedSettings>, SettingsReadError>;
|
|
22
|
+
readonly lockfile: Effect.Effect<Option.Option<DecodedLockfile>, LockfileReadError>;
|
|
23
|
+
readonly settingsRaw: Effect.Effect<Option.Option<RawSourceBytes>, SettingsIoError>;
|
|
24
|
+
readonly lockfileRaw: Effect.Effect<Option.Option<RawSourceBytes>, LockfileIoError>;
|
|
25
|
+
}
|
|
26
|
+
/** Construction inputs captured and threaded into every cached loader. */
|
|
27
|
+
export interface ScopedStateDeps {
|
|
28
|
+
readonly fs: FileSystem.FileSystem;
|
|
29
|
+
readonly path: Path.Path;
|
|
30
|
+
readonly settingsPath: string;
|
|
31
|
+
readonly lockfilePath: string | null;
|
|
32
|
+
}
|
|
33
|
+
/** Build the cached, requirement-free `ScopedStateLoaders` for one scope. */
|
|
34
|
+
export declare const makeScopedStateApi: (_scope: Scope, deps: ScopedStateDeps) => Effect.Effect<ScopedStateLoaders>;
|
|
35
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** Cached scoped state-source loaders for `axm.json` and `axm-lock.yaml`. */
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Option from "effect/Option";
|
|
4
|
+
import * as Schema from "effect/Schema";
|
|
5
|
+
import YAML from "yaml";
|
|
6
|
+
import { LockfileSchema } from "../../lockfile/schema.js";
|
|
7
|
+
import { formatSchemaIssuesToLines } from "@agentxm/extension-model/unstable/schema-issues";
|
|
8
|
+
import { SettingsSchema } from "../../settings/schema.js";
|
|
9
|
+
import { LockfileDecodeError, LockfileIoError, LockfileParseError, SettingsDecodeError, SettingsIoError, SettingsParseError, } from "./errors.js";
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Raw bytes loaders (shared by the decoded loaders and the public raw cells)
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
const loadRawSettingsBytes = Effect.fn("workspace.read-model.state.settings.raw")(function* (deps) {
|
|
14
|
+
const { fs, settingsPath } = deps;
|
|
15
|
+
const exists = yield* fs
|
|
16
|
+
.exists(settingsPath)
|
|
17
|
+
.pipe(Effect.mapError((cause) => new SettingsIoError({ path: settingsPath, cause })));
|
|
18
|
+
if (!exists)
|
|
19
|
+
return Option.none();
|
|
20
|
+
const bytes = yield* fs
|
|
21
|
+
.readFileString(settingsPath)
|
|
22
|
+
.pipe(Effect.mapError((cause) => new SettingsIoError({ path: settingsPath, cause })));
|
|
23
|
+
return Option.some({ path: settingsPath, bytes });
|
|
24
|
+
});
|
|
25
|
+
const loadRawLockfileBytes = Effect.fn("workspace.read-model.state.lockfile.raw")(function* (deps) {
|
|
26
|
+
const { fs, lockfilePath } = deps;
|
|
27
|
+
const exists = yield* fs
|
|
28
|
+
.exists(lockfilePath)
|
|
29
|
+
.pipe(Effect.mapError((cause) => new LockfileIoError({ path: lockfilePath, cause })));
|
|
30
|
+
if (!exists)
|
|
31
|
+
return Option.none();
|
|
32
|
+
const bytes = yield* fs
|
|
33
|
+
.readFileString(lockfilePath)
|
|
34
|
+
.pipe(Effect.mapError((cause) => new LockfileIoError({ path: lockfilePath, cause })));
|
|
35
|
+
return Option.some({ path: lockfilePath, bytes });
|
|
36
|
+
});
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Settings loader (decode pipeline) — sources bytes from the cached raw cell
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
/** Decode settings from cached raw bytes. Source-independent (Decision 2). */
|
|
41
|
+
const loadSettings = (rawCell) => Effect.gen(function* () {
|
|
42
|
+
const rawOpt = yield* rawCell;
|
|
43
|
+
if (Option.isNone(rawOpt))
|
|
44
|
+
return Option.none();
|
|
45
|
+
const { path, bytes } = rawOpt.value;
|
|
46
|
+
const parsed = yield* Effect.try({
|
|
47
|
+
try: () => JSON.parse(bytes),
|
|
48
|
+
catch: (cause) => new SettingsParseError({ path, raw: bytes, cause }),
|
|
49
|
+
});
|
|
50
|
+
const decoded = yield* Schema.decodeUnknownEffect(SettingsSchema)(parsed, {
|
|
51
|
+
onExcessProperty: "error",
|
|
52
|
+
}).pipe(Effect.mapError((error) => {
|
|
53
|
+
return new SettingsDecodeError({
|
|
54
|
+
path,
|
|
55
|
+
issues: formatSchemaIssuesToLines(error.issue),
|
|
56
|
+
raw: parsed,
|
|
57
|
+
});
|
|
58
|
+
}));
|
|
59
|
+
return Option.some(decoded);
|
|
60
|
+
}).pipe(Effect.withSpan("workspace.read-model.state.settings"));
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Lockfile loader (decode pipeline) — sources bytes from the cached raw cell
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
/** Decode lockfile from cached raw bytes. Source-independent (Decision 2). */
|
|
65
|
+
const loadLockfile = (rawCell) => Effect.gen(function* () {
|
|
66
|
+
const rawOpt = yield* rawCell;
|
|
67
|
+
if (Option.isNone(rawOpt))
|
|
68
|
+
return Option.none();
|
|
69
|
+
const { path, bytes } = rawOpt.value;
|
|
70
|
+
const parsed = yield* Effect.try({
|
|
71
|
+
try: () => YAML.parse(bytes),
|
|
72
|
+
catch: (cause) => new LockfileParseError({ path, raw: bytes, cause }),
|
|
73
|
+
});
|
|
74
|
+
const decoded = yield* Schema.decodeUnknownEffect(LockfileSchema)(parsed).pipe(Effect.mapError((error) => new LockfileDecodeError({
|
|
75
|
+
path,
|
|
76
|
+
issues: formatSchemaIssuesToLines(error.issue),
|
|
77
|
+
raw: parsed,
|
|
78
|
+
})));
|
|
79
|
+
return Option.some(decoded);
|
|
80
|
+
}).pipe(Effect.withSpan("workspace.read-model.state.lockfile"));
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Public API
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
/** Build the cached, requirement-free `ScopedStateLoaders` for one scope. */
|
|
85
|
+
export const makeScopedStateApi = (_scope, deps) => Effect.gen(function* () {
|
|
86
|
+
const { fs, settingsPath, lockfilePath } = deps;
|
|
87
|
+
const settingsRaw = yield* Effect.cached(loadRawSettingsBytes({ fs, settingsPath }));
|
|
88
|
+
const settings = yield* Effect.cached(loadSettings(settingsRaw));
|
|
89
|
+
const lockfileRaw = lockfilePath === null
|
|
90
|
+
? Effect.succeed(Option.none())
|
|
91
|
+
: yield* Effect.cached(loadRawLockfileBytes({ fs, lockfilePath }));
|
|
92
|
+
const lockfile = lockfilePath === null
|
|
93
|
+
? Effect.succeed(Option.none())
|
|
94
|
+
: yield* Effect.cached(loadLockfile(lockfileRaw));
|
|
95
|
+
return { settings, lockfile, settingsRaw, lockfileRaw };
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared, non-circular type declarations for the WorkspaceReadModel capability.
|
|
3
|
+
*
|
|
4
|
+
* Subject modules under `extensions/` and `agents/` own their payload types;
|
|
5
|
+
* this file holds only subject-agnostic declarations referenced from multiple
|
|
6
|
+
* places (Scope, ExtensionKey, ActivationState, InstallationOrigin, the
|
|
7
|
+
* empty-shape ExtensionStateReader contract, and the public surface contracts
|
|
8
|
+
* for WorkspaceReadModel / ScopedStateApi / ScopedSourceHostsApi /
|
|
9
|
+
* ScopedOwnerApi / ScopedAgentsApi).
|
|
10
|
+
*
|
|
11
|
+
* Source-backed cell failure channels carry per-source tagged error unions
|
|
12
|
+
* imported from `errors.ts`: `SettingsReadError` for `declared` and
|
|
13
|
+
* `LockfileReadError` for `resolved`.
|
|
14
|
+
*/
|
|
15
|
+
import type * as Effect from "effect/Effect";
|
|
16
|
+
import type * as Option from "effect/Option";
|
|
17
|
+
import type { ExtensionType } from "@agentxm/extension-model/unstable/extensions/common";
|
|
18
|
+
import type { LockfileReadError, SettingsReadError } from "./errors.js";
|
|
19
|
+
/**
|
|
20
|
+
* Workspace scope discriminator. Project state is read from the project root;
|
|
21
|
+
* user state is read from `.axm/workspace/` under the resolved user home.
|
|
22
|
+
*/
|
|
23
|
+
export type Scope = "project" | "user";
|
|
24
|
+
/**
|
|
25
|
+
* Stable identity for an extension row across declared, resolved, actual, and
|
|
26
|
+
* projection cells. Subject modules reuse this shape for their projection rows.
|
|
27
|
+
*/
|
|
28
|
+
export interface ExtensionKey<TType extends ExtensionType = ExtensionType> {
|
|
29
|
+
readonly scope: Scope;
|
|
30
|
+
readonly type: TType;
|
|
31
|
+
readonly name: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Activation state on installed rows for subjects that support it.
|
|
35
|
+
*
|
|
36
|
+
* Subjects without a configurable activation flag use `enabled` by policy.
|
|
37
|
+
*/
|
|
38
|
+
export type ActivationState = "enabled" | "disabled";
|
|
39
|
+
/**
|
|
40
|
+
* Why an installed row exists. Direct rows carry the declared entry; pack
|
|
41
|
+
* member rows carry the installed pack reference and the resolved member.
|
|
42
|
+
*/
|
|
43
|
+
export type InstallationOrigin<TDeclared, TPackMember> = {
|
|
44
|
+
readonly _tag: "direct";
|
|
45
|
+
readonly declared: TDeclared;
|
|
46
|
+
} | {
|
|
47
|
+
readonly _tag: "pack-member";
|
|
48
|
+
readonly member: TPackMember;
|
|
49
|
+
readonly pack: InstalledPackRef;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Reference to an installed pack carried on pack-member installation origins.
|
|
53
|
+
*
|
|
54
|
+
* Subject modules that need pack-member rows narrow this further; phase 7
|
|
55
|
+
* defines the concrete shape on the pack subject module.
|
|
56
|
+
*/
|
|
57
|
+
export interface InstalledPackRef {
|
|
58
|
+
readonly key: ExtensionKey<"pack">;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Empty-shape contract for the three independent layers per subject. Each
|
|
62
|
+
* subject module instantiates this with its own payload types.
|
|
63
|
+
*
|
|
64
|
+
* The failure channels are intentionally narrow: `declared` only fails with
|
|
65
|
+
* `SettingsReadError` (3 tags), `resolved` only fails with
|
|
66
|
+
* `LockfileReadError` (3 tags), and `actual` never fails — workspace-root
|
|
67
|
+
* path-escape is validated once at provider construction (Layer-level), not
|
|
68
|
+
* per cell.
|
|
69
|
+
*/
|
|
70
|
+
export interface ExtensionStateReader<TDeclared, TResolved, TActual> {
|
|
71
|
+
readonly declared: Effect.Effect<Option.Option<TDeclared>, SettingsReadError>;
|
|
72
|
+
readonly resolved: Effect.Effect<Option.Option<TResolved>, LockfileReadError>;
|
|
73
|
+
readonly actual: Effect.Effect<TActual>;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared, non-circular type declarations for the WorkspaceReadModel capability.
|
|
3
|
+
*
|
|
4
|
+
* Subject modules under `extensions/` and `agents/` own their payload types;
|
|
5
|
+
* this file holds only subject-agnostic declarations referenced from multiple
|
|
6
|
+
* places (Scope, ExtensionKey, ActivationState, InstallationOrigin, the
|
|
7
|
+
* empty-shape ExtensionStateReader contract, and the public surface contracts
|
|
8
|
+
* for WorkspaceReadModel / ScopedStateApi / ScopedSourceHostsApi /
|
|
9
|
+
* ScopedOwnerApi / ScopedAgentsApi).
|
|
10
|
+
*
|
|
11
|
+
* Source-backed cell failure channels carry per-source tagged error unions
|
|
12
|
+
* imported from `errors.ts`: `SettingsReadError` for `declared` and
|
|
13
|
+
* `LockfileReadError` for `resolved`.
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
|
16
|
+
// -----------------------------------------------------------------------------
|
|
17
|
+
// Public scoped surfaces — concrete shapes live in `context.ts`
|
|
18
|
+
// -----------------------------------------------------------------------------
|
|
19
|
+
//
|
|
20
|
+
// `service.ts` (Phase 9) defines the real `ScopedStateApi`,
|
|
21
|
+
// `ScopedSourceHostsApi`, `ScopedOwnerApi`, and `WorkspaceReadModel`
|
|
22
|
+
// surfaces. They attach payload types from per-subject modules under
|
|
23
|
+
// `extensions/` and per-agent modules under `agents/`, which would create
|
|
24
|
+
// import cycles if defined here. `ScopedAgentsApi` is owned by
|
|
25
|
+
// `agents/index.ts` for the same reason.
|
|
26
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
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 type * as Path from "effect/Path";
|
|
9
|
+
import { type InstallableExtensionType } from "@agentxm/extension-model/unstable/extensions/installable-types";
|
|
10
|
+
import type { WorkspaceStateReadFailure } from "./service-interface.js";
|
|
11
|
+
import type { DesiredStateGraph } from "./desired-state-graph.js";
|
|
12
|
+
import type { LockfileReadError, SettingsReadError } from "./read-model/errors.js";
|
|
13
|
+
import { type ExtensionInventory } from "./read-model/extensions/inventory.js";
|
|
14
|
+
import type { WorkspaceReadModel } from "./read-model/service.js";
|
|
15
|
+
import type { ReadModelRecordRow } from "./read-model-record-types.js";
|
|
16
|
+
type WorkspaceManagedExtensionType = InstallableExtensionType;
|
|
17
|
+
type ReadScopedContext = <A>(f: (scoped: WorkspaceReadModel) => Effect.Effect<A, SettingsReadError | LockfileReadError>) => Effect.Effect<A, WorkspaceStateReadFailure>;
|
|
18
|
+
export interface ReadModelRecordReaders {
|
|
19
|
+
readonly getInventory: (options: {
|
|
20
|
+
readonly type?: InstallableExtensionType;
|
|
21
|
+
}) => Effect.Effect<ExtensionInventory, WorkspaceStateReadFailure>;
|
|
22
|
+
readonly getReadModelRecordRows: (type: WorkspaceManagedExtensionType) => Effect.Effect<ReadonlyArray<ReadModelRecordRow>, WorkspaceStateReadFailure>;
|
|
23
|
+
readonly getExtensionInventory: (type: WorkspaceManagedExtensionType, options: {
|
|
24
|
+
readonly agents?: ReadonlyArray<string>;
|
|
25
|
+
}) => Effect.Effect<ExtensionInventory, WorkspaceStateReadFailure>;
|
|
26
|
+
}
|
|
27
|
+
export declare const makeReadModelRecordReaders: (args: {
|
|
28
|
+
readonly baseDir: string;
|
|
29
|
+
readonly path: Path.Path;
|
|
30
|
+
readonly readScopedContext: ReadScopedContext;
|
|
31
|
+
readonly getDesiredStateGraph: () => Effect.Effect<DesiredStateGraph, WorkspaceStateReadFailure>;
|
|
32
|
+
}) => ReadModelRecordReaders;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=read-model-record-readers.d.ts.map
|