@positronic/core 0.0.60 → 0.0.62

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.
Files changed (36) hide show
  1. package/dist/src/dsl/brain-runner.js +7 -6
  2. package/dist/src/dsl/brain-state-machine.js +42 -9
  3. package/dist/src/dsl/builder/brain.js +33 -121
  4. package/dist/src/dsl/constants.js +4 -1
  5. package/dist/src/dsl/execution/event-stream.js +546 -89
  6. package/dist/src/dsl/execution/retry.js +0 -291
  7. package/dist/src/ui/generate-ui.js +2 -1
  8. package/dist/types/clients/types.d.ts +28 -0
  9. package/dist/types/clients/types.d.ts.map +1 -1
  10. package/dist/types/dsl/brain-runner.d.ts.map +1 -1
  11. package/dist/types/dsl/brain-state-machine.d.ts +12 -0
  12. package/dist/types/dsl/brain-state-machine.d.ts.map +1 -1
  13. package/dist/types/dsl/brain.d.ts +1 -1
  14. package/dist/types/dsl/brain.d.ts.map +1 -1
  15. package/dist/types/dsl/builder/brain.d.ts +7 -4
  16. package/dist/types/dsl/builder/brain.d.ts.map +1 -1
  17. package/dist/types/dsl/constants.d.ts +2 -0
  18. package/dist/types/dsl/constants.d.ts.map +1 -1
  19. package/dist/types/dsl/definitions/blocks.d.ts +20 -1
  20. package/dist/types/dsl/definitions/blocks.d.ts.map +1 -1
  21. package/dist/types/dsl/definitions/events.d.ts +12 -1
  22. package/dist/types/dsl/definitions/events.d.ts.map +1 -1
  23. package/dist/types/dsl/definitions/run-params.d.ts +6 -0
  24. package/dist/types/dsl/definitions/run-params.d.ts.map +1 -1
  25. package/dist/types/dsl/definitions/steps.d.ts +1 -1
  26. package/dist/types/dsl/definitions/steps.d.ts.map +1 -1
  27. package/dist/types/dsl/execution/event-stream.d.ts +9 -0
  28. package/dist/types/dsl/execution/event-stream.d.ts.map +1 -1
  29. package/dist/types/dsl/execution/retry.d.ts +0 -25
  30. package/dist/types/dsl/execution/retry.d.ts.map +1 -1
  31. package/dist/types/dsl/types.d.ts +8 -14
  32. package/dist/types/dsl/types.d.ts.map +1 -1
  33. package/dist/types/index.d.ts +4 -4
  34. package/dist/types/index.d.ts.map +1 -1
  35. package/dist/types/ui/generate-ui.d.ts.map +1 -1
  36. package/package.json +1 -1
@@ -281,7 +281,7 @@ import { DEFAULT_ENV } from './brain.js';
281
281
  * Adds agent context to the deepest level.
282
282
  * Webhook response is no longer passed here - it comes from signals during execution.
283
283
  * This is internal to BrainRunner - external consumers don't need to know about ResumeContext.
