deepclause-sdk 0.0.75 → 0.0.76

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/runner.d.ts CHANGED
@@ -42,6 +42,7 @@ export declare class DMLRunner {
42
42
  private engine;
43
43
  private sessionId;
44
44
  private currentMemory;
45
+ private stepCounter;
45
46
  constructor(swipl: SWIPLModule, options: RunnerOptions);
46
47
  /**
47
48
  * Get the current conversation memory
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
package/dist/runner.js CHANGED
@@ -142,6 +142,7 @@ export class DMLRunner {
142
142
  engine = null;
143
143
  sessionId = '';
144
144
  currentMemory = [];
145
+ stepCounter = 0;
145
146
  constructor(swipl, options) {
146
147
  this.swipl = swipl;
147
148
  this.options = options;
@@ -411,215 +412,228 @@ export class DMLRunner {
411
412
  */
412
413
  async *handleAgentLoop(payload, _memoryId, // No longer used - memory comes from payload
413
414
  options) {
414
- // Safely extract payload fields with proper conversion
415
415
  const rawPayload = payload;
416
416
  const taskDescription = String(toJsValue(rawPayload.taskDescription) ?? '');
417
- // Ensure outputVars is an array of either strings or TypedVar objects
418
- const outputVars = decodeAgentOutputVars(rawPayload.outputVars);
419
- // Parse userTools - now contains schema info as array of tool_info dicts
420
- const userTools = [];
421
- const rawUserTools = toJsValue(rawPayload.userTools);
422
- if (process.env.DEBUG_RUNNER) {
423
- console.log('[RUNNER] Raw userTools from Prolog:', JSON.stringify(rawUserTools, null, 2));
424
- }
425
- if (Array.isArray(rawUserTools)) {
426
- for (const tool of rawUserTools) {
427
- const toolObj = toJsValue(tool);
428
- const toolInfo = this.parseUserToolInfo(toolObj);
429
- if (toolInfo) {
430
- userTools.push(toolInfo);
431
- }
432
- }
433
- }
434
- // Queue for streaming and internal runtime events
435
- const streamQueue = [];
436
- let streamResolve = null;
437
- const emitRunnerEvent = (event) => {
438
- streamQueue.push(event);
439
- if (streamResolve) {
440
- streamResolve();
441
- streamResolve = null;
417
+ const stepId = `step_${this.stepCounter++}`;
418
+ yield { type: 'task_activity', taskState: 'started', taskDescription, taskId: stepId };
419
+ let stepSucceeded = null;
420
+ try {
421
+ // Ensure outputVars is an array of either strings or TypedVar objects
422
+ const outputVars = decodeAgentOutputVars(rawPayload.outputVars);
423
+ // Parse userTools - now contains schema info as array of tool_info dicts
424
+ const userTools = [];
425
+ const rawUserTools = toJsValue(rawPayload.userTools);
426
+ if (process.env.DEBUG_RUNNER) {
427
+ console.log('[RUNNER] Raw userTools from Prolog:', JSON.stringify(rawUserTools, null, 2));
442
428
  }
443
- };
444
- // Extract memory from payload (now passed via state threading)
445
- const preparedMemory = this.extractMemoryFromPayload(rawPayload);
446
- // Store current memory for getMemory() access
447
- this.currentMemory = preparedMemory;
448
- const emitToolEvent = (event) => {
449
- emitRunnerEvent(event);
450
- };
451
- // Callback for tool output events
452
- const onToolOutput = (text) => {
453
- emitToolEvent({ type: 'output', content: text });
454
- };
455
- // Augment registered tools with internal ask_user so DML tools can call exec(ask_user(...))
456
- const augmentedTools = new Map(options.tools);
457
- if (!augmentedTools.has('ask_user')) {
458
- augmentedTools.set('ask_user', {
459
- description: 'Ask the user for input or clarification',
460
- parameters: {
461
- type: 'object',
462
- properties: {
463
- prompt: { type: 'string', description: 'The question or prompt to show the user' }
464
- },
465
- required: ['prompt']
466
- },
467
- execute: async (args) => {
468
- const argsObj = args;
469
- const prompt = (argsObj.prompt ?? argsObj.arg1 ?? Object.values(argsObj).find(v => typeof v === 'string'));
470
- if (!prompt) {
471
- return { error: 'No prompt provided to ask_user' };
472
- }
473
- try {
474
- emitToolEvent({ type: 'input_required', prompt });
475
- const response = await options.onInputRequired(prompt);
476
- return { user_response: response };
477
- }
478
- catch (err) {
479
- return { error: String(err) };
429
+ if (Array.isArray(rawUserTools)) {
430
+ for (const tool of rawUserTools) {
431
+ const toolObj = toJsValue(tool);
432
+ const toolInfo = this.parseUserToolInfo(toolObj);
433
+ if (toolInfo) {
434
+ userTools.push(toolInfo);
480
435
  }
481
- },
482
- });
483
- }
484
- // Callback to emit tool call events
485
- const emitToolCall = (toolName, args) => {
486
- emitToolEvent({ type: 'tool_call', toolName, toolArgs: args });
487
- };
488
- // Build available tools for agent - SIMPLIFIED: tools run in isolated engines
489
- const availableTools = this.buildAgentTools(userTools, options.toolPolicy,
490
- // executeToolIsolated callback - runs tool in separate engine (no state sharing)
491
- async (toolName, args) => {
492
- return this.executeToolIsolated(toolName, args, augmentedTools, onToolOutput, {
493
- workspacePath: options.workspacePath,
494
- signal: options.signal,
495
- compaction: options.compaction,
496
- toolPolicy: options.toolPolicy,
497
- }, [], emitToolCall, emitToolEvent);
498
- });
499
- // Run agent loop with streaming support
500
- const resultPromise = runAgentLoop({
501
- taskDescription,
502
- outputVars,
503
- memory: preparedMemory,
504
- tools: availableTools,
505
- workspacePath: options.workspacePath,
506
- modelOptions: {
507
- model: this.options.model,
508
- provider: this.options.provider,
509
- temperature: this.options.temperature,
510
- maxOutputTokens: this.options.maxTokens,
511
- baseUrl: this.options.baseUrl,
512
- providerOptions: this.options.providerOptions,
513
- },
514
- streaming: this.options.streaming,
515
- debug: this.options.debug,
516
- onOutput: (_text) => { },
517
- onStream: (chunk, done) => {
518
- streamQueue.push({ type: 'stream', content: chunk, done });
519
- if (streamResolve) {
520
- streamResolve();
521
- streamResolve = null;
522
- }
523
- },
524
- onToolCall: (toolName, args) => {
525
- streamQueue.push({ type: 'tool_call', toolName, toolArgs: args });
526
- if (streamResolve) {
527
- streamResolve();
528
- streamResolve = null;
529
436
  }
530
- },
531
- onUsage: (usage) => {
532
- streamQueue.push({ type: 'usage', usage });
437
+ }
438
+ // Queue for streaming and internal runtime events
439
+ const streamQueue = [];
440
+ let streamResolve = null;
441
+ const emitRunnerEvent = (event) => {
442
+ streamQueue.push(event);
533
443
  if (streamResolve) {
534
444
  streamResolve();
535
445
  streamResolve = null;
536
446
  }
537
- },
538
- onBeforeModelCall: async (messages) => this.applyCompactionBindings({
539
- messages,
540
- scope: 'loop',
541
- trigger: 'before_model_call',
542
- options,
543
- executionContext: {
447
+ };
448
+ // Extract memory from payload (now passed via state threading)
449
+ const preparedMemory = this.extractMemoryFromPayload(rawPayload);
450
+ // Store current memory for getMemory() access
451
+ this.currentMemory = preparedMemory;
452
+ const emitToolEvent = (event) => {
453
+ emitRunnerEvent(event);
454
+ };
455
+ // Callback for tool output events
456
+ const onToolOutput = (text) => {
457
+ emitToolEvent({ type: 'output', content: text });
458
+ };
459
+ // Augment registered tools with internal ask_user so DML tools can call exec(ask_user(...))
460
+ const augmentedTools = new Map(options.tools);
461
+ if (!augmentedTools.has('ask_user')) {
462
+ augmentedTools.set('ask_user', {
463
+ description: 'Ask the user for input or clarification',
464
+ parameters: {
465
+ type: 'object',
466
+ properties: {
467
+ prompt: { type: 'string', description: 'The question or prompt to show the user' }
468
+ },
469
+ required: ['prompt']
470
+ },
471
+ execute: async (args) => {
472
+ const argsObj = args;
473
+ const prompt = (argsObj.prompt ?? argsObj.arg1 ?? Object.values(argsObj).find(v => typeof v === 'string'));
474
+ if (!prompt) {
475
+ return { error: 'No prompt provided to ask_user' };
476
+ }
477
+ try {
478
+ emitToolEvent({ type: 'input_required', prompt });
479
+ const response = await options.onInputRequired(prompt);
480
+ return { user_response: response };
481
+ }
482
+ catch (err) {
483
+ return { error: String(err) };
484
+ }
485
+ },
486
+ });
487
+ }
488
+ // Callback to emit tool call events
489
+ const emitToolCall = (toolName, args) => {
490
+ emitToolEvent({ type: 'tool_call', toolName, toolArgs: args });
491
+ };
492
+ // Build available tools for agent - SIMPLIFIED: tools run in isolated engines
493
+ const availableTools = this.buildAgentTools(userTools, options.toolPolicy,
494
+ // executeToolIsolated callback - runs tool in separate engine (no state sharing)
495
+ async (toolName, args) => {
496
+ return this.executeToolIsolated(toolName, args, augmentedTools, onToolOutput, {
544
497
  workspacePath: options.workspacePath,
545
498
  signal: options.signal,
546
499
  compaction: options.compaction,
500
+ toolPolicy: options.toolPolicy,
501
+ }, [], emitToolCall, emitToolEvent);
502
+ });
503
+ // Run agent loop with streaming support
504
+ const resultPromise = runAgentLoop({
505
+ taskDescription,
506
+ outputVars,
507
+ memory: preparedMemory,
508
+ tools: availableTools,
509
+ workspacePath: options.workspacePath,
510
+ modelOptions: {
511
+ model: this.options.model,
512
+ provider: this.options.provider,
513
+ temperature: this.options.temperature,
514
+ maxOutputTokens: this.options.maxTokens,
515
+ baseUrl: this.options.baseUrl,
516
+ providerOptions: this.options.providerOptions,
547
517
  },
548
- registeredTools: options.tools,
549
- toolPolicy: options.toolPolicy,
550
- emitEvent: emitRunnerEvent,
551
- }),
552
- onAskUser: options.onInputRequired,
553
- signal: options.signal,
554
- });
555
- // Yield streaming events as they arrive
556
- if (this.options.streaming) {
557
- while (true) {
558
- // Process any queued events
559
- while (streamQueue.length > 0) {
560
- yield streamQueue.shift();
561
- }
562
- // Check if result is ready
563
- const raceResult = await Promise.race([
564
- resultPromise.then(r => ({ type: 'done', result: r })),
565
- new Promise(resolve => {
566
- streamResolve = () => resolve({ type: 'stream' });
567
- }),
568
- ]);
569
- if (raceResult.type === 'done') {
570
- // Drain remaining queue
571
- while (streamQueue.length > 0) {
572
- yield streamQueue.shift();
518
+ streaming: this.options.streaming,
519
+ debug: this.options.debug,
520
+ onOutput: (_text) => { },
521
+ onStream: (chunk, done) => {
522
+ streamQueue.push({ type: 'stream', content: chunk, done });
523
+ if (streamResolve) {
524
+ streamResolve();
525
+ streamResolve = null;
526
+ }
527
+ },
528
+ onToolCall: (toolName, args) => {
529
+ streamQueue.push({ type: 'tool_call', toolName, toolArgs: args });
530
+ if (streamResolve) {
531
+ streamResolve();
532
+ streamResolve = null;
573
533
  }
574
- // In streaming mode, output was already shown via onStream - don't repeat it
575
- // The outputs array is kept for memory/history purposes only
576
- const finalizedMemory = [
577
- ...preparedMemory.filter((message) => message.role === 'system'),
578
- ...raceResult.result.messages,
579
- ];
534
+ },
535
+ onUsage: (usage) => {
536
+ streamQueue.push({ type: 'usage', usage });
537
+ if (streamResolve) {
538
+ streamResolve();
539
+ streamResolve = null;
540
+ }
541
+ },
542
+ onBeforeModelCall: async (messages) => this.applyCompactionBindings({
543
+ messages,
544
+ scope: 'loop',
545
+ trigger: 'before_model_call',
546
+ options,
547
+ executionContext: {
548
+ workspacePath: options.workspacePath,
549
+ signal: options.signal,
550
+ compaction: options.compaction,
551
+ },
552
+ registeredTools: options.tools,
553
+ toolPolicy: options.toolPolicy,
554
+ emitEvent: emitRunnerEvent,
555
+ }),
556
+ onAskUser: options.onInputRequired,
557
+ signal: options.signal,
558
+ });
559
+ // Yield streaming events as they arrive
560
+ if (this.options.streaming) {
561
+ while (true) {
562
+ // Process any queued events
580
563
  while (streamQueue.length > 0) {
581
564
  yield streamQueue.shift();
582
565
  }
583
- // Update memory with full agent conversation
584
- this.currentMemory = finalizedMemory;
585
- // Post result back to Prolog
586
- this.postAgentResult(raceResult.result, finalizedMemory);
587
- return;
566
+ // Check if result is ready
567
+ const raceResult = await Promise.race([
568
+ resultPromise.then(r => ({ type: 'done', result: r })),
569
+ new Promise(resolve => {
570
+ streamResolve = () => resolve({ type: 'stream' });
571
+ }),
572
+ ]);
573
+ if (raceResult.type === 'done') {
574
+ // Drain remaining queue
575
+ while (streamQueue.length > 0) {
576
+ yield streamQueue.shift();
577
+ }
578
+ // In streaming mode, output was already shown via onStream - don't repeat it
579
+ // The outputs array is kept for memory/history purposes only
580
+ const finalizedMemory = [
581
+ ...preparedMemory.filter((message) => message.role === 'system'),
582
+ ...raceResult.result.messages,
583
+ ];
584
+ while (streamQueue.length > 0) {
585
+ yield streamQueue.shift();
586
+ }
587
+ // Update memory with full agent conversation
588
+ this.currentMemory = finalizedMemory;
589
+ // Post result back to Prolog
590
+ stepSucceeded = raceResult.result.success;
591
+ this.postAgentResult(raceResult.result, finalizedMemory);
592
+ return;
593
+ }
594
+ // Otherwise continue loop to yield queued stream events
588
595
  }
589
- // Otherwise continue loop to yield queued stream events
590
596
  }
591
- }
592
- else {
593
- // Non-streaming mode - wait for completion
594
- const result = await resultPromise;
595
- // Drain tool_call events from queue (they were queued during agent execution)
596
- if (process.env.DEBUG_QUEUE) {
597
- console.log('[RUNNER] Non-streaming: streamQueue length before drain:', streamQueue.length);
598
- if (streamQueue.length > 0) {
599
- console.log('[RUNNER] streamQueue contents:', streamQueue.map(e => `${e.type}:${e.content?.substring(0, 40)}`));
597
+ else {
598
+ // Non-streaming mode - wait for completion
599
+ const result = await resultPromise;
600
+ // Drain tool_call events from queue (they were queued during agent execution)
601
+ if (process.env.DEBUG_QUEUE) {
602
+ console.log('[RUNNER] Non-streaming: streamQueue length before drain:', streamQueue.length);
603
+ if (streamQueue.length > 0) {
604
+ console.log('[RUNNER] streamQueue contents:', streamQueue.map(e => `${e.type}:${e.content?.substring(0, 40)}`));
605
+ }
600
606
  }
607
+ while (streamQueue.length > 0) {
608
+ yield streamQueue.shift();
609
+ }
610
+ if (process.env.DEBUG_QUEUE) {
611
+ console.log('[RUNNER] Non-streaming agent result.outputs:', result.outputs);
612
+ }
613
+ // Stream any output from the agent
614
+ for (const output of result.outputs) {
615
+ yield { type: 'output', content: output };
616
+ }
617
+ const finalizedMemory = [
618
+ ...preparedMemory.filter((message) => message.role === 'system'),
619
+ ...result.messages,
620
+ ];
621
+ while (streamQueue.length > 0) {
622
+ yield streamQueue.shift();
623
+ }
624
+ // Update memory with full agent conversation
625
+ this.currentMemory = finalizedMemory;
626
+ // Post result back to Prolog
627
+ stepSucceeded = result.success;
628
+ this.postAgentResult(result, finalizedMemory);
601
629
  }
602
- while (streamQueue.length > 0) {
603
- yield streamQueue.shift();
604
- }
605
- if (process.env.DEBUG_QUEUE) {
606
- console.log('[RUNNER] Non-streaming agent result.outputs:', result.outputs);
607
- }
608
- // Stream any output from the agent
609
- for (const output of result.outputs) {
610
- yield { type: 'output', content: output };
611
- }
612
- const finalizedMemory = [
613
- ...preparedMemory.filter((message) => message.role === 'system'),
614
- ...result.messages,
615
- ];
616
- while (streamQueue.length > 0) {
617
- yield streamQueue.shift();
618
- }
619
- // Update memory with full agent conversation
620
- this.currentMemory = finalizedMemory;
621
- // Post result back to Prolog
622
- this.postAgentResult(result, finalizedMemory);
630
+ }
631
+ finally {
632
+ yield {
633
+ type: 'task_activity',
634
+ taskState: stepSucceeded === true ? 'completed' : 'failed',
635
+ taskId: stepId,
636
+ };
623
637
  }
624
638
  }
625
639
  /**
@@ -632,6 +646,10 @@ export class DMLRunner {
632
646
  const allowedTokens = Array.isArray(rawAllowedTokens)
633
647
  ? rawAllowedTokens.map((token) => String(token))
634
648
  : [];
649
+ const stepId = `step_${this.stepCounter++}`;
650
+ const taskDescription = prompt || 'sample_token';
651
+ yield { type: 'task_activity', taskState: 'started', taskDescription, taskId: stepId };
652
+ let succeeded = false;
635
653
  try {
636
654
  const token = await sampleSingleToken({
637
655
  prompt,
@@ -645,6 +663,7 @@ export class DMLRunner {
645
663
  },
646
664
  signal: options.signal,
647
665
  });
666
+ succeeded = true;
648
667
  this.postSampleTokenResult({ success: true, token });
649
668
  }
650
669
  catch (error) {
@@ -652,6 +671,9 @@ export class DMLRunner {
652
671
  this.postSampleTokenResult({ success: false, error: message });
653
672
  yield { type: 'log', content: `sample_token failed: ${message}` };
654
673
  }
674
+ finally {
675
+ yield { type: 'task_activity', taskState: succeeded ? 'completed' : 'failed', taskId: stepId };
676
+ }
655
677
  }
656
678
  /**
657
679
  * Handle direct one-shot LLM request (llm/2)
@@ -659,6 +681,10 @@ export class DMLRunner {
659
681
  async *handleLlm(payload, options) {
660
682
  const data = payload;
661
683
  const messages = this.extractMessagesFromValue(data.messages);
684
+ const stepId = `step_${this.stepCounter++}`;
685
+ const taskDescription = summarizeLlmMessages(messages);
686
+ yield { type: 'task_activity', taskState: 'started', taskDescription, taskId: stepId };
687
+ let succeeded = false;
662
688
  try {
663
689
  const text = await generateLlmReply({
664
690
  messages,
@@ -672,6 +698,7 @@ export class DMLRunner {
672
698
  },
673
699
  signal: options.signal,
674
700
  });
701
+ succeeded = true;
675
702
  this.postLlmResult({ success: true, text });
676
703
  }
677
704
  catch (error) {
@@ -679,6 +706,9 @@ export class DMLRunner {
679
706
  this.postLlmResult({ success: false, error: message });
680
707
  yield { type: 'log', content: `llm/2 failed: ${message}` };
681
708
  }
709
+ finally {
710
+ yield { type: 'task_activity', taskState: succeeded ? 'completed' : 'failed', taskId: stepId };
711
+ }
682
712
  }
683
713
  /**
684
714
  * Handle exec request (exec() predicate)
@@ -1022,6 +1052,8 @@ export class DMLRunner {
1022
1052
  const allowedTokens = Array.isArray(rawAllowedTokens)
1023
1053
  ? rawAllowedTokens.map((token) => String(token))
1024
1054
  : [];
1055
+ const nestedStepId = `step_${this.stepCounter++}`;
1056
+ onToolEvent?.({ type: 'task_activity', taskState: 'started', taskDescription: prompt || 'sample_token', taskId: nestedStepId });
1025
1057
  try {
1026
1058
  const token = await sampleSingleToken({
1027
1059
  prompt,
@@ -1036,10 +1068,12 @@ export class DMLRunner {
1036
1068
  signal: runContext.signal,
1037
1069
  });
1038
1070
  this.postSampleTokenResult({ success: true, token });
1071
+ onToolEvent?.({ type: 'task_activity', taskState: 'completed', taskId: nestedStepId });
1039
1072
  }
1040
1073
  catch (error) {
1041
1074
  const message = error instanceof Error ? error.message : String(error);
1042
1075
  this.postSampleTokenResult({ success: false, error: message });
1076
+ onToolEvent?.({ type: 'task_activity', taskState: 'failed', taskId: nestedStepId });
1043
1077
  if (process.env.DEBUG_RUNNER) {
1044
1078
  console.log('[RUNNER] sample_token request failed:', message);
1045
1079
  }
@@ -1048,6 +1082,8 @@ export class DMLRunner {
1048
1082
  }
1049
1083
  case 'request_llm': {
1050
1084
  const messages = this.extractMessagesFromValue(payload?.messages);
1085
+ const nestedStepId = `step_${this.stepCounter++}`;
1086
+ onToolEvent?.({ type: 'task_activity', taskState: 'started', taskDescription: summarizeLlmMessages(messages), taskId: nestedStepId });
1051
1087
  try {
1052
1088
  const text = await generateLlmReply({
1053
1089
  messages,
@@ -1062,10 +1098,12 @@ export class DMLRunner {
1062
1098
  signal: runContext.signal,
1063
1099
  });
1064
1100
  this.postLlmResult({ success: true, text });
1101
+ onToolEvent?.({ type: 'task_activity', taskState: 'completed', taskId: nestedStepId });
1065
1102
  }
1066
1103
  catch (error) {
1067
1104
  const message = error instanceof Error ? error.message : String(error);
1068
1105
  this.postLlmResult({ success: false, error: message });
1106
+ onToolEvent?.({ type: 'task_activity', taskState: 'failed', taskId: nestedStepId });
1069
1107
  if (process.env.DEBUG_RUNNER) {
1070
1108
  console.log('[RUNNER] llm/2 request failed:', message);
1071
1109
  }
@@ -1167,6 +1205,8 @@ export class DMLRunner {
1167
1205
  };
1168
1206
  const availableTools = this.buildAgentTools(filteredTools, null, // No policy override for nested
1169
1207
  nestedToolCallback);
1208
+ const nestedStepId = `step_${this.stepCounter++}`;
1209
+ onToolEvent?.({ type: 'task_activity', taskState: 'started', taskDescription, taskId: nestedStepId });
1170
1210
  try {
1171
1211
  // Run the nested agent loop
1172
1212
  const result = await runAgentLoop({
@@ -1216,6 +1256,7 @@ export class DMLRunner {
1216
1256
  ];
1217
1257
  // Post result back to tool engine
1218
1258
  this.postToolAgentResult(toolEngineId, result, finalizedMemory);
1259
+ onToolEvent?.({ type: 'task_activity', taskState: 'completed', taskId: nestedStepId });
1219
1260
  }
1220
1261
  catch (error) {
1221
1262
  const message = error instanceof Error ? error.message : String(error);
@@ -1229,6 +1270,7 @@ export class DMLRunner {
1229
1270
  variables: {},
1230
1271
  messages: preparedMemory.filter((message) => message.role !== 'system'),
1231
1272
  });
1273
+ onToolEvent?.({ type: 'task_activity', taskState: 'failed', taskId: nestedStepId });
1232
1274
  }
1233
1275
  break;
1234
1276
  }
@@ -1486,4 +1528,14 @@ export class DMLRunner {
1486
1528
  this.cleanup();
1487
1529
  }
1488
1530
  }
1531
+ function summarizeLlmMessages(messages) {
1532
+ if (messages.length === 0)
1533
+ return 'llm()';
1534
+ const last = messages[messages.length - 1];
1535
+ const text = typeof last.content === 'string' ? last.content : '';
1536
+ const summary = text.replace(/\s+/g, ' ').trim();
1537
+ if (!summary)
1538
+ return `llm(${messages.length} messages)`;
1539
+ return summary.length > 80 ? summary.slice(0, 77) + '...' : summary;
1540
+ }
1489
1541
  //# sourceMappingURL=runner.js.map