@camox/api-contract 0.74.1 → 0.75.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
@@ -4,6 +4,9 @@ import { AgentActivity, ConnectedAgentClient, ThreadSender, ThreadView } from "@
4
4
  import { PiHarness, PiHarnessOptions } from "agents/harness/pi";
5
5
  import { CapabilityStartContext, Lifecycle } from "agents/lifecycle";
6
6
  import { WebSockets } from "agents/websockets";
7
+ import "@earendil-works/pi-ai";
8
+ import "@earendil-works/pi-ai/models";
9
+ import "@earendil-works/pi-durable/tools";
7
10
  import { FileErrorCode } from "@earendil-works/pi-durable/env";
8
11
  import "camox/_internal/sdkBundleName";
9
12
  import "@camox/ai-tools";
@@ -38,6 +41,198 @@ declare class EdgeCachePurger extends DurableObject<Bindings> {
38
41
  //#region ../../apps/api/src/lib/edge-cache-purges.d.ts
39
42
  type EdgeCachePurgerNamespace = DurableObjectNamespace<EdgeCachePurger>;
40
43
  //#endregion
44
+ //#region ../../apps/api/src/domains/attachments/schema.d.ts
45
+ /**
46
+ * An Attachment (ADR 0044): an image a member's Connected Agent uploaded for Camox's agent to
47
+ * see with one of its messages. Its bytes are a blob in the files bucket, under their own
48
+ * `attachments/` key space, and its row is apart from files', so it never shows among the
49
+ * project's Files. It becomes a File only when the agent puts it on the website.
50
+ *
51
+ * An Attachment no message used yet lasts a day from `createdAt`. A used one lasts as long as any
52
+ * thread whose message used it (`attachmentUses`).
53
+ */
54
+ declare const attachments: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
55
+ name: "attachments";
56
+ schema: undefined;
57
+ columns: {
58
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
59
+ name: "id";
60
+ tableName: "attachments";
61
+ dataType: "string";
62
+ columnType: "SQLiteText";
63
+ data: string;
64
+ driverParam: string;
65
+ notNull: true;
66
+ hasDefault: false;
67
+ isPrimaryKey: true;
68
+ isAutoincrement: false;
69
+ hasRuntimeDefault: false;
70
+ enumValues: [string, ...string[]];
71
+ baseColumn: never;
72
+ identity: undefined;
73
+ generated: undefined;
74
+ }, {}, {
75
+ length: undefined;
76
+ }>;
77
+ projectId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
78
+ name: "project_id";
79
+ tableName: "attachments";
80
+ dataType: "number";
81
+ columnType: "SQLiteInteger";
82
+ data: number;
83
+ driverParam: number;
84
+ notNull: true;
85
+ hasDefault: false;
86
+ isPrimaryKey: false;
87
+ isAutoincrement: false;
88
+ hasRuntimeDefault: false;
89
+ enumValues: undefined;
90
+ baseColumn: never;
91
+ identity: undefined;
92
+ generated: undefined;
93
+ }, {}, {}>;
94
+ memberId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
95
+ name: "member_id";
96
+ tableName: "attachments";
97
+ dataType: "string";
98
+ columnType: "SQLiteText";
99
+ data: string;
100
+ driverParam: string;
101
+ notNull: true;
102
+ hasDefault: false;
103
+ isPrimaryKey: false;
104
+ isAutoincrement: false;
105
+ hasRuntimeDefault: false;
106
+ enumValues: [string, ...string[]];
107
+ baseColumn: never;
108
+ identity: undefined;
109
+ generated: undefined;
110
+ }, {}, {
111
+ length: number | undefined;
112
+ }>;
113
+ filename: import("drizzle-orm/sqlite-core").SQLiteColumn<{
114
+ name: "filename";
115
+ tableName: "attachments";
116
+ dataType: "string";
117
+ columnType: "SQLiteText";
118
+ data: string;
119
+ driverParam: string;
120
+ notNull: true;
121
+ hasDefault: false;
122
+ isPrimaryKey: false;
123
+ isAutoincrement: false;
124
+ hasRuntimeDefault: false;
125
+ enumValues: [string, ...string[]];
126
+ baseColumn: never;
127
+ identity: undefined;
128
+ generated: undefined;
129
+ }, {}, {
130
+ length: undefined;
131
+ }>;
132
+ mimeType: import("drizzle-orm/sqlite-core").SQLiteColumn<{
133
+ name: "mime_type";
134
+ tableName: "attachments";
135
+ dataType: "string";
136
+ columnType: "SQLiteText";
137
+ data: "image/jpeg" | "image/png" | "image/svg+xml" | "image/webp";
138
+ driverParam: string;
139
+ notNull: true;
140
+ hasDefault: false;
141
+ isPrimaryKey: false;
142
+ isAutoincrement: false;
143
+ hasRuntimeDefault: false;
144
+ enumValues: [string, ...string[]];
145
+ baseColumn: never;
146
+ identity: undefined;
147
+ generated: undefined;
148
+ }, {}, {
149
+ length: number | undefined;
150
+ $type: "image/jpeg" | "image/png" | "image/svg+xml" | "image/webp";
151
+ }>;
152
+ size: import("drizzle-orm/sqlite-core").SQLiteColumn<{
153
+ name: "size";
154
+ tableName: "attachments";
155
+ dataType: "number";
156
+ columnType: "SQLiteInteger";
157
+ data: number;
158
+ driverParam: number;
159
+ notNull: true;
160
+ hasDefault: false;
161
+ isPrimaryKey: false;
162
+ isAutoincrement: false;
163
+ hasRuntimeDefault: false;
164
+ enumValues: undefined;
165
+ baseColumn: never;
166
+ identity: undefined;
167
+ generated: undefined;
168
+ }, {}, {}>;
169
+ blobKey: import("drizzle-orm/sqlite-core").SQLiteColumn<{
170
+ name: "blob_key";
171
+ tableName: "attachments";
172
+ dataType: "string";
173
+ columnType: "SQLiteText";
174
+ data: string;
175
+ driverParam: string;
176
+ notNull: true;
177
+ hasDefault: false;
178
+ isPrimaryKey: false;
179
+ isAutoincrement: false;
180
+ hasRuntimeDefault: false;
181
+ enumValues: [string, ...string[]];
182
+ baseColumn: never;
183
+ identity: undefined;
184
+ generated: undefined;
185
+ }, {}, {
186
+ length: number | undefined;
187
+ }>;
188
+ url: import("drizzle-orm/sqlite-core").SQLiteColumn<{
189
+ name: "url";
190
+ tableName: "attachments";
191
+ dataType: "string";
192
+ columnType: "SQLiteText";
193
+ data: string;
194
+ driverParam: string;
195
+ notNull: true;
196
+ hasDefault: false;
197
+ isPrimaryKey: false;
198
+ isAutoincrement: false;
199
+ hasRuntimeDefault: false;
200
+ enumValues: [string, ...string[]];
201
+ baseColumn: never;
202
+ identity: undefined;
203
+ generated: undefined;
204
+ }, {}, {
205
+ length: undefined;
206
+ }>;
207
+ createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
208
+ name: "created_at";
209
+ tableName: "attachments";
210
+ dataType: "number";
211
+ columnType: "SQLiteInteger";
212
+ data: number;
213
+ driverParam: number;
214
+ notNull: true;
215
+ hasDefault: false;
216
+ isPrimaryKey: false;
217
+ isAutoincrement: false;
218
+ hasRuntimeDefault: false;
219
+ enumValues: undefined;
220
+ baseColumn: never;
221
+ identity: undefined;
222
+ generated: undefined;
223
+ }, {}, {}>;
224
+ };
225
+ dialect: 'sqlite';
226
+ }>;
227
+ type Attachment = typeof attachments.$inferSelect;
228
+ //#endregion
229
+ //#region ../../apps/api/src/domains/attachments/model-input.d.ts
230
+ /**
231
+ * An Attachment as a thread message carries it: what a model's label and the studio name it by,
232
+ * and where its bytes are.
233
+ */
234
+ type MessageAttachment = Pick<Attachment, "id" | "filename" | "mimeType" | "url" | "blobKey">;
235
+ //#endregion
41
236
  //#region ../../apps/api/src/domains/code/remote-env.d.ts
