@columenlabs/lumen-ai 0.1.81 → 0.1.82

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.
@@ -541,7 +541,7 @@ export class Assistant {
541
541
  }
542
542
  const page = this.cardNews(doc) +
543
543
  (req.refs?.length
544
- ? `The person points at: ${JSON.stringify(req.refs).slice(0, 8000)}\n\n`
544
+ ? `The person points at: ${JSON.stringify(req.refs).slice(0, 16000)}\n\n`
545
545
  : '') +
546
546
  (req.context
547
547
  ? `Page: ${req.context.label}${req.context.note === undefined ? '' : `\n${JSON.stringify(req.context.note).slice(0, 4000)}`}\n\n`
@@ -966,23 +966,41 @@ export class Assistant {
966
966
  // On a plan a forced call is the one tool offered, with any call required.
967
967
  const only = plan && typeof force === 'object' ? force.name : undefined;
968
968
  const choice = only ? 'required' : force;
969
- const stream = client.responses.stream({
970
- model: session.model.id,
971
- instructions,
972
- input,
973
- ...sent(only),
974
- store: false,
975
- stream: true,
976
- include: ['reasoning.encrypted_content'],
977
- ...(effort ? { reasoning: { effort } } : {}),
978
- ...(choice ? { tool_choice: choice } : {}),
979
- }, signal ? { signal } : {});
969
+ // The raw event stream, not the SDK's accumulator: a plan sign-in's backend sends event types
970
+ // the SDK does not know and its accumulator throws on them. The final response rides on the
971
+ // completed, incomplete or failed event; every other event but text deltas is skipped.
980
972
  let partial = '';
981
- stream.on('response.output_text.delta', (e) => {
982
- partial += e.delta;
983
- emit('text', { delta: e.delta });
984
- });
985
- const res = await stream.finalResponse().catch((err) => {
973
+ const res = await (async () => {
974
+ const stream = await client.responses.create({
975
+ model: session.model.id,
976
+ instructions,
977
+ input,
978
+ ...sent(only),
979
+ store: false,
980
+ stream: true,
981
+ include: ['reasoning.encrypted_content'],
982
+ ...(effort ? { reasoning: { effort } } : {}),
983
+ ...(choice ? { tool_choice: choice } : {}),
984
+ }, signal ? { signal } : {});
985
+ let done;
986
+ for await (const e of stream) {
987
+ if (e.type === 'response.output_text.delta' && typeof e.delta === 'string') {
988
+ partial += e.delta;
989
+ emit('text', { delta: e.delta });
990
+ }
991
+ else if (e.type === 'response.completed' ||
992
+ e.type === 'response.incomplete' ||
993
+ e.type === 'response.failed') {
994
+ done = e.response;
995
+ }
996
+ else if (e.type === 'error') {
997
+ throw new AssistantError('OpenAI could not finish the answer.', 'upstream');
998
+ }
999
+ }
1000
+ if (!done)
1001
+ throw new AssistantError('OpenAI ended the answer early.', 'upstream');
1002
+ return done;
1003
+ })().catch((err) => {
986
1004
  if (signal?.aborted && partial)
987
1005
  sink.push({ kind: 'text', text: partial });
988
1006
  throw err;
@@ -1011,7 +1029,12 @@ export class Assistant {
1011
1029
  const cut = res.incomplete_details?.reason === 'max_output_tokens' ? ' …(cut)' : '';
1012
1030
  if (cut)
1013
1031
  emit('text', { delta: cut });
1014
- const text = (res.output_text ?? '') + cut;
1032
+ // Raw events carry no `output_text`: the words are the output messages' text parts.
1033
+ const words = res.output
1034
+ .flatMap((b) => (b.type === 'message' ? b.content : []))
1035
+ .map((c) => (c.type === 'output_text' ? c.text : ''))
1036
+ .join('');
1037
+ const text = words + cut;
1015
1038
  if (text) {
1016
1039
  answer += (answer ? '\n\n' : '') + text;
1017
1040
  sink.push({ kind: 'text', text });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@columenlabs/lumen-ai",
3
- "version": "0.1.81",
3
+ "version": "0.1.82",
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",
@@ -41,8 +41,8 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@anthropic-ai/sdk": "0.133.0",
44
- "@columenlabs/lumen-ops": "0.1.81",
45
- "@columenlabs/lumen-ui-types": "0.1.81",
44
+ "@columenlabs/lumen-ops": "0.1.82",
45
+ "@columenlabs/lumen-ui-types": "0.1.82",
46
46
  "openai": "7.32.0",
47
47
  "zod": "^4.3.6"
48
48
  },