@frockbot/cloudflare 0.7.295 → 0.7.296

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frockbot/cloudflare",
3
- "version": "0.7.295",
3
+ "version": "0.7.296",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,12 +23,12 @@
23
23
  "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.access.json && tsc --noEmit -p test/tsconfig.json && tsc --noEmit -p e2e/tsconfig.json"
24
24
  },
25
25
  "dependencies": {
26
- "@frockbot/app": "0.7.295",
27
- "@frockbot/applets": "0.7.295",
28
- "@frockbot/computer": "0.7.295",
29
- "@frockbot/core": "0.7.295",
30
- "@frockbot/frock-compose": "0.7.295",
31
- "@frockbot/providers": "0.7.295",
26
+ "@frockbot/app": "0.7.296",
27
+ "@frockbot/applets": "0.7.296",
28
+ "@frockbot/computer": "0.7.296",
29
+ "@frockbot/core": "0.7.296",
30
+ "@frockbot/frock-compose": "0.7.296",
31
+ "@frockbot/providers": "0.7.296",
32
32
  "@rive-app/flutter-native-wasm": "44.0.0",
33
33
  "agents": "0.24.0",
34
34
  "ai": "^7.0.107",
package/src/bot-state.ts CHANGED
@@ -231,6 +231,7 @@ import {
231
231
  type ClientRunLookupQueryV1,
232
232
  type ClientRunStopCommandV1,
233
233
  } from "@frockbot/app/shell/run-protocol";
234
+ import { decodeWorkLogQueryV1 } from "@frockbot/app/shell/work-log";
234
235
  import {
235
236
  decodeBotUnreadCommandV1,
236
237
  type BotUnreadCommandV1,
@@ -3806,6 +3807,22 @@ export class BotState
3806
3807
  return shell.listRuns(request.query as ClientRunListQueryV1);
3807
3808
  }
3808
3809
 
3810
+ /** The Work log: a page of this Bot's Turns, every step of each. */
3811
+ async workLog(input: unknown) {
3812
+ const request = decodeRpcEnvelopeV1(input, {
3813
+ userId: rpcIdentifier,
3814
+ botId: rpcBotId,
3815
+ query: rpcDecoded(decodeWorkLogQueryV1),
3816
+ });
3817
+ const identity = {
3818
+ userId: request.userId as string,
3819
+ botId: request.botId as string,
3820
+ };
3821
+ const { shell } = await this.materialized(identity);
3822
+ await shell.validateIdentity(identity);
3823
+ return shell.workLog(request.query);
3824
+ }
3825
+
3809
3826
  /**
3810
3827
  * The operator snapshot behind `/api/debug`. Bot-scoped like every other
3811
3828
  * Bot RPC — the debug token authorizes the *caller*, it does not widen what
package/src/contracts.ts CHANGED
@@ -20,6 +20,7 @@ import type {
20
20
  SettingsFrame,
21
21
  ConnectionsFrame,
22
22
  SettingsChangeCommand,
23
+ WorkLogPage,
23
24
  } from "@frockbot/core/protocol-schemas";
24
25
  import {
25
26
  type AuthPackageV1,
@@ -28,6 +29,7 @@ import {
28
29
  type SessionEvent,
29
30
  } from "@frockbot/core/contracts";
30
31
  import type { MachineResultDeliveryV1 } from "@frockbot/app/machine/delivery";
32
+ import type { WorkLogQueryV1 } from "@frockbot/app/shell/work-log";
31
33
  import type { DebugGatewaySurface } from "./debug.js";
32
34
  import type { BotTurnCommandRequestV1 } from "./durable-rpc.js";
33
35
  import type {
@@ -275,6 +277,12 @@ export interface UserBotStateBinding {
275
277
  botId: string;
276
278
  query: ClientRunListQueryV1;
277
279
  }): Promise<ClientRunListV1>;
280
+ /** Everything the Bot did, a page of Turns at a time. */
281
+ workLog(input: {
282
+ schemaVersion: 1;
283
+ botId: string;
284
+ query: WorkLogQueryV1;
285
+ }): Promise<WorkLogPage>;
278
286
  lookupRun(input: {
279
287
  schemaVersion: 1;
280
288
  botId: string;
package/src/index.ts CHANGED
@@ -59,6 +59,11 @@ import {
59
59
  type ClientRunStopCommandV1,
60
60
  type ClientRunStopReceiptV1,
61
61
  } from "@frockbot/app/shell/run-protocol";
62
+ import {
63
+ decodeWorkLogQueryV1,
64
+ type WorkLogQueryV1,
65
+ } from "@frockbot/app/shell/work-log";
66
+ import type { WorkLogPage } from "@frockbot/core/protocol-schemas";
62
67
  import {
63
68
  decodeBotNotificationDirectoryViewV1,
64
69
  decodeBotUnreadDirectoryViewV1,
@@ -504,6 +509,7 @@ interface BotStateRpc extends BotConfigurationBinding {
504
509
  command: BotTurnCommandRequestV1<OwnedBotTurnCommand>,
505
510
  ): Promise<{ schemaVersion: 1; runId: string }>;
506
511
  listRuns(query: ClientRunListQueryV1): Promise<ClientRunListV1>;
512
+ workLog(query: WorkLogQueryV1): Promise<WorkLogPage>;
507
513
  debugSnapshot(query: BotDebugQueryV1): Promise<unknown>;
508
514
  lookupRun(query: ClientRunLookupQueryV1): Promise<ClientRunLookupV1>;
509
515
  runQuestions(query: ClientRunLookupQueryV1): Promise<ClientRunQuestionsV1>;
@@ -691,6 +697,7 @@ function botStateStub(env: Env, userId: string, botId: string): BotStateRpc {
691
697
  admitRun: (command) => rpc.admitRun(botTurnRpcV1(command)),
692
698
  listRuns: (query) =>
693
699
  rpc.listRuns({ schemaVersion: 1, userId, botId, query }),
700
+ workLog: (query) => rpc.workLog({ schemaVersion: 1, userId, botId, query }),
694
701
  debugSnapshot: (query) =>
695
702
  rpc.debugSnapshot({ schemaVersion: 1, userId, botId, query }),
696
703
  lookupRun: (query) =>
@@ -1296,6 +1303,18 @@ export class UserBotState extends WorkerEntrypoint<Env, UserScopedProps> {
1296
1303
  ).listRuns(request.query as ClientRunListQueryV1);
1297
1304
  }
1298
1305
 
1306
+ async workLog(input: unknown): Promise<WorkLogPage> {
1307
+ const request = decodeRpcEnvelopeV1(input, {
1308
+ botId: rpcBotId,
1309
+ query: rpcDecoded(decodeWorkLogQueryV1),
1310
+ });
1311
+ return botStateStub(
1312
+ this.env,
1313
+ this.ctx.props.userId,
1314
+ request.botId as string,
1315
+ ).workLog(request.query as WorkLogQueryV1);
1316
+ }
1317
+
1299
1318
  async lookupRun(input: unknown): Promise<ClientRunLookupV1> {
1300
1319
  const request = decodeUserBotRunLookupRpcV1(input);
1301
1320
  return botStateStub(
@@ -29,6 +29,10 @@ import {
29
29
  type ClientTurnRefusalV1,
30
30
  } from "@frockbot/app/shell/run-protocol";
31
31
  import { decodeApprovalDecisionCommandV1 } from "@frockbot/app/shell/approvals";
32
+ import {
33
+ decodeWorkLogQueryV1,
34
+ type WorkLogQueryV1,
35
+ } from "@frockbot/app/shell/work-log";
32
36
  import {
33
37
  decodeSecretSubmitCommandV1,
34
38
  isSecretRequestIdV1,
@@ -726,6 +730,7 @@ function createUserApplicationRoute() {
726
730
  }
727
731
 
728
732
  const skillsMatch = url.pathname.match(/^\/api\/bots\/([^/]+)\/skills$/);
733
+ const workLogMatch = url.pathname.match(/^\/api\/bots\/([^/]+)\/work-log$/);
729
734
  const workspaceFileMatch = url.pathname.match(
730
735
  /^\/api\/bots\/([^/]+)\/workspace\/file$/,
731
736
  );
@@ -744,6 +749,7 @@ function createUserApplicationRoute() {
744
749
  );
745
750
  if (
746
751
  !skillsMatch &&
752
+ !workLogMatch &&
747
753
  !workspaceFileMatch &&
748
754
  !turnMatch &&
749
755
  !lookupMatch &&
@@ -757,6 +763,7 @@ function createUserApplicationRoute() {
757
763
  try {
758
764
  const matched =
759
765
  skillsMatch ??
766
+ workLogMatch ??
760
767
  workspaceFileMatch ??
761
768
  turnMatch ??
762
769
  lookupMatch ??
@@ -776,7 +783,7 @@ function createUserApplicationRoute() {
776
783
  env,
777
784
  botId,
778
785
  request.method === "GET" &&
779
- Boolean(turnMatch || lookupMatch || questionsMatch),
786
+ Boolean(turnMatch || lookupMatch || questionsMatch || workLogMatch),
780
787
  );
781
788
  if (missingBot) return missingBot;
782
789
  // An installed client older than protocol 3 refuses a Run it does not
@@ -800,6 +807,37 @@ function createUserApplicationRoute() {
800
807
  }
801
808
  }
802
809
 
810
+ if (workLogMatch) {
811
+ if (request.method !== "GET") return jsonError(405, "method not allowed");
812
+ let query: WorkLogQueryV1;
813
+ try {
814
+ const keys = [...url.searchParams.keys()];
815
+ if (
816
+ keys.some((key) => key !== "before") ||
817
+ url.searchParams.getAll("before").length > 1
818
+ ) {
819
+ throw new Error("work log query is invalid");
820
+ }
821
+ const before = url.searchParams.get("before");
822
+ query = decodeWorkLogQueryV1({
823
+ schemaVersion: 1,
824
+ ...(before === null ? {} : { before }),
825
+ });
826
+ } catch (error) {
827
+ return jsonError(
828
+ 400,
829
+ error instanceof Error ? error.message : "invalid work log page",
830
+ );
831
+ }
832
+ try {
833
+ return Response.json(
834
+ await env.BOT_STATE.workLog({ schemaVersion: 1, botId, query }),
835
+ );
836
+ } catch (error) {
837
+ return botFailure(error, "work log failed");
838
+ }
839
+ }
840
+
803
841
  if (workspaceFileMatch) {
804
842
  // Read-only, and the durable root and path arrive as one encoded
805
843
  // `WorkspacePathV1` so the route cannot assemble a root the decoder