@dereekb/openrouter 14.7.0 → 14.9.0

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.
@@ -1,6 +1,6 @@
1
1
  import { firestoreModelId, firestoreModelKeyParentKey, getDocumentSnapshotDataTuples } from '@dereekb/firebase';
2
- import { runAsyncTasksForValues, mergeObjects, KeyValueTypleValueFilter, concatArraysUnique, MS_IN_MINUTE, arrayToMap, expiringCachedGetter, filterMaybeArrayValues, filterUniqueValues, mergeArrays, addMilliseconds, filterUndefinedValues, randomNumberFactory, performTasksInParallel } from '@dereekb/util';
3
- import { validateOpenRouterModelConfig, openRouterPromptRequest, callModelForOpenRouterRequest, openRouterMessagesWithoutFileAttachmentData, openRouterMessagesWithFreshFileAttachments, openRouterInputMessages, openRouterFunctionCallOutputItems } from '@dereekb/openrouter';
2
+ import { runAsyncTasksForValues, mergeObjects, KeyValueTypleValueFilter, concatArraysUnique, MS_IN_MINUTE, arrayToMap, expiringCachedGetter, filterMaybeArrayValues, addMilliseconds, filterUniqueValues, mergeArrays, filterUndefinedValues, randomNumberFactory, performTasksInParallel } from '@dereekb/util';
3
+ import { validateOpenRouterModelConfig, validateOpenRouterDecisionQuestions, openRouterPromptRequest, callModelForOpenRouterRequest, openRouterDecisionRequest, openRouterDecision, openRouterMessagesWithoutFileAttachmentData, openRouterMessagesWithFreshFileAttachments, openRouterInputMessages, openRouterFunctionCallOutputItems } from '@dereekb/openrouter';
4
4
  import { updateOpenRouterPromptParamsType, readOpenRouterPromptParamsType, createOpenRouterPromptVersionParamsType, updateOpenRouterPromptVersionParamsType, OpenRouterPromptState, openRouterPromptVersionId, openRouterResolvedPromptForVersion, OpenRouterRunTaskState, openRouterRunTasksRunnableQuery, openRouterRunTasksReclaimableQuery, OPENROUTER_RUN_TASK_MAX_AGE, openRouterRunTasksExpiredQuery, isOpenRouterRunTaskStateTerminal } from '@dereekb/openrouter/firebase';
5
5
 
