@camox/api-contract 0.63.0 → 0.65.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.
package/src/threads.ts CHANGED
@@ -45,7 +45,8 @@ export const RECONCILE_ENTRY = "camox.reconcile";
45
45
  /**
46
46
  * The kind of the transcript entry opening a draft's thread a Live thread handed a request off
47
47
  * to: the Brief, which the model reads and editors see as from Camox, ahead of the editor's
48
- * messages.
48
+ * messages. In a draft Camox opened, such as its Patrol Draft, Camox's own messages are Briefs
49
+ * too, with their `operationId` as data, and start the agent's run, which acts for Camox.
49
50
  */
50
51
  export const BRIEF_ENTRY = "camox.brief";
51
52
 
@@ -76,6 +77,9 @@ export const START_DRAFT_TOOL = "startDraft";
76
77
  /** The agent's tool building its code changes mid-turn, which the end of a turn also does. */
77
78
  export const BUILD_TOOL = "build";
78
79
 
80
+ /** The agent's tool rendering the draft in a browser and returning screenshots to the model. */
81
+ export const LOOK_TOOL = "look";
82
+
79
83
  /**
80
84
  * The tools whose calls change a draft: the content tools that write, and the code tools that
81
85
  * write files. The model calls the code tools, and code mode scripts call both. A test in the API
@@ -85,6 +89,7 @@ export const CHANGING_TOOLS: ReadonlySet<string> = new Set([
85
89
  // Content
86
90
  "addBackToLocale",
87
91
  "addLocale",
92
+ "applyFindingFix",
88
93
  "createBlock",
89
94
  "createCollectionRecord",
90
95
  "createPage",
@@ -274,6 +279,8 @@ export type ThreadMessage =
274
279
  * - `changing`: a call of that round changes the draft (`CHANGING_TOOLS`), as soon as it's written
275
280
  * or, in a code mode script, as soon as the script calls one.
276
281
  * - `building`: its `build` call runs, or the end of the turn builds its code changes.
282
+ * - `checking`: it looks at what it designed, from writing a `look` call until the model is
283
+ * called again.
277
284
  * - `fixing`: the end of the turn's build failed, and the agent fixes it.
278
285
  * - `startingDraft`: on Live, its `startDraft` call runs.
279
286
  */
@@ -282,6 +289,7 @@ export type AgentActivity =
282
289
  | "exploring"
283
290
  | "changing"
284
291
  | "building"
292
+ | "checking"
285
293
  | "fixing"
286
294
  | "startingDraft";
287
295
 
@@ -313,6 +321,8 @@ export type ThreadState = {
313
321
  * or making it until the model is called again.
314
322
  */
315
323
  changing?: boolean;
324
+ /** Whether the model's latest round calls `look`: from writing the call until it's called again. */
325
+ checking?: boolean;
316
326
  /** The drafts the thread's cards name, as the thread last looked them up. */
317
327
  drafts?: DraftCardStates;
318
328
  };
@@ -547,6 +557,7 @@ export function threadViewOf({
547
557
  toolCalls = [],
548
558
  callingTools = false,
549
559
  changing = false,
560
+ checking = false,
550
561
  drafts = {},
551
562
  }: ThreadState): ThreadView {
552
563
  const messages: ThreadMessage[] = [];
@@ -680,7 +691,7 @@ export function threadViewOf({
680
691
  return {
681
692
  messages,
682
693
  running,
683
- activity: activityOf({ status, toolCalls, callingTools, changing }),
694
+ activity: activityOf({ status, toolCalls, callingTools, changing, checking }),
684
695
  };
685
696
  }
686
697
 
@@ -690,16 +701,19 @@ function activityOf({
690
701
  toolCalls,
691
702
  callingTools,
692
703
  changing,
704
+ checking,
693
705
  }: {
694
706
  status: BuildStatus | undefined;
695
707
  toolCalls: NonNullable<ThreadState["toolCalls"]>;
696
708
  callingTools: boolean;
697
709
  changing: boolean;
710
+ checking: boolean;
698
711
  }): AgentActivity {
699
712
  const calling = (name: string) => toolCalls.some((call) => call.name === name);
700
713
  // Fixing a build error takes thinking, reading and writing, which all read as fixing, but its
701
714
  // builds show as building.
702
715
  if (status === "building" || calling(BUILD_TOOL)) return "building";
716
+ if (checking) return "checking";
703
717
  if (status === "fixing") return "fixing";
704
718
  if (calling(START_DRAFT_TOOL)) return "startingDraft";
705
719
  if (changing) return "changing";
@@ -714,6 +728,10 @@ const changes = (name: string) => CHANGING_TOOLS.has(name);
714
728
  const callsChangingTool = (block: AssistantMessage["content"][number]) =>
715
729
  block.type === "toolCall" && changes(block.name);
716
730
 
731
+ /** Whether a block of the model's message is a call of `look`. */
732
+ const callsLook = (block: AssistantMessage["content"][number]) =>
733
+ block.type === "toolCall" && block.name === LOOK_TOOL;
734
+
717
735
  const append = (state: ThreadState, entry: EntryRecord | undefined): ThreadState => {
718
736
  const step = entry && threadStepOf(entry);
719
737
  if (!step || state.steps.some((known) => known.id === step.id)) return state;
@@ -734,6 +752,7 @@ export function reduceThreadState(state: ThreadState, event: AgentEvent): Thread
734
752
  running: event.run !== undefined,
735
753
  toolCalls,
736
754
  callingTools: generated.some((part) => part.type === "toolCall"),
755
+ checking: generated.some(callsLook) || toolCalls.some((call) => call.name === LOOK_TOOL),
737
756
  // A script's calls count while the script runs, finished or not.
738
757
  changing:
739
758
  generated.some(callsChangingTool) ||
@@ -752,11 +771,18 @@ export function reduceThreadState(state: ThreadState, event: AgentEvent): Thread
752
771
  case "run_start":
753
772
  return { ...state, running: true };
754
773
  case "run_end":
755
- return { ...state, running: false, toolCalls: [], callingTools: false, changing: false };
774
+ return {
775
+ ...state,
776
+ running: false,
777
+ toolCalls: [],
778
+ callingTools: false,
779
+ changing: false,
780
+ checking: false,
781
+ };
756
782
  case "message_start":
757
783
  // The model is called again: it thinks until it writes a tool call.
758
784
  return event.message.role === "assistant"
759
- ? { ...state, callingTools: false, changing: false }
785
+ ? { ...state, callingTools: false, changing: false, checking: false }
760
786
  : state;
761
787
  case "message_update": {
762
788
  // A call's name may come with its start, a later change to its block, or the whole message.
@@ -772,6 +798,7 @@ export function reduceThreadState(state: ThreadState, event: AgentEvent): Thread
772
798
  ...state,
773
799
  callingTools: state.callingTools || calls.some((block) => block.type === "toolCall"),
774
800
  changing: state.changing || calls.some(callsChangingTool),
801
+ checking: state.checking || calls.some(callsLook),
775
802
  };
776
803
  }
777
804
  case "tool_execution_start": {
@@ -780,6 +807,7 @@ export function reduceThreadState(state: ThreadState, event: AgentEvent): Thread
780
807
  return {
781
808
  ...state,
782
809
  changing,
810
+ checking: state.checking || event.toolName === LOOK_TOOL,
783
811
  toolCalls: [...(state.toolCalls ?? []), { callId: event.toolCallId, name: event.toolName }],
784
812
  };
785
813
  }