@columenlabs/lumen-ai 0.1.217 → 0.1.218
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 +2 -0
- package/dist/agent/agent.d.ts +5 -1
- package/dist/agent/agent.js +16 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -241,6 +241,8 @@ Drafts and writes are cards in the chat's own storage (`lumen_cards` in the agen
|
|
|
241
241
|
|
|
242
242
|
**The panel.** `LumenAssistant` reads a Think chat with no change. `ask(input, sink)` runs one answer and sends the panel's own events (`AssistantEvent`: the chat, the text, each tool line, cards, hand-off sections, advice, the use) to `sink`. The app's `POST /chat` returns `askResponse((sink) => chat.ask(input, sink), { signal, stop: () => chat.stop() })`, the same server-sent events `assistantRoutes` sends. `view()` gives a stored chat as the panel's items, and `usage()` gives the chat's use so far. A card's id is its tool call's, so the panel's Save, Dismiss and Undo go to `saveCard`, `dismissCard` and `undoCard`. The app keeps the list of chats, and each chat is its own agent, such as a facet of the person's store. `chunkEvents` and `itemsOf` are the mapping, for an app that streams some other way.
|
|
243
243
|
|
|
244
|
+
**Steps.** One answer makes at most `plan.maxSteps` model calls (`MAX_STEPS`, 8). The last one runs with no tools and `LAST_STEP_NOTE`, so an answer always ends in words: what it found, and what is left when the task did not fit.
|
|
245
|
+
|
|
244
246
|
**Steer and queue.** While an answer runs, the panel's box stays open: Enter steers the message into the answer (`steer(message)` on the agent; the app routes `POST /chats/:id/steer` `{ message }` to it and answers `{ steered }`), Alt+Enter queues it for after. A steer joins at the answer's next step, after the tool it is on, with `STEER_NOTE` before it for the model; the panel shows it there marked Steered (event `steered`), and `view()` keeps it in place (`SteerNote`, under the message the answer is to). A steer the answer ends before reading comes back as `unsteered` and goes first in the queue. `plan.steer: false` turns it off for a model; an app without the route (404) shows Queue only. Queued messages each go as their own message when the answer before them ends; each has Steer now, Edit and Remove.
|
|
245
247
|
|
|
246
248
|
```ts
|
package/dist/agent/agent.d.ts
CHANGED
|
@@ -74,7 +74,7 @@ export interface AgentTurnPlan {
|
|
|
74
74
|
left?: number;
|
|
75
75
|
/** The person lets the assistant move their screen: the `screen` tool joins when the browser sent its map. */
|
|
76
76
|
screen?: boolean;
|
|
77
|
-
/** Most model calls in one answer;
|
|
77
|
+
/** Most model calls in one answer (`MAX_STEPS`, 8); the last one answers in words, with no tools. */
|
|
78
78
|
maxSteps?: number;
|
|
79
79
|
/**
|
|
80
80
|
* A message sent while the answer runs joins it at its next step (Steer); on unless `false`,
|
|
@@ -99,6 +99,10 @@ export interface AgentTurnEnd {
|
|
|
99
99
|
capped: boolean;
|
|
100
100
|
}
|
|
101
101
|
export declare const CAP_NOTE = "The spend cap for this month is reached: answer now from what you have, in a sentence or two. You can call no more tools.";
|
|
102
|
+
/** The last call of an answer: no tools, so the answer never ends on a tool's result with nothing said. */
|
|
103
|
+
export declare const LAST_STEP_NOTE = "This is the answer's last call and you can call no more tools: answer now from what you found. If the task is not finished, say what is done, what is left and that you can carry on when asked.";
|
|
104
|
+
/** Most model calls in one answer when the plan names none. */
|
|
105
|
+
export declare const MAX_STEPS = 8;
|
|
102
106
|
/** Put before a message the person steered into a running answer, for the model only. */
|
|
103
107
|
export declare const STEER_NOTE = "The person sent this while you were working. Take it into account from here on; it does not cancel what you were asked before unless it says so.";
|
|
104
108
|
/** A card in the chat: a draft the person saves or dismisses, or a write made at once (Undo). */
|
package/dist/agent/agent.js
CHANGED
|
@@ -24,6 +24,10 @@ import { chunkEvents, itemsOf } from './stream.js';
|
|
|
24
24
|
import { openAiTools, } from './tools.js';
|
|
25
25
|
import { UsageMeter } from './usage.js';
|
|
26
26
|
export const CAP_NOTE = 'The spend cap for this month is reached: answer now from what you have, in a sentence or two. You can call no more tools.';
|
|
27
|
+
/** The last call of an answer: no tools, so the answer never ends on a tool's result with nothing said. */
|
|
28
|
+
export const LAST_STEP_NOTE = "This is the answer's last call and you can call no more tools: answer now from what you found. If the task is not finished, say what is done, what is left and that you can carry on when asked.";
|
|
29
|
+
/** Most model calls in one answer when the plan names none. */
|
|
30
|
+
export const MAX_STEPS = 8;
|
|
27
31
|
/** Put before a message the person steered into a running answer, for the model only. */
|
|
28
32
|
export const STEER_NOTE = 'The person sent this while you were working. Take it into account from here on; it does not cancel what you were asked before unless it says so.';
|
|
29
33
|
/** Past this many tokens in the chat Think summarizes its older part. */
|
|
@@ -596,7 +600,7 @@ export class LumenAgent extends Think {
|
|
|
596
600
|
tools,
|
|
597
601
|
...(lazy ? { activeTools: lazy.active() } : {}),
|
|
598
602
|
...(plan.first ? { toolChoice: { type: 'tool', toolName: plan.first } } : {}),
|
|
599
|
-
maxSteps: plan.maxSteps ??
|
|
603
|
+
maxSteps: plan.maxSteps ?? MAX_STEPS,
|
|
600
604
|
...turnSettings(plan.model, {
|
|
601
605
|
effort: plan.effort ?? 'default',
|
|
602
606
|
...(plan.out ? { out: plan.out } : {}),
|
|
@@ -620,6 +624,17 @@ export class LumenAgent extends Think {
|
|
|
620
624
|
};
|
|
621
625
|
return capped;
|
|
622
626
|
}
|
|
627
|
+
// The last call answers in words: past it the loop stops, so a tool call there would end the
|
|
628
|
+
// answer on a tool's result with nothing said.
|
|
629
|
+
if (ctx.stepNumber >= (t.plan.maxSteps ?? MAX_STEPS) - 1) {
|
|
630
|
+
const last = {
|
|
631
|
+
...messages,
|
|
632
|
+
activeTools: [],
|
|
633
|
+
toolChoice: 'none',
|
|
634
|
+
instructions: `${t.system}\n\n${LAST_STEP_NOTE}`,
|
|
635
|
+
};
|
|
636
|
+
return last;
|
|
637
|
+
}
|
|
623
638
|
// A forced first call is for the first step only; tools a search found join each step.
|
|
624
639
|
const auto = t.plan.first && ctx.stepNumber > 0;
|
|
625
640
|
if (!auto && !t.lazy && !steered)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.218",
|
|
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.218",
|
|
56
|
+
"@columenlabs/lumen-ui-types": "0.1.218",
|
|
57
57
|
"agents": "0.32.0",
|
|
58
58
|
"ai": "7.0.162",
|
|
59
59
|
"just-bash": "3.6.0",
|