@remnic/core 1.1.9 → 1.1.11

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 (209) hide show
  1. package/dist/access-cli.js +35 -32
  2. package/dist/access-cli.js.map +1 -1
  3. package/dist/access-http.d.ts +8 -7
  4. package/dist/access-http.js +17 -14
  5. package/dist/access-mcp.d.ts +8 -7
  6. package/dist/access-mcp.js +16 -13
  7. package/dist/{access-service-BJCIjVRY.d.ts → access-service-BkXt3di1.d.ts} +11 -9
  8. package/dist/access-service.d.ts +8 -7
  9. package/dist/access-service.js +15 -12
  10. package/dist/active-memory-bridge.d.ts +2 -1
  11. package/dist/active-recall.d.ts +2 -1
  12. package/dist/behavior-learner.d.ts +2 -1
  13. package/dist/behavior-signals.d.ts +2 -1
  14. package/dist/bootstrap.d.ts +7 -6
  15. package/dist/briefing.d.ts +3 -2
  16. package/dist/briefing.js +3 -3
  17. package/dist/buffer-surprise-report.d.ts +2 -1
  18. package/dist/buffer.d.ts +3 -2
  19. package/dist/calibration.d.ts +4 -1
  20. package/dist/calibration.js +10 -5
  21. package/dist/calibration.js.map +1 -1
  22. package/dist/causal-behavior.d.ts +2 -1
  23. package/dist/causal-consolidation.d.ts +5 -2
  24. package/dist/causal-consolidation.js +14 -8
  25. package/dist/causal-consolidation.js.map +1 -1
  26. package/dist/{chunk-ICULSMDG.js → chunk-2YMTO4ZJ.js} +2 -2
  27. package/dist/{chunk-XL3UCAZA.js → chunk-363MWCD3.js} +35 -35
  28. package/dist/{chunk-PHQH2VUO.js → chunk-36CTNQY7.js} +7 -7
  29. package/dist/{chunk-XN4D6Z7X.js → chunk-4DXC6HQQ.js} +5 -3
  30. package/dist/chunk-4DXC6HQQ.js.map +1 -0
  31. package/dist/{chunk-OWGGXPKV.js → chunk-57QNCUEZ.js} +5 -5
  32. package/dist/{chunk-LOBRX7VD.js → chunk-5UM2VJ6D.js} +12 -1
  33. package/dist/chunk-5UM2VJ6D.js.map +1 -0
  34. package/dist/{chunk-KMWZXT5T.js → chunk-6XA7UN4Z.js} +2 -2
  35. package/dist/{chunk-G6NX57V2.js → chunk-C5HUWVH2.js} +2 -2
  36. package/dist/{chunk-NN3TS5BM.js → chunk-D54LZC5L.js} +4 -4
  37. package/dist/{chunk-U4SZXGEO.js → chunk-EYNQTST2.js} +2 -2
  38. package/dist/chunk-HJYHRE4S.js +647 -0
  39. package/dist/chunk-HJYHRE4S.js.map +1 -0
  40. package/dist/{chunk-M3DK45UM.js → chunk-I6BQZSML.js} +4 -4
  41. package/dist/chunk-IBX3VFOM.js +446 -0
  42. package/dist/chunk-IBX3VFOM.js.map +1 -0
  43. package/dist/{chunk-G3G3LY22.js → chunk-KBYWQWSB.js} +7 -7
  44. package/dist/{chunk-FPWUENQH.js → chunk-KUHRUM6B.js} +92 -487
  45. package/dist/chunk-KUHRUM6B.js.map +1 -0
  46. package/dist/chunk-KWBPHZUU.js +83 -0
  47. package/dist/chunk-KWBPHZUU.js.map +1 -0
  48. package/dist/{chunk-CTYRIJ5E.js → chunk-LIO5X3CM.js} +2 -2
  49. package/dist/{chunk-MJLUHRSF.js → chunk-MCC6KDQF.js} +2 -2
  50. package/dist/{chunk-J3P6WSFZ.js → chunk-O4XJUPSF.js} +2 -2
  51. package/dist/{chunk-6OAQEOGV.js → chunk-PB5KW5PL.js} +2 -2
  52. package/dist/{chunk-Y3VT6ZCP.js → chunk-PHNGXFQ6.js} +5 -3
  53. package/dist/chunk-PHNGXFQ6.js.map +1 -0
  54. package/dist/{chunk-2MVUXO4H.js → chunk-RXTFCYQF.js} +2 -2
  55. package/dist/chunk-S2JJBLJG.js +2101 -0
  56. package/dist/chunk-S2JJBLJG.js.map +1 -0
  57. package/dist/{chunk-Q7FJ5ZHM.js → chunk-S3IP6R6K.js} +8 -2
  58. package/dist/{chunk-Q7FJ5ZHM.js.map → chunk-S3IP6R6K.js.map} +1 -1
  59. package/dist/{chunk-ET4BL42V.js → chunk-VQXK37XA.js} +1 -1
  60. package/dist/{chunk-ET4BL42V.js.map → chunk-VQXK37XA.js.map} +1 -1
  61. package/dist/{chunk-FLBYSB2V.js → chunk-VX2IUQFE.js} +94 -8
  62. package/dist/chunk-VX2IUQFE.js.map +1 -0
  63. package/dist/{chunk-QPLYTPYL.js → chunk-WGK4VHGP.js} +77 -15
  64. package/dist/chunk-WGK4VHGP.js.map +1 -0
  65. package/dist/{chunk-7SFAENUZ.js → chunk-WTFWLUSX.js} +2 -2
  66. package/dist/{chunk-A6PGANSE.js → chunk-Y5KDIOKF.js} +3 -3
  67. package/dist/{chunk-KIF7QNKL.js → chunk-Z5S5HNGY.js} +5 -3
  68. package/dist/chunk-Z5S5HNGY.js.map +1 -0
  69. package/dist/{chunk-BIHCWSWA.js → chunk-ZL4S7ARC.js} +3 -3
  70. package/dist/{cli-BojuyOOp.d.ts → cli-Cvy2SNhF.d.ts} +4 -4
  71. package/dist/cli.d.ts +9 -8
  72. package/dist/cli.js +27 -25
  73. package/dist/codex-cli-fallback.d.ts +44 -0
  74. package/dist/codex-cli-fallback.js +12 -0
  75. package/dist/{codex-materialize-YVC2wb6n.d.ts → codex-materialize-CQlLTzke.d.ts} +1 -1
  76. package/dist/compression-optimizer.d.ts +2 -1
  77. package/dist/config.d.ts +2 -1
  78. package/dist/consolidation-provenance-check.d.ts +3 -2
  79. package/dist/consolidation-undo.d.ts +3 -2
  80. package/dist/day-summary.d.ts +2 -1
  81. package/dist/delinearize.d.ts +2 -1
  82. package/dist/direct-answer-wiring.d.ts +2 -1
  83. package/dist/direct-answer.d.ts +2 -1
  84. package/dist/embedding-fallback.d.ts +2 -1
  85. package/dist/{engine-EDFFOWDD.js → engine-FOC3IJLA.js} +4 -4
  86. package/dist/entity-retrieval.d.ts +3 -2
  87. package/dist/entity-retrieval.js +3 -3
  88. package/dist/entity-schema.d.ts +2 -1
  89. package/dist/explicit-capture.d.ts +7 -6
  90. package/dist/explicit-cue-recall.d.ts +16 -1
  91. package/dist/explicit-cue-recall.js +7 -3
  92. package/dist/extraction-judge-telemetry.d.ts +2 -1
  93. package/dist/extraction-judge-training.d.ts +2 -1
  94. package/dist/extraction-judge.d.ts +2 -1
  95. package/dist/extraction.d.ts +2 -1
  96. package/dist/extraction.js +6 -4
  97. package/dist/fallback-llm.d.ts +8 -1
  98. package/dist/fallback-llm.js +5 -3
  99. package/dist/identity-continuity.d.ts +2 -1
  100. package/dist/importance.d.ts +2 -1
  101. package/dist/index-1qIcnbG1.d.ts +34 -0
  102. package/dist/index.d.ts +16 -14
  103. package/dist/index.js +62 -51
  104. package/dist/index.js.map +1 -1
  105. package/dist/intent.d.ts +2 -1
  106. package/dist/lifecycle.d.ts +2 -1
  107. package/dist/live-connectors-runner.d.ts +2 -1
  108. package/dist/local-llm.d.ts +2 -1
  109. package/dist/memory-action-policy.d.ts +2 -1
  110. package/dist/memory-cache.d.ts +2 -1
  111. package/dist/{memory-governance-AAQPBZEP.js → memory-governance-F3QOJGEY.js} +4 -4
  112. package/dist/memory-governance-F3QOJGEY.js.map +1 -0
  113. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
  114. package/dist/{memory-projection-store-BW8u5U0u.d.ts → memory-projection-store-CY8TU40w.d.ts} +1 -1
  115. package/dist/memory-projection-store.d.ts +3 -2
  116. package/dist/memory-worth-outcomes.d.ts +3 -2
  117. package/dist/models-json.d.ts +2 -1
  118. package/dist/native-knowledge.d.ts +2 -1
  119. package/dist/objective-state-writers.d.ts +23 -1
  120. package/dist/objective-state-writers.js +10 -306
  121. package/dist/objective-state-writers.js.map +1 -1
  122. package/dist/objective-state.d.ts +7 -1
  123. package/dist/objective-state.js +3 -1
  124. package/dist/operator-toolkit.d.ts +3 -2
  125. package/dist/operator-toolkit.js +6 -6
  126. package/dist/{orchestrator-CYqmqxco.d.ts → orchestrator-AOQMo7QI.d.ts} +5 -3
  127. package/dist/orchestrator.d.ts +7 -6
  128. package/dist/orchestrator.js +29 -27
  129. package/dist/patterns-cli.d.ts +2 -1
  130. package/dist/policy-runtime.d.ts +2 -1
  131. package/dist/{port-Br27H8dy.d.ts → port-B6VEDIkC.d.ts} +1 -1
  132. package/dist/qmd-recall-cache.d.ts +3 -2
  133. package/dist/qmd.d.ts +3 -2
  134. package/dist/recall-disclosure-escalation.d.ts +2 -1
  135. package/dist/recall-explain-renderer.d.ts +2 -1
  136. package/dist/recall-explain-renderer.js +3 -3
  137. package/dist/recall-state.d.ts +2 -1
  138. package/dist/recall-tag-filter.d.ts +2 -1
  139. package/dist/recall-xray-cli.d.ts +2 -1
  140. package/dist/recall-xray-cli.js +4 -4
  141. package/dist/recall-xray-renderer.d.ts +2 -1
  142. package/dist/recall-xray-renderer.js +3 -3
  143. package/dist/recall-xray.d.ts +2 -1
  144. package/dist/recall-xray.js +2 -2
  145. package/dist/resolve-auth-token.d.ts +2 -1
  146. package/dist/resolve-provider-secret.d.ts +2 -1
  147. package/dist/resolve-provider-secret.js +3 -1
  148. package/dist/resume-bundles.js +3 -3
  149. package/dist/retrieval-agents.d.ts +3 -2
  150. package/dist/retrieval-tiers.d.ts +2 -1
  151. package/dist/schemas.d.ts +22 -22
  152. package/dist/sdk-compat.d.ts +3 -2
  153. package/dist/sdk-compat.js.map +1 -1
  154. package/dist/{semantic-consolidation-GPcLr9BQ.d.ts → semantic-consolidation-ByBXb-sf.d.ts} +2 -2
  155. package/dist/semantic-consolidation.d.ts +4 -3
  156. package/dist/semantic-consolidation.js +3 -3
  157. package/dist/semantic-rule-promotion.js +3 -3
  158. package/dist/semantic-rule-verifier.d.ts +2 -1
  159. package/dist/semantic-rule-verifier.js +3 -3
  160. package/dist/session-observer-bands.d.ts +2 -1
  161. package/dist/session-observer-state.d.ts +2 -1
  162. package/dist/signal.d.ts +2 -1
  163. package/dist/storage.d.ts +3 -2
  164. package/dist/storage.js +2 -2
  165. package/dist/summarizer.d.ts +2 -1
  166. package/dist/summarizer.js +6 -4
  167. package/dist/summary-snapshot.d.ts +2 -1
  168. package/dist/temporal-supersession.d.ts +3 -2
  169. package/dist/temporal-validity.d.ts +2 -1
  170. package/dist/threading.d.ts +2 -1
  171. package/dist/tier-migration.d.ts +4 -3
  172. package/dist/tier-routing.d.ts +2 -1
  173. package/dist/topics.d.ts +2 -1
  174. package/dist/transcript.d.ts +2 -1
  175. package/dist/types.d.ts +2693 -1
  176. package/dist/types.js +1 -1
  177. package/dist/utility-runtime.d.ts +2 -1
  178. package/dist/verified-recall.js +3 -3
  179. package/package.json +1 -1
  180. package/dist/chunk-3VRIIII5.js +0 -905
  181. package/dist/chunk-3VRIIII5.js.map +0 -1
  182. package/dist/chunk-FLBYSB2V.js.map +0 -1
  183. package/dist/chunk-FPWUENQH.js.map +0 -1
  184. package/dist/chunk-KIF7QNKL.js.map +0 -1
  185. package/dist/chunk-LOBRX7VD.js.map +0 -1
  186. package/dist/chunk-QPLYTPYL.js.map +0 -1
  187. package/dist/chunk-XN4D6Z7X.js.map +0 -1
  188. package/dist/chunk-Y3VT6ZCP.js.map +0 -1
  189. package/dist/types-Bmp9ssU2.d.ts +0 -2714
  190. /package/dist/{chunk-ICULSMDG.js.map → chunk-2YMTO4ZJ.js.map} +0 -0
  191. /package/dist/{chunk-XL3UCAZA.js.map → chunk-363MWCD3.js.map} +0 -0
  192. /package/dist/{chunk-PHQH2VUO.js.map → chunk-36CTNQY7.js.map} +0 -0
  193. /package/dist/{chunk-OWGGXPKV.js.map → chunk-57QNCUEZ.js.map} +0 -0
  194. /package/dist/{chunk-KMWZXT5T.js.map → chunk-6XA7UN4Z.js.map} +0 -0
  195. /package/dist/{chunk-G6NX57V2.js.map → chunk-C5HUWVH2.js.map} +0 -0
  196. /package/dist/{chunk-NN3TS5BM.js.map → chunk-D54LZC5L.js.map} +0 -0
  197. /package/dist/{chunk-U4SZXGEO.js.map → chunk-EYNQTST2.js.map} +0 -0
  198. /package/dist/{chunk-M3DK45UM.js.map → chunk-I6BQZSML.js.map} +0 -0
  199. /package/dist/{chunk-G3G3LY22.js.map → chunk-KBYWQWSB.js.map} +0 -0
  200. /package/dist/{chunk-CTYRIJ5E.js.map → chunk-LIO5X3CM.js.map} +0 -0
  201. /package/dist/{chunk-MJLUHRSF.js.map → chunk-MCC6KDQF.js.map} +0 -0
  202. /package/dist/{chunk-J3P6WSFZ.js.map → chunk-O4XJUPSF.js.map} +0 -0
  203. /package/dist/{chunk-6OAQEOGV.js.map → chunk-PB5KW5PL.js.map} +0 -0
  204. /package/dist/{chunk-2MVUXO4H.js.map → chunk-RXTFCYQF.js.map} +0 -0
  205. /package/dist/{chunk-7SFAENUZ.js.map → chunk-WTFWLUSX.js.map} +0 -0
  206. /package/dist/{chunk-A6PGANSE.js.map → chunk-Y5KDIOKF.js.map} +0 -0
  207. /package/dist/{chunk-BIHCWSWA.js.map → chunk-ZL4S7ARC.js.map} +0 -0
  208. /package/dist/{engine-EDFFOWDD.js.map → codex-cli-fallback.js.map} +0 -0
  209. /package/dist/{memory-governance-AAQPBZEP.js.map → engine-FOC3IJLA.js.map} +0 -0
