@metaobjectsdev/sdk 0.7.0-rc.1 → 0.7.0-rc.3

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/dist/memory.js CHANGED
@@ -60,21 +60,25 @@ async function collectMetadataPaths(repoRoot) {
60
60
  for (const pkg of ordered) {
61
61
  // Each workspace package's metadata lives alongside its .meta/ dir
62
62
  const pkgRoot = join(pkg.metaDir, "..");
63
- paths.push(...(await listJsonFiles(join(pkgRoot, DEFAULT_METADATA_DIR))));
63
+ paths.push(...(await listMetadataFiles(join(pkgRoot, DEFAULT_METADATA_DIR))));
64
64
  }
65
65
  return paths;
66
66
  }
67
67
  }
68
68
  // Single-package path: scan metaobjects/ at the project root
69
- return listJsonFiles(join(repoRoot, DEFAULT_METADATA_DIR));
69
+ return listMetadataFiles(join(repoRoot, DEFAULT_METADATA_DIR));
70
70
  }
71
71
  /**
72
- * Recursively list *.json files under a directory, excluding _pending/ at
73
- * any level. Subdirectories (e.g. projections/) are walked depth-first.
74
- * Files within a directory are sorted alphabetically for deterministic load
75
- * order; subdirectories are visited after files at the same level.
72
+ * Recursively list metadata files (*.json, *.yaml, *.yml) under a directory,
73
+ * excluding _pending/ at any level. Subdirectories (e.g. projections/) are
74
+ * walked depth-first. Files within a directory are sorted alphabetically for
75
+ * deterministic load order; subdirectories are visited after files at the
76
+ * same level.
77
+ *
78
+ * Format selection (parsing) happens downstream in `FileSource` from
79
+ * `@metaobjectsdev/metadata`, which infers the parser from file extension.
76
80
  */
