@camox/api-contract 0.76.0 → 0.77.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/router.d.ts CHANGED
@@ -7,8 +7,6 @@ import { WebSockets } from "agents/websockets";
7
7
  import "@earendil-works/pi-ai";
8
8
  import "@earendil-works/pi-ai/models";
9
9
  import "@earendil-works/pi-durable/tools";
10
- import { FileErrorCode } from "@earendil-works/pi-durable/env";
11
- import "camox/_internal/sdkBundleName";
12
10
  import "@camox/ai-tools";
13
11
  import { AgentEvent } from "@earendil-works/pi-durable";
14
12
  import "effect";
@@ -18,6 +16,8 @@ import "drizzle-orm";
18
16
  import "drizzle-orm/sqlite-core";
19
17
  import { SpecialistId } from "@camox/api-contract/specialists";
20
18
  import { DrizzleD1Database } from "drizzle-orm/d1";
19
+ import { FileErrorCode } from "@earendil-works/pi-durable/env";
20
+ import { SdkBundleNames } from "camox/_internal/sdkBundleName";
21
21
  import { CIWorkflow, CiContext, CiParams, CloudflareArtifacts } from "@cloudflare/ci";
22
22
  import { CiBindings } from "@cloudflare/ci/worker";
23
23
  import { ProjectRoomMessage } from "@camox/api-contract/query-keys";
@@ -233,34 +233,6 @@ type Attachment = typeof attachments.$inferSelect;
233
233
  */
234
234
  type MessageAttachment = Pick<Attachment, "id" | "filename" | "mimeType" | "url" | "blobKey">;
235
235
  //#endregion
236
- //#region ../../apps/api/src/domains/code/remote-env.d.ts
237
- /** The operations sent as they are: every argument but the context is plain data. */
238
- declare const SENT: ["absolutePath", "joinPath", "readTextFile", "readTextLines", "readBinaryFile", "writeFile", "appendFile", "truncateFile", "flushFile", "renameFile", "fileInfo", "listDir", "canonicalPath", "exists", "createDir", "remove"];
239
- /** What a remote environment asks of the one it reaches. */
240
- type EnvCall = {
241
- operation: (typeof SENT)[number];
242
- args: unknown[];
243
- } |
244
- /** Opens a binary reader there and reads the whole file it opened. */
245
- {
246
- operation: "openBinaryReader";
247
- args: [path: string, options?: {
248
- noFollow?: boolean;
249
- }];
250
- };
251
- /** An operation's result as it crosses: its value, or its error as plain data. */
252
- type EnvAnswer = {
253
- ok: true;
254
- value: unknown;
255
- } | {
256
- ok: false;
257
- error: {
258
- code: FileErrorCode;
259
- message: string;
260
- path?: string;
261
- };
262
- };
263
- //#endregion
264
236
  //#region ../../apps/api/src/domains/revisions/result.d.ts
265
237
  /** A revision's ID: a UUIDv7. */
266
238
  type RevisionId = string;
@@ -301,347 +273,19 @@ type BuildResult = {
301
273
  };
302
274
  };
303
275
  //#endregion
