@columenlabs/lumen-ai 0.1.185 → 0.1.186
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/dist/agent/models.d.ts +5 -2
- package/dist/agent/models.js +61 -9
- package/package.json +3 -3
package/dist/agent/models.d.ts
CHANGED
|
@@ -15,8 +15,11 @@ export interface AiModelOptions {
|
|
|
15
15
|
/**
|
|
16
16
|
* A ChatGPT plan sign-in takes function tools only inside one namespace and no output cap, and a
|
|
17
17
|
* forced call is the one tool offered with any call required (developers.openai.com/siwc, Preview
|
|
18
|
-
* limitations).
|
|
19
|
-
*
|
|
18
|
+
* limitations). It also keeps nothing (`store: false`, so earlier reasoning rides along encrypted)
|
|
19
|
+
* and takes the system prompt as `instructions`, as the assistant's own OpenAI loop sends it (the
|
|
20
|
+
* AI SDK's request without these came back 400 Bad Request on a plan, 2026-11-04). This fetch
|
|
21
|
+
* rewrites each Responses request to those rules, so the AI SDK's OpenAI provider runs on a plan
|
|
22
|
+
* unchanged.
|
|
20
23
|
*/
|
|
21
24
|
export declare function planFetch(base?: typeof fetch, name?: string): typeof fetch;
|
|
22
25
|
/** The AI SDK model a tier runs: its provider's client on the payer's key. */
|
package/dist/agent/models.js
CHANGED
|
@@ -8,8 +8,11 @@ import { createOpenAI } from '@ai-sdk/openai';
|
|
|
8
8
|
/**
|
|
9
9
|
* A ChatGPT plan sign-in takes function tools only inside one namespace and no output cap, and a
|
|
10
10
|
* forced call is the one tool offered with any call required (developers.openai.com/siwc, Preview
|
|
11
|
-
* limitations).
|
|
12
|
-
*
|
|
11
|
+
* limitations). It also keeps nothing (`store: false`, so earlier reasoning rides along encrypted)
|
|
12
|
+
* and takes the system prompt as `instructions`, as the assistant's own OpenAI loop sends it (the
|
|
13
|
+
* AI SDK's request without these came back 400 Bad Request on a plan, 2026-11-04). This fetch
|
|
14
|
+
* rewrites each Responses request to those rules, so the AI SDK's OpenAI provider runs on a plan
|
|
15
|
+
* unchanged.
|
|
13
16
|
*/
|
|
14
17
|
export function planFetch(base = fetch, name = 'Assistant') {
|
|
15
18
|
return async (input, init) => {
|
|
@@ -17,22 +20,66 @@ export function planFetch(base = fetch, name = 'Assistant') {
|
|
|
17
20
|
if (!url.endsWith('/responses') || typeof init?.body !== 'string')
|
|
18
21
|
return base(input, init);
|
|
19
22
|
const { max_output_tokens: _cap, ...body } = JSON.parse(init.body);
|
|
23
|
+
body.store = false;
|
|
24
|
+
const include = Array.isArray(body.include) ? body.include : [];
|
|
25
|
+
if (!include.includes('reasoning.encrypted_content'))
|
|
26
|
+
body.include = [...include, 'reasoning.encrypted_content'];
|
|
27
|
+
// System and developer messages become the request's instructions.
|
|
28
|
+
const items = Array.isArray(body.input) ? body.input : [];
|
|
29
|
+
const lead = items.filter((m) => m.role === 'system' || m.role === 'developer');
|
|
30
|
+
if (lead.length) {
|
|
31
|
+
const said = lead.map((m) => textOf(m.content)).filter(Boolean);
|
|
32
|
+
if (typeof body.instructions === 'string' && body.instructions)
|
|
33
|
+
said.unshift(body.instructions);
|
|
34
|
+
body.instructions = said.join('\n\n');
|
|
35
|
+
body.input = items.filter((m) => !lead.includes(m));
|
|
36
|
+
}
|
|
20
37
|
let tools = body.tools ?? [];
|
|
21
38
|
const choice = body.tool_choice;
|
|
22
39
|
if (choice && typeof choice === 'object' && choice.type === 'function' && choice.name) {
|
|
23
40
|
tools = tools.filter((t) => t.name === choice.name);
|
|
24
41
|
body.tool_choice = 'required';
|
|
25
42
|
}
|
|
26
|
-
|
|
43
|
+
// Each function as the assistant's own loop sends it: no `strict`, no JSON Schema dialect tag.
|
|
44
|
+
const fns = tools
|
|
45
|
+
.filter((t) => t.type === 'function')
|
|
46
|
+
.map(({ strict: _, ...t }) => {
|
|
47
|
+
const p = t.parameters;
|
|
48
|
+
if (!p || !('$schema' in p))
|
|
49
|
+
return t;
|
|
50
|
+
const { $schema: _s, ...parameters } = p;
|
|
51
|
+
return { ...t, parameters };
|
|
52
|
+
});
|
|
27
53
|
const rest = tools.filter((t) => t.type !== 'function');
|
|
28
54
|
if (fns.length)
|
|
29
55
|
body.tools = [
|
|
30
56
|
...rest,
|
|
31
57
|
{ type: 'namespace', name: 'app', description: `${name}'s tools`, tools: fns },
|
|
32
58
|
];
|
|
33
|
-
|
|
59
|
+
const res = await base(input, { ...init, body: JSON.stringify(body) });
|
|
60
|
+
// A refusal is logged with OpenAI's own reason; the person sees a plain sentence.
|
|
61
|
+
if (!res.ok)
|
|
62
|
+
console.error(JSON.stringify({
|
|
63
|
+
event: 'assistant_plan_refused',
|
|
64
|
+
status: res.status,
|
|
65
|
+
body: (await res.clone().text()).slice(0, 500),
|
|
66
|
+
}));
|
|
67
|
+
return res;
|
|
34
68
|
};
|
|
35
69
|
}
|
|
70
|
+
/** A message's text, whether a string or a list of text parts. */
|
|
71
|
+
function textOf(content) {
|
|
72
|
+
if (typeof content === 'string')
|
|
73
|
+
return content;
|
|
74
|
+
if (!Array.isArray(content))
|
|
75
|
+
return '';
|
|
76
|
+
return content
|
|
77
|
+
.map((p) => p && typeof p === 'object' && typeof p.text === 'string'
|
|
78
|
+
? p.text
|
|
79
|
+
: '')
|
|
80
|
+
.filter(Boolean)
|
|
81
|
+
.join('\n');
|
|
82
|
+
}
|
|
36
83
|
/** The AI SDK model a tier runs: its provider's client on the payer's key. */
|
|
37
84
|
export function aiModel(model, key, o = {}) {
|
|
38
85
|
if (model.provider === 'anthropic')
|
|
@@ -43,9 +90,14 @@ export function aiModel(model, key, o = {}) {
|
|
|
43
90
|
/** A tier's effort and output cap as a turn's settings; nothing at the model's own default. */
|
|
44
91
|
export function turnSettings(model, o) {
|
|
45
92
|
const out = o.plan || !o.out ? {} : { maxOutputTokens: o.out };
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
93
|
+
// A plan keeps nothing, so earlier turns go back as items, not references to stored ones.
|
|
94
|
+
const openai = o.plan ? { store: false } : {};
|
|
95
|
+
if (o.effort !== 'default') {
|
|
96
|
+
if (model.provider === 'anthropic')
|
|
97
|
+
return { ...out, providerOptions: { anthropic: { effort: o.effort } } };
|
|
98
|
+
openai.reasoningEffort = o.effort;
|
|
99
|
+
}
|
|
100
|
+
return model.provider === 'openai' && Object.keys(openai).length
|
|
101
|
+
? { ...out, providerOptions: { openai } }
|
|
102
|
+
: out;
|
|
51
103
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.186",
|
|
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",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
"@ai-sdk/openai": "4.0.108",
|
|
49
49
|
"@anthropic-ai/sdk": "0.133.0",
|
|
50
50
|
"@cloudflare/think": "0.23.0",
|
|
51
|
-
"@columenlabs/lumen-ops": "0.1.
|
|
52
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
51
|
+
"@columenlabs/lumen-ops": "0.1.186",
|
|
52
|
+
"@columenlabs/lumen-ui-types": "0.1.186",
|
|
53
53
|
"agents": "0.32.0",
|
|
54
54
|
"ai": "7.0.162",
|
|
55
55
|
"just-bash": "3.6.0",
|