@edukors/ai-cli 0.0.0-stage → 0.1.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 (106) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +162 -2
  3. package/dist/cli/main.d.ts +2 -0
  4. package/dist/cli/main.js +256 -0
  5. package/dist/cli/main.js.map +1 -0
  6. package/dist/constants.d.ts +2 -0
  7. package/dist/constants.js +3 -0
  8. package/dist/constants.js.map +1 -0
  9. package/dist/diagnostics.d.ts +28 -0
  10. package/dist/diagnostics.js +35 -0
  11. package/dist/diagnostics.js.map +1 -0
  12. package/dist/engine.d.ts +157 -0
  13. package/dist/engine.js +395 -0
  14. package/dist/engine.js.map +1 -0
  15. package/dist/errors.d.ts +27 -0
  16. package/dist/errors.js +59 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/events.d.ts +95 -0
  19. package/dist/events.js +8 -0
  20. package/dist/events.js.map +1 -0
  21. package/dist/host/main.d.ts +2 -0
  22. package/dist/host/main.js +30 -0
  23. package/dist/host/main.js.map +1 -0
  24. package/dist/host/stdio.d.ts +34 -0
  25. package/dist/host/stdio.js +254 -0
  26. package/dist/host/stdio.js.map +1 -0
  27. package/dist/index.d.ts +34 -0
  28. package/dist/index.js +21 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/mcp/config.d.ts +19 -0
  31. package/dist/mcp/config.js +63 -0
  32. package/dist/mcp/config.js.map +1 -0
  33. package/dist/mcp/external.d.ts +55 -0
  34. package/dist/mcp/external.js +129 -0
  35. package/dist/mcp/external.js.map +1 -0
  36. package/dist/mcp/toolServer.d.ts +30 -0
  37. package/dist/mcp/toolServer.js +102 -0
  38. package/dist/mcp/toolServer.js.map +1 -0
  39. package/dist/platform/discovery.d.ts +23 -0
  40. package/dist/platform/discovery.js +64 -0
  41. package/dist/platform/discovery.js.map +1 -0
  42. package/dist/platform/env.d.ts +12 -0
  43. package/dist/platform/env.js +104 -0
  44. package/dist/platform/env.js.map +1 -0
  45. package/dist/platform/login.d.ts +16 -0
  46. package/dist/platform/login.js +42 -0
  47. package/dist/platform/login.js.map +1 -0
  48. package/dist/platform/paths.d.ts +19 -0
  49. package/dist/platform/paths.js +46 -0
  50. package/dist/platform/paths.js.map +1 -0
  51. package/dist/platform/process.d.ts +55 -0
  52. package/dist/platform/process.js +186 -0
  53. package/dist/platform/process.js.map +1 -0
  54. package/dist/provider.d.ts +156 -0
  55. package/dist/provider.js +2 -0
  56. package/dist/provider.js.map +1 -0
  57. package/dist/providers/claude/adapter.d.ts +43 -0
  58. package/dist/providers/claude/adapter.js +398 -0
  59. package/dist/providers/claude/adapter.js.map +1 -0
  60. package/dist/providers/claude/events.d.ts +36 -0
  61. package/dist/providers/claude/events.js +90 -0
  62. package/dist/providers/claude/events.js.map +1 -0
  63. package/dist/providers/codex/adapter.d.ts +28 -0
  64. package/dist/providers/codex/adapter.js +497 -0
  65. package/dist/providers/codex/adapter.js.map +1 -0
  66. package/dist/providers/codex/rpc.d.ts +17 -0
  67. package/dist/providers/codex/rpc.js +75 -0
  68. package/dist/providers/codex/rpc.js.map +1 -0
  69. package/dist/providers.d.ts +9 -0
  70. package/dist/providers.js +15 -0
  71. package/dist/providers.js.map +1 -0
  72. package/dist/redact.d.ts +7 -0
  73. package/dist/redact.js +48 -0
  74. package/dist/redact.js.map +1 -0
  75. package/dist/registry/lock.d.ts +18 -0
  76. package/dist/registry/lock.js +83 -0
  77. package/dist/registry/lock.js.map +1 -0
  78. package/dist/registry/registry.d.ts +38 -0
  79. package/dist/registry/registry.js +119 -0
  80. package/dist/registry/registry.js.map +1 -0
  81. package/dist/session.d.ts +126 -0
  82. package/dist/session.js +333 -0
  83. package/dist/session.js.map +1 -0
  84. package/dist/settings.d.ts +8 -0
  85. package/dist/settings.js +7 -0
  86. package/dist/settings.js.map +1 -0
  87. package/dist/skills.d.ts +24 -0
  88. package/dist/skills.js +91 -0
  89. package/dist/skills.js.map +1 -0
  90. package/dist/testing/fakeProvider.d.ts +22 -0
  91. package/dist/testing/fakeProvider.js +266 -0
  92. package/dist/testing/fakeProvider.js.map +1 -0
  93. package/dist/testing/index.d.ts +2 -0
  94. package/dist/testing/index.js +2 -0
  95. package/dist/testing/index.js.map +1 -0
  96. package/dist/tools.d.ts +45 -0
  97. package/dist/tools.js +32 -0
  98. package/dist/tools.js.map +1 -0
  99. package/dist/version.d.ts +2 -0
  100. package/dist/version.js +3 -0
  101. package/dist/version.js.map +1 -0
  102. package/fixtures/fake-ai.mjs +230 -0
  103. package/fixtures/fake-claude.mjs +62 -0
  104. package/fixtures/fake-codex.mjs +281 -0
  105. package/fixtures/fake-mcp-server.mjs +14 -0
  106. package/package.json +74 -4