304
- //#region ../../apps/api/src/lib/timing.d.ts
305
- /** What a span's line says beside its name and duration. Undefined fields are left out. */
306
- type SpanFields = Record<string, string | number | boolean | null | undefined>;
307
- //#endregion
308
- //#region ../../apps/api/src/durable-objects/draft-code.d.ts
309
- /** A revision of the draft whose build goes up as its publish script. */
310
- type PublishUpload = {
311
- /** The project's Project ID. */
312
- project: string;
313
- revision: string;
314
- /** Its build in `REVISION_BUILDS`. */
315
- archiveKey: string;
316
- };
317
- /** A commit `prepareCommit` made, not on the branch yet. */
318
- type PreparedCommit = {
319
- commit: string;
320
- tree: string;
321
- /** The tree's files, as a tar archive. */
322
- files: Uint8Array;
323
- /** The tree's `pnpm-lock.yaml`, if it has one. */
324
- lockfile: string | null;
325
- };
326
- /**
327
- * A merge of `main` that doesn't land as a revision as it is: it conflicts, or its tree doesn't
328
- * build or type check. Recorded for Camox's reconcile turn, which tries once for each move of
329
- * `main`, until code holding that `main` builds without errors (`settleClash`): the draft has
330
- * the "doesn't merge with Live's" blocker until then.
331
- */
332
- type MergeClash = {
333
- /** The commit of `main` that clashed. */
334
- main: string;
335
- /** The files both sides changed in ways that don't merge, for a merge that conflicts. */
336
- conflicts?: string[];
337
- /** The merged tree's build, for a merge that doesn't build or type check. */
338
- result?: BuildResult;
339
- };
340
- /** What merging `main` into the working copy found. */
341
- type MergeOutcome =
342
- /** The draft holds the current `main` already. */
343
- {
344
- outcome: "upToDate";
345
- } |
346
- /** The working copy has changes no revision holds yet: the merge waits for them. */
347
- {
348
- outcome: "unsettled";
349
- } |
350
- /** This move of `main` clashed already, and isn't merged again until `main` moves again. */
351
- {
352
- outcome: "clashedBefore";
353
- main: string;
354
- } | {
355
- outcome: "conflicts";
356
- main: string;
357
- conflicts: string[];
358
- } |
359
- /** A merge commit of `main`, not on the branch yet, for a build to commit. */
360
- {
361
- outcome: "merged";
362
- main: string;
363
- prepared: PreparedCommit;
276
+ //#region ../../apps/api/src/domains/layouts/schema.d.ts
277
+ /** Which collection a layout's record pages render, and the field they're found by. */
278
+ type RecordPages = {
279
+ collectionId: string;
280
+ field: string;
364
281
  };
282
+ //#endregion
283
+ //#region ../../apps/api/src/domains/pages/schema.d.ts
365
284
  /**
366
- * The working copy of one draft with code, addressed by the draft's ID (`getByName`): a depth-1
367
- * clone of the draft's branch, held in memory, which the agent's code tools read and write over
368
- * RPC, through the write line. Every change is saved to its SQLite as it's made, Git's own
369
- * directory included, so an eviction restores it without cloning again. The skills of its `camox`
370
- * version are mounted beside the files and never saved, nor committed.
371
- *
372
- * It stores nothing until `start` made it, and nothing once `delete` deleted it.
373
- */
374
- declare class DraftCode extends DurableObject<Bindings> {
375
- #private;
376
- /** Whether the draft has code: its branch was made, and not deleted since. */
377
- held(): Promise<boolean>;
378
- /**
379
- * The commit of `main` the draft's code holds: the one its branch last merged, or forked from,
380
- * once it has code.
381
- */
382
- mergedMain(): Promise<string | undefined>;
383
- /**
384
- * Where the draft's merges of `main` stand: the branch's head, the `main` it holds, and the
385
- * last merge that clashed, read at once, as a commit moves them together.
386
- */
387
- merges(): Promise<{
388
- head: string;
389
- mergedMain: string;
390
- clash: MergeClash | undefined;
391
- }>;
392
- /** The last merge of `main` that clashed, until a merge of `main` lands. */
393
- clash(): Promise<MergeClash | undefined>;
394
- /**
395
- * Records that the merge of `main` at `clash.main` clashed (see `MergeClash`), for Camox's
396
- * reconcile turn. A merge that didn't land is left in the files, uncommitted, conflict markers
397
- * included, and the next revision is its merge commit: see `merging`.
398
- */
399
- recordClash(clash: MergeClash): Promise<void>;
400
- /**
401
- * The commit of `main` whose merge the files hold, uncommitted, if they do: Camox's reconcile
402
- * turn fixes it, and its build commits the merge commit.
403
- */
404
- merging(): Promise<string | undefined>;
405
- /**
406
- * Forgets the clash, once the draft's code built without errors and holds the `main` that
407
- * clashed: unless the files still hold a merge no commit landed.
408
- */
409
- settleClash(): Promise<void>;
410
- /**
411
- * Uploads the build of the draft's revision `revision` as the draft's publish script, ahead of
412
- * its publish, unless the script holds it already: its publish then only checks it's there
413
- * (`uploadForPublish`). Nothing once a publish took the script, until that publish ends, nor
414
- * once the draft ended. A draft that ended during the upload, deleted, loses the script.
415
- */
416
- prepareUpload(toUpload: PublishUpload): Promise<void>;
417
- /**
418
- * The draft's publish script holding the build of `revision`, which the publish `instanceId`
419
- * ships, taking it: no upload ahead replaces it until that publish ends. Uploads it unless the
420
- * script holds it already, as the upload ahead left it. Returns its name, and whether this
421
- * uploaded it.
422
- */
423
- uploadForPublish(toUpload: PublishUpload, instanceId: string, span?: SpanFields): Promise<{
424
- script: string;
425
- uploaded: boolean;
426
- }>;
427
- /** The publish of the draft going now, if any: its Workflow instance. */
428
- publishGoing(): Promise<string | null>;
429
- /**
430
- * Records that a member's push landed during the publish `instanceId`: the revision it waits
431
- * for a build to leave changed under it, so it goes back to the review (ADR 0043).
432
- */
433
- notePushDuring(instanceId: string): Promise<void>;
434
- /** Whether a member's push landed during the publish `instanceId`. */
435
- pushedDuring(instanceId: string): Promise<boolean>;
436
- /** Records that a build of the draft's code started, or ended. */
437
- markBuilding(building: boolean): Promise<void>;
438
- /**
439
- * Whether a build of the draft's code is going (see `BUILD_GOING_FOR_AT_MOST_MS`), or owed:
440
- * Camox's infrastructure failed the last one, and Camox retries it. A type check, going or
441
- * owed, isn't building (ADR 0043).
442
- */
443
- building(): Promise<boolean>;
444
- /**
445
- * Records that the thread `threadId` couldn't build the draft's code because of Camox's own
446
- * infrastructure, or with `typesOnly`, only check the types of a revision that built, and has
447
- * it retry later (`alarm`), each retry waiting longer.
448
- */
449
- oweBuild({ threadId, typesOnly }: {
450
- threadId: string;
451
- typesOnly?: boolean;
452
- }): Promise<void>;
453
- /** Forgets the build Camox owed the draft, once one ended without Camox's failing. */
454
- settleOwedBuild(): Promise<void>;
455
- /** Retries the build Camox owes the draft, in its thread's build queue, until one lands. */
456
- alarm(): Promise<void>;
457
- /**
458
- * Makes the draft's branch and working copy, from `commit` of `main` in the project's repo
459
- * `repo`, unless they were made already. Returns the commit the branch forked from.
460
- */
461
- start({ repo, commit }: {
462
- repo: string;
463
- commit: string;
464
- }): Promise<string>;
465
- /**
466
- * Makes the branch and working copy of a draft reverting a Publication, unless they were made
467
- * already: forked from `commit`, the Publication's commit on `main`, with one commit on top,
468
- * `message`, putting back the tree `main` had before it. Merging the current `main` then
469
- * applies that undo to Live's latest code, as a merge of `main` into any draft (`mergeMain`):
470
- * code a later publish changed since clashes as merges do. Returns whether `main` moved since
471
- * `commit`, which a merge then brings in, or null, making nothing, when `commit` is `main`'s
472
- * first: there's no code before it to put back.
473
- */
474
- startReverting({ repo, commit, message }: {
475
- repo: string;
476
- commit: string;
477
- message: string;
478
- }): Promise<{
479
- mainMoved: boolean;
480
- } | null>;
481
- /** Runs one operation of the agent's environment on the working copy, and saves what it changed. */
482
- call(call: EnvCall): Promise<EnvAnswer>;
483
- /**
484
- * The files that have merge conflict markers, as a merge of `main` that conflicts leaves them:
485
- * only files the branch's head doesn't hold as they are, since no commit holds markers.
486
- */
487
- conflicts(): Promise<string[]>;
488
- /**
489
- * The paths of the working copy's files that differ from the commit `since`, added or changed
490
- * since, without those deleted: since the branch's head when the working copy doesn't hold it,
491
- * or without `since`.
492
- */
493
- changedFiles({ since }?: {
494
- since?: string;
495
- }): Promise<string[]>;
496
- /**
497
- * The working copy's files that installing its dependencies reads, as a tar archive, with its
498
- * lockfile: what its sandbox needs to install ahead of a build, which `prepareCommit` would
499
- * give only once it staged and committed every change.
500
- */
501
- installFiles(): Promise<Pick<PreparedCommit, "files" | "lockfile">>;
502
- /**
503
- * Stages the working copy's every change and makes, without moving the branch, the commit it
504
- * would be: `message` on top of the branch's head. Returns the commit and its tree, with the
505
- * tree's files as a tar archive, which a build streams into its sandbox, and the lockfile.
506
- * Neither Git's directory nor the references mounted beside the files are in the tree.
507
- */
508
- prepareCommit({ message }: {
509
- message: string;
510
- }): Promise<PreparedCommit>;
511
- /**
512
- * Adds a member's pushed commits to the working copy, without moving the branch: the objects of
513
- * `pack`, a bundle's packfile, which may build on the objects of `prerequisites`, commits of
514
- * `main` fetched for it when the working copy doesn't hold them. A build then commits the
515
- * pushed head (`commit`, with `checkout`).
516
- */
517
- receive({ pack, prerequisites }: {
518
- pack: Uint8Array;
519
- prerequisites: string[];
520
- }): Promise<void>;
521
- /**
522
- * Moves the draft's branch to `commit`, which `prepareCommit` made, or a member pushed on top
523
- * of the branch's head, and pushes it. A commit of the tree the branch's head already has, such
524
- * as one prepared again after the push of the first, leaves the head as it is. With
525
- * `checkout`, for a commit made beside the files, the files take its tree. A member's pushed
526
- * head names `mergedMain`, the newest commit of `main` it holds, which the draft's next merge of
527
- * `main` merges from. Returns the branch's head and its parents.
528
- */
529
- commit({ commit, checkout, mergedMain }: {
530
- commit: string;
531
- checkout?: boolean;
532
- mergedMain?: string;
533
- }): Promise<{
534
- commit: string;
535
- parents: string[];
536
- }>;
537
- /** Whether `commit` is the branch's head or one of its descendants: it includes the head. */
538
- includesHead(commit: string): Promise<boolean>;
539
- /**
540
- * Pushes the draft's code to `main` as one squashed commit, as a publish lands: the tree of
541
- * `commit`, a revision on the branch, with the current tip of `main` as its only parent. A
542
- * `main` that already has that tree, as after a retried push that landed, is left as it is.
543
- * Returns the commit `main` points to.
544
- */
545
- publishToMain({ commit, message }: {
546
- commit: string;
547
- message: string;
548
- }): Promise<string>;
549
- /**
550
- * Merges the current `main` into the branch, without moving it: fetches `main` shallowly, its
551
- * history down to the `main` commit the branch last merged or forked from, which is then the
552
- * merge base, and merges it into the branch's head. A clean merge is returned as a merge commit
553
- * whose parents are the head and `main`, for a build to commit (`commit`): the files stay as
554
- * they are until then. A merge that conflicts changes nothing either.
555
- *
556
- * It waits while the files have changes no commit holds, and doesn't merge again a move of
557
- * `main` that clashed. Files holding the merge of an earlier `main` that Camox's reconcile
558
- * turn didn't fix (`merging`) are put back to the branch's head first, to merge this one.
559
- */
560
- mergeMain(): Promise<MergeOutcome>;
561
- /** Deletes the draft's branch and everything the working copy stored, as the draft ends. */
562
- delete(): Promise<void>;
563
- }
564
- //#endregion
565
- //#region ../../apps/api/src/domains/code-pushes/checks.d.ts
566
- /** Why a push was refused: each reason is a stable code the CLI and its users can rely on. */
567
- type PushRefusalReason =
568
- /** What was sent isn't a Git bundle of one branch's commits. */
569
- "invalidBundle" |
570
- /** The pushed tree changes a platform-owned file, which only Upgrades change. */
571
- "platformFile" |
572
- /** The pushed tree adds or changes a file under `src/` that isn't TypeScript or CSS. */
573
- "notCode" |
574
- /** `main` changed a platform-owned file since the branch last merged it. */
575
- "mergeMainFirst" |
576
- /** The branch starts from a commit that was never on `main`. */
577
- "baseNotOnMain" |
578
- /** The branch doesn't merge cleanly with the current `main`. */
579
- "conflictsWithMain" |
580
- /** The pushed head doesn't build. */
581
- "doesNotBuild" |
582
- /** The pushed head doesn't include the draft's current head. */
583
- "pullDraftFirst" |
584
- /** The draft the push names was published or deleted. */
585
- "draftEnded";
586
- type PushRefusal = {
587
- reason: PushRefusalReason;
588
- message: string;
589
- data?: Record<string, unknown>;
590
- };
591
- /** A push that passed the checks: its head, as a commit to build, and what landing it needs. */
592
- type CheckedPush = {
593
- /** The pushed head, as a commit to build. */
594
- prepared: PreparedCommit;
595
- /**
596
- * The commits of `main` or of the draft's branch the pushed commits build on: the bundle's
597
- * prerequisites.
598
- */
599
- prerequisites: string[];
600
- /** The newest commit of `main` the pushed head holds, which a draft it opens forks from. */
601
- base: string;
602
- pack: Uint8Array;
603
- /** The subject of each pushed commit, oldest first. */
604
- subjects: string[];
605
- };
606
- //#endregion
607
- //#region ../../apps/api/src/domains/code-pushes/land.d.ts
608
- /** A push that passed its checks, as the draft it lands on receives it. */
609
- type CheckedLanding = CheckedPush & {
610
- /** The project's Project ID, which names its repo. */
611
- repo: string;
612
- };
613
- /** Whether the push landed, with its head's build, or why it was refused. */
614
- type Landing = {
615
- refused: PushRefusal;
616
- } | {
617
- result: BuildResult;
618
- };
619
- //#endregion
620
- //#region ../../apps/api/src/domains/revisions/merge.d.ts
621
- /** How a merge of `main` into a draft ended. */
622
- type MergeEnd =
623
- /** The draft holds the current `main`, or will once its changes are committed. */
624
- "upToDate" |
625
- /** A merge revision landed, built, and the draft previews it. */
626
- "merged" |
627
- /** The merge clashed: it's left for Camox's reconcile turn (`DraftCode.clash`), to start. */
628
- "clashed" |
629
- /** This move of `main` clashed already: Camox's reconcile turn had its one try. */
630
- "clashedBefore";
631
- //#endregion
632
- //#region ../../apps/api/src/domains/layouts/schema.d.ts
633
- /** Which collection a layout's record pages render, and the field they're found by. */
634
- type RecordPages = {
635
- collectionId: string;
636
- field: string;
637
- };
638
- //#endregion
639
- //#region ../../apps/api/src/domains/pages/schema.d.ts
640
- /**
641
- * A page. Live and every draft store pages side by side (ADR 0005), like blocks: a Live row has
642
- * no draft, a draft row is the draft's copy of a page, a page the draft created, or a tombstone.
643
- * An id is unique within each locale of Live and of each draft (ADR 0015). Read and write pages
644
- * through the draft overlay.
285
+ * A page. Live and every draft store pages side by side (ADR 0005), like blocks: a Live row has
286
+ * no draft, a draft row is the draft's copy of a page, a page the draft created, or a tombstone.
287
+ * An id is unique within each locale of Live and of each draft (ADR 0015). Read and write pages
288
+ * through the draft overlay.
645
289
  */
646
290
  declare const pages: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
647
291
  name: "pages";
@@ -1994,6 +1638,14 @@ type DraftRequest = {
1994
1638
  declare const ENTITY_KINDS: readonly ["locale", "page", "block", "sharedContent", "repeatableItem", "file", "record", "exclusion"];
1995
1639
  type EntityKind = (typeof ENTITY_KINDS)[number];
1996
1640
  //#endregion
1641
+ //#region ../../apps/api/src/domains/revisions/schema.d.ts
1642
+ /**
1643
+ * What left a revision: the agent's `build`, the end of its turn, a merge of `main`, a
1644
+ * member's `push` from their own checkout (ADR 0026), or the undo of a Publication's code
1645
+ * starting the draft reverting it (ADR 0045).
1646
+ */
1647
+ type RevisionSource = "build" | "turn" | "merge" | "push" | "revert";
1648
+ //#endregion
1997
1649
  //#region ../../apps/api/src/db.d.ts
1998
1650
  declare const schema: {
1999
1651
  projects: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
@@ -6831,7 +6483,14 @@ declare const schema: {
6831
6483
  dialect: 'sqlite';
6832
6484
  }>;
6833
6485
  };
6834
- declare function createDb(d1: D1Database): DrizzleD1Database<typeof schema> & {
6486
+ /**
6487
+ * A database on `d1` whose reads issued together share one round trip (`coalescingReads`). A
6488
+ * database kept beyond one request must not: a batch would answer each request's reads from
6489
+ * another's I/O. Pass `coalesce: false` for it.
6490
+ */
6491
+ declare function createDb(d1: D1Database, { coalesce }?: {
6492
+ coalesce?: boolean;
6493
+ }): DrizzleD1Database<typeof schema> & {
6835
6494
  $client: D1Database;
6836
6495
  };
6837
6496
  type Database = ReturnType<typeof createDb>;
@@ -9958,6 +9617,8 @@ type TurnOutcome = TurnEnd | {
9958
9617
  type OpeningSender = {
9959
9618
  kind: "editor";
9960
9619
  editor: ThreadSender;
9620
+ /** The locale the editor was in as they sent it, in the studio. */
9621
+ locale?: string;
9961
9622
  } | {
9962
9623
  kind: "connectedAgent";
9963
9624
  member: ThreadSender;
@@ -10015,22 +9676,6 @@ declare class Thread extends DurableObject<Bindings> {
10015
9676
  readonly harness: UntilStartedPiHarness;
10016
9677
  readonly webSockets: WebSockets;
10017
9678
  readonly lifecycle: Lifecycle<object, object>;
10018
- /**
10019
- * Builds the code of the draft `draftId`, the thread's, in its build queue, as a publish of a
10020
- * head revision whose build is gone asks: the head's tree finds its revision, built again.
10021
- */
10022
- buildForPublish(draftId: string): Promise<BuildResult | null>;
10023
- /**
10024
- * Lands a member's checked push `push` on the thread's draft, in its build queue, as `pusher`
10025
- * pushed it (ADR 0026): once the agent's turn going, if any, made its last commit, and before
10026
- * the next message. Starts the thread, if nobody messaged it yet, so Camox's merges of `main`
10027
- * reach the draft. `waiting` hears that the push waits for the turn. A push that landed adds
10028
- * its entry to the thread: the agent reads it, and doesn't answer it.
10029
- */
10030
- landPush(push: CheckedLanding & {
10031
- identity: ThreadIdentity;
10032
- pusher: ThreadSender;
10033
- }, waiting?: () => Promise<void> | void): Promise<Landing>;
10034
9679
  /**
10035
9680
  * Adds the entry of a member's push that landed on the thread's draft, starting the thread if
10036
9681
  * nobody messaged it yet: who pushed, their commits, and how the pushed head built. The model
@@ -10043,31 +9688,10 @@ declare class Thread extends DurableObject<Bindings> {
10043
9688
  result: BuildResult;
10044
9689
  }): Promise<void>;
10045
9690
  /**
10046
- * Merges the current `main` into the thread's draft, when it has code, as a push to `main`
10047
- * asks: right away when the agent is idle, or else right after its turn's last commit, before
10048
- * the next message (`#onYield`). Nothing of it shows in the thread.
10049
- */
10050
- mergeMain(): Promise<MergeEnd | "afterTheTurn" | "noCode">;
10051
- /**
10052
- * Lands the undo of a Publication's code on the thread's draft, which reverts it (ADR 0045),
10053
- * starting the thread: the draft's branch, made by `DraftCode.startReverting`, holds the undo
10054
- * on top of the Publication's commit. When `main` moved since, its merge applies the undo to
10055
- * Live's latest code, a clash starting Camox's reconcile turn, as any merge of `main` does
10056
- * (ADR 0020). Otherwise the undo is built as the draft's revision. Either goes on in the
10057
- * background: the draft shows it's building, or not holding Live's code, until it lands.
10058
- */
10059
- revertCode({ identity, mainMoved }: {
10060
- identity: ThreadIdentity;
10061
- mainMoved: boolean;
10062
- }): Promise<void>;
10063
- /**
10064
- * Builds the code of the thread's draft, as the end of a turn would on its last try, when
10065
- * Camox's infrastructure failed the last build: changes that don't build are committed as a
10066
- * revision that isn't built, which blocks publishing. Nothing of it shows in the thread. A
10067
- * failure on Camox's side again owes the next retry. `busy` while the agent's turn runs: its
10068
- * end builds.
9691
+ * Starts Camox's reconcile turn in the thread of the draft `identity` names, as a merge of
9692
+ * `main` into its code clashed, starting the thread if nobody messaged it yet.
10069
9693
  */
10070
- retryBuild(): Promise<"built" | "failed" | "busy" | "noCode">;
9694
+ reconcile(identity: ThreadIdentity): Promise<void>;
10071
9695
  /**
10072
9696
  * Lifecycle's alarm, which wakes Pi's runs, unless the thread ended: an alarm already on its
10073
9697
  * way when it did would look for the jobs its storage no longer has. A published draft's
@@ -10160,46 +9784,642 @@ declare class Thread extends DurableObject<Bindings> {
10160
9784
  * reconnecting. Everything it stored stays, so it continues where it stopped once the draft
10161
9785
  * is restored.
10162
9786
  */
10163
- archive(archivedBy: ThreadSender): Promise<void>;
10164
- }
10165
- //#endregion
10166
- //#region ../../apps/api/src/domains/code/main-copy.d.ts
10167
- /** A file of a project's code: its content, or where a symlink points. */
10168
- type CodeFile = {
10169
- path: string;
10170
- content: Uint8Array;
10171
- } | {
10172
- path: string;
10173
- symlink: string;
10174
- };
10175
- //#endregion
10176
- //#region ../../apps/api/src/durable-objects/project-code.d.ts
10177
- /** What `snapshot` answers: the files only when the caller doesn't already have that commit. */
10178
- type MainSnapshot = {
10179
- commit: string;
10180
- files?: CodeFile[];
10181
- };
10182
- /**
10183
- * A read-only copy of one project's `main`, addressed by its Project ID, which names its repo.
10184
- * The agent reads the website's code from it on Live, and in a draft without code. A push to
10185
- * `main` refreshes it (the release Workflow), and a copy that was never made is made on its first
10186
- * read. It keeps the files in its SQLite, so an eviction doesn't clone again; Git's own directory
10187
- * isn't kept.
10188
- */
10189
- declare class ProjectCode extends DurableObject<Bindings> {
10190
- #private;
10191
- constructor(ctx: DurableObjectState, env: Bindings);
9787
+ archive(archivedBy: ThreadSender): Promise<void>;
9788
+ }
9789
+ //#endregion
9790
+ //#region ../../apps/api/src/domains/code/main-copy.d.ts
9791
+ /** A file of a project's code: its content, or where a symlink points. */
9792
+ type CodeFile = {
9793
+ path: string;
9794
+ content: Uint8Array;
9795
+ } | {
9796
+ path: string;
9797
+ symlink: string;
9798
+ };
9799
+ //#endregion
9800
+ //#region ../../apps/api/src/durable-objects/project-code.d.ts
9801
+ /** What `snapshot` answers: the files only when the caller doesn't already have that commit. */
9802
+ type MainSnapshot = {
9803
+ commit: string;
9804
+ files?: CodeFile[];
9805
+ };
9806
+ /**
9807
+ * A read-only copy of one project's `main`, addressed by its Project ID, which names its repo.
9808
+ * The agent reads the website's code from it on Live, and in a draft without code. A push to
9809
+ * `main` refreshes it (the release Workflow), and a copy that was never made is made on its first
9810
+ * read. It keeps the files in its SQLite, so an eviction doesn't clone again; Git's own directory
9811
+ * isn't kept.
9812
+ */
9813
+ declare class ProjectCode extends DurableObject<Bindings> {
9814
+ #private;
9815
+ constructor(ctx: DurableObjectState, env: Bindings);
9816
+ /**
9817
+ * Makes the copy match `main`, unless it already holds `commit`, the commit a push moved `main`
9818
+ * to. Returns the commit it holds. One refresh at a time.
9819
+ */
9820
+ refresh(commit?: string): Promise<string>;
9821
+ /** Deletes the copy, as its project is deleted. */
9822
+ discard(): Promise<void>;
9823
+ /** The commit of `main` the copy holds, without making it if it never was. */
9824
+ commit(): Promise<string | undefined>;
9825
+ /** The copy, made first if it never was; only its commit when it's `known`. */
9826
+ snapshot(known?: string): Promise<MainSnapshot>;
9827
+ }
9828
+ //#endregion
9829
+ //#region ../../apps/api/src/lib/timing.d.ts
9830
+ /** What a span's line says beside its name and duration. Undefined fields are left out. */
9831
+ type SpanFields = Record<string, string | number | boolean | null | undefined>;
9832
+ //#endregion
9833
+ //#region ../../apps/api/src/domains/revisions/sandbox.d.ts
9834
+ /** A type check's outcome, with what it printed: its errors when it failed. */
9835
+ type SandboxTypeCheck = {
9836
+ ok: boolean;
9837
+ output: string;
9838
+ };
9839
+ /**
9840
+ * A build's outcome: its output as one gzipped tar archive, with the SDK Bundle it names (null
9841
+ * for a whole-app build) and the type check of the same tree, which may still be running, or the
9842
+ * log of its failure. Either way, `lint` has the findings of the lint that ran beside it: null
9843
+ * when it was asked for none, or Camox couldn't lint.
9844
+ */
9845
+ type SandboxBuild = {
9846
+ lint: Promise<LintError[] | null>;
9847
+ } & ({
9848
+ ok: true;
9849
+ archive: Uint8Array;
9850
+ sdkBundle: SdkBundleNames | null;
9851
+ typeCheck: Promise<SandboxTypeCheck>;
9852
+ } | {
9853
+ ok: false;
9854
+ log: string;
9855
+ });
9856
+ //#endregion
9857
+ //#region ../../apps/api/src/domains/code-pushes/checks.d.ts
9858
+ /** Why a push was refused: each reason is a stable code the CLI and its users can rely on. */
9859
+ type PushRefusalReason =
9860
+ /** What was sent isn't a Git bundle of one branch's commits. */
9861
+ "invalidBundle" |
9862
+ /** The pushed tree changes a platform-owned file, which only Upgrades change. */
9863
+ "platformFile" |
9864
+ /** The pushed tree adds or changes a file under `src/` that isn't TypeScript or CSS. */
9865
+ "notCode" |
9866
+ /** `main` changed a platform-owned file since the branch last merged it. */
9867
+ "mergeMainFirst" |
9868
+ /** The branch starts from a commit that was never on `main`. */
9869
+ "baseNotOnMain" |
9870
+ /** The branch doesn't merge cleanly with the current `main`. */
9871
+ "conflictsWithMain" |
9872
+ /** The pushed head doesn't build. */
9873
+ "doesNotBuild" |
9874
+ /** The pushed head doesn't include the draft's current head. */
9875
+ "pullDraftFirst" |
9876
+ /** The draft the push names was published or deleted. */
9877
+ "draftEnded";
9878
+ type PushRefusal = {
9879
+ reason: PushRefusalReason;
9880
+ message: string;
9881
+ data?: Record<string, unknown>;
9882
+ };
9883
+ /** A push that passed the checks: its head, as a commit to build, and what landing it needs. */
9884
+ type CheckedPush = {
9885
+ /** The pushed head, as a commit to build. */
9886
+ prepared: PreparedCommit;
9887
+ /**
9888
+ * The commits of `main` or of the draft's branch the pushed commits build on: the bundle's
9889
+ * prerequisites.
9890
+ */
9891
+ prerequisites: string[];
9892
+ /** The newest commit of `main` the pushed head holds, which a draft it opens forks from. */
9893
+ base: string;
9894
+ pack: Uint8Array;
9895
+ /** The subject of each pushed commit, oldest first. */
9896
+ subjects: string[];
9897
+ };
9898
+ //#endregion
9899
+ //#region ../../apps/api/src/domains/code-pushes/land.d.ts
9900
+ /** A push that passed its checks, as the draft it lands on receives it. */
9901
+ type CheckedLanding = CheckedPush & {
9902
+ /** The project's Project ID, which names its repo. */
9903
+ repo: string;
9904
+ };
9905
+ /** Whether the push landed, with its head's build, or why it was refused. */
9906
+ type Landing = {
9907
+ refused: PushRefusal;
9908
+ } | {
9909
+ result: BuildResult;
9910
+ };
9911
+ //#endregion
9912
+ //#region ../../apps/api/src/domains/code/remote-env.d.ts
9913
+ /** The operations sent as they are: every argument but the context is plain data. */
9914
+ declare const SENT: ["absolutePath", "joinPath", "readTextFile", "readTextLines", "readBinaryFile", "writeFile", "appendFile", "truncateFile", "flushFile", "renameFile", "fileInfo", "listDir", "canonicalPath", "exists", "createDir", "remove"];
9915
+ /** What a remote environment asks of the one it reaches. */
9916
+ type EnvCall = {
9917
+ operation: (typeof SENT)[number];
9918
+ args: unknown[];
9919
+ } |
9920
+ /** Opens a binary reader there and reads the whole file it opened. */
9921
+ {
9922
+ operation: "openBinaryReader";
9923
+ args: [path: string, options?: {
9924
+ noFollow?: boolean;
9925
+ }];
9926
+ };
9927
+ /** An operation's result as it crosses: its value, or its error as plain data. */
9928
+ type EnvAnswer = {
9929
+ ok: true;
9930
+ value: unknown;
9931
+ } | {
9932
+ ok: false;
9933
+ error: {
9934
+ code: FileErrorCode;
9935
+ message: string;
9936
+ path?: string;
9937
+ };
9938
+ };
9939
+ //#endregion
9940
+ //#region ../../apps/api/src/domains/revisions/build.d.ts
9941
+ /** What left a revision, and the thread run that did, if one did. */
9942
+ type RevisionOrigin = {
9943
+ leftBy: RevisionSource;
9944
+ run?: {
9945
+ threadId: string;
9946
+ runId: string;
9947
+ };
9948
+ /**
9949
+ * The commit to build, made beside the working copy's files, such as a merge of `main`
9950
+ * (`DraftCode.prepareMerge`) or a member's pushed head (`DraftCode.receive`). Without it, the
9951
+ * build is of the files.
9952
+ */
9953
+ prepared?: PreparedCommit;
9954
+ /**
9955
+ * The build of `prepared` made already, which a push's checks make before anything is
9956
+ * written: it's committed as it is rather than built again.
9957
+ */
9958
+ built?: Extract<SandboxBuild, {
9959
+ ok: true;
9960
+ }>;
9961
+ /** For a member's pushed head, the newest commit of `main` it holds. */
9962
+ mergedMain?: string;
9963
+ /**
9964
+ * The files whose lint findings the result lists, linted beside the build. A lint Camox can't
9965
+ * run finds nothing: it never fails the build.
9966
+ */
9967
+ lint?: string[];
9968
+ };
9969
+ //#endregion
9970
+ //#region ../../apps/api/src/domains/revisions/end-of-turn.d.ts
9971
+ /** What the end of a turn did about the code the turn changed. */
9972
+ type TurnBuild =
9973
+ /** The turn's code already is a revision: nothing changed since the last one. */
9974
+ {
9975
+ outcome: "unchanged";
9976
+ } | {
9977
+ outcome: "built";
9978
+ result: BuildResult;
9979
+ } |
9980
+ /**
9981
+ * The turn's code builds, but lint found problems in the files it changed: the agent is handed
9982
+ * `result` to fix them. Once it had them too often, the turn ends `built`, with them.
9983
+ */
9984
+ {
9985
+ outcome: "linted";
9986
+ result: BuildResult;
9987
+ } |
9988
+ /** The build failed: the agent is handed `result` to fix it. */
9989
+ {
9990
+ outcome: "failed";
9991
+ result: BuildResult;
9992
+ } |
9993
+ /** The build failed once too often: the changes are committed anyway, as a revision not built. */
9994
+ {
9995
+ outcome: "committedUnbuilt";
9996
+ result: BuildResult;
9997
+ } |
9998
+ /**
9999
+ * The changes built, committed, but had errors once too often: type errors, or definitions the
10000
+ * draft can't use. They stay as they are.
10001
+ */
10002
+ {
10003
+ outcome: "keptErrors";
10004
+ result: BuildResult;
10005
+ } |
10006
+ /**
10007
+ * The build failed once too often, but its changes can't be committed as they are: the files
10008
+ * hold a merge of Live's code that Camox's reconcile turn didn't fix, or conflict markers.
10009
+ * Nothing is committed: `merging` says whether the files hold a merge.
10010
+ */
10011
+ {
10012
+ outcome: "uncommitted";
10013
+ result: BuildResult;
10014
+ merging: boolean;
10015
+ };
10016
+ /**
10017
+ * Builds what a turn changed in the code of the draft `draftId`, which has code, as the turn
10018
+ * ends: whatever changed since its last revision, nothing when the agent's last `build` already
10019
+ * covered it without errors. A passing build leaves a revision, even with type errors. A build
10020
+ * fails when it, its type check or its definitions have errors. `failedInARow` is how many
10021
+ * end-of-turn builds of this turn failed before this one: once this one makes
10022
+ * `END_OF_TURN_BUILD_FAILURES`, changes that didn't build are committed anyway, as a revision
10023
+ * that isn't built, and ones that did stay with their errors. `building` runs before a build
10024
+ * starts.
10025
+ *
10026
+ * The files the turn changed since `base`, the commit its code was at as it started, are linted
10027
+ * too, beside the build, or alone when the agent's builds covered its changes: findings in code
10028
+ * that builds hand the agent a `linted` result, and count as a failure, and the findings of a
10029
+ * build that fails come with its errors. Lint never fails a build, and the turn ends with
10030
+ * findings it had once too often.
10031
+ */
10032
+ declare function buildAtEndOfTurn(env: Bindings, draftId: string, { run, failedInARow, building, base }: {
10033
+ run?: RevisionOrigin["run"];
10034
+ failedInARow: number;
10035
+ building: () => Promise<void>;
10036
+ base?: string;
10037
+ }): Promise<TurnBuild>;
10038
+ //#endregion
10039
+ //#region ../../apps/api/src/domains/revisions/merge.d.ts
10040
+ /** How a merge of `main` into a draft ended. */
10041
+ type MergeEnd =
10042
+ /** The draft holds the current `main`, or will once its changes are committed. */
10043
+ "upToDate" |
10044
+ /** A merge revision landed, built, and the draft previews it. */
10045
+ "merged" |
10046
+ /** The merge clashed: it's left for Camox's reconcile turn (`DraftCode.clash`), to start. */
10047
+ "clashed" |
10048
+ /** This move of `main` clashed already: Camox's reconcile turn had its one try. */
10049
+ "clashedBefore";
10050
+ //#endregion
10051
+ //#region ../../apps/api/src/domains/revisions/code-queue.d.ts
10052
+ /** What the code queue asks of the draft's thread. */
10053
+ type DraftThread = {
10054
+ /** Whether the agent is mid-turn in the draft's thread. */
10055
+ turnGoing(): Promise<boolean>;
10056
+ /** Starts Camox's turn reconciling the draft's code with Live's, whose merge clashed. */
10057
+ reconcile(): Promise<void>;
10058
+ };
10059
+ /** What the code queue needs of the `DraftCode` holding it. */
10060
+ type CodeQueueHost = {
10061
+ env: Bindings;
10062
+ storage: DurableObjectStorage;
10063
+ draftId: () => string;
10064
+ /** Whether the draft has code. */
10065
+ held: () => boolean;
10066
+ /** The files its sandbox installs from, ahead of a build (`DraftCode.installFiles`). */
10067
+ installFiles: () => Promise<Pick<PreparedCommit, "files" | "lockfile">>;
10068
+ thread: () => DraftThread;
10069
+ waitUntil: (promise: Promise<unknown>) => void;
10070
+ };
10071
+ /** The draft's code queue (see above), for its `DraftCode` to answer with. */
10072
+ declare class CodeQueue {
10073
+ #private;
10074
+ constructor(host: CodeQueueHost);
10075
+ /** Builds the files as a revision, as the agent's `build` or a publish asks. None without code. */
10076
+ build({ run }?: {
10077
+ run?: RevisionOrigin["run"];
10078
+ }): Promise<BuildResult | null>;
10079
+ /**
10080
+ * Builds what the agent's turn changed, as it ends (`buildAtEndOfTurn`). A build Camox's
10081
+ * infrastructure failed is owed, and retried later: the turn ends on it.
10082
+ */
10083
+ buildAtTurnEnd(turn: Omit<Parameters<typeof buildAtEndOfTurn>[2], "building"> & {
10084
+ building: () => Promise<void> | void;
10085
+ }): Promise<TurnBuild | {
10086
+ outcome: "owed";
10087
+ }>;
10088
+ /**
10089
+ * Starts the draft's sandbox and installs its dependencies, in the queue, so the next build
10090
+ * finds them. Doesn't count as building.
10091
+ */
10092
+ warmSandbox(span: SpanFields): Promise<void>;
10093
+ /**
10094
+ * Merges the current `main` into the draft, as a push to `main` asks: right away unless the
10095
+ * agent is mid-turn, or else once its turn ended (`turnEnded`).
10096
+ */
10097
+ mergeMain(): Promise<MergeEnd | "afterTheTurn" | "noCode">;
10098
+ /**
10099
+ * Lands the member's checked push `push`, once the agent's turn going, if any, made its last
10100
+ * commit. `waiting` hears that it waits for the turn.
10101
+ */
10102
+ landPush(push: CheckedLanding, waiting?: () => Promise<void> | void): Promise<Landing>;
10103
+ /**
10104
+ * Lands what waited for the agent's turn, as it ends: the merge of the `main` that moved
10105
+ * during it, then the members' pushes, one after the other.
10106
+ */
10107
+ turnEnded(): Promise<void>;
10108
+ /**
10109
+ * Lands the undo of a Publication's code, which `DraftCode.startReverting` put on the
10110
+ * draft's branch, in the background: merged with Live's latest code when `main` moved since,
10111
+ * or else built as the draft's revision. The draft shows it's building from now, so a publish
10112
+ * asked meanwhile waits for it.
10113
+ */
10114
+ landRevert({ mainMoved }: {
10115
+ mainMoved: boolean;
10116
+ }): void;
10117
+ /** Waits for the merge of `main` or the member's push landing now, if any: it lands beside the files. */
10118
+ untilLanded(): Promise<void>;
10119
+ /**
10120
+ * Whether a build of the draft's code is going (see `BUILD_GOING_FOR_AT_MOST_MS`), or owed:
10121
+ * Camox's infrastructure failed the last one, and Camox retries it. A type check, going or
10122
+ * owed, isn't building (ADR 0043).
10123
+ */
10124
+ building(): boolean;
10125
+ /**
10126
+ * Records that the build going ended, or is previewed, its type check going on: the draft no
10127
+ * longer shows it's building, and a publish waiting for it ships what it left.
10128
+ */
10129
+ buildEnded(): Promise<void>;
10130
+ /**
10131
+ * Retries the build Camox owes the draft, as the end of a turn would on its last try: changes
10132
+ * that don't build are committed as a revision that isn't built. A turn going builds at its
10133
+ * end, so the retry waits for the next one.
10134
+ */
10135
+ retryOwed(): Promise<void>;
10136
+ }
10137
+ //#endregion
10138
+ //#region ../../apps/api/src/durable-objects/draft-code.d.ts
10139
+ /** A revision of the draft whose build goes up as its publish script. */
10140
+ type PublishUpload = {
10141
+ /** The project's Project ID. */
10142
+ project: string;
10143
+ revision: string;
10144
+ /** Its build in `REVISION_BUILDS`. */
10145
+ archiveKey: string;
10146
+ };
10147
+ /** A commit `prepareCommit` made, not on the branch yet. */
10148
+ type PreparedCommit = {
10149
+ commit: string;
10150
+ tree: string;
10151
+ /** The tree's files, as a tar archive. */
10152
+ files: Uint8Array;
10153
+ /** The tree's `pnpm-lock.yaml`, if it has one. */
10154
+ lockfile: string | null;
10155
+ };
10156
+ /**
10157
+ * A merge of `main` that doesn't land as a revision as it is: it conflicts, or its tree doesn't
10158
+ * build or type check. Recorded for Camox's reconcile turn, which tries once for each move of
10159
+ * `main`, until code holding that `main` builds without errors (`settleClash`): the draft has
10160
+ * the "doesn't merge with Live's" blocker until then.
10161
+ */
10162
+ type MergeClash = {
10163
+ /** The commit of `main` that clashed. */
10164
+ main: string;
10165
+ /** The files both sides changed in ways that don't merge, for a merge that conflicts. */
10166
+ conflicts?: string[];
10167
+ /** The merged tree's build, for a merge that doesn't build or type check. */
10168
+ result?: BuildResult;
10169
+ };
10170
+ /** What merging `main` into the working copy found. */
10171
+ type MergeOutcome =
10172
+ /** The draft holds the current `main` already. */
10173
+ {
10174
+ outcome: "upToDate";
10175
+ } |
10176
+ /** The working copy has changes no revision holds yet: the merge waits for them. */
10177
+ {
10178
+ outcome: "unsettled";
10179
+ } |
10180
+ /** This move of `main` clashed already, and isn't merged again until `main` moves again. */
10181
+ {
10182
+ outcome: "clashedBefore";
10183
+ main: string;
10184
+ } | {
10185
+ outcome: "conflicts";
10186
+ main: string;
10187
+ conflicts: string[];
10188
+ } |
10189
+ /** A merge commit of `main`, not on the branch yet, for a build to commit. */
10190
+ {
10191
+ outcome: "merged";
10192
+ main: string;
10193
+ prepared: PreparedCommit;
10194
+ };
10195
+ /**
10196
+ * The working copy of one draft with code, addressed by the draft's ID (`getByName`): a depth-1
10197
+ * clone of the draft's branch, held in memory, which the agent's code tools read and write over
10198
+ * RPC, through the write line. Every change is saved to its SQLite as it's made, Git's own
10199
+ * directory included, so an eviction restores it without cloning again. The skills of its `camox`
10200
+ * version are mounted beside the files and never saved, nor committed.
10201
+ *
10202
+ * It stores nothing until `start` made it, and nothing once `delete` deleted it.
10203
+ */
10204
+ declare class DraftCode extends DurableObject<Bindings> {
10205
+ #private;
10206
+ /** Whether the draft has code: its branch was made, and not deleted since. */
10207
+ held(): Promise<boolean>;
10208
+ /**
10209
+ * The commit of `main` the draft's code holds: the one its branch last merged, or forked from,
10210
+ * once it has code.
10211
+ */
10212
+ mergedMain(): Promise<string | undefined>;
10213
+ /**
10214
+ * Where the draft's merges of `main` stand: the branch's head, the `main` it holds, and the
10215
+ * last merge that clashed, read at once, as a commit moves them together.
10216
+ */
10217
+ merges(): Promise<{
10218
+ head: string;
10219
+ mergedMain: string;
10220
+ clash: MergeClash | undefined;
10221
+ }>;
10222
+ /** The last merge of `main` that clashed, until a merge of `main` lands. */
10223
+ clash(): Promise<MergeClash | undefined>;
10224
+ /**
10225
+ * Records that the merge of `main` at `clash.main` clashed (see `MergeClash`), for Camox's
10226
+ * reconcile turn. A merge that didn't land is left in the files, uncommitted, conflict markers
10227
+ * included, and the next revision is its merge commit: see `merging`.
10228
+ */
10229
+ recordClash(clash: MergeClash): Promise<void>;
10230
+ /**
10231
+ * The commit of `main` whose merge the files hold, uncommitted, if they do: Camox's reconcile
10232
+ * turn fixes it, and its build commits the merge commit.
10233
+ */
10234
+ merging(): Promise<string | undefined>;
10235
+ /**
10236
+ * Forgets the clash, once the draft's code built without errors and holds the `main` that
10237
+ * clashed: unless the files still hold a merge no commit landed.
10238
+ */
10239
+ settleClash(): Promise<void>;
10240
+ /**
10241
+ * Uploads the build of the draft's revision `revision` as the draft's publish script, ahead of
10242
+ * its publish, unless the script holds it already: its publish then only checks it's there
10243
+ * (`uploadForPublish`). Nothing once a publish took the script, until that publish ends, nor
10244
+ * once the draft ended. A draft that ended during the upload, deleted, loses the script.
10245
+ */
10246
+ prepareUpload(toUpload: PublishUpload): Promise<void>;
10247
+ /**
10248
+ * The draft's publish script holding the build of `revision`, which the publish `instanceId`
10249
+ * ships, taking it: no upload ahead replaces it until that publish ends. Uploads it unless the
10250
+ * script holds it already, as the upload ahead left it. Returns its name, and whether this
10251
+ * uploaded it.
10252
+ */
10253
+ uploadForPublish(toUpload: PublishUpload, instanceId: string, span?: SpanFields): Promise<{
10254
+ script: string;
10255
+ uploaded: boolean;
10256
+ }>;
10257
+ /** The publish of the draft going now, if any: its Workflow instance. */
10258
+ publishGoing(): Promise<string | null>;
10259
+ /**
10260
+ * Records that a member's push landed during the publish `instanceId`: the revision it waits
10261
+ * for a build to leave changed under it, so it goes back to the review (ADR 0043).
10262
+ */
10263
+ notePushDuring(instanceId: string): Promise<void>;
10264
+ /** Whether a member's push landed during the publish `instanceId`. */
10265
+ pushedDuring(instanceId: string): Promise<boolean>;
10266
+ /**
10267
+ * The draft's thread, as its code queue asks it whether a turn is going: the one the draft's
10268
+ * row names. Tests put a fake in its place.
10269
+ */
10270
+ draftThread: DraftThread;
10271
+ /** Builds the files as a revision, as the agent's `build` or a publish asks. None without code. */
10272
+ build(options?: Parameters<CodeQueue["build"]>[0]): Promise<BuildResult | null>;
10273
+ /**
10274
+ * Builds what the agent's turn changed, as it ends: `building` runs before a build starts. A
10275
+ * build Camox's infrastructure failed is owed, and retried later: the turn ends on it.
10276
+ */
10277
+ buildAtTurnEnd(turn: Parameters<CodeQueue["buildAtTurnEnd"]>[0]): Promise<TurnBuild | {
10278
+ outcome: "owed";
10279
+ }>;
10280
+ /** Starts the draft's sandbox ahead of its next build, in the queue. */
10281
+ warmSandbox(span: SpanFields): Promise<void>;
10282
+ /**
10283
+ * Merges the current `main` into the draft, as a push to `main` asks: right away unless the
10284
+ * agent is mid-turn, or else once its turn ended (`turnEnded`). Nothing of it shows in the
10285
+ * thread, unless it clashes: Camox's reconcile turn then starts there.
10286
+ */
10287
+ mergeMain(): Promise<MergeEnd | "afterTheTurn" | "noCode">;
10288
+ /**
10289
+ * Lands a member's checked push on the draft (ADR 0026), once the agent's turn going, if any,
10290
+ * made its last commit. `waiting` hears that the push waits for the turn. A draft without
10291
+ * code gets its branch from the push.
10292
+ */
10293
+ landPush(push: CheckedLanding, waiting?: () => Promise<void> | void): Promise<Landing>;
10294
+ /** Lands what waited for the agent's turn, as it ends: a merge of `main`, then pushes. */
10295
+ turnEnded(): Promise<void>;
10296
+ /**
10297
+ * Lands the undo of a Publication's code, which `startReverting` made, in the background
10298
+ * (ADR 0045). The draft shows it's building from now, so its publish waits for it.
10299
+ */
10300
+ landRevert({ mainMoved }: {
10301
+ mainMoved: boolean;
10302
+ }): Promise<void>;
10303
+ /** Waits for the merge of `main` or the push landing now, if any: code writes wait for it. */
10304
+ untilLanded(): Promise<void>;
10305
+ /**
10306
+ * Whether a build of the draft's code is going, or owed: Camox's infrastructure failed the
10307
+ * last one, and Camox retries it. A type check, going or owed, isn't building (ADR 0043).
10308
+ */
10309
+ building(): Promise<boolean>;
10310
+ /**
10311
+ * Records that the build going is previewed: the draft no longer shows it's building, though
10312
+ * its type check goes on.
10313
+ */
10314
+ buildPreviewed(): Promise<void>;
10315
+ /** Retries the build Camox owes the draft, until one lands. */
10316
+ alarm(): Promise<void>;
10317
+ /**
10318
+ * Makes the draft's branch and working copy, from `commit` of `main` in the project's repo
10319
+ * `repo`, unless they were made already. Returns the commit the branch forked from.
10320
+ */
10321
+ start({ repo, commit }: {
10322
+ repo: string;
10323
+ commit: string;
10324
+ }): Promise<string>;
10325
+ /**
10326
+ * Makes the branch and working copy of a draft reverting a Publication, unless they were made
10327
+ * already: forked from `commit`, the Publication's commit on `main`, with one commit on top,
10328
+ * `message`, putting back the tree `main` had before it. Merging the current `main` then
10329
+ * applies that undo to Live's latest code, as a merge of `main` into any draft (`prepareMerge`):
10330
+ * code a later publish changed since clashes as merges do. Returns whether `main` moved since
10331
+ * `commit`, which a merge then brings in, or null, making nothing, when `commit` is `main`'s
10332
+ * first: there's no code before it to put back.
10333
+ */
10334
+ startReverting({ repo, commit, message }: {
10335
+ repo: string;
10336
+ commit: string;
10337
+ message: string;
10338
+ }): Promise<{
10339
+ mainMoved: boolean;
10340
+ } | null>;
10341
+ /** Runs one operation of the agent's environment on the working copy, and saves what it changed. */
10342
+ call(call: EnvCall): Promise<EnvAnswer>;
10343
+ /**
10344
+ * The files that have merge conflict markers, as a merge of `main` that conflicts leaves them:
10345
+ * only files the branch's head doesn't hold as they are, since no commit holds markers.
10346
+ */
10347
+ conflicts(): Promise<string[]>;
10348
+ /**
10349
+ * The paths of the working copy's files that differ from the commit `since`, added or changed
10350
+ * since, without those deleted: since the branch's head when the working copy doesn't hold it,
10351
+ * or without `since`.
10352
+ */
10353
+ changedFiles({ since }?: {
10354
+ since?: string;
10355
+ }): Promise<string[]>;
10356
+ /**
10357
+ * The working copy's files that installing its dependencies reads, as a tar archive, with its
10358
+ * lockfile: what its sandbox needs to install ahead of a build, which `prepareCommit` would
10359
+ * give only once it staged and committed every change.
10360
+ */
10361
+ installFiles(): Promise<Pick<PreparedCommit, "files" | "lockfile">>;
10362
+ /**
10363
+ * Stages the working copy's every change and makes, without moving the branch, the commit it
10364
+ * would be: `message` on top of the branch's head. Returns the commit and its tree, with the
10365
+ * tree's files as a tar archive, which a build streams into its sandbox, and the lockfile.
10366
+ * Neither Git's directory nor the references mounted beside the files are in the tree.
10367
+ */
10368
+ prepareCommit({ message }: {
10369
+ message: string;
10370
+ }): Promise<PreparedCommit>;
10371
+ /**
10372
+ * Adds a member's pushed commits to the working copy, without moving the branch: the objects of
10373
+ * `pack`, a bundle's packfile, which may build on the objects of `prerequisites`, commits of
10374
+ * `main` fetched for it when the working copy doesn't hold them. A build then commits the
10375
+ * pushed head (`commit`, with `checkout`).
10376
+ */
10377
+ receive({ pack, prerequisites }: {
10378
+ pack: Uint8Array;
10379
+ prerequisites: string[];
10380
+ }): Promise<void>;
10381
+ /**
10382
+ * Moves the draft's branch to `commit`, which `prepareCommit` made, or a member pushed on top
10383
+ * of the branch's head, and pushes it. A commit of the tree the branch's head already has, such
10384
+ * as one prepared again after the push of the first, leaves the head as it is. With
10385
+ * `checkout`, for a commit made beside the files, the files take its tree. A member's pushed
10386
+ * head names `mergedMain`, the newest commit of `main` it holds, which the draft's next merge of
10387
+ * `main` merges from. Returns the branch's head and its parents.
10388
+ */
10389
+ commit({ commit, checkout, mergedMain }: {
10390
+ commit: string;
10391
+ checkout?: boolean;
10392
+ mergedMain?: string;
10393
+ }): Promise<{
10394
+ commit: string;
10395
+ parents: string[];
10396
+ }>;
10397
+ /** Whether `commit` is the branch's head or one of its descendants: it includes the head. */
10398
+ includesHead(commit: string): Promise<boolean>;
10399
+ /**
10400
+ * Pushes the draft's code to `main` as one squashed commit, as a publish lands: the tree of
10401
+ * `commit`, a revision on the branch, with the current tip of `main` as its only parent. A
10402
+ * `main` that already has that tree, as after a retried push that landed, is left as it is.
10403
+ * Returns the commit `main` points to.
10404
+ */
10405
+ publishToMain({ commit, message }: {
10406
+ commit: string;
10407
+ message: string;
10408
+ }): Promise<string>;
10192
10409
  /**
10193
- * Makes the copy match `main`, unless it already holds `commit`, the commit a push moved `main`
10194
- * to. Returns the commit it holds. One refresh at a time.
10410
+ * Merges the current `main` into the branch, without moving it: fetches `main` shallowly, its
10411
+ * history down to the `main` commit the branch last merged or forked from, which is then the
10412
+ * merge base, and merges it into the branch's head. A clean merge is returned as a merge commit
10413
+ * whose parents are the head and `main`, for a build to commit (`commit`): the files stay as
10414
+ * they are until then. A merge that conflicts changes nothing either.
10415
+ *
10416
+ * It waits while the files have changes no commit holds, and doesn't merge again a move of
10417
+ * `main` that clashed. Files holding the merge of an earlier `main` that Camox's reconcile
10418
+ * turn didn't fix (`merging`) are put back to the branch's head first, to merge this one.
10195
10419
  */
10196
- refresh(commit?: string): Promise<string>;
10197
- /** Deletes the copy, as its project is deleted. */
10198
- discard(): Promise<void>;
10199
- /** The commit of `main` the copy holds, without making it if it never was. */
10200
- commit(): Promise<string | undefined>;
10201
- /** The copy, made first if it never was; only its commit when it's `known`. */
10202
- snapshot(known?: string): Promise<MainSnapshot>;
10420
+ prepareMerge(): Promise<MergeOutcome>;
10421
+ /** Deletes the draft's branch and everything the working copy stored, as the draft ends. */
10422
+ delete(): Promise<void>;
10203
10423
  }
10204
10424
  //#endregion
10205
10425
  //#region ../../apps/api/src/domains/project-creation/workflow.d.ts
@@ -10388,7 +10608,7 @@ type Dispatch = {
10388
10608
  * `archive` when the API sends it, as it does while it stores it, or else from R2:
10389
10609
  * dispatch serves its client assets from then on, and has loaded and rendered it once. Returns
10390
10610
  * its Definition Set (JSON, not yet checked), with what each part took, for the API's timing
10391
- * logs.
10611
+ * logs. Fails as `REVISION_CODE_THREW` says when the revision's own code throws.
10392
10612
  */
10393
10613
  prepare(revision: RevisionToLoad, archive?: Uint8Array): Promise<PreparedRevision>;
10394
10614
  };
@@ -15524,6 +15744,100 @@ declare const router: {
15524
15744
  projectId: import("zod").ZodNumber;
15525
15745
  tag: import("zod").ZodString;
15526
15746
  }, import("zod/v4/core").$strip>, import("@orpc/server").Schema<LocaleView, LocaleView>, Record<never, never>, Record<never, never>>;
15747
+ setDefault: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<import("@orpc/server").MergedInitialContext<import("@orpc/server").MergedInitialContext<import("@orpc/server").MergedInitialContext<BaseContext & Record<never, never>, BaseContext, BaseContext>, import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
15748
+ draft: DraftRequest | null;
15749
+ locale: string | undefined;
15750
+ publishingDraft: string | undefined;
15751
+ look: LookGrant | undefined;
15752
+ }>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
15753
+ draft: DraftRequest | null;
15754
+ locale: string | undefined;
15755
+ publishingDraft: string | undefined;
15756
+ look: LookGrant | undefined;
15757
+ }>>, {
15758
+ draft: DraftRequest | null;
15759
+ } & Record<never, never>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
15760
+ draft: DraftRequest | null;
15761
+ locale: string | undefined;
15762
+ publishingDraft: string | undefined;
15763
+ look: LookGrant | undefined;
15764
+ }>, {
15765
+ db: Database;
15766
+ env: Bindings;
15767
+ headers: Headers;
15768
+ client: string;
15769
+ telemetryDisabled: boolean;
15770
+ waitUntil: (promise: Promise<unknown>) => void;
15771
+ apiOrigin?: string;
15772
+ draft: DraftRequest | null;
15773
+ locale: string | undefined;
15774
+ publishingDraft: string | undefined;
15775
+ look: LookGrant | undefined;
15776
+ user: {
15777
+ id: string;
15778
+ createdAt: Date;
15779
+ updatedAt: Date;
15780
+ email: string;
15781
+ emailVerified: boolean;
15782
+ name: string;
15783
+ image?: string | null | undefined;
15784
+ };
15785
+ session: {
15786
+ id: string;
15787
+ createdAt: Date;
15788
+ updatedAt: Date;
15789
+ userId: string;
15790
+ expiresAt: Date;
15791
+ token: string;
15792
+ ipAddress?: string | null | undefined;
15793
+ userAgent?: string | null | undefined;
15794
+ activeOrganizationId?: string | null | undefined;
15795
+ local?: boolean | null | undefined;
15796
+ studio?: boolean | null | undefined;
15797
+ };
15798
+ }>>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
15799
+ draft: DraftRequest | null;
15800
+ locale: string | undefined;
15801
+ publishingDraft: string | undefined;
15802
+ look: LookGrant | undefined;
15803
+ }>, {
15804
+ db: Database;
15805
+ env: Bindings;
15806
+ headers: Headers;
15807
+ client: string;
15808
+ telemetryDisabled: boolean;
15809
+ waitUntil: (promise: Promise<unknown>) => void;
15810
+ apiOrigin?: string;
15811
+ draft: DraftRequest | null;
15812
+ locale: string | undefined;
15813
+ publishingDraft: string | undefined;
15814
+ look: LookGrant | undefined;
15815
+ user: {
15816
+ id: string;
15817
+ createdAt: Date;
15818
+ updatedAt: Date;
15819
+ email: string;
15820
+ emailVerified: boolean;
15821
+ name: string;
15822
+ image?: string | null | undefined;
15823
+ };
15824
+ session: {
15825
+ id: string;
15826
+ createdAt: Date;
15827
+ updatedAt: Date;
15828
+ userId: string;
15829
+ expiresAt: Date;
15830
+ token: string;
15831
+ ipAddress?: string | null | undefined;
15832
+ userAgent?: string | null | undefined;
15833
+ activeOrganizationId?: string | null | undefined;
15834
+ local?: boolean | null | undefined;
15835
+ studio?: boolean | null | undefined;
15836
+ };
15837
+ }>, Record<never, never>>, import("zod").ZodObject<{
15838
+ projectId: import("zod").ZodNumber;
15839
+ tag: import("zod").ZodString;
15840
+ }, import("zod/v4/core").$strip>, import("@orpc/server").Schema<LocaleView, LocaleView>, Record<never, never>, Record<never, never>>;
15527
15841
  setDefaultTag: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<import("@orpc/server").MergedInitialContext<import("@orpc/server").MergedInitialContext<BaseContext & Record<never, never>, BaseContext, BaseContext>, import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
15528
15842
  draft: DraftRequest | null;
15529
15843
  locale: string | undefined;
@@ -15739,6 +16053,114 @@ declare const router: {
15739
16053
  entity: "page" | "record";
15740
16054
  id: string;
15741
16055
  }>, Record<never, never>, Record<never, never>>;
16056
+ retranslate: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<import("@orpc/server").MergedInitialContext<import("@orpc/server").MergedInitialContext<import("@orpc/server").MergedInitialContext<BaseContext & Record<never, never>, BaseContext, BaseContext>, import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
16057
+ draft: DraftRequest | null;
16058
+ locale: string | undefined;
16059
+ publishingDraft: string | undefined;
16060
+ look: LookGrant | undefined;
16061
+ }>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
16062
+ draft: DraftRequest | null;
16063
+ locale: string | undefined;
16064
+ publishingDraft: string | undefined;
16065
+ look: LookGrant | undefined;
16066
+ }>>, {
16067
+ draft: DraftRequest | null;
16068
+ } & Record<never, never>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
16069
+ draft: DraftRequest | null;
16070
+ locale: string | undefined;
16071
+ publishingDraft: string | undefined;
16072
+ look: LookGrant | undefined;
16073
+ }>, {
16074
+ db: Database;
16075
+ env: Bindings;
16076
+ headers: Headers;
16077
+ client: string;
16078
+ telemetryDisabled: boolean;
16079
+ waitUntil: (promise: Promise<unknown>) => void;
16080
+ apiOrigin?: string;
16081
+ draft: DraftRequest | null;
16082
+ locale: string | undefined;
16083
+ publishingDraft: string | undefined;
16084
+ look: LookGrant | undefined;
16085
+ user: {
16086
+ id: string;
16087
+ createdAt: Date;
16088
+ updatedAt: Date;
16089
+ email: string;
16090
+ emailVerified: boolean;
16091
+ name: string;
16092
+ image?: string | null | undefined;
16093
+ };
16094
+ session: {
16095
+ id: string;
16096
+ createdAt: Date;
16097
+ updatedAt: Date;
16098
+ userId: string;
16099
+ expiresAt: Date;
16100
+ token: string;
16101
+ ipAddress?: string | null | undefined;
16102
+ userAgent?: string | null | undefined;
16103
+ activeOrganizationId?: string | null | undefined;
16104
+ local?: boolean | null | undefined;
16105
+ studio?: boolean | null | undefined;
16106
+ };
16107
+ }>>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
16108
+ draft: DraftRequest | null;
16109
+ locale: string | undefined;
16110
+ publishingDraft: string | undefined;
16111
+ look: LookGrant | undefined;
16112
+ }>, {
16113
+ db: Database;
16114
+ env: Bindings;
16115
+ headers: Headers;
16116
+ client: string;
16117
+ telemetryDisabled: boolean;
16118
+ waitUntil: (promise: Promise<unknown>) => void;
16119
+ apiOrigin?: string;
16120
+ draft: DraftRequest | null;
16121
+ locale: string | undefined;
16122
+ publishingDraft: string | undefined;
16123
+ look: LookGrant | undefined;
16124
+ user: {
16125
+ id: string;
16126
+ createdAt: Date;
16127
+ updatedAt: Date;
16128
+ email: string;
16129
+ emailVerified: boolean;
16130
+ name: string;
16131
+ image?: string | null | undefined;
16132
+ };
16133
+ session: {
16134
+ id: string;
16135
+ createdAt: Date;
16136
+ updatedAt: Date;
16137
+ userId: string;
16138
+ expiresAt: Date;
16139
+ token: string;
16140
+ ipAddress?: string | null | undefined;
16141
+ userAgent?: string | null | undefined;
16142
+ activeOrganizationId?: string | null | undefined;
16143
+ local?: boolean | null | undefined;
16144
+ studio?: boolean | null | undefined;
16145
+ };
16146
+ }>, Record<never, never>>, import("zod").ZodObject<{
16147
+ projectId: import("zod").ZodNumber;
16148
+ entity: import("zod").ZodEnum<{
16149
+ block: "block";
16150
+ page: "page";
16151
+ record: "record";
16152
+ repeatableItem: "repeatableItem";
16153
+ }>;
16154
+ id: import("zod").ZodUUID;
16155
+ }, import("zod/v4/core").$strip>, import("@orpc/server").Schema<{
16156
+ entity: "block" | "page" | "record" | "repeatableItem";
16157
+ id: string;
16158
+ localizations: number;
16159
+ }, {
16160
+ entity: "block" | "page" | "record" | "repeatableItem";
16161
+ id: string;
16162
+ localizations: number;
16163
+ }>, Record<never, never>, Record<never, never>>;
15742
16164
  };
15743
16165
  files: {
15744
16166
  list: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<import("@orpc/server").MergedInitialContext<BaseContext & Record<never, never>, BaseContext, BaseContext>, import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>>, import("@orpc/server").MergedCurrentContext<import("@orpc/server").MergedCurrentContext<BaseContext, Record<never, never>>, {
@@ -18889,7 +19311,7 @@ declare const router: {
18889
19311
  token: string;
18890
19312
  blockers: Problem[];
18891
19313
  changes: Change[];
18892
- defaultLocale: string | null;
19314
+ defaultLocale: string;
18893
19315
  overview: {
18894
19316
  status: "pending";
18895
19317
  } | {
@@ -18914,7 +19336,7 @@ declare const router: {
18914
19336
  token: string;
18915
19337
  blockers: Problem[];
18916
19338
  changes: Change[];
18917
- defaultLocale: string | null;
19339
+ defaultLocale: string;
18918
19340
  overview: {
18919
19341
  status: "pending";
18920
19342
  } | {