42
237
  /** The operations sent as they are: every argument but the context is plain data. */
43
238
  declare const SENT: ["absolutePath", "joinPath", "readTextFile", "readTextLines", "readBinaryFile", "writeFile", "appendFile", "truncateFile", "flushFile", "renameFile", "fileInfo", "listDir", "canonicalPath", "exists", "createDir", "remove"];
@@ -9543,13 +9738,15 @@ type OpeningSender = {
9543
9738
  };
9544
9739
  /**
9545
9740
  * A message a draft's thread opens with: its text, the operation id it was sent with, and who
9546
- * sent it. A Connected Agent's message may be its answer to the agent's questions (ADR 0042).
9741
+ * sent it. A Connected Agent's message may be its answer to the agent's questions (ADR 0042), and
9742
+ * may carry Attachments, images the model sees with it (ADR 0044).
9547
9743
  */
9548
9744
  type OpeningMessage = {
9549
9745
  operationId: string;
9550
9746
  text: string;
9551
9747
  from: OpeningSender;
9552
9748
  answer?: boolean;
9749
+ attachments?: MessageAttachment[];
9553
9750
  };
9554
9751
  /**
9555
9752
  * How the API opens a draft's thread with no studio connected (`Thread.open`): what it belongs
package/dist/threads.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { DraftOutcome } from "./drafts.js";
2
2
  import { z } from "zod";
3
- import { AgentEvent } from "@earendil-works/pi-durable";
4
3
  import { Message } from "@earendil-works/pi-ai";
4
+ import { AgentEvent } from "@earendil-works/pi-durable";
5
5
  //#region src/threads.d.ts
6
6
  /**
7
7
  * The kind of the transcript entry recording an editor's message, with its sender and the
@@ -190,6 +190,14 @@ export declare const connectedAgentClientSchema: z.ZodObject<{
190
190
  verified: z.ZodBoolean;
191
191
  }, z.core.$strip>;
192
192
  export type ConnectedAgentClient = z.infer<typeof connectedAgentClientSchema>;
193
+ /** An Attachment a Connected Agent's message carries: an image the agent sees with it. */
194
+ export declare const messageAttachmentSchema: z.ZodObject<{
195
+ id: z.ZodString;
196
+ filename: z.ZodString;
197
+ mimeType: z.ZodString;
198
+ url: z.ZodString;
199
+ }, z.core.$strip>;
200
+ export type MessageAttachmentData = z.infer<typeof messageAttachmentSchema>;
193
201
  /**
194
202
  * What a Connected Agent's message entry records: the member it acts as, its client, the
195
203
  * operation id it was sent with, and whether it answers the agent's questions (ADR 0042).
@@ -206,6 +214,12 @@ export declare const connectedAgentMessageDataSchema: z.ZodObject<{
206
214
  }, z.core.$strip>;
207
215
  operationId: z.ZodOptional<z.ZodString>;
208
216
  answer: z.ZodOptional<z.ZodBoolean>;
217
+ attachments: z.ZodOptional<z.ZodArray<z.ZodObject<{
218
+ id: z.ZodString;
219
+ filename: z.ZodString;
220
+ mimeType: z.ZodString;
221
+ url: z.ZodString;
222
+ }, z.core.$strip>>>;
209
223
  }, z.core.$strip>;
210
224
  export type ConnectedAgentMessageData = z.infer<typeof connectedAgentMessageDataSchema>;
211
225
  /** What a push's entry records: who pushed, their commits' subjects, oldest first, and the build. */
