@oml/cli 0.13.0 → 0.14.1

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 (77) hide show
  1. package/README.md +28 -21
  2. package/out/{auth.d.ts → auth/auth.d.ts} +7 -0
  3. package/out/{auth.js → auth/auth.js} +42 -3
  4. package/out/auth/auth.js.map +1 -0
  5. package/out/{platform-constants.js → auth/constants.js} +1 -1
  6. package/out/auth/constants.js.map +1 -0
  7. package/out/{platform.d.ts → auth/platform.d.ts} +5 -7
  8. package/out/{platform.js → auth/platform.js} +13 -19
  9. package/out/auth/platform.js.map +1 -0
  10. package/out/cli.d.ts +6 -0
  11. package/out/cli.js +175 -62
  12. package/out/cli.js.map +1 -1
  13. package/out/commands/export.d.ts +8 -0
  14. package/out/commands/export.js +27 -0
  15. package/out/commands/export.js.map +1 -0
  16. package/out/commands/lint.d.ts +22 -2
  17. package/out/commands/lint.js +64 -18
  18. package/out/commands/lint.js.map +1 -1
  19. package/out/commands/reason.d.ts +2 -9
  20. package/out/commands/reason.js +52 -48
  21. package/out/commands/reason.js.map +1 -1
  22. package/out/commands/render.d.ts +1 -9
  23. package/out/commands/render.js +15 -726
  24. package/out/commands/render.js.map +1 -1
  25. package/out/commands/server/actions.d.ts +22 -0
  26. package/out/commands/server/actions.js +394 -0
  27. package/out/commands/server/actions.js.map +1 -0
  28. package/out/commands/server/require.d.ts +1 -0
  29. package/out/commands/server/require.js +89 -0
  30. package/out/commands/server/require.js.map +1 -0
  31. package/out/commands/server/rest.d.ts +2 -0
  32. package/out/commands/server/rest.js +117 -0
  33. package/out/commands/server/rest.js.map +1 -0
  34. package/out/commands/validate.d.ts +3 -3
  35. package/out/commands/validate.js +35 -171
  36. package/out/commands/validate.js.map +1 -1
  37. package/package.json +5 -7
  38. package/src/{auth.ts → auth/auth.ts} +54 -3
  39. package/src/{platform.ts → auth/platform.ts} +13 -19
  40. package/src/cli.ts +207 -63
  41. package/src/commands/export.ts +54 -0
  42. package/src/commands/lint.ts +88 -18
  43. package/src/commands/reason.ts +69 -56
  44. package/src/commands/render.ts +23 -995
  45. package/src/commands/server/actions.ts +480 -0
  46. package/src/commands/server/require.ts +99 -0
  47. package/src/commands/server/rest.ts +135 -0
  48. package/src/commands/validate.ts +46 -207
  49. package/out/auth.js.map +0 -1
  50. package/out/backend/backend-types.d.ts +0 -21
  51. package/out/backend/backend-types.js +0 -3
  52. package/out/backend/backend-types.js.map +0 -1
  53. package/out/backend/create-backend.d.ts +0 -2
  54. package/out/backend/create-backend.js +0 -6
  55. package/out/backend/create-backend.js.map +0 -1
  56. package/out/backend/direct-backend.d.ts +0 -20
  57. package/out/backend/direct-backend.js +0 -150
  58. package/out/backend/direct-backend.js.map +0 -1
  59. package/out/backend/reasoned-output.d.ts +0 -38
  60. package/out/backend/reasoned-output.js +0 -568
  61. package/out/backend/reasoned-output.js.map +0 -1
  62. package/out/commands/closure.d.ts +0 -33
  63. package/out/commands/closure.js +0 -537
  64. package/out/commands/closure.js.map +0 -1
  65. package/out/commands/compile.d.ts +0 -11
  66. package/out/commands/compile.js +0 -63
  67. package/out/commands/compile.js.map +0 -1
  68. package/out/platform-constants.js.map +0 -1
  69. package/out/platform.js.map +0 -1
  70. package/src/backend/backend-types.ts +0 -27
  71. package/src/backend/create-backend.ts +0 -8
  72. package/src/backend/direct-backend.ts +0 -169
  73. package/src/backend/reasoned-output.ts +0 -697
  74. package/src/commands/closure.ts +0 -624
  75. package/src/commands/compile.ts +0 -88
  76. /package/out/{platform-constants.d.ts → auth/constants.d.ts} +0 -0
  77. /package/src/{platform-constants.ts → auth/constants.ts} +0 -0