284
- */ function executionStackToResumeContext(stack, agentContext) {
284
+ */ function executionStackToResumeContext(stack, agentContext, batchContext) {
285
285
  if (stack.length === 0) {
286
286
  throw new Error('Cannot convert empty execution stack to ResumeContext');
287
287
  }
@@ -290,11 +290,12 @@ import { DEFAULT_ENV } from './brain.js';
290
290
  for(var i = stack.length - 1; i >= 0; i--){
291
291
  var entry = stack[i];
292
292
  if (i === stack.length - 1) {
293
- // Deepest level - add agent context (webhook response comes from signals now)
293
+ // Deepest level - add agent context and batch progress (webhook response comes from signals now)
294
294
  context = {
295
295
  stepIndex: entry.stepIndex,
296
296
  state: entry.state,
297
- agentContext: agentContext !== null && agentContext !== void 0 ? agentContext : undefined
297
+ agentContext: agentContext !== null && agentContext !== void 0 ? agentContext : undefined,
298
+ batchProgress: batchContext !== null && batchContext !== void 0 ? batchContext : undefined
298
299
  };
299
300
  } else {
300
301
  // Outer level - wrap inner context
@@ -409,13 +410,13 @@ export var BrainRunner = /*#__PURE__*/ function() {
409
410
  * Webhook response data comes from signals, not as a parameter.
410
411
  */ function resume(brain, options) {
411
412
  return _async_to_generator(function() {
412
- var machine, brainRunId, brainOptions, endAfter, signal, _machine_context, executionStack, agentContext, resumeContext;
413
+ var machine, brainRunId, brainOptions, endAfter, signal, _machine_context, executionStack, agentContext, batchContext, resumeContext;
413
414
  return _ts_generator(this, function(_state) {
414
415
  machine = options.machine, brainRunId = options.brainRunId, brainOptions = options.options, endAfter = options.endAfter, signal = options.signal;
415
416
  // Build ResumeContext from machine's execution stack
416
417
  // Webhook response comes from signals during execution, not from resume parameters
417
- _machine_context = machine.context, executionStack = _machine_context.executionStack, agentContext = _machine_context.agentContext;
418
- resumeContext = executionStackToResumeContext(executionStack, agentContext);
418
+ _machine_context = machine.context, executionStack = _machine_context.executionStack, agentContext = _machine_context.agentContext, batchContext = _machine_context.batchContext;
419
+ resumeContext = executionStackToResumeContext(executionStack, agentContext, batchContext);
419
420
  return [
420
421
  2,
421
422
  this.execute(brain, {
@@ -125,6 +125,7 @@ var createInitialContext = function(opts) {
125
125
  currentState: (_opts_initialState = opts === null || opts === void 0 ? void 0 : opts.initialState) !== null && _opts_initialState !== void 0 ? _opts_initialState : {},
126
126
  options: (_opts_options = opts === null || opts === void 0 ? void 0 : opts.options) !== null && _opts_options !== void 0 ? _opts_options : {},
127
127
  agentContext: null,
128
+ batchContext: null,
128
129
  status: STATUS.PENDING,
129
130
  isTopLevel: false,
130
131
  isRunning: false,
@@ -318,20 +319,33 @@ var startStep = reduce(function(ctx, param) {
318
319
  });
319
320
  });
320
321
  var completeStep = reduce(function(ctx, param) {
321
- var stepId = param.stepId, patch = param.patch;
322
+ var stepId = param.stepId, stepTitle = param.stepTitle, patch = param.patch, halted = param.halted;
322
323
  var brains = ctx.brains, brainIdStack = ctx.brainIdStack, executionStack = ctx.executionStack, depth = ctx.depth, currentState = ctx.currentState, topLevelStepCount = ctx.topLevelStepCount;
323
324
  if (brainIdStack.length === 0) return ctx;
324
325
  // === NEW: Update flat structures ===
325
326
  var currentBrainId = brainIdStack[brainIdStack.length - 1];
326
327
  var currentBrain = brains[currentBrainId];
327
328
  if (!currentBrain) return ctx;
328
- // Update step status
329
- var newSteps = currentBrain.steps.map(function(s) {
329
+ // Use explicit halted flag from the event
330
+ var isHalted = halted === true;
331
+ // Update step status - HALTED if explicitly marked, COMPLETE otherwise
332
+ var stepStatus = isHalted ? STATUS.HALTED : STATUS.COMPLETE;
333
+ var existingStep = currentBrain.steps.find(function(s) {
334
+ return s.id === stepId;
335
+ });
336
+ var newSteps = existingStep ? currentBrain.steps.map(function(s) {
330
337
  return s.id === stepId ? _object_spread_props(_object_spread({}, s), {
331
- status: STATUS.COMPLETE,
338
+ status: stepStatus,
332
339
  patch: patch
333
340
  }) : s;
334
- });
341
+ }) : _to_consumable_array(currentBrain.steps).concat([
342
+ {
343
+ id: stepId,
344
+ title: stepTitle,
345
+ status: stepStatus,
346
+ patch: patch
347
+ }
348
+ ]);
335
349
  var newBrains = _object_spread_props(_object_spread({}, brains), _define_property({}, currentBrainId, _object_spread_props(_object_spread({}, currentBrain), {
336
350
  steps: newSteps
337
351
  })));
@@ -339,7 +353,7 @@ var completeStep = reduce(function(ctx, param) {
339
353
  var newExecutionStack = executionStack;
340
354
  if (executionStack.length > 0) {
341
355
  var topEntry = executionStack[executionStack.length - 1];
342
- var newState = patch ? applyPatches(topEntry.state, [
356
+ var newState = patch && !isHalted ? applyPatches(topEntry.state, [
343
357
  patch
344
358
  ]) : topEntry.state;
345
359
  // Increment stepIndex so resume knows to start from the NEXT step
@@ -351,9 +365,10 @@ var completeStep = reduce(function(ctx, param) {
351
365
  ]);
352
366
  }
353
367
  // Apply patch to currentState only for top-level brain (for backwards compat)
368
+ // Skipped steps don't change state or count toward topLevelStepCount
354
369
  var newState1 = currentState;
355
370
  var newStepCount = topLevelStepCount;
356
- if (depth === 1 && patch) {
371
+ if (depth === 1 && patch && !isHalted) {
357
372
  newState1 = applyPatches(currentState, [
358
373
  patch
359
374
  ]);
@@ -363,7 +378,8 @@ var completeStep = reduce(function(ctx, param) {
363
378
  brains: newBrains,
364
379
  executionStack: newExecutionStack,
365
380
  currentState: newState1,
366
- topLevelStepCount: newStepCount
381
+ topLevelStepCount: newStepCount,
382
+ batchContext: null
367
383
  });
368
384
  });
369
385
  var webhookPause = reduce(function(ctx, param) {
@@ -430,6 +446,22 @@ var passthrough = function() {
430
446
  return ctx;
431
447
  });
432
448
  };
449
+ // Reducer for BATCH_CHUNK_COMPLETE - merges chunk results into batchContext
450
+ var batchChunkComplete = reduce(function(ctx, payload) {
451
+ var existing = ctx.batchContext;
452
+ var newResults = (existing === null || existing === void 0 ? void 0 : existing.accumulatedResults) ? _to_consumable_array(existing.accumulatedResults) : [];
453
+ for(var i = 0; i < payload.chunkResults.length; i++){
454
+ newResults[payload.chunkStartIndex + i] = payload.chunkResults[i];
455
+ }
456
+ return _object_spread_props(_object_spread({}, ctx), {
457
+ batchContext: {
458
+ accumulatedResults: newResults,
459
+ processedCount: payload.processedCount,
460
+ totalItems: payload.totalItems,
461
+ schemaName: payload.schemaName
462
+ }
463
+ });
464
+ });
433
465
  // Reducer for agent iteration events that tracks tokens per-iteration
434
466
  // This ensures tokens are counted even if the agent doesn't complete (e.g., webhook interruption)
435
467
  var agentIteration = reduce(function(ctx, ev) {
@@ -536,7 +568,8 @@ var makeBrainMachine = function(initialContext) {
536
568
  transition(BRAIN_EVENTS.PAUSED, 'paused', pauseBrain), // Webhook -> waiting (for non-agent webhooks)
537
569
  transition(BRAIN_EVENTS.WEBHOOK, 'waiting', webhookPause), // Webhook response (for resume from non-agent webhook)
538
570
  transition(BRAIN_EVENTS.WEBHOOK_RESPONSE, 'running', webhookResponse), // Step events
539
- transition(BRAIN_EVENTS.STEP_START, 'running', startStep), transition(BRAIN_EVENTS.STEP_COMPLETE, 'running', completeStep), transition(BRAIN_EVENTS.STEP_STATUS, 'running', stepStatus), transition(BRAIN_EVENTS.STEP_RETRY, 'running', stepRetry), // AGENT_START transitions to the agentLoop state
571
+ transition(BRAIN_EVENTS.STEP_START, 'running', startStep), transition(BRAIN_EVENTS.STEP_COMPLETE, 'running', completeStep), transition(BRAIN_EVENTS.STEP_STATUS, 'running', stepStatus), transition(BRAIN_EVENTS.STEP_RETRY, 'running', stepRetry), // Batch chunk complete - stays in running, accumulates results
572
+ transition(BRAIN_EVENTS.BATCH_CHUNK_COMPLETE, 'running', batchChunkComplete), // AGENT_START transitions to the agentLoop state
540
573
  transition(BRAIN_EVENTS.AGENT_START, 'agentLoop', agentStart)),
541
574
  // Explicit agent loop state - isolates agent execution logic
542
575
  agentLoop: state.apply(void 0, // Spread agent micro-transitions
@@ -375,7 +375,6 @@ function _ts_values(o) {
375
375
  }
376
376
  import { z } from 'zod';
377
377
  import { BrainEventStream } from '../execution/event-stream.js';
378
- import { Semaphore, normalizeRetryConfig, executeWithRetry } from '../execution/retry.js';
379
378
  export var Brain = /*#__PURE__*/ function() {
380
379
  "use strict";
381
380
  function Brain(title, description) {
@@ -413,6 +412,11 @@ export var Brain = /*#__PURE__*/ function() {
413
412
  type: 'agent',
414
413
  title: block.title
415
414
  };
415
+ } else if (block.type === 'guard') {
416
+ return {
417
+ type: 'guard',
418
+ title: block.title
419
+ };
416
420
  } else {
417
421
  // block.type === 'brain'
418
422
  return {
@@ -543,6 +547,18 @@ export var Brain = /*#__PURE__*/ function() {
543
547
  return this.nextBrain();
544
548
  }
545
549
  },
550
+ {
551
+ key: "guard",
552
+ value: function guard(predicate, title) {
553
+ var guardBlock = {
554
+ type: 'guard',
555
+ title: title !== null && title !== void 0 ? title : 'Guard',
556
+ predicate: predicate
557
+ };
558
+ this.blocks.push(guardBlock);
559
+ return this.nextBrain();
560
+ }
561
+ },
546
562
  {
547
563
  // Implementation
548
564
  key: "brain",
@@ -635,134 +651,30 @@ export var Brain = /*#__PURE__*/ function() {
635
651
  // At this point, outputSchema is guaranteed to exist (schema-less case returned early)
636
652
  var outputSchema = config.outputSchema;
637
653
  if (batchConfig) {
638
- // Batch mode - run prompt for each item
654
+ // Batch mode - store config on block for event-stream to execute with per-item events
639
655
  var promptBlock1 = {
640
656
  type: 'step',
641
657
  title: title,
642
658
  action: function(param) {
643
- var state = param.state, runClient = param.client, resources = param.resources;
659
+ var state = param.state;
644
660
  return _async_to_generator(function() {
645
- var template, stepClient, schema, schemaName, client, items, _batchConfig_concurrency, semaphore, _batchConfig_stagger, stagger, retryConfig, results, sleep, promises, finalResults;
646
661
  return _ts_generator(this, function(_state) {
647
- switch(_state.label){
648
- case 0:
649
- template = config.template, stepClient = config.client;
650
- schema = outputSchema.schema, schemaName = outputSchema.name;
651
- client = stepClient !== null && stepClient !== void 0 ? stepClient : runClient;
652
- items = batchConfig.over(state);
653
- semaphore = new Semaphore((_batchConfig_concurrency = batchConfig.concurrency) !== null && _batchConfig_concurrency !== void 0 ? _batchConfig_concurrency : 10);
654
- stagger = (_batchConfig_stagger = batchConfig.stagger) !== null && _batchConfig_stagger !== void 0 ? _batchConfig_stagger : 0;
655
- retryConfig = normalizeRetryConfig(batchConfig.retry);
656
- results = new Array(items.length);
657
- sleep = function(ms) {
658
- return new Promise(function(r) {
659
- return setTimeout(r, ms);
660
- });
661
- };
662
- promises = items.map(function(item, index) {
663
- return _async_to_generator(function() {
664
- var promptText, output, error, fallback;
665
- return _ts_generator(this, function(_state) {
666
- switch(_state.label){
667
- case 0:
668
- if (!(stagger > 0 && index > 0)) return [
669
- 3,
670
- 2
671
- ];
672
- return [
673
- 4,
674
- sleep(stagger * index)
675
- ];
676
- case 1:
677
- _state.sent();
678
- _state.label = 2;
679
- case 2:
680
- return [
681
- 4,
682
- semaphore.acquire()
683
- ];
684
- case 3:
685
- _state.sent();
686
- _state.label = 4;
687
- case 4:
688
- _state.trys.push([
689
- 4,
690
- 7,
691
- 8,
692
- 9
693
- ]);
694
- return [
695
- 4,
696
- template(item, resources)
697
- ];
698
- case 5:
699
- promptText = _state.sent();
700
- return [
701
- 4,
702
- executeWithRetry(function() {
703
- return client.generateObject({
704
- schema: schema,
705
- schemaName: schemaName,
706
- prompt: promptText
707
- });
708
- }, retryConfig)
709
- ];
710
- case 6:
711
- output = _state.sent();
712
- results[index] = [
713
- item,
714
- output
715
- ];
716
- return [
717
- 3,
718
- 9
719
- ];
720
- case 7:
721
- error = _state.sent();
722
- if (batchConfig.error) {
723
- fallback = batchConfig.error(item, error);
724
- if (fallback !== null) {
725
- results[index] = [
726
- item,
727
- fallback
728
- ];
729
- }
730
- } else {
731
- throw error;
732
- }
733
- return [
734
- 3,
735
- 9
736
- ];
737
- case 8:
738
- semaphore.release();
739
- return [
740
- 7
741
- ];
742
- case 9:
743
- return [
744
- 2
745
- ];
746
- }
747
- });
748
- })();
749
- });
750
- return [
751
- 4,
752
- Promise.all(promises)
753
- ];
754
- case 1:
755
- _state.sent();
756
- finalResults = results.filter(function(r) {
757
- return r !== undefined;
758
- });
759
- return [
760
- 2,
761
- _object_spread_props(_object_spread({}, state), _define_property({}, outputSchema.name, finalResults))
762
- ];
763
- }
662
+ return [
663
+ 2,
664
+ state
665
+ ];
764
666
  });
765
667
  })();
668
+ },
669
+ batchConfig: {
670
+ over: batchConfig.over,
671
+ maxRetries: batchConfig.maxRetries,
672
+ error: batchConfig.error,
673
+ template: config.template,
674
+ schema: outputSchema.schema,
675
+ schemaName: outputSchema.name,
676
+ client: config.client,
677
+ chunkSize: batchConfig.chunkSize
766
678
  }
767
679
  };
768
680
  this.blocks.push(promptBlock1);
@@ -25,7 +25,9 @@ export var BRAIN_EVENTS = {
25
25
  AGENT_ITERATION_LIMIT: 'agent:iteration_limit',
26
26
  AGENT_WEBHOOK: 'agent:webhook',
27
27
  AGENT_RAW_RESPONSE_MESSAGE: 'agent:raw_response_message',
28
- AGENT_USER_MESSAGE: 'agent:user_message'
28
+ AGENT_USER_MESSAGE: 'agent:user_message',
29
+ // Batch prompt events (prompt with `over`)
30
+ BATCH_CHUNK_COMPLETE: 'batch:chunk_complete'
29
31
  };
30
32
  export var STATUS = {
31
33
  PENDING: 'pending',
@@ -35,6 +37,7 @@ export var STATUS = {
35
37
  CANCELLED: 'cancelled',
36
38
  WAITING: 'waiting',
37
39
  PAUSED: 'paused',
40
+ HALTED: 'halted',
38
41
  // Internal status for tracking when execution is inside an agent loop.
39
42
  // Publicly this maps to RUNNING for consumers.
40
43
  AGENT_LOOP: 'agent_loop'