@eventmodelers/cli 0.0.27 → 0.0.28
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/README.md +4 -4
- package/cli.js +2 -1
- package/lib/fetch.js +25 -51
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -225,9 +225,9 @@ npx @eventmodelers/cli run --ollama # same, via local Ollama (ra
|
|
|
225
225
|
npx @eventmodelers/cli run --bash # bash-only loop, no realtime (ralph.sh)
|
|
226
226
|
npx @eventmodelers/cli listen # start the code-export listener (code-export.mjs) from the installed kit dir
|
|
227
227
|
npx @eventmodelers/cli listen --port 4000 # same, on a different port
|
|
228
|
-
npx @eventmodelers/cli fetch
|
|
229
|
-
npx @eventmodelers/cli fetch --slice-id <id>
|
|
230
|
-
npx @eventmodelers/cli fetch --slice-title <title>
|
|
228
|
+
npx @eventmodelers/cli fetch --context <name> # pull full slice detail for one context on the board into <kit-dir>/.slices/ (project root if no kit, or a modeling-kit, is installed)
|
|
229
|
+
npx @eventmodelers/cli fetch --context <name> --slice-id <id> # same, then print just that slice
|
|
230
|
+
npx @eventmodelers/cli fetch --context <name> --slice-title <title> # same, then print just the slice matching this title
|
|
231
231
|
npx @eventmodelers/cli stacks # list available stacks
|
|
232
232
|
npx @eventmodelers/cli status # check what's installed
|
|
233
233
|
npx @eventmodelers/cli config # print the fully resolved config (file + env), token masked
|
|
@@ -238,7 +238,7 @@ npx @eventmodelers/cli uninstall # remove everything init/ini
|
|
|
238
238
|
|
|
239
239
|
`listen` is the same kind of dispatcher, but for `<kit-dir>/code-export.mjs` — a local HTTP server (port 3001 by default) that the eventmodelers board UI posts slice/screen data to, which then gets written under `<kit-dir>/.slices/`.
|
|
240
240
|
|
|
241
|
-
`fetch` is the pull-based counterpart to `listen`: instead of waiting for the board UI to push data to a running listener, it
|
|
241
|
+
`fetch` is the pull-based counterpart to `listen`: instead of waiting for the board UI to push data to a running listener, it calls `slicedata?contextName=<name>` for the required `--context` (full slice detail — commands/events/readmodels/screens/processors/specifications/comments), and writes the same `.slices/<context>/<slice>/slice.json`, `index.json`, and `context.json` layout — useful in CI or any context where nothing is listening on a port. It does not fetch screen images (those only arrive via `listen`'s push). Unlike every other command, `fetch` also works with no kit installed at all — it only needs credentials, not kit-specific files — and, unique to modeling-kit, writes `.slices/` to the project root instead of nesting it under `.agent-modeling-kit/`, since nothing reads it from there (modeling-kit has no `code-export.mjs`/`listen`). If credentials are missing, it prompts the same way `init-config` does. `--slice-id`/`--slice-title` still fetch and persist the whole context, then just print the one slice you asked about.
|
|
242
242
|
|
|
243
243
|
### Uninstall
|
|
244
244
|
|
package/cli.js
CHANGED
|
@@ -1463,7 +1463,8 @@ program
|
|
|
1463
1463
|
|
|
1464
1464
|
program
|
|
1465
1465
|
.command('fetch')
|
|
1466
|
-
.description('Pull full slice detail
|
|
1466
|
+
.description('Pull full slice detail for one context on the board via the slicedata API and write it into .slices/ — the pull-based counterpart to `listen`, without screen images')
|
|
1467
|
+
.requiredOption('--context <name>', 'Name of the MODEL_CONTEXT to fetch')
|
|
1467
1468
|
.option('--slice-id <id>', 'After fetching, print just the slice with this id')
|
|
1468
1469
|
.option('--slice-title <title>', 'After fetching, print just the slice with this title (case-insensitive)')
|
|
1469
1470
|
.action(async (opts, command) => {
|
package/lib/fetch.js
CHANGED
|
@@ -45,13 +45,13 @@ function sliceFolderName(title) {
|
|
|
45
45
|
return (title ?? '').replaceAll(' ', '').replaceAll('slice:', '').toLowerCase();
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
// Pulls full slice detail from
|
|
48
|
+
// Pulls full slice detail from a single context on a board and writes it into
|
|
49
49
|
// .slices/, mirroring the layout code-export.mjs's /api/generate handler produces
|
|
50
50
|
// (minus screen images, which only ever arrive via that push-based listener).
|
|
51
51
|
//
|
|
52
52
|
// kitDir here is null for modeling-kit (see cli.js's fetch action) — nothing
|
|
53
53
|
// nests .slices/ under .agent-modeling-kit/, so it lands at cwd instead.
|
|
54
|
-
// { cwd, kitDir, cfg: { token, organizationId, boardId, baseUrl }, opts: { sliceId?, sliceTitle? } }
|
|
54
|
+
// { cwd, kitDir, cfg: { token, organizationId, boardId, baseUrl }, opts: { context, sliceId?, sliceTitle? } }
|
|
55
55
|
export async function runFetch({ cwd, kitDir, cfg, opts = {} }) {
|
|
56
56
|
const baseUrl = cfg.baseUrl || DEFAULT_BASE_URL;
|
|
57
57
|
const headers = { 'x-token': cfg.token, 'x-board-id': cfg.boardId, 'x-user-id': 'cli-fetch' };
|
|
@@ -74,63 +74,42 @@ export async function runFetch({ cwd, kitDir, cfg, opts = {} }) {
|
|
|
74
74
|
return res.json();
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
console.log(`▶ Fetching
|
|
78
|
-
|
|
79
|
-
// No dedicated "list contexts" endpoint — MODEL_CONTEXT nodes are the contexts,
|
|
80
|
-
// same as how the connect skill lists CHAPTER nodes for its health check.
|
|
81
|
-
const contextNodes = await fetchJson(
|
|
82
|
-
`${baseUrl}/api/org/${cfg.organizationId}/boards/${cfg.boardId}/nodes?type=MODEL_CONTEXT`,
|
|
83
|
-
'nodes?type=MODEL_CONTEXT',
|
|
84
|
-
);
|
|
85
|
-
if (!contextNodes?.length) {
|
|
86
|
-
console.log('ℹ️ No contexts found on this board.');
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
77
|
+
console.log(`▶ Fetching context "${opts.context}" from ${baseUrl} (board ${cfg.boardId})...`);
|
|
89
78
|
|
|
90
79
|
// Falls back to cwd when no kit is installed — fetch doesn't need kit-specific
|
|
91
80
|
// files, just somewhere to write .slices/.
|
|
92
81
|
const SLICES_DIR = join(kitDir || cwd, '.slices');
|
|
93
82
|
|
|
94
83
|
// /slicedata (buildSliceData) is per-context and returns full slice detail —
|
|
95
|
-
// commands/events/readmodels/screens/processors/specifications/comments
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
allSlices.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
// .slices/<context>/config.json, alongside the per-slice output below — kept
|
|
114
|
-
// for parity with `listen` even though nothing in this repo reads it back.
|
|
115
|
-
const contextSlug = slugify(slices[0]?.context || contextName || 'default') || 'default';
|
|
116
|
-
const baseFolder = join(SLICES_DIR, contextSlug);
|
|
117
|
-
mkdirSync(baseFolder, { recursive: true });
|
|
118
|
-
writeFileSync(join(baseFolder, 'config.json'), JSON.stringify(payload, null, 2));
|
|
119
|
-
}
|
|
84
|
+
// commands/events/readmodels/screens/processors/specifications/comments. It
|
|
85
|
+
// resolves contextName by exact match, so no separate "list contexts" lookup
|
|
86
|
+
// is needed first.
|
|
87
|
+
const contextQuery = `contextName=${encodeURIComponent(opts.context)}`;
|
|
88
|
+
const payload = await fetchJson(
|
|
89
|
+
`${baseUrl}/api/org/${cfg.organizationId}/boards/${cfg.boardId}/slicedata?${contextQuery}`,
|
|
90
|
+
`slicedata?${contextQuery}`,
|
|
91
|
+
);
|
|
92
|
+
const { slices: allSlices } = payload;
|
|
93
|
+
|
|
94
|
+
if (allSlices.length) {
|
|
95
|
+
// Mirrors code-export.mjs's /api/generate: a raw per-context payload dump at
|
|
96
|
+
// .slices/<context>/config.json, alongside the per-slice output below — kept
|
|
97
|
+
// for parity with `listen` even though nothing in this repo reads it back.
|
|
98
|
+
const contextSlug = slugify(allSlices[0]?.context || opts.context || 'default') || 'default';
|
|
99
|
+
const baseFolder = join(SLICES_DIR, contextSlug);
|
|
100
|
+
mkdirSync(baseFolder, { recursive: true });
|
|
101
|
+
writeFileSync(join(baseFolder, 'config.json'), JSON.stringify(payload, null, 2));
|
|
120
102
|
}
|
|
121
103
|
|
|
122
104
|
if (!allSlices.length) {
|
|
123
|
-
console.log(
|
|
105
|
+
console.log(`ℹ️ No slices found in context "${opts.context}".`);
|
|
124
106
|
return;
|
|
125
107
|
}
|
|
126
108
|
|
|
127
|
-
const contextNames = new Set();
|
|
128
|
-
|
|
129
109
|
for (const slice of allSlices) {
|
|
130
110
|
// buildSliceData names this field `context`, not `contextName` (that's the
|
|
131
111
|
// /slicedata/slices summary endpoint's field) — read the one this endpoint sends.
|
|
132
|
-
const contextName = slice.context || 'default';
|
|
133
|
-
contextNames.add(contextName);
|
|
112
|
+
const contextName = slice.context || opts.context || 'default';
|
|
134
113
|
const contextSlug = slugify(contextName) || 'default';
|
|
135
114
|
const baseFolder = join(SLICES_DIR, contextSlug);
|
|
136
115
|
const sliceFolder = sliceFolderName(slice.title);
|
|
@@ -165,14 +144,9 @@ export async function runFetch({ cwd, kitDir, cfg, opts = {} }) {
|
|
|
165
144
|
writeFileSync(indexFile, JSON.stringify(sliceIndices, null, 2));
|
|
166
145
|
}
|
|
167
146
|
|
|
168
|
-
|
|
169
|
-
// belongs to one context — with several, any one choice would be arbitrary, so
|
|
170
|
-
// leave whatever `listen`/a prior fetch already wrote there untouched.
|
|
171
|
-
if (contextNames.size === 1) {
|
|
172
|
-
writeFileSync(join(SLICES_DIR, 'current_context.json'), JSON.stringify({ name: [...contextNames][0] }, null, 2));
|
|
173
|
-
}
|
|
147
|
+
writeFileSync(join(SLICES_DIR, 'current_context.json'), JSON.stringify({ name: opts.context }, null, 2));
|
|
174
148
|
|
|
175
|
-
console.log(`✅ Fetched ${allSlices.length} slice${allSlices.length === 1 ? '' : 's'}
|
|
149
|
+
console.log(`✅ Fetched ${allSlices.length} slice${allSlices.length === 1 ? '' : 's'} from context "${opts.context}" → ${relative(cwd, SLICES_DIR)}/`);
|
|
176
150
|
|
|
177
151
|
// --slice-id/--slice-title mirror load-slice's Step 4/5 — fetch+persist everything
|
|
178
152
|
// regardless, then just report the one the caller asked about.
|
package/package.json
CHANGED