@columenlabs/lumen-ai 0.1.208 → 0.1.209
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/assistant/engine.d.ts +4 -0
- package/dist/assistant/engine.js +18 -6
- 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. It throws `AssistantError` `not_connected`, `app_cap` or `own_cap` when nobody can pay, so the caller waits and tries later.
|
|
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.
|
|
107
107
|
|
|
108
108
|
### Commands, `@` and `#`
|
|
109
109
|
|
|
@@ -56,6 +56,8 @@ export interface AllowanceNotice {
|
|
|
56
56
|
request: AllowanceRequest;
|
|
57
57
|
unit: AllowanceUnit;
|
|
58
58
|
}
|
|
59
|
+
/** The largest answer `complete` asks for, tokens (thinking included). Streamed, so minutes are fine. */
|
|
60
|
+
export declare const COMPLETE_MAX_TOKENS = 32000;
|
|
59
61
|
/** A change a write tool made at once, as `undo` gets it. */
|
|
60
62
|
export interface AssistantWrite {
|
|
61
63
|
/** The tool's own name (not the `group__tool` the model calls). */
|
|
@@ -292,12 +294,14 @@ export declare class Assistant {
|
|
|
292
294
|
prompt: string;
|
|
293
295
|
/** Photos read with the prompt (a scanned page, a screenshot). */
|
|
294
296
|
images?: CompleteImage[];
|
|
297
|
+
/** The answer's token cap, thinking included (default 1,000, at most COMPLETE_MAX_TOKENS). */
|
|
295
298
|
maxTokens?: number;
|
|
296
299
|
signal?: AbortSignal;
|
|
297
300
|
}): Promise<{
|
|
298
301
|
text: string;
|
|
299
302
|
usd: number;
|
|
300
303
|
model: string;
|
|
304
|
+
cut: boolean;
|
|
301
305
|
}>;
|
|
302
306
|
/** Starts a person's ChatGPT plan sign-in: the address to open in a new tab. */
|
|
303
307
|
startSignin(caller: Caller, provider: AssistantProvider): Promise<{
|
package/dist/assistant/engine.js
CHANGED
|
@@ -23,6 +23,8 @@ const DOLLARS = { one: 'dollar', many: 'dollars', usd: 1 };
|
|
|
23
23
|
const round2 = (n) => Math.round(n * 100) / 100;
|
|
24
24
|
/** A request may ask for at most this many times the starter or monthly cap. */
|
|
25
25
|
const REQUEST_MAX_TIMES = 100;
|
|
26
|
+
/** The largest answer `complete` asks for, tokens (thinking included). Streamed, so minutes are fine. */
|
|
27
|
+
export const COMPLETE_MAX_TOKENS = 32_000;
|
|
26
28
|
/** A turn's failure the person can act on. */
|
|
27
29
|
export class AssistantError extends Error {
|
|
28
30
|
code;
|
|
@@ -887,7 +889,10 @@ export class Assistant {
|
|
|
887
889
|
cache_read_input_tokens: read,
|
|
888
890
|
}, plan);
|
|
889
891
|
}
|
|
890
|
-
return
|
|
892
|
+
return {
|
|
893
|
+
text: text || done?.output_text || '',
|
|
894
|
+
cut: done?.status === 'incomplete' && done.incomplete_details?.reason === 'max_output_tokens',
|
|
895
|
+
};
|
|
891
896
|
}
|
|
892
897
|
// ---------------------------------------------------------------- one-shot work
|
|
893
898
|
/**
|
|
@@ -904,15 +909,20 @@ export class Assistant {
|
|
|
904
909
|
throw new AssistantError(waitText(code, s.model.provider, !!this.o.allowance), code, 402);
|
|
905
910
|
}
|
|
906
911
|
const clients = this.clients(paying);
|
|
907
|
-
const max = Math.min(o.maxTokens ?? 1000,
|
|
912
|
+
const max = Math.min(o.maxTokens ?? 1000, COMPLETE_MAX_TOKENS);
|
|
908
913
|
let text = '';
|
|
914
|
+
// The answer stopped at `max` before it ended (its thinking counts toward the cap too).
|
|
915
|
+
let cut = false;
|
|
909
916
|
try {
|
|
910
917
|
if ((s.model.provider === 'openai' && clients.openai) ||
|
|
911
918
|
(s.model.provider === 'xai' && clients.xai)) {
|
|
912
|
-
text = await this.openaiOnce(clients, s, o.system, o.prompt, max, o.signal, o.images);
|
|
919
|
+
({ text, cut } = await this.openaiOnce(clients, s, o.system, o.prompt, max, o.signal, o.images));
|
|
913
920
|
}
|
|
914
921
|
else if (clients.anthropic) {
|
|
915
|
-
|
|
922
|
+
// Streamed and read whole: a long answer (minutes at a high cap) keeps its connection alive,
|
|
923
|
+
// and the SDK refuses a long answer as one unstreamed request.
|
|
924
|
+
const msg = await clients.anthropic.messages
|
|
925
|
+
.stream({
|
|
916
926
|
model: s.model.id,
|
|
917
927
|
max_tokens: max,
|
|
918
928
|
system: o.system,
|
|
@@ -935,8 +945,10 @@ export class Assistant {
|
|
|
935
945
|
},
|
|
936
946
|
],
|
|
937
947
|
...effortParams(s.effort),
|
|
938
|
-
}, o.signal ? { signal: o.signal } : undefined)
|
|
948
|
+
}, o.signal ? { signal: o.signal } : undefined)
|
|
949
|
+
.finalMessage();
|
|
939
950
|
s.meter.add(msg.usage);
|
|
951
|
+
cut = msg.stop_reason === 'max_tokens';
|
|
940
952
|
text = msg.content
|
|
941
953
|
.filter((b) => b.type === 'text')
|
|
942
954
|
.map((b) => b.text)
|
|
@@ -953,7 +965,7 @@ export class Assistant {
|
|
|
953
965
|
finally {
|
|
954
966
|
await this.state.addSpend(caller.id, paying.payer, [s.meter.part()]);
|
|
955
967
|
}
|
|
956
|
-
return { text, usd: s.meter.usd, model: s.model.id };
|
|
968
|
+
return { text, usd: s.meter.usd, model: s.model.id, cut };
|
|
957
969
|
}
|
|
958
970
|
// ---------------------------------------------------------------- keys
|
|
959
971
|
/** Starts a person's ChatGPT plan sign-in: the address to open in a new tab. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.209",
|
|
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.209",
|
|
56
|
+
"@columenlabs/lumen-ui-types": "0.1.209",
|
|
57
57
|
"agents": "0.32.0",
|
|
58
58
|
"ai": "7.0.162",
|
|
59
59
|
"just-bash": "3.6.0",
|