@@ -350,6 +364,8 @@ export type ThreadMessage = {
350
364
  client: ConnectedAgentClient;
351
365
  text: string;
352
366
  answer: boolean;
367
+ /** The images it carries for the agent to see, if any (ADR 0044). */
368
+ attachments?: MessageAttachmentData[];
353
369
  } |
354
370
  /** Camox's own message, starting a turn it began itself: why it did. */
355
371
  {
@@ -502,6 +518,7 @@ type ThreadStep = {
502
518
  client: ConnectedAgentClient;
503
519
  text: string;
504
520
  answer: boolean;
521
+ attachments?: MessageAttachmentData[];
505
522
  } |
506
523
  /** Camox starting a turn of its own, saying why. */
507
524
  {
package/dist/threads.js CHANGED
@@ -182,6 +182,13 @@ const connectedAgentClientSchema = z.object({
182
182
  name: z.string(),
183
183
  verified: z.boolean()
184
184
  });
185
+ /** An Attachment a Connected Agent's message carries: an image the agent sees with it. */
186
+ const messageAttachmentSchema = z.object({
187
+ id: z.string(),
188
+ filename: z.string(),
189
+ mimeType: z.string(),
190
+ url: z.string()
191
+ });
185
192
  /**
186
193
  * What a Connected Agent's message entry records: the member it acts as, its client, the
187
194
  * operation id it was sent with, and whether it answers the agent's questions (ADR 0042).
@@ -190,7 +197,9 @@ const connectedAgentMessageDataSchema = z.object({
190
197
  member: threadSenderSchema,
191
198
  client: connectedAgentClientSchema,
192
199
  operationId: z.string().optional(),
193
- answer: z.boolean().optional()
200
+ answer: z.boolean().optional(),
201
+ /** The images the message carries for the agent to see, as studios list them (ADR 0044). */
202
+ attachments: z.array(messageAttachmentSchema).optional()
194
203
  });
