@zeyos/cli 0.3.0 → 0.4.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/bin/zeyos.mjs CHANGED
@@ -51,6 +51,7 @@ ${_c.bold('Commands:')}
51
51
  ${_c.cyan('describe')} <resource> Show a resource's fields, types and enums
52
52
  ${_c.cyan('doctor')} agent Check local CLI readiness for coding agents
53
53
  ${_c.cyan('skills')} <command> List / show / install ZeyOS agent skills
54
+ ${_c.cyan('okf')} <command> List / show / check / export the OKF knowledge bundle
54
55
  ${_c.cyan('profile')} <command> Manage credential profiles / switch instances
55
56
 
56
57
  ${_c.bold('Global options:')}
@@ -120,6 +121,8 @@ const OPTIONS = {
120
121
  'target': { type: 'string' },
121
122
  'dir': { type: 'string' },
122
123
  'no-logo': { type: 'boolean' },
124
+ // okf
125
+ 'out': { type: 'string' },
123
126
  // profile
124
127
  'from-current': { type: 'boolean' },
125
128
  };
@@ -147,6 +150,7 @@ const COMMANDS = {
147
150
  doctor: '../commands/doctor.mjs',
148
151
  skills: '../commands/skills.mjs',
149
152
  skill: '../commands/skills.mjs',
153
+ okf: '../commands/okf.mjs',
150
154
  profile: '../commands/profile.mjs',
151
155
  profiles: '../commands/profile.mjs',
152
156
  };
