@revealui/ai 0.6.3 → 0.7.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/README.md +5 -4
- package/dist/a2a/card.d.ts +9 -0
- package/dist/a2a/card.d.ts.map +1 -1
- package/dist/a2a/card.js +11 -2
- package/dist/embeddings/index.d.ts +8 -0
- package/dist/embeddings/index.d.ts.map +1 -1
- package/dist/embeddings/index.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/llm/cache-utils.d.ts +11 -25
- package/dist/llm/cache-utils.d.ts.map +1 -1
- package/dist/llm/cache-utils.js +27 -27
- package/dist/llm/client.d.ts +28 -8
- package/dist/llm/client.d.ts.map +1 -1
- package/dist/llm/client.js +92 -13
- package/dist/llm/providers/anthropic.d.ts +30 -0
- package/dist/llm/providers/anthropic.d.ts.map +1 -0
- package/dist/llm/providers/anthropic.js +45 -0
- package/dist/llm/providers/base.d.ts +80 -27
- package/dist/llm/providers/base.d.ts.map +1 -1
- package/dist/llm/providers/base.js +5 -1
- package/dist/llm/providers/groq.d.ts +2 -1
- package/dist/llm/providers/groq.d.ts.map +1 -1
- package/dist/llm/providers/groq.js +14 -0
- package/dist/llm/providers/inference-snaps.d.ts +2 -1
- package/dist/llm/providers/inference-snaps.d.ts.map +1 -1
- package/dist/llm/providers/inference-snaps.js +15 -0
- package/dist/llm/providers/ollama.d.ts +2 -1
- package/dist/llm/providers/ollama.d.ts.map +1 -1
- package/dist/llm/providers/ollama.js +14 -0
- package/dist/llm/providers/openai-compat.d.ts +18 -1
- package/dist/llm/providers/openai-compat.d.ts.map +1 -1
- package/dist/llm/providers/openai-compat.js +50 -3
- package/dist/llm/providers/openai.d.ts +27 -0
- package/dist/llm/providers/openai.d.ts.map +1 -0
- package/dist/llm/providers/openai.js +41 -0
- package/dist/llm/resolve.d.ts +97 -0
- package/dist/llm/resolve.d.ts.map +1 -0
- package/dist/llm/resolve.js +218 -0
- package/dist/llm/server.d.ts +1 -0
- package/dist/llm/server.d.ts.map +1 -1
- package/dist/llm/server.js +2 -0
- package/dist/llm/token-counter.d.ts +18 -0
- package/dist/llm/token-counter.d.ts.map +1 -1
- package/dist/llm/token-counter.js +16 -13
- package/dist/orchestration/runtime.d.ts +6 -12
- package/dist/orchestration/runtime.d.ts.map +1 -1
- package/dist/orchestration/runtime.js +4 -16
- package/dist/orchestration/streaming-runtime.js +1 -1
- package/dist/skills/types.d.ts +6 -6
- package/package.json +7 -7
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request LLM client resolver (GAP-360 PR-2).
|
|
3
|
+
*
|
|
4
|
+
* The single home for key resolution at every dispatch site (spec §5.2 / §5.4).
|
|
5
|
+
* One resolver, consumed by all sites — no site-local copies.
|
|
6
|
+
*
|
|
7
|
+
* Resolution order (spec §5.2):
|
|
8
|
+
* 1. Per-user BYOK — createLLMClientForUser (preferred)
|
|
9
|
+
* 2. Site inference config — workspace_inference_configs (hostedViable on hosted)
|
|
10
|
+
* 3. Deployment env — createLLMClientFromEnv (SELF-HOSTED ONLY)
|
|
11
|
+
* 4. Hosted + nothing above → throw LLMNotConfiguredError (typed → HTTP 409)
|
|
12
|
+
*
|
|
13
|
+
* Security invariants (spec §6, guardrail-2):
|
|
14
|
+
* - §6.1 userId is authenticated-identity-scoped; the caller derives it from
|
|
15
|
+
* session/entitlement context — or, for the durable worker, the
|
|
16
|
+
* authenticated dispatcher captured server-side at enqueue time — never
|
|
17
|
+
* from request params/body, and never from a client-writable DB column
|
|
18
|
+
* (e.g. a ticket's `reporterId`, which has no ownership check on the
|
|
19
|
+
* general tickets API). The resolver takes userId as an argument and
|
|
20
|
+
* never reads it from a request. The same rule binds the step-2 site
|
|
21
|
+
* inference key: the workspaceId is client-writable, so its stored key is
|
|
22
|
+
* decrypted only after userCanAccessSite confirms the caller owns or
|
|
23
|
+
* collaborates on that site. Otherwise a request could name another
|
|
24
|
+
* tenant's site id and run on that site's key.
|
|
25
|
+
* - §6.2 plaintext lifetime = request scope. The client is constructed per
|
|
26
|
+
* request; no key cache. Nothing here logs, serializes, or returns a key.
|
|
27
|
+
* - §6.3 decryption is server-side only via the existing decryptApiKey.
|
|
28
|
+
* - §6.4 the byok:key:accessed audit event fires inside createLLMClientForUser
|
|
29
|
+
* when an audit store is wired (ctx.auditStore).
|
|
30
|
+
* - §6.5 fail-closed: unknown provider / failed decrypt / a non-hostedViable
|
|
31
|
+
* provider on hosted resolves to LLMNotConfiguredError, never an env
|
|
32
|
+
* fallthrough on hosted (the exact silent-localhost defect class).
|
|
33
|
+
* - §6.6 no new secret surface.
|
|
34
|
+
*
|
|
35
|
+
* Feature flag (spec §7): HOSTED_BYOK_DISPATCH. Default ON for hosted, absent
|
|
36
|
+
* (off) for self-hosted so self-hosted env-first behavior is byte-unchanged.
|
|
37
|
+
* The flag is the one-release rollback lever.
|
|
38
|
+
*/
|
|
39
|
+
import type { Database } from '@revealui/db/client';
|
|
40
|
+
import type { AuditStore } from '../audit/store.js';
|
|
41
|
+
import { LLMClient } from './client.js';
|
|
42
|
+
/**
|
|
43
|
+
* Thrown when a hosted deployment has no usable LLM configuration for the
|
|
44
|
+
* request. Maps to HTTP 409 (configuration is the remedy, not payment).
|
|
45
|
+
* Callers name {@link settingsPath} in the machine-readable response body.
|
|
46
|
+
*/
|
|
47
|
+
export declare class LLMNotConfiguredError extends Error {
|
|
48
|
+
/** Stable machine-readable code for API response bodies. */
|
|
49
|
+
readonly code: "LLM_NOT_CONFIGURED";
|
|
50
|
+
/** Where the account owner configures a key. */
|
|
51
|
+
readonly settingsPath: "/settings/api-keys";
|
|
52
|
+
constructor(message?: string);
|
|
53
|
+
}
|
|
54
|
+
/** The 409 response body every dispatch site returns for an unconfigured account. */
|
|
55
|
+
export interface LLMNotConfiguredBody {
|
|
56
|
+
success: false;
|
|
57
|
+
error: string;
|
|
58
|
+
code: 'LLM_NOT_CONFIGURED';
|
|
59
|
+
settingsPath: '/settings/api-keys';
|
|
60
|
+
}
|
|
61
|
+
/** Build the machine-readable 409 body for {@link LLMNotConfiguredError}. */
|
|
62
|
+
export declare function llmNotConfiguredBody(err: LLMNotConfiguredError): LLMNotConfiguredBody;
|
|
63
|
+
export interface ResolveLLMContext {
|
|
64
|
+
/**
|
|
65
|
+
* True on the hosted revealui.com SaaS deployment. Derived by the caller from
|
|
66
|
+
* the existing deployment-mode signal (server: detectDeploymentMode; admin:
|
|
67
|
+
* REVEALUI_LICENSE_PRIVATE_KEY presence) — never sniffed here.
|
|
68
|
+
*/
|
|
69
|
+
isHosted: boolean;
|
|
70
|
+
/** Site id for step-2 site-level config lookup. Omit when the site has none. */
|
|
71
|
+
workspaceId?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Durable audit sink for the byok:key:accessed event (§6.4). Only `append` is
|
|
74
|
+
* used, so a persistent store (DrizzleAuditStore) fits. Omit where none is
|
|
75
|
+
* wired (e.g. the admin process, in-memory until GAP-338 closes).
|
|
76
|
+
*/
|
|
77
|
+
auditStore?: Pick<AuditStore, 'append'>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Whether the BYOK dispatch order (spec §5.2) is active. Default follows the
|
|
81
|
+
* deployment: ON when hosted, OFF when self-hosted. HOSTED_BYOK_DISPATCH
|
|
82
|
+
* overrides explicitly; an unrecognized value falls back to the default.
|
|
83
|
+
*/
|
|
84
|
+
export declare function hostedByokDispatchEnabled(isHosted: boolean): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Resolve the LLM client for a single request.
|
|
87
|
+
*
|
|
88
|
+
* @param userId - Authenticated user id, from session/entitlement context for
|
|
89
|
+
* request-scoped callers, or the authenticated dispatcher captured
|
|
90
|
+
* server-side at enqueue time for the durable worker. Never a request
|
|
91
|
+
* param/body value, and never a client-writable DB column. Null when there
|
|
92
|
+
* is no authenticated user.
|
|
93
|
+
* @param db - Drizzle client.
|
|
94
|
+
* @param ctx - Deployment mode, optional site id, optional audit sink.
|
|
95
|
+
*/
|
|
96
|
+
export declare function resolveLLMClientForRequest(userId: string | null, db: Database, ctx: ResolveLLMContext): Promise<LLMClient>;
|
|
97
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/llm/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAIL,SAAS,EAEV,MAAM,aAAa,CAAC;AAMrB;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAG,oBAAoB,CAAU;IAC9C,gDAAgD;IAChD,QAAQ,CAAC,YAAY,EAAG,oBAAoB,CAAU;gBAE1C,OAAO,SAAoD;CAIxE;AAED,qFAAqF;AACrF,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,oBAAoB,CAAC;IAC3B,YAAY,EAAE,oBAAoB,CAAC;CACpC;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,qBAAqB,GAAG,oBAAoB,CAOrF;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;CACzC;AAKD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAOpE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,SAAS,CAAC,CAsDpB"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request LLM client resolver (GAP-360 PR-2).
|
|
3
|
+
*
|
|
4
|
+
* The single home for key resolution at every dispatch site (spec §5.2 / §5.4).
|
|
5
|
+
* One resolver, consumed by all sites — no site-local copies.
|
|
6
|
+
*
|
|
7
|
+
* Resolution order (spec §5.2):
|
|
8
|
+
* 1. Per-user BYOK — createLLMClientForUser (preferred)
|
|
9
|
+
* 2. Site inference config — workspace_inference_configs (hostedViable on hosted)
|
|
10
|
+
* 3. Deployment env — createLLMClientFromEnv (SELF-HOSTED ONLY)
|
|
11
|
+
* 4. Hosted + nothing above → throw LLMNotConfiguredError (typed → HTTP 409)
|
|
12
|
+
*
|
|
13
|
+
* Security invariants (spec §6, guardrail-2):
|
|
14
|
+
* - §6.1 userId is authenticated-identity-scoped; the caller derives it from
|
|
15
|
+
* session/entitlement context — or, for the durable worker, the
|
|
16
|
+
* authenticated dispatcher captured server-side at enqueue time — never
|
|
17
|
+
* from request params/body, and never from a client-writable DB column
|
|
18
|
+
* (e.g. a ticket's `reporterId`, which has no ownership check on the
|
|
19
|
+
* general tickets API). The resolver takes userId as an argument and
|
|
20
|
+
* never reads it from a request. The same rule binds the step-2 site
|
|
21
|
+
* inference key: the workspaceId is client-writable, so its stored key is
|
|
22
|
+
* decrypted only after userCanAccessSite confirms the caller owns or
|
|
23
|
+
* collaborates on that site. Otherwise a request could name another
|
|
24
|
+
* tenant's site id and run on that site's key.
|
|
25
|
+
* - §6.2 plaintext lifetime = request scope. The client is constructed per
|
|
26
|
+
* request; no key cache. Nothing here logs, serializes, or returns a key.
|
|
27
|
+
* - §6.3 decryption is server-side only via the existing decryptApiKey.
|
|
28
|
+
* - §6.4 the byok:key:accessed audit event fires inside createLLMClientForUser
|
|
29
|
+
* when an audit store is wired (ctx.auditStore).
|
|
30
|
+
* - §6.5 fail-closed: unknown provider / failed decrypt / a non-hostedViable
|
|
31
|
+
* provider on hosted resolves to LLMNotConfiguredError, never an env
|
|
32
|
+
* fallthrough on hosted (the exact silent-localhost defect class).
|
|
33
|
+
* - §6.6 no new secret surface.
|
|
34
|
+
*
|
|
35
|
+
* Feature flag (spec §7): HOSTED_BYOK_DISPATCH. Default ON for hosted, absent
|
|
36
|
+
* (off) for self-hosted so self-hosted env-first behavior is byte-unchanged.
|
|
37
|
+
* The flag is the one-release rollback lever.
|
|
38
|
+
*/
|
|
39
|
+
import { createLogger } from '@revealui/core/observability/logger';
|
|
40
|
+
import { decryptApiKey } from '@revealui/db/crypto';
|
|
41
|
+
import { siteCollaborators, sites, workspaceInferenceConfigs } from '@revealui/db/schema';
|
|
42
|
+
import { and, eq } from 'drizzle-orm';
|
|
43
|
+
import { createLLMClientForUser, createLLMClientFromEnv, isHostedViable, LLMClient, } from './client.js';
|
|
44
|
+
const resolverLogger = createLogger({ component: 'resolveLLMClientForRequest' });
|
|
45
|
+
/** Emitted once per process when the hosted BYOK rollback lever is pulled. */
|
|
46
|
+
let warnedBreakGlass = false;
|
|
47
|
+
/**
|
|
48
|
+
* Thrown when a hosted deployment has no usable LLM configuration for the
|
|
49
|
+
* request. Maps to HTTP 409 (configuration is the remedy, not payment).
|
|
50
|
+
* Callers name {@link settingsPath} in the machine-readable response body.
|
|
51
|
+
*/
|
|
52
|
+
export class LLMNotConfiguredError extends Error {
|
|
53
|
+
/** Stable machine-readable code for API response bodies. */
|
|
54
|
+
code = 'LLM_NOT_CONFIGURED';
|
|
55
|
+
/** Where the account owner configures a key. */
|
|
56
|
+
settingsPath = '/settings/api-keys';
|
|
57
|
+
constructor(message = 'No LLM provider is configured for this account.') {
|
|
58
|
+
super(message);
|
|
59
|
+
this.name = 'LLMNotConfiguredError';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Build the machine-readable 409 body for {@link LLMNotConfiguredError}. */
|
|
63
|
+
export function llmNotConfiguredBody(err) {
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
error: err.message,
|
|
67
|
+
code: err.code,
|
|
68
|
+
settingsPath: err.settingsPath,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const FLAG_ON = new Set(['true', '1', 'on', 'yes']);
|
|
72
|
+
const FLAG_OFF = new Set(['false', '0', 'off', 'no']);
|
|
73
|
+
/**
|
|
74
|
+
* Whether the BYOK dispatch order (spec §5.2) is active. Default follows the
|
|
75
|
+
* deployment: ON when hosted, OFF when self-hosted. HOSTED_BYOK_DISPATCH
|
|
76
|
+
* overrides explicitly; an unrecognized value falls back to the default.
|
|
77
|
+
*/
|
|
78
|
+
export function hostedByokDispatchEnabled(isHosted) {
|
|
79
|
+
const raw = process.env.HOSTED_BYOK_DISPATCH;
|
|
80
|
+
if (raw === undefined || raw.trim() === '')
|
|
81
|
+
return isHosted;
|
|
82
|
+
const value = raw.trim().toLowerCase();
|
|
83
|
+
if (FLAG_OFF.has(value))
|
|
84
|
+
return false;
|
|
85
|
+
if (FLAG_ON.has(value))
|
|
86
|
+
return true;
|
|
87
|
+
return isHosted;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Resolve the LLM client for a single request.
|
|
91
|
+
*
|
|
92
|
+
* @param userId - Authenticated user id, from session/entitlement context for
|
|
93
|
+
* request-scoped callers, or the authenticated dispatcher captured
|
|
94
|
+
* server-side at enqueue time for the durable worker. Never a request
|
|
95
|
+
* param/body value, and never a client-writable DB column. Null when there
|
|
96
|
+
* is no authenticated user.
|
|
97
|
+
* @param db - Drizzle client.
|
|
98
|
+
* @param ctx - Deployment mode, optional site id, optional audit sink.
|
|
99
|
+
*/
|
|
100
|
+
export async function resolveLLMClientForRequest(userId, db, ctx) {
|
|
101
|
+
const hosted = ctx.isHosted;
|
|
102
|
+
// Feature-flag gate. When disabled (self-hosted default), behavior is
|
|
103
|
+
// byte-unchanged: env-first, exactly as before this PR.
|
|
104
|
+
if (!hostedByokDispatchEnabled(hosted)) {
|
|
105
|
+
if (hosted && !warnedBreakGlass) {
|
|
106
|
+
warnedBreakGlass = true;
|
|
107
|
+
// Break-glass: HOSTED_BYOK_DISPATCH is explicitly off on a hosted
|
|
108
|
+
// deployment. Every account now shares the deployment env client while
|
|
109
|
+
// this lever is pulled — a deliberate one-release rollback, but an
|
|
110
|
+
// operator must know it is active.
|
|
111
|
+
resolverLogger.warn('HOSTED_BYOK_DISPATCH is disabled on a hosted deployment — all accounts are ' +
|
|
112
|
+
'sharing the deployment env LLM client instead of per-account BYOK keys.');
|
|
113
|
+
}
|
|
114
|
+
return createLLMClientFromEnv();
|
|
115
|
+
}
|
|
116
|
+
// 1. Per-user BYOK (preferred). On hosted, filter to hostedViable providers
|
|
117
|
+
// so a localhost-only BYOK key (e.g. ollama) can never yield a localhost
|
|
118
|
+
// client — that is the silent-localhost defect (§6.5, fail-closed).
|
|
119
|
+
if (userId) {
|
|
120
|
+
try {
|
|
121
|
+
const byok = await createLLMClientForUser(userId, db, ctx.auditStore, {
|
|
122
|
+
hostedViableOnly: hosted,
|
|
123
|
+
});
|
|
124
|
+
if (byok)
|
|
125
|
+
return byok;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Failed decrypt / unknown-provider row / CHECK-violating row. Fail-closed
|
|
129
|
+
// on hosted — never fall through to env. Self-hosted may continue.
|
|
130
|
+
if (hosted) {
|
|
131
|
+
throw new LLMNotConfiguredError('Your stored API key could not be used. Re-add it under /settings/api-keys.');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// 2. Site-level inference config. userId is passed so the site's stored key
|
|
136
|
+
// is decrypted only for a caller authorized on that site (§6.1) — the
|
|
137
|
+
// workspaceId reaching here is a client-writable value (e.g. a request
|
|
138
|
+
// body field), so it carries no ownership guarantee on its own.
|
|
139
|
+
const siteClient = await resolveSiteInferenceClient(db, userId, ctx.workspaceId, hosted);
|
|
140
|
+
if (siteClient)
|
|
141
|
+
return siteClient;
|
|
142
|
+
// 3. Deployment env — SELF-HOSTED ONLY. Forbidden on hosted (§5.2 step 3).
|
|
143
|
+
if (!hosted) {
|
|
144
|
+
return createLLMClientFromEnv();
|
|
145
|
+
}
|
|
146
|
+
// 4. Hosted + nothing above → fail loud, actionable.
|
|
147
|
+
throw new LLMNotConfiguredError();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Whether `userId` is authorized to act on `siteId` — the site's owner, or a
|
|
151
|
+
* row in `site_collaborators`. Gate for the site inference key (§6.1): the
|
|
152
|
+
* site's stored provider key must never be decrypted for a caller who does not
|
|
153
|
+
* belong to the site, even though the workspaceId is client-supplied.
|
|
154
|
+
*/
|
|
155
|
+
async function userCanAccessSite(db, userId, siteId) {
|
|
156
|
+
const [owned] = await db
|
|
157
|
+
.select({ id: sites.id })
|
|
158
|
+
.from(sites)
|
|
159
|
+
.where(and(eq(sites.id, siteId), eq(sites.ownerId, userId)))
|
|
160
|
+
.limit(1);
|
|
161
|
+
if (owned)
|
|
162
|
+
return true;
|
|
163
|
+
const [collaborator] = await db
|
|
164
|
+
.select({ id: siteCollaborators.id })
|
|
165
|
+
.from(siteCollaborators)
|
|
166
|
+
.where(and(eq(siteCollaborators.siteId, siteId), eq(siteCollaborators.userId, userId)))
|
|
167
|
+
.limit(1);
|
|
168
|
+
return Boolean(collaborator);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Build a client from the site's workspace_inference_configs row (spec §5.2
|
|
172
|
+
* step 2). Returns null when the site has no config, when the caller is not
|
|
173
|
+
* authorized on the site, or (on hosted) when its provider is not hostedViable.
|
|
174
|
+
* Fail-closed: a malformed row throws on hosted and is skipped on self-hosted.
|
|
175
|
+
*/
|
|
176
|
+
async function resolveSiteInferenceClient(db, userId, workspaceId, hosted) {
|
|
177
|
+
if (!workspaceId)
|
|
178
|
+
return null;
|
|
179
|
+
// §6.1 authorization: only decrypt a site's key for a caller who belongs to
|
|
180
|
+
// that site. An unauthorized (or anonymous) request skips the site config
|
|
181
|
+
// entirely; on hosted it then falls through to the step-4 409, never a
|
|
182
|
+
// decrypt of another tenant's key.
|
|
183
|
+
if (!(userId && (await userCanAccessSite(db, userId, workspaceId))))
|
|
184
|
+
return null;
|
|
185
|
+
const [config] = await db
|
|
186
|
+
.select()
|
|
187
|
+
.from(workspaceInferenceConfigs)
|
|
188
|
+
.where(eq(workspaceInferenceConfigs.workspaceId, workspaceId))
|
|
189
|
+
.limit(1);
|
|
190
|
+
if (!config)
|
|
191
|
+
return null;
|
|
192
|
+
const provider = config.provider;
|
|
193
|
+
// On hosted, only hostedViable providers are reachable. A non-viable site
|
|
194
|
+
// config is skipped so resolution fails closed rather than hitting localhost.
|
|
195
|
+
if (hosted && !isHostedViable(provider))
|
|
196
|
+
return null;
|
|
197
|
+
try {
|
|
198
|
+
// Keyless providers (ollama / inference-snaps) carry a NULL encrypted key
|
|
199
|
+
// and use the provider name as the placeholder key — matches the env
|
|
200
|
+
// factory. Keyed providers decrypt server-side at dispatch time (§6.3).
|
|
201
|
+
const apiKey = config.encryptedApiKey ? decryptApiKey(config.encryptedApiKey) : provider;
|
|
202
|
+
return new LLMClient({
|
|
203
|
+
provider,
|
|
204
|
+
apiKey,
|
|
205
|
+
model: config.model ?? undefined,
|
|
206
|
+
baseURL: config.baseURL ?? undefined,
|
|
207
|
+
temperature: config.temperature ?? undefined,
|
|
208
|
+
maxTokens: config.maxTokens ?? undefined,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// Unknown provider / failed decrypt. Fail-closed on hosted; skip on self-hosted.
|
|
213
|
+
if (hosted) {
|
|
214
|
+
throw new LLMNotConfiguredError('This site’s inference configuration could not be used. Update it under /settings/api-keys.');
|
|
215
|
+
}
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
package/dist/llm/server.d.ts
CHANGED
|
@@ -10,5 +10,6 @@ export * from './providers/groq.js';
|
|
|
10
10
|
export * from './providers/inference-snaps.js';
|
|
11
11
|
export * from './providers/ollama.js';
|
|
12
12
|
export * from './providers/openai-compat.js';
|
|
13
|
+
export * from './resolve.js';
|
|
13
14
|
export * from './workspace-provider-config.js';
|
|
14
15
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/llm/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/llm/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/llm/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,aAAa,CAAC;AAE5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAE7C,cAAc,cAAc,CAAC;AAI7B,cAAc,gCAAgC,CAAC"}
|
package/dist/llm/server.js
CHANGED
|
@@ -12,6 +12,8 @@ export * from './providers/groq.js';
|
|
|
12
12
|
export * from './providers/inference-snaps.js';
|
|
13
13
|
export * from './providers/ollama.js';
|
|
14
14
|
export * from './providers/openai-compat.js';
|
|
15
|
+
// Export the per-request client resolver (GAP-360 PR-2)
|
|
16
|
+
export * from './resolve.js';
|
|
15
17
|
// Export per-workspace provider registry (used by admin inference-config route
|
|
16
18
|
// to hydrate per-site config at boot + apply changes immediately on PUT)
|
|
17
19
|
export * from './workspace-provider-config.js';
|
|
@@ -19,6 +19,24 @@ export interface CostEstimate {
|
|
|
19
19
|
model: string;
|
|
20
20
|
direction: 'input' | 'output';
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Per-1M-token pricing (USD). Single source of truth for every cost path in the package:
|
|
24
|
+
* `estimateCost` (input/output) and `calculateCacheCost` (cache-utils, cacheWrite/cacheRead).
|
|
25
|
+
* Cache rates follow Anthropic's model (write ~125% of input, read ~10%); non-caching
|
|
26
|
+
* providers carry 0 (local models are free; cache cost is not modelled for hosted
|
|
27
|
+
* non-Anthropic providers here).
|
|
28
|
+
*/
|
|
29
|
+
export interface ModelPricing {
|
|
30
|
+
/** USD per 1M input tokens. */
|
|
31
|
+
input: number;
|
|
32
|
+
/** USD per 1M output tokens. */
|
|
33
|
+
output: number;
|
|
34
|
+
/** USD per 1M tokens written to the prompt cache (0 where unsupported/unmodelled). */
|
|
35
|
+
cacheWrite: number;
|
|
36
|
+
/** USD per 1M tokens read from the prompt cache (0 where unsupported/unmodelled). */
|
|
37
|
+
cacheRead: number;
|
|
38
|
+
}
|
|
39
|
+
export declare const MODEL_PRICING: Record<string, ModelPricing>;
|
|
22
40
|
/**
|
|
23
41
|
* Estimate token count for a string.
|
|
24
42
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-counter.d.ts","sourceRoot":"","sources":["../../src/llm/token-counter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC/B;
|
|
1
|
+
{"version":3,"file":"token-counter.d.ts","sourceRoot":"","sources":["../../src/llm/token-counter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,UAAU,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAmBtD,CAAC;AAeF;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAGxF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAQjG;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,OAAO,GAAG,QAAQ,GAC5B,YAAY,CASd;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,MAAM,GACZ;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAI9C"}
|
|
@@ -8,22 +8,25 @@
|
|
|
8
8
|
* Limitation: actual token counts differ by model tokenizer. This is
|
|
9
9
|
* accurate enough for budget tracking and context window management.
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
'claude-
|
|
15
|
-
'claude-
|
|
16
|
-
|
|
11
|
+
export const MODEL_PRICING = {
|
|
12
|
+
// Anthropic (current)
|
|
13
|
+
'claude-opus-4-6': { input: 15.0, output: 75.0, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
14
|
+
'claude-sonnet-4-6': { input: 3.0, output: 15.0, cacheWrite: 3.75, cacheRead: 0.3 },
|
|
15
|
+
'claude-haiku-4-5-20251001': { input: 0.25, output: 1.25, cacheWrite: 0.3125, cacheRead: 0.025 },
|
|
16
|
+
// Anthropic (legacy 2024 - retained for cache-cost callers/examples)
|
|
17
|
+
'claude-3-5-sonnet-20241022': { input: 3.0, output: 15.0, cacheWrite: 3.75, cacheRead: 0.3 },
|
|
18
|
+
'claude-3-5-haiku-20241022': { input: 1.0, output: 5.0, cacheWrite: 1.25, cacheRead: 0.1 },
|
|
19
|
+
'claude-3-opus-20240229': { input: 15.0, output: 75.0, cacheWrite: 18.75, cacheRead: 1.5 },
|
|
17
20
|
// OpenAI
|
|
18
|
-
'gpt-4o': { input: 5.0, output: 15.0 },
|
|
19
|
-
'gpt-4o-mini': { input: 0.15, output: 0.6 },
|
|
21
|
+
'gpt-4o': { input: 5.0, output: 15.0, cacheWrite: 0, cacheRead: 0 },
|
|
22
|
+
'gpt-4o-mini': { input: 0.15, output: 0.6, cacheWrite: 0, cacheRead: 0 },
|
|
20
23
|
// Groq (Qwen - Apache 2.0)
|
|
21
|
-
'qwen/qwen3-32b': { input: 0.59, output: 0.79 },
|
|
24
|
+
'qwen/qwen3-32b': { input: 0.59, output: 0.79, cacheWrite: 0, cacheRead: 0 },
|
|
22
25
|
// Ollama (self-hosted - no cost)
|
|
23
|
-
'gemma4:e2b': { input: 0, output: 0 },
|
|
24
|
-
'gemma4:e4b': { input: 0, output: 0 },
|
|
25
|
-
'gemma4:26b': { input: 0, output: 0 },
|
|
26
|
-
'nomic-embed-text': { input: 0, output: 0 },
|
|
26
|
+
'gemma4:e2b': { input: 0, output: 0, cacheWrite: 0, cacheRead: 0 },
|
|
27
|
+
'gemma4:e4b': { input: 0, output: 0, cacheWrite: 0, cacheRead: 0 },
|
|
28
|
+
'gemma4:26b': { input: 0, output: 0, cacheWrite: 0, cacheRead: 0 },
|
|
29
|
+
'nomic-embed-text': { input: 0, output: 0, cacheWrite: 0, cacheRead: 0 },
|
|
27
30
|
};
|
|
28
31
|
function charsPerToken(model) {
|
|
29
32
|
const lower = model.toLowerCase();
|
|
@@ -4,24 +4,18 @@
|
|
|
4
4
|
* Executes agent tasks with tool execution, memory management, and error handling
|
|
5
5
|
*/
|
|
6
6
|
import type { LLMClient } from '../llm/client.js';
|
|
7
|
+
import type { ReasoningEffort } from '../llm/providers/base.js';
|
|
7
8
|
import type { AgentSkillProvider } from '../skills/integration/agent-skill-provider.js';
|
|
8
9
|
import type { ApprovalCallback } from '../tools/base.js';
|
|
9
10
|
import type { MCPToolSource, McpClientLike } from '../tools/mcp-adapter.js';
|
|
10
11
|
import type { Agent, AgentResult, Task } from './agent.js';
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* |---------|-----------------|-----------------------------------|
|
|
17
|
-
* | off | 0 | Disabled (default) |
|
|
18
|
-
* | minimal | 512 | Simple tasks, cost-sensitive |
|
|
19
|
-
* | low | 2 048 | Moderate complexity |
|
|
20
|
-
* | medium | 8 000 | Multi-step reasoning |
|
|
21
|
-
* | high | 16 000 | Complex planning |
|
|
22
|
-
* | xhigh | 31 999 | Maximum depth (expensive) |
|
|
13
|
+
* Reasoning-depth hint for a task. Alias of the neutral `ReasoningEffort` — the agnostic
|
|
14
|
+
* Reasoner port's control vocabulary. Mapping a level to a provider's native control
|
|
15
|
+
* (e.g. a thinking-token budget) is the adapter's job; a provider that advertises
|
|
16
|
+
* `reasoningEffort: false` treats it as a no-op.
|
|
23
17
|
*/
|
|
24
|
-
export type ThinkingLevel =
|
|
18
|
+
export type ThinkingLevel = ReasoningEffort;
|
|
25
19
|
export interface RuntimeConfig {
|
|
26
20
|
maxIterations?: number;
|
|
27
21
|
timeout?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/orchestration/runtime.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/orchestration/runtime.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAW,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AAE3E,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG5E,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,eAAe,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IACpE;;;;OAIG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,gCAAgC,EAAE,SAAS,CAAC;IAC/D;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC;AAED,qBAAa,YAAY;IACvB,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC;IAChC,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,cAAc,CAAgD;IACtE,OAAO,CAAC,cAAc,CAAS;gBAEnB,MAAM,GAAE,aAAkB;IA0BtC;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;YAqBzE,OAAO;IA8OrB;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAI7B;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAc9E;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA+B9B;;OAEG;IACH,SAAS,IAAI;QACX,cAAc,EAAE,OAAO,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,MAAM,CAAC;KACxB;CAOF"}
|
|
@@ -9,14 +9,6 @@ import { estimateCost } from '../llm/token-counter.js';
|
|
|
9
9
|
import { ToolCallDeduplicator } from '../tools/deduplicator.js';
|
|
10
10
|
import { createToolsFromMcpClient, discoverMCPTools } from '../tools/mcp-adapter.js';
|
|
11
11
|
import { createWebSearchTool } from '../tools/web/duck-duck-go.js';
|
|
12
|
-
const THINKING_BUDGETS = {
|
|
13
|
-
off: 0,
|
|
14
|
-
minimal: 512,
|
|
15
|
-
low: 2048,
|
|
16
|
-
medium: 8000,
|
|
17
|
-
high: 16000,
|
|
18
|
-
xhigh: 31999,
|
|
19
|
-
};
|
|
20
12
|
export class AgentRuntime {
|
|
21
13
|
config;
|
|
22
14
|
taskQueue = [];
|
|
@@ -101,8 +93,8 @@ export class AgentRuntime {
|
|
|
101
93
|
{
|
|
102
94
|
role: 'system',
|
|
103
95
|
content: agent.instructions,
|
|
104
|
-
// Cache agent instructions for cost savings (
|
|
105
|
-
|
|
96
|
+
// Cache agent instructions for cost savings (effective where promptCache is supported)
|
|
97
|
+
cache: this.config.enableCache || undefined,
|
|
106
98
|
},
|
|
107
99
|
{
|
|
108
100
|
role: 'user',
|
|
@@ -130,10 +122,6 @@ export class AgentRuntime {
|
|
|
130
122
|
},
|
|
131
123
|
};
|
|
132
124
|
}
|
|
133
|
-
// Resolve thinking budget if a level is configured
|
|
134
|
-
const thinkingBudget = this.config.thinkingLevel && this.config.thinkingLevel !== 'off'
|
|
135
|
-
? THINKING_BUDGETS[this.config.thinkingLevel]
|
|
136
|
-
: undefined;
|
|
137
125
|
// Get LLM response (with caching for agent instructions and tools)
|
|
138
126
|
const response = await llmClient.chat(messages, {
|
|
139
127
|
tools: allTools.map((tool) => ({
|
|
@@ -144,8 +132,8 @@ export class AgentRuntime {
|
|
|
144
132
|
parameters: z.toJSONSchema(tool.parameters),
|
|
145
133
|
},
|
|
146
134
|
})),
|
|
147
|
-
|
|
148
|
-
|
|
135
|
+
cacheHint: this.config.enableCache,
|
|
136
|
+
effort: this.config.thinkingLevel,
|
|
149
137
|
});
|
|
150
138
|
// Accumulate token usage and cost
|
|
151
139
|
const iterationTokens = response.usage?.totalTokens ?? 0;
|
package/dist/skills/types.d.ts
CHANGED
|
@@ -27,13 +27,13 @@ export declare const SkillMetadataSchema: z.ZodObject<{
|
|
|
27
27
|
repository: z.ZodOptional<z.ZodString>;
|
|
28
28
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
29
29
|
compatibility: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
30
|
+
anthropic: "anthropic";
|
|
31
|
+
openai: "openai";
|
|
30
32
|
"claude-code": "claude-code";
|
|
31
33
|
cursor: "cursor";
|
|
32
34
|
windsurf: "windsurf";
|
|
33
35
|
cline: "cline";
|
|
34
36
|
copilot: "copilot";
|
|
35
|
-
openai: "openai";
|
|
36
|
-
anthropic: "anthropic";
|
|
37
37
|
universal: "universal";
|
|
38
38
|
}>>>;
|
|
39
39
|
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -78,13 +78,13 @@ export declare const SkillSchema: z.ZodObject<{
|
|
|
78
78
|
repository: z.ZodOptional<z.ZodString>;
|
|
79
79
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
80
80
|
compatibility: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
81
|
+
anthropic: "anthropic";
|
|
82
|
+
openai: "openai";
|
|
81
83
|
"claude-code": "claude-code";
|
|
82
84
|
cursor: "cursor";
|
|
83
85
|
windsurf: "windsurf";
|
|
84
86
|
cline: "cline";
|
|
85
87
|
copilot: "copilot";
|
|
86
|
-
openai: "openai";
|
|
87
|
-
anthropic: "anthropic";
|
|
88
88
|
universal: "universal";
|
|
89
89
|
}>>>;
|
|
90
90
|
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -143,13 +143,13 @@ export declare const SkillActivationResultSchema: z.ZodObject<{
|
|
|
143
143
|
repository: z.ZodOptional<z.ZodString>;
|
|
144
144
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
145
145
|
compatibility: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
146
|
+
anthropic: "anthropic";
|
|
147
|
+
openai: "openai";
|
|
146
148
|
"claude-code": "claude-code";
|
|
147
149
|
cursor: "cursor";
|
|
148
150
|
windsurf: "windsurf";
|
|
149
151
|
cline: "cline";
|
|
150
152
|
copilot: "copilot";
|
|
151
|
-
openai: "openai";
|
|
152
|
-
anthropic: "anthropic";
|
|
153
153
|
universal: "universal";
|
|
154
154
|
}>>>;
|
|
155
155
|
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revealui/ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "AI runtime for agent-driven products — agents, memory, LLM providers (Inference Snaps, Ollama, OpenAI-compatible), tools, and orchestration. Anthropic-SDK-free.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -25,20 +25,20 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"lru-cache": "^11.5.1",
|
|
27
27
|
"zod": "^4.4.3",
|
|
28
|
-
"@revealui/contracts": "0.
|
|
29
|
-
"@revealui/core": "0.
|
|
30
|
-
"@revealui/db": "0.
|
|
28
|
+
"@revealui/contracts": "0.7.0",
|
|
29
|
+
"@revealui/core": "0.11.1",
|
|
30
|
+
"@revealui/db": "0.8.0",
|
|
31
31
|
"@revealui/resilience": "0.2.4"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@electric-sql/pglite": "^0.5.
|
|
34
|
+
"@electric-sql/pglite": "^0.5.4",
|
|
35
35
|
"@testing-library/react": "^16.3.2",
|
|
36
|
-
"@vitest/coverage-v8": "^4.1.
|
|
36
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
37
37
|
"jsdom": "29.1.1",
|
|
38
38
|
"react": "^19.2.7",
|
|
39
39
|
"react-dom": "^19.2.7",
|
|
40
40
|
"typescript": "^6.0.3",
|
|
41
|
-
"vitest": "^4.1.
|
|
41
|
+
"vitest": "^4.1.10",
|
|
42
42
|
"@revealui/dev": "0.1.0"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|