195
204
  /** What a push's entry records: who pushed, their commits' subjects, oldest first, and the build. */
196
205
  const pushDataSchema = z.object({
@@ -419,7 +428,8 @@ function threadStepOf(entry) {
419
428
  verified: data.client.verified
420
429
  },
421
430
  text: editorTextOf(message.content),
422
- answer: data.answer ?? false
431
+ answer: data.answer ?? false,
432
+ ...data.attachments?.length && { attachments: data.attachments }
423
433
  };
424
434
  }
425
435
  if (entry.kind === "camox.brief") return {
@@ -525,7 +535,8 @@ function threadViewOf({ steps, running, toolCalls = [], callingTools = false, ch
525
535
  member: step.member,
526
536
  client: step.client,
527
537
  text: step.text,
528
- answer: step.answer
538
+ answer: step.answer,
539
+ ...step.attachments && { attachments: step.attachments }
529
540
  });
530
541
  waiting = step.id;
531
542
  break;
@@ -761,4 +772,4 @@ function reduceThreadFrame(state, frame) {
761
772
  }
762
773
 
763
774
  //#endregion
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 };
775
+ 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, messageAttachmentSchema, pushDataSchema, pushOutcomeSchema, questionsDataSchema, reconcileDataSchema, reduceThreadEvents, reduceThreadFrame, reduceThreadState, startedDraftCardSchema, startedDraftSchema, textOf, threadClientMessageSchema, threadSenderSchema, threadViewOf, touchKindSchema, touchSchema, touchedBatchSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camox/api-contract",
3
- "version": "0.74.1",
3
+ "version": "0.75.0",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "src",
package/src/threads.ts CHANGED
@@ -232,6 +232,15 @@ export const isSender = (data: unknown): data is ThreadSender =>
232
232
  export const connectedAgentClientSchema = z.object({ name: z.string(), verified: z.boolean() });
233
233
  export type ConnectedAgentClient = z.infer<typeof connectedAgentClientSchema>;
234
234
 
235
+ /** An Attachment a Connected Agent's message carries: an image the agent sees with it. */
236
+ export const messageAttachmentSchema = z.object({
237
+ id: z.string(),
238
+ filename: z.string(),
239
+ mimeType: z.string(),
240
+ url: z.string(),
241
+ });
242
+ export type MessageAttachmentData = z.infer<typeof messageAttachmentSchema>;
243
+
235
244
  /**
236
245
  * What a Connected Agent's message entry records: the member it acts as, its client, the
237
246
  * operation id it was sent with, and whether it answers the agent's questions (ADR 0042).
@@ -241,6 +250,8 @@ export const connectedAgentMessageDataSchema = z.object({
241
250
  client: connectedAgentClientSchema,
242
251
  operationId: z.string().optional(),
243
252
  answer: z.boolean().optional(),
253
+ /** The images the message carries for the agent to see, as studios list them (ADR 0044). */
254
+ attachments: z.array(messageAttachmentSchema).optional(),
244
255
  });
245
256
  export type ConnectedAgentMessageData = z.infer<typeof connectedAgentMessageDataSchema>;
246
257
 
@@ -326,6 +337,8 @@ export type ThreadMessage =
326
337
  client: ConnectedAgentClient;
327
338
  text: string;
328
339
  answer: boolean;
340
+ /** The images it carries for the agent to see, if any (ADR 0044). */
341
+ attachments?: MessageAttachmentData[];
329
342
  }
330
343
  /** Camox's own message, starting a turn it began itself: why it did. */
331
344
  | { id: string; from: "camox"; text: string }
@@ -441,6 +454,7 @@ type ThreadStep = { id: string } & (
441
454
  client: ConnectedAgentClient;
442
455
  text: string;
443
456
  answer: boolean;
457
+ attachments?: MessageAttachmentData[];
444
458
  }
445
459
  /** Camox starting a turn of its own, saying why. */
446
460
  | { type: "camox"; text: string }
@@ -618,6 +632,7 @@ function threadStepOf(entry: EntryRecord): ThreadStep | undefined {
618
632
  client: { name: data.client.name, verified: data.client.verified },
619
633
  text: editorTextOf(message.content),
620
634
  answer: data.answer ?? false,
635
+ ...(data.attachments?.length && { attachments: data.attachments }),
621
636
  }
622
637
  );
623
638
  }
@@ -722,6 +737,7 @@ export function threadViewOf({
722
737
  client: step.client,
723
738
  text: step.text,
724
739
  answer: step.answer,
740
+ ...(step.attachments && { attachments: step.attachments }),
725
741
  });
726
742
  waiting = step.id;
727
743
  break;