@@ -0,0 +1,2101 @@
1
+ import {
2
+ buildEvidencePack
3
+ } from "./chunk-74WWN7ZW.js";
4
+
5
+ // src/explicit-cue-recall.ts
6
+ var DEFAULT_MAX_CHARS = 2400;
7
+ var DEFAULT_MAX_ITEM_CHARS = 1200;
8
+ var DEFAULT_MAX_REFERENCES = 24;
9
+ var REFERENCE_SCAN_TOKEN_FACTOR = 3;
10
+ var TURN_REFERENCE_WINDOW_RADIUS = 0;
11
+ var LEXICAL_CUE_WINDOW_RADIUS = 1;
12
+ var LEXICAL_CUE_SEARCH_LIMIT = 3;
13
+ var LEXICAL_CUE_MAX_TOKENS = 400;
14
+ var CONTENT_LABEL_SEARCH_LIMIT = 64;
15
+ var CONTENT_LABEL_MAX_TOKENS = 2e3;
16
+ var CONTENT_LABEL_MAX_PAIRED_WINDOWS_PER_REFERENCE = 1;
17
+ var TRAJECTORY_ANALYSIS_MAX_TOKENS = 25e4;
18
+ var TRAJECTORY_ANALYSIS_MAX_RANGE_STEPS = 80;
19
+ var TRAJECTORY_ANALYSIS_MAX_LINES = 160;
20
+ var LATEST_STATE_CUES = /* @__PURE__ */ new Set([
21
+ "as of",
22
+ "currently",
23
+ "latest",
24
+ "most recent",
25
+ "newest",
26
+ "now",
27
+ "updated",
28
+ "changed",
29
+ "change"
30
+ ]);
31
+ var STRUCTURED_PLAN_FIELD_CUES = /* @__PURE__ */ new Set([
32
+ "accommodation",
33
+ "attraction",
34
+ "breakfast",
35
+ "current city",
36
+ "dinner",
37
+ "flight",
38
+ "flights",
39
+ "hotel",
40
+ "lunch",
41
+ "restaurant",
42
+ "restaurants",
43
+ "transportation",
44
+ "traveler",
45
+ "travelers"
46
+ ]);
47
+ var STRUCTURED_PLAN_DEPENDENCY_CUES = /* @__PURE__ */ new Set([
48
+ "comparison",
49
+ "constraint",
50
+ "constraints",
51
+ "dependency",
52
+ "dependencies",
53
+ "join",
54
+ "same",
55
+ "shared"
56
+ ]);
57
+ var BENCHMARK_ABILITY_CUES = /* @__PURE__ */ new Map([
58
+ ["information extraction", "ability=information_extraction"],
59
+ ["knowledge update", "ability=knowledge_update"],
60
+ ["multi session reasoning", "ability=multi_session_reasoning"],
61
+ ["multi-session reasoning", "ability=multi_session_reasoning"],
62
+ ["instruction following", "ability=instruction_following"]
63
+ ]);
64
+ var BENCHMARK_ANCHOR_VALUE_STOPWORDS = /* @__PURE__ */ new Set([
65
+ "a",
66
+ "about",
67
+ "an",
68
+ "for",
69
+ "from",
70
+ "in",
71
+ "on",
72
+ "the",
73
+ "to",
74
+ "use",
75
+ "using",
76
+ "with"
77
+ ]);
78
+ var RELATIVE_TEMPORAL_CUES = [
79
+ "as of",
80
+ "most recent",
81
+ "last time",
82
+ "last week",
83
+ "last month",
84
+ "last year",
85
+ "last session",
86
+ "last conversation",
87
+ "next time",
88
+ "next week",
89
+ "next month",
90
+ "next year",
91
+ "next session",
92
+ "next conversation",
93
+ "previous time",
94
+ "previous week",
95
+ "previous month",
96
+ "previous year",
97
+ "previous session",
98
+ "previous conversation",
99
+ "prior time",
100
+ "prior week",
101
+ "prior month",
102
+ "prior year",
103
+ "prior session",
104
+ "prior conversation",
105
+ "today",
106
+ "yesterday",
107
+ "tomorrow",
108
+ "tonight",
109
+ "earlier",
110
+ "later",
111
+ "recently",
112
+ "previously",
113
+ "currently",
114
+ "now",
115
+ "latest",
116
+ "newest",
117
+ "oldest",
118
+ "earliest",
119
+ "before",
120
+ "after",
121
+ "since",
122
+ "updated",
123
+ "changed",
124
+ "change"
125
+ ];
126
+ var SPEAKER_NAME_STOPWORDS = /* @__PURE__ */ new Set([
127
+ "A",
128
+ "According",
129
+ "An",
130
+ "And",
131
+ "Are",
132
+ "As",
133
+ "At",
134
+ "Before",
135
+ "Can",
136
+ "Compare",
137
+ "Could",
138
+ "Did",
139
+ "Do",
140
+ "Does",
141
+ "For",
142
+ "From",
143
+ "Had",
144
+ "Has",
145
+ "Have",
146
+ "How",
147
+ "In",
148
+ "Is",
149
+ "It",
150
+ "Join",
151
+ "Of",
152
+ "On",
153
+ "Or",
154
+ "Please",
155
+ "Review",
156
+ "Step",
157
+ "Tell",
158
+ "The",
159
+ "To",
160
+ "Turn",
161
+ "Use",
162
+ "Was",
163
+ "Were",
164
+ "What",
165
+ "When",
166
+ "Where",
167
+ "Which",
168
+ "Who",
169
+ "Why",
170
+ "Will",
171
+ "Would"
172
+ ]);
173
+ var QUESTION_SLOT_STOPWORDS = /* @__PURE__ */ new Set([
174
+ "answer",
175
+ "choice",
176
+ "did",
177
+ "does",
178
+ "do",
179
+ "is",
180
+ "should",
181
+ "single",
182
+ "the",
183
+ "user",
184
+ "was",
185
+ "were"
186
+ ]);
187
+ async function buildExplicitCueRecallSection(options) {
188
+ const engine = options.engine;
189
+ const query = options.query.trim();
190
+ const maxChars = normalizePositiveInteger(options.maxChars, DEFAULT_MAX_CHARS);
191
+ if (!engine || query.length === 0 || maxChars <= 0) {
192
+ return "";
193
+ }
194
+ const maxReferences = normalizePositiveInteger(
195
+ options.maxReferences,
196
+ DEFAULT_MAX_REFERENCES
197
+ );
198
+ if (maxReferences <= 0) {
199
+ return "";
200
+ }
201
+ const evidenceItems = [];
202
+ const seenTurns = /* @__PURE__ */ new Set();
203
+ await collectTurnReferenceEvidence({
204
+ engine,
205
+ sessionId: options.sessionId,
206
+ query,
207
+ maxReferences,
208
+ evidenceItems,
209
+ seenTurns
210
+ });
211
+ await collectLexicalCueEvidence({
212
+ engine,
213
+ sessionId: options.sessionId,
214
+ query,
215
+ maxReferences,
216
+ includeBenchmarkAnchorCues: options.includeBenchmarkAnchorCues,
217
+ includeStructuredPlanCues: options.includeStructuredPlanCues,
218
+ evidenceItems,
219
+ seenTurns
220
+ });
221
+ return buildEvidencePack(evidenceItems, {
222
+ title: "Explicit Cue Evidence",
223
+ maxChars,
224
+ maxItemChars: normalizePositiveInteger(
225
+ options.maxItemChars,
226
+ DEFAULT_MAX_ITEM_CHARS
227
+ )
228
+ });
229
+ }
230
+ async function buildTrajectoryAnalysisRecallSection(options) {
231
+ const engine = options.engine;
232
+ const sessionId = options.sessionId;
233
+ const query = options.query.trim();
234
+ const maxChars = normalizePositiveInteger(options.maxChars, DEFAULT_MAX_CHARS);
235
+ if (!engine || !sessionId || !engine.getStats || query.length === 0 || maxChars <= 0) {
236
+ return "";
237
+ }
238
+ if (!hasTrajectoryAnalysisIntent(query)) {
239
+ return "";
240
+ }
241
+ const stats = await engine.getStats(sessionId);
242
+ const totalMessages = Math.max(0, Math.floor(stats.totalMessages));
243
+ if (totalMessages <= 0) {
244
+ return "";
245
+ }
246
+ const expansionEnd = normalizeTurnExpansionEnd(stats);
247
+ const messages = await engine.expandContext(
248
+ sessionId,
249
+ 0,
250
+ expansionEnd,
251
+ TRAJECTORY_ANALYSIS_MAX_TOKENS
252
+ );
253
+ const trajectory = parseLabeledTrajectory(messages);
254
+ if (trajectory.length === 0) {
255
+ return "";
256
+ }
257
+ const bounds = inferTrajectoryBounds(query, trajectory);
258
+ const lines = buildTrajectoryAnalysisLines(query, trajectory, bounds);
259
+ if (lines.length === 0) {
260
+ return "";
261
+ }
262
+ const header = "## Trajectory analysis";
263
+ const bodyBudget = maxChars - header.length - 1;
264
+ if (bodyBudget <= 0) {
265
+ return "";
266
+ }
267
+ const clipped = truncateTrajectoryAnalysisLines(lines, bodyBudget);
268
+ return clipped.length === 0 ? "" : `${header}
269
+ ${clipped.join("\n")}`;
270
+ }
271
+ async function collectTurnReferenceEvidence(options) {
272
+ if (!options.sessionId) {
273
+ return;
274
+ }
275
+ const references = collectExplicitTurnReferences(options.query).slice(
276
+ 0,
277
+ options.maxReferences
278
+ );
279
+ if (references.length === 0) {
280
+ return;
281
+ }
282
+ await collectContentLabelReferenceEvidence({
283
+ engine: options.engine,
284
+ sessionId: options.sessionId,
285
+ query: options.query,
286
+ references,
287
+ evidenceItems: options.evidenceItems,
288
+ seenTurns: options.seenTurns
289
+ });
290
+ const windows = /* @__PURE__ */ new Map();
291
+ for (const reference of references) {
292
+ for (const center of candidateTurnIndexesForReference(reference)) {
293
+ if (center < 0) {
294
+ continue;
295
+ }
296
+ const fromTurn = Math.max(0, center - TURN_REFERENCE_WINDOW_RADIUS);
297
+ const toTurn = center + TURN_REFERENCE_WINDOW_RADIUS;
298
+ windows.set(`${fromTurn}:${toTurn}`, { fromTurn, toTurn });
299
+ }
300
+ }
301
+ for (const window of [...windows.values()].sort(
302
+ (left, right) => left.fromTurn - right.fromTurn || left.toTurn - right.toTurn
303
+ )) {
304
+ const expanded = await options.engine.expandContext(
305
+ options.sessionId,
306
+ window.fromTurn,
307
+ window.toTurn,
308
+ 2e3
309
+ );
310
+ appendExpandedEvidence(
311
+ options.evidenceItems,
312
+ options.seenTurns,
313
+ options.sessionId,
314
+ expanded
315
+ );
316
+ }
317
+ }
318
+ async function collectContentLabelReferenceEvidence(options) {
319
+ const resolved = /* @__PURE__ */ new Set();
320
+ for (const reference of options.references) {
321
+ if (reference.includeDirectTurn) {
322
+ continue;
323
+ }
324
+ const hits = await searchReferenceContentLabels(
325
+ options.engine,
326
+ reference.number,
327
+ options.sessionId
328
+ );
329
+ if (hits.length === 0) {
330
+ continue;
331
+ }
332
+ resolved.add(reference.number);
333
+ let appendedWindows = 0;
334
+ for (const hit of hits) {
335
+ if (appendedWindows >= CONTENT_LABEL_MAX_PAIRED_WINDOWS_PER_REFERENCE) {
336
+ break;
337
+ }
338
+ const { fromTurn, toTurn } = contentLabelEvidenceWindow(hit, {
339
+ includeSuccessor: hasSuccessorTrajectoryIntent(options.query)
340
+ });
341
+ const expanded = await options.engine.expandContext(
342
+ hit.session_id,
343
+ fromTurn,
344
+ toTurn,
345
+ CONTENT_LABEL_MAX_TOKENS
346
+ );
347
+ if (!expandedHasPairedTrajectoryLabels(expanded, reference.number)) {
348
+ continue;
349
+ }
350
+ if (expanded.length === 0) {
351
+ appendEvidenceItem(options.evidenceItems, options.seenTurns, {
352
+ id: `${hit.session_id}:${hit.turn_index}`,
353
+ sessionId: hit.session_id,
354
+ turnIndex: hit.turn_index,
355
+ role: hit.role,
356
+ content: hit.content
357
+ });
358
+ continue;
359
+ }
360
+ appendExpandedEvidence(
361
+ options.evidenceItems,
362
+ options.seenTurns,
363
+ hit.session_id,
364
+ expanded
365
+ );
366
+ appendedWindows += 1;
367
+ }
368
+ }
369
+ return resolved;
370
+ }
371
+ async function searchReferenceContentLabels(engine, referenceNumber, sessionId) {
372
+ const hits = /* @__PURE__ */ new Map();
373
+ for (const labelKind of ["action", "observation"]) {
374
+ const label = labelKind === "action" ? "Action" : "Observation";
375
+ for (const query of [`[${label} ${referenceNumber}]`, `${label} ${referenceNumber}`]) {
376
+ const results = await engine.searchContextFull(
377
+ query,
378
+ CONTENT_LABEL_SEARCH_LIMIT,
379
+ sessionId
380
+ );
381
+ for (const result of results) {
382
+ if (!isReferenceLabelRole(result.role, labelKind) || !contentHasReferenceLabel(result.content, labelKind, referenceNumber)) {
383
+ continue;
384
+ }
385
+ hits.set(`${result.session_id}:${result.turn_index}:${labelKind}`, {
386
+ turn_index: result.turn_index,
387
+ role: result.role,
388
+ content: result.content,
389
+ session_id: result.session_id,
390
+ labelKind
391
+ });
392
+ }
393
+ }
394
+ }
395
+ const numericCandidates = candidateTurnIndexesForReference({
396
+ number: referenceNumber,
397
+ includeDirectTurn: false
398
+ });
399
+ return [...hits.values()].sort((left, right) => {
400
+ const sessionOrder = left.session_id.localeCompare(right.session_id);
401
+ if (sessionOrder !== 0) {
402
+ return sessionOrder;
403
+ }
404
+ const leftDistance = nearestTurnDistance(left.turn_index, numericCandidates);
405
+ const rightDistance = nearestTurnDistance(right.turn_index, numericCandidates);
406
+ if (leftDistance !== rightDistance) {
407
+ return leftDistance - rightDistance;
408
+ }
409
+ return left.turn_index - right.turn_index || left.labelKind.localeCompare(right.labelKind);
410
+ });
411
+ }
412
+ function nearestTurnDistance(turnIndex, candidates) {
413
+ let nearest = Number.POSITIVE_INFINITY;
414
+ for (const candidate of candidates) {
415
+ nearest = Math.min(nearest, Math.abs(turnIndex - candidate));
416
+ }
417
+ return nearest;
418
+ }
419
+ function contentLabelEvidenceWindow(hit, options = {}) {
420
+ const successorTurns = options.includeSuccessor === true ? 2 : 0;
421
+ if (hit.labelKind === "action") {
422
+ return {
423
+ fromTurn: Math.max(0, hit.turn_index - 1),
424
+ toTurn: hit.turn_index + 1 + successorTurns
425
+ };
426
+ }
427
+ return {
428
+ fromTurn: Math.max(0, hit.turn_index - 1),
429
+ toTurn: hit.turn_index + successorTurns
430
+ };
431
+ }
432
+ function hasSuccessorTrajectoryIntent(query) {
433
+ const raw = query.toLowerCase();
434
+ const normalized = raw.replace(/[^a-z0-9]+/g, " ").trim();
435
+ if ([
436
+ /\bafter\s+(?:step|action|observation|turn)\s+\d+\b/,
437
+ /\b(?:next|following|subsequent|successor)\s+(?:step|action|observation|turn)\b/,
438
+ /\b(?:step|action|observation|turn)\s+\d+\s+(?:then|and then)\b/,
439
+ /\bwhat\s+(?:happened|came|occurred)\s+next\b/
440
+ ].some((pattern) => pattern.test(normalized))) {
441
+ return true;
442
+ }
443
+ if (!hasLoopExitIntent(normalized)) {
444
+ return false;
445
+ }
446
+ if (!hasBoundedTrajectoryReference(raw)) {
447
+ return true;
448
+ }
449
+ return !asksForActionInsideBoundedRange(normalized) && hasNamedTrajectoryActionCue(normalized);
450
+ }
451
+ function hasBoundedTrajectoryReference(query) {
452
+ return hasBoundedTrajectoryRange(query) || hasSingleTrajectoryReference(query);
453
+ }
454
+ function hasLoopExitIntent(normalizedQuery) {
455
+ const exitVerbs = "(?:breaks?|breaking|broke|ends?|ending|ended|stops?|stopping|stopped)";
456
+ const loopNouns = "(?:loop|cycle|pattern|sequence)";
457
+ return [
458
+ new RegExp(
459
+ `\\b${exitVerbs}\\s+(?:out\\s+of\\s+)?(?:this|that|the|a|an)?\\s*${loopNouns}\\b`
460
+ ),
461
+ new RegExp(
462
+ `\\b${loopNouns}\\s+(?:${exitVerbs}|is\\s+${exitVerbs}|was\\s+${exitVerbs})\\b`
463
+ )
464
+ ].some((pattern) => pattern.test(normalizedQuery));
465
+ }
466
+ function hasBoundedTrajectoryRange(query) {
467
+ return [
468
+ /\b(?:between|from|in|during|within)\s+(?:steps?|actions?|observations?|turns?)\s+#?\d+\s*(?:-|\u2013|\u2014|\bto\b|\bthrough\b|\bthru\b|\band\b)\s*(?:(?:steps?|actions?|observations?|turns?)\s+)?#?\d+\b/,
469
+ /\b(?:steps?|actions?|observations?|turns?)\s+#?\d+\s*(?:-|\u2013|\u2014|\bto\b|\bthrough\b|\bthru\b)\s*(?:(?:steps?|actions?|observations?|turns?)\s+)?#?\d+\b/
470
+ ].some((pattern) => pattern.test(query));
471
+ }
472
+ function hasSingleTrajectoryReference(query) {
473
+ return /\b(?:in|during|within|at|on)?\s*(?:steps?|actions?|observations?|turns?)\s+#?\d+\b/.test(
474
+ query
475
+ );
476
+ }
477
+ function asksForActionInsideBoundedRange(normalizedQuery) {
478
+ return /\b(?:which|what)\s+(?:single\s+)?(?:action|move|step|maneuver)\s+(?:broke|breaks|breaking|ended|ends|stopped|stops|mattered|accomplished|advanced)\b/.test(
479
+ normalizedQuery
480
+ );
481
+ }
482
+ function hasNamedTrajectoryActionCue(normalizedQuery) {
483
+ const actions = "(?:up|down|left|right|wait|stay|push|pull|open|close|use|enter|exit)";
484
+ return new RegExp(
485
+ `\\b(?:${actions}\\s+(?:action|move|step|maneuver)|(?:action|move|step|maneuver)\\s+${actions})\\b`
486
+ ).test(normalizedQuery);
487
+ }
488
+ function contentHasReferenceLabel(content, labelKind, referenceNumber) {
489
+ const label = labelKind === "action" ? "Action" : "Observation";
490
+ const escapedNumber = String(referenceNumber).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
491
+ return new RegExp(
492
+ `^\\s*\\[\\s*${label}\\s+${escapedNumber}\\s*\\]\\s*(?::\\s*)?`,
493
+ "i"
494
+ ).test(content);
495
+ }
496
+ function isReferenceLabelRole(role, labelKind) {
497
+ if (labelKind === "action") {
498
+ return role === "user";
499
+ }
500
+ return role === "assistant";
501
+ }
502
+ function expandedHasPairedTrajectoryLabels(expanded, referenceNumber) {
503
+ let hasAction = false;
504
+ let hasObservation = false;
505
+ for (const message of expanded) {
506
+ if (isReferenceLabelRole(message.role, "action") && contentHasReferenceLabel(message.content, "action", referenceNumber)) {
507
+ hasAction = true;
508
+ }
509
+ if (isReferenceLabelRole(message.role, "observation") && contentHasReferenceLabel(message.content, "observation", referenceNumber)) {
510
+ hasObservation = true;
511
+ }
512
+ }
513
+ return hasAction && hasObservation;
514
+ }
515
+ async function collectLexicalCueEvidence(options) {
516
+ const cues = collectLexicalCues(options.query, {
517
+ includeBenchmarkAnchorCues: options.includeBenchmarkAnchorCues,
518
+ includeStructuredPlanCues: options.includeStructuredPlanCues
519
+ }).slice(0, options.maxReferences);
520
+ const preferLatest = hasLatestStateIntent(options.query);
521
+ for (const cue of cues) {
522
+ const results = sortLexicalCueResults(
523
+ await options.engine.searchContextFull(
524
+ cue,
525
+ LEXICAL_CUE_SEARCH_LIMIT,
526
+ options.sessionId
527
+ ),
528
+ preferLatest
529
+ );
530
+ for (const result of results) {
531
+ const windowRadius = preferLatest ? 0 : LEXICAL_CUE_WINDOW_RADIUS;
532
+ const fromTurn = Math.max(0, result.turn_index - windowRadius);
533
+ const toTurn = result.turn_index + windowRadius;
534
+ const expanded = await options.engine.expandContext(
535
+ result.session_id,
536
+ fromTurn,
537
+ toTurn,
538
+ LEXICAL_CUE_MAX_TOKENS
539
+ );
540
+ if (expanded.length === 0) {
541
+ appendEvidenceItem(options.evidenceItems, options.seenTurns, {
542
+ id: `${result.session_id}:${result.turn_index}`,
543
+ sessionId: result.session_id,
544
+ turnIndex: result.turn_index,
545
+ role: result.role,
546
+ content: result.content,
547
+ ...typeof result.score === "number" ? { score: result.score } : {}
548
+ });
549
+ continue;
550
+ }
551
+ appendExpandedEvidence(
552
+ options.evidenceItems,
553
+ options.seenTurns,
554
+ result.session_id,
555
+ expanded
556
+ );
557
+ }
558
+ }
559
+ }
560
+ function hasTrajectoryAnalysisIntent(query) {
561
+ const normalized = normalizeTrajectoryQuery(query);
562
+ if (collectExplicitTurnReferences(query).length > 0) {
563
+ return true;
564
+ }
565
+ return [
566
+ /\bbefore\s+(?:step|action|observation)\s+\d+\b/,
567
+ /\b(?:until|through|thru)\s+(?:step|action|observation)\s+\d+\b/,
568
+ /\bup\s+to\s+(?:and\s+including\s+)?(?:step|action|observation)\s+\d+\b/,
569
+ /\bwhat\s+sequence\s+of\s+actions\s+would\s+transform\b/,
570
+ /\bactions?\s+were\s+performed\b/,
571
+ /\bstate\s+of\s+[a-z0-9 _-]+\s+\d+\s+at\s+step\s+\d+\b/,
572
+ /\bwhole\s+changes?\s+history\b/,
573
+ /\bthroughout\s+the\s+trajectory\b/,
574
+ /\binventory\b/,
575
+ /\bcontainers?\b.*\binteracted\b/,
576
+ /\btypes?\s+of\s+actions?\b.*\bfrequen/,
577
+ /\bhow\s+frequently\b/
578
+ ].some((pattern) => pattern.test(normalized));
579
+ }
580
+ function parseLabeledTrajectory(messages) {
581
+ const byStep = /* @__PURE__ */ new Map();
582
+ for (const message of messages) {
583
+ const action = parseTrajectoryLabel(message.content, "Action");
584
+ if (action && isReferenceLabelRole(message.role, "action")) {
585
+ const step = getOrCreateTrajectoryStep(byStep, action.step);
586
+ step.action = action.value;
587
+ step.actionTurnIndex = message.turn_index;
588
+ continue;
589
+ }
590
+ const observation = parseTrajectoryLabel(message.content, "Observation");
591
+ if (observation && isReferenceLabelRole(message.role, "observation")) {
592
+ const step = getOrCreateTrajectoryStep(byStep, observation.step);
593
+ step.observation = observation.value;
594
+ step.observationTurnIndex = message.turn_index;
595
+ }
596
+ }
597
+ return [...byStep.values()].sort((left, right) => left.step - right.step);
598
+ }
599
+ function parseTrajectoryLabel(content, label) {
600
+ const match = new RegExp(
601
+ `^\\s*\\[\\s*${label}\\s+(\\d+)\\s*\\]\\s*(?::\\s*)?([\\s\\S]*)$`,
602
+ "i"
603
+ ).exec(content);
604
+ if (!match) {
605
+ return void 0;
606
+ }
607
+ const step = parseNonNegativeIntegerToken(match[1] ?? "");
608
+ if (step === void 0) {
609
+ return void 0;
610
+ }
611
+ const value = (match[2] ?? "").trim();
612
+ return { step, value };
613
+ }
614
+ function getOrCreateTrajectoryStep(byStep, stepNumber) {
615
+ const existing = byStep.get(stepNumber);
616
+ if (existing) {
617
+ return existing;
618
+ }
619
+ const created = { step: stepNumber };
620
+ byStep.set(stepNumber, created);
621
+ return created;
622
+ }
623
+ function inferTrajectoryBounds(query, trajectory) {
624
+ const minStep = trajectory[0]?.step ?? 0;
625
+ const maxStep = trajectory[trajectory.length - 1]?.step ?? minStep;
626
+ const normalized = normalizeTrajectoryQuery(query);
627
+ const before = firstMatchInteger(
628
+ normalized,
629
+ /\bbefore\s+(?:step|action|observation)\s+(\d+)\b/
630
+ );
631
+ if (before !== void 0) {
632
+ return clampTrajectoryBounds(minStep, before - 1, minStep, maxStep, "before");
633
+ }
634
+ const until = firstMatchInteger(
635
+ normalized,
636
+ /\b(?:until|through|thru)\s+(?:step|action|observation)\s+(\d+)\b/
637
+ ) ?? firstMatchInteger(
638
+ normalized,
639
+ /\bup\s+to\s+(?:and\s+including\s+)?(?:step|action|observation)\s+(\d+)\b/
640
+ );
641
+ if (until !== void 0) {
642
+ return clampTrajectoryBounds(minStep, until, minStep, maxStep, "through");
643
+ }
644
+ const explicitRange = extractExplicitTrajectoryRange(normalized);
645
+ if (explicitRange) {
646
+ return clampTrajectoryBounds(
647
+ explicitRange.start,
648
+ explicitRange.end,
649
+ minStep,
650
+ maxStep,
651
+ "range"
652
+ );
653
+ }
654
+ const references = collectExplicitTurnReferences(query).map((reference) => reference.number);
655
+ if (references.length > 1) {
656
+ return clampTrajectoryBounds(
657
+ Math.min(...references),
658
+ Math.max(...references),
659
+ minStep,
660
+ maxStep,
661
+ "references"
662
+ );
663
+ }
664
+ const atStep = firstMatchInteger(
665
+ normalized,
666
+ /\b(?:at|in|on)\s+(?:step|action|observation)\s+(\d+)\b/
667
+ );
668
+ if (atStep !== void 0) {
669
+ return clampTrajectoryBounds(minStep, atStep, minStep, maxStep, "at");
670
+ }
671
+ return { start: minStep, end: maxStep, reason: "full" };
672
+ }
673
+ function buildTrajectoryAnalysisLines(query, trajectory, bounds) {
674
+ const normalized = normalizeTrajectoryQuery(query);
675
+ const explicitReferences = collectExplicitTurnReferences(query);
676
+ const lines = [
677
+ `Analyzed labeled action/observation transcript window: steps ${bounds.start}-${bounds.end} (${bounds.reason}).`
678
+ ];
679
+ const hasQuotedObservationPair = extractQuotedObservations(query).length >= 2;
680
+ const transition = findObservationTransition(query, trajectory);
681
+ const entities = extractNumberedEntities(query);
682
+ const asksActionRange = asksForTrajectoryActionRange(normalized) || transition !== void 0;
683
+ const asksFrequency = asksForActionFrequency(normalized);
684
+ const asksInventory = /\binventory\b/.test(normalized);
685
+ const asksLocation = /\blocations?\b/.test(normalized) || /\bwhere\b/.test(normalized);
686
+ const asksContainerHistory = /\bcontainers?\b/.test(normalized) || /\binteracted\b/.test(normalized);
687
+ const asksEntityState = /\bstate\b/.test(normalized) || /\bchanges?\s+history\b/.test(normalized) || /\bwhole\s+changes?\s+history\b/.test(normalized);
688
+ if (transition) {
689
+ lines.push(
690
+ `Matched quoted observations: Observation ${transition.fromStep} -> Observation ${transition.toStep}.`
691
+ );
692
+ appendActionRangeLines(lines, trajectory, transition.fromStep + 1, transition.toStep, {
693
+ includeObservations: true,
694
+ heading: "Actions that transform the quoted observations:"
695
+ });
696
+ }
697
+ if (asksActionRange && !transition && entities.length === 0 && !hasQuotedObservationPair) {
698
+ if (bounds.reason === "references") {
699
+ appendReferencedTrajectoryLines(lines, trajectory, explicitReferences, {
700
+ includeObservations: false,
701
+ heading: "Actions at referenced steps:"
702
+ });
703
+ } else {
704
+ appendActionRangeLines(lines, trajectory, bounds.start, bounds.end, {
705
+ includeObservations: false,
706
+ heading: "Actions in requested step window:"
707
+ });
708
+ }
709
+ }
710
+ if (asksFrequency) {
711
+ appendActionFrequencyLines(lines, trajectory, bounds);
712
+ }
713
+ appendSpatialTrajectoryInferenceLines(lines, query, trajectory, bounds);
714
+ if (asksInventory) {
715
+ appendInventoryChangeLines(lines, trajectory, bounds);
716
+ }
717
+ if (asksContainerHistory) {
718
+ appendContainerStateChangeLines(lines, trajectory, bounds);
719
+ }
720
+ if (entities.length > 0 && (asksEntityState || asksLocation || /actions?\s+were\s+performed/.test(normalized))) {
721
+ appendEntityTimelineLines(lines, trajectory, bounds, entities, {
722
+ includeIndirectMentions: asksLocation
723
+ });
724
+ }
725
+ if (lines.length === 1 && explicitReferences.length > 0) {
726
+ if (bounds.reason === "references") {
727
+ appendReferencedTrajectoryLines(lines, trajectory, explicitReferences, {
728
+ includeObservations: true,
729
+ heading: "Referenced trajectory evidence:"
730
+ });
731
+ } else {
732
+ appendActionRangeLines(lines, trajectory, bounds.start, bounds.end, {
733
+ includeObservations: true,
734
+ heading: "Referenced trajectory evidence:"
735
+ });
736
+ }
737
+ }
738
+ return lines.length === 1 ? [] : lines;
739
+ }
740
+ function appendReferencedTrajectoryLines(lines, trajectory, references, options) {
741
+ const byStep = new Map(trajectory.map((step) => [step.step, step]));
742
+ const window = [...new Set(references.map((reference) => reference.number))].sort((left, right) => left - right).map((step) => byStep.get(step)).filter((step) => step !== void 0);
743
+ if (window.length === 0) {
744
+ return;
745
+ }
746
+ lines.push(options.heading);
747
+ for (const step of window) {
748
+ if (step.action) {
749
+ lines.push(`[Action ${step.step}]: ${step.action}`);
750
+ }
751
+ if (options.includeObservations && step.observation) {
752
+ lines.push(`[Observation ${step.step}]: ${oneLine(step.observation)}`);
753
+ }
754
+ }
755
+ }
756
+ function appendActionRangeLines(lines, trajectory, start, end, options) {
757
+ const low = Math.min(start, end);
758
+ const high = Math.max(start, end);
759
+ if (high - low + 1 > TRAJECTORY_ANALYSIS_MAX_RANGE_STEPS) {
760
+ lines.push(`${options.heading} requested range ${low}-${high} is too large for inline expansion.`);
761
+ return;
762
+ }
763
+ const window = trajectory.filter((step) => step.step >= low && step.step <= high);
764
+ if (window.length === 0) {
765
+ return;
766
+ }
767
+ lines.push(options.heading);
768
+ for (const step of window) {
769
+ if (step.action) {
770
+ lines.push(`[Action ${step.step}]: ${step.action}`);
771
+ }
772
+ if (options.includeObservations && step.observation) {
773
+ lines.push(`[Observation ${step.step}]: ${oneLine(step.observation)}`);
774
+ }
775
+ }
776
+ }
777
+ function appendSpatialTrajectoryInferenceLines(lines, query, trajectory, bounds) {
778
+ const normalized = normalizeTrajectoryQuery(query);
779
+ const wantsRelativePosition = /\brelative\s+position\b/.test(normalized) || /\bsteps?\s+(?:to\s+the\s+)?(?:left|right|up|down)\b/.test(normalized);
780
+ const wantsRules = /\brules?\b/.test(normalized) || /\bwin\s+condition\b/.test(normalized) || /\bpush(?:able)?\s+word\b/.test(normalized);
781
+ const wantsStrategicOrCounterfactual = /\b(?:counterproductive|strategic|objective|instead|alternative|progress|goal|necessary|critical)\b/.test(
782
+ normalized
783
+ );
784
+ if (!wantsRelativePosition && !wantsRules && !wantsStrategicOrCounterfactual) {
785
+ return;
786
+ }
787
+ const window = boundedTrajectory(trajectory, bounds);
788
+ const movementLines = collectMovementDeltaLines(query, window);
789
+ if (movementLines.length > 0) {
790
+ lines.push("Relative-position movement cues:");
791
+ lines.push(...movementLines);
792
+ }
793
+ const objectAlignmentWindow = objectAlignmentWindowForQuery(query, trajectory, bounds);
794
+ const objectAlignmentLines = collectObjectAlignmentLines(
795
+ query,
796
+ objectAlignmentWindow,
797
+ normalized
798
+ );
799
+ if (objectAlignmentLines.length > 0) {
800
+ lines.push("Object alignment cues:");
801
+ lines.push(...objectAlignmentLines);
802
+ }
803
+ const alternativeActionLines = collectAlternativeActionLines(query, trajectory);
804
+ if (alternativeActionLines.length > 0) {
805
+ lines.push("Counterfactual action cues:");
806
+ lines.push(...alternativeActionLines);
807
+ }
808
+ const ruleTextPositionLines = collectRuleTextPositionLines(window, normalized);
809
+ if (ruleTextPositionLines.length > 0) {
810
+ lines.push("Rule-text positioning cues:");
811
+ lines.push(...ruleTextPositionLines);
812
+ }
813
+ const ruleLines = collectRuleStateLines(window, normalized);
814
+ if (ruleLines.length > 0) {
815
+ lines.push("Rule-state cues:");
816
+ lines.push(...ruleLines);
817
+ }
818
+ }
819
+ function collectMovementDeltaLines(query, window) {
820
+ const entities = extractRelativePositionEntities(query);
821
+ const lines = [];
822
+ const focusSteps = new Set(collectExplicitTurnReferences(query).map((reference) => reference.number));
823
+ for (let index = 1; index < window.length; index += 1) {
824
+ const previous = window[index - 1];
825
+ const current = window[index];
826
+ if (!previous.observation || !current.observation) {
827
+ continue;
828
+ }
829
+ if (focusSteps.size > 0 && !focusSteps.has(previous.step) && !focusSteps.has(current.step)) {
830
+ continue;
831
+ }
832
+ const previousPositions = parseRelativePositions(previous.observation);
833
+ const currentPositions = parseRelativePositions(current.observation);
834
+ for (const [entity, previousPosition] of previousPositions.entries()) {
835
+ if (entities.size > 0 && ![...entities].some((candidate) => entity.includes(candidate))) {
836
+ continue;
837
+ }
838
+ const currentPosition = currentPositions.get(entity);
839
+ if (!currentPosition) {
840
+ continue;
841
+ }
842
+ const dx = currentPosition.x - previousPosition.x;
843
+ const dy = currentPosition.y - previousPosition.y;
844
+ if (dx === 0 && dy === 0) {
845
+ continue;
846
+ }
847
+ const inferredAgentMove = inferAgentMoveFromRelativeDelta(dx, dy);
848
+ if (!inferredAgentMove) {
849
+ continue;
850
+ }
851
+ lines.push(
852
+ `Observation ${previous.step}->${current.step}: ${entity} changed from ${previousPosition.raw} to ${currentPosition.raw}; this implies the agent moved ${inferredAgentMove} relative to a static object.`
853
+ );
854
+ }
855
+ }
856
+ return lines.slice(0, 8);
857
+ }
858
+ function collectObjectAlignmentLines(query, window, normalizedQuery) {
859
+ const entities = extractRelativePositionEntities(query);
860
+ const focusSteps = new Set(collectExplicitTurnReferences(query).map((reference) => reference.number));
861
+ const lines = [];
862
+ const strategicCueEntities = /* @__PURE__ */ new Set();
863
+ for (let index = 1; index < window.length; index += 1) {
864
+ const previous = window[index - 1];
865
+ const current = window[index];
866
+ const next = window[index + 1];
867
+ if (!previous.observation || !current.observation || !current.action) {
868
+ continue;
869
+ }
870
+ if (focusSteps.size > 0 && !focusSteps.has(previous.step) && !focusSteps.has(current.step) && (!next || !focusSteps.has(next.step))) {
871
+ continue;
872
+ }
873
+ const move = agentMoveDeltaFromAction(current.action);
874
+ if (!move) {
875
+ continue;
876
+ }
877
+ const previousPositions = parseRelativePositions(previous.observation);
878
+ const currentPositions = parseRelativePositions(current.observation);
879
+ for (const [entity, previousPosition] of previousPositions.entries()) {
880
+ if (entity.startsWith("rule ")) {
881
+ continue;
882
+ }
883
+ if (entities.size > 0 && ![...entities].some((candidate) => entity.includes(candidate))) {
884
+ continue;
885
+ }
886
+ if (currentPositions.has(entity)) {
887
+ continue;
888
+ }
889
+ if (!relativePositionMatchesMove(previousPosition, move)) {
890
+ continue;
891
+ }
892
+ lines.push(
893
+ `Observation ${previous.step}->${current.step}: ${entity} was ${previousPosition.raw}, Action ${current.step} was ${move.direction}, and ${entity} is absent from Observation ${current.step}; infer a zero-offset same-tile alignment at the end of step ${current.step}, not that ${entity} was removed.`
894
+ );
895
+ if (next?.observation && next.action) {
896
+ const nextPositions = parseRelativePositions(next.observation);
897
+ const nextPosition = nextPositions.get(entity);
898
+ const nextMove = agentMoveDeltaFromAction(next.action);
899
+ if (nextPosition && nextMove) {
900
+ lines.push(
901
+ `Observation ${current.step}->${next.step}: after Action ${next.step} ${nextMove.direction}, ${entity} reappears ${nextPosition.raw}; this confirms the step-${current.step} same-tile alignment and leaves the agent on the opposite side of ${entity} for a future ${oppositeDirection(nextMove.direction)} interaction or alignment.`
902
+ );
903
+ if (normalizedQuery.includes("win") || hasManeuverInterpretationCue(normalizedQuery) && hasRelativeEntityInObservations("rule win", [
904
+ previous.observation,
905
+ current.observation,
906
+ next.observation
907
+ ])) {
908
+ lines.push(
909
+ `Because the question asks about a win-condition objective, treat that future ${oppositeDirection(nextMove.direction)} setup as supporting possible ${entity} manipulation or rule alignment toward a new win condition.`
910
+ );
911
+ }
912
+ }
913
+ }
914
+ if (hasManeuverInterpretationCue(normalizedQuery) && !hasExactRelativeStateIntent(normalizedQuery) && !strategicCueEntities.has(entity)) {
915
+ lines.push(
916
+ `For ${entity} strategic maneuver questions, treat same-tile or vanishing-object cues as path-positioning evidence; the strategic goal should be framed as repositioning around a blocking object for later rule/object manipulation, not as pushing, collecting, or removing ${entity}.`
917
+ );
918
+ strategicCueEntities.add(entity);
919
+ }
920
+ }
921
+ }
922
+ return lines.slice(0, 8);
923
+ }
924
+ function objectAlignmentWindowForQuery(query, trajectory, bounds) {
925
+ const normalized = normalizeTrajectoryQuery(query);
926
+ let end = bounds.end;
927
+ if (/(?:after|vanish|vanished|disappear|disappeared|reappear|reappeared)/.test(normalized)) {
928
+ for (const reference of collectExplicitTurnReferences(query)) {
929
+ if (reference.number > end) {
930
+ end = reference.number;
931
+ }
932
+ }
933
+ }
934
+ const maxStep = trajectory[trajectory.length - 1]?.step ?? bounds.end;
935
+ return boundedTrajectory(trajectory, {
936
+ start: bounds.start,
937
+ end: Math.min(end, maxStep),
938
+ reason: bounds.reason
939
+ });
940
+ }
941
+ function collectAlternativeActionLines(query, trajectory) {
942
+ const normalized = normalizeTrajectoryQuery(query);
943
+ if (!/\b(?:alternative|instead|would\s+have|should\s+have)\b/.test(normalized) || !/\b(?:loop|zero\s+progress|reversing|reverse|win\s+condition|objective)\b/.test(normalized)) {
944
+ return [];
945
+ }
946
+ const targetStep = firstMatchInteger(normalized, /\bstart\s+of\s+step\s+(\d+)\b/) ?? firstMatchInteger(normalized, /\binstead\s+of\s+(?:moving|going)\s+[a-z]+\s+(?:in|at|on)\s+step\s+(\d+)\b/);
947
+ if (targetStep === void 0) {
948
+ return [];
949
+ }
950
+ const byStep = new Map(trajectory.map((step) => [step.step, step]));
951
+ const priorStep = byStep.get(targetStep - 1);
952
+ const target = byStep.get(targetStep);
953
+ if (!priorStep?.observation) {
954
+ return [];
955
+ }
956
+ const unavailableMove = extractDisallowedMove(normalized) ?? (target?.action ? agentMoveDeltaFromAction(target.action)?.direction : void 0);
957
+ const positions = parseRelativePositions(priorStep.observation);
958
+ const focus = selectAlternativeActionTargets(positions, normalized);
959
+ if (focus.length === 0) {
960
+ return [];
961
+ }
962
+ const scored = ["left", "right", "up", "down"].map((direction) => agentMoveDeltaFromAction(direction)).filter((move) => move.direction !== unavailableMove).map((move) => ({
963
+ move,
964
+ score: scoreMoveTowardTargets(move, focus)
965
+ })).sort((left, right) => {
966
+ if (right.score !== left.score) {
967
+ return right.score - left.score;
968
+ }
969
+ return left.move.direction.localeCompare(right.move.direction);
970
+ });
971
+ const best = scored[0];
972
+ if (!best || best.score <= 0) {
973
+ return [];
974
+ }
975
+ const targetDescriptions = focus.map(
976
+ ({ entity, position }) => `${entity} at ${position.raw}`
977
+ );
978
+ const lines = [
979
+ `At the start of step ${targetStep}, use Observation ${priorStep.step} as the decision state: ${targetDescriptions.join("; ")}.`,
980
+ `Excluding the actual/reversing move${unavailableMove ? ` ${unavailableMove}` : ""}, ${best.move.direction} is the alternative that most directly reduces distance to the win-condition rule text target(s).`
981
+ ];
982
+ if (normalized.includes("win condition")) {
983
+ lines.push(
984
+ `${best.move.direction} advances the objective of getting beside or behind IS/WIN rule text for later rule construction; moves toward unrelated object words should not be preferred when the question asks about creating a win condition.`
985
+ );
986
+ }
987
+ return lines;
988
+ }
989
+ function collectRuleTextPositionLines(window, normalizedQuery) {
990
+ if (!hasManeuverInterpretationCue(normalizedQuery)) {
991
+ return [];
992
+ }
993
+ const firstByEntity = /* @__PURE__ */ new Map();
994
+ const lastByEntity = /* @__PURE__ */ new Map();
995
+ for (const step of window) {
996
+ if (!step.observation) {
997
+ continue;
998
+ }
999
+ for (const [entity, position] of parseRelativePositions(step.observation).entries()) {
1000
+ if (!entity.startsWith("rule ")) {
1001
+ continue;
1002
+ }
1003
+ if (!firstByEntity.has(entity)) {
1004
+ firstByEntity.set(entity, position);
1005
+ }
1006
+ lastByEntity.set(entity, position);
1007
+ }
1008
+ }
1009
+ const movedLeft = [...firstByEntity.entries()].map(([entity, first]) => ({
1010
+ entity,
1011
+ first,
1012
+ last: lastByEntity.get(entity)
1013
+ })).filter((item) => item.last !== void 0 && item.last.x < item.first.x).sort((left, right) => left.entity.localeCompare(right.entity)).slice(0, 4);
1014
+ if (movedLeft.length === 0) {
1015
+ return [];
1016
+ }
1017
+ const descriptions = movedLeft.map(
1018
+ ({ entity, first, last }) => `${entity} moved from ${first.raw} to ${last.raw}`
1019
+ );
1020
+ return [
1021
+ `${descriptions.join("; ")}; this supports describing the maneuver as repositioning the agent to the right of those rule text blocks for later rule manipulation.`
1022
+ ];
1023
+ }
1024
+ function collectRuleStateLines(window, normalizedQuery) {
1025
+ const lines = [];
1026
+ const seenRules = /* @__PURE__ */ new Set();
1027
+ const seenObjects = /* @__PURE__ */ new Set();
1028
+ for (const step of window) {
1029
+ if (!step.observation) {
1030
+ continue;
1031
+ }
1032
+ for (const rule of parseActiveRules(step.observation)) {
1033
+ seenRules.add(rule);
1034
+ }
1035
+ for (const position of parseRelativePositions(step.observation).values()) {
1036
+ const normalizedEntity = normalizeEntity(position.entity);
1037
+ if (!normalizedEntity.startsWith("rule ")) {
1038
+ seenObjects.add(normalizedEntity);
1039
+ }
1040
+ }
1041
+ }
1042
+ const activeRules = [...seenRules].sort((left, right) => left.localeCompare(right));
1043
+ const asksExactRelativeState = hasExactRelativeStateIntent(normalizedQuery);
1044
+ if (activeRules.length > 0) {
1045
+ lines.push(`Active rules in this window: ${activeRules.join("; ")}.`);
1046
+ }
1047
+ for (const object of [...seenObjects].sort((left, right) => left.localeCompare(right))) {
1048
+ if (!activeRules.some((rule) => rule.startsWith(`${object} is `))) {
1049
+ lines.push(
1050
+ `No active rule for ${object} appears in this window; specifically, no "${object} is push" rule is active, so treat ${object} as not currently pushable and do not claim that a current move pushed ${object} unless the observations state that rule.`
1051
+ );
1052
+ if (normalizedQuery.includes(object) && hasManeuverInterpretationCue(normalizedQuery) && !asksExactRelativeState) {
1053
+ lines.push(
1054
+ `For ${object} maneuver questions, make bypassing or repositioning around a not-pushable obstacle the strategic goal unless an active rule says "${object} is push"; do not make overlap, collection, removal, or pushing the goal unless the question asks that exact relative state.`
1055
+ );
1056
+ }
1057
+ }
1058
+ }
1059
+ return lines.slice(0, 8);
1060
+ }
1061
+ function appendActionFrequencyLines(lines, trajectory, bounds) {
1062
+ const counts = /* @__PURE__ */ new Map();
1063
+ for (const step of boundedTrajectory(trajectory, bounds)) {
1064
+ if (!step.action) continue;
1065
+ const verb = normalizeActionVerb(step.action);
1066
+ if (!verb) continue;
1067
+ counts.set(verb, (counts.get(verb) ?? 0) + 1);
1068
+ }
1069
+ if (counts.size === 0) {
1070
+ return;
1071
+ }
1072
+ const frequencies = [...counts.entries()].sort(
1073
+ (left, right) => right[1] - left[1] || left[0].localeCompare(right[0])
1074
+ );
1075
+ lines.push(
1076
+ `Action frequency through requested window: ${frequencies.map(([verb, count]) => `${verb}=${count}`).join(", ")}.`
1077
+ );
1078
+ }
1079
+ function appendInventoryChangeLines(lines, trajectory, bounds) {
1080
+ const held = /* @__PURE__ */ new Set();
1081
+ const changes = [];
1082
+ for (const step of boundedTrajectory(trajectory, bounds)) {
1083
+ if (!step.action) continue;
1084
+ const change = parseInventoryChange(step.action, held);
1085
+ if (change) {
1086
+ changes.push(`[Action ${step.step}]: ${step.action} => ${change}`);
1087
+ }
1088
+ }
1089
+ if (changes.length === 0) {
1090
+ return;
1091
+ }
1092
+ lines.push("Inventory changes from action transcript:");
1093
+ lines.push(...changes);
1094
+ }
1095
+ function appendContainerStateChangeLines(lines, trajectory, bounds) {
1096
+ const changes = collectContainerStateChanges(trajectory, bounds);
1097
+ if (changes.length === 0) {
1098
+ return;
1099
+ }
1100
+ lines.push("Container open/close state changes:");
1101
+ for (const change of changes) {
1102
+ lines.push(`[Action ${change.step}]: ${change.action} => ${change.entity} ${change.state}`);
1103
+ }
1104
+ }
1105
+ function appendEntityTimelineLines(lines, trajectory, bounds, entities, options) {
1106
+ for (const entity of entities) {
1107
+ const directActions = boundedTrajectory(trajectory, bounds).filter(
1108
+ (step) => step.action && (isDirectEntityAction(step.action, entity) || options.includeIndirectMentions && actionMentionsEntity(step.action, entity))
1109
+ );
1110
+ const stateChanges = collectContainerStateChanges(trajectory, bounds).filter(
1111
+ (change) => normalizeEntity(change.entity) === normalizeEntity(entity)
1112
+ );
1113
+ if (directActions.length === 0 && stateChanges.length === 0) {
1114
+ continue;
1115
+ }
1116
+ lines.push(`Timeline for ${entity}:`);
1117
+ for (const step of directActions) {
1118
+ lines.push(`[Action ${step.step}]: ${step.action}`);
1119
+ }
1120
+ const inferredLocation = inferEntityLocation(trajectory, bounds, entity);
1121
+ if (inferredLocation) {
1122
+ lines.push(
1123
+ `Inferred ${entity} location at step ${bounds.end}: ${inferredLocation}.`
1124
+ );
1125
+ }
1126
+ if (stateChanges.length > 0) {
1127
+ const latest = stateChanges[stateChanges.length - 1];
1128
+ lines.push(
1129
+ `Latest ${entity} state at step ${bounds.end}: ${latest.state}; state changes: ${stateChanges.map((change) => `${change.step}:${change.state}`).join(", ")}.`
1130
+ );
1131
+ }
1132
+ }
1133
+ }
1134
+ function boundedTrajectory(trajectory, bounds) {
1135
+ return trajectory.filter((step) => step.step >= bounds.start && step.step <= bounds.end);
1136
+ }
1137
+ function collectContainerStateChanges(trajectory, bounds) {
1138
+ const changes = [];
1139
+ for (const step of boundedTrajectory(trajectory, bounds)) {
1140
+ if (!step.action) continue;
1141
+ const match = /^(open|close)\s+(.+)$/i.exec(step.action.trim());
1142
+ if (!match) continue;
1143
+ const verb = match[1].toLowerCase();
1144
+ changes.push({
1145
+ step: step.step,
1146
+ action: step.action,
1147
+ entity: match[2].trim(),
1148
+ state: verb === "open" ? "open" : "closed"
1149
+ });
1150
+ }
1151
+ return changes;
1152
+ }
1153
+ function parseInventoryChange(action, held) {
1154
+ const normalized = action.trim();
1155
+ const take = /^take\s+(.+?)\s+from\s+(.+)$/i.exec(normalized);
1156
+ if (take) {
1157
+ const object = take[1].trim();
1158
+ const source = take[2].trim();
1159
+ held.add(normalizeEntity(object));
1160
+ return `inventory added ${object}; ${object} removed from ${source}`;
1161
+ }
1162
+ const place = /^(?:move|put|place|insert)\s+(.+?)\s+(?:to|in|into|on)\s+(.+)$/i.exec(
1163
+ normalized
1164
+ );
1165
+ if (place) {
1166
+ const object = place[1].trim();
1167
+ const destination = place[2].trim();
1168
+ const key = normalizeEntity(object);
1169
+ const wasHeld = held.delete(key);
1170
+ return wasHeld ? `inventory removed ${object}; ${object} moved to ${destination}` : `${object} moved to ${destination}`;
1171
+ }
1172
+ const drop = /^drop\s+(.+)$/i.exec(normalized);
1173
+ if (drop) {
1174
+ const object = drop[1].trim();
1175
+ held.delete(normalizeEntity(object));
1176
+ return `inventory removed ${object}`;
1177
+ }
1178
+ return void 0;
1179
+ }
1180
+ function asksForTrajectoryActionRange(normalizedQuery) {
1181
+ return [
1182
+ /\bwhat\s+actions?\s+were\s+performed\b/,
1183
+ /\bwhich\s+actions?\s+were\s+performed\b/,
1184
+ /\bsequence\s+of\s+actions?\b/,
1185
+ /\bactions?\s+(?:between|from|during|within)\b/
1186
+ ].some((pattern) => pattern.test(normalizedQuery));
1187
+ }
1188
+ function asksForActionFrequency(normalizedQuery) {
1189
+ return /\btypes?\s+of\s+actions?\b/.test(normalizedQuery) || /\bfrequen/.test(normalizedQuery) || /\bhow\s+often\b/.test(normalizedQuery);
1190
+ }
1191
+ function extractExplicitTrajectoryRange(normalizedQuery) {
1192
+ const patterns = [
1193
+ /\b(?:between|from|during|within)\s+(?:steps?|actions?|observations?)\s+(\d+)\s*(?:-|to|through|thru|and)\s*(?:(?:steps?|actions?|observations?)\s+)?(\d+)\b/,
1194
+ /\b(?:steps?|actions?|observations?)\s+(\d+)\s*(?:-|to|through|thru)\s*(?:(?:steps?|actions?|observations?)\s+)?(\d+)\b/
1195
+ ];
1196
+ for (const pattern of patterns) {
1197
+ const match = pattern.exec(normalizedQuery);
1198
+ if (!match) continue;
1199
+ const start = parseNonNegativeIntegerToken(match[1] ?? "");
1200
+ const end = parseNonNegativeIntegerToken(match[2] ?? "");
1201
+ if (start !== void 0 && end !== void 0) {
1202
+ return { start, end };
1203
+ }
1204
+ }
1205
+ return void 0;
1206
+ }
1207
+ function findObservationTransition(query, trajectory) {
1208
+ const quoted = extractQuotedObservations(query);
1209
+ if (quoted.length < 2) {
1210
+ return void 0;
1211
+ }
1212
+ const fromCandidates = findObservationStepCandidates(trajectory, quoted[0]);
1213
+ const toCandidates = findObservationStepCandidates(trajectory, quoted[1]);
1214
+ if (fromCandidates.length === 0 || toCandidates.length === 0) {
1215
+ return void 0;
1216
+ }
1217
+ let best;
1218
+ for (const fromStep of fromCandidates) {
1219
+ for (const toStep of toCandidates) {
1220
+ if (toStep <= fromStep) {
1221
+ continue;
1222
+ }
1223
+ if (!best || toStep - fromStep < best.toStep - best.fromStep || toStep - fromStep === best.toStep - best.fromStep && fromStep < best.fromStep) {
1224
+ best = { fromStep, toStep };
1225
+ }
1226
+ }
1227
+ }
1228
+ if (best) {
1229
+ return best;
1230
+ }
1231
+ return void 0;
1232
+ }
1233
+ function extractQuotedObservations(query) {
1234
+ const observations = [];
1235
+ for (const match of query.matchAll(/\bobservation:\s*"([\s\S]*?)"/gi)) {
1236
+ const value = match[1]?.trim();
1237
+ if (value) {
1238
+ observations.push(value);
1239
+ }
1240
+ }
1241
+ return observations;
1242
+ }
1243
+ function findObservationStepCandidates(trajectory, quotedObservation) {
1244
+ const normalizedQuoted = normalizeObservationText(quotedObservation);
1245
+ const normalizedQuotedCore = normalizeObservationCore(quotedObservation);
1246
+ const candidates = /* @__PURE__ */ new Set();
1247
+ for (const step of trajectory) {
1248
+ if (!step.observation) continue;
1249
+ const normalizedObservation = normalizeObservationText(step.observation);
1250
+ if (normalizedObservation === normalizedQuoted || normalizedObservation.includes(normalizedQuoted) || normalizedQuoted.includes(normalizedObservation)) {
1251
+ candidates.add(step.step);
1252
+ continue;
1253
+ }
1254
+ const normalizedObservationCore = normalizeObservationCore(step.observation);
1255
+ if (normalizedObservationCore.length > 0 && normalizedQuotedCore.length > 0 && (normalizedObservationCore === normalizedQuotedCore || normalizedObservationCore.includes(normalizedQuotedCore) || normalizedQuotedCore.includes(normalizedObservationCore))) {
1256
+ candidates.add(step.step);
1257
+ }
1258
+ }
1259
+ return [...candidates].sort((left, right) => left - right);
1260
+ }
1261
+ function extractNumberedEntities(query) {
1262
+ const entities = /* @__PURE__ */ new Set();
1263
+ for (const match of query.matchAll(/\b([a-z][a-z0-9_-]*(?:\s+[a-z][a-z0-9_-]*)?)\s+(\d+)\b/gi)) {
1264
+ const rawPrefix = match[1]?.trim().toLowerCase();
1265
+ const number = match[2]?.trim();
1266
+ if (!rawPrefix || !number || isTrajectoryReferenceEntity(rawPrefix)) {
1267
+ continue;
1268
+ }
1269
+ const words = rawPrefix.split(/\s+/);
1270
+ const entityHead = words[words.length - 1];
1271
+ if (isTrajectoryReferenceEntity(entityHead)) {
1272
+ continue;
1273
+ }
1274
+ entities.add(`${entityHead} ${number}`);
1275
+ }
1276
+ return [...entities].sort((left, right) => left.localeCompare(right));
1277
+ }
1278
+ function isTrajectoryReferenceEntity(value) {
1279
+ return [
1280
+ "action",
1281
+ "actions",
1282
+ "observation",
1283
+ "observations",
1284
+ "step",
1285
+ "steps",
1286
+ "turn",
1287
+ "turns"
1288
+ ].includes(value);
1289
+ }
1290
+ function actionMentionsEntity(action, entity) {
1291
+ const normalizedAction = normalizeTrajectoryQuery(action);
1292
+ const normalizedEntity = normalizeEntity(entity);
1293
+ return normalizedAction === normalizedEntity || normalizedAction.startsWith(`${normalizedEntity} `) || normalizedAction.endsWith(` ${normalizedEntity}`) || normalizedAction.includes(` ${normalizedEntity} `);
1294
+ }
1295
+ function isDirectEntityAction(action, entity) {
1296
+ const normalizedAction = normalizeTrajectoryQuery(action);
1297
+ const normalizedEntity = normalizeEntity(entity);
1298
+ return [
1299
+ `open ${normalizedEntity}`,
1300
+ `close ${normalizedEntity}`,
1301
+ `examine ${normalizedEntity}`
1302
+ ].includes(normalizedAction);
1303
+ }
1304
+ function inferEntityLocation(trajectory, bounds, entity) {
1305
+ const normalizedEntity = normalizeEntity(entity);
1306
+ let location;
1307
+ for (const step of boundedTrajectory(trajectory, bounds)) {
1308
+ if (!step.action) continue;
1309
+ const action = step.action.trim();
1310
+ const take = /^take\s+(.+?)\s+from\s+(.+)$/i.exec(action);
1311
+ if (take && normalizeEntity(take[1]) === normalizedEntity) {
1312
+ location = "inventory";
1313
+ continue;
1314
+ }
1315
+ const move = /^(?:move|put|place|insert)\s+(.+?)\s+(?:to|in|into|on)\s+(.+)$/i.exec(
1316
+ action
1317
+ );
1318
+ if (move && normalizeEntity(move[1]) === normalizedEntity) {
1319
+ location = move[2].trim();
1320
+ }
1321
+ }
1322
+ return location;
1323
+ }
1324
+ function normalizeActionVerb(action) {
1325
+ const match = /^([a-z][a-z0-9_-]*)\b/i.exec(action.trim());
1326
+ return match?.[1]?.toLowerCase();
1327
+ }
1328
+ function clampTrajectoryBounds(start, end, minStep, maxStep, reason) {
1329
+ const low = Math.max(minStep, Math.min(start, end));
1330
+ const high = Math.min(maxStep, Math.max(start, end));
1331
+ return {
1332
+ start: Math.min(low, high),
1333
+ end: Math.max(low, high),
1334
+ reason
1335
+ };
1336
+ }
1337
+ function firstMatchInteger(query, pattern) {
1338
+ const match = pattern.exec(query);
1339
+ return match ? parseNonNegativeIntegerToken(match[1] ?? "") : void 0;
1340
+ }
1341
+ function normalizeTurnExpansionEnd(stats) {
1342
+ const messageCountEnd = Math.max(0, Math.floor(stats.totalMessages) - 1);
1343
+ if (typeof stats.maxTurnIndex !== "number" || !Number.isFinite(stats.maxTurnIndex)) {
1344
+ return messageCountEnd;
1345
+ }
1346
+ return Math.max(messageCountEnd, Math.floor(stats.maxTurnIndex));
1347
+ }
1348
+ function truncateTrajectoryAnalysisLines(lines, maxChars) {
1349
+ const result = [];
1350
+ let used = 0;
1351
+ for (const line of lines.slice(0, TRAJECTORY_ANALYSIS_MAX_LINES)) {
1352
+ const separator = result.length === 0 ? 0 : 1;
1353
+ const remaining = maxChars - used - separator;
1354
+ if (remaining <= 0) {
1355
+ break;
1356
+ }
1357
+ const clipped = line.length > remaining ? remaining <= 3 ? line.slice(0, remaining) : `${line.slice(0, remaining - 3).trimEnd()}...` : line;
1358
+ if (clipped.length === 0) {
1359
+ break;
1360
+ }
1361
+ result.push(clipped);
1362
+ used += separator + clipped.length;
1363
+ }
1364
+ return result;
1365
+ }
1366
+ function oneLine(value) {
1367
+ return value.replace(/\s+/g, " ").trim();
1368
+ }
1369
+ function normalizeEntity(value) {
1370
+ return normalizeTrajectoryQuery(value);
1371
+ }
1372
+ function normalizeObservationText(value) {
1373
+ return value.toLowerCase().replace(/\s+/g, " ").trim();
1374
+ }
1375
+ function normalizeObservationCore(value) {
1376
+ return normalizeObservationText(
1377
+ value.split(/\bthe current available actions are:/i)[0] ?? value
1378
+ );
1379
+ }
1380
+ function parseActiveRules(observation) {
1381
+ const rulesBlock = /active rules:\s*([\s\S]*?)(?:\n\s*\n|objects on the map:|$)/i.exec(
1382
+ observation
1383
+ )?.[1];
1384
+ if (!rulesBlock) {
1385
+ return [];
1386
+ }
1387
+ return rulesBlock.split(/\n+/).map((line) => normalizeTrajectoryQuery(line)).filter((line) => line.length > 0);
1388
+ }
1389
+ function parseRelativePositions(observation) {
1390
+ const positions = /* @__PURE__ */ new Map();
1391
+ const objectsBlock = /objects on the map:\s*([\s\S]*)$/i.exec(observation)?.[1];
1392
+ if (!objectsBlock) {
1393
+ return positions;
1394
+ }
1395
+ for (const rawLine of objectsBlock.split(/\n+/)) {
1396
+ const line = rawLine.trim();
1397
+ if (!line) {
1398
+ continue;
1399
+ }
1400
+ const parsed = parseRelativePositionLine(line);
1401
+ if (parsed) {
1402
+ positions.set(normalizeEntity(parsed.entity), parsed);
1403
+ }
1404
+ }
1405
+ return positions;
1406
+ }
1407
+ function parseRelativePositionLine(line) {
1408
+ const normalizedLine = line.replace(/`/g, "").trim();
1409
+ const positionStart = findRelativePositionStart(normalizedLine);
1410
+ if (positionStart <= 0) {
1411
+ return void 0;
1412
+ }
1413
+ const entity = normalizedLine.slice(0, positionStart).trim();
1414
+ const rawPosition = normalizedLine.slice(positionStart).trim();
1415
+ if (!entity || !rawPosition) {
1416
+ return void 0;
1417
+ }
1418
+ let x = 0;
1419
+ let y = 0;
1420
+ let found = false;
1421
+ for (const phrase of rawPosition.split(/\s+and\s+/i)) {
1422
+ const parsed = parseRelativePositionPhrase(phrase);
1423
+ if (!parsed) {
1424
+ return void 0;
1425
+ }
1426
+ found = true;
1427
+ if (parsed.direction === "left") x -= parsed.amount;
1428
+ if (parsed.direction === "right") x += parsed.amount;
1429
+ if (parsed.direction === "up") y -= parsed.amount;
1430
+ if (parsed.direction === "down") y += parsed.amount;
1431
+ }
1432
+ return found ? { entity, x, y, raw: rawPosition } : void 0;
1433
+ }
1434
+ function findRelativePositionStart(value) {
1435
+ let best = -1;
1436
+ for (const direction of ["left", "right", "up", "down"]) {
1437
+ for (const prefix of [
1438
+ ` step to the ${direction}`,
1439
+ ` steps to the ${direction}`,
1440
+ ` step ${direction}`,
1441
+ ` steps ${direction}`
1442
+ ]) {
1443
+ const index = value.toLowerCase().indexOf(prefix);
1444
+ if (index < 0) {
1445
+ continue;
1446
+ }
1447
+ let cursor = index - 1;
1448
+ while (cursor >= 0 && /\d/.test(value[cursor])) {
1449
+ cursor -= 1;
1450
+ }
1451
+ if (cursor === index - 1) {
1452
+ continue;
1453
+ }
1454
+ const start = cursor + 1;
1455
+ best = best < 0 ? start : Math.min(best, start);
1456
+ }
1457
+ }
1458
+ return best;
1459
+ }
1460
+ function parseRelativePositionPhrase(phrase) {
1461
+ const tokens = phrase.trim().toLowerCase().split(/\s+/);
1462
+ if (tokens.length < 3) {
1463
+ return void 0;
1464
+ }
1465
+ const amount = parseNonNegativeIntegerToken(tokens[0] ?? "");
1466
+ if (amount === void 0) {
1467
+ return void 0;
1468
+ }
1469
+ const direction = tokens[tokens.length - 1];
1470
+ if (direction !== "left" && direction !== "right" && direction !== "up" && direction !== "down") {
1471
+ return void 0;
1472
+ }
1473
+ if (tokens[1] !== "step" && tokens[1] !== "steps") {
1474
+ return void 0;
1475
+ }
1476
+ return { amount, direction };
1477
+ }
1478
+ function extractRelativePositionEntities(query) {
1479
+ const entities = /* @__PURE__ */ new Set();
1480
+ for (const value of extractBacktickValues(query)) {
1481
+ addRelativePositionEntity(entities, value);
1482
+ }
1483
+ const tokens = normalizeTrajectoryQuery(query).split(" ").filter(Boolean);
1484
+ for (let index = 0; index < tokens.length; index += 1) {
1485
+ const token = tokens[index];
1486
+ if (token === "relative" && tokens[index + 1] === "position") {
1487
+ const candidate = nearestEntityTokenBefore(tokens, index);
1488
+ if (candidate) {
1489
+ addRelativePositionEntity(entities, candidate);
1490
+ }
1491
+ }
1492
+ if (token === "rule" || token === "text" || token === "object") {
1493
+ const candidate = tokens[index + 1];
1494
+ if (candidate && isRelativeEntityToken(candidate)) {
1495
+ addRelativePositionEntity(entities, candidate);
1496
+ }
1497
+ }
1498
+ }
1499
+ return entities;
1500
+ }
1501
+ function extractBacktickValues(value) {
1502
+ const results = [];
1503
+ let start = value.indexOf("`");
1504
+ while (start >= 0) {
1505
+ const end = value.indexOf("`", start + 1);
1506
+ if (end < 0) {
1507
+ break;
1508
+ }
1509
+ const inner = value.slice(start + 1, end).trim();
1510
+ if (inner) {
1511
+ results.push(inner);
1512
+ }
1513
+ start = value.indexOf("`", end + 1);
1514
+ }
1515
+ return results;
1516
+ }
1517
+ function nearestEntityTokenBefore(tokens, beforeIndex) {
1518
+ for (let index = beforeIndex - 1; index >= Math.max(0, beforeIndex - 6); index -= 1) {
1519
+ const token = tokens[index];
1520
+ if (token && isRelativeEntityToken(token)) {
1521
+ return token;
1522
+ }
1523
+ }
1524
+ return void 0;
1525
+ }
1526
+ function isRelativeEntityToken(token) {
1527
+ return token.length > 1 && ![
1528
+ "block",
1529
+ "object",
1530
+ "position",
1531
+ "relative",
1532
+ "rule",
1533
+ "step",
1534
+ "steps",
1535
+ "text",
1536
+ "the"
1537
+ ].includes(token) && !isAllDigits(token);
1538
+ }
1539
+ function addRelativePositionEntity(entities, value) {
1540
+ const normalized = normalizeEntity(value);
1541
+ if (!normalized || !isRelativeEntityToken(normalized)) {
1542
+ return;
1543
+ }
1544
+ entities.add(normalized);
1545
+ entities.add(normalizeEntity(`rule ${normalized}`));
1546
+ }
1547
+ function hasManeuverInterpretationCue(normalizedQuery) {
1548
+ return [
1549
+ "strategic",
1550
+ "goal",
1551
+ "necessary",
1552
+ "critical",
1553
+ "maneuver",
1554
+ "path",
1555
+ "blocking",
1556
+ "bypass",
1557
+ "reposition"
1558
+ ].some((cue) => normalizedQuery.includes(cue));
1559
+ }
1560
+ function hasExactRelativeStateIntent(normalizedQuery) {
1561
+ return /(?:exact\s+position|relative\s+to|same\s+tile|zero[- ]offset|vanished|reappeared)/.test(
1562
+ normalizedQuery
1563
+ );
1564
+ }
1565
+ function isAllDigits(value) {
1566
+ if (value.length === 0) {
1567
+ return false;
1568
+ }
1569
+ for (const char of value) {
1570
+ if (char < "0" || char > "9") {
1571
+ return false;
1572
+ }
1573
+ }
1574
+ return true;
1575
+ }
1576
+ function inferAgentMoveFromRelativeDelta(dx, dy) {
1577
+ if (dx === 1 && dy === 0) return "left";
1578
+ if (dx === -1 && dy === 0) return "right";
1579
+ if (dx === 0 && dy === 1) return "up";
1580
+ if (dx === 0 && dy === -1) return "down";
1581
+ return void 0;
1582
+ }
1583
+ function agentMoveDeltaFromAction(action) {
1584
+ const verb = normalizeActionVerb(action);
1585
+ if (verb === "up") return { direction: "up", dx: 0, dy: -1 };
1586
+ if (verb === "down") return { direction: "down", dx: 0, dy: 1 };
1587
+ if (verb === "left") return { direction: "left", dx: -1, dy: 0 };
1588
+ if (verb === "right") return { direction: "right", dx: 1, dy: 0 };
1589
+ return void 0;
1590
+ }
1591
+ function extractDisallowedMove(normalizedQuery) {
1592
+ for (const direction of ["up", "down", "left", "right"]) {
1593
+ if (normalizedQuery.includes(`instead of moving ${direction}`) || normalizedQuery.includes(`instead of going ${direction}`)) {
1594
+ return direction;
1595
+ }
1596
+ }
1597
+ return void 0;
1598
+ }
1599
+ function selectAlternativeActionTargets(positions, normalizedQuery) {
1600
+ const targets = [];
1601
+ if (normalizedQuery.includes("win condition") || normalizedQuery.includes("win")) {
1602
+ for (const entity of ["rule win", "rule is"]) {
1603
+ const position = positions.get(entity);
1604
+ if (position) {
1605
+ targets.push({ entity, position });
1606
+ }
1607
+ }
1608
+ return targets;
1609
+ }
1610
+ for (const [entity, position] of positions.entries()) {
1611
+ if (entity.startsWith("rule ")) {
1612
+ targets.push({ entity, position });
1613
+ }
1614
+ }
1615
+ return targets;
1616
+ }
1617
+ function scoreMoveTowardTargets(move, targets) {
1618
+ let score = 0;
1619
+ for (const { position } of targets) {
1620
+ const before = Math.abs(position.x) + Math.abs(position.y);
1621
+ const after = Math.abs(position.x - move.dx) + Math.abs(position.y - move.dy);
1622
+ score += before - after;
1623
+ }
1624
+ return score;
1625
+ }
1626
+ function hasRelativeEntityInObservations(entity, observations) {
1627
+ const normalizedEntity = normalizeEntity(entity);
1628
+ for (const observation of observations) {
1629
+ if (!observation) {
1630
+ continue;
1631
+ }
1632
+ if (parseRelativePositions(observation).has(normalizedEntity)) {
1633
+ return true;
1634
+ }
1635
+ }
1636
+ return false;
1637
+ }
1638
+ function relativePositionMatchesMove(position, move) {
1639
+ return position.x === move.dx && position.y === move.dy;
1640
+ }
1641
+ function oppositeDirection(direction) {
1642
+ if (direction === "up") return "downward";
1643
+ if (direction === "down") return "upward";
1644
+ if (direction === "left") return "rightward";
1645
+ return "leftward";
1646
+ }
1647
+ function normalizeTrajectoryQuery(value) {
1648
+ return value.toLowerCase().replace(/[^a-z0-9_-]+/g, " ").trim();
1649
+ }
1650
+ function appendExpandedEvidence(evidenceItems, seenTurns, sessionId, expanded) {
1651
+ for (const message of expanded) {
1652
+ appendEvidenceItem(evidenceItems, seenTurns, {
1653
+ id: `${sessionId}:${message.turn_index}`,
1654
+ sessionId,
1655
+ turnIndex: message.turn_index,
1656
+ role: message.role,
1657
+ content: message.content
1658
+ });
1659
+ }
1660
+ }
1661
+ function appendEvidenceItem(evidenceItems, seenTurns, item) {
1662
+ if (seenTurns.has(item.id)) {
1663
+ return;
1664
+ }
1665
+ seenTurns.add(item.id);
1666
+ evidenceItems.push(item);
1667
+ }
1668
+ function collectExplicitTurnReferences(query) {
1669
+ const references = /* @__PURE__ */ new Map();
1670
+ const addReference = (value, label) => {
1671
+ const existing = references.get(String(value));
1672
+ references.set(String(value), {
1673
+ number: value,
1674
+ includeDirectTurn: (existing?.includeDirectTurn ?? false) || label === "turn"
1675
+ });
1676
+ };
1677
+ const tokens = tokenizeReferenceQuery(query);
1678
+ for (let index = 0; index < tokens.length; index += 1) {
1679
+ const label = normalizeReferenceLabel(tokens[index]);
1680
+ if (!label) {
1681
+ continue;
1682
+ }
1683
+ const parsed = parseReferenceNumbers(tokens, index + 1);
1684
+ for (const number of parsed.numbers) {
1685
+ addReference(number, label);
1686
+ }
1687
+ index = Math.max(index, parsed.nextIndex - 1);
1688
+ }
1689
+ return [...references.values()].sort((left, right) => left.number - right.number);
1690
+ }
1691
+ function collectLexicalCues(query, options = {}) {
1692
+ const cues = /* @__PURE__ */ new Set();
1693
+ for (const match of query.matchAll(/\b[A-Za-z][A-Za-z0-9]{0,12}\d+:\d+\b/g)) {
1694
+ cues.add(match[0]);
1695
+ }
1696
+ for (const match of query.matchAll(/\b\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}(?::\d{2})?Z?)?\b/g)) {
1697
+ cues.add(match[0]);
1698
+ }
1699
+ for (const cue of collectTemporalLexicalCues(query)) {
1700
+ cues.add(cue);
1701
+ }
1702
+ for (const cue of collectQuestionSlotCues(query)) {
1703
+ cues.add(cue);
1704
+ }
1705
+ if (options.includeBenchmarkAnchorCues) {
1706
+ for (const cue of collectBenchmarkAnchorCues(query)) {
1707
+ cues.add(cue);
1708
+ }
1709
+ }
1710
+ if (options.includeStructuredPlanCues) {
1711
+ for (const cue of collectStructuredPlanCues(query)) {
1712
+ cues.add(cue);
1713
+ }
1714
+ }
1715
+ for (const match of query.matchAll(/\b(?:session|source|chat|plan|task|event|file|tool)[_-][A-Za-z0-9][A-Za-z0-9_.:-]{0,80}\b/gi)) {
1716
+ cues.add(match[0]);
1717
+ }
1718
+ for (const match of query.matchAll(/\b[A-Z][a-z]{1,30}(?:\s+[A-Z][a-z]{1,30}){0,2}\b/g)) {
1719
+ const value = normalizeSpeakerNameCue(match[0]);
1720
+ if (value) {
1721
+ cues.add(value);
1722
+ }
1723
+ }
1724
+ for (const match of query.matchAll(/\[([A-Za-z0-9][A-Za-z0-9_.:/ -]{1,80})\]/g)) {
1725
+ const value = match[1]?.trim();
1726
+ if (value) {
1727
+ cues.add(value);
1728
+ }
1729
+ }
1730
+ return [...cues].sort((left, right) => left.localeCompare(right));
1731
+ }
1732
+ function collectQuestionSlotCues(query) {
1733
+ const cues = /* @__PURE__ */ new Set();
1734
+ for (const match of query.matchAll(
1735
+ /\b(?:what|which)\s+([a-z][a-z0-9_-]{2,30})\s+(?:does|do|did|is|are|was|were|should|would|could|can|will)\b/gi
1736
+ )) {
1737
+ const value = match[1]?.toLowerCase();
1738
+ if (value && !QUESTION_SLOT_STOPWORDS.has(value)) {
1739
+ cues.add(value);
1740
+ }
1741
+ }
1742
+ return [...cues].sort((left, right) => left.localeCompare(right));
1743
+ }
1744
+ function collectBenchmarkAnchorCues(query) {
1745
+ const cues = /* @__PURE__ */ new Set();
1746
+ const normalizedQuery = query.toLowerCase().replace(/\s+/g, " ");
1747
+ for (const [phrase, cue] of BENCHMARK_ABILITY_CUES) {
1748
+ if (containsBoundedPhrase(normalizedQuery, phrase)) {
1749
+ cues.add(cue);
1750
+ }
1751
+ }
1752
+ const tokens = tokenizeAnchorQuery(query);
1753
+ for (let index = 0; index < tokens.length; index += 1) {
1754
+ let prefix = normalizeBenchmarkAnchorPrefix(tokens[index]);
1755
+ if (!prefix) {
1756
+ continue;
1757
+ }
1758
+ let valueIndex = index + 1;
1759
+ if (prefix === "source" && tokens[valueIndex]?.toLowerCase() === "chat") {
1760
+ prefix = "source_chat";
1761
+ valueIndex += 1;
1762
+ }
1763
+ const maybeIdLabel = tokens[valueIndex]?.toLowerCase();
1764
+ if (maybeIdLabel === "id" || maybeIdLabel === "ids") {
1765
+ valueIndex += 1;
1766
+ }
1767
+ let consumedValue = false;
1768
+ for (let currentValueIndex = valueIndex; currentValueIndex < tokens.length; currentValueIndex += 1) {
1769
+ const rawValue = tokens[currentValueIndex];
1770
+ const normalizedValue = rawValue?.toLowerCase();
1771
+ if (!rawValue || normalizeBenchmarkAnchorPrefix(rawValue)) {
1772
+ break;
1773
+ }
1774
+ if (normalizedValue === "and" || normalizedValue === "or") {
1775
+ continue;
1776
+ }
1777
+ if (BENCHMARK_ANCHOR_VALUE_STOPWORDS.has(normalizedValue)) {
1778
+ break;
1779
+ }
1780
+ if (!isBenchmarkAnchorValue(rawValue)) {
1781
+ break;
1782
+ }
1783
+ addBenchmarkAnchorCues(cues, prefix, rawValue);
1784
+ consumedValue = true;
1785
+ index = currentValueIndex;
1786
+ }
1787
+ if (!consumedValue) {
1788
+ continue;
1789
+ }
1790
+ }
1791
+ return [...cues].sort((left, right) => left.localeCompare(right));
1792
+ }
1793
+ function addBenchmarkAnchorCues(cues, prefix, rawValue) {
1794
+ cues.add(`${prefix}_id=${rawValue}`);
1795
+ cues.add(`${prefix}-${rawValue}`);
1796
+ if (prefix === "source_chat") {
1797
+ cues.add(`chat_id=${rawValue}`);
1798
+ }
1799
+ }
1800
+ function isBenchmarkAnchorValue(token) {
1801
+ for (const char of token) {
1802
+ if (isAsciiDigitChar(char)) {
1803
+ return true;
1804
+ }
1805
+ }
1806
+ return false;
1807
+ }
1808
+ function isAsciiDigitChar(char) {
1809
+ const code = char.charCodeAt(0);
1810
+ return code >= 48 && code <= 57;
1811
+ }
1812
+ function normalizeBenchmarkAnchorPrefix(token) {
1813
+ switch (token?.toLowerCase()) {
1814
+ case "ability":
1815
+ case "chat":
1816
+ case "plan":
1817
+ case "rubric":
1818
+ case "source":
1819
+ return token.toLowerCase();
1820
+ default:
1821
+ return void 0;
1822
+ }
1823
+ }
1824
+ function tokenizeAnchorQuery(query) {
1825
+ const tokens = [];
1826
+ let current = "";
1827
+ const push = () => {
1828
+ const token = trimTrailingAnchorTokenPunctuation(current);
1829
+ if (token.length > 0) {
1830
+ tokens.push(token);
1831
+ }
1832
+ current = "";
1833
+ };
1834
+ for (const char of query) {
1835
+ if (isAsciiLetterOrDigit(char) || char === "_" || char === "-" || char === "." || char === ":") {
1836
+ current += char;
1837
+ continue;
1838
+ }
1839
+ push();
1840
+ }
1841
+ push();
1842
+ return tokens;
1843
+ }
1844
+ function trimTrailingAnchorTokenPunctuation(token) {
1845
+ let end = token.length;
1846
+ while (end > 0) {
1847
+ const char = token[end - 1];
1848
+ if (char !== "." && char !== ":" && char !== ";" && char !== "!" && char !== "?") {
1849
+ break;
1850
+ }
1851
+ end -= 1;
1852
+ }
1853
+ return token.slice(0, end);
1854
+ }
1855
+ function collectStructuredPlanCues(query) {
1856
+ const cues = /* @__PURE__ */ new Set();
1857
+ const normalizedQuery = query.toLowerCase().replace(/\s+/g, " ");
1858
+ for (const cue of STRUCTURED_PLAN_FIELD_CUES) {
1859
+ if (containsBoundedPhrase(normalizedQuery, cue)) {
1860
+ cues.add(cue);
1861
+ }
1862
+ }
1863
+ if (cues.size === 0) {
1864
+ return [];
1865
+ }
1866
+ for (const cue of STRUCTURED_PLAN_DEPENDENCY_CUES) {
1867
+ if (containsBoundedPhrase(normalizedQuery, cue)) {
1868
+ cues.add(cue);
1869
+ }
1870
+ }
1871
+ return [...cues].sort((left, right) => left.localeCompare(right));
1872
+ }
1873
+ function containsBoundedPhrase(normalizedHaystack, phrase) {
1874
+ let searchFrom = 0;
1875
+ while (searchFrom < normalizedHaystack.length) {
1876
+ const index = normalizedHaystack.indexOf(phrase, searchFrom);
1877
+ if (index < 0) {
1878
+ return false;
1879
+ }
1880
+ const afterIndex = index + phrase.length;
1881
+ if (isTemporalCueBoundary(normalizedHaystack[index - 1]) && isTemporalCueBoundary(normalizedHaystack[afterIndex])) {
1882
+ return true;
1883
+ }
1884
+ searchFrom = afterIndex;
1885
+ }
1886
+ return false;
1887
+ }
1888
+ function collectTemporalLexicalCues(query) {
1889
+ const cues = /* @__PURE__ */ new Set();
1890
+ const normalizedQuery = query.toLowerCase().replace(/\s+/g, " ");
1891
+ for (const cue of RELATIVE_TEMPORAL_CUES) {
1892
+ if (containsBoundedPhrase(normalizedQuery, cue)) {
1893
+ cues.add(cue);
1894
+ }
1895
+ }
1896
+ return [...cues].sort((left, right) => left.localeCompare(right));
1897
+ }
1898
+ function hasLatestStateIntent(query) {
1899
+ return collectTemporalLexicalCues(query).some(
1900
+ (cue) => LATEST_STATE_CUES.has(cue)
1901
+ );
1902
+ }
1903
+ function sortLexicalCueResults(results, preferLatest) {
1904
+ return [...results].sort((left, right) => {
1905
+ if (preferLatest) {
1906
+ const sessionOrder2 = left.session_id.localeCompare(right.session_id);
1907
+ if (sessionOrder2 !== 0) {
1908
+ return sessionOrder2;
1909
+ }
1910
+ const turnOrder = right.turn_index - left.turn_index;
1911
+ if (turnOrder !== 0) {
1912
+ return turnOrder;
1913
+ }
1914
+ return (right.score ?? 0) - (left.score ?? 0);
1915
+ }
1916
+ const scoreDelta = (right.score ?? 0) - (left.score ?? 0);
1917
+ if (scoreDelta !== 0) {
1918
+ return scoreDelta;
1919
+ }
1920
+ const sessionOrder = left.session_id.localeCompare(right.session_id);
1921
+ if (sessionOrder !== 0) {
1922
+ return sessionOrder;
1923
+ }
1924
+ return left.turn_index - right.turn_index;
1925
+ });
1926
+ }
1927
+ function normalizeSpeakerNameCue(value) {
1928
+ const words = value.trim().split(/\s+/).filter(Boolean);
1929
+ while (words.length > 0 && SPEAKER_NAME_STOPWORDS.has(words[0])) {
1930
+ words.shift();
1931
+ }
1932
+ while (words.length > 0 && SPEAKER_NAME_STOPWORDS.has(words[words.length - 1])) {
1933
+ words.pop();
1934
+ }
1935
+ return words.length > 0 ? words.join(" ") : void 0;
1936
+ }
1937
+ function isTemporalCueBoundary(char) {
1938
+ if (!char) {
1939
+ return true;
1940
+ }
1941
+ return !isAsciiLetterOrDigit(char);
1942
+ }
1943
+ function tokenizeReferenceQuery(query) {
1944
+ const tokens = [];
1945
+ let current = "";
1946
+ const flushCurrent = () => {
1947
+ if (current) {
1948
+ tokens.push(current);
1949
+ current = "";
1950
+ }
1951
+ };
1952
+ for (const char of query) {
1953
+ if (isAsciiLetterOrDigit(char)) {
1954
+ current += char;
1955
+ continue;
1956
+ }
1957
+ flushCurrent();
1958
+ if (char === "#" || char === ",") {
1959
+ tokens.push(char);
1960
+ } else if (isReferenceDash(char)) {
1961
+ tokens.push("-");
1962
+ }
1963
+ }
1964
+ flushCurrent();
1965
+ return tokens;
1966
+ }
1967
+ function parseReferenceNumbers(tokens, startIndex) {
1968
+ const numbers = [];
1969
+ let lastNumber;
1970
+ let pendingRangeStart;
1971
+ let index = startIndex;
1972
+ const scanEnd = Math.min(
1973
+ tokens.length,
1974
+ startIndex + DEFAULT_MAX_REFERENCES * REFERENCE_SCAN_TOKEN_FACTOR
1975
+ );
1976
+ for (; index < scanEnd; index += 1) {
1977
+ const token = tokens[index];
1978
+ const normalized = token.toLowerCase();
1979
+ const value = parseNonNegativeIntegerToken(token);
1980
+ if (value !== void 0) {
1981
+ if (pendingRangeStart !== void 0) {
1982
+ numbers.push(...expandReferenceRange(pendingRangeStart, value));
1983
+ pendingRangeStart = void 0;
1984
+ } else {
1985
+ numbers.push(value);
1986
+ }
1987
+ lastNumber = value;
1988
+ continue;
1989
+ }
1990
+ if (normalized === "#" || normalized === "number" || normalized === ",") {
1991
+ continue;
1992
+ }
1993
+ if (normalized === "-" || normalized === "to" || normalized === "through" || normalized === "thru") {
1994
+ if (lastNumber !== void 0) {
1995
+ if (numbers[numbers.length - 1] === lastNumber) {
1996
+ numbers.pop();
1997
+ }
1998
+ pendingRangeStart = lastNumber;
1999
+ }
2000
+ continue;
2001
+ }
2002
+ if (normalized === "and" && numbers.length > 0) {
2003
+ continue;
2004
+ }
2005
+ if (normalizeReferenceLabel(token)) {
2006
+ break;
2007
+ }
2008
+ break;
2009
+ }
2010
+ if (pendingRangeStart !== void 0) {
2011
+ numbers.push(pendingRangeStart);
2012
+ }
2013
+ return {
2014
+ numbers: [...new Set(numbers)],
2015
+ nextIndex: index
2016
+ };
2017
+ }
2018
+ function expandReferenceRange(start, end) {
2019
+ const low = Math.min(start, end);
2020
+ const high = Math.max(start, end);
2021
+ if (high - low + 1 > DEFAULT_MAX_REFERENCES) {
2022
+ return [start, end];
2023
+ }
2024
+ const values = [];
2025
+ for (let value = low; value <= high; value += 1) {
2026
+ values.push(value);
2027
+ }
2028
+ return values;
2029
+ }
2030
+ function normalizeReferenceLabel(token) {
2031
+ const normalized = token?.toLowerCase();
2032
+ switch (normalized) {
2033
+ case "step":
2034
+ case "steps":
2035
+ return "step";
2036
+ case "turn":
2037
+ case "turns":
2038
+ return "turn";
2039
+ case "action":
2040
+ case "actions":
2041
+ return "action";
2042
+ case "observation":
2043
+ case "observations":
2044
+ return "observation";
2045
+ default:
2046
+ return void 0;
2047
+ }
2048
+ }
2049
+ function candidateTurnIndexesForReference(reference) {
2050
+ const candidates = /* @__PURE__ */ new Set();
2051
+ if (reference.includeDirectTurn) {
2052
+ for (let offset = -1; offset <= 1; offset += 1) {
2053
+ candidates.add(reference.number + offset);
2054
+ }
2055
+ }
2056
+ const pairedBase = reference.number * 2;
2057
+ for (let offset = -1; offset <= 1; offset += 1) {
2058
+ candidates.add(pairedBase + offset);
2059
+ }
2060
+ return [...candidates].sort((left, right) => left - right);
2061
+ }
2062
+ function parseNonNegativeIntegerToken(token) {
2063
+ if (token.length === 0) {
2064
+ return void 0;
2065
+ }
2066
+ let value = 0;
2067
+ for (const char of token) {
2068
+ const code = char.charCodeAt(0);
2069
+ if (code < 48 || code > 57) {
2070
+ return void 0;
2071
+ }
2072
+ value = value * 10 + (code - 48);
2073
+ }
2074
+ return value;
2075
+ }
2076
+ function normalizePositiveInteger(value, fallback) {
2077
+ if (typeof value !== "number" || !Number.isFinite(value)) {
2078
+ return fallback;
2079
+ }
2080
+ return Math.max(0, Math.floor(value));
2081
+ }
2082
+ function isAsciiLetterOrDigit(char) {
2083
+ const code = char.charCodeAt(0);
2084
+ return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122;
2085
+ }
2086
+ function isReferenceDash(char) {
2087
+ return char === "-" || char === "\u2010" || char === "\u2011" || char === "\u2012" || char === "\u2013" || char === "\u2014" || char === "\u2015";
2088
+ }
2089
+
2090
+ export {
2091
+ buildExplicitCueRecallSection,
2092
+ buildTrajectoryAnalysisRecallSection,
2093
+ normalizeTurnExpansionEnd,
2094
+ collectExplicitTurnReferences,
2095
+ collectLexicalCues,
2096
+ collectQuestionSlotCues,
2097
+ collectBenchmarkAnchorCues,
2098
+ collectStructuredPlanCues,
2099
+ collectTemporalLexicalCues
2100
+ };
2101
+ //# sourceMappingURL=chunk-S2JJBLJG.js.map