@@ -0,0 +1,157 @@
1
+ import type { AiEventListener, Usage } from "./events.js";
2
+ import { Diagnostics, type DiagnosticEntry, type LogSink } from "./diagnostics.js";
3
+ import { DataPaths } from "./platform/paths.js";
4
+ import { AccountRegistry } from "./registry/registry.js";
5
+ import type { AccountStatus, Capabilities, Detection, LoginPrompt, ModelInfo, ProviderAdapter, SessionOptions } from "./provider.js";
6
+ import { AiSession, type Authorizer } from "./session.js";
7
+ import { type ToolDefinition } from "./tools.js";
8
+ export interface AiCliOptions {
9
+ /** Identifies the application, e.g. `slides` or `graph`. Namespaces sessions and logs. */
10
+ appId: string;
11
+ providers: ProviderAdapter[];
12
+ /** Defaults to the shared per-OS-user EDUKORS directory. */
13
+ dataDir?: string;
14
+ /** Receives every (already redacted) diagnostic entry. */
15
+ logSink?: LogSink;
16
+ /** How long a provider has to stop after an interruption before it is shut down. */
17
+ interruptGraceMs?: number;
18
+ /** How long a detection result is reused. */
19
+ detectionTtlMs?: number;
20
+ /** How long `connectAccount` waits for another process signing in to the same provider. */
21
+ authLockTimeoutMs?: number;
22
+ }
23
+ export interface AccountInfo {
24
+ id: string;
25
+ providerId: string;
26
+ label: string;
27
+ createdAt: string;
28
+ updatedAt: string;
29
+ /** Absolute path of the account's managed provider directory (advanced settings only). */
30
+ homeDir: string;
31
+ /** False when this application has no adapter for the account's provider. */
32
+ supported: boolean;
33
+ }
34
+ export interface OpenSessionOptions {
35
+ accountId: string;
36
+ documentId: string;
37
+ instructions?: string;
38
+ tools?: ToolDefinition[];
39
+ options?: SessionOptions;
40
+ /** A provider conversation id saved from a previous session (`session.resumeId`). */
41
+ resumeId?: string;
42
+ /**
43
+ * The user's own MCP servers (`{ name: { command, args, env } | { type: "http" | "sse", url, headers } }`).
44
+ * The library connects to them and offers their tools; each call goes through `authorize`.
45
+ */
46
+ mcpServers?: Record<string, unknown>;
47
+ /** Decides each call to a user's MCP server. Without it, such calls are denied. */
48
+ authorize?: Authorizer;
49
+ /** A folder of skills (`<name>/SKILL.md`) to offer; no other skill is enabled. */
50
+ skillsDir?: string;
51
+ }
52
+ export interface DiagnosticReport {
53
+ library: {
54
+ name: string;
55
+ version: string;
56
+ };
57
+ appId: string;
58
+ platform: string;
59
+ arch: string;
60
+ node: string;
61
+ providers: Detection[];
62
+ accounts: Record<string, number>;
63
+ sessions: {
64
+ id: string;
65
+ providerId: string;
66
+ state: string;
67
+ lateEventsDropped: number;
68
+ }[];
69
+ entries: DiagnosticEntry[];
70
+ }
71
+ export declare class AiCli {
72
+ private readonly options;
73
+ readonly appId: string;
74
+ readonly paths: DataPaths;
75
+ readonly registry: AccountRegistry;
76
+ readonly diagnostics: Diagnostics;
77
+ private readonly adapters;
78
+ private readonly detections;
79
+ private readonly openSessions;
80
+ private readonly listeners;
81
+ private readonly authMutex;
82
+ /** Sign-ins in progress in this process, by account, waiting for a pasted code or not. */
83
+ private readonly logins;
84
+ private readonly log;
85
+ private seq;
86
+ private disposed;
87
+ constructor(options: AiCliOptions);
88
+ providers(): {
89
+ id: string;
90
+ displayName: string;
91
+ installUrl?: string;
92
+ }[];
93
+ /** Whether a provider's CLI is installed and compatible. Cached; `refresh` re-checks. */
94
+ detect(providerId: string, options?: {
95
+ refresh?: boolean;
96
+ }): Promise<Detection>;
97
+ detectAll(options?: {
98
+ refresh?: boolean;
99
+ }): Promise<Detection[]>;
100
+ capabilities(providerId: string): Promise<Capabilities>;
101
+ listAccounts(): Promise<AccountInfo[]>;
102
+ createAccount(input: {
103
+ providerId: string;
104
+ label?: string;
105
+ }): Promise<AccountInfo>;
106
+ /** Labels are display-only; the account id, and every session, stays the same. */
107
+ renameAccount(accountId: string, label: string): Promise<AccountInfo>;
108
+ /**
109
+ * Removes the account from the shared registry, for every EDUKORS
110
+ * application. Sessions this application has open on it are closed.
111
+ * `deleteData` also deletes the account's managed directory; it never
112
+ * touches the user's own provider configuration.
113
+ */
114
+ removeAccount(accountId: string, options?: {
115
+ deleteData?: boolean;
116
+ }): Promise<void>;
117
+ /**
118
+ * Starts the provider's sign-in flow for this account. Sign-ins to the same
119
+ * provider are serialized, in this process and across EDUKORS applications.
120
+ */
121
+ connectAccount(accountId: string, options?: {
122
+ signal?: AbortSignal;
123
+ onLogin?: (prompt: LoginPrompt) => void;
124
+ }): Promise<AccountStatus>;
125
+ /**
126
+ * Hands the code the user pasted to a sign-in waiting for one (after an
127
+ * `onLogin` prompt with `acceptsCode`). The code is never logged.
128
+ */
129
+ submitLoginCode(accountId: string, code: string): void;
130
+ accountStatus(accountId: string, options?: {
131
+ signal?: AbortSignal;
132
+ }): Promise<AccountStatus>;
133
+ /** Signs the account out at the provider. Unlike `removeAccount`, it stays in the registry. */
134
+ logoutAccount(accountId: string): Promise<void>;
135
+ listModels(accountId: string): Promise<ModelInfo[]>;
136
+ /** `null` means the provider did not report usage: unknown, not zero. */
137
+ readUsage(accountId: string): Promise<Usage | null>;
138
+ /**
139
+ * Opens a conversation for one document on one account. Switching accounts
140
+ * means opening a new session: a session id is never reused across accounts.
141
+ */
142
+ openSession(input: OpenSessionOptions): Promise<AiSession>;
143
+ sessions(): AiSession[];
144
+ /** Every event of every session of this instance. Returns an unsubscribe function. */
145
+ onEvent(listener: AiEventListener): () => void;
146
+ /** Safe to export: no credentials, no document content. */
147
+ diagnosticReport(): Promise<DiagnosticReport>;
148
+ /** Closes every session and stops every provider process this instance started. */
149
+ dispose(): Promise<void>;
150
+ private adapter;
151
+ private accountInfo;
152
+ private accountContext;
153
+ private guard;
154
+ private unsupported;
155
+ private publish;
156
+ }
157
+ export declare const createAiCli: (options: AiCliOptions) => AiCli;
package/dist/engine.js ADDED
@@ -0,0 +1,395 @@
1
+ import { randomBytes, randomUUID } from "node:crypto";
2
+ import { mkdir, rm } from "node:fs/promises";
3
+ import { join, relative, isAbsolute } from "node:path";
4
+ import { arch, platform } from "node:os";
5
+ import { AiCliError, toAiCliError } from "./errors.js";
6
+ import { Diagnostics } from "./diagnostics.js";
7
+ import { DataPaths, defaultDataDir } from "./platform/paths.js";
8
+ import { AccountRegistry } from "./registry/registry.js";
9
+ import { KeyedMutex, withLock } from "./registry/lock.js";
10
+ import { AiSession } from "./session.js";
11
+ import { ExternalServers } from "./mcp/external.js";
12
+ import { assertToolNames, toolSpec } from "./tools.js";
13
+ import { redactValue } from "./redact.js";
14
+ import { VERSION } from "./version.js";
15
+ const APP_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;
16
+ export class AiCli {
17
+ options;
18
+ appId;
19
+ paths;
20
+ registry;
21
+ diagnostics;
22
+ adapters = new Map();
23
+ detections = new Map();
24
+ openSessions = new Map();
25
+ listeners = new Set();
26
+ authMutex = new KeyedMutex();
27
+ /** Sign-ins in progress in this process, by account, waiting for a pasted code or not. */
28
+ logins = new Map();
29
+ log;
30
+ seq = 0;
31
+ disposed = false;
32
+ constructor(options) {
33
+ this.options = options;
34
+ if (!APP_ID.test(options.appId))
35
+ throw new AiCliError("INVALID_ARGUMENT", `invalid appId: ${options.appId}`);
36
+ this.appId = options.appId;
37
+ for (const adapter of options.providers) {
38
+ if (this.adapters.has(adapter.id))
39
+ throw new AiCliError("INVALID_ARGUMENT", `duplicate provider: ${adapter.id}`);
40
+ this.adapters.set(adapter.id, adapter);
41
+ }
42
+ this.paths = new DataPaths(options.dataDir ?? defaultDataDir());
43
+ this.registry = new AccountRegistry(this.paths.registryFile, join(this.paths.locksDir, "registry.lock"));
44
+ this.diagnostics = new Diagnostics(500, options.logSink);
45
+ this.log = this.diagnostics.scoped("core");
46
+ }
47
+ // ----------------------------------------------------------------- providers
48
+ providers() {
49
+ return [...this.adapters.values()].map((a) => ({ id: a.id, displayName: a.displayName, ...(a.installUrl ? { installUrl: a.installUrl } : {}) }));
50
+ }
51
+ /** Whether a provider's CLI is installed and compatible. Cached; `refresh` re-checks. */
52
+ detect(providerId, options = {}) {
53
+ const adapter = this.adapter(providerId);
54
+ const cached = this.detections.get(providerId);
55
+ const ttl = this.options.detectionTtlMs ?? 60_000;
56
+ if (cached && !options.refresh && Date.now() - cached.at < ttl)
57
+ return cached.value;
58
+ const log = this.diagnostics.scoped(`provider:${providerId}`);
59
+ const value = adapter.detect(log).catch((e) => {
60
+ log.error("detection failed", e);
61
+ return { providerId, status: "error", detail: e instanceof Error ? e.message : String(e) };
62
+ });
63
+ this.detections.set(providerId, { at: Date.now(), value });
64
+ return value;
65
+ }
66
+ detectAll(options = {}) {
67
+ return Promise.all([...this.adapters.keys()].map((id) => this.detect(id, options)));
68
+ }
69
+ async capabilities(providerId) {
70
+ return this.adapter(providerId).capabilities(await this.detect(providerId));
71
+ }
72
+ // ------------------------------------------------------------------ accounts
73
+ async listAccounts() {
74
+ return (await this.registry.list()).map((a) => this.accountInfo(a));
75
+ }
76
+ async createAccount(input) {
77
+ const adapter = this.adapter(input.providerId);
78
+ const caps = await this.capabilities(adapter.id);
79
+ const label = (input.label ?? "").trim() || `${adapter.displayName}`;
80
+ const id = randomBytes(9).toString("base64url");
81
+ const now = new Date().toISOString();
82
+ const record = await this.registry.update((accounts) => {
83
+ if (!caps.multiAccount && accounts.some((a) => a.providerId === adapter.id)) {
84
+ throw new AiCliError("CAPABILITY_UNSUPPORTED", `${adapter.displayName} does not support more than one account here`, { meta: { providerId: adapter.id } });
85
+ }
86
+ const created = { id, providerId: adapter.id, label: label.slice(0, 80), home: this.paths.accountHomeRelative(id), createdAt: now, updatedAt: now };
87
+ accounts.push(created);
88
+ return created;
89
+ });
90
+ await mkdir(this.paths.resolve(record.home), { recursive: true, mode: 0o700 });
91
+ this.log.info("account created", { accountId: id, providerId: adapter.id });
92
+ return this.accountInfo(record);
93
+ }
94
+ /** Labels are display-only; the account id, and every session, stays the same. */
95
+ async renameAccount(accountId, label) {
96
+ const clean = label.trim();
97
+ if (!clean)
98
+ throw new AiCliError("INVALID_ARGUMENT", "the label cannot be empty");
99
+ const record = await this.registry.update((accounts) => {
100
+ const account = accounts.find((a) => a.id === accountId);
101
+ if (!account)
102
+ throw new AiCliError("ACCOUNT_NOT_FOUND", "no such account", { meta: { accountId } });
103
+ account.label = clean.slice(0, 80);
104
+ account.updatedAt = new Date().toISOString();
105
+ return { ...account };
106
+ });
107
+ return this.accountInfo(record);
108
+ }
109
+ /**
110
+ * Removes the account from the shared registry, for every EDUKORS
111
+ * application. Sessions this application has open on it are closed.
112
+ * `deleteData` also deletes the account's managed directory; it never
113
+ * touches the user's own provider configuration.
114
+ */
115
+ async removeAccount(accountId, options = {}) {
116
+ const record = await this.registry.update((accounts) => {
117
+ const index = accounts.findIndex((a) => a.id === accountId);
118
+ if (index === -1)
119
+ throw new AiCliError("ACCOUNT_NOT_FOUND", "no such account", { meta: { accountId } });
120
+ return accounts.splice(index, 1)[0];
121
+ });
122
+ await Promise.all([...this.openSessions.values()].filter((s) => s.accountId === accountId).map((s) => s.close("accountRemoved")));
123
+ if (options.deleteData) {
124
+ const home = this.paths.resolve(record.home);
125
+ const rel = relative(join(this.paths.root, "ai", "accounts"), home);
126
+ if (!rel || rel.startsWith("..") || isAbsolute(rel))
127
+ throw new AiCliError("INTERNAL", "refusing to delete outside the managed accounts directory");
128
+ await rm(home, { recursive: true, force: true });
129
+ }
130
+ this.log.info("account removed", { accountId, deleteData: Boolean(options.deleteData) });
131
+ }
132
+ /**
133
+ * Starts the provider's sign-in flow for this account. Sign-ins to the same
134
+ * provider are serialized, in this process and across EDUKORS applications.
135
+ */
136
+ async connectAccount(accountId, options = {}) {
137
+ const { adapter, context } = await this.accountContext(accountId, options.signal);
138
+ if (this.logins.has(accountId))
139
+ throw new AiCliError("SESSION_BUSY", "this account is already signing in", { meta: { accountId } });
140
+ const entry = {};
141
+ this.logins.set(accountId, entry);
142
+ const login = {
143
+ prompt: (prompt) => {
144
+ this.log.info("sign-in address offered", { accountId, acceptsCode: prompt.acceptsCode });
145
+ try {
146
+ options.onLogin?.(prompt);
147
+ }
148
+ catch (e) {
149
+ this.log.error("onLogin threw", e);
150
+ }
151
+ },
152
+ code: () => new Promise((resolve, reject) => {
153
+ entry.submit = resolve;
154
+ if (options.signal?.aborted)
155
+ reject(new AiCliError("CANCELLED", "sign-in cancelled"));
156
+ options.signal?.addEventListener("abort", () => reject(new AiCliError("CANCELLED", "sign-in cancelled")), { once: true });
157
+ }),
158
+ };
159
+ try {
160
+ return await this.authMutex.run(adapter.id, () => withLock(join(this.paths.locksDir, `auth-${adapter.id}.lock`), () => this.guard(adapter.connectAccount({ ...context, login }), "LOGIN_FAILED"), {
161
+ timeoutMs: this.options.authLockTimeoutMs ?? 5 * 60_000,
162
+ onTimeout: () => new AiCliError("TIMEOUT", "another EDUKORS application is signing in to this provider", { meta: { providerId: adapter.id } }),
163
+ }));
164
+ }
165
+ finally {
166
+ this.logins.delete(accountId);
167
+ }
168
+ }
169
+ /**
170
+ * Hands the code the user pasted to a sign-in waiting for one (after an
171
+ * `onLogin` prompt with `acceptsCode`). The code is never logged.
172
+ */
173
+ submitLoginCode(accountId, code) {
174
+ const clean = code.trim();
175
+ if (!clean || clean.length > 4096 || /[\r\n\0]/.test(clean))
176
+ throw new AiCliError("INVALID_ARGUMENT", "the code must be a single line of text");
177
+ const entry = this.logins.get(accountId);
178
+ if (!entry?.submit)
179
+ throw new AiCliError("INVALID_ARGUMENT", "no sign-in is waiting for a code on this account", { meta: { accountId } });
180
+ entry.submit(clean);
181
+ entry.submit = undefined;
182
+ }
183
+ async accountStatus(accountId, options = {}) {
184
+ const { adapter, context } = await this.accountContext(accountId, options.signal);
185
+ if (!adapter.capabilities(context.detection).accountStatus)
186
+ return { state: "unknown" };
187
+ return this.guard(adapter.accountStatus(context), "PROVIDER_ERROR");
188
+ }
189
+ /** Signs the account out at the provider. Unlike `removeAccount`, it stays in the registry. */
190
+ async logoutAccount(accountId) {
191
+ const { adapter, context } = await this.accountContext(accountId);
192
+ if (!adapter.logout || !adapter.capabilities(context.detection).logout)
193
+ throw this.unsupported(adapter, "logout");
194
+ await this.authMutex.run(adapter.id, () => this.guard(adapter.logout(context), "PROVIDER_ERROR"));
195
+ }
196
+ async listModels(accountId) {
197
+ const { adapter, context } = await this.accountContext(accountId);
198
+ if (!adapter.listModels || !adapter.capabilities(context.detection).models)
199
+ throw this.unsupported(adapter, "models");
200
+ return this.guard(adapter.listModels(context), "PROVIDER_ERROR");
201
+ }
202
+ /** `null` means the provider did not report usage: unknown, not zero. */
203
+ async readUsage(accountId) {
204
+ const { adapter, context } = await this.accountContext(accountId);
205
+ if (!adapter.readUsage || !adapter.capabilities(context.detection).usage)
206
+ throw this.unsupported(adapter, "usage");
207
+ return this.guard(adapter.readUsage(context), "PROVIDER_ERROR");
208
+ }
209
+ // ------------------------------------------------------------------ sessions
210
+ /**
211
+ * Opens a conversation for one document on one account. Switching accounts
212
+ * means opening a new session: a session id is never reused across accounts.
213
+ */
214
+ async openSession(input) {
215
+ if (this.disposed)
216
+ throw new AiCliError("SESSION_CLOSED", "the library has been disposed");
217
+ if (!input.documentId)
218
+ throw new AiCliError("INVALID_ARGUMENT", "documentId is required");
219
+ const tools = input.tools ?? [];
220
+ try {
221
+ assertToolNames(tools);
222
+ }
223
+ catch (e) {
224
+ throw toAiCliError(e, "INVALID_ARGUMENT");
225
+ }
226
+ const { adapter, context, account } = await this.accountContext(input.accountId);
227
+ const capabilities = adapter.capabilities(context.detection);
228
+ if (tools.length > 0 && !capabilities.tools)
229
+ throw this.unsupported(adapter, "tools");
230
+ if (input.skillsDir && !isAbsolute(input.skillsDir))
231
+ throw new AiCliError("INVALID_ARGUMENT", "skillsDir must be an absolute path");
232
+ const sessionId = randomUUID();
233
+ const log = this.diagnostics.scoped(`session:${sessionId.slice(0, 8)}`);
234
+ const external = input.mcpServers && Object.keys(input.mcpServers).length ? await ExternalServers.connect(input.mcpServers, log) : null;
235
+ const workDir = this.paths.sessionDir(this.appId, input.documentId, account.id);
236
+ const scope = { appId: this.appId, documentId: input.documentId, accountId: account.id, providerId: adapter.id, sessionId };
237
+ const session = new AiSession({
238
+ adapter,
239
+ capabilities,
240
+ scope,
241
+ tools: new Map(tools.map((t) => [t.name, t])),
242
+ ...(external ? { external: external.servers } : {}),
243
+ ...(input.authorize ? { authorize: input.authorize } : {}),
244
+ options: input.options ?? {},
245
+ log,
246
+ interruptGraceMs: this.options.interruptGraceMs ?? 5_000,
247
+ publish: (event) => this.publish(event),
248
+ onClosed: (s) => {
249
+ this.openSessions.delete(s.id);
250
+ void external?.servers.close();
251
+ },
252
+ context: async () => {
253
+ // Re-read on every (re)start: the account may have been removed or relabelled.
254
+ const fresh = await this.accountContext(account.id);
255
+ await mkdir(workDir, { recursive: true, mode: 0o700 });
256
+ return {
257
+ ...fresh.context,
258
+ appId: this.appId,
259
+ documentId: input.documentId,
260
+ workDir,
261
+ instructions: input.instructions ?? "",
262
+ tools: tools.map(toolSpec),
263
+ externalServers: external?.servers.list() ?? [],
264
+ ...(input.skillsDir ? { skillsDir: input.skillsDir } : {}),
265
+ options: {},
266
+ };
267
+ },
268
+ });
269
+ this.openSessions.set(sessionId, session);
270
+ try {
271
+ await session.start(input.resumeId);
272
+ }
273
+ catch (e) {
274
+ // Only the user's servers were started.
275
+ this.openSessions.delete(sessionId);
276
+ await external?.servers.close();
277
+ throw e;
278
+ }
279
+ if (external)
280
+ session.reportServers(external.statuses);
281
+ return session;
282
+ }
283
+ sessions() {
284
+ return [...this.openSessions.values()];
285
+ }
286
+ /** Every event of every session of this instance. Returns an unsubscribe function. */
287
+ onEvent(listener) {
288
+ this.listeners.add(listener);
289
+ return () => this.listeners.delete(listener);
290
+ }
291
+ // --------------------------------------------------------------- diagnostics
292
+ /** Safe to export: no credentials, no document content. */
293
+ async diagnosticReport() {
294
+ const accounts = {};
295
+ try {
296
+ for (const a of await this.registry.list())
297
+ accounts[a.providerId] = (accounts[a.providerId] ?? 0) + 1;
298
+ }
299
+ catch (e) {
300
+ this.log.error("could not read the registry", e);
301
+ }
302
+ return redactValue({
303
+ library: { name: "@edukors/ai-cli", version: VERSION },
304
+ appId: this.appId,
305
+ platform: platform(),
306
+ arch: arch(),
307
+ node: process.version,
308
+ providers: await this.detectAll(),
309
+ accounts,
310
+ sessions: this.sessions().map((s) => ({ id: s.id, providerId: s.providerId, state: s.state, lateEventsDropped: s.lateEventsDropped })),
311
+ entries: this.diagnostics.snapshot(),
312
+ });
313
+ }
314
+ /** Closes every session and stops every provider process this instance started. */
315
+ async dispose() {
316
+ this.disposed = true;
317
+ await Promise.all(this.sessions().map((s) => s.close("disposed")));
318
+ this.listeners.clear();
319
+ }
320
+ // ----------------------------------------------------------------- internals
321
+ adapter(providerId) {
322
+ const adapter = this.adapters.get(providerId);
323
+ if (!adapter)
324
+ throw new AiCliError("PROVIDER_UNKNOWN", `unknown provider: ${providerId}`, { meta: { providerId } });
325
+ return adapter;
326
+ }
327
+ accountInfo(record) {
328
+ return {
329
+ id: record.id,
330
+ providerId: record.providerId,
331
+ label: record.label,
332
+ createdAt: record.createdAt,
333
+ updatedAt: record.updatedAt,
334
+ homeDir: this.paths.resolve(record.home),
335
+ supported: this.adapters.has(record.providerId),
336
+ };
337
+ }
338
+ async accountContext(accountId, signal) {
339
+ const account = await this.registry.get(accountId);
340
+ if (!account)
341
+ throw new AiCliError("ACCOUNT_NOT_FOUND", "no such account", { meta: { accountId } });
342
+ const adapter = this.adapter(account.providerId);
343
+ const detection = await this.detect(adapter.id);
344
+ if (detection.status === "missing")
345
+ throw new AiCliError("CLI_MISSING", `${adapter.displayName} is not installed`, { meta: { providerId: adapter.id } });
346
+ if (detection.status === "incompatible") {
347
+ throw new AiCliError("CLI_INCOMPATIBLE", `${adapter.displayName} ${detection.version ?? ""} is not supported`.trim(), {
348
+ meta: { providerId: adapter.id, version: detection.version, required: detection.requiredVersion },
349
+ });
350
+ }
351
+ if (detection.status !== "ready")
352
+ throw new AiCliError("PROVIDER_ERROR", `${adapter.displayName} could not be checked`, { meta: { providerId: adapter.id, detail: detection.detail } });
353
+ const homeDir = this.paths.resolve(account.home);
354
+ await mkdir(homeDir, { recursive: true, mode: 0o700 });
355
+ return {
356
+ adapter,
357
+ account,
358
+ context: {
359
+ accountId: account.id,
360
+ label: account.label,
361
+ homeDir,
362
+ detection,
363
+ log: this.diagnostics.scoped(`provider:${adapter.id}`),
364
+ ...(signal ? { signal } : {}),
365
+ },
366
+ };
367
+ }
368
+ async guard(work, fallback) {
369
+ try {
370
+ return await work;
371
+ }
372
+ catch (e) {
373
+ const error = toAiCliError(e, fallback);
374
+ this.log.warn(`operation failed: ${error.code}`, { message: error.message, meta: error.meta });
375
+ throw error;
376
+ }
377
+ }
378
+ unsupported(adapter, capability) {
379
+ return new AiCliError("CAPABILITY_UNSUPPORTED", `${adapter.displayName} does not support ${capability}`, { meta: { providerId: adapter.id, capability } });
380
+ }
381
+ publish(partial) {
382
+ const event = { ...partial, seq: ++this.seq, at: new Date().toISOString() };
383
+ for (const listener of this.listeners) {
384
+ try {
385
+ listener(event);
386
+ }
387
+ catch (e) {
388
+ this.log.error("event listener threw", e);
389
+ }
390
+ }
391
+ return event;
392
+ }
393
+ }
394
+ export const createAiCli = (options) => new AiCli(options);
395
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Stable error codes. Applications translate these into actionable language;
3
+ * the raw provider message belongs in redacted diagnostics, not the main UI.
4
+ */
5
+ export declare const ERROR_CODES: readonly ["PROVIDER_UNKNOWN", "CLI_MISSING", "CLI_INCOMPATIBLE", "CAPABILITY_UNSUPPORTED", "ACCOUNT_NOT_FOUND", "ACCOUNT_DISCONNECTED", "ACCOUNT_EXPIRED", "LOGIN_FAILED", "SESSION_CLOSED", "SESSION_BUSY", "QUESTION_NOT_FOUND", "PROVIDER_START_FAILED", "PROVIDER_CRASHED", "PROVIDER_PROTOCOL", "PROVIDER_ERROR", "RATE_LIMITED", "TIMEOUT", "CANCELLED", "TOOL_NOT_FOUND", "TOOL_INVALID_ARGUMENTS", "TOOL_FAILED", "TOOL_DENIED", "REGISTRY_LOCKED", "REGISTRY_CORRUPT", "REGISTRY_TOO_NEW", "INVALID_ARGUMENT", "INTERNAL"];
6
+ export type ErrorCode = (typeof ERROR_CODES)[number];
7
+ export type ErrorMeta = Record<string, string | number | boolean | null | undefined>;
8
+ export interface SerializedError {
9
+ code: ErrorCode;
10
+ message: string;
11
+ retryable: boolean;
12
+ meta?: ErrorMeta;
13
+ }
14
+ export declare class AiCliError extends Error {
15
+ readonly code: ErrorCode;
16
+ readonly meta: ErrorMeta | undefined;
17
+ readonly retryable: boolean;
18
+ constructor(code: ErrorCode, message: string, options?: {
19
+ meta?: ErrorMeta;
20
+ cause?: unknown;
21
+ retryable?: boolean;
22
+ });
23
+ toJSON(): SerializedError;
24
+ }
25
+ export declare const isAiCliError: (value: unknown) => value is AiCliError;
26
+ /** Wraps anything thrown into an AiCliError, keeping the original as the cause. */
27
+ export declare function toAiCliError(value: unknown, fallback?: ErrorCode): AiCliError;