@columenlabs/lumen-ai 0.1.205 → 0.1.207

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.
@@ -18,7 +18,7 @@ import { generateText } from 'ai';
18
18
  import { CONNECTOR_GROUP, checkConnectorUrl, connectorGroup, connectorId, connectorSource, } from './connectors.js';
19
19
  import { aiModel, cachedTurn, planFallback, turnSettings } from './models.js';
20
20
  import { screenMapOf, screenNews, screenOutcomesOf, screenRules, screenTool, } from './screen.js';
21
- import { LAZY_AT, TOOL_SEARCH, lazyTools } from './search.js';
21
+ import { LAZY_AT, TOOL_SEARCH, lazyTools, usedTools } from './search.js';
22
22
  import { chunkEvents, itemsOf } from './stream.js';
23
23
  import { openAiTools, } from './tools.js';
24
24
  import { UsageMeter } from './usage.js';
@@ -515,7 +515,7 @@ export class LumenAgent extends Think {
515
515
  ];
516
516
  if (plan.first && !core.includes(plan.first))
517
517
  core.push(plan.first);
518
- lazy = lazyTools(tools, core, (n) => groups.get(n) ?? 'other');
518
+ lazy = lazyTools(tools, core, (n) => groups.get(n) ?? 'other', usedTools(ctx.messages));
519
519
  tools[TOOL_SEARCH] = lazy.search;
520
520
  system = `${system}\n\n${lazy.catalog}`;
521
521
  this.#turn.system = system;
@@ -18,8 +18,15 @@ export interface LazyTools {
18
18
  }
19
19
  /** How well a tool's name and description match the query's words. */
20
20
  export declare function toolScore(query: string, name: string, description?: string): number;
21
+ /**
22
+ * The tools a chat already used or found in earlier turns: each turn starts with only its core
23
+ * tools on, so a reply such as "yes" to a card offered last turn would call a tool that is off
24
+ * (AI_NoSuchToolError). Read from the history's tool calls and `tool_search` results.
25
+ */
26
+ export declare function usedTools(messages: readonly unknown[]): string[];
21
27
  /**
22
28
  * A search over `tools` whose finds stay on for the rest of the turn. `core` names are always on;
23
- * `groupOf` names each tool's group for the catalog.
29
+ * `groupOf` names each tool's group for the catalog; `start` names tools already on (those the
30
+ * chat used or found in earlier turns, `usedTools`), at most `FOUND_MAX` of the latest.
24
31
  */
25
- export declare function lazyTools(tools: ToolSet, core: string[], groupOf: (name: string) => string): LazyTools;
32
+ export declare function lazyTools(tools: ToolSet, core: string[], groupOf: (name: string) => string, start?: readonly string[]): LazyTools;
@@ -32,12 +32,38 @@ export function toolScore(query, name, description = '') {
32
32
  }
33
33
  return score;
34
34
  }
35
+ /**
36
+ * The tools a chat already used or found in earlier turns: each turn starts with only its core
37
+ * tools on, so a reply such as "yes" to a card offered last turn would call a tool that is off
38
+ * (AI_NoSuchToolError). Read from the history's tool calls and `tool_search` results.
39
+ */
40
+ export function usedTools(messages) {
41
+ const out = new Set();
42
+ for (const m of messages) {
43
+ const content = m.content;
44
+ if (!Array.isArray(content))
45
+ continue;
46
+ for (const part of content) {
47
+ if (part.type === 'tool-call' && part.toolName)
48
+ out.add(part.toolName);
49
+ if (part.type === 'tool-result' && part.toolName === TOOL_SEARCH) {
50
+ const o = part.output;
51
+ const v = (o && typeof o === 'object' && 'value' in o ? o.value : o);
52
+ for (const f of v?.found ?? [])
53
+ if (typeof f?.name === 'string')
54
+ out.add(f.name);
55
+ }
56
+ }
57
+ }
58
+ return [...out];
59
+ }
35
60
  /**
36
61
  * A search over `tools` whose finds stay on for the rest of the turn. `core` names are always on;
37
- * `groupOf` names each tool's group for the catalog.
62
+ * `groupOf` names each tool's group for the catalog; `start` names tools already on (those the
63
+ * chat used or found in earlier turns, `usedTools`), at most `FOUND_MAX` of the latest.
38
64
  */
39
- export function lazyTools(tools, core, groupOf) {
40
- const found = new Set();
65
+ export function lazyTools(tools, core, groupOf, start = []) {
66
+ const found = new Set(start.filter((n) => n in tools && !core.includes(n) && n !== TOOL_SEARCH).slice(-FOUND_MAX));
41
67
  const about = (n) => {
42
68
  const d = tools[n]?.description;
43
69
  return typeof d === 'string' ? d : '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@columenlabs/lumen-ai",
3
- "version": "0.1.205",
3
+ "version": "0.1.207",
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.205",
56
- "@columenlabs/lumen-ui-types": "0.1.205",
55
+ "@columenlabs/lumen-ops": "0.1.207",
56
+ "@columenlabs/lumen-ui-types": "0.1.207",
57
57
  "agents": "0.32.0",
58
58
  "ai": "7.0.162",
59
59
  "just-bash": "3.6.0",