@mnemom/mnemom 0.11.0 → 0.12.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.
package/dist/lib/auth.js CHANGED
@@ -311,11 +311,7 @@ async function startCallbackServer(expectedState) {
311
311
  };
312
312
  }
313
313
  function openBrowser(url) {
314
- const cmd = process.platform === "darwin"
315
- ? "open"
316
- : process.platform === "win32"
317
- ? "start"
318
- : "xdg-open";
314
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
319
315
  exec(`${cmd} ${JSON.stringify(url)}`);
320
316
  }
321
317
  // ============================================================================
@@ -0,0 +1,40 @@
1
+ /**
2
+ * SSE event-stream consumer for `mnemom listen` (Track 2 W3.4b).
3
+ *
4
+ * Parses `text/event-stream` framing into `SseFrame` objects per the
5
+ * W3C EventSource spec subset we need:
6
+ *
7
+ * - Events delimited by `\n\n`.
8
+ * - Lines starting with `:` are comments (heartbeats).
9
+ * - `event: <name>` sets the frame's event name (default "message").
10
+ * - `data: <json>` accumulates into a multi-line payload.
11
+ * - `id: <cursor>` sets the frame's last-event-id.
12
+ *
13
+ * Exposed as a generator so callers can iterate with `for await`.
14
+ */
15
+ export interface SseFrame {
16
+ event: string;
17
+ /** Multi-line `data:` payload joined with `\n`. */
18
+ data: string;
19
+ /** The `id:` cursor (for Last-Event-ID reconnect). */
20
+ id?: string;
21
+ }
22
+ /**
23
+ * Consume a fetch Response body and yield SSE frames.
24
+ *
25
+ * Buffers across chunk boundaries — SSE delimiters can land mid-chunk.
26
+ */
27
+ export declare function parseSseStream(body: ReadableStream<Uint8Array>): AsyncGenerator<SseFrame, void, void>;
28
+ /**
29
+ * Re-sign a webhook event body with a local-only secret. Mirrors the
30
+ * platform's HMAC-SHA256 over `${ts}.${rawBody}` convention so the
31
+ * receiver verifies cleanly with the same scheme.
32
+ *
33
+ * Used by `mnemom listen --forward-to <url> --secret <hex>` to make
34
+ * the local receiver behave identically to a production webhook
35
+ * subscriber.
36
+ */
37
+ export declare function reSignDelivery(rawBody: string, signingSecret: string, nowSeconds?: number): {
38
+ timestamp: string;
39
+ signature: string;
40
+ };
@@ -0,0 +1,101 @@
1
+ /**
2
+ * SSE event-stream consumer for `mnemom listen` (Track 2 W3.4b).
3
+ *
4
+ * Parses `text/event-stream` framing into `SseFrame` objects per the
5
+ * W3C EventSource spec subset we need:
6
+ *
7
+ * - Events delimited by `\n\n`.
8
+ * - Lines starting with `:` are comments (heartbeats).
9
+ * - `event: <name>` sets the frame's event name (default "message").
10
+ * - `data: <json>` accumulates into a multi-line payload.
11
+ * - `id: <cursor>` sets the frame's last-event-id.
12
+ *
13
+ * Exposed as a generator so callers can iterate with `for await`.
14
+ */
15
+ import { createHmac } from "node:crypto";
16
+ /**
17
+ * Consume a fetch Response body and yield SSE frames.
18
+ *
19
+ * Buffers across chunk boundaries — SSE delimiters can land mid-chunk.
20
+ */
21
+ export async function* parseSseStream(body) {
22
+ const reader = body.getReader();
23
+ const decoder = new TextDecoder();
24
+ let buf = "";
25
+ try {
26
+ while (true) {
27
+ const { done, value } = await reader.read();
28
+ if (done)
29
+ break;
30
+ buf += decoder.decode(value, { stream: true });
31
+ // Frames end at \n\n. Process all complete frames; keep the trailing partial.
32
+ let idx;
33
+ while ((idx = buf.indexOf("\n\n")) !== -1) {
34
+ const frameRaw = buf.slice(0, idx);
35
+ buf = buf.slice(idx + 2);
36
+ const frame = parseFrame(frameRaw);
37
+ if (frame)
38
+ yield frame;
39
+ }
40
+ }
41
+ // Drain trailing partial — usually a comment line right before the
42
+ // server-side close. Process if it parses cleanly.
43
+ if (buf.length > 0) {
44
+ const frame = parseFrame(buf);
45
+ if (frame)
46
+ yield frame;
47
+ }
48
+ }
49
+ finally {
50
+ try {
51
+ await reader.cancel();
52
+ }
53
+ catch {
54
+ /* socket already torn down */
55
+ }
56
+ }
57
+ }
58
+ function parseFrame(raw) {
59
+ const lines = raw.split("\n");
60
+ let event = "message";
61
+ let id;
62
+ const dataLines = [];
63
+ let hadDataField = false;
64
+ for (const line of lines) {
65
+ if (line.length === 0)
66
+ continue;
67
+ if (line.startsWith(":"))
68
+ continue; // heartbeat comment
69
+ const colonIdx = line.indexOf(":");
70
+ if (colonIdx === -1)
71
+ continue;
72
+ const field = line.slice(0, colonIdx);
73
+ const value = line.slice(colonIdx + 1).replace(/^ /, ""); // strip optional leading space
74
+ if (field === "event")
75
+ event = value;
76
+ else if (field === "data") {
77
+ dataLines.push(value);
78
+ hadDataField = true;
79
+ }
80
+ else if (field === "id")
81
+ id = value;
82
+ }
83
+ if (!hadDataField)
84
+ return null;
85
+ return { event, data: dataLines.join("\n"), id };
86
+ }
87
+ // ─── HMAC re-signing for local forwarding ───────────────────────────────
88
+ /**
89
+ * Re-sign a webhook event body with a local-only secret. Mirrors the
90
+ * platform's HMAC-SHA256 over `${ts}.${rawBody}` convention so the
91
+ * receiver verifies cleanly with the same scheme.
92
+ *
93
+ * Used by `mnemom listen --forward-to <url> --secret <hex>` to make
94
+ * the local receiver behave identically to a production webhook
95
+ * subscriber.
96
+ */
97
+ export function reSignDelivery(rawBody, signingSecret, nowSeconds = Math.floor(Date.now() / 1000)) {
98
+ const timestamp = String(nowSeconds);
99
+ const signature = "v1=" + createHmac("sha256", signingSecret).update(`${timestamp}.${rawBody}`).digest("hex");
100
+ return { timestamp, signature };
101
+ }
@@ -0,0 +1,80 @@
1
+ export interface WebhookEndpoint {
2
+ endpoint_id: string;
3
+ billing_account_id: string;
4
+ url: string;
5
+ description: string;
6
+ signing_secret?: string;
7
+ event_types: string[];
8
+ is_active: boolean;
9
+ consecutive_failures: number;
10
+ disabled_at: string | null;
11
+ disabled_reason: string | null;
12
+ created_at: string;
13
+ updated_at: string;
14
+ }
15
+ export interface WebhookDelivery {
16
+ delivery_id: string;
17
+ event_id: string;
18
+ endpoint_id: string;
19
+ status: string;
20
+ attempt_count?: number;
21
+ last_attempt_at?: string | null;
22
+ next_attempt_at?: string | null;
23
+ last_status_code?: number | null;
24
+ last_error?: string | null;
25
+ created_at?: string;
26
+ }
27
+ export interface WebhookReplayResponse {
28
+ event_id: string;
29
+ event_type: string;
30
+ deliveries: Array<{
31
+ delivery_id: string;
32
+ endpoint_id: string;
33
+ }>;
34
+ failed_endpoints?: Array<{
35
+ endpoint_id: string;
36
+ error: string;
37
+ }>;
38
+ message?: string;
39
+ }
40
+ export interface TestDeliveryResult {
41
+ success: boolean;
42
+ status: number | null;
43
+ latency_ms: number | null;
44
+ error: string | null;
45
+ }
46
+ export declare function listWebhookEndpoints(orgId: string): Promise<WebhookEndpoint[]>;
47
+ export declare function getWebhookEndpoint(orgId: string, endpointId: string): Promise<WebhookEndpoint>;
48
+ export declare function createWebhookEndpoint(orgId: string, body: {
49
+ url: string;
50
+ description?: string;
51
+ event_types?: string[];
52
+ }): Promise<WebhookEndpoint>;
53
+ export declare function updateWebhookEndpoint(orgId: string, endpointId: string, body: {
54
+ url?: string;
55
+ description?: string;
56
+ event_types?: string[];
57
+ is_active?: boolean;
58
+ }): Promise<WebhookEndpoint>;
59
+ export declare function deleteWebhookEndpoint(orgId: string, endpointId: string): Promise<{
60
+ deleted: true;
61
+ endpoint_id: string;
62
+ }>;
63
+ export declare function rotateWebhookSecret(orgId: string, endpointId: string): Promise<{
64
+ endpoint_id: string;
65
+ signing_secret: string;
66
+ }>;
67
+ export declare function testWebhookEndpoint(orgId: string, endpointId: string): Promise<TestDeliveryResult>;
68
+ export declare function listWebhookDeliveries(orgId: string, opts?: {
69
+ endpointId?: string;
70
+ limit?: number;
71
+ offset?: number;
72
+ }): Promise<WebhookDelivery[]>;
73
+ export declare function redeliverWebhookEvent(orgId: string, deliveryId: string): Promise<{
74
+ delivery_id: string;
75
+ event_id: string;
76
+ status: string;
77
+ }>;
78
+ export declare function replayWebhookEvent(orgId: string, eventId: string, opts?: {
79
+ endpointIds?: string[];
80
+ }): Promise<WebhookReplayResponse>;
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Webhook lifecycle API client for the Mnemom CLI.
3
+ *
4
+ * Wraps `/v1/orgs/:org_id/webhooks*` endpoints. Every mutation includes
5
+ * a fresh `Idempotency-Key` per the post-W2.x server contract — see
6
+ * `mnemom-api/src/webhooks/handlers.ts` for the requirement.
7
+ */
8
+ import { getApiUrl } from "./config.js";
9
+ import { newIdempotencyKey } from "./api.js";
10
+ import { resolveAuth, forceRefreshAccessToken } from "./auth.js";
11
+ const API_BASE = getApiUrl();
12
+ function validateUrl(url) {
13
+ const parsed = new URL(url);
14
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
15
+ throw new Error(`Invalid URL protocol: ${parsed.protocol}`);
16
+ }
17
+ return parsed.href;
18
+ }
19
+ async function authHeaders() {
20
+ const cred = await resolveAuth();
21
+ switch (cred.type) {
22
+ case "jwt":
23
+ return { Authorization: `Bearer ${cred.token}` };
24
+ case "api-key":
25
+ return { "X-Mnemom-Api-Key": cred.key };
26
+ case "none":
27
+ return {};
28
+ }
29
+ }
30
+ async function fetchWithAuthRetry(url, buildInit) {
31
+ const first = await fetch(url, await buildInit());
32
+ if (first.status !== 401)
33
+ return first;
34
+ const refreshed = await forceRefreshAccessToken();
35
+ if (!refreshed)
36
+ return first;
37
+ return fetch(url, await buildInit());
38
+ }
39
+ async function unwrap(response, action) {
40
+ if (!response.ok) {
41
+ if (response.status === 401) {
42
+ throw new Error("Not authenticated. Run `mnemom login` or set MNEMOM_API_KEY.");
43
+ }
44
+ const err = (await response.json().catch(() => ({})));
45
+ const msg = err.message || err.error || `${action} failed: HTTP ${response.status}`;
46
+ throw new Error(`${response.status}: ${msg}`);
47
+ }
48
+ return (await response.json());
49
+ }
50
+ // ─── List + get ──────────────────────────────────────────────────────────
51
+ export async function listWebhookEndpoints(orgId) {
52
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks`);
53
+ const response = await fetchWithAuthRetry(url, async () => ({
54
+ headers: { ...(await authHeaders()), Accept: "application/json" },
55
+ }));
56
+ return unwrap(response, "List webhook endpoints");
57
+ }
58
+ export async function getWebhookEndpoint(orgId, endpointId) {
59
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks/${endpointId}`);
60
+ const response = await fetchWithAuthRetry(url, async () => ({
61
+ headers: { ...(await authHeaders()), Accept: "application/json" },
62
+ }));
63
+ return unwrap(response, `Get webhook endpoint '${endpointId}'`);
64
+ }
65
+ // ─── Create / update / delete ────────────────────────────────────────────
66
+ export async function createWebhookEndpoint(orgId, body) {
67
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks`);
68
+ const response = await fetchWithAuthRetry(url, async () => ({
69
+ method: "POST",
70
+ headers: {
71
+ ...(await authHeaders()),
72
+ "Content-Type": "application/json",
73
+ Accept: "application/json",
74
+ "Idempotency-Key": newIdempotencyKey(),
75
+ },
76
+ body: JSON.stringify(body),
77
+ }));
78
+ return unwrap(response, "Create webhook endpoint");
79
+ }
80
+ export async function updateWebhookEndpoint(orgId, endpointId, body) {
81
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks/${endpointId}`);
82
+ const response = await fetchWithAuthRetry(url, async () => ({
83
+ method: "PATCH",
84
+ headers: {
85
+ ...(await authHeaders()),
86
+ "Content-Type": "application/json",
87
+ Accept: "application/json",
88
+ "Idempotency-Key": newIdempotencyKey(),
89
+ },
90
+ body: JSON.stringify(body),
91
+ }));
92
+ return unwrap(response, `Update webhook endpoint '${endpointId}'`);
93
+ }
94
+ export async function deleteWebhookEndpoint(orgId, endpointId) {
95
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks/${endpointId}`);
96
+ const response = await fetchWithAuthRetry(url, async () => ({
97
+ method: "DELETE",
98
+ headers: {
99
+ ...(await authHeaders()),
100
+ Accept: "application/json",
101
+ "Idempotency-Key": newIdempotencyKey(),
102
+ },
103
+ }));
104
+ return unwrap(response, `Delete webhook endpoint '${endpointId}'`);
105
+ }
106
+ // ─── Operate ─────────────────────────────────────────────────────────────
107
+ export async function rotateWebhookSecret(orgId, endpointId) {
108
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks/${endpointId}/rotate-secret`);
109
+ const response = await fetchWithAuthRetry(url, async () => ({
110
+ method: "POST",
111
+ headers: {
112
+ ...(await authHeaders()),
113
+ Accept: "application/json",
114
+ "Idempotency-Key": newIdempotencyKey(),
115
+ },
116
+ }));
117
+ return unwrap(response, `Rotate signing secret for '${endpointId}'`);
118
+ }
119
+ export async function testWebhookEndpoint(orgId, endpointId) {
120
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks/${endpointId}/test`);
121
+ const response = await fetchWithAuthRetry(url, async () => ({
122
+ method: "POST",
123
+ headers: {
124
+ ...(await authHeaders()),
125
+ Accept: "application/json",
126
+ "Idempotency-Key": newIdempotencyKey(),
127
+ },
128
+ }));
129
+ return unwrap(response, `Test webhook endpoint '${endpointId}'`);
130
+ }
131
+ export async function listWebhookDeliveries(orgId, opts = {}) {
132
+ const params = new URLSearchParams();
133
+ if (opts.endpointId)
134
+ params.set("endpoint_id", opts.endpointId);
135
+ if (opts.limit !== undefined)
136
+ params.set("limit", String(opts.limit));
137
+ if (opts.offset !== undefined)
138
+ params.set("offset", String(opts.offset));
139
+ const qs = params.toString();
140
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks/deliveries${qs ? `?${qs}` : ""}`);
141
+ const response = await fetchWithAuthRetry(url, async () => ({
142
+ headers: { ...(await authHeaders()), Accept: "application/json" },
143
+ }));
144
+ return unwrap(response, "List webhook deliveries");
145
+ }
146
+ export async function redeliverWebhookEvent(orgId, deliveryId) {
147
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks/deliveries/${deliveryId}/redeliver`);
148
+ const response = await fetchWithAuthRetry(url, async () => ({
149
+ method: "POST",
150
+ headers: {
151
+ ...(await authHeaders()),
152
+ Accept: "application/json",
153
+ "Idempotency-Key": newIdempotencyKey(),
154
+ },
155
+ }));
156
+ return unwrap(response, `Redeliver webhook event '${deliveryId}'`);
157
+ }
158
+ export async function replayWebhookEvent(orgId, eventId, opts = {}) {
159
+ const url = validateUrl(`${API_BASE}/v1/orgs/${orgId}/webhooks/events/${eventId}/replay`);
160
+ const body = opts.endpointIds && opts.endpointIds.length > 0 ? { endpoint_ids: opts.endpointIds } : {};
161
+ const response = await fetchWithAuthRetry(url, async () => ({
162
+ method: "POST",
163
+ headers: {
164
+ ...(await authHeaders()),
165
+ "Content-Type": "application/json",
166
+ Accept: "application/json",
167
+ "Idempotency-Key": newIdempotencyKey(),
168
+ },
169
+ body: JSON.stringify(body),
170
+ }));
171
+ return unwrap(response, `Replay event '${eventId}'`);
172
+ }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  // smoltbot is deprecated — this shim prints a warning then hands off to mnemom
3
- process.stderr.write('\n⚠️ The smoltbot command is deprecated. Use mnemom instead.\n' +
4
- ' Install: npm install -g @mnemom/mnemom\n\n');
3
+ process.stderr.write("\n⚠️ The smoltbot command is deprecated. Use mnemom instead.\n" +
4
+ " Install: npm install -g @mnemom/mnemom\n\n");
5
5
  // Dynamic import runs index.ts which calls program.parse(process.argv) automatically
6
- await import('./index.js');
6
+ await import("./index.js");
7
7
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnemom/mnemom",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "description": "Transparent AI agent tracing",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,16 +0,0 @@
1
- import type { ModelDefinition, Provider } from "./openclaw.js";
2
- /**
3
- * Refresh the model cache in the background.
4
- * Fetches from the gateway and saves to disk.
5
- * Fails silently — never blocks the caller.
6
- */
7
- export declare function refreshModelCache(): Promise<void>;
8
- /**
9
- * Get a model definition, checking: static registry -> cache -> inference fallback.
10
- * This is the primary entry point for looking up model definitions.
11
- */
12
- export declare function getCachedModelDefinition(modelId: string): ModelDefinition;
13
- /**
14
- * Get all known models from both static registry and cache.
15
- */
16
- export declare function getAllCachedModels(): Record<Provider, Record<string, ModelDefinition>>;
@@ -1,137 +0,0 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import { MODEL_REGISTRY, getModelDefinition as getStaticModelDefinition } from "./models.js";
4
- import { MNEMOM_DIR } from "./config.js";
5
- const CACHE_FILE = path.join(MNEMOM_DIR, "models-cache.json");
6
- const MODELS_URL = "https://gateway.mnemom.ai/models.json";
7
- const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
8
- /**
9
- * Load the cached model registry from disk.
10
- * Returns null if cache doesn't exist or is expired.
11
- */
12
- function loadCache() {
13
- if (!fs.existsSync(CACHE_FILE)) {
14
- return null;
15
- }
16
- try {
17
- const content = fs.readFileSync(CACHE_FILE, "utf-8");
18
- const cache = JSON.parse(content);
19
- // Check TTL
20
- const fetchedAt = new Date(cache.fetchedAt).getTime();
21
- if (Date.now() - fetchedAt > CACHE_TTL_MS) {
22
- return null; // Expired
23
- }
24
- return cache;
25
- }
26
- catch {
27
- return null;
28
- }
29
- }
30
- /**
31
- * Save model registry to disk cache.
32
- */
33
- function saveCache(models) {
34
- if (!models || typeof models !== "object") {
35
- return;
36
- }
37
- // Ensure directory exists
38
- if (!fs.existsSync(MNEMOM_DIR)) {
39
- fs.mkdirSync(MNEMOM_DIR, { recursive: true });
40
- }
41
- // Validate write path stays within expected directory
42
- const resolvedCachePath = path.resolve(CACHE_FILE);
43
- if (!resolvedCachePath.startsWith(path.resolve(MNEMOM_DIR))) {
44
- throw new Error("Cache file path escapes expected directory");
45
- }
46
- // Re-serialize HTTP-sourced data to sanitize before writing to disk
47
- const sanitizedModels = JSON.parse(JSON.stringify(models));
48
- const cache = {
49
- fetchedAt: new Date().toISOString(),
50
- models: sanitizedModels,
51
- };
52
- // Atomic write: temp file + rename to prevent corruption
53
- const tmpFile = `${resolvedCachePath}.${process.pid}.tmp`;
54
- fs.writeFileSync(tmpFile, JSON.stringify(cache, null, 2));
55
- fs.renameSync(tmpFile, resolvedCachePath);
56
- }
57
- /**
58
- * Fetch fresh model registry from the gateway.
59
- * Fails silently on network errors — returns null.
60
- */
61
- async function fetchRemoteModels() {
62
- try {
63
- const response = await fetch(MODELS_URL, {
64
- signal: AbortSignal.timeout(5000),
65
- });
66
- if (!response.ok) {
67
- return null;
68
- }
69
- const data = (await response.json());
70
- // Basic validation
71
- if (!data.anthropic && !data.openai && !data.gemini) {
72
- return null;
73
- }
74
- return data;
75
- }
76
- catch {
77
- return null;
78
- }
79
- }
80
- /**
81
- * Refresh the model cache in the background.
82
- * Fetches from the gateway and saves to disk.
83
- * Fails silently — never blocks the caller.
84
- */
85
- export async function refreshModelCache() {
86
- const remote = await fetchRemoteModels();
87
- if (remote) {
88
- saveCache(remote);
89
- }
90
- }
91
- /**
92
- * Get a model definition, checking: static registry -> cache -> inference fallback.
93
- * This is the primary entry point for looking up model definitions.
94
- */
95
- export function getCachedModelDefinition(modelId) {
96
- // 1. Check static registry first (always up to date with code)
97
- for (const provider of Object.values(MODEL_REGISTRY)) {
98
- const known = provider[modelId];
99
- if (known)
100
- return known;
101
- }
102
- // 2. Check disk cache
103
- const cache = loadCache();
104
- if (cache) {
105
- for (const provider of Object.values(cache.models)) {
106
- const cached = provider[modelId];
107
- if (cached)
108
- return cached;
109
- }
110
- }
111
- // 3. Fall back to inference (same as static getModelDefinition)
112
- return getStaticModelDefinition(modelId);
113
- }
114
- /**
115
- * Get all known models from both static registry and cache.
116
- */
117
- export function getAllCachedModels() {
118
- const result = {
119
- anthropic: { ...MODEL_REGISTRY.anthropic },
120
- openai: { ...MODEL_REGISTRY.openai },
121
- gemini: { ...MODEL_REGISTRY.gemini },
122
- };
123
- // Merge cache (cache entries don't override static entries)
124
- const cache = loadCache();
125
- if (cache) {
126
- for (const [provider, models] of Object.entries(cache.models)) {
127
- if (!result[provider])
128
- continue;
129
- for (const [id, model] of Object.entries(models)) {
130
- if (!(id in result[provider])) {
131
- result[provider][id] = model;
132
- }
133
- }
134
- }
135
- }
136
- return result;
137
- }
@@ -1,41 +0,0 @@
1
- import type { ModelDefinition, Provider } from "./openclaw.js";
2
- /**
3
- * Multi-provider model registry.
4
- * Focuses on top-tier reasoning models that OpenClaws use as substrates.
5
- */
6
- export declare const MODEL_REGISTRY: Record<Provider, Record<string, ModelDefinition>>;
7
- /**
8
- * Backward-compatible re-export of Anthropic models.
9
- */
10
- export declare const ANTHROPIC_MODELS: Record<string, ModelDefinition>;
11
- /**
12
- * Detect provider from a model ID string.
13
- */
14
- export declare function detectProvider(modelId: string): Provider | null;
15
- /**
16
- * Get model definition by ID — searches all providers.
17
- * Returns the definition if known, or creates a basic one if unknown.
18
- */
19
- export declare function getModelDefinition(modelId: string): ModelDefinition;
20
- /**
21
- * Check if a model ID is a known model (any provider).
22
- */
23
- export declare function isKnownModel(modelId: string): boolean;
24
- /**
25
- * Check if a model ID looks like an Anthropic model.
26
- */
27
- export declare function isAnthropicModel(modelId: string): boolean;
28
- /**
29
- * Format a model ID into a human-readable name.
30
- * Handles Anthropic, OpenAI, and Gemini model ID formats.
31
- */
32
- export declare function formatModelName(modelId: string): string;
33
- /**
34
- * Get all known model IDs across all providers.
35
- */
36
- export declare function getAllKnownModelIds(): string[];
37
- /**
38
- * Get the latest models per provider.
39
- * Returns { anthropic: [...], openai: [...], gemini: [...] }
40
- */
41
- export declare function getLatestModels(): Record<Provider, ModelDefinition[]>;