@@ -0,0 +1,117 @@
1
+ // Copyright (c) 2026 Modelware. All rights reserved.
2
+ import * as fs from 'node:fs/promises';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import { createHash } from 'node:crypto';
6
+ const DEFAULT_HOST = '127.0.0.1';
7
+ function workspaceHash(workspaceRoot) {
8
+ return createHash('sha256').update(path.resolve(workspaceRoot)).digest('hex');
9
+ }
10
+ function serverLockFileForWorkspace(workspaceRoot) {
11
+ return path.join(os.homedir(), '.oml', 'workspaces', workspaceHash(workspaceRoot), 'server.lock');
12
+ }
13
+ function isProcessAlive(pid) {
14
+ try {
15
+ process.kill(pid, 0);
16
+ return true;
17
+ }
18
+ catch {
19
+ return false;
20
+ }
21
+ }
22
+ function parseServerState(raw) {
23
+ try {
24
+ const parsed = JSON.parse(raw);
25
+ const pid = Number(parsed.pid);
26
+ const port = Number(parsed.port);
27
+ if (!Number.isFinite(pid) || !Number.isFinite(port)) {
28
+ return undefined;
29
+ }
30
+ const pidInt = Math.trunc(pid);
31
+ const portInt = Math.trunc(port);
32
+ if (pidInt <= 0 || portInt <= 0 || portInt > 65535) {
33
+ return undefined;
34
+ }
35
+ return { pid: pidInt, port: portInt };
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ }
41
+ async function readRunningState(workspaceRoot = process.cwd()) {
42
+ const lockFile = serverLockFileForWorkspace(path.resolve(workspaceRoot));
43
+ try {
44
+ const raw = (await fs.readFile(lockFile, 'utf-8')).trim();
45
+ if (!raw) {
46
+ return undefined;
47
+ }
48
+ const state = parseServerState(raw);
49
+ if (!state || !isProcessAlive(state.pid)) {
50
+ return undefined;
51
+ }
52
+ return state;
53
+ }
54
+ catch {
55
+ return undefined;
56
+ }
57
+ }
58
+ function createHeaders(token) {
59
+ const headers = new Headers();
60
+ headers.set('content-type', 'application/json');
61
+ if (token && token.trim().length > 0) {
62
+ headers.set('authorization', `Bearer ${token.trim()}`);
63
+ }
64
+ return headers;
65
+ }
66
+ function ensureServerBaseUrl(state) {
67
+ if (!state) {
68
+ throw new Error('start server first');
69
+ }
70
+ return `http://${DEFAULT_HOST}:${state.port}`;
71
+ }
72
+ async function parseJsonResponse(response) {
73
+ const text = await response.text();
74
+ if (!text.trim()) {
75
+ throw new Error(`Server returned HTTP ${response.status} ${response.statusText} with empty response body.`);
76
+ }
77
+ try {
78
+ return JSON.parse(text);
79
+ }
80
+ catch {
81
+ throw new Error(`Server returned HTTP ${response.status} ${response.statusText} with invalid JSON response.`);
82
+ }
83
+ }
84
+ export async function restGet(route, authToken) {
85
+ const baseUrl = ensureServerBaseUrl(await readRunningState());
86
+ const response = await fetch(`${baseUrl}${route}`, {
87
+ method: 'GET',
88
+ headers: createHeaders(authToken),
89
+ });
90
+ const payload = await parseJsonResponse(response);
91
+ if (!response.ok) {
92
+ const message = payload.error;
93
+ throw new Error(message && message.trim().length > 0 ? message : `Server request failed: GET ${route} (${response.status}).`);
94
+ }
95
+ return payload;
96
+ }
97
+ export async function restPost(route, body, authToken) {
98
+ const baseUrl = ensureServerBaseUrl(await readRunningState());
99
+ const response = await fetch(`${baseUrl}${route}`, {
100
+ method: 'POST',
101
+ headers: createHeaders(authToken),
102
+ body: JSON.stringify(body),
103
+ });
104
+ const payload = await parseJsonResponse(response);
105
+ if (!response.ok) {
106
+ const message = payload.error;
107
+ throw new Error(message && message.trim().length > 0 ? message : `Server request failed: POST ${route} (${response.status}).`);
108
+ }
109
+ if (payload.ok === false) {
110
+ throw new Error(payload.error?.trim() || `Server request failed: POST ${route}.`);
111
+ }
112
+ if (payload.result === undefined) {
113
+ throw new Error(`Server request failed: POST ${route} did not return a result.`);
114
+ }
115
+ return payload.result;
116
+ }
117
+ //# sourceMappingURL=rest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest.js","sourceRoot":"","sources":["../../../src/commands/server/rest.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import type { ReasonOptions } from './reason.js';
2
- export type ValidateOptions = ReasonOptions & {
3
- md: string;
1
+ export type ValidateOptions = {
2
+ only?: boolean;
3
+ authToken?: string;
4
4
  };
5
5
  export declare const validateAction: (opts: ValidateOptions) => Promise<void>;
@@ -1,186 +1,50 @@
1
1
  // Copyright (c) 2026 Modelware. All rights reserved.
2
- import { normalizeNamespace } from '@oml/language';
3
- import { createDefaultShaclService, createOwlServices } from '@oml/owl';
4
- import { MarkdownPreviewRuntime, MarkdownHandlerRegistry } from '@oml/markdown';
5
2
  import chalk from 'chalk';
6
- import { URI } from 'langium';
7
- import { NodeFileSystem } from 'langium/node';
8
- import * as fs from 'node:fs/promises';
9
- import * as path from 'node:path';
10
- import * as url from 'node:url';
11
- import { loadPreparedDatasetFromOutput, normalizeFormatExtension } from '../backend/reasoned-output.js';
12
3
  import { failCli } from '../cli-error.js';
13
4
  import { formatDuration } from '../util.js';
14
- import { reasonAction } from './reason.js';
15
- import { resolveCompileOutputRoot, resolveCompileWorkspaceRoot } from './compile.js';
16
- const markdownRuntime = new MarkdownPreviewRuntime(new MarkdownHandlerRegistry());
5
+ import { restPost } from './server/rest.js';
6
+ import { formatLintSummary, printLintDiagnostics } from './lint.js';
17
7
  export const validateAction = async (opts) => {
18
- const workspaceRoot = resolveCompileWorkspaceRoot(opts.workspace);
19
- const owlOutputRoot = resolveCompileOutputRoot(workspaceRoot, opts.owl);
20
- const rdfFormat = normalizeFormatExtension(opts.format);
21
- const markdownRoot = path.resolve(workspaceRoot, opts.md);
22
- const markdownStat = await fs.stat(markdownRoot).catch(() => undefined);
23
- if (!markdownStat?.isDirectory()) {
24
- failCli(chalk.red(`Markdown folder does not exist: ${markdownRoot}`));
25
- }
26
- if (!opts.only) {
27
- await reasonAction({
28
- workspace: workspaceRoot,
29
- owl: owlOutputRoot,
30
- format: rdfFormat,
31
- clean: opts.clean,
32
- pretty: opts.pretty,
33
- only: false,
34
- checkOnly: false,
35
- uniqueNamesAssumption: opts.uniqueNamesAssumption,
36
- explanations: opts.explanations,
37
- profile: opts.profile,
38
- });
39
- }
40
- const servicesBundle = createOwlServices(NodeFileSystem);
41
- await servicesBundle.Oml.shared.workspace.WorkspaceManager.initializeWorkspace([
42
- { uri: URI.file(workspaceRoot).toString(), name: path.basename(workspaceRoot) }
43
- ]);
44
- const preparedDataset = await loadPreparedDatasetFromOutput(workspaceRoot, owlOutputRoot, rdfFormat);
45
- servicesBundle.Oml.reasoning.ReasoningService.loadPreparedDataset(preparedDataset);
46
- const shaclService = createDefaultShaclService(servicesBundle.Oml.reasoning.ReasoningService.getSparqlService(), (modelUri) => servicesBundle.Oml.reasoning.ReasoningService.ensureQueryContext(modelUri), (modelUri) => servicesBundle.Oml.reasoning.ReasoningService.getContextIri(modelUri));
47
- const validationStartedAt = Date.now();
48
- const markdownFiles = await discoverMarkdownFiles(markdownRoot);
49
- const results = [];
50
- for (const markdownFile of markdownFiles) {
51
- const markdown = await fs.readFile(markdownFile, 'utf-8');
52
- const prepared = markdownRuntime.prepare(markdown);
53
- const contextModelUri = resolveContextModelUri(markdownFile, prepared.contextUri, workspaceRoot);
54
- for (const block of prepared.codeBlocks) {
55
- if (block.language !== 'table-editor') {
56
- continue;
57
- }
58
- const validation = await shaclService.validateShacl(contextModelUri, block.content);
59
- results.push({
60
- markdownFile,
61
- blockId: block.id,
62
- lineStart: block.lineStart,
63
- lineEnd: block.lineEnd,
64
- contextModelUri,
65
- conforms: validation.conforms,
66
- issues: validation.issues,
67
- error: validation.error,
68
- });
8
+ const startedAt = Date.now();
9
+ const result = await restPost('/v0/validate', {
10
+ only: opts.only === true,
11
+ }, opts.authToken);
12
+ if (result.lint) {
13
+ const lint = result.lint;
14
+ if (lint.filesChecked <= 0) {
15
+ console.log(chalk.yellow('No .oml files found in server workspace.'));
69
16
  }
70
- }
71
- reportValidationResults(results, workspaceRoot, markdownRoot, validationStartedAt);
72
- if (results.some((result) => result.error || result.issues.length > 0 || !result.conforms)) {
73
- failCli('');
74
- }
75
- };
76
- async function discoverMarkdownFiles(root) {
77
- const entries = await fs.readdir(root, { withFileTypes: true });
78
- const markdownFiles = [];
79
- for (const entry of entries) {
80
- const fullPath = path.join(root, entry.name);
81
- if (entry.isDirectory()) {
82
- if (entry.name === 'node_modules' || entry.name.startsWith('.')) {
83
- continue;
17
+ else {
18
+ printLintDiagnostics(lint);
19
+ const lintElapsedMs = typeof lint.elapsedMs === 'number' && Number.isFinite(lint.elapsedMs) && lint.elapsedMs >= 0
20
+ ? lint.elapsedMs
21
+ : Date.now() - startedAt;
22
+ const lintSummary = formatLintSummary(lint, lintElapsedMs);
23
+ if (lint.errors > 0) {
24
+ failCli(chalk.red(lintSummary));
84
25
  }
85
- markdownFiles.push(...await discoverMarkdownFiles(fullPath));
86
- continue;
87
- }
88
- if (entry.isFile() && entry.name.toLowerCase().endsWith('.md')) {
89
- markdownFiles.push(fullPath);
26
+ if (lint.warnings > 0) {
27
+ failCli(chalk.yellow(lintSummary));
28
+ }
29
+ console.log(chalk.green(lintSummary));
90
30
  }
91
31
  }
92
- return markdownFiles.sort();
93
- }
94
- function resolveContextModelUri(documentFile, contextUri, workspaceRoot) {
95
- if (!contextUri) {
96
- return undefined;
97
- }
98
- const trimmed = contextUri.trim();
99
- if (!trimmed) {
100
- return undefined;
101
- }
102
- if (trimmed.startsWith('workspace:/')) {
103
- const resolved = resolveWorkspacePath(workspaceRoot, trimmed);
104
- return resolved ? url.pathToFileURL(resolved).toString() : undefined;
105
- }
106
- if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) {
107
- return trimmed;
108
- }
109
- if (trimmed.startsWith('/')) {
110
- return url.pathToFileURL(path.resolve(workspaceRoot, trimmed.replace(/^\/+/, ''))).toString();
32
+ if (!result.success) {
33
+ failCli(chalk.red(result.error?.trim() || 'validate failed.'));
111
34
  }
112
- return url.pathToFileURL(path.resolve(path.dirname(documentFile), trimmed)).toString();
113
- }
114
- function resolveWorkspacePath(workspaceRoot, href) {
115
- const trimmed = href.trim();
116
- if (!trimmed.startsWith('workspace:/')) {
117
- return undefined;
118
- }
119
- return path.resolve(workspaceRoot, trimmed.slice('workspace:/'.length));
120
- }
121
- function reportValidationResults(results, workspaceRoot, markdownRoot, startedAt) {
122
- if (results.length === 0) {
123
- console.log(chalk.yellow(`No table-editor blocks found under ${path.relative(workspaceRoot, markdownRoot) || markdownRoot}.`));
35
+ if (result.filesChecked === 0) {
36
+ console.log(chalk.yellow('No markdown/table-editor targets found in server workspace.'));
124
37
  return;
125
38
  }
126
- let issueCount = 0;
127
- let errorCount = 0;
128
- let failingBlockCount = 0;
129
- for (const result of results) {
130
- const relativeFile = path.relative(markdownRoot, result.markdownFile) || path.basename(result.markdownFile);
131
- const location = relativeFile;
132
- if (result.error) {
133
- failingBlockCount += 1;
134
- errorCount += 1;
135
- console.log(chalk.red(`Violation: ${location}: ${result.error}`));
136
- continue;
137
- }
138
- const hasIssues = result.issues.length > 0 || !result.conforms;
139
- if (!hasIssues) {
140
- continue;
141
- }
142
- failingBlockCount += 1;
143
- for (const issue of result.issues) {
144
- issueCount += 1;
145
- const elementLabel = issue.focusNode ? shortIri(issue.focusNode) : '-';
146
- const propertyLabel = issue.propertyName ?? (issue.path ? shortIri(issue.path) : '-');
147
- const severityLabel = shortIri(issue.severity || 'Violation');
148
- console.log(chalk.red(`${severityLabel}: ${location} element=${elementLabel} property=${propertyLabel}: ${describeIssue(issue)}`));
149
- }
150
- if (!result.conforms && result.issues.length === 0) {
151
- issueCount += 1;
152
- console.log(chalk.red(`Violation: ${location}: SHACL validation failed without detailed issues.`));
153
- }
39
+ const validateElapsedMs = typeof result.elapsedMs === 'number' && Number.isFinite(result.elapsedMs) && result.elapsedMs >= 0
40
+ ? result.elapsedMs
41
+ : Date.now() - startedAt;
42
+ if (result.errors > 0) {
43
+ failCli(chalk.red(`validate: ${result.filesChecked} item(s) checked with ${result.errors} error(s) and ${result.warnings} warning(s). [${formatDuration(validateElapsedMs)}]`));
154
44
  }
155
- const duration = formatDuration(Date.now() - startedAt);
156
- const summary = `${results.length} table-editor block(s) scanned [${duration}]`;
157
- if (issueCount === 0 && errorCount === 0) {
158
- console.log(chalk.green(`validate: ${summary}`));
159
- return;
45
+ if (result.warnings > 0) {
46
+ failCli(chalk.yellow(`validate: ${result.filesChecked} item(s) checked with ${result.warnings} warning(s). [${formatDuration(validateElapsedMs)}]`));
160
47
  }
161
- console.log(chalk.red(`validate: ${summary}; ${failingBlockCount} failing block(s), ${issueCount} issue(s), ${errorCount} error(s)`));
162
- }
163
- function shortIri(value) {
164
- const normalized = normalizeNamespace(value);
165
- const hashIndex = normalized.lastIndexOf('#');
166
- if (hashIndex >= 0 && hashIndex < normalized.length - 1) {
167
- return normalized.slice(hashIndex + 1);
168
- }
169
- const slashIndex = normalized.lastIndexOf('/');
170
- if (slashIndex >= 0 && slashIndex < normalized.length - 1) {
171
- return normalized.slice(slashIndex + 1);
172
- }
173
- return normalized;
174
- }
175
- function describeIssue(issue) {
176
- const message = issue.message.trim();
177
- if (message && message !== 'Validation issue.') {
178
- return message;
179
- }
180
- const source = issue.source ? shortIri(issue.source) : undefined;
181
- if (source) {
182
- return source;
183
- }
184
- return 'Validation issue.';
185
- }
48
+ console.log(chalk.green(`validate: ${result.filesChecked} item(s) checked. [${formatDuration(validateElapsedMs)}]`));
49
+ };
186
50
  //# sourceMappingURL=validate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oml/cli",
3
3
  "description": "The cli specific package",
4
- "version": "0.13.0",
4
+ "version": "0.14.1",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": ">=20.10.0",
@@ -21,14 +21,12 @@
21
21
  "build:clean": "npm run clean && npm run build"
22
22
  },
23
23
  "dependencies": {
24
- "@oml/language": "0.13.0",
25
- "@oml/markdown": "0.13.0",
26
- "@oml/owl": "0.13.0",
27
- "@oml/platform": "^0.4.0",
28
- "@oml/reasoner": "^0.3.0",
24
+ "@oml/platform": "^0.5.0",
25
+ "@oml/server": "0.14.1",
29
26
  "chalk": "~5.3.0",
30
- "chevrotain": "11.1.2",
27
+ "chevrotain": "^12.0.0",
31
28
  "commander": "~11.1.0",
29
+ "langium-cli": "^4.2.0",
32
30
  "n3": "^2.0.1"
33
31
  },
34
32
  "volta": {
@@ -9,7 +9,7 @@ import {
9
9
  DEFAULT_API_BASE_URL,
10
10
  DEFAULT_SUPABASE_ANON_KEY,
11
11
  DEFAULT_SUPABASE_URL
12
- } from './platform-constants.js';
12
+ } from './constants.js';
13
13
  const GITHUB_DEVICE_CODE_URL = 'https://github.com/login/device/code';
14
14
  const GITHUB_TOKEN_URL = 'https://github.com/login/oauth/access_token';
15
15
  const GITHUB_USER_URL = 'https://api.github.com/user';
@@ -36,11 +36,17 @@ type StoredSession = {
36
36
  type LoginOptions = {
37
37
  };
38
38
 
39
+ export type OmlCliServerAuthSnapshot = {
40
+ accessToken: string;
41
+ refreshToken?: string;
42
+ expiresAtMs?: number;
43
+ };
44
+
39
45
  export class OmlCliAuthService {
40
46
 
41
47
  async login(options: LoginOptions): Promise<void> {
42
48
  const session = await this.authenticate();
43
- await writeSession(session);
49
+ await writeSession(session, true);
44
50
  const summary = session.userLabel ?? session.email ?? 'signed-in user';
45
51
  console.error(chalk.green(`Signed in as ${summary} via ${session.provider}.`));
46
52
  }
@@ -103,12 +109,49 @@ export class OmlCliAuthService {
103
109
  tokenType: refreshed.token_type,
104
110
  expiresIn: refreshed.expires_in,
105
111
  email: refreshed.email ?? session.email,
112
+ signedInAt: new Date().toISOString(),
106
113
  };
107
114
 
108
115
  await writeSession(updatedSession);
109
116
  return updatedSession.accessToken;
110
117
  }
111
118
 
119
+ async getServerAuthSnapshot(): Promise<OmlCliServerAuthSnapshot> {
120
+ const session = await readSession();
121
+ if (!session?.accessToken) {
122
+ throw new Error('OML CLI authentication is required. Run \'oml login\' first.');
123
+ }
124
+ const signedInAtMs = Date.parse(session.signedInAt);
125
+ const expiresAtMs = Number.isFinite(signedInAtMs)
126
+ ? signedInAtMs + (session.expiresIn * 1000)
127
+ : undefined;
128
+ if (expiresAtMs !== undefined && Date.now() + 20_000 >= expiresAtMs) {
129
+ await this.refreshAccessToken();
130
+ return await this.getServerAuthSnapshot();
131
+ }
132
+ return {
133
+ accessToken: session.accessToken,
134
+ refreshToken: session.refreshToken,
135
+ expiresAtMs,
136
+ };
137
+ }
138
+
139
+ async storeRefreshedTokens(accessToken: string, refreshToken: string, expiresAtMs: number): Promise<void> {
140
+ const session = await readSession();
141
+ if (!session) {
142
+ return;
143
+ }
144
+ const expiresIn = Math.max(0, Math.round((expiresAtMs - Date.now()) / 1000));
145
+ const updatedSession: StoredSession = {
146
+ ...session,
147
+ accessToken,
148
+ refreshToken,
149
+ expiresIn,
150
+ signedInAt: new Date().toISOString(),
151
+ };
152
+ await writeSession(updatedSession);
153
+ }
154
+
112
155
  private async authenticate(): Promise<StoredSession> {
113
156
  return authenticateWithGitHub();
114
157
  }
@@ -147,10 +190,18 @@ async function readSession(): Promise<StoredSession | undefined> {
147
190
  }
148
191
  }
149
192
 
150
- async function writeSession(session: StoredSession): Promise<void> {
193
+ async function writeSession(session: StoredSession, warnAboutPlaintext = false): Promise<void> {
151
194
  const sessionPath = getSessionPath();
152
195
  await fs.mkdir(path.dirname(sessionPath), { recursive: true });
153
196
  await fs.writeFile(sessionPath, `${JSON.stringify(session, null, 2)}\n`, 'utf-8');
197
+ if (warnAboutPlaintext) {
198
+ process.stderr.write(
199
+ chalk.yellow(
200
+ `[oml] Warning: credentials stored in plaintext at ${sessionPath}. ` +
201
+ `A system keychain is not available in this environment.\n`
202
+ )
203
+ );
204
+ }
154
205
  }
155
206
 
156
207
  async function deleteSession(): Promise<void> {
@@ -3,19 +3,18 @@
3
3
  /**
4
4
  * OML Platform integration for the CLI.
5
5
  *
6
- * The platform is the sole authorization mechanism. Users must have
7
- * a valid API key configured and the platform must be reachable for
8
- * commands to execute. No whitelist or other fallback is used.
6
+ * The platform is the sole authorization mechanism. Users must be
7
+ * authenticated via oml login and the platform must be reachable for
8
+ * commands to execute.
9
9
  */
10
10
 
11
11
  import { OmlClient, FileStorageAdapter, installNodeShutdownHandlers } from '@oml/platform';
12
12
  import type { OmlClientConfig } from '@oml/platform';
13
13
  import type { NodeShutdownHandle } from '@oml/platform';
14
14
  import chalk from 'chalk';
15
- import { DEFAULT_API_BASE_URL } from './platform-constants.js';
15
+ import { DEFAULT_API_BASE_URL } from './constants.js';
16
16
  import { OmlCliAuthService } from './auth.js';
17
17
  const API_BASE_URL_ENV = 'OML_PLATFORM_API_URL';
18
- const PLATFORM_DEBUG_ENV = 'OML_PLATFORM_DEBUG';
19
18
 
20
19
  let client: OmlClient | null = null;
21
20
  let shutdownHandle: NodeShutdownHandle | null = null;
@@ -24,10 +23,8 @@ export type CommandInvocationTracker = ReturnType<OmlClient['trackInvocation']>;
24
23
 
25
24
  /**
26
25
  * Initialize the platform client. Call once during CLI startup.
27
- * Uses OML_PLATFORM_API_KEY when present, otherwise the stored
28
- * OAuth platform session from OML CLI login.
29
- * Throws if the platform is unreachable or the chosen auth mode
30
- * is not configured.
26
+ * Uses the stored OAuth session from oml login.
27
+ * Throws if the platform is unreachable or the user is not authenticated.
31
28
  */
32
29
  export async function initializePlatform(
33
30
  authService: OmlCliAuthService,
@@ -35,20 +32,17 @@ export async function initializePlatform(
35
32
  ): Promise<void> {
36
33
  await disposePlatform();
37
34
 
38
- const key = process.env.OML_PLATFORM_API_KEY;
39
35
  const resolvedApiBaseUrl = process.env[API_BASE_URL_ENV]?.trim() || apiBaseUrl;
40
36
 
41
37
  const config: OmlClientConfig = {
42
38
  apiBaseUrl: resolvedApiBaseUrl,
43
39
  tool: 'oml-cli',
44
40
  storage: new FileStorageAdapter(),
45
- auth: key
46
- ? { method: 'api_key', key }
47
- : {
48
- method: 'oauth',
49
- getToken: () => authService.getAccessToken(),
50
- refreshToken: () => authService.refreshAccessToken(),
51
- },
41
+ auth: {
42
+ method: 'oauth',
43
+ getToken: () => authService.getAccessToken(),
44
+ refreshToken: () => authService.refreshAccessToken(),
45
+ },
52
46
  onConcurrencyLimit: (info) => {
53
47
  console.error(chalk.yellow(
54
48
  `OML Platform: concurrent session limit reached `
@@ -61,7 +55,7 @@ export async function initializePlatform(
61
55
  `OML Platform: authentication error — ${toGenericPlatformErrorMessage(error)}`
62
56
  ));
63
57
  },
64
- debug: process.env.OML_PLATFORM_DEBUG === '1',
58
+ debug: isDebugEnabled(),
65
59
  };
66
60
 
67
61
  const platformClient = new OmlClient(config);
@@ -118,7 +112,7 @@ function toGenericPlatformErrorMessage(error: unknown): string {
118
112
  }
119
113
 
120
114
  function isDebugEnabled(): boolean {
121
- return process.env[PLATFORM_DEBUG_ENV] === '1';
115
+ return process.env.OML_PLATFORM_DEBUG === '1';
122
116
  }
123
117
 
124
118
  function formatErrorChain(error: unknown): string {