6
6
  function _array_like_to_array$2(arr, len) {
@@ -299,9 +299,9 @@ function _unsupported_iterable_to_array$2(o, minLen) {
299
299
  var firebaseServerActionTransformFunctionFactory = context.firebaseServerActionTransformFunctionFactory, openRouterPromptCollection = context.openRouterPromptCollection, openRouterPromptVersionCollectionFactory = context.openRouterPromptVersionCollectionFactory, openRouterPromptService = context.openRouterPromptService;
300
300
  return firebaseServerActionTransformFunctionFactory(updateOpenRouterPromptParamsType, function(params) {
301
301
  return _async_to_generator$8(function() {
302
- var name, description, tags, state, activeVersion;
302
+ var name, description, tags, state, activeVersion, storeLocked;
303
303
  return _ts_generator$8(this, function(_state) {
304
- name = params.name, description = params.description, tags = params.tags, state = params.state, activeVersion = params.activeVersion;
304
+ name = params.name, description = params.description, tags = params.tags, state = params.state, activeVersion = params.activeVersion, storeLocked = params.storeLocked;
305
305
  return [
306
306
  2,
307
307
  function(document) {
@@ -353,6 +353,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
353
353
  t: tags,
354
354
  s: state !== null && state !== void 0 ? state : undefined,
355
355
  av: activeVersion,
356
+ sl: storeLocked,
356
357
  uat: new Date()
357
358
  })
358
359
  ];
@@ -423,7 +424,9 @@ function _unsupported_iterable_to_array$2(o, minLen) {
423
424
  2
424
425
  ]), prompt = _ref[0], resolution = _ref[1];
425
426
  resolved = resolution.resolved, source = resolution.source;
426
- validation = validateOpenRouterModelConfig(resolved.config);
427
+ validation = validateOpenRouterModelConfig(resolved.config, {
428
+ decision: resolved.questions != null
429
+ });
427
430
  result = {
428
431
  prompt: prompt !== null && prompt !== void 0 ? prompt : null,
429
432
  resolved: resolved,
@@ -457,22 +460,31 @@ function _unsupported_iterable_to_array$2(o, minLen) {
457
460
  var firebaseServerActionTransformFunctionFactory = context.firebaseServerActionTransformFunctionFactory, openRouterPromptCollection = context.openRouterPromptCollection, openRouterPromptVersionCollectionFactory = context.openRouterPromptVersionCollectionFactory, openRouterPromptService = context.openRouterPromptService;
458
461
  return firebaseServerActionTransformFunctionFactory(createOpenRouterPromptVersionParamsType, function(params) {
459
462
  return _async_to_generator$8(function() {
460
- var instructions, messages, config, notes, activate;
463
+ var instructions, messages, config, questions, notes, activate;
461
464
  return _ts_generator$8(this, function(_state) {
462
- instructions = params.instructions, messages = params.messages, config = params.config, notes = params.notes, activate = params.activate;
465
+ instructions = params.instructions, messages = params.messages, config = params.config, questions = params.questions, notes = params.notes, activate = params.activate;
463
466
  return [
464
467
  2,
465
468
  function(document) {
466
469
  return _async_to_generator$8(function() {
467
- var modelConfig, validation, result;
470
+ var modelConfig, modelQuestions, validation, questionValidation, result;
468
471
  return _ts_generator$8(this, function(_state) {
469
472
  switch(_state.label){
470
473
  case 0:
471
474
  modelConfig = config !== null && config !== void 0 ? config : undefined;
472
- validation = validateOpenRouterModelConfig(modelConfig !== null && modelConfig !== void 0 ? modelConfig : {});
475
+ modelQuestions = questions !== null && questions !== void 0 ? questions : undefined;
476
+ validation = validateOpenRouterModelConfig(modelConfig !== null && modelConfig !== void 0 ? modelConfig : {}, {
477
+ decision: modelQuestions != null
478
+ });
473
479
  if (!validation.valid) {
474
480
  throw new Error('Cannot create a version of OpenRouterPrompt "'.concat(document.id, '": ').concat(validation.errors.join(' ')));
475
481
  }
482
+ if (modelQuestions != null) {
483
+ questionValidation = validateOpenRouterDecisionQuestions(modelQuestions);
484
+ if (!questionValidation.valid) {
485
+ throw new Error('Cannot create a version of OpenRouterPrompt "'.concat(document.id, '": ').concat(questionValidation.errors.join(' ')));
486
+ }
487
+ }
476
488
  return [
477
489
  4,
478
490
  openRouterPromptCollection.firestoreContext.runTransaction(function(transaction) {
@@ -532,6 +544,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
532
544
  };
533
545
  }),
534
546
  c: modelConfig,
547
+ q: modelQuestions,
535
548
  nt: notes
536
549
  };
537
550
  if (!(previousVersionDocument != null && previousVersionExists)) return [
@@ -611,23 +624,24 @@ function _unsupported_iterable_to_array$2(o, minLen) {
611
624
  var firebaseServerActionTransformFunctionFactory = context.firebaseServerActionTransformFunctionFactory, openRouterPromptCollection = context.openRouterPromptCollection, openRouterPromptVersionCollectionGroup = context.openRouterPromptVersionCollectionGroup, openRouterPromptService = context.openRouterPromptService;
612
625
  return firebaseServerActionTransformFunctionFactory(updateOpenRouterPromptVersionParamsType, function(params) {
613
626
  return _async_to_generator$8(function() {
614
- var instructions, messages, config, notes;
627
+ var instructions, messages, config, questions, notes;
615
628
  return _ts_generator$8(this, function(_state) {
616
- instructions = params.instructions, messages = params.messages, config = params.config, notes = params.notes;
629
+ instructions = params.instructions, messages = params.messages, config = params.config, questions = params.questions, notes = params.notes;
617
630
  return [
618
631
  2,
619
632
  function(document) {
620
633
  return _async_to_generator$8(function() {
621
- var inputConfig, validation;
634
+ var inputConfig, inputQuestions, validation;
622
635
  return _ts_generator$8(this, function(_state) {
623
636
  switch(_state.label){
624
637
  case 0:
625
638
  inputConfig = config;
639
+ inputQuestions = questions;
626
640
  return [
627
641
  4,
628
642
  openRouterPromptCollection.firestoreContext.runTransaction(function(transaction) {
629
643
  return _async_to_generator$8(function() {
630
- var _ref, inTransaction, version, result;
644
+ var _ref, inTransaction, version, nextQuestions, result, questionValidation;
631
645
  return _ts_generator$8(this, function(_state) {
632
646
  switch(_state.label){
633
647
  case 0:
@@ -648,10 +662,22 @@ function _unsupported_iterable_to_array$2(o, minLen) {
648
662
  // touches only the instructions must not be judged against an empty config and refused for
649
663
  // naming no model. An explicitly null config is judged as the empty config it would leave behind,
650
664
  // which is exactly the refusal that should happen.
651
- result = validateOpenRouterModelConfig((_ref = config === undefined ? version.c : inputConfig) !== null && _ref !== void 0 ? _ref : {});
665
+ // The same "judge what it will SAY" rule applied to the questions: an omitted `questions` leaves
666
+ // the version's own, so an edit touching only the instructions is still judged as the decision
667
+ // it remains rather than as a completion that names a System One model.
668
+ nextQuestions = questions === undefined ? version.q : inputQuestions;
669
+ result = validateOpenRouterModelConfig((_ref = config === undefined ? version.c : inputConfig) !== null && _ref !== void 0 ? _ref : {}, {
670
+ decision: nextQuestions != null
671
+ });
652
672
  if (!result.valid) {
653
673
  throw new Error('Cannot update OpenRouterPromptVersion "'.concat(document.key, '": ').concat(result.errors.join(' ')));
654
674
  }
675
+ if (nextQuestions != null) {
676
+ questionValidation = validateOpenRouterDecisionQuestions(nextQuestions);
677
+ if (!questionValidation.valid) {
678
+ throw new Error('Cannot update OpenRouterPromptVersion "'.concat(document.key, '": ').concat(questionValidation.errors.join(' ')));
679
+ }
680
+ }
655
681
  // Undefined fields are stripped before the write, so an omitted field is left as it was. `null`
656
682
  // is passed through for the fields that can meaningfully carry nothing.
657
683
  return [
@@ -666,6 +692,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
666
692
  };
667
693
  }),
668
694
  c: inputConfig,
695
+ q: inputQuestions,
669
696
  nt: notes
670
697
  })
671
698
  ];
@@ -753,7 +780,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
753
780
  * @returns What the write did.
754
781
  */ function seedTarget(target) {
755
782
  return _async_to_generator$8(function() {
756
- var _ref, definition, promptDocument, prompt, promptKey, version, latestVersion, archived, outcome, versionCollection, versionAccessor, targetVersionId, targetVersionExists, _definition_messages, previousVersionId, previousVersionExists, _tmp, versionData, writeBatch, versionWriteAccessor, promptWriteDocument;
783
+ var _ref, definition, promptDocument, prompt, promptKey, version, latestVersion, archived, storeLocked, outcome, versionCollection, versionAccessor, targetVersionId, targetVersionExists, _definition_messages, previousVersionId, previousVersionExists, _tmp, versionData, writeBatch, versionWriteAccessor, promptWriteDocument;
757
784
  return _ts_generator$8(this, function(_state) {
758
785
  switch(_state.label){
759
786
  case 0:
@@ -764,6 +791,11 @@ function _unsupported_iterable_to_array$2(o, minLen) {
764
791
  // reseed silently undoing it is the same class of bug as reverting an operator's rename. Decided
765
792
  // from the prompt alone, so an archived definition costs no further read.
766
793
  archived = (prompt === null || prompt === void 0 ? void 0 : prompt.s) === OpenRouterPromptState.ARCHIVED;
794
+ // A STORE-LOCKED prompt is the same rule pointed at a different writer: its content is maintained
795
+ // at runtime, so code publishing over it would silently discard an operator's work. Reported as a
796
+ // warning rather than skipped in silence, because a definition whose version has moved ahead and
797
+ // never lands otherwise looks exactly like a seed that ran and did nothing.
798
+ storeLocked = (prompt === null || prompt === void 0 ? void 0 : prompt.sl) === true;
767
799
  if (!archived) return [
768
800
  3,
769
801
  1
@@ -771,9 +803,20 @@ function _unsupported_iterable_to_array$2(o, minLen) {
771
803
  outcome = 'skipped';
772
804
  return [
773
805
  3,
774
- 15
806
+ 16
775
807
  ];
776
808
  case 1:
809
+ if (!storeLocked) return [
810
+ 3,
811
+ 2
812
+ ];
813
+ warnings.push("".concat(promptKey, ": the prompt is store-locked, so the definition declaring version ").concat(version, " was not published. Unset `storeLocked` to let code seed it again."));
814
+ outcome = 'skipped';
815
+ return [
816
+ 3,
817
+ 16
818
+ ];
819
+ case 2:
777
820
  versionCollection = openRouterPromptVersionCollectionFactory(promptDocument);
778
821
  versionAccessor = versionCollection.documentAccessor();
779
822
  targetVersionId = openRouterPromptVersionId(version);
@@ -781,11 +824,11 @@ function _unsupported_iterable_to_array$2(o, minLen) {
781
824
  4,
782
825
  versionAccessor.loadDocumentForId(targetVersionId).accessor.exists()
783
826
  ];
784
- case 2:
827
+ case 3:
785
828
  targetVersionExists = _state.sent();
786
829
  if (!(version > latestVersion && !targetVersionExists)) return [
787
830
  3,
788
- 14
831
+ 15
789
832
  ];
790
833
  // The outgoing head's address comes from the prompt's own `lv`, and `version > latestVersion`
791
834
  // above is what guarantees it is not the document about to be written. Existence-checked
@@ -794,22 +837,22 @@ function _unsupported_iterable_to_array$2(o, minLen) {
794
837
  previousVersionId = latestVersion > 0 ? openRouterPromptVersionId(latestVersion) : undefined;
795
838
  if (!(previousVersionId == null)) return [
796
839
  3,
797
- 3
840
+ 4
798
841
  ];
799
842
  _tmp = false;
800
843
  return [
801
844
  3,
802
- 5
845
+ 6
803
846
  ];
804
- case 3:
847
+ case 4:
805
848
  return [
806
849
  4,
807
850
  versionAccessor.loadDocumentForId(previousVersionId).accessor.exists()
808
851
  ];
809
- case 4:
810
- _tmp = _state.sent();
811
- _state.label = 5;
812
852
  case 5:
853
+ _tmp = _state.sent();
854
+ _state.label = 6;
855
+ case 6:
813
856
  previousVersionExists = _tmp;
814
857
  versionData = {
815
858
  cat: new Date(),
@@ -823,6 +866,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
823
866
  };
824
867
  }),
825
868
  c: definition.config,
869
+ q: definition.questions,
826
870
  nt: "Seeded from the code definition declaring version ".concat(version, ".")
827
871
  };
828
872
  // One batch for this definition and nothing else. Atomic, so a prompt never ends up pointing
@@ -833,7 +877,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
833
877
  promptWriteDocument = openRouterPromptCollection.documentAccessorForWriteBatch(writeBatch).loadDocumentForId(promptKey);
834
878
  if (!(previousVersionId != null && previousVersionExists)) return [
835
879
  3,
836
- 7
880
+ 8
837
881
  ];
838
882
  return [
839
883
  4,
@@ -841,20 +885,23 @@ function _unsupported_iterable_to_array$2(o, minLen) {
841
885
  lk: true
842
886
  })
843
887
  ];
844
- case 6:
845
- _state.sent();
846
- _state.label = 7;
847
888
  case 7:
889
+ _state.sent();
890
+ _state.label = 8;
891
+ case 8:
848
892
  return [
849
893
  4,
850
894
  versionWriteAccessor.loadDocumentForId(targetVersionId).accessor.set(versionData)
851
895
  ];
852
- case 8:
896
+ case 9:
853
897
  _state.sent();
854
898
  if (!(prompt == null)) return [
855
899
  3,
856
- 10
900
+ 11
857
901
  ];
902
+ // `storeLocked` is written ONLY here, on create. A definition cannot lock a prompt it did
903
+ // not create: doing so would let code seize one an operator is already maintaining, which
904
+ // is the exact thing the flag exists to prevent in the other direction.
858
905
  return [
859
906
  4,
860
907
  promptWriteDocument.accessor.set({
@@ -863,16 +910,17 @@ function _unsupported_iterable_to_array$2(o, minLen) {
863
910
  d: definition.description,
864
911
  s: OpenRouterPromptState.ACTIVE,
865
912
  lv: version,
866
- av: version
913
+ av: version,
914
+ sl: definition.storeLocked
867
915
  })
868
916
  ];
869
- case 9:
917
+ case 10:
870
918
  _state.sent();
871
919
  return [
872
920
  3,
873
- 12
921
+ 13
874
922
  ];
875
- case 10:
923
+ case 11:
876
924
  // `n`/`d`/`t` are deliberately untouched: they are operator-editable through
877
925
  // updateOpenRouterPrompt, and a scheduled reseed reverting a rename is a silent regression.
878
926
  return [
@@ -884,15 +932,15 @@ function _unsupported_iterable_to_array$2(o, minLen) {
884
932
  uat: new Date()
885
933
  })
886
934
  ];
887
- case 11:
888
- _state.sent();
889
- _state.label = 12;
890
935
  case 12:
936
+ _state.sent();
937
+ _state.label = 13;
938
+ case 13:
891
939
  return [
892
940
  4,
893
941
  writeBatch.commit()
894
942
  ];
895
- case 13:
943
+ case 14:
896
944
  _state.sent();
897
945
  // Only the prompts that actually changed, and only once the commit landed. Missing this
898
946
  // leaves a scheduled reseed invisible for the whole OPENROUTER_PROMPT_CACHE_DURATION window.
@@ -900,15 +948,15 @@ function _unsupported_iterable_to_array$2(o, minLen) {
900
948
  outcome = prompt == null ? 'created' : 'published';
901
949
  return [
902
950
  3,
903
- 15
951
+ 16
904
952
  ];
905
- case 14:
953
+ case 15:
906
954
  // The only way to land on `upToDate` is a prompt whose `lv` already covers the declared
907
955
  // number AND whose document at that number is present — anything else is drift the seed
908
956
  // refuses to paper over by overwriting a number someone else wrote.
909
957
  outcome = version > latestVersion || !targetVersionExists ? 'skipped' : 'upToDate';
910
- _state.label = 15;
911
- case 15:
958
+ _state.label = 16;
959
+ case 16:
912
960
  return [
913
961
  2,
914
962
  outcome
@@ -938,13 +986,26 @@ function _unsupported_iterable_to_array$2(o, minLen) {
938
986
  if (!Number.isInteger(version) || version < 1) {
939
987
  throw new Error('Cannot seed OpenRouterPrompt "'.concat(promptKey, '": the definition declares version ').concat(version, ", which is not an integer >= 1."));
940
988
  }
941
- var validation = validateOpenRouterModelConfig(config);
989
+ var decision = definition.questions != null;
990
+ var validation = validateOpenRouterModelConfig(config, {
991
+ decision: decision
992
+ });
942
993
  if (!validation.valid) {
943
994
  throw new Error('Cannot seed OpenRouterPrompt "'.concat(promptKey, '": ').concat(validation.errors.join(' ')));
944
995
  }
945
996
  validation.warnings.forEach(function(warning) {
946
997
  return warnings.push("".concat(promptKey, ": ").concat(warning));
947
998
  });
999
+ if (decision) {
1000
+ // A malformed question map is refused HERE rather than at the wire. The limits it enforces are
1001
+ // quiet ones — an eleven-level Score looks entirely reasonable and is rejected by the route — so
1002
+ // a seed that published one would produce a prompt that resolves, validates, and then fails
1003
+ // every time it is asked.
1004
+ var questionValidation = validateOpenRouterDecisionQuestions(definition.questions);
1005
+ if (!questionValidation.valid) {
1006
+ throw new Error('Cannot seed OpenRouterPrompt "'.concat(promptKey, '": ').concat(questionValidation.errors.join(' ')));
1007
+ }
1008
+ }
948
1009
  });
949
1010
  // Every prompt document up front, in one pass, before a single write: the addresses are the keys the
950
1011
  // definitions declare, so they all resolve together, and reading them here is what lets the write
@@ -1443,6 +1504,55 @@ function _ts_generator$6(thisArg, body) {
1443
1504
  });
1444
1505
  })();
1445
1506
  }
1507
+ /**
1508
+ * Asks a decision prompt INLINE and returns its answers, with no run task document.
1509
+ *
1510
+ * The default way to ask a decision. A System One call typically answers in around a hundred
1511
+ * milliseconds, has no tools to loop and nothing to defer, so the queue's lease, sweep interval and
1512
+ * retry ladder buy nothing on the happy path — paying for a document to run a call that finishes before
1513
+ * the write does is pure overhead.
1514
+ *
1515
+ * Reach for `enqueueRunTask({ state, questions, immediate: true })` instead when a FAILURE needs to
1516
+ * survive this process: that keeps the same run-it-now latency and leaves a retryable failure queued for
1517
+ * the sweep, at the cost of one document per run.
1518
+ *
1519
+ * @param params - The client, prompt service, prompt, state, and questions.
1520
+ * @returns The decision result.
1521
+ */ function decideForPrompt(params) {
1522
+ return _async_to_generator$6(function() {
1523
+ var client, promptService, promptKey, version, state, questions, configOverrides, sessionId, trace, prompt, request;
1524
+ return _ts_generator$6(this, function(_state) {
1525
+ switch(_state.label){
1526
+ case 0:
1527
+ client = params.client, promptService = params.promptService, promptKey = params.promptKey, version = params.version, state = params.state, questions = params.questions, configOverrides = params.configOverrides, sessionId = params.sessionId, trace = params.trace;
1528
+ return [
1529
+ 4,
1530
+ promptService.resolvePrompt({
1531
+ promptKey: promptKey,
1532
+ version: version
1533
+ })
1534
+ ];
1535
+ case 1:
1536
+ prompt = _state.sent();
1537
+ request = openRouterDecisionRequest({
1538
+ prompt: prompt,
1539
+ state: state,
1540
+ questions: questions,
1541
+ overrides: configOverrides,
1542
+ sessionId: sessionId,
1543
+ trace: trace
1544
+ });
1545
+ return [
1546
+ 2,
1547
+ openRouterDecision({
1548
+ client: client,
1549
+ request: request
1550
+ })
1551
+ ];
1552
+ }
1553
+ });
1554
+ })();
1555
+ }
1446
1556
 
1447
1557
  function asyncGeneratorStep$5(gen, resolve, reject, _next, _throw, key, arg) {
1448
1558
  try {
@@ -2165,11 +2275,17 @@ function _wrap_native_super(Class) {
2165
2275
  8
2166
2276
  ];
2167
2277
  case 5:
2168
- if (!(definition != null && (storedActiveVersion == null || definition.version > storedActiveVersion))) return [
2278
+ if (!(definition != null && (storedActiveVersion == null || definition.version > storedActiveVersion && (prompt === null || prompt === void 0 ? void 0 : prompt.sl) !== true))) return [
2169
2279
  3,
2170
2280
  6
2171
2281
  ];
2172
2282
  // Unpinned, and code is either standing in for the store or ahead of it.
2283
+ //
2284
+ // A STORE-LOCKED prompt (`sl`) cannot be overtaken: past this point the store is the source of
2285
+ // truth, and a definition whose version has moved ahead is ignored rather than served. It can
2286
+ // still STAND IN when the store holds nothing at all, which is what keeps a fresh environment —
2287
+ // an emulator, a test, a project that has never been seeded — able to serve the prompt with no
2288
+ // manual step first. The lock defends against being overwritten, not against being served.
2173
2289
  resolved = definition;
2174
2290
  source = 'definition';
2175
2291
  return [
@@ -2203,7 +2319,11 @@ function _wrap_native_super(Class) {
2203
2319
  }
2204
2320
  }
2205
2321
  if (rejectInvalidConfig) {
2206
- validation = validateOpenRouterModelConfig(resolved.config);
2322
+ // Which arm the version belongs to is read off the version itself: a version carrying questions is
2323
+ // a decision and needs a System One model, one without is a completion and must not have one.
2324
+ validation = validateOpenRouterModelConfig(resolved.config, {
2325
+ decision: resolved.questions != null
2326
+ });
2207
2327
  if (!validation.valid) {
2208
2328
  throw new OpenRouterPromptResolutionError(promptKey, "has an invalid config: ".concat(validation.errors.join(' ')), resolved.version);
2209
2329
  }
@@ -2460,6 +2580,33 @@ function _ts_generator$3(thisArg, body) {
2460
2580
  };
2461
2581
  }
2462
2582
  }
2583
+ /**
2584
+ * Whether a run task is a DECISION run.
2585
+ *
2586
+ * Reads the state field, which is the discriminator — see `OpenRouterRunTask.st`.
2587
+ *
2588
+ * @param task - The run task.
2589
+ * @returns True when the task asks a decision rather than a completion.
2590
+ *
2591
+ * @__NO_SIDE_EFFECTS__
2592
+ */ function isOpenRouterDecisionRunTask(task) {
2593
+ return (task === null || task === void 0 ? void 0 : task.st) != null;
2594
+ }
2595
+ /**
2596
+ * Reads the answers off a completed decision run.
2597
+ *
2598
+ * The type parameter is the caller's own question map, which is what lets a consumer read
2599
+ * `answers.urgency.noul` rather than walking an untyped record. It is an ASSERTION, not a check: the
2600
+ * answers were membership-checked against the declared questions when they were written, so the only
2601
+ * way this lies is a caller naming a different question map than the run used.
2602
+ *
2603
+ * @param task - The run task.
2604
+ * @returns The answers, or undefined when the run is not a completed decision.
2605
+ *
2606
+ * @__NO_SIDE_EFFECTS__
2607
+ */ function openRouterRunTaskDecisionAnswers(task) {
2608
+ return task === null || task === void 0 ? void 0 : task.an;
2609
+ }
2463
2610
  /**
2464
2611
  * Classifies a run task into an outcome.
2465
2612
  *
@@ -3229,6 +3376,13 @@ function _unsupported_iterable_to_array(o, minLen) {
3229
3376
  * Comfortably longer than any single inference plus its retries, so a healthy run is never stolen from
3230
3377
  * itself, and short enough that a crashed sweep's work resumes on the next tick or two.
3231
3378
  */ var DEFAULT_OPENROUTER_LEASE_DURATION = MS_IN_MINUTE * 10;
3379
+ /**
3380
+ * Distinguishes one immediate run's lease from another's, and from a sweep's.
3381
+ */ var randomImmediateRunId = /* @__PURE__ */ randomNumberFactory({
3382
+ min: 0,
3383
+ max: 1000000000,
3384
+ round: 'floor'
3385
+ });
3232
3386
  /**
3233
3387
  * Default number of attempts before a task is marked FAILED.
3234
3388
  *
@@ -3278,11 +3432,11 @@ function _unsupported_iterable_to_array(o, minLen) {
3278
3432
  }
3279
3433
  function enqueueRunTask(params) {
3280
3434
  return _async_to_generator$1(function() {
3281
- var key, promptKey, version, input, files, configOverrides, continueFrom, restart, document, existing, created, task, resolved, history, _tmp;
3435
+ var key, promptKey, version, input, files, configOverrides, continueFrom, restart, state, questions, immediate, document, existing, created, task, resolved, history, _tmp, execution;
3282
3436
  return _ts_generator$1(this, function(_state) {
3283
3437
  switch(_state.label){
3284
3438
  case 0:
3285
- key = params.key, promptKey = params.promptKey, version = params.version, input = params.input, files = params.files, configOverrides = params.configOverrides, continueFrom = params.continueFrom, restart = params.restart;
3439
+ key = params.key, promptKey = params.promptKey, version = params.version, input = params.input, files = params.files, configOverrides = params.configOverrides, continueFrom = params.continueFrom, restart = params.restart, state = params.state, questions = params.questions, immediate = params.immediate;
3286
3440
  document = runTaskDocument(key);
3287
3441
  return [
3288
3442
  4,
@@ -3339,6 +3493,8 @@ function _unsupported_iterable_to_array(o, minLen) {
3339
3493
  in: openRouterInputMessages(input),
3340
3494
  fp: files,
3341
3495
  co: configOverrides,
3496
+ st: state,
3497
+ q: questions,
3342
3498
  msg: history
3343
3499
  };
3344
3500
  created = true;
@@ -3350,19 +3506,81 @@ function _unsupported_iterable_to_array(o, minLen) {
3350
3506
  _state.sent();
3351
3507
  _state.label = 8;
3352
3508
  case 8:
3509
+ if (!immediate) return [
3510
+ 3,
3511
+ 10
3512
+ ];
3513
+ return [
3514
+ 4,
3515
+ runEnqueuedRunTaskNow(document)
3516
+ ];
3517
+ case 9:
3518
+ execution = _state.sent();
3519
+ _state.label = 10;
3520
+ case 10:
3353
3521
  return [
3354
3522
  2,
3355
3523
  {
3356
3524
  key: key,
3357
3525
  document: document,
3358
3526
  created: created,
3359
- task: task
3527
+ task: task,
3528
+ execution: execution
3360
3529
  }
3361
3530
  ];
3362
3531
  }
3363
3532
  });
3364
3533
  })();
3365
3534
  }
3535
+ /**
3536
+ * Runs a just-enqueued task in this process, through the same claim-and-execute the sweep uses.
3537
+ *
3538
+ * Leased first, and not as a formality: an overlapping sweep tick can reach a QUEUED document between
3539
+ * the write above and this line, and the lease is what stops the two from running the same call twice
3540
+ * and billing for both. A task the claim does not win is left alone — its other owner will finish it —
3541
+ * and no execution is reported.
3542
+ *
3543
+ * Nothing thrown here escapes as an enqueue failure. `executeRunTask` already records a failed attempt
3544
+ * on the document and classifies whether it may be retried, so the state is on the document and the
3545
+ * caller's queue write succeeded either way. Throwing instead would make `immediate: true` a strictly
3546
+ * more fragile enqueue than `immediate: false`, which is the opposite of the point.
3547
+ *
3548
+ * @param document - The enqueued run task.
3549
+ * @returns What the attempt did, or undefined when the task was not claimable.
3550
+ */ function runEnqueuedRunTaskNow(document) {
3551
+ return _async_to_generator$1(function() {
3552
+ var now, leaseCutoff, claimed, result;
3553
+ return _ts_generator$1(this, function(_state) {
3554
+ switch(_state.label){
3555
+ case 0:
3556
+ now = new Date();
3557
+ leaseCutoff = addMilliseconds(now, -defaultLeaseDuration);
3558
+ return [
3559
+ 4,
3560
+ claimRunTask(document, "openRouterRunTaskImmediate_".concat(now.getTime(), "_").concat(randomImmediateRunId()), now, leaseCutoff)
3561
+ ];
3562
+ case 1:
3563
+ claimed = _state.sent();
3564
+ if (!(claimed != null)) return [
3565
+ 3,
3566
+ 3
3567
+ ];
3568
+ return [
3569
+ 4,
3570
+ executeRunTask(claimed)
3571
+ ];
3572
+ case 2:
3573
+ result = _state.sent();
3574
+ _state.label = 3;
3575
+ case 3:
3576
+ return [
3577
+ 2,
3578
+ result
3579
+ ];
3580
+ }
3581
+ });
3582
+ })();
3583
+ }
3366
3584
  function historyForRunTask(key) {
3367
3585
  return _async_to_generator$1(function() {
3368
3586
  var prior, result, _prior_in, messages;
@@ -3648,6 +3866,156 @@ function _unsupported_iterable_to_array(o, minLen) {
3648
3866
  })();
3649
3867
  }
3650
3868
  function executeRunTaskData(document, task) {
3869
+ return _async_to_generator$1(function() {
3870
+ var executionResult;
3871
+ return _ts_generator$1(this, function(_state) {
3872
+ switch(_state.label){
3873
+ case 0:
3874
+ if (!(task.st == null)) return [
3875
+ 3,
3876
+ 2
3877
+ ];
3878
+ return [
3879
+ 4,
3880
+ executeCompletionRunTaskData(document, task)
3881
+ ];
3882
+ case 1:
3883
+ executionResult = _state.sent();
3884
+ return [
3885
+ 3,
3886
+ 4
3887
+ ];
3888
+ case 2:
3889
+ return [
3890
+ 4,
3891
+ executeDecisionRunTaskData(document, task, task.st)
3892
+ ];
3893
+ case 3:
3894
+ executionResult = _state.sent();
3895
+ _state.label = 4;
3896
+ case 4:
3897
+ return [
3898
+ 2,
3899
+ executionResult
3900
+ ];
3901
+ }
3902
+ });
3903
+ })();
3904
+ }
3905
+ /**
3906
+ * Runs a DECISION task: resolve the version, merge its questions with the run's own, ask, and record.
3907
+ *
3908
+ * @param document - The run task document.
3909
+ * @param task - The task data.
3910
+ * @param state - The content to judge.
3911
+ * @returns What the attempt did.
3912
+ */ function executeDecisionRunTaskData(document, task, state) {
3913
+ return _async_to_generator$1(function() {
3914
+ var key, executionResult, resolved, request, decision, e, failure;
3915
+ return _ts_generator$1(this, function(_state) {
3916
+ switch(_state.label){
3917
+ case 0:
3918
+ key = document.id;
3919
+ _state.label = 1;
3920
+ case 1:
3921
+ _state.trys.push([
3922
+ 1,
3923
+ 5,
3924
+ ,
3925
+ 7
3926
+ ]);
3927
+ return [
3928
+ 4,
3929
+ promptService.resolvePrompt({
3930
+ promptKey: task.pk,
3931
+ version: task.pv
3932
+ })
3933
+ ];
3934
+ case 2:
3935
+ resolved = _state.sent();
3936
+ request = openRouterDecisionRequest({
3937
+ prompt: resolved,
3938
+ state: state,
3939
+ questions: task.q,
3940
+ overrides: task.co,
3941
+ sessionId: key,
3942
+ trace: {
3943
+ runTaskKey: key
3944
+ }
3945
+ });
3946
+ return [
3947
+ 4,
3948
+ openRouterDecision({
3949
+ client: client,
3950
+ request: request
3951
+ })
3952
+ ];
3953
+ case 3:
3954
+ decision = _state.sent();
3955
+ return [
3956
+ 4,
3957
+ document.update({
3958
+ s: OpenRouterRunTaskState.COMPLETE,
3959
+ fat: new Date(),
3960
+ an: decision.answers,
3961
+ gi: concatArraysUnique(task.gi, decision.generationIds),
3962
+ u: decision.usage,
3963
+ e: null,
3964
+ lat: null,
3965
+ lo: null
3966
+ })
3967
+ ];
3968
+ case 4:
3969
+ _state.sent();
3970
+ executionResult = {
3971
+ key: key,
3972
+ state: OpenRouterRunTaskState.COMPLETE,
3973
+ decision: decision
3974
+ };
3975
+ return [
3976
+ 3,
3977
+ 7
3978
+ ];
3979
+ case 5:
3980
+ e = _state.sent();
3981
+ return [
3982
+ 4,
3983
+ recordFailure({
3984
+ document: document,
3985
+ task: task,
3986
+ error: {
3987
+ code: openRouterErrorCode(e),
3988
+ message: openRouterErrorMessage(e)
3989
+ },
3990
+ cause: e,
3991
+ at: new Date()
3992
+ })
3993
+ ];
3994
+ case 6:
3995
+ failure = _state.sent();
3996
+ executionResult = _object_spread_props(_object_spread({}, failure), {
3997
+ error: e
3998
+ });
3999
+ return [
4000
+ 3,
4001
+ 7
4002
+ ];
4003
+ case 7:
4004
+ return [
4005
+ 2,
4006
+ executionResult
4007
+ ];
4008
+ }
4009
+ });
4010
+ })();
4011
+ }
4012
+ /**
4013
+ * Runs a COMPLETION task.
4014
+ *
4015
+ * @param document - The run task document.
4016
+ * @param task - The task data.
4017
+ * @returns What the attempt did.
4018
+ */ function executeCompletionRunTaskData(document, task) {
3651
4019
  return _async_to_generator$1(function() {
3652
4020
  var key, executionResult, resolved, attachedFiles, hasTools, request, result, afterCall, _tmp, pausedForTools, finishedAt, e, failure;
3653
4021
  return _ts_generator$1(this, function(_state) {
@@ -4558,4 +4926,4 @@ var randomSweepId = randomNumberFactory({
4558
4926
  })();
4559
4927
  }
4560
4928
 
4561
- export { AbstractAppOpenRouterModule, DEFAULT_OPENROUTER_EXPIRATION_SWEEP_MAX_RUN_TIME, DEFAULT_OPENROUTER_EXPIRATION_SWEEP_PAGE_SIZE, DEFAULT_OPENROUTER_INLINE_FILE_CONTENT_TYPE, DEFAULT_OPENROUTER_LEASE_DURATION, DEFAULT_OPENROUTER_MAX_ATTEMPTS, DEFAULT_OPENROUTER_MAX_INLINE_FILE_SIZE_BYTES, DEFAULT_OPENROUTER_SIGNED_URL_TTL, DEFAULT_OPENROUTER_SWEEP_MAX_PARALLEL_TASKS, DEFAULT_OPENROUTER_SWEEP_MAX_RUN_TIME, DEFAULT_OPENROUTER_SWEEP_PAGE_SIZE, OPENROUTER_BROADCAST_RUN_TASK_KEY_ATTRIBUTES, OPENROUTER_MAX_EXPIRED_RUN_TASK_DELETE_PAGE_SIZE, OPENROUTER_PERMANENT_ERROR_STATUSES, OPENROUTER_PROMPT_CACHE_DURATION, OPENROUTER_PROMPT_SERVICE_TOKEN, OPENROUTER_RUN_TASK_SERVICE_TOKEN, OPENROUTER_SEED_PROMPTS_MAX_PARALLEL_UPDATES, OpenRouterPromptResolutionError, OpenRouterPromptServerActions, OpenRouterPromptService, OpenRouterRunTaskService, appOpenRouterModuleMetadata, callModelForPrompt, conversationStateForOpenRouterRunTask, conversationStatusForOpenRouterRunTaskState, createOpenRouterPromptFactory, createOpenRouterPromptVersionFactory, firestoreOpenRouterStateAccessor, handleOpenRouterRunTaskResultFactory, hasUnresolvedOpenRouterPendingToolCalls, isOpenRouterRunTaskClaimable, isRetryableOpenRouterError, mergeOpenRouterRunUsage, openRouterConversationValueForFirestore, openRouterDeferredToolResolutionsForRunTask, openRouterErrorCode, openRouterErrorMessage, openRouterFileAttachmentModeForConfig, openRouterFileAttachmentResolver, openRouterPromptServerActions, openRouterPromptService, openRouterRunTaskExpirationSweep, openRouterRunTaskKeyFromBroadcastAttributes, openRouterRunTaskOutcome, openRouterRunTaskService, openRouterRunTaskStateForConversationStatus, openRouterRunTaskSweep, openRouterRunTaskUpdateForConversationState, readOpenRouterPromptFactory, reconcileOpenRouterRunTaskFromBroadcast, seedOpenRouterPromptsFactory, updateOpenRouterPromptFactory, updateOpenRouterPromptVersionFactory };
4929
+ export { AbstractAppOpenRouterModule, DEFAULT_OPENROUTER_EXPIRATION_SWEEP_MAX_RUN_TIME, DEFAULT_OPENROUTER_EXPIRATION_SWEEP_PAGE_SIZE, DEFAULT_OPENROUTER_INLINE_FILE_CONTENT_TYPE, DEFAULT_OPENROUTER_LEASE_DURATION, DEFAULT_OPENROUTER_MAX_ATTEMPTS, DEFAULT_OPENROUTER_MAX_INLINE_FILE_SIZE_BYTES, DEFAULT_OPENROUTER_SIGNED_URL_TTL, DEFAULT_OPENROUTER_SWEEP_MAX_PARALLEL_TASKS, DEFAULT_OPENROUTER_SWEEP_MAX_RUN_TIME, DEFAULT_OPENROUTER_SWEEP_PAGE_SIZE, OPENROUTER_BROADCAST_RUN_TASK_KEY_ATTRIBUTES, OPENROUTER_MAX_EXPIRED_RUN_TASK_DELETE_PAGE_SIZE, OPENROUTER_PERMANENT_ERROR_STATUSES, OPENROUTER_PROMPT_CACHE_DURATION, OPENROUTER_PROMPT_SERVICE_TOKEN, OPENROUTER_RUN_TASK_SERVICE_TOKEN, OPENROUTER_SEED_PROMPTS_MAX_PARALLEL_UPDATES, OpenRouterPromptResolutionError, OpenRouterPromptServerActions, OpenRouterPromptService, OpenRouterRunTaskService, appOpenRouterModuleMetadata, callModelForPrompt, conversationStateForOpenRouterRunTask, conversationStatusForOpenRouterRunTaskState, createOpenRouterPromptFactory, createOpenRouterPromptVersionFactory, decideForPrompt, firestoreOpenRouterStateAccessor, handleOpenRouterRunTaskResultFactory, hasUnresolvedOpenRouterPendingToolCalls, isOpenRouterDecisionRunTask, isOpenRouterRunTaskClaimable, isRetryableOpenRouterError, mergeOpenRouterRunUsage, openRouterConversationValueForFirestore, openRouterDeferredToolResolutionsForRunTask, openRouterErrorCode, openRouterErrorMessage, openRouterFileAttachmentModeForConfig, openRouterFileAttachmentResolver, openRouterPromptServerActions, openRouterPromptService, openRouterRunTaskDecisionAnswers, openRouterRunTaskExpirationSweep, openRouterRunTaskKeyFromBroadcastAttributes, openRouterRunTaskOutcome, openRouterRunTaskService, openRouterRunTaskStateForConversationStatus, openRouterRunTaskSweep, openRouterRunTaskUpdateForConversationState, readOpenRouterPromptFactory, reconcileOpenRouterRunTaskFromBroadcast, seedOpenRouterPromptsFactory, updateOpenRouterPromptFactory, updateOpenRouterPromptVersionFactory };