@@ -158,6 +162,7 @@ const COMMANDS = {
158
162
 
159
163
  const ALWAYS_FLAGS = ['help', 'json', 'yaml', 'no-color', 'profile'];
160
164
  const SKILLS_FLAGS = ['target', 'dir', 'global', 'local', 'force', 'yes', 'no-logo'];
165
+ const OKF_FLAGS = ['dir', 'out', 'force', 'no-logo'];
161
166
  const PROFILE_FLAGS = ['base-url', 'client-id', 'secret', 'local', 'from-current'];
162
167
  const DELETE_FLAGS = ['force', 'query'];
163
168
  const GET_FLAGS = ['fields', 'extdata', 'tags', 'expand', 'all', 'query'];
@@ -182,6 +187,7 @@ const COMMAND_FLAGS = {
182
187
  doctor: [],
183
188
  skills: SKILLS_FLAGS,
184
189
  skill: SKILLS_FLAGS,
190
+ okf: OKF_FLAGS,
185
191
  profile: PROFILE_FLAGS,
186
192
  profiles: PROFILE_FLAGS,
187
193
  };
@@ -0,0 +1,192 @@
1
+ /**
2
+ * zeyos okf <list|show|check|build|export>
3
+ *
4
+ * Work with the Open Knowledge Format (OKF v0.1) bundle that ships with
5
+ * @zeyos/client (under okf/): a directory of Markdown concept docs describing the
6
+ * ZeyOS data model (entities, schema, foreign keys, enums, indexes, operations)
7
+ * plus curated metrics, playbooks, and query concepts. Consumers — coding agents,
8
+ * viewers, search — read it; this command lists/shows/validates the shipped bundle
9
+ * and can synthesize or export one.
10
+ */
11
+
12
+ import { readFileSync, existsSync, cpSync, mkdirSync, writeFileSync } from 'node:fs';
13
+ import { homedir } from 'node:os';
14
+ import path from 'node:path';
15
+ import { createRequire } from 'node:module';
16
+
17
+ import { loadOkfBundle, validateOkfFiles, buildOkf, OKF_VERSION } from '@zeyos/client';
18
+ import { outputMode, printJson, printYaml, printTable, colors, success, error, info, warn } from '../lib/output.mjs';
19
+
20
+ const require = createRequire(import.meta.url);
21
+
22
+ export const USAGE = `\
23
+ Usage: zeyos okf <command> [options]
24
+
25
+ Commands:
26
+ list List concepts in the OKF bundle (type, id, title)
27
+ show <concept> Print a concept doc (e.g. "tickets" or "entities/tickets")
28
+ check Validate the bundle for OKF v0.1 conformance
29
+ build [--out <dir>] Synthesize an OKF bundle from the client's schema
30
+ export [--out <dir>] Copy the shipped okf/ bundle into a directory
31
+
32
+ Options:
33
+ --dir <path> Read from an explicit bundle directory (list/show/check)
34
+ --out <path> Write to this directory (build/export; default ./okf)
35
+ --force Overwrite an existing target (export)
36
+ --json Output as JSON
37
+ --yaml Output as YAML
38
+ -h, --help Show this help
39
+
40
+ Examples:
41
+ zeyos okf list
42
+ zeyos okf show tickets
43
+ zeyos okf check
44
+ zeyos okf export --out ./vendor/okf
45
+ zeyos okf build --out ./okf-live`;
46
+
47
+ // Locate the okf/ bundle shipped inside the @zeyos/client package (mirrors the
48
+ // skills command's findAgentsDir).
49
+ function findOkfDir() {
50
+ let entry;
51
+ try {
52
+ entry = require.resolve('@zeyos/client');
53
+ } catch {
54
+ return null;
55
+ }
56
+ let dir = path.dirname(entry);
57
+ for (let i = 0; i < 6; i++) {
58
+ const candidate = path.join(dir, 'okf');
59
+ if (existsSync(path.join(candidate, 'index.md'))) return candidate;
60
+ const parent = path.dirname(dir);
61
+ if (parent === dir) break;
62
+ dir = parent;
63
+ }
64
+ return null;
65
+ }
66
+
67
+ function expandHome(p) {
68
+ if (p === '~') return homedir();
69
+ if (p.startsWith('~/') || p.startsWith('~\\')) return path.join(homedir(), p.slice(2));
70
+ return p;
71
+ }
72
+
73
+ function displayPath(abs) {
74
+ const rel = path.relative(process.cwd(), abs);
75
+ if (rel && !rel.startsWith('..') && !path.isAbsolute(rel)) return rel;
76
+ const home = homedir();
77
+ if (abs === home || abs.startsWith(home + path.sep)) return '~' + abs.slice(home.length);
78
+ return abs;
79
+ }
80
+
81
+ function resolveInputDir(values) {
82
+ if (values.dir) return path.resolve(expandHome(values.dir));
83
+ const found = findOkfDir();
84
+ if (!found) {
85
+ error('Could not locate the bundled OKF bundle (the @zeyos/client okf/ directory). Pass --dir <path>.');
86
+ process.exit(1);
87
+ }
88
+ return found;
89
+ }
90
+
91
+ function conceptsToRows(concepts) {
92
+ return Object.entries(concepts)
93
+ .map(([id, { frontmatter }]) => ({ type: frontmatter.type || '(none)', concept: id, title: frontmatter.title || '' }))
94
+ .sort((a, b) => a.concept.localeCompare(b.concept));
95
+ }
96
+
97
+ async function runList(values) {
98
+ const dir = resolveInputDir(values);
99
+ const { version, concepts } = await loadOkfBundle(dir);
100
+ const rows = conceptsToRows(concepts);
101
+ const mode = outputMode(values);
102
+ if (mode === 'json') return printJson({ version, concepts: rows });
103
+ if (mode === 'yaml') return printYaml({ version, concepts: rows });
104
+ printTable(rows, ['type', 'concept', 'title']);
105
+ info(`OKF v${version || OKF_VERSION} — ${rows.length} concepts in ${displayPath(dir)}. Show one with: zeyos okf show <concept>`);
106
+ }
107
+
108
+ function runShow(values, name) {
109
+ const dir = resolveInputDir(values);
110
+ const candidates = [name, `${name}.md`, `entities/${name}.md`, path.join(dir, name), path.join(dir, `${name}.md`), path.join(dir, 'entities', `${name}.md`)];
111
+ for (const candidate of candidates) {
112
+ const abs = path.isAbsolute(candidate) ? candidate : path.join(dir, candidate);
113
+ if (existsSync(abs)) {
114
+ process.stdout.write(readFileSync(abs, 'utf8'));
115
+ return;
116
+ }
117
+ }
118
+ error(`Unknown concept "${name}". Run "zeyos okf list".`);
119
+ process.exit(1);
120
+ }
121
+
122
+ async function runCheck(values) {
123
+ const dir = resolveInputDir(values);
124
+ const { files } = await loadOkfBundle(dir);
125
+ const result = validateOkfFiles(files);
126
+ const mode = outputMode(values);
127
+ if (mode === 'json') { printJson(result); process.exit(result.valid ? 0 : 1); }
128
+ if (mode === 'yaml') { printYaml(result); process.exit(result.valid ? 0 : 1); }
129
+ if (result.valid) {
130
+ success(`OKF bundle is conformant: ${result.conceptCount} concepts, 0 errors (${displayPath(dir)}).`);
131
+ return;
132
+ }
133
+ for (const err of result.errors) error(`${err.path}: ${err.message}`);
134
+ error(`OKF bundle is NOT conformant: ${result.errors.length} error(s).`);
135
+ process.exit(1);
136
+ }
137
+
138
+ function writeBundle(outDir, files) {
139
+ for (const [rel, content] of Object.entries(files)) {
140
+ const abs = path.join(outDir, rel);
141
+ mkdirSync(path.dirname(abs), { recursive: true });
142
+ writeFileSync(abs, content, 'utf8');
143
+ }
144
+ }
145
+
146
+ function runBuild(values) {
147
+ const outDir = path.resolve(expandHome(values.out || 'okf'));
148
+ const files = buildOkf();
149
+ writeBundle(outDir, files);
150
+ const mode = outputMode(values);
151
+ const summary = { out: outDir, files: Object.keys(files).length };
152
+ if (mode === 'json') return printJson(summary);
153
+ if (mode === 'yaml') return printYaml(summary);
154
+ success(`Synthesized ${summary.files} OKF files → ${displayPath(outDir)}`);
155
+ info('This is the runtime projection from the client schema (structural only). The shipped okf/ bundle adds curated metrics, playbooks, and notes.');
156
+ }
157
+
158
+ function runExport(values) {
159
+ const dir = resolveInputDir(values);
160
+ const outDir = path.resolve(expandHome(values.out || 'okf'));
161
+ if (existsSync(outDir) && !values.force) {
162
+ if (path.resolve(dir) === outDir) {
163
+ warn(`Source and target are the same (${displayPath(outDir)}); nothing to do.`);
164
+ return;
165
+ }
166
+ error(`Target ${displayPath(outDir)} already exists. Use --force to overwrite.`);
167
+ process.exit(1);
168
+ }
169
+ cpSync(dir, outDir, { recursive: true });
170
+ const mode = outputMode(values);
171
+ const summary = { from: dir, out: outDir };
172
+ if (mode === 'json') return printJson(summary);
173
+ if (mode === 'yaml') return printYaml(summary);
174
+ success(`Exported OKF bundle → ${displayPath(outDir)}`);
175
+ }
176
+
177
+ export async function run(values, positional = []) {
178
+ const sub = positional[0] || 'list';
179
+ const rest = positional.slice(1);
180
+ switch (sub) {
181
+ case 'list': return runList(values);
182
+ case 'show':
183
+ if (!rest[0]) { error('Usage: zeyos okf show <concept>'); process.exit(1); }
184
+ return runShow(values, rest[0]);
185
+ case 'check': return runCheck(values);
186
+ case 'build': return runBuild(values);
187
+ case 'export': return runExport(values);
188
+ default:
189
+ error(`Unknown okf command "${sub}".\n\n${USAGE}`);
190
+ process.exit(1);
191
+ }
192
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeyos/cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Command-line interface for the ZeyOS API",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -39,7 +39,7 @@
39
39
  "node": ">=18.3"
40
40
  },
41
41
  "dependencies": {
42
- "@zeyos/client": "^0.3.0"
42
+ "@zeyos/client": "^0.4.0"
43
43
  },
44
44
  "scripts": {
45
45
  "test": "node --test test/offline.mjs"