@camox/api-contract 0.71.0 → 0.74.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.
@@ -1,13 +1,13 @@
1
- //#region src/patrol.d.ts
1
+ //#region src/specialists.d.ts
2
2
  /**
3
- * The Patrol (ADR 0024): every patroller of a project, the work each did as reports, as the
3
+ * The Specialists (ADR 0024): every specialist of a project, the work each did as reports, as the
4
4
  * studio shows it at the top of the Agent Sidebar. The API reads it for one scope, a draft or
5
5
  * Live, and names each report's subject, so the studio needs no entity loaded to show it.
6
6
  */
7
- /** Every patroller's stable id. The registry in the API lists them all. */
8
- export declare const PATROLLER_IDS: readonly ["translator", "seoManager", "linkChecker"];
9
- /** A patroller's stable id. */
10
- export type PatrollerId = (typeof PATROLLER_IDS)[number];
7
+ /** Every specialist's stable id. The registry in the API lists them all. */
8
+ export declare const SPECIALIST_IDS: readonly ["translator", "seoManager", "linkChecker"];
9
+ /** A specialist's stable id. */
10
+ export type SpecialistId = (typeof SPECIALIST_IDS)[number];
11
11
  /**
12
12
  * What a structured report says was done. Each has a failed form, by the report's outcome. A
13
13
  * merge with Live's localization reads as a translation.
@@ -15,7 +15,7 @@ export type PatrollerId = (typeof PATROLLER_IDS)[number];
15
15
  export type ReportVerb = "translated" | "mergedWithLive" | "wroteSeo" | "describedFile" | "publishedCatchUp" | "removedLink" | "fixedLink";
16
16
  /** What a report can be about. */
17
17
  export type ReportEntity = "page" | "block" | "sharedContent" | "repeatableItem" | "record" | "file";