77
- async function listJsonFiles(dir) {
81
+ async function listMetadataFiles(dir) {
78
82
  let entries;
79
83
  try {
80
84
  entries = await readdir(dir);
@@ -92,14 +96,17 @@ async function listJsonFiles(dir) {
92
96
  if (s.isDirectory()) {
93
97
  subdirs.push(full);
94
98
  }
95
- else if (s.isFile() && entry.endsWith(".json")) {
99
+ else if (s.isFile() && isMetadataFile(entry)) {
96
100
  paths.push(full);
97
101
  }
98
102
  }
99
103
  // Recurse into subdirectories after collecting files at this level
100
104
  for (const sub of subdirs.sort()) {
101
- paths.push(...(await listJsonFiles(sub)));
105
+ paths.push(...(await listMetadataFiles(sub)));
102
106
  }
103
107
  return paths;
104
108
  }
109
+ function isMetadataFile(name) {
110
+ return name.endsWith(".json") || name.endsWith(".yaml") || name.endsWith(".yml");
111
+ }
105
112
  //# sourceMappingURL=memory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaobjectsdev/sdk",
3
- "version": "0.7.0-rc.1",
3
+ "version": "0.7.0-rc.3",
4
4
  "description": "Workspace helpers and agent-docs utilities for MetaObjects projects.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,7 +38,7 @@
38
38
  "access": "public"
39
39
  },
40
40
  "dependencies": {
41
- "@metaobjectsdev/metadata": "0.7.0-rc.1",
41
+ "@metaobjectsdev/metadata": "0.7.0-rc.3",
42
42
  "zod": "^3.23.0"
43
43
  },
44
44
  "devDependencies": {
@@ -104,6 +104,7 @@ export type ForgeAttr = (typeof FORGE_ATTRS)[number];
104
104
 
105
105
  import {
106
106
  type ChildRule,
107
+ type MetaDataTypeProvider,
107
108
  type TypeDefinition,
108
109
  TypeId,
109
110
  TypeRegistry,
@@ -138,30 +139,47 @@ function def(
138
139
  };
139
140
  }
140
141
 
142
+ /**
143
+ * The Meta Forge provider — registers Meta Forge's five descriptive top-level
144
+ * types (decision, principle, convention, glossary, failure) plus their
145
+ * subtypes. Composed AFTER `metaobjects-core-types` so the structural attr
146
+ * type is available for forge child rules.
147
+ *
148
+ * Use via `composeRegistry([...coreProviders, forgeTypesProvider])` or via
149
+ * `loadMemory()`'s default bundle (forge is included by default).
150
+ */
151
+ export const forgeTypesProvider: MetaDataTypeProvider = {
152
+ id: "metaobjects-forge",
153
+ dependencies: ["metaobjects-core-types"],
154
+ description: "Meta Forge descriptive top-level types (decision, principle, convention, glossary, failure).",
155
+ registerTypes(registry: TypeRegistry): void {
156
+ const forgeChildRules = [wildcardOf(TYPE_ATTR)];
157
+
158
+ for (const subType of FORGE_DECISION_SUBTYPES) {
159
+ registry.register(def(FORGE_TYPE_DECISION, subType, `Forge decision (${subType})`, forgeChildRules));
160
+ }
161
+ for (const subType of FORGE_PRINCIPLE_SUBTYPES) {
162
+ registry.register(def(FORGE_TYPE_PRINCIPLE, subType, `Forge principle (${subType})`, forgeChildRules));
163
+ }
164
+ for (const subType of FORGE_CONVENTION_SUBTYPES) {
165
+ registry.register(def(FORGE_TYPE_CONVENTION, subType, `Forge convention (${subType})`, forgeChildRules));
166
+ }
167
+ for (const subType of FORGE_GLOSSARY_SUBTYPES) {
168
+ registry.register(def(FORGE_TYPE_GLOSSARY, subType, `Forge glossary entry (${subType})`, forgeChildRules));
169
+ }
170
+ for (const subType of FORGE_FAILURE_SUBTYPES) {
171
+ registry.register(def(FORGE_TYPE_FAILURE, subType, `Forge failure record (${subType})`, forgeChildRules));
172
+ }
173
+ },
174
+ };
175
+
141
176
  /**
142
177
  * Register Meta Forge's five descriptive top-level types into the given
143
178
  * registry. Must be called AFTER `registerCoreTypes()`.
144
179
  *
145
- * Each type accepts `attr` children for expanded-form @forge* attributes.
146
- * Loader's default permissive mode tolerates these new types as children
147
- * of the metadata wrapper (unknowns are warned, not errored).
180
+ * Thin back-compat wrapper over `forgeTypesProvider.registerTypes`; prefer
181
+ * the provider directly for new code (composes correctly with other providers).
148
182
  */
149
183
  export function registerForgeTypes(registry: TypeRegistry): void {
150
- const forgeChildRules = [wildcardOf(TYPE_ATTR)];
151
-
152
- for (const subType of FORGE_DECISION_SUBTYPES) {
153
- registry.register(def(FORGE_TYPE_DECISION, subType, `Forge decision (${subType})`, forgeChildRules));
154
- }
155
- for (const subType of FORGE_PRINCIPLE_SUBTYPES) {
156
- registry.register(def(FORGE_TYPE_PRINCIPLE, subType, `Forge principle (${subType})`, forgeChildRules));
157
- }
158
- for (const subType of FORGE_CONVENTION_SUBTYPES) {
159
- registry.register(def(FORGE_TYPE_CONVENTION, subType, `Forge convention (${subType})`, forgeChildRules));
160
- }
161
- for (const subType of FORGE_GLOSSARY_SUBTYPES) {
162
- registry.register(def(FORGE_TYPE_GLOSSARY, subType, `Forge glossary entry (${subType})`, forgeChildRules));
163
- }
164
- for (const subType of FORGE_FAILURE_SUBTYPES) {
165
- registry.register(def(FORGE_TYPE_FAILURE, subType, `Forge failure record (${subType})`, forgeChildRules));
166
- }
184
+ forgeTypesProvider.registerTypes(registry);
167
185
  }
package/src/index.ts CHANGED
@@ -70,15 +70,22 @@ export {
70
70
  FORGE_ATTR_WHAT_WAS_TRIED,
71
71
  FORGE_ATTR_WHY_IT_FAILED,
72
72
  FORGE_ATTRS,
73
- // Registration helper
73
+ // Registration helper + provider
74
74
  registerForgeTypes,
75
+ forgeTypesProvider,
75
76
  } from "./forge-types.js";
76
77
  export type { ForgeType, ForgeAttr } from "./forge-types.js";
77
78
 
78
79
  // Memory loader — read metaobjects/ into a MetaData tree
79
80
  // (workspace-aware: walks extends: deps via pnpm-workspace.yaml or
80
81
  // package.json workspaces field if present)
81
- export { loadMemory, DEFAULT_METADATA_DIR, DEFAULT_METAOBJECTS_DIR } from "./memory.js";
82
+ export {
83
+ loadMemory,
84
+ defaultLoadMemoryProviders,
85
+ DEFAULT_METADATA_DIR,
86
+ DEFAULT_METAOBJECTS_DIR,
87
+ } from "./memory.js";
88
+ export type { LoadMemoryOptions } from "./memory.js";
82
89
 
83
90
  // Workspace discovery — finds peer metadata packages in a monorepo
84
91
  export { discoverWorkspace, resolveExtendsOrder, packageLabel } from "./workspace.js";
package/src/memory.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import { join } from "node:path";
2
2
  import { readdir, stat } from "node:fs/promises";
3
3
  import {
4
+ composeRegistry,
5
+ coreProviders,
4
6
  MetaDataLoader,
5
- TypeRegistry,
6
- registerCoreTypes,
7
+ type MetaDataTypeProvider,
7
8
  type MetaRoot,
8
9
  } from "@metaobjectsdev/metadata";
9
10
  import { FileSource } from "@metaobjectsdev/metadata/core";
10
- import { registerForgeTypes } from "./forge-types.js";
11
+ import { forgeTypesProvider } from "./forge-types.js";
11
12
  import { discoverWorkspace, resolveExtendsOrder } from "./workspace.js";
12
13
 
13
14
  /**
@@ -23,6 +24,36 @@ export const DEFAULT_METADATA_DIR = "metaobjects";
23
24
  */
24
25
  export const DEFAULT_METAOBJECTS_DIR = ".metaobjects";
25
26
 
27
+ /**
28
+ * Options for {@link loadMemory}. Consumers can supply additional
29
+ * {@link MetaDataTypeProvider}s to extend the metamodel with their own
30
+ * subtypes/attrs (e.g. a `template.toolcall` subtype).
31
+ */
32
+ export interface LoadMemoryOptions {
33
+ /**
34
+ * Consumer-supplied providers. Composed AFTER the default core providers
35
+ * (core-types + db + documentation + forge) unless `replaceDefaults: true`
36
+ * is set. Use this to register additional subtypes or extend existing
37
+ * ones without forking the loader.
38
+ */
39
+ providers?: readonly MetaDataTypeProvider[];
40
+ /**
41
+ * Skip the default core providers; supply your own full set. Advanced —
42
+ * use only when you need to compose a custom metamodel from scratch.
43
+ * Throws if `providers` is absent or empty.
44
+ */
45
+ replaceDefaults?: boolean;
46
+ }
47
+
48
+ /** Default provider bundle threaded by {@link loadMemory} when no options
49
+ * override is supplied. Exposed for tests/inspection; callers shouldn't need
50
+ * to spread this manually — `loadMemory(root, { providers: [mine] })`
51
+ * composes `[...defaultLoadMemoryProviders, mine]` automatically. */
52
+ export const defaultLoadMemoryProviders: readonly MetaDataTypeProvider[] = [
53
+ ...coreProviders,
54
+ forgeTypesProvider,
55
+ ];
56
+
26
57
  /**
27
58
  * Load all metadata files from `<repoRoot>/metaobjects/` into a single
28
59
  * MetaData. If `<repoRoot>/.meta/package.meta.json` declares `extends:` deps
@@ -31,18 +62,35 @@ export const DEFAULT_METAOBJECTS_DIR = ".metaobjects";
31
62
  *
32
63
  * Excludes `_pending/`. Registers metaobjects core types plus Meta Forge's
33
64
  * descriptive top-level types (decision, principle, etc.) so mixed content
34
- * parses without warnings.
65
+ * parses without warnings. Consumer-supplied providers (via
66
+ * {@link LoadMemoryOptions.providers}) are composed AFTER the defaults so
67
+ * they may depend on core/forge ids.
35
68
  *
36
69
  * Throws if `metaobjects/` doesn't exist (callers should run `meta init`).
37
70
  *
38
71
  * @param repoRoot The project's working-directory root (e.g. process.cwd()).
39
72
  * `loadMemory` resolves `metaobjects/` and (if workspace-aware) the
40
73
  * transitive `extends:` graph automatically.
74
+ * @param options Optional {@link LoadMemoryOptions} — supply additional
75
+ * providers or replace the default bundle entirely.
41
76
  */
42
- export async function loadMemory(repoRoot: string): Promise<MetaRoot> {
43
- const registry = new TypeRegistry();
44
- registerCoreTypes(registry);
45
- registerForgeTypes(registry);
77
+ export async function loadMemory(
78
+ repoRoot: string,
79
+ options?: LoadMemoryOptions,
80
+ ): Promise<MetaRoot> {
81
+ const extra = options?.providers ?? [];
82
+ let providers: readonly MetaDataTypeProvider[];
83
+ if (options?.replaceDefaults === true) {
84
+ if (extra.length === 0) {
85
+ throw new Error(
86
+ "loadMemory: `replaceDefaults: true` requires at least one provider in `providers`.",
87
+ );
88
+ }
89
+ providers = extra;
90
+ } else {
91
+ providers = [...defaultLoadMemoryProviders, ...extra];
92
+ }
93
+ const registry = composeRegistry(providers);
46
94
 
47
95
  // Collect all metadata file paths to load. Order matters for the parser's
48
96
  // deferred-resolution pass (it parses in array order, then resolves supers
@@ -74,23 +122,27 @@ async function collectMetadataPaths(repoRoot: string): Promise<string[]> {
74
122
  for (const pkg of ordered) {
75
123
  // Each workspace package's metadata lives alongside its .meta/ dir
76
124
  const pkgRoot = join(pkg.metaDir, "..");
77
- paths.push(...(await listJsonFiles(join(pkgRoot, DEFAULT_METADATA_DIR))));
125
+ paths.push(...(await listMetadataFiles(join(pkgRoot, DEFAULT_METADATA_DIR))));
78
126
  }
79
127
  return paths;
80
128
  }
81
129
  }
82
130
 
83
131
  // Single-package path: scan metaobjects/ at the project root
84
- return listJsonFiles(join(repoRoot, DEFAULT_METADATA_DIR));
132
+ return listMetadataFiles(join(repoRoot, DEFAULT_METADATA_DIR));
85
133
  }
86
134
 
87
135
  /**
88
- * Recursively list *.json files under a directory, excluding _pending/ at
89
- * any level. Subdirectories (e.g. projections/) are walked depth-first.
90
- * Files within a directory are sorted alphabetically for deterministic load
91
- * order; subdirectories are visited after files at the same level.
136
+ * Recursively list metadata files (*.json, *.yaml, *.yml) under a directory,
137
+ * excluding _pending/ at any level. Subdirectories (e.g. projections/) are
138
+ * walked depth-first. Files within a directory are sorted alphabetically for
139
+ * deterministic load order; subdirectories are visited after files at the
140
+ * same level.
141
+ *
142
+ * Format selection (parsing) happens downstream in `FileSource` from
143
+ * `@metaobjectsdev/metadata`, which infers the parser from file extension.
92
144
  */
93
- async function listJsonFiles(dir: string): Promise<string[]> {
145
+ async function listMetadataFiles(dir: string): Promise<string[]> {
94
146
  let entries: string[];
95
147
  try {
96
148
  entries = await readdir(dir);
@@ -105,13 +157,17 @@ async function listJsonFiles(dir: string): Promise<string[]> {
105
157
  const s = await stat(full);
106
158
  if (s.isDirectory()) {
107
159
  subdirs.push(full);
108
- } else if (s.isFile() && entry.endsWith(".json")) {
160
+ } else if (s.isFile() && isMetadataFile(entry)) {
109
161
  paths.push(full);
110
162
  }
111
163
  }
112
164
  // Recurse into subdirectories after collecting files at this level
113
165
  for (const sub of subdirs.sort()) {
114
- paths.push(...(await listJsonFiles(sub)));
166
+ paths.push(...(await listMetadataFiles(sub)));
115
167
  }
116
168
  return paths;
117
169
  }
170
+
171
+ function isMetadataFile(name: string): boolean {
172
+ return name.endsWith(".json") || name.endsWith(".yaml") || name.endsWith(".yml");
173
+ }