bead 0.1.0__py3-none-any.whl

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 (231) hide show
  1. bead/__init__.py +11 -0
  2. bead/__main__.py +11 -0
  3. bead/active_learning/__init__.py +15 -0
  4. bead/active_learning/config.py +231 -0
  5. bead/active_learning/loop.py +566 -0
  6. bead/active_learning/models/__init__.py +24 -0
  7. bead/active_learning/models/base.py +852 -0
  8. bead/active_learning/models/binary.py +910 -0
  9. bead/active_learning/models/categorical.py +943 -0
  10. bead/active_learning/models/cloze.py +862 -0
  11. bead/active_learning/models/forced_choice.py +956 -0
  12. bead/active_learning/models/free_text.py +773 -0
  13. bead/active_learning/models/lora.py +365 -0
  14. bead/active_learning/models/magnitude.py +835 -0
  15. bead/active_learning/models/multi_select.py +795 -0
  16. bead/active_learning/models/ordinal_scale.py +811 -0
  17. bead/active_learning/models/peft_adapter.py +155 -0
  18. bead/active_learning/models/random_effects.py +639 -0
  19. bead/active_learning/selection.py +354 -0
  20. bead/active_learning/strategies.py +391 -0
  21. bead/active_learning/trainers/__init__.py +26 -0
  22. bead/active_learning/trainers/base.py +210 -0
  23. bead/active_learning/trainers/data_collator.py +172 -0
  24. bead/active_learning/trainers/dataset_utils.py +261 -0
  25. bead/active_learning/trainers/huggingface.py +304 -0
  26. bead/active_learning/trainers/lightning.py +324 -0
  27. bead/active_learning/trainers/metrics.py +424 -0
  28. bead/active_learning/trainers/mixed_effects.py +551 -0
  29. bead/active_learning/trainers/model_wrapper.py +509 -0
  30. bead/active_learning/trainers/registry.py +104 -0
  31. bead/adapters/__init__.py +11 -0
  32. bead/adapters/huggingface.py +61 -0
  33. bead/behavioral/__init__.py +116 -0
  34. bead/behavioral/analytics.py +646 -0
  35. bead/behavioral/extraction.py +343 -0
  36. bead/behavioral/merging.py +343 -0
  37. bead/cli/__init__.py +11 -0
  38. bead/cli/active_learning.py +513 -0
  39. bead/cli/active_learning_commands.py +779 -0
  40. bead/cli/completion.py +359 -0
  41. bead/cli/config.py +624 -0
  42. bead/cli/constraint_builders.py +286 -0
  43. bead/cli/deployment.py +859 -0
  44. bead/cli/deployment_trials.py +493 -0
  45. bead/cli/deployment_ui.py +332 -0
  46. bead/cli/display.py +378 -0
  47. bead/cli/items.py +960 -0
  48. bead/cli/items_factories.py +776 -0
  49. bead/cli/list_constraints.py +714 -0
  50. bead/cli/lists.py +490 -0
  51. bead/cli/main.py +430 -0
  52. bead/cli/models.py +877 -0
  53. bead/cli/resource_loaders.py +621 -0
  54. bead/cli/resources.py +1036 -0
  55. bead/cli/shell.py +356 -0
  56. bead/cli/simulate.py +840 -0
  57. bead/cli/templates.py +1158 -0
  58. bead/cli/training.py +1080 -0
  59. bead/cli/utils.py +614 -0
  60. bead/cli/workflow.py +1273 -0
  61. bead/config/__init__.py +68 -0
  62. bead/config/active_learning.py +1009 -0
  63. bead/config/config.py +192 -0
  64. bead/config/defaults.py +118 -0
  65. bead/config/deployment.py +217 -0
  66. bead/config/env.py +147 -0
  67. bead/config/item.py +45 -0
  68. bead/config/list.py +193 -0
  69. bead/config/loader.py +149 -0
  70. bead/config/logging.py +42 -0
  71. bead/config/model.py +49 -0
  72. bead/config/paths.py +46 -0
  73. bead/config/profiles.py +320 -0
  74. bead/config/resources.py +47 -0
  75. bead/config/serialization.py +210 -0
  76. bead/config/simulation.py +206 -0
  77. bead/config/template.py +238 -0
  78. bead/config/validation.py +267 -0
  79. bead/data/__init__.py +65 -0
  80. bead/data/base.py +87 -0
  81. bead/data/identifiers.py +97 -0
  82. bead/data/language_codes.py +61 -0
  83. bead/data/metadata.py +270 -0
  84. bead/data/range.py +123 -0
  85. bead/data/repository.py +358 -0
  86. bead/data/serialization.py +249 -0
  87. bead/data/timestamps.py +89 -0
  88. bead/data/validation.py +349 -0
  89. bead/data_collection/__init__.py +11 -0
  90. bead/data_collection/jatos.py +223 -0
  91. bead/data_collection/merger.py +154 -0
  92. bead/data_collection/prolific.py +198 -0
  93. bead/deployment/__init__.py +5 -0
  94. bead/deployment/distribution.py +402 -0
  95. bead/deployment/jatos/__init__.py +1 -0
  96. bead/deployment/jatos/api.py +200 -0
  97. bead/deployment/jatos/exporter.py +210 -0
  98. bead/deployment/jspsych/__init__.py +9 -0
  99. bead/deployment/jspsych/biome.json +44 -0
  100. bead/deployment/jspsych/config.py +411 -0
  101. bead/deployment/jspsych/generator.py +598 -0
  102. bead/deployment/jspsych/package.json +51 -0
  103. bead/deployment/jspsych/pnpm-lock.yaml +2141 -0
  104. bead/deployment/jspsych/randomizer.py +299 -0
  105. bead/deployment/jspsych/src/lib/list-distributor.test.ts +327 -0
  106. bead/deployment/jspsych/src/lib/list-distributor.ts +1282 -0
  107. bead/deployment/jspsych/src/lib/randomizer.test.ts +232 -0
  108. bead/deployment/jspsych/src/lib/randomizer.ts +367 -0
  109. bead/deployment/jspsych/src/plugins/cloze-dropdown.ts +252 -0
  110. bead/deployment/jspsych/src/plugins/forced-choice.ts +265 -0
  111. bead/deployment/jspsych/src/plugins/plugins.test.ts +141 -0
  112. bead/deployment/jspsych/src/plugins/rating.ts +248 -0
  113. bead/deployment/jspsych/src/slopit/index.ts +9 -0
  114. bead/deployment/jspsych/src/types/jatos.d.ts +256 -0
  115. bead/deployment/jspsych/src/types/jspsych.d.ts +228 -0
  116. bead/deployment/jspsych/templates/experiment.css +1 -0
  117. bead/deployment/jspsych/templates/experiment.js.template +289 -0
  118. bead/deployment/jspsych/templates/index.html +51 -0
  119. bead/deployment/jspsych/templates/randomizer.js +241 -0
  120. bead/deployment/jspsych/templates/randomizer.js.template +313 -0
  121. bead/deployment/jspsych/trials.py +723 -0
  122. bead/deployment/jspsych/tsconfig.json +23 -0
  123. bead/deployment/jspsych/tsup.config.ts +30 -0
  124. bead/deployment/jspsych/ui/__init__.py +1 -0
  125. bead/deployment/jspsych/ui/components.py +383 -0
  126. bead/deployment/jspsych/ui/styles.py +411 -0
  127. bead/dsl/__init__.py +80 -0
  128. bead/dsl/ast.py +168 -0
  129. bead/dsl/context.py +178 -0
  130. bead/dsl/errors.py +71 -0
  131. bead/dsl/evaluator.py +570 -0
  132. bead/dsl/grammar.lark +81 -0
  133. bead/dsl/parser.py +231 -0
  134. bead/dsl/stdlib.py +929 -0
  135. bead/evaluation/__init__.py +13 -0
  136. bead/evaluation/convergence.py +485 -0
  137. bead/evaluation/interannotator.py +398 -0
  138. bead/items/__init__.py +40 -0
  139. bead/items/adapters/__init__.py +70 -0
  140. bead/items/adapters/anthropic.py +224 -0
  141. bead/items/adapters/api_utils.py +167 -0
  142. bead/items/adapters/base.py +216 -0
  143. bead/items/adapters/google.py +259 -0
  144. bead/items/adapters/huggingface.py +1074 -0
  145. bead/items/adapters/openai.py +323 -0
  146. bead/items/adapters/registry.py +202 -0
  147. bead/items/adapters/sentence_transformers.py +224 -0
  148. bead/items/adapters/togetherai.py +309 -0
  149. bead/items/binary.py +515 -0
  150. bead/items/cache.py +558 -0
  151. bead/items/categorical.py +593 -0
  152. bead/items/cloze.py +757 -0
  153. bead/items/constructor.py +784 -0
  154. bead/items/forced_choice.py +413 -0
  155. bead/items/free_text.py +681 -0
  156. bead/items/generation.py +432 -0
  157. bead/items/item.py +396 -0
  158. bead/items/item_template.py +787 -0
  159. bead/items/magnitude.py +573 -0
  160. bead/items/multi_select.py +621 -0
  161. bead/items/ordinal_scale.py +569 -0
  162. bead/items/scoring.py +448 -0
  163. bead/items/validation.py +723 -0
  164. bead/lists/__init__.py +30 -0
  165. bead/lists/balancer.py +263 -0
  166. bead/lists/constraints.py +1067 -0
  167. bead/lists/experiment_list.py +286 -0
  168. bead/lists/list_collection.py +378 -0
  169. bead/lists/partitioner.py +1141 -0
  170. bead/lists/stratification.py +254 -0
  171. bead/participants/__init__.py +73 -0
  172. bead/participants/collection.py +699 -0
  173. bead/participants/merging.py +312 -0
  174. bead/participants/metadata_spec.py +491 -0
  175. bead/participants/models.py +276 -0
  176. bead/resources/__init__.py +29 -0
  177. bead/resources/adapters/__init__.py +19 -0
  178. bead/resources/adapters/base.py +104 -0
  179. bead/resources/adapters/cache.py +128 -0
  180. bead/resources/adapters/glazing.py +508 -0
  181. bead/resources/adapters/registry.py +117 -0
  182. bead/resources/adapters/unimorph.py +796 -0
  183. bead/resources/classification.py +856 -0
  184. bead/resources/constraint_builders.py +329 -0
  185. bead/resources/constraints.py +165 -0
  186. bead/resources/lexical_item.py +223 -0
  187. bead/resources/lexicon.py +744 -0
  188. bead/resources/loaders.py +209 -0
  189. bead/resources/template.py +441 -0
  190. bead/resources/template_collection.py +707 -0
  191. bead/resources/template_generation.py +349 -0
  192. bead/simulation/__init__.py +29 -0
  193. bead/simulation/annotators/__init__.py +15 -0
  194. bead/simulation/annotators/base.py +175 -0
  195. bead/simulation/annotators/distance_based.py +135 -0
  196. bead/simulation/annotators/lm_based.py +114 -0
  197. bead/simulation/annotators/oracle.py +182 -0
  198. bead/simulation/annotators/random.py +181 -0
  199. bead/simulation/dsl_extension/__init__.py +3 -0
  200. bead/simulation/noise_models/__init__.py +13 -0
  201. bead/simulation/noise_models/base.py +42 -0
  202. bead/simulation/noise_models/random_noise.py +82 -0
  203. bead/simulation/noise_models/systematic.py +132 -0
  204. bead/simulation/noise_models/temperature.py +86 -0
  205. bead/simulation/runner.py +144 -0
  206. bead/simulation/strategies/__init__.py +23 -0
  207. bead/simulation/strategies/base.py +123 -0
  208. bead/simulation/strategies/binary.py +103 -0
  209. bead/simulation/strategies/categorical.py +123 -0
  210. bead/simulation/strategies/cloze.py +224 -0
  211. bead/simulation/strategies/forced_choice.py +127 -0
  212. bead/simulation/strategies/free_text.py +105 -0
  213. bead/simulation/strategies/magnitude.py +116 -0
  214. bead/simulation/strategies/multi_select.py +129 -0
  215. bead/simulation/strategies/ordinal_scale.py +131 -0
  216. bead/templates/__init__.py +27 -0
  217. bead/templates/adapters/__init__.py +17 -0
  218. bead/templates/adapters/base.py +128 -0
  219. bead/templates/adapters/cache.py +178 -0
  220. bead/templates/adapters/huggingface.py +312 -0
  221. bead/templates/combinatorics.py +103 -0
  222. bead/templates/filler.py +605 -0
  223. bead/templates/renderers.py +177 -0
  224. bead/templates/resolver.py +178 -0
  225. bead/templates/strategies.py +1806 -0
  226. bead/templates/streaming.py +195 -0
  227. bead-0.1.0.dist-info/METADATA +212 -0
  228. bead-0.1.0.dist-info/RECORD +231 -0
  229. bead-0.1.0.dist-info/WHEEL +4 -0
  230. bead-0.1.0.dist-info/entry_points.txt +2 -0
  231. bead-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,248 @@