18
- /** A report's subject, named as the Canvas names it, read when the Patrol is. */
18
+ /** A report's subject, named as the Canvas names it, read when the Specialists is. */
19
19
  export type ReportSubject = {
20
20
  entity: ReportEntity;
21
21
  id: string;
@@ -44,10 +44,10 @@ export declare const reportLocale: (summary: {
44
44
  /** Whether the work was done, or failed. A failure shows in its report only. */
45
45
  export type ReportOutcome = "done" | "failed";
46
46
  /**
47
- * Where a patroller is on duty, in drafts or on Live: it works as you go, checks when you
48
- * publish, or is off there (ADR 0034).
47
+ * Where a specialist is on duty, in drafts or on Live: it works as you go, or is off there (ADR
48
+ * 0034). None checks when you publish: publishing never waits on Camox (ADR 0043).
49
49
  */
50
- export type PatrollerDuty = "asYouGo" | "atPublish" | "off";
50
+ export type SpecialistDuty = "asYouGo" | "off";
51
51
  /**
52
52
  * Where the studio shows a report's subject: a page on the Canvas, with the block and repeatable
53
53
  * item to select on it, a collection record, or a file.
@@ -66,7 +66,7 @@ export type ReportPlace = {
66
66
  fileId: string;
67
67
  };
68
68
  export type ReportView = {
69
- /** Unique among the patroller's reports in the view. */
69
+ /** Unique among the specialist's reports in the view. */
70
70
  id: string;
71
71
  summary: ReportSummary;
72
72
  outcome: ReportOutcome;
@@ -84,6 +84,7 @@ export type ReportView = {
84
84
  * What a finding is about (ADR 0034), by its kind:
85
85
  * - `missingPage`: a link to a page that doesn't exist, the page's name as it was last known.
86
86
  * - `brokenLink`: an external link that failed, and how.
87
+ * - `missingMetaTitle`: a page whose meta title is written by hand, and empty.
87
88
  * A link's `url` is as content stores it: a page link's is `camox:page:<id>`, and `text` is what
88
89
  * the link reads.
89
90
  */
@@ -97,6 +98,8 @@ export type FindingAbout = {
97
98
  url: string;
98
99
  text: string;
99
100
  failure: LinkFailure;
101
+ } | {
102
+ kind: "missingMetaTitle";
100
103
  };
101
104
  /** How a link failed: an HTTP error status, no connection (DNS included), or no answer in time. */
102
105
  export type LinkFailure = {
@@ -129,14 +132,17 @@ export type FindingView = {
129
132
  fieldKind: string | null;
130
133
  /** When it was first raised, in milliseconds since the epoch. */
131
134
  raisedAt: number;
132
- /** Whether it's Live's. Live's are fixed in the Patrol Draft. */
135
+ /**
136
+ * Whether it's Live's. A draft shows Live's findings on the content it still holds, and fixes
137
+ * them there.
138
+ */
133
139
  live: boolean;
134
140
  /** Where its content shows, as for reports. */
135
141
  place: ReportPlace | null;
136
142
  };
137
143
  /**
138
144
  * A finding as one sentence, as the studio, emails, Briefs and refusals word it: "“About us” in
139
- * Footer links to About, a page that no longer exists".
145
+ * Footer links to About, a page that no longer exists", or "Pricing has no meta title".
140
146
  */
141
147
  export declare function findingSentence(finding: Pick<FindingView, "about" | "subject">): string;
142
148
  /**
@@ -159,27 +165,27 @@ export type DismissalView = {
159
165
  export type ApplyResult = {
160
166
  applied: boolean;
161
167
  };
162
- /** How many subjects a patroller is on in one locale, a locale's tag. */
168
+ /** How many subjects a specialist is on in one locale, a locale's tag. */
163
169
  export type LocaleCount = {
164
170
  locale: string;
165
171
  count: number;
166
172
  };
167
173
  /**
168
- * What a patroller is on: the one subject when there's one, and how many subjects in each
174
+ * What a specialist is on: the one subject when there's one, and how many subjects in each
169
175
  * locale, the most first. A subject in several locales counts in each.
170
176
  */
171
- export type PatrollerWorking = {
177
+ export type SpecialistWorking = {
172
178
  subject: ReportSubject | null;
173
179
  locales: LocaleCount[];
174
180
  };
175
- export type PatrollerView = {
176
- id: PatrollerId;
181
+ export type SpecialistView = {
182
+ id: SpecialistId;
177
183
  /** Its role, as editors know it: "Translator", "SEO manager". */
178
184
  role: string;
179
185
  /** Its duty in the scope viewed. Off there, it still has its reports. */
180
- duty: PatrollerDuty;
186
+ duty: SpecialistDuty;
181
187
  /** Null when it isn't working in the scope. */
182
- working: PatrollerWorking | null;
188
+ working: SpecialistWorking | null;
183
189
  /**
184
190
  * When it last finished a check in the scope, whether it found anything or not, or null when it
185
191
  * never checked there.
@@ -202,17 +208,15 @@ export type PatrollerView = {
202
208
  /** The project's dismissals of its findings, the newest first. */
203
209
  dismissals: DismissalView[];
204
210
  };
211
+ /** Every specialist of the registry, the latest activity first; never-worked ones last. */
212
+ export type SpecialistsView = {
213
+ specialists: SpecialistView[];
214
+ };
205
215
  /**
206
- * Every patroller of the registry, the latest activity first; never-worked ones last. With the
207
- * project's open Patrol Draft, where Live's findings are fixed, if any.
216
+ * URL search param the studio opens a specialist's findings from, by its id, as the email about
217
+ * Live's new findings links to them. The studio drops it once opened.
208
218
  */
209
- export type PatrolView = {
210
- patrollers: PatrollerView[];
211
- patrolDraft: {
212
- id: string;
213
- name: string | null;
214
- } | null;
215
- };
216
- /** How many reports the Patrol shows of each patroller; the rest are counted. */
219
+ export declare const SPECIALIST_SEARCH_PARAM = "camox-specialist";
220
+ /** How many reports the Specialists shows of each specialist; the rest are counted. */
217
221
  export declare const REPORTS_SHOWN = 5;
218
222
  //#endregion
@@ -1,19 +1,19 @@
1
- //#region src/patrol.ts
1
+ //#region src/specialists.ts
2
2
  /**
3
- * The Patrol (ADR 0024): every patroller of a project, the work each did as reports, as the
3
+ * The Specialists (ADR 0024): every specialist of a project, the work each did as reports, as the
4
4
  * studio shows it at the top of the Agent Sidebar. The API reads it for one scope, a draft or
5
5
  * Live, and names each report's subject, so the studio needs no entity loaded to show it.
6
6
  */
7
- /** Every patroller's stable id. The registry in the API lists them all. */
8
- const PATROLLER_IDS = [
7
+ /** Every specialist's stable id. The registry in the API lists them all. */
8
+ const SPECIALIST_IDS = [
9
9
  "translator",
10
10
  "seoManager",
11
11
  "linkChecker"
12
12
  ];
13
13
  /** The locale a summary's work was in: a structured summary's, if any. A text summary has none. */
14
14
  const reportLocale = (summary) => summary.kind === "structured" ? summary.locale : null;
15
- /** What a finding is about, after where it is: "links to About, a page that no longer exists". */
16
- function aboutSentence(about) {
15
+ /** What a link finding is about, after where it is: "links to About, a page that no longer exists". */
16
+ function linkSentence(about) {
17
17
  switch (about.kind) {
18
18
  case "missingPage": return about.page === null ? "links to a page that no longer exists" : `links to ${about.page}, a page that no longer exists`;
19
19
  case "brokenLink": {
@@ -25,20 +25,29 @@ function aboutSentence(about) {
25
25
  }
26
26
  /**
27
27
  * A finding as one sentence, as the studio, emails, Briefs and refusals word it: "“About us” in
28
- * Footer links to About, a page that no longer exists".
28
+ * Footer links to About, a page that no longer exists", or "Pricing has no meta title".
29
29
  */
30
30
  function findingSentence(finding) {
31
- return `“${finding.about.text}” in ${finding.subject.name} ${aboutSentence(finding.about)}`;
31
+ const { about, subject } = finding;
32
+ if (about.kind === "missingMetaTitle") return `${subject.name} has no meta title`;
33
+ return `“${about.text}” in ${subject.name} ${linkSentence(about)}`;
32
34
  }
33
35
  /**
34
36
  * A finding as one sentence where its content is already shown, as the studio's sidebar shows it
35
37
  * by its field: "“About us” links to About, a page that no longer exists".
36
38
  */
37
39
  function findingSentenceInPlace(finding) {
38
- return `“${finding.about.text}” ${aboutSentence(finding.about)}`;
40
+ const { about } = finding;
41
+ if (about.kind === "missingMetaTitle") return "The page has no meta title";
42
+ return `“${about.text}” ${linkSentence(about)}`;
39
43
  }
40
- /** How many reports the Patrol shows of each patroller; the rest are counted. */
44
+ /**
45
+ * URL search param the studio opens a specialist's findings from, by its id, as the email about
46
+ * Live's new findings links to them. The studio drops it once opened.
47
+ */
48
+ const SPECIALIST_SEARCH_PARAM = "camox-specialist";
49
+ /** How many reports the Specialists shows of each specialist; the rest are counted. */
41
50
  const REPORTS_SHOWN = 5;
42
51
 
43
52
  //#endregion
44
- export { PATROLLER_IDS, REPORTS_SHOWN, findingSentence, findingSentenceInPlace, reportLocale };
53
+ export { REPORTS_SHOWN, SPECIALIST_IDS, SPECIALIST_SEARCH_PARAM, findingSentence, findingSentenceInPlace, reportLocale };
package/dist/threads.d.ts CHANGED
@@ -34,9 +34,8 @@ export declare const BUILD_STATUS_ENTRY = "camox.build-status";
34
34
  export declare const RECONCILE_ENTRY = "camox.reconcile";
35
35
  /**
36
36
  * The kind of the transcript entry opening a draft's thread a Live thread handed a request off
37
- * to: the Brief, which the model reads and editors see as from Camox, ahead of the editor's
38
- * messages. In a draft Camox opened, such as its Patrol Draft, Camox's own messages are Briefs
39
- * too, with their `operationId` as data, and start the agent's run, which acts for Camox.
37
+ * to: the Brief, which the model reads ahead of the editor's messages, and editors see collapsed
38
+ * after them, so the request reads on as they sent it.
40
39
  */
41
40
  export declare const BRIEF_ENTRY = "camox.brief";
42
41
  /**
@@ -48,8 +47,8 @@ export declare const DRAFT_ENDED_ENTRY = "camox.draft-ended";
48
47
  /**
49
48
  * The kind of the transcript entry a Live thread starts afresh from once its agent handed a
50
49
  * request off to a draft (ADR 0036): a reset of Pi's context, with a `startedDraftCardSchema` as
51
- * data. Editors see it as the draft's card, alone, and the model reads a note naming the draft.
52
- * Everything before it is left out of both.
50
+ * data. Editors see an empty thread, and the model reads a note naming the draft. Everything
51
+ * before it is left out of both.
53
52
  */
54
53
  export declare const DRAFT_CARD_ENTRY = "camox.draft-card";
55
54
  /**
@@ -109,6 +108,30 @@ export declare const codeRequestDataSchema: z.ZodObject<{
109
108
  reconciling: z.ZodOptional<z.ZodBoolean>;
110
109
  }, z.core.$strip>;
111
110
  export type CodeRequestData = z.infer<typeof codeRequestDataSchema>;
111
+ /**
112
+ * The draft thread's agent's tool asking the Connected Agents following its turn questions, which
113
+ * their waiting calls come back with as the agent works on (ADR 0042). The model calls it itself,
114
+ * never from a script.
115
+ */
116
+ export declare const ASK_TOOL = "askConnectedAgent";
117
+ /**
118
+ * The kind of the transcript entry recording questions the agent asked the Connected Agents
119
+ * following its turn, with a `questionsDataSchema` as data. Neither the model nor editors read
120
+ * it: questions are never a thread's messages, and never end its turn.
121
+ */
122
+ export declare const QUESTIONS_ENTRY = "camox.questions";
123
+ /**
124
+ * What a questions entry records: the questions, in the order the agent asked them, and the
125
+ * Connected Agents they were asked of, each by its member's id and client id.
126
+ */
127
+ export declare const questionsDataSchema: z.ZodObject<{
128
+ questions: z.ZodArray<z.ZodString>;
129
+ to: z.ZodArray<z.ZodObject<{
130
+ memberId: z.ZodString;
131
+ clientId: z.ZodString;
132
+ }, z.core.$strip>>;
133
+ }, z.core.$strip>;
134
+ export type QuestionsData = z.infer<typeof questionsDataSchema>;
112
135
  /** Whether `name` is a tool handing work to an agent of its own (`HANDING_OFF_TOOLS`). */
113
136
  export declare const handsOff: (name: string) => boolean;
114
137
  /**
@@ -168,8 +191,8 @@ export declare const connectedAgentClientSchema: z.ZodObject<{
168
191
  }, z.core.$strip>;
169
192
  export type ConnectedAgentClient = z.infer<typeof connectedAgentClientSchema>;
170
193
  /**
171
- * What a Connected Agent's message entry records: the member it acts as, its client, and the
172
- * operation id it was sent with.
194
+ * What a Connected Agent's message entry records: the member it acts as, its client, the
195
+ * operation id it was sent with, and whether it answers the agent's questions (ADR 0042).
173
196
  */
174
197
  export declare const connectedAgentMessageDataSchema: z.ZodObject<{
175
198
  member: z.ZodObject<{
@@ -182,6 +205,7 @@ export declare const connectedAgentMessageDataSchema: z.ZodObject<{
182
205
  verified: z.ZodBoolean;
183
206
  }, z.core.$strip>;
184
207
  operationId: z.ZodOptional<z.ZodString>;
208
+ answer: z.ZodOptional<z.ZodBoolean>;
185
209
  }, z.core.$strip>;
186
210
  export type ConnectedAgentMessageData = z.infer<typeof connectedAgentMessageDataSchema>;
187
211
  /** What a push's entry records: who pushed, their commits' subjects, oldest first, and the build. */
@@ -315,7 +339,9 @@ export type ThreadMessage = {
315
339
  } |
316
340
  /**
317
341
  * A member's Connected Agent's message: the member's own AI, in its client, writing as itself.
318
- * Never shown as the member's own words.
342
+ * Never shown as the member's own words. An answer to the agent's questions shows as the
343
+ * context the draft was built on, collapsed, as a Brief does, rather than as a request
344
+ * (ADR 0042).
319
345
  */
320
346
  {
321
347
  id: string;
@@ -323,6 +349,7 @@ export type ThreadMessage = {
323
349
  member: ThreadSender;
324
350
  client: ConnectedAgentClient;
325
351
  text: string;
352
+ answer: boolean;
326
353
  } |
327
354
  /** Camox's own message, starting a turn it began itself: why it did. */
328
355
  {
@@ -330,6 +357,15 @@ export type ThreadMessage = {
330
357
  from: "camox";
331
358
  text: string;
332
359
  } |
360
+ /**
361
+ * The Brief the agent on Live wrote as it handed the request off to the draft, shown after the
362
+ * editor's messages it opened the thread with, though the model reads it before them.
363
+ */
364
+ {
365
+ id: string;
366
+ from: "brief";
367
+ text: string;
368
+ } |
333
369
  /** The agent's final message of a turn, in Markdown. */
334
370
  {
335
371
  id: string;
@@ -465,11 +501,17 @@ type ThreadStep = {
465
501
  member: ThreadSender;
466
502
  client: ConnectedAgentClient;
467
503
  text: string;
504
+ answer: boolean;
468
505
  } |
469
506
  /** Camox starting a turn of its own, saying why. */
470
507
  {
471
508
  type: "camox";
472
509
  text: string;
510
+ } |
511
+ /** The Brief opening a draft's thread a Live thread handed a request off to. */
512
+ {
513
+ type: "brief";
514
+ text: string;
473
515
  } | {
474
516
  type: "answer";
475
517
  text: string;
package/dist/threads.js CHANGED
@@ -32,9 +32,8 @@ const BUILD_STATUS_ENTRY = "camox.build-status";
32
32
  const RECONCILE_ENTRY = "camox.reconcile";
33
33
  /**
34
34
  * The kind of the transcript entry opening a draft's thread a Live thread handed a request off
35
- * to: the Brief, which the model reads and editors see as from Camox, ahead of the editor's
36
- * messages. In a draft Camox opened, such as its Patrol Draft, Camox's own messages are Briefs
37
- * too, with their `operationId` as data, and start the agent's run, which acts for Camox.
35
+ * to: the Brief, which the model reads ahead of the editor's messages, and editors see collapsed
36
+ * after them, so the request reads on as they sent it.
38
37
  */
39
38
  const BRIEF_ENTRY = "camox.brief";
40
39
  /**
@@ -46,8 +45,8 @@ const DRAFT_ENDED_ENTRY = "camox.draft-ended";
46
45
  /**
47
46
  * The kind of the transcript entry a Live thread starts afresh from once its agent handed a
48
47
  * request off to a draft (ADR 0036): a reset of Pi's context, with a `startedDraftCardSchema` as
49
- * data. Editors see it as the draft's card, alone, and the model reads a note naming the draft.
50
- * Everything before it is left out of both.
48
+ * data. Editors see an empty thread, and the model reads a note naming the draft. Everything
49
+ * before it is left out of both.
51
50
  */
52
51
  const DRAFT_CARD_ENTRY = "camox.draft-card";
53
52
  /**
@@ -101,6 +100,29 @@ const CODE_REQUEST_ENTRY = "camox.code-request";
101
100
  /** What a Code Agent's request records: as an Artifact Agent's, and whether Camox reconciles. */
102
101
  const codeRequestDataSchema = artifactRequestDataSchema.extend({ reconciling: z.boolean().optional() });
103
102
  /**
103
+ * The draft thread's agent's tool asking the Connected Agents following its turn questions, which
104
+ * their waiting calls come back with as the agent works on (ADR 0042). The model calls it itself,
105
+ * never from a script.
106
+ */
107
+ const ASK_TOOL = "askConnectedAgent";
108
+ /**
109
+ * The kind of the transcript entry recording questions the agent asked the Connected Agents
110
+ * following its turn, with a `questionsDataSchema` as data. Neither the model nor editors read
111
+ * it: questions are never a thread's messages, and never end its turn.
112
+ */
113
+ const QUESTIONS_ENTRY = "camox.questions";
114
+ /**
115
+ * What a questions entry records: the questions, in the order the agent asked them, and the
116
+ * Connected Agents they were asked of, each by its member's id and client id.
117
+ */
118
+ const questionsDataSchema = z.object({
119
+ questions: z.array(z.string()).min(1),
120
+ to: z.array(z.object({
121
+ memberId: z.string(),
122
+ clientId: z.string()
123
+ }))
124
+ });
125
+ /**
104
126
  * The agent's tools handing work to an agent of its own, in a conversation beside the thread's,
105
127
  * whose answer they return: editors see what that agent does as the agent's.
106
128
  */
@@ -161,13 +183,14 @@ const connectedAgentClientSchema = z.object({
161
183
  verified: z.boolean()
162
184
  });
163
185
  /**
164
- * What a Connected Agent's message entry records: the member it acts as, its client, and the
165
- * operation id it was sent with.
186
+ * What a Connected Agent's message entry records: the member it acts as, its client, the
187
+ * operation id it was sent with, and whether it answers the agent's questions (ADR 0042).
166
188
  */
167
189
  const connectedAgentMessageDataSchema = z.object({
168
190
  member: threadSenderSchema,
169
191
  client: connectedAgentClientSchema,
170
- operationId: z.string().optional()
192
+ operationId: z.string().optional(),
193
+ answer: z.boolean().optional()
171
194
  });
172
195
  /** What a push's entry records: who pushed, their commits' subjects, oldest first, and the build. */
173
196
  const pushDataSchema = z.object({
@@ -375,14 +398,7 @@ function threadStepOf(entry) {
375
398
  ...push
376
399
  };
377
400
  }
378
- if (entry.kind === "camox.draft-card") {
379
- const card = startedDraftCardSchema.safeParse(entry.data).data;
380
- return card && {
381
- id,
382
- type: "draft",
383
- ...card
384
- };
385
- }
401
+ if (entry.kind === "camox.draft-card") return void 0;
386
402
  const message = entry.model?.find((candidate) => candidate.role !== "system");
387
403
  if (!message) return void 0;
388
404
  if (message.role === "user") {
@@ -402,12 +418,13 @@ function threadStepOf(entry) {
402
418
  name: data.client.name,
403
419
  verified: data.client.verified
404
420
  },
405
- text: editorTextOf(message.content)
421
+ text: editorTextOf(message.content),
422
+ answer: data.answer ?? false
406
423
  };
407
424
  }
408
425
  if (entry.kind === "camox.brief") return {
409
426
  id,
410
- type: "camox",
427
+ type: z.object({ operationId: z.string() }).safeParse(entry.data).success ? "camox" : "brief",
411
428
  text: textOf(message.content)
412
429
  };
413
430
  if (entry.kind === "camox.reconcile") {
@@ -474,101 +491,119 @@ function threadViewOf({ steps, running, toolCalls = [], callingTools = false, ch
474
491
  });
475
492
  endTurn();
476
493
  };
477
- for (const step of steps) switch (step.type) {
478
- case "editor":
479
- if (unfinished) fail();
480
- messages.push({
481
- id: step.id,
482
- from: "editor",
483
- sender: step.sender,
484
- text: step.text
485
- });
486
- waiting = step.id;
487
- break;
488
- case "connectedAgent":
489
- if (unfinished) fail();
490
- messages.push({
491
- id: step.id,
492
- from: "connectedAgent",
493
- member: step.member,
494
- client: step.client,
495
- text: step.text
496
- });
497
- waiting = step.id;
498
- break;
499
- case "camox":
500
- if (unfinished) fail();
501
- messages.push({
502
- id: step.id,
503
- from: "camox",
504
- text: step.text
505
- });
506
- waiting = step.id;
507
- break;
508
- case "stopped":
509
- if (waiting === void 0) break;
510
- messages.push({
511
- id: step.id,
512
- from: "stopped",
513
- sender: step.sender
514
- });
515
- endTurn();
516
- break;
517
- case "answer":
518
- if (waiting === void 0 && messages.at(-1)?.from === "stopped") break;
519
- messages.push({
520
- id: step.id,
521
- from: "agent",
522
- text: step.text
523
- });
524
- {
525
- const before = {
526
- waiting,
527
- status
494
+ /** A hand-off's Brief, shown once the editors' messages it opened the thread with are. */
495
+ let brief;
496
+ const showBrief = () => {
497
+ if (brief) messages.push(brief);
498
+ brief = void 0;
499
+ };
500
+ for (const step of steps) {
501
+ if (step.type !== "editor" && step.type !== "connectedAgent") showBrief();
502
+ switch (step.type) {
503
+ case "brief":
504
+ brief = {
505
+ id: step.id,
506
+ from: "brief",
507
+ text: step.text
528
508
  };
509
+ break;
510
+ case "editor":
511
+ if (unfinished) fail();
512
+ messages.push({
513
+ id: step.id,
514
+ from: "editor",
515
+ sender: step.sender,
516
+ text: step.text
517
+ });
518
+ waiting = step.id;
519
+ break;
520
+ case "connectedAgent":
521
+ if (unfinished) fail();
522
+ messages.push({
523
+ id: step.id,
524
+ from: "connectedAgent",
525
+ member: step.member,
526
+ client: step.client,
527
+ text: step.text,
528
+ answer: step.answer
529
+ });
530
+ waiting = step.id;
531
+ break;
532
+ case "camox":
533
+ if (unfinished) fail();
534
+ messages.push({
535
+ id: step.id,
536
+ from: "camox",
537
+ text: step.text
538
+ });
539
+ waiting = step.id;
540
+ break;
541
+ case "stopped":
542
+ if (waiting === void 0) break;
543
+ messages.push({
544
+ id: step.id,
545
+ from: "stopped",
546
+ sender: step.sender
547
+ });
529
548
  endTurn();
530
- answered = before;
531
- }
532
- break;
533
- case "draft":
534
- if (waiting === void 0 && messages.at(-1)?.from === "stopped") break;
535
- {
536
- const draft = drafts[step.draftId];
549
+ break;
550
+ case "answer":
551
+ if (waiting === void 0 && messages.at(-1)?.from === "stopped") break;
537
552
  messages.push({
538
553
  id: step.id,
539
- from: "draft",
540
- draftId: step.draftId,
541
- name: draft?.name ?? step.name,
542
- ...draft?.ended && { ended: draft.ended }
554
+ from: "agent",
555
+ text: step.text
543
556
  });
544
- }
545
- endTurn();
546
- break;
547
- case "continued":
548
- if (!answered) break;
549
- if (messages.at(-1)?.from === "agent") messages.pop();
550
- waiting = answered.waiting;
551
- status = answered.status === "fixing" ? "fixing" : void 0;
552
- answered = void 0;
553
- break;
554
- case "build":
555
- status = step.status;
556
- break;
557
- case "push":
558
- messages.push({
559
- id: step.id,
560
- from: "push",
561
- sender: step.pusher,
562
- subjects: step.subjects,
563
- outcome: step.outcome
564
- });
565
- break;
566
- case "tools":
567
- unfinished = false;
568
- status = void 0;
569
- break;
570
- case "unfinished": unfinished = true;
557
+ {
558
+ const before = {
559
+ waiting,
560
+ status
561
+ };
562
+ endTurn();
563
+ answered = before;
564
+ }
565
+ break;
566
+ case "draft":
567
+ if (waiting === void 0 && messages.at(-1)?.from === "stopped") break;
568
+ {
569
+ const draft = drafts[step.draftId];
570
+ messages.push({
571
+ id: step.id,
572
+ from: "draft",
573
+ draftId: step.draftId,
574
+ name: draft?.name ?? step.name,
575
+ ...draft?.ended && { ended: draft.ended }
576
+ });
577
+ }
578
+ endTurn();
579
+ break;
580
+ case "continued":
581
+ if (!answered) break;
582
+ if (messages.at(-1)?.from === "agent") messages.pop();
583
+ waiting = answered.waiting;
584
+ status = answered.status === "fixing" ? "fixing" : void 0;
585
+ answered = void 0;
586
+ break;
587
+ case "build":
588
+ status = step.status;
589
+ break;
590
+ case "push":
591
+ messages.push({
592
+ id: step.id,
593
+ from: "push",
594
+ sender: step.pusher,
595
+ subjects: step.subjects,
596
+ outcome: step.outcome
597
+ });
598
+ break;
599
+ case "tools":
600
+ unfinished = false;
601
+ status = void 0;
602
+ break;
603
+ case "unfinished": unfinished = true;
604
+ }
571
605
  }
606
+ showBrief();
572
607
  if (!running) fail();
573
608
  if (!running) return {
574
609
  messages,
@@ -607,7 +642,7 @@ const callsChangingTool = (block) => block.type === "toolCall" && changes(block.
607
642
  const callsLook = (block) => block.type === "toolCall" && block.name === "look";
608
643
  /**
609
644
  * Adds an entry to the thread's state as Pi places it. An entry heading a new context, such as
610
- * the card a Live thread starts afresh from, leaves out every step before its head, as Pi's
645
+ * the one a Live thread starts afresh from, leaves out every step before its head, as Pi's
611
646
  * snapshots do.
612
647
  */
613
648
  const append = (state, entry) => {
@@ -726,4 +761,4 @@ function reduceThreadFrame(state, frame) {
726
761
  }
727
762
 
728
763
  //#endregion
729
- export { ARTIFACT_REQUEST_ENTRY, ARTIFACT_TOOL, BRIEF_ENTRY, BUILD_STATUS_ENTRY, BUILD_TOOL, CHANGING_TOOLS, CODE_REQUEST_ENTRY, CODE_TOOL, CONNECTED_AGENT_MESSAGE_ENTRY, DRAFT_CARD_ENTRY, DRAFT_ENDED_ENTRY, EDITOR_MESSAGE_ENTRY, EMPTY_THREAD_STATE, EMPTY_THREAD_VIEW, LOOK_TOOL, PUSH_ENTRY, RECONCILE_ENTRY, RUN_STOPPED_ENTRY, START_DRAFT_TOOL, THREAD_ENDED_CLOSE_CODE, agentActivitySchema, artifactRequestDataSchema, buildStatusDataSchema, buildStatusSchema, codeRequestDataSchema, connectedAgentClientSchema, connectedAgentMessageDataSchema, editorMessageDataSchema, editorSelectionSchema, editorTextOf, editorWhereSchema, handOffDetailsSchema, handsOff, isSender, pushDataSchema, pushOutcomeSchema, reconcileDataSchema, reduceThreadEvents, reduceThreadFrame, reduceThreadState, startedDraftCardSchema, startedDraftSchema, textOf, threadClientMessageSchema, threadSenderSchema, threadViewOf, touchKindSchema, touchSchema, touchedBatchSchema };
764
+ export { ARTIFACT_REQUEST_ENTRY, ARTIFACT_TOOL, ASK_TOOL, BRIEF_ENTRY, BUILD_STATUS_ENTRY, BUILD_TOOL, CHANGING_TOOLS, CODE_REQUEST_ENTRY, CODE_TOOL, CONNECTED_AGENT_MESSAGE_ENTRY, DRAFT_CARD_ENTRY, DRAFT_ENDED_ENTRY, EDITOR_MESSAGE_ENTRY, EMPTY_THREAD_STATE, EMPTY_THREAD_VIEW, LOOK_TOOL, PUSH_ENTRY, QUESTIONS_ENTRY, RECONCILE_ENTRY, RUN_STOPPED_ENTRY, START_DRAFT_TOOL, THREAD_ENDED_CLOSE_CODE, agentActivitySchema, artifactRequestDataSchema, buildStatusDataSchema, buildStatusSchema, codeRequestDataSchema, connectedAgentClientSchema, connectedAgentMessageDataSchema, editorMessageDataSchema, editorSelectionSchema, editorTextOf, editorWhereSchema, handOffDetailsSchema, handsOff, isSender, pushDataSchema, pushOutcomeSchema, questionsDataSchema, reconcileDataSchema, reduceThreadEvents, reduceThreadFrame, reduceThreadState, startedDraftCardSchema, startedDraftSchema, textOf, threadClientMessageSchema, threadSenderSchema, threadViewOf, touchKindSchema, touchSchema, touchedBatchSchema };