@columenlabs/lumen-ai 0.1.224 → 0.1.226
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 +1 -1
- package/dist/agent/agent.d.ts +11 -1
- package/dist/agent/agent.js +29 -2
- package/dist/agent/stream.d.ts +3 -1
- package/dist/agent/stream.js +3 -1
- package/dist/assistant/engine.d.ts +5 -0
- package/dist/assistant/engine.js +8 -2
- package/dist/assistant/index.d.ts +1 -1
- package/dist/assistant/state.d.ts +30 -2
- package/dist/assistant/state.js +34 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ app.all('/api/assistant/*', (c) => routes(c.req.raw));
|
|
|
103
103
|
- **Hand off and advice.** The `escalate` tool hands one task to a higher tier (the person sets next, any or only when asked); Anthropic's advisor tool lets a higher tier send a plan, at most two an answer.
|
|
104
104
|
- **Chats** run on the agent (`./agent`, `LumenAgent`, below): the app routes `POST /chat` and each chat's reads, cards and Undo to its own agent, and `assistantRoutes` answers `POST /chat` with 410 `moved`. Chats saved by the old turn loop stay readable (`GET /chats`, `GET|DELETE /chats/:id`) until `assistant.purge()` drops them 30 days after their last message.
|
|
105
105
|
- **Screen moves**: while the person's Settings ▸ Screen is Move (the default), the panel sends its page map (`AssistantMessage.screen`: routes, nav pages, Settings sections, cards on screen, rows to open) and `LumenAgent` gives the model a `screen` tool (`./agent` `screen.ts`). Each call's moves (go, settings, chart, open, point) are checked against the map, kept in the chat and streamed as a `screen` event; the panel runs them through `AssistantScreenProvider` (mounted by `LumenShell`) with an Undo chip, and their outcomes go back with the next message (`outcomes`). Nothing is saved by a move.
|
|
106
|
-
- **Background work** an app runs for a person (a score, a summary) is `assistant.complete(caller, { task, system, prompt, images?, maxTokens })`: one answer on the task's tier (`tasks`, so the person picks its model in Settings ▸ Models), no chat and no tools (`images`, base64 with their media type, are read with the prompt: a scanned page, a screenshot), billed to their payer and counted in their spend and allowance like a chat turn. `maxTokens` (default 1,000) goes up to `COMPLETE_MAX_TOKENS` (32,000, thinking included); the answer is streamed, so a long one keeps its connection, and `cut: true` says it stopped at the cap before it ended (the app can ask again, shorter, or continue). It throws `AssistantError` `not_connected`, `app_cap` or `own_cap` when nobody can pay, so the caller waits and tries later. It returns the answer's `usd`, `model` and `usage` (tokens in, cache reads, out, per model). `effort` sets how hard the model thinks on that one call (`low` to `max`; on an OpenAI or xAI model it is the request's reasoning effort), over what the person saved for the tier. `run: { id, title }` makes the calls that share an `id` one line of the person's usage history (every round of one rebuild); without it a task's calls that day share a line.
|
|
106
|
+
- **Background work** an app runs for a person (a score, a summary) is `assistant.complete(caller, { task, system, prompt, images?, maxTokens })`: one answer on the task's tier (`tasks`, so the person picks its model in Settings ▸ Models), no chat and no tools (`images`, base64 with their media type, are read with the prompt: a scanned page, a screenshot), billed to their payer and counted in their spend and allowance like a chat turn. `maxTokens` (default 1,000) goes up to `COMPLETE_MAX_TOKENS` (32,000, thinking included); the answer is streamed, so a long one keeps its connection, and `cut: true` says it stopped at the cap before it ended (the app can ask again, shorter, or continue). It throws `AssistantError` `not_connected`, `app_cap` or `own_cap` when nobody can pay, so the caller waits and tries later. It returns the answer's `usd`, `model` and `usage` (tokens in, cache reads, out, per model). `effort` sets how hard the model thinks on that one call (`low` to `max`; on an OpenAI or xAI model it is the request's reasoning effort), over what the person saved for the tier. `run: { id, title }` makes the calls that share an `id` one line of the person's usage history (every round of one rebuild); without it a task's calls that day share a line. The month's spend also adds up per task and model (`spend:YYYY-MM` `tasks`: answers, calls, tokens, cost and time, a chat answer as `chat`), so an app's admin page can show what each kind of work costs; `tag` counts one call under another name when a task does more than one kind of work (a first try, a repair).
|
|
107
107
|
- **Usage history.** Each chat (`agentTurn` with `chat`) and each run of background work is one line of the person's month (`usage:YYYY-MM`, the newest 300): its title, first and last use, tokens, cost and its parts per tier and model. `GET /usage?month=YYYY-MM` returns it beside that month's spend and the months that have any; `LumenAssistant`'s footer shows this month's total and opens it (`UsageHistoryView`).
|
|
108
108
|
|
|
109
109
|
### Commands, `@` and `#`
|
package/dist/agent/agent.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* An `Assistant` gives both: `assistant.agentTurn(caller, input)` returns a plan and its settle.
|
|
13
13
|
*/
|
|
14
14
|
import { type ChatResponseResult, type PrepareStepContext, type Session, type StepConfig, type StepContext, Think, type ThinkModel, type TurnConfig, type TurnContext } from '@cloudflare/think';
|
|
15
|
-
import { type AssistantChat, type AssistantEffort, type AssistantEvent, type AssistantImage, type AssistantRefNote, type AssistantScreenMap, type AssistantScreenOutcome, type ChatUsage, type UsagePart } from '@columenlabs/lumen-ui-types/assistant';
|
|
15
|
+
import { type AssistantChat, type AssistantEffort, type AssistantEvent, type AssistantImage, type AssistantQuote, type AssistantRefNote, type AssistantScreenMap, type AssistantScreenOutcome, type ChatUsage, type UsagePart } from '@columenlabs/lumen-ui-types/assistant';
|
|
16
16
|
import { type ModelMessage, type ToolSet } from 'ai';
|
|
17
17
|
import type { ModelDef } from '../assistant/models.js';
|
|
18
18
|
import { type AgentConnector, type ConnectorAt } from './connectors.js';
|
|
@@ -134,6 +134,8 @@ export interface AskInput {
|
|
|
134
134
|
note?: unknown;
|
|
135
135
|
};
|
|
136
136
|
refs?: AssistantRefNote[];
|
|
137
|
+
/** The piece of the chat this message replies to (Reply on selected text). */
|
|
138
|
+
quote?: AssistantQuote;
|
|
137
139
|
tier?: string;
|
|
138
140
|
time_zone?: string;
|
|
139
141
|
/** What the browser can show (Screen on): the `screen` tool and its rules join the turn. */
|
|
@@ -141,6 +143,14 @@ export interface AskInput {
|
|
|
141
143
|
/** How earlier screen calls ended in the browser. */
|
|
142
144
|
outcomes?: AssistantScreenOutcome[];
|
|
143
145
|
}
|
|
146
|
+
/** A quote as sent, checked: its text cut to `ASSISTANT_QUOTE_MAX`, and whose message it came from. */
|
|
147
|
+
export declare function quoteOf(q: unknown): AssistantQuote | undefined;
|
|
148
|
+
/**
|
|
149
|
+
* The words the model reads before a message that replies to a quote: which message it came from
|
|
150
|
+
* and the quote itself. It is the message's first text part; the panel shows the quote from the
|
|
151
|
+
* message's metadata instead, so `itemsOf` leaves this part out.
|
|
152
|
+
*/
|
|
153
|
+
export declare function quoteLead(q: AssistantQuote): string;
|
|
144
154
|
/**
|
|
145
155
|
* The images a message may carry, as file parts: allowed types only, at most `ASSISTANT_IMAGES_MAX`,
|
|
146
156
|
* and no more than `ASSISTANT_IMAGE_CHARS` of base64 together; the rest are left out.
|
package/dist/agent/agent.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { anthropic } from '@ai-sdk/anthropic';
|
|
15
15
|
import { Think, } from '@cloudflare/think';
|
|
16
|
-
import { ASSISTANT_IMAGES_MAX, ASSISTANT_IMAGE_CHARS, ASSISTANT_IMAGE_TYPES, } from '@columenlabs/lumen-ui-types/assistant';
|
|
16
|
+
import { ASSISTANT_IMAGES_MAX, ASSISTANT_IMAGE_CHARS, ASSISTANT_IMAGE_TYPES, ASSISTANT_QUOTE_MAX, } from '@columenlabs/lumen-ui-types/assistant';
|
|
17
17
|
import { createCompactFunction } from 'agents/sessions';
|
|
18
18
|
import { generateText } from 'ai';
|
|
19
19
|
import { CONNECTOR_GROUP, checkConnectorUrl, connectorGroup, connectorId, connectorSource, } from './connectors.js';
|
|
@@ -73,6 +73,27 @@ export function withLead(messages, lead) {
|
|
|
73
73
|
: [{ type: 'text', text: lead }, ...m.content];
|
|
74
74
|
return [...messages.slice(0, i), { ...m, content }, ...messages.slice(i + 1)];
|
|
75
75
|
}
|
|
76
|
+
/** A quote as sent, checked: its text cut to `ASSISTANT_QUOTE_MAX`, and whose message it came from. */
|
|
77
|
+
export function quoteOf(q) {
|
|
78
|
+
const o = q;
|
|
79
|
+
const text = typeof o?.text === 'string' ? o.text.trim().slice(0, ASSISTANT_QUOTE_MAX) : '';
|
|
80
|
+
if (!text)
|
|
81
|
+
return undefined;
|
|
82
|
+
return { text, from: o?.from === 'user' ? 'user' : 'assistant' };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The words the model reads before a message that replies to a quote: which message it came from
|
|
86
|
+
* and the quote itself. It is the message's first text part; the panel shows the quote from the
|
|
87
|
+
* message's metadata instead, so `itemsOf` leaves this part out.
|
|
88
|
+
*/
|
|
89
|
+
export function quoteLead(q) {
|
|
90
|
+
const whose = q.from === 'user' ? 'their own earlier message' : 'your earlier answer';
|
|
91
|
+
const lines = q.text
|
|
92
|
+
.split('\n')
|
|
93
|
+
.map((l) => `> ${l}`)
|
|
94
|
+
.join('\n');
|
|
95
|
+
return `The person replies to this part of ${whose}:\n${lines}\n\n`;
|
|
96
|
+
}
|
|
76
97
|
/**
|
|
77
98
|
* The images a message may carry, as file parts: allowed types only, at most `ASSISTANT_IMAGES_MAX`,
|
|
78
99
|
* and no more than `ASSISTANT_IMAGE_CHARS` of base64 together; the rest are left out.
|
|
@@ -209,10 +230,12 @@ export class LumenAgent extends Think {
|
|
|
209
230
|
this.#put('at', at);
|
|
210
231
|
await sink.event({ event: 'chat', data: { id: this.name, title } });
|
|
211
232
|
this.#outcomes(screenOutcomesOf(input.outcomes));
|
|
233
|
+
const quote = quoteOf(input.quote);
|
|
212
234
|
const meta = {
|
|
213
235
|
at,
|
|
214
236
|
...(input.context ? { context: { label: input.context.label } } : {}),
|
|
215
237
|
...(input.refs?.length ? { refs: input.refs } : {}),
|
|
238
|
+
...(quote ? { quote } : {}),
|
|
216
239
|
...(input.tier ? { tier: input.tier } : {}),
|
|
217
240
|
};
|
|
218
241
|
const toEvents = chunkEvents({
|
|
@@ -237,7 +260,11 @@ export class LumenAgent extends Think {
|
|
|
237
260
|
await this.chat({
|
|
238
261
|
id: userId,
|
|
239
262
|
role: 'user',
|
|
240
|
-
parts: [
|
|
263
|
+
parts: [
|
|
264
|
+
...(quote ? [{ type: 'text', text: quoteLead(quote) }] : []),
|
|
265
|
+
{ type: 'text', text: input.message },
|
|
266
|
+
...imageParts(input.images),
|
|
267
|
+
],
|
|
241
268
|
metadata: meta,
|
|
242
269
|
}, {
|
|
243
270
|
onStart: () => undefined,
|
package/dist/agent/stream.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* panel's `AssistantEvent`s, and a stored chat's messages and cards as its `ChatItem`s. The panel
|
|
4
4
|
* (`@columenlabs/lumen-ui`'s `LumenAssistant`) reads a Think chat the same way as before.
|
|
5
5
|
*/
|
|
6
|
-
import type { AssistantEvent, AssistantRefNote, ChatItem } from '@columenlabs/lumen-ui-types/assistant';
|
|
6
|
+
import type { AssistantEvent, AssistantQuote, AssistantRefNote, ChatItem } from '@columenlabs/lumen-ui-types/assistant';
|
|
7
7
|
import type { AgentCard } from './agent.js';
|
|
8
8
|
import type { ScreenCall } from './screen.js';
|
|
9
9
|
/** A tool's name as a line's title: `notes__find_notes` → `find notes`. */
|
|
@@ -40,6 +40,8 @@ export interface AskMeta {
|
|
|
40
40
|
label: string;
|
|
41
41
|
};
|
|
42
42
|
refs?: AssistantRefNote[];
|
|
43
|
+
/** The piece of the chat the message replies to; its words to the model are the first text part. */
|
|
44
|
+
quote?: AssistantQuote;
|
|
43
45
|
tier?: string;
|
|
44
46
|
}
|
|
45
47
|
/** A stored chat as the panel's items: the messages in order, each tool call as it ended. */
|
package/dist/agent/stream.js
CHANGED
|
@@ -137,11 +137,12 @@ export function itemsOf(messages, cards, screens = new Map(), steers = {}) {
|
|
|
137
137
|
for (const m of messages) {
|
|
138
138
|
if (m.role === 'user') {
|
|
139
139
|
asked = m.id;
|
|
140
|
+
const meta = (obj(m.metadata) ?? {});
|
|
140
141
|
const text = m.parts
|
|
141
142
|
.filter((p) => p.type === 'text')
|
|
143
|
+
.slice(meta.quote ? 1 : 0)
|
|
142
144
|
.map((p) => String(p.text ?? ''))
|
|
143
145
|
.join('');
|
|
144
|
-
const meta = (obj(m.metadata) ?? {});
|
|
145
146
|
const images = m.parts
|
|
146
147
|
.filter((p) => p.type === 'file' && typeof p.url === 'string' && p.url.startsWith('data:image/'))
|
|
147
148
|
.map((p) => p.url);
|
|
@@ -152,6 +153,7 @@ export function itemsOf(messages, cards, screens = new Map(), steers = {}) {
|
|
|
152
153
|
...(images.length ? { images } : {}),
|
|
153
154
|
...(meta.context?.label ? { context: meta.context.label } : {}),
|
|
154
155
|
...(meta.refs?.length ? { refs: meta.refs } : {}),
|
|
156
|
+
...(meta.quote ? { quote: meta.quote } : {}),
|
|
155
157
|
...(meta.tier ? { tier: meta.tier } : {}),
|
|
156
158
|
});
|
|
157
159
|
continue;
|
|
@@ -322,6 +322,11 @@ export declare class Assistant {
|
|
|
322
322
|
id: string;
|
|
323
323
|
title: string;
|
|
324
324
|
};
|
|
325
|
+
/**
|
|
326
|
+
* What this call counts as in the month's spend per task (`spend:YYYY-MM` `tasks`), when one
|
|
327
|
+
* task does more than one kind of work (a first try, a repair). Left out, it is the task.
|
|
328
|
+
*/
|
|
329
|
+
tag?: string;
|
|
325
330
|
}): Promise<{
|
|
326
331
|
text: string;
|
|
327
332
|
usd: number;
|
package/dist/assistant/engine.js
CHANGED
|
@@ -332,7 +332,9 @@ export class Assistant {
|
|
|
332
332
|
: {},
|
|
333
333
|
};
|
|
334
334
|
const settle = async (end) => {
|
|
335
|
-
await this.state
|
|
335
|
+
await this.state
|
|
336
|
+
.addSpend(caller.id, paying.payer, end.parts, { task: 'chat', ms: end.ms })
|
|
337
|
+
.catch(() => undefined);
|
|
336
338
|
if (input.chat)
|
|
337
339
|
await this.state
|
|
338
340
|
.addUsage(caller.id, { id: `chat:${input.chat}`, kind: 'chat', title: message.split('\n')[0] || 'Chat' }, end.parts)
|
|
@@ -909,6 +911,7 @@ export class Assistant {
|
|
|
909
911
|
* `not_connected`, `app_cap` or `own_cap` when nobody can pay, or `upstream` when the model fails.
|
|
910
912
|
*/
|
|
911
913
|
async complete(caller, o) {
|
|
914
|
+
const began = Date.now();
|
|
912
915
|
const s = await this.session(caller, await this.mainTier(caller, o.task));
|
|
913
916
|
const { paying, wait } = await this.state.paying(caller.id, s.model.provider);
|
|
914
917
|
if (!paying) {
|
|
@@ -971,7 +974,10 @@ export class Assistant {
|
|
|
971
974
|
}
|
|
972
975
|
finally {
|
|
973
976
|
const part = s.meter.part();
|
|
974
|
-
await this.state.addSpend(caller.id, paying.payer, [part]
|
|
977
|
+
await this.state.addSpend(caller.id, paying.payer, [part], {
|
|
978
|
+
task: o.tag ?? o.task,
|
|
979
|
+
ms: Date.now() - began,
|
|
980
|
+
});
|
|
975
981
|
const task = this.tasks.find((t) => t.id === o.task);
|
|
976
982
|
await this.state
|
|
977
983
|
.addUsage(caller.id, {
|
|
@@ -19,7 +19,7 @@ export * from './find.js';
|
|
|
19
19
|
export * from './meaning.js';
|
|
20
20
|
export * from './models.js';
|
|
21
21
|
export * from './routes.js';
|
|
22
|
-
export { DEFAULT_CAP, type KeyDoc, keyDocName, type KeyTest, monthIn, type Paying, type PersonDoc, type SpendDoc, State, type TokenDoc, waitText, } from './state.js';
|
|
22
|
+
export { DEFAULT_CAP, type KeyDoc, keyDocName, type KeyTest, monthIn, type Paying, type PersonDoc, type SpendDoc, type TaskSpend, State, type TokenDoc, waitText, } from './state.js';
|
|
23
23
|
export * from './store.js';
|
|
24
24
|
export * from './tools.js';
|
|
25
25
|
export * from './web.js';
|
|
@@ -97,8 +97,30 @@ export interface RequestsDoc {
|
|
|
97
97
|
export type SpendRow = UsagePart & {
|
|
98
98
|
payer: AssistantPayer;
|
|
99
99
|
};
|
|
100
|
+
/**
|
|
101
|
+
* One task's use of one model this month: what a kind of work cost (a chat answer, a background
|
|
102
|
+
* task), beside `rows`, which stay per tier and payer.
|
|
103
|
+
*/
|
|
104
|
+
export interface TaskSpend {
|
|
105
|
+
/** The task's id (`chat`, or a `complete` call's `tag` or `task`). */
|
|
106
|
+
task: string;
|
|
107
|
+
/** The model's id. */
|
|
108
|
+
model: string;
|
|
109
|
+
/** Answers: chat turns, or `complete` calls. */
|
|
110
|
+
runs: number;
|
|
111
|
+
/** Model calls. */
|
|
112
|
+
calls: number;
|
|
113
|
+
in: number;
|
|
114
|
+
read: number;
|
|
115
|
+
out: number;
|
|
116
|
+
usd: number;
|
|
117
|
+
/** Time the answers took in all, in ms (`ms / runs` is the average). */
|
|
118
|
+
ms: number;
|
|
119
|
+
}
|
|
100
120
|
export interface SpendDoc {
|
|
101
121
|
rows: SpendRow[];
|
|
122
|
+
/** Per task and model, counted since the kit began tagging (older spend is only in `rows`). */
|
|
123
|
+
tasks?: TaskSpend[];
|
|
102
124
|
}
|
|
103
125
|
/** Chats and runs kept in one month's usage history: the newest this many. */
|
|
104
126
|
export declare const USAGE_KEPT = 300;
|
|
@@ -210,8 +232,14 @@ export declare class State {
|
|
|
210
232
|
} | null>;
|
|
211
233
|
appCap(): Promise<number>;
|
|
212
234
|
spend(id: string, month?: string): Promise<SpendDoc>;
|
|
213
|
-
/**
|
|
214
|
-
|
|
235
|
+
/**
|
|
236
|
+
* Adds an answer's use to this month's spend, by label and payer. `at` names the task the answer
|
|
237
|
+
* was for and how long it took, so the month also adds up per task and model (`tasks`).
|
|
238
|
+
*/
|
|
239
|
+
addSpend(id: string, payer: AssistantPayer, parts: UsagePart[], at?: {
|
|
240
|
+
task: string;
|
|
241
|
+
ms?: number;
|
|
242
|
+
}): Promise<void>;
|
|
215
243
|
/**
|
|
216
244
|
* Adds one answer's use to a chat or run in this month's history (`usage:YYYY-MM`): one entry a
|
|
217
245
|
* chat or run, its parts merged, the newest `USAGE_KEPT` kept. `title` names a new entry only.
|
package/dist/assistant/state.js
CHANGED
|
@@ -227,12 +227,43 @@ export class State {
|
|
|
227
227
|
spend(id, month = this.month()) {
|
|
228
228
|
return this.docs.read(id, `spend:${month}`).then((d) => d ?? { rows: [] });
|
|
229
229
|
}
|
|
230
|
-
/**
|
|
231
|
-
|
|
230
|
+
/**
|
|
231
|
+
* Adds an answer's use to this month's spend, by label and payer. `at` names the task the answer
|
|
232
|
+
* was for and how long it took, so the month also adds up per task and model (`tasks`).
|
|
233
|
+
*/
|
|
234
|
+
async addSpend(id, payer, parts, at) {
|
|
232
235
|
if (!parts.some((p) => p.calls))
|
|
233
236
|
return;
|
|
234
237
|
await this.docs.update(id, `spend:${this.month()}`, (d) => {
|
|
235
238
|
const rows = [...(d?.rows ?? [])];
|
|
239
|
+
const tasks = [...(d?.tasks ?? [])];
|
|
240
|
+
if (at) {
|
|
241
|
+
// The answer and its time count once, on its first model.
|
|
242
|
+
let first = true;
|
|
243
|
+
for (const p of parts) {
|
|
244
|
+
if (!p.calls)
|
|
245
|
+
continue;
|
|
246
|
+
const model = p.model ?? p.label;
|
|
247
|
+
const i = tasks.findIndex((t) => t.task === at.task && t.model === model);
|
|
248
|
+
const prev = i >= 0 ? tasks[i] : undefined;
|
|
249
|
+
const row = {
|
|
250
|
+
task: at.task,
|
|
251
|
+
model,
|
|
252
|
+
runs: (prev?.runs ?? 0) + (first ? 1 : 0),
|
|
253
|
+
calls: (prev?.calls ?? 0) + p.calls,
|
|
254
|
+
in: (prev?.in ?? 0) + p.in,
|
|
255
|
+
read: (prev?.read ?? 0) + p.read,
|
|
256
|
+
out: (prev?.out ?? 0) + p.out,
|
|
257
|
+
usd: (prev?.usd ?? 0) + p.usd,
|
|
258
|
+
ms: (prev?.ms ?? 0) + (first ? (at.ms ?? 0) : 0),
|
|
259
|
+
};
|
|
260
|
+
first = false;
|
|
261
|
+
if (i >= 0)
|
|
262
|
+
tasks[i] = row;
|
|
263
|
+
else
|
|
264
|
+
tasks.push(row);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
236
267
|
for (const p of parts) {
|
|
237
268
|
if (!p.calls)
|
|
238
269
|
continue;
|
|
@@ -253,7 +284,7 @@ export class State {
|
|
|
253
284
|
else
|
|
254
285
|
rows.push(row);
|
|
255
286
|
}
|
|
256
|
-
return { rows };
|
|
287
|
+
return tasks.length ? { rows, tasks } : { rows };
|
|
257
288
|
});
|
|
258
289
|
if (payer === 'app' && this.o.allowance?.period === 'once') {
|
|
259
290
|
const usd = parts.reduce((a, p) => a + p.usd, 0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.226",
|
|
4
4
|
"description": "Lumen's assistant and agent parts: a chat assistant's server (Claude tiers, tools over MCP, the web, hand off, spend caps), serving an MCP server from a Worker, read-only tool sets and metered tool calls.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"@ai-sdk/openai": "4.0.108",
|
|
53
53
|
"@anthropic-ai/sdk": "0.133.0",
|
|
54
54
|
"@cloudflare/think": "0.23.0",
|
|
55
|
-
"@columenlabs/lumen-ops": "0.1.
|
|
56
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
55
|
+
"@columenlabs/lumen-ops": "0.1.226",
|
|
56
|
+
"@columenlabs/lumen-ui-types": "0.1.226",
|
|
57
57
|
"agents": "0.32.0",
|
|
58
58
|
"ai": "7.0.162",
|
|
59
59
|
"just-bash": "3.6.0",
|