modjules 0.1.1

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.
@@ -0,0 +1,927 @@
1
+ class g extends Error {
2
+ /** The original error that caused this error, if any. */
3
+ cause;
4
+ constructor(t, e) {
5
+ super(t), this.name = this.constructor.name, this.cause = e?.cause;
6
+ }
7
+ }
8
+ class k extends g {
9
+ url;
10
+ constructor(t, e) {
11
+ super(`Network request to ${t} failed`, e), this.url = t;
12
+ }
13
+ }
14
+ class f extends g {
15
+ url;
16
+ status;
17
+ statusText;
18
+ constructor(t, e, i, a, r) {
19
+ const o = a ?? `[${e} ${i}] Request to ${t} failed`;
20
+ super(o, r), this.url = t, this.status = e, this.statusText = i;
21
+ }
22
+ }
23
+ class x extends f {
24
+ constructor(t, e, i) {
25
+ super(
26
+ t,
27
+ e,
28
+ i,
29
+ `[${e} ${i}] Authentication to ${t} failed. Ensure your API key is correct.`
30
+ );
31
+ }
32
+ }
33
+ class E extends f {
34
+ constructor(t, e, i) {
35
+ super(
36
+ t,
37
+ e,
38
+ i,
39
+ `[${e} ${i}] API rate limit exceeded for ${t}.`
40
+ );
41
+ }
42
+ }
43
+ class I extends g {
44
+ constructor() {
45
+ super(
46
+ "Jules API key is missing. Pass it to the constructor or set the JULES_API_KEY environment variable."
47
+ );
48
+ }
49
+ }
50
+ class A extends g {
51
+ constructor(t) {
52
+ super(`Could not get source '${t}'`);
53
+ }
54
+ }
55
+ class P extends g {
56
+ constructor(t) {
57
+ let e = "The Jules automated session terminated with a FAILED state.";
58
+ t && (e += ` Reason: ${t}`), super(e);
59
+ }
60
+ }
61
+ class q extends g {
62
+ constructor(t) {
63
+ super(t);
64
+ }
65
+ }
66
+ class U {
67
+ apiKey;
68
+ baseUrl;
69
+ requestTimeoutMs;
70
+ constructor(t) {
71
+ this.apiKey = t.apiKey, this.baseUrl = t.baseUrl, this.requestTimeoutMs = t.requestTimeoutMs;
72
+ }
73
+ async request(t, e = {}) {
74
+ if (!this.apiKey)
75
+ throw new I();
76
+ const { method: i = "GET", body: a, params: r } = e, o = new URL(`${this.baseUrl}/${t}`);
77
+ r && Object.entries(r).forEach(([l, u]) => {
78
+ o.searchParams.append(l, u);
79
+ });
80
+ const p = {
81
+ "X-Goog-Api-Key": this.apiKey,
82
+ "Content-Type": "application/json"
83
+ }, c = new AbortController(), d = setTimeout(
84
+ () => c.abort(),
85
+ this.requestTimeoutMs
86
+ );
87
+ let n;
88
+ try {
89
+ n = await fetch(o.toString(), {
90
+ method: i,
91
+ headers: p,
92
+ body: a ? JSON.stringify(a) : void 0,
93
+ signal: c.signal
94
+ });
95
+ } catch (l) {
96
+ throw new k(o.toString(), {
97
+ cause: l
98
+ });
99
+ } finally {
100
+ clearTimeout(d);
101
+ }
102
+ if (!n.ok)
103
+ switch (n.status) {
104
+ case 401:
105
+ case 403:
106
+ throw new x(
107
+ o.toString(),
108
+ n.status,
109
+ n.statusText
110
+ );
111
+ case 429:
112
+ throw new E(
113
+ o.toString(),
114
+ n.status,
115
+ n.statusText
116
+ );
117
+ default:
118
+ const l = await n.text().catch(() => "Could not read error body"), u = `[${n.status} ${n.statusText}] ${i} ${o.toString()} - ${l}`;
119
+ throw new f(
120
+ o.toString(),
121
+ n.status,
122
+ n.statusText,
123
+ u
124
+ );
125
+ }
126
+ const h = await n.text();
127
+ return h ? JSON.parse(h) : {};
128
+ }
129
+ }
130
+ function v(s) {
131
+ if (s.githubRepo)
132
+ return {
133
+ name: s.name,
134
+ id: s.id,
135
+ type: "githubRepo",
136
+ githubRepo: s.githubRepo
137
+ };
138
+ throw new Error(`Unknown source type for source: ${s.name}`);
139
+ }
140
+ class R {
141
+ apiClient;
142
+ constructor(t) {
143
+ this.apiClient = t;
144
+ }
145
+ /**
146
+ * Lists all connected sources.
147
+ *
148
+ * **Logic:**
149
+ * - Automatically handles API pagination by following `nextPageToken`.
150
+ * - Yields sources one by one as they are retrieved.
151
+ */
152
+ async *list() {
153
+ let t;
154
+ for (; ; ) {
155
+ const e = { pageSize: "100" };
156
+ t && (e.pageToken = t);
157
+ const i = await this.apiClient.request(
158
+ "sources",
159
+ { params: e }
160
+ );
161
+ if (i && i.sources)
162
+ for (const a of i.sources)
163
+ yield v(a);
164
+ if (t = i?.nextPageToken, !t)
165
+ break;
166
+ }
167
+ }
168
+ /**
169
+ * Retrieves a specific source by its external identifier.
170
+ *
171
+ * **Data Transformation:**
172
+ * - Constructs a resource name (e.g., `sources/github/owner/repo`) from the input filter.
173
+ *
174
+ * @param filter Filter criteria (currently supports GitHub repo name).
175
+ * @returns The matching Source object, or `undefined` if not found (404).
176
+ * @throws {Error} If the filter format is invalid.
177
+ */
178
+ async get(t) {
179
+ const { github: e } = t;
180
+ if (!e || !e.includes("/"))
181
+ throw new Error("Invalid GitHub filter. Expected format: 'owner/repo'.");
182
+ const i = `sources/github/${e}`;
183
+ try {
184
+ const a = await this.apiClient.request(i);
185
+ return a ? v(a) : void 0;
186
+ } catch (a) {
187
+ if (a instanceof f && a.status === 404)
188
+ return;
189
+ throw a;
190
+ }
191
+ }
192
+ }
193
+ function O(s) {
194
+ const t = new R(s), i = t.list.bind(t);
195
+ return i.get = t.get.bind(t), i;
196
+ }
197
+ typeof process < "u" && process.versions != null && process.versions.node != null;
198
+ class _ {
199
+ type = "media";
200
+ data;
201
+ format;
202
+ platform;
203
+ activityId;
204
+ constructor(t, e, i) {
205
+ this.data = t.data, this.format = t.format, this.platform = e, this.activityId = i;
206
+ }
207
+ /**
208
+ * Saves the media artifact to a file.
209
+ *
210
+ * **Side Effects:**
211
+ * - Node.js: Writes the file to disk (overwrites if exists).
212
+ * - Browser: Saves the file to the 'artifacts' object store in IndexedDB.
213
+ *
214
+ * @param filepath The path where the file should be saved.
215
+ */
216
+ async save(t) {
217
+ await this.platform.saveFile(
218
+ t,
219
+ this.data,
220
+ "base64",
221
+ this.activityId
222
+ );
223
+ }
224
+ /**
225
+ * Converts the media artifact to a data URL.
226
+ * Useful for displaying images in a browser.
227
+ *
228
+ * **Data Transformation:**
229
+ * - Prefixes the base64 data with `data:<mimeType>;base64,`.
230
+ *
231
+ * @returns A valid Data URI string.
232
+ */
233
+ toUrl() {
234
+ return this.platform.createDataUrl(this.data, this.format);
235
+ }
236
+ }
237
+ class F {
238
+ type = "bashOutput";
239
+ command;
240
+ stdout;
241
+ stderr;
242
+ exitCode;
243
+ constructor(t) {
244
+ this.command = t.command, this.stdout = t.stdout, this.stderr = t.stderr, this.exitCode = t.exitCode;
245
+ }
246
+ /**
247
+ * Formats the bash output as a string, mimicking a terminal session.
248
+ *
249
+ * **Data Transformation:**
250
+ * - Combines `stdout` and `stderr`.
251
+ * - Formats the command with a `$` prompt.
252
+ * - Appends the exit code.
253
+ */
254
+ toString() {
255
+ const t = [this.stdout, this.stderr].filter(Boolean).join(""), e = `$ ${this.command}`, i = t ? `${t}
256
+ ` : "", a = `[exit code: ${this.exitCode ?? "N/A"}]`;
257
+ return `${e}
258
+ ${i}${a}`;
259
+ }
260
+ }
261
+ function N(s, t, e) {
262
+ if ("changeSet" in s)
263
+ return { type: "changeSet", changeSet: s.changeSet };
264
+ if ("media" in s)
265
+ return new _(s.media, t, e);
266
+ if ("bashOutput" in s)
267
+ return new F(s.bashOutput);
268
+ throw new Error(`Unknown artifact type: ${JSON.stringify(s)}`);
269
+ }
270
+ function w(s, t) {
271
+ const {
272
+ name: e,
273
+ createTime: i,
274
+ originator: a,
275
+ artifacts: r
276
+ } = s, o = e.split("/").pop(), p = (r || []).map(
277
+ (d) => N(d, t, o)
278
+ ), c = {
279
+ name: e,
280
+ id: o,
281
+ createTime: i,
282
+ originator: a || "system",
283
+ artifacts: p
284
+ };
285
+ if (s.agentMessaged)
286
+ return {
287
+ ...c,
288
+ type: "agentMessaged",
289
+ message: s.agentMessaged.agentMessage
290
+ };
291
+ if (s.userMessaged)
292
+ return {
293
+ ...c,
294
+ type: "userMessaged",
295
+ message: s.userMessaged.userMessage
296
+ };
297
+ if (s.planGenerated)
298
+ return {
299
+ ...c,
300
+ type: "planGenerated",
301
+ plan: s.planGenerated.plan
302
+ };
303
+ if (s.planApproved)
304
+ return {
305
+ ...c,
306
+ type: "planApproved",
307
+ planId: s.planApproved.planId
308
+ };
309
+ if (s.progressUpdated)
310
+ return {
311
+ ...c,
312
+ type: "progressUpdated",
313
+ title: s.progressUpdated.title,
314
+ description: s.progressUpdated.description
315
+ };
316
+ if (s.sessionCompleted)
317
+ return {
318
+ ...c,
319
+ type: "sessionCompleted"
320
+ };
321
+ if (s.sessionFailed)
322
+ return {
323
+ ...c,
324
+ type: "sessionFailed",
325
+ reason: s.sessionFailed.reason
326
+ };
327
+ throw new Error("Unknown activity type");
328
+ }
329
+ function b(s) {
330
+ if (s.state === "failed")
331
+ throw new P(`Session ${s.id} failed.`);
332
+ const t = s.outputs.find((i) => "pullRequest" in i), e = t ? t.pullRequest : void 0;
333
+ return {
334
+ sessionId: s.id,
335
+ title: s.title,
336
+ state: "completed",
337
+ // We only call this mapper on a completed session.
338
+ pullRequest: e,
339
+ outputs: s.outputs
340
+ };
341
+ }
342
+ const T = (s) => new Promise((t) => setTimeout(t, s));
343
+ async function* J(s, t, e, i, a = {}) {
344
+ let r, o = !0;
345
+ const p = /* @__PURE__ */ new Set();
346
+ for (; ; ) {
347
+ let c;
348
+ try {
349
+ c = await t.request(
350
+ `sessions/${s}/activities`,
351
+ {
352
+ params: {
353
+ pageSize: "50",
354
+ // A reasonable page size
355
+ ...r ? { pageToken: r } : {}
356
+ }
357
+ }
358
+ );
359
+ } catch (n) {
360
+ if (o && n instanceof f && n.status === 404) {
361
+ let h = n, l, u = 1e3;
362
+ for (let y = 0; y < 5; y++) {
363
+ await T(u), u *= 2;
364
+ try {
365
+ l = await t.request(
366
+ `sessions/${s}/activities`,
367
+ {
368
+ params: {
369
+ pageSize: "50",
370
+ ...r ? { pageToken: r } : {}
371
+ }
372
+ }
373
+ );
374
+ break;
375
+ } catch (m) {
376
+ if (m instanceof f && m.status === 404)
377
+ h = m;
378
+ else
379
+ throw m;
380
+ }
381
+ }
382
+ if (l)
383
+ c = l;
384
+ else
385
+ throw h;
386
+ } else
387
+ throw n;
388
+ }
389
+ o = !1;
390
+ const d = c.activities || [];
391
+ for (const n of d) {
392
+ if (p.has(n.name))
393
+ continue;
394
+ const h = w(n, i);
395
+ a.exclude?.originator && h.originator === a.exclude.originator || (p.add(n.name), yield h);
396
+ }
397
+ if (c.nextPageToken) {
398
+ r = c.nextPageToken;
399
+ continue;
400
+ } else
401
+ r = void 0, await T(e);
402
+ }
403
+ }
404
+ const D = (s) => new Promise((t) => setTimeout(t, s));
405
+ async function C(s, t, e, i) {
406
+ for (; ; ) {
407
+ const a = await t.request(
408
+ `sessions/${s}`
409
+ );
410
+ if (e(a))
411
+ return a;
412
+ await D(i);
413
+ }
414
+ }
415
+ async function M(s, t, e) {
416
+ return C(
417
+ s,
418
+ t,
419
+ (i) => i.state === "completed" || i.state === "failed",
420
+ e
421
+ );
422
+ }
423
+ class K {
424
+ constructor(t, e) {
425
+ this.storage = t, this.network = e;
426
+ }
427
+ /**
428
+ * Returns an async iterable of all activities stored locally.
429
+ */
430
+ async *history() {
431
+ await this.storage.init(), yield* this.storage.scan();
432
+ }
433
+ /**
434
+ * Returns an async iterable of new activities from the network.
435
+ * This method polls the network and updates the local storage.
436
+ *
437
+ * **Side Effects:**
438
+ * - Polls the network continuously.
439
+ * - Appends new activities to local storage (write-through caching).
440
+ *
441
+ * **Logic:**
442
+ * - Reads the latest activity from storage to determine the "high-water mark".
443
+ * - Ignores incoming activities older than or equal to the high-water mark.
444
+ */
445
+ async *updates() {
446
+ await this.storage.init();
447
+ const t = await this.storage.latest();
448
+ let e = t?.createTime ? new Date(t.createTime).getTime() : 0, i = t?.id;
449
+ for await (const a of this.network.rawStream()) {
450
+ const r = new Date(a.createTime).getTime();
451
+ r < e || r === e && a.id === i || (await this.storage.append(a), e = r, i = a.id, yield a);
452
+ }
453
+ }
454
+ /**
455
+ * Returns a combined stream of history and updates.
456
+ * This is the primary method for consuming the activity stream.
457
+ *
458
+ * **Behavior:**
459
+ * 1. Yields all historical activities from local storage (offline capable).
460
+ * 2. Switches to `updates()` to yield new activities from the network (real-time).
461
+ */
462
+ async *stream() {
463
+ yield* this.history(), yield* this.updates();
464
+ }
465
+ /**
466
+ * Queries local storage for activities matching the given options.
467
+ */
468
+ async select(t = {}) {
469
+ await this.storage.init();
470
+ const e = [];
471
+ let i = !t.after, a = 0;
472
+ for await (const r of this.storage.scan()) {
473
+ if (!i) {
474
+ r.id === t.after && (i = !0);
475
+ continue;
476
+ }
477
+ if (t.before && r.id === t.before)
478
+ break;
479
+ if (!(t.type && r.type !== t.type) && (e.push(r), a++, t.limit && a >= t.limit))
480
+ break;
481
+ }
482
+ return e;
483
+ }
484
+ /**
485
+ * Lists activities from the network directly.
486
+ * @param options Pagination options.
487
+ */
488
+ async list(t) {
489
+ return this.network.listActivities(t);
490
+ }
491
+ /**
492
+ * Gets a single activity by ID.
493
+ * Implements a "read-through" caching strategy.
494
+ *
495
+ * **Logic:**
496
+ * 1. Checks local storage. If found, returns it immediately (fast).
497
+ * 2. If missing, fetches from the network.
498
+ * 3. Persists the fetched activity to storage (future reads will hit cache).
499
+ * 4. Returns the activity.
500
+ *
501
+ * **Side Effects:**
502
+ * - May perform a network request.
503
+ * - May write to local storage.
504
+ */
505
+ async get(t) {
506
+ await this.storage.init();
507
+ const e = await this.storage.get(t);
508
+ if (e)
509
+ return e;
510
+ const i = await this.network.fetchActivity(t);
511
+ return await this.storage.append(i), i;
512
+ }
513
+ }
514
+ class L {
515
+ constructor(t, e, i = 5e3, a) {
516
+ this.apiClient = t, this.sessionId = e, this.pollingIntervalMs = i, this.platform = a;
517
+ }
518
+ /**
519
+ * Fetches a single activity from the API.
520
+ */
521
+ async fetchActivity(t) {
522
+ const e = await this.apiClient.request(
523
+ `sessions/${this.sessionId}/activities/${t}`
524
+ );
525
+ return w(e, this.platform);
526
+ }
527
+ /**
528
+ * Lists activities from the API with pagination.
529
+ */
530
+ async listActivities(t) {
531
+ const e = {};
532
+ t?.pageSize && (e.pageSize = t.pageSize.toString()), t?.pageToken && (e.pageToken = t.pageToken);
533
+ const i = await this.apiClient.request(`sessions/${this.sessionId}/activities`, { params: e });
534
+ return {
535
+ activities: (i.activities || []).map(
536
+ (a) => w(a, this.platform)
537
+ ),
538
+ nextPageToken: i.nextPageToken
539
+ };
540
+ }
541
+ /**
542
+ * Polls the API for new activities and yields them.
543
+ * This stream never ends unless the process is terminated.
544
+ */
545
+ async *rawStream() {
546
+ for (; ; ) {
547
+ let t;
548
+ do {
549
+ const e = await this.listActivities({ pageToken: t });
550
+ for (const i of e.activities)
551
+ yield i;
552
+ t = e.nextPageToken;
553
+ } while (t);
554
+ await this.platform.sleep(this.pollingIntervalMs);
555
+ }
556
+ }
557
+ }
558
+ class S {
559
+ id;
560
+ apiClient;
561
+ config;
562
+ // The new client instance
563
+ _activities;
564
+ /**
565
+ * Creates a new instance of SessionClientImpl.
566
+ *
567
+ * @param sessionId The ID of the session.
568
+ * @param apiClient The API client to use for network requests.
569
+ * @param config The configuration options.
570
+ * @param storage The storage engine for activities.
571
+ * @param platform The platform adapter.
572
+ */
573
+ constructor(t, e, i, a, r) {
574
+ this.id = t.replace(/^sessions\//, ""), this.apiClient = e, this.config = i;
575
+ const o = new L(
576
+ this.apiClient,
577
+ this.id,
578
+ this.config.pollingIntervalMs,
579
+ r
580
+ );
581
+ this._activities = new K(a, o);
582
+ }
583
+ /**
584
+ * COLD STREAM: Yields all known past activities from local storage.
585
+ */
586
+ history() {
587
+ return this._activities.history();
588
+ }
589
+ /**
590
+ * HOT STREAM: Yields ONLY future activities as they arrive from the network.
591
+ */
592
+ updates() {
593
+ return this._activities.updates();
594
+ }
595
+ /**
596
+ * LOCAL QUERY: Performs rich filtering against local storage only.
597
+ */
598
+ select(t) {
599
+ return this._activities.select(t);
600
+ }
601
+ /**
602
+ * Provides a real-time stream of activities for the session.
603
+ *
604
+ * @param options Options to control the stream.
605
+ */
606
+ async *stream(t = {}) {
607
+ for await (const e of this._activities.stream())
608
+ t.exclude?.originator && e.originator === t.exclude.originator || (yield e);
609
+ }
610
+ /**
611
+ * Approves the currently pending plan.
612
+ * Only valid if the session state is `awaitingPlanApproval`.
613
+ *
614
+ * **Side Effects:**
615
+ * - Sends a POST request to `sessions/{id}:approvePlan`.
616
+ * - Transitions the session state from `awaitingPlanApproval` to `inProgress` (eventually).
617
+ *
618
+ * @throws {InvalidStateError} If the session is not in the `awaitingPlanApproval` state.
619
+ *
620
+ * @example
621
+ * await session.waitFor('awaitingPlanApproval');
622
+ * await session.approve();
623
+ */
624
+ async approve() {
625
+ const t = (await this.info()).state;
626
+ if (t !== "awaitingPlanApproval")
627
+ throw new q(
628
+ `Cannot approve plan because the session is not awaiting approval. Current state: ${t}`
629
+ );
630
+ await this.apiClient.request(`sessions/${this.id}:approvePlan`, {
631
+ method: "POST",
632
+ body: {}
633
+ });
634
+ }
635
+ /**
636
+ * Sends a message (prompt) to the agent in the context of the current session.
637
+ * This is a fire-and-forget operation. To see the response, use `stream()` or `ask()`.
638
+ *
639
+ * **Side Effects:**
640
+ * - Sends a POST request to `sessions/{id}:sendMessage`.
641
+ * - Appends a new `userMessaged` activity to the session history.
642
+ *
643
+ * @param prompt The message to send.
644
+ *
645
+ * @example
646
+ * await session.send("Please clarify step 2.");
647
+ */
648
+ async send(t) {
649
+ await this.apiClient.request(`sessions/${this.id}:sendMessage`, {
650
+ method: "POST",
651
+ body: { prompt: t }
652
+ });
653
+ }
654
+ /**
655
+ * Sends a message to the agent and waits specifically for the agent's immediate reply.
656
+ * This provides a convenient request/response flow for conversational interactions.
657
+ *
658
+ * **Behavior:**
659
+ * - Sends the prompt using `send()`.
660
+ * - Subscribes to the activity stream.
661
+ * - Resolves with the first `agentMessaged` activity that appears *after* the prompt was sent.
662
+ *
663
+ * @param prompt The message to send.
664
+ * @returns The agent's reply activity.
665
+ * @throws {JulesError} If the session terminates before the agent replies.
666
+ *
667
+ * @example
668
+ * const reply = await session.ask("What is the status?");
669
+ * console.log(reply.message);
670
+ */
671
+ async ask(t) {
672
+ const e = /* @__PURE__ */ new Date();
673
+ await this.send(t);
674
+ for await (const i of this.stream({
675
+ exclude: { originator: "user" }
676
+ })) {
677
+ const a = new Date(i.createTime).getTime(), r = e.getTime();
678
+ if (!(a <= r) && i.type === "agentMessaged")
679
+ return i;
680
+ }
681
+ throw new g("Session ended before the agent replied.");
682
+ }
683
+ /**
684
+ * Waits for the session to reach a terminal state and returns the result.
685
+ *
686
+ * **Behavior:**
687
+ * - Polls the session API until state is 'completed' or 'failed'.
688
+ * - Maps the final session resource to a friendly `Outcome` object.
689
+ *
690
+ * @returns The final outcome of the session.
691
+ * @throws {AutomatedSessionFailedError} If the session ends in a 'failed' state.
692
+ */
693
+ async result() {
694
+ const t = await M(
695
+ this.id,
696
+ this.apiClient,
697
+ this.config.pollingIntervalMs
698
+ );
699
+ return b(t);
700
+ }
701
+ /**
702
+ * Pauses execution and waits until the session reaches a specific state.
703
+ * Also returns if the session reaches a terminal state ('completed' or 'failed')
704
+ * to prevent infinite waiting.
705
+ *
706
+ * **Behavior:**
707
+ * - Polls the session API at the configured interval.
708
+ * - Resolves immediately if the session is already in the target state (or terminal).
709
+ *
710
+ * @param targetState The target state to wait for.
711
+ *
712
+ * @example
713
+ * await session.waitFor('awaitingPlanApproval');
714
+ */
715
+ async waitFor(t) {
716
+ await C(
717
+ this.id,
718
+ this.apiClient,
719
+ (e) => e.state === t || e.state === "completed" || e.state === "failed",
720
+ this.config.pollingIntervalMs
721
+ );
722
+ }
723
+ /**
724
+ * Retrieves the latest state of the underlying session resource from the API.
725
+ */
726
+ async info() {
727
+ return this.apiClient.request(`sessions/${this.id}`);
728
+ }
729
+ }
730
+ async function z(s, t, e = {}) {
731
+ const i = e.concurrency ?? 3, a = e.stopOnError ?? !0, r = e.delayMs ?? 0, o = new Array(s.length), p = new Array(), c = s.entries(), d = new Array(i).fill(c).map(async (n) => {
732
+ for (const [h, l] of n) {
733
+ r > 0 && await new Promise((u) => setTimeout(u, r));
734
+ try {
735
+ o[h] = await t(l);
736
+ } catch (u) {
737
+ if (a)
738
+ throw u;
739
+ p.push(u);
740
+ }
741
+ }
742
+ });
743
+ if (await Promise.all(d), !a && p.length > 0)
744
+ throw new AggregateError(
745
+ p,
746
+ "Multiple errors occurred during jules.all()"
747
+ );
748
+ return o;
749
+ }
750
+ class $ {
751
+ /**
752
+ * Manages source connections (e.g., GitHub repositories).
753
+ */
754
+ sources;
755
+ apiClient;
756
+ config;
757
+ options;
758
+ storageFactory;
759
+ platform;
760
+ /**
761
+ * Creates a new instance of the JulesClient.
762
+ *
763
+ * @param options Configuration options for the client.
764
+ * @param defaultStorageFactory Factory for creating storage instances.
765
+ * @param defaultPlatform Platform-specific implementation.
766
+ */
767
+ constructor(t = {}, e, i) {
768
+ this.options = t, this.storageFactory = t.storageFactory ?? e, this.platform = t.platform ?? i;
769
+ const a = t.apiKey ?? process.env.JULES_API_KEY, r = t.baseUrl ?? "https://jules.googleapis.com/v1alpha";
770
+ this.config = {
771
+ pollingIntervalMs: t.config?.pollingIntervalMs ?? 5e3,
772
+ requestTimeoutMs: t.config?.requestTimeoutMs ?? 3e4
773
+ }, this.apiClient = new U({
774
+ apiKey: a,
775
+ baseUrl: r,
776
+ requestTimeoutMs: this.config.requestTimeoutMs
777
+ }), this.sources = O(this.apiClient);
778
+ }
779
+ /**
780
+ * Creates a new Jules client instance with updated configuration.
781
+ * This is an immutable operation; the original client instance remains unchanged.
782
+ *
783
+ * @param options The new configuration options to merge with the existing ones.
784
+ * @returns A new JulesClient instance with the updated configuration.
785
+ */
786
+ with(t) {
787
+ return new $(
788
+ {
789
+ ...this.options,
790
+ ...t,
791
+ config: {
792
+ ...this.options.config,
793
+ ...t.config
794
+ }
795
+ },
796
+ this.storageFactory,
797
+ this.platform
798
+ );
799
+ }
800
+ async all(t, e, i) {
801
+ return z(
802
+ t,
803
+ async (a) => {
804
+ const r = await e(a);
805
+ return this.run(r);
806
+ },
807
+ i
808
+ );
809
+ }
810
+ async _prepareSessionCreation(t) {
811
+ const e = await this.sources.get({ github: t.source.github });
812
+ if (!e)
813
+ throw new A(t.source.github);
814
+ return {
815
+ prompt: t.prompt,
816
+ title: t.title,
817
+ sourceContext: {
818
+ source: e.name,
819
+ githubRepoContext: {
820
+ startingBranch: t.source.branch
821
+ }
822
+ }
823
+ };
824
+ }
825
+ /**
826
+ * Executes a task in automated mode.
827
+ * This is a high-level abstraction for "fire-and-forget" tasks.
828
+ *
829
+ * **Side Effects:**
830
+ * - Creates a new session on the Jules API (`POST /sessions`).
831
+ * - Initiates background polling for activity updates.
832
+ * - May create a Pull Request if `autoPr` is true (default).
833
+ *
834
+ * **Data Transformation:**
835
+ * - Resolves the `github` source identifier (e.g., `owner/repo`) to a full resource name.
836
+ * - Defaults `requirePlanApproval` to `false` for automated runs.
837
+ *
838
+ * @param config The configuration for the run.
839
+ * @returns A `AutomatedSession` object, which is an enhanced Promise that resolves to the final outcome.
840
+ * @throws {SourceNotFoundError} If the specified GitHub repository cannot be found or accessed.
841
+ * @throws {JulesApiError} If the session creation fails (e.g., 401 Unauthorized).
842
+ *
843
+ * @example
844
+ * const run = await jules.run({
845
+ * prompt: "Fix the login bug",
846
+ * source: { github: "my-org/repo", branch: "main" }
847
+ * });
848
+ * const outcome = await run.result();
849
+ */
850
+ async run(t) {
851
+ const e = await this._prepareSessionCreation(t), a = (await this.apiClient.request(
852
+ "sessions",
853
+ {
854
+ method: "POST",
855
+ body: {
856
+ ...e,
857
+ automationMode: t.autoPr === !1 ? "AUTOMATION_MODE_UNSPECIFIED" : "AUTO_CREATE_PR",
858
+ requirePlanApproval: t.requireApproval ?? !1
859
+ }
860
+ }
861
+ )).id;
862
+ return {
863
+ id: a,
864
+ stream: (async function* () {
865
+ yield* J(
866
+ a,
867
+ this.apiClient,
868
+ this.config.pollingIntervalMs,
869
+ this.platform
870
+ );
871
+ }).bind(this),
872
+ result: async () => {
873
+ const r = await M(
874
+ a,
875
+ this.apiClient,
876
+ this.config.pollingIntervalMs
877
+ );
878
+ return b(r);
879
+ }
880
+ };
881
+ }
882
+ session(t) {
883
+ if (typeof t == "string") {
884
+ const a = this.storageFactory(t);
885
+ return new S(
886
+ t,
887
+ this.apiClient,
888
+ this.config,
889
+ a,
890
+ this.platform
891
+ );
892
+ }
893
+ const e = t;
894
+ return (async () => {
895
+ const a = await this._prepareSessionCreation(e), r = await this.apiClient.request(
896
+ "sessions",
897
+ {
898
+ method: "POST",
899
+ body: {
900
+ ...a,
901
+ automationMode: "AUTOMATION_MODE_UNSPECIFIED",
902
+ requirePlanApproval: e.requireApproval ?? !0
903
+ }
904
+ }
905
+ ), o = this.storageFactory(r.id);
906
+ return new S(
907
+ r.name,
908
+ this.apiClient,
909
+ this.config,
910
+ o,
911
+ this.platform
912
+ );
913
+ })();
914
+ }
915
+ }
916
+ export {
917
+ P as A,
918
+ q as I,
919
+ $ as J,
920
+ I as M,
921
+ A as S,
922
+ g as a,
923
+ k as b,
924
+ f as c,
925
+ x as d,
926
+ E as e
927
+ };