1
+ /**
2
+ * bead-rating plugin
3
+ *
4
+ * jsPsych plugin for ordinal scale judgments (Likert scales, rating scales).
5
+ *
6
+ * Features:
7
+ * - Discrete scales (e.g., 1-7, 1-9)
8
+ * - Custom labels for scale points
9
+ * - Keyboard shortcuts (number keys 1-9)
10
+ * - Material Design styling
11
+ * - Required response validation
12
+ * - Preserves all item and template metadata
13
+ *
14
+ * @author Bead Project
15
+ * @version 0.1.0
16
+ */
17
+
18
+ import type { JsPsych, JsPsychPlugin, KeyboardResponseInfo, PluginInfo } from "../types/jspsych.js";
19
+
20
+ /** Task specification from bead metadata */
21
+ interface TaskSpec {
22
+ scale_bounds?: [number, number];
23
+ scale_labels?: Record<number, string>;
24
+ prompt?: string;
25
+ }
26
+
27
+ /** Bead item/template metadata */
28
+ interface BeadMetadata {
29
+ task_spec?: TaskSpec;
30
+ [key: string]: unknown;
31
+ }
32
+
33
+ /** Rating trial parameters */
34
+ export interface RatingTrialParams {
35
+ /** The prompt to display above the rating scale */
36
+ prompt: string | null;
37
+ /** Minimum value of the scale */
38
+ scale_min: number;
39
+ /** Maximum value of the scale */
40
+ scale_max: number;
41
+ /** Labels for specific scale points (e.g., {1: "Strongly Disagree", 7: "Strongly Agree"}) */
42
+ scale_labels: Record<number, string>;
43
+ /** Whether to require a response before continuing */
44
+ require_response: boolean;
45
+ /** Text for the continue button */
46
+ button_label: string;
47
+ /** Complete item and template metadata (automatically populated from trial.data) */
48
+ metadata: BeadMetadata;
49
+ }
50
+
51
+ /** Rating response data */
52
+ interface RatingResponse {
53
+ rating: number | null;
54
+ rt: number | null;
55
+ }
56
+
57
+ /** Plugin info constant */
58
+ const info: PluginInfo = {
59
+ name: "bead-rating",
60
+ parameters: {
61
+ prompt: {
62
+ type: 8, // ParameterType.HTML_STRING
63
+ default: null,
64
+ },
65
+ scale_min: {
66
+ type: 2, // ParameterType.INT
67
+ default: 1,
68
+ },
69
+ scale_max: {
70
+ type: 2, // ParameterType.INT
71
+ default: 7,
72
+ },
73
+ scale_labels: {
74
+ type: 12, // ParameterType.OBJECT
75
+ default: {},
76
+ },
77
+ require_response: {
78
+ type: 0, // ParameterType.BOOL
79
+ default: true,
80
+ },
81
+ button_label: {
82
+ type: 1, // ParameterType.STRING
83
+ default: "Continue",
84
+ },
85
+ metadata: {
86
+ type: 12, // ParameterType.OBJECT
87
+ default: {},
88
+ },
89
+ },
90
+ };
91
+
92
+ /**
93
+ * BeadRatingPlugin - jsPsych plugin for ordinal scale judgments
94
+ */
95
+ class BeadRatingPlugin implements JsPsychPlugin<typeof info, RatingTrialParams> {
96
+ static info = info;
97
+
98
+ private jsPsych: JsPsych;
99
+
100
+ constructor(jsPsych: JsPsych) {
101
+ this.jsPsych = jsPsych;
102
+ }
103
+
104
+ trial(display_element: HTMLElement, trial: RatingTrialParams): void {
105
+ const response: RatingResponse = {
106
+ rating: null,
107
+ rt: null,
108
+ };
109
+
110
+ const start_time = performance.now();
111
+
112
+ // Override scale bounds from metadata if available
113
+ if (trial.metadata.task_spec?.scale_bounds) {
114
+ trial.scale_min = trial.metadata.task_spec.scale_bounds[0];
115
+ trial.scale_max = trial.metadata.task_spec.scale_bounds[1];
116
+ }
117
+
118
+ // Override scale labels from metadata if available
119
+ if (trial.metadata.task_spec?.scale_labels) {
120
+ trial.scale_labels = trial.metadata.task_spec.scale_labels;
121
+ }
122
+
123
+ // Override prompt from metadata if available
124
+ if (trial.metadata.task_spec?.prompt && !trial.prompt) {
125
+ trial.prompt = trial.metadata.task_spec.prompt;
126
+ }
127
+
128
+ // Create HTML
129
+ let html = '<div class="bead-rating-container">';
130
+
131
+ if (trial.prompt !== null) {
132
+ html += `<div class="bead-rating-prompt">${trial.prompt}</div>`;
133
+ }
134
+
135
+ html += '<div class="bead-rating-scale">';
136
+
137
+ // Create rating buttons
138
+ for (let i = trial.scale_min; i <= trial.scale_max; i++) {
139
+ const label = trial.scale_labels[i] ?? i;
140
+ html += `
141
+ <div class="bead-rating-option">
142
+ <button class="bead-rating-button" data-value="${i}">${i}</button>
143
+ <div class="bead-rating-label">${label}</div>
144
+ </div>
145
+ `;
146
+ }
147
+
148
+ html += "</div>"; // Close scale
149
+
150
+ // Continue button
151
+ html += `
152
+ <div class="bead-rating-button-container">
153
+ <button class="bead-button bead-continue-button" id="bead-rating-continue" disabled>
154
+ ${trial.button_label}
155
+ </button>
156
+ </div>
157
+ `;
158
+
159
+ html += "</div>"; // Close container
160
+
161
+ display_element.innerHTML = html;
162
+
163
+ // Add event listeners for rating buttons
164
+ const rating_buttons =
165
+ display_element.querySelectorAll<HTMLButtonElement>(".bead-rating-button");
166
+ for (const button of rating_buttons) {
167
+ button.addEventListener("click", (e) => {
168
+ const target = e.target as HTMLButtonElement;
169
+ const valueAttr = target.getAttribute("data-value");
170
+ if (valueAttr !== null) {
171
+ const value = Number.parseInt(valueAttr, 10);
172
+ select_rating(value);
173
+ }
174
+ });
175
+ }
176
+
177
+ // Keyboard listener
178
+ const keyboard_listener = this.jsPsych.pluginAPI.getKeyboardResponse({
179
+ callback_function: (info: KeyboardResponseInfo) => {
180
+ // Check if key is 1-9
181
+ const key = info.key;
182
+ const num = Number.parseInt(key, 10);
183
+ if (!Number.isNaN(num) && num >= trial.scale_min && num <= trial.scale_max) {
184
+ select_rating(num);
185
+ }
186
+ },
187
+ valid_responses: "ALL_KEYS",
188
+ rt_method: "performance",
189
+ persist: true,
190
+ allow_held_key: false,
191
+ });
192
+
193
+ // Continue button listener
194
+ const continue_button =
195
+ display_element.querySelector<HTMLButtonElement>("#bead-rating-continue");
196
+ if (continue_button) {
197
+ continue_button.addEventListener("click", () => {
198
+ if (response.rating !== null || !trial.require_response) {
199
+ end_trial();
200
+ }
201
+ });
202
+ }
203
+
204
+ const select_rating = (value: number): void => {
205
+ // Update response
206
+ response.rating = value;
207
+ response.rt = performance.now() - start_time;
208
+
209
+ // Update UI
210
+ for (const btn of rating_buttons) {
211
+ btn.classList.remove("selected");
212
+ }
213
+ const selected_button = display_element.querySelector<HTMLButtonElement>(
214
+ `[data-value="${value}"]`,
215
+ );
216
+ if (selected_button) {
217
+ selected_button.classList.add("selected");
218
+ }
219
+
220
+ // Enable continue button
221
+ if (continue_button) {
222
+ continue_button.disabled = false;
223
+ }
224
+ };
225
+
226
+ const end_trial = (): void => {
227
+ // Kill keyboard listener
228
+ if (keyboard_listener) {
229
+ this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboard_listener);
230
+ }
231
+
232
+ // Preserve all metadata from trial.metadata and add response data
233
+ const trial_data: Record<string, unknown> = {
234
+ ...trial.metadata, // Spread all metadata
235
+ rating: response.rating,
236
+ rt: response.rt,
237
+ };
238
+
239
+ // Clear display
240
+ display_element.innerHTML = "";
241
+
242
+ // End trial
243
+ this.jsPsych.finishTrial(trial_data);
244
+ };
245
+ }
246
+ }
247
+
248
+ export { BeadRatingPlugin };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Slopit bundle for bead experiments.
3
+ *
4
+ * This module re-exports the slopit jsPsych adapter for use in
5
+ * browser-based experiments.
6
+ */
7
+
8
+ // Re-export the jsPsych extension from slopit
9
+ export { SlopitExtension } from "@slopit/adapter-jspsych";
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Type declarations for JATOS (Just Another Tool for Online Studies) API.
3
+ *
4
+ * JATOS provides a server-side infrastructure for running online experiments
5
+ * with features like batch sessions, worker management, and data storage.
6
+ */
7
+
8
+ /** JATOS URL query parameters (typically from Prolific/MTurk) */
9
+ export interface JatosUrlParams {
10
+ /** Prolific participant ID */
11
+ PROLIFIC_PID?: string;
12
+ /** Prolific study ID */
13
+ STUDY_ID?: string;
14
+ /** Prolific session ID */
15
+ SESSION_ID?: string;
16
+ /** Generic participant ID */
17
+ participant_id?: string;
18
+ /** Any other URL parameters */
19
+ [key: string]: string | undefined;
20
+ }
21
+
22
+ /** Batch session data stored in JATOS */
23
+ export interface BatchSessionData {
24
+ /** Assignment queue for random/sequential distribution */
25
+ assignment_queue?: number[];
26
+ /** Counts of participants assigned to each list */
27
+ assignment_counts?: Record<string, number>;
28
+ /** Latin square counter for counterbalancing */
29
+ latin_square_counter?: number;
30
+ /** Quota tracking per list */
31
+ quotas?: Record<string, number>;
32
+ /** Workers currently assigned (for completion tracking) */
33
+ active_workers?: Record<string, number>;
34
+ /** Workers who completed the study */
35
+ completed_workers?: string[];
36
+ /** Custom metadata for stratification */
37
+ stratification_state?: Record<string, unknown>;
38
+ /** Version for optimistic locking */
39
+ version?: number;
40
+ /** Any other batch session data */
41
+ [key: string]: unknown;
42
+ }
43
+
44
+ /** JATOS batch session API */
45
+ export interface JatosBatchSession {
46
+ /**
47
+ * Get a value from the batch session by path.
48
+ * Uses dot notation (e.g., "assignment_counts.list_0").
49
+ */
50
+ get<T = unknown>(path: string): T | undefined;
51
+
52
+ /**
53
+ * Check if a path is defined in the batch session.
54
+ */
55
+ defined(path: string): boolean;
56
+
57
+ /**
58
+ * Set a value in the batch session.
59
+ * Returns a promise that resolves when the write is confirmed.
60
+ */
61
+ set<T>(path: string, value: T): JatosPromise<void>;
62
+
63
+ /**
64
+ * Replace the entire batch session data.
65
+ * Useful for atomic updates.
66
+ */
67
+ replace(data: BatchSessionData): JatosPromise<void>;
68
+
69
+ /**
70
+ * Remove a value from the batch session.
71
+ */
72
+ remove(path: string): JatosPromise<void>;
73
+
74
+ /**
75
+ * Find a value using JSON pointer or path.
76
+ */
77
+ find(path: string): unknown;
78
+
79
+ /**
80
+ * Get all batch session data.
81
+ */
82
+ getAll(): BatchSessionData;
83
+
84
+ /**
85
+ * Clear all batch session data.
86
+ */
87
+ clear(): JatosPromise<void>;
88
+ }
89
+
90
+ /** JATOS-style promise with .fail() for error handling */
91
+ export interface JatosPromise<T> extends Promise<T> {
92
+ /**
93
+ * Handle errors (JATOS uses .fail() instead of .catch()).
94
+ */
95
+ fail(onRejected: (reason: Error) => void): JatosPromise<T>;
96
+
97
+ /**
98
+ * Chain operations (alias for .then()).
99
+ */
100
+ then<TResult1 = T, TResult2 = never>(
101
+ onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
102
+ onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,
103
+ ): JatosPromise<TResult1 | TResult2>;
104
+ }
105
+
106
+ /** Component result state */
107
+ export type ComponentResultState =
108
+ | "PRE"
109
+ | "STARTED"
110
+ | "DATA_RETRIEVED"
111
+ | "RESULTDATA_POSTED"
112
+ | "FINISHED"
113
+ | "RELOADED"
114
+ | "ABORTED"
115
+ | "FAIL";
116
+
117
+ /** Study result state */
118
+ export type StudyResultState =
119
+ | "PRE"
120
+ | "STARTED"
121
+ | "DATA_RETRIEVED"
122
+ | "FINISHED"
123
+ | "ABORTED"
124
+ | "FAIL";
125
+
126
+ /** Main JATOS API interface */
127
+ export interface JatosAPI {
128
+ /** Current JATOS version */
129
+ version: string;
130
+
131
+ /** Worker ID assigned by JATOS */
132
+ workerId: string;
133
+
134
+ /** Current study result ID */
135
+ studyResultId: string;
136
+
137
+ /** Current component result ID */
138
+ componentResultId: string;
139
+
140
+ /** Study ID */
141
+ studyId: string;
142
+
143
+ /** Component ID */
144
+ componentId: string;
145
+
146
+ /** Batch ID */
147
+ batchId: string;
148
+
149
+ /** Group result ID (if in group study) */
150
+ groupResultId?: string;
151
+
152
+ /** URL query parameters */
153
+ urlQueryParameters: JatosUrlParams;
154
+
155
+ /** Study properties set in JATOS GUI */
156
+ studyProperties: Record<string, unknown>;
157
+
158
+ /** Component properties set in JATOS GUI */
159
+ componentProperties: Record<string, unknown>;
160
+
161
+ /** Study session data (persists across components) */
162
+ studySessionData: Record<string, unknown>;
163
+
164
+ /** Batch session API */
165
+ batchSession: JatosBatchSession;
166
+
167
+ /**
168
+ * Called when JATOS is ready.
169
+ */
170
+ onLoad(callback: () => void): void;
171
+
172
+ /**
173
+ * Submit result data to JATOS.
174
+ */
175
+ submitResultData(data: string | object): JatosPromise<void>;
176
+
177
+ /**
178
+ * Append to result data.
179
+ */
180
+ appendResultData(data: string | object): JatosPromise<void>;
181
+
182
+ /**
183
+ * End the study successfully.
184
+ */
185
+ endStudy(successful?: boolean, message?: string): void;
186
+
187
+ /**
188
+ * End the study and redirect to a URL.
189
+ */
190
+ endStudyAndRedirect(url: string, message?: string): void;
191
+
192
+ /**
193
+ * End the current component and move to next.
194
+ */
195
+ startNextComponent(): void;
196
+
197
+ /**
198
+ * End the current component and move to a specific component.
199
+ */
200
+ startComponent(componentId: number | string): void;
201
+
202
+ /**
203
+ * End the current component and move to the last component.
204
+ */
205
+ startLastComponent(): void;
206
+
207
+ /**
208
+ * Abort the study.
209
+ */
210
+ abortStudy(message?: string): void;
211
+
212
+ /**
213
+ * Add an abort button to the page.
214
+ */
215
+ addAbortButton(): void;
216
+
217
+ /**
218
+ * Remove the abort button.
219
+ */
220
+ removeAbortButton(): void;
221
+
222
+ /**
223
+ * Log a message to the JATOS console.
224
+ */
225
+ log(message: string): void;
226
+
227
+ /**
228
+ * Set study session data.
229
+ */
230
+ setStudySessionData(data: Record<string, unknown>): JatosPromise<void>;
231
+
232
+ /**
233
+ * Upload a file to JATOS.
234
+ */
235
+ uploadResultFile(file: File | Blob, filename: string): JatosPromise<{ url: string }>;
236
+
237
+ /**
238
+ * Download study assets.
239
+ */
240
+ downloadAssetFile(filename: string): Promise<Blob>;
241
+
242
+ /**
243
+ * Get the component result state.
244
+ */
245
+ getComponentResultState(): ComponentResultState;
246
+
247
+ /**
248
+ * Get the study result state.
249
+ */
250
+ getStudyResultState(): StudyResultState;
251
+ }
252
+
253
+ /** Global JATOS instance */
254
+ declare global {
255
+ const jatos: JatosAPI;
256
+ }