@frockbot/plugin-shell 0.2.4 → 0.3.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/frockbot.json CHANGED
@@ -35,7 +35,6 @@
35
35
  "frockbot.right-panel",
36
36
  "frockbot.computer",
37
37
  "frockbot.sidebar-bots",
38
- "frockbot.sidebar-computer",
39
38
  "frockbot.sidebar-actions",
40
39
  "frockbot.user-profile",
41
40
  "frockbot.bot-actions",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frockbot/plugin-shell",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -46,39 +46,39 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@cordisjs/plugin-webui": "0.8.2",
49
- "@frockbot/agent-runtime": "0.2.4",
50
- "@frockbot/application-foundation": "0.2.4",
51
- "@frockbot/catalog-core": "0.2.4",
52
- "@frockbot/client-core": "0.2.4",
53
- "@frockbot/client-ui": "0.2.4",
54
- "@frockbot/computer-core": "0.2.4",
55
- "@frockbot/computer-host-protocol": "0.2.4",
56
- "@frockbot/configuration-core": "0.2.4",
57
- "@frockbot/connection-core": "0.2.4",
58
- "@frockbot/kernel-agent-loop": "0.2.4",
59
- "@frockbot/kernel-composition": "0.2.4",
60
- "@frockbot/kernel-contracts": "0.2.4",
61
- "@frockbot/kernel-do": "0.2.4",
62
- "@frockbot/machine-protocol": "0.2.4",
63
- "@frockbot/plugin-authoring": "0.2.4",
64
- "@frockbot/plugin-package-catalog": "0.2.4",
65
- "@frockbot/plugin-bot-template": "0.2.4",
66
- "@frockbot/plugin-flock": "0.2.4",
67
- "@frockbot/plugin-image": "0.2.4",
68
- "@frockbot/plugin-machine-messages": "0.2.4",
69
- "@frockbot/plugin-mcp": "0.2.4",
70
- "@frockbot/plugin-memory": "0.2.4",
71
- "@frockbot/plugin-routines": "0.2.4",
72
- "@frockbot/plugin-skills": "0.2.4",
73
- "@frockbot/plugin-subagents": "0.2.4",
74
- "@frockbot/plugin-user-machine": "0.2.4",
75
- "@frockbot/protocol": "0.2.4",
49
+ "@frockbot/agent-runtime": "0.3.0",
50
+ "@frockbot/application-foundation": "0.3.0",
51
+ "@frockbot/catalog-core": "0.3.0",
52
+ "@frockbot/client-core": "0.3.0",
53
+ "@frockbot/client-ui": "0.3.0",
54
+ "@frockbot/computer-core": "0.3.0",
55
+ "@frockbot/computer-host-protocol": "0.3.0",
56
+ "@frockbot/configuration-core": "0.3.0",
57
+ "@frockbot/connection-core": "0.3.0",
58
+ "@frockbot/kernel-agent-loop": "0.3.0",
59
+ "@frockbot/kernel-composition": "0.3.0",
60
+ "@frockbot/kernel-contracts": "0.3.0",
61
+ "@frockbot/kernel-do": "0.3.0",
62
+ "@frockbot/machine-protocol": "0.3.0",
63
+ "@frockbot/plugin-authoring": "0.3.0",
64
+ "@frockbot/plugin-package-catalog": "0.3.0",
65
+ "@frockbot/plugin-bot-template": "0.3.0",
66
+ "@frockbot/plugin-flock": "0.3.0",
67
+ "@frockbot/plugin-image": "0.3.0",
68
+ "@frockbot/plugin-machine-messages": "0.3.0",
69
+ "@frockbot/plugin-mcp": "0.3.0",
70
+ "@frockbot/plugin-memory": "0.3.0",
71
+ "@frockbot/plugin-routines": "0.3.0",
72
+ "@frockbot/plugin-skills": "0.3.0",
73
+ "@frockbot/plugin-subagents": "0.3.0",
74
+ "@frockbot/plugin-user-machine": "0.3.0",
75
+ "@frockbot/protocol": "0.3.0",
76
76
  "cordis": "4.0.0-rc.8",
77
77
  "vue": "3.5.41"
78
78
  },
79
79
  "devDependencies": {
80
80
  "@cloudflare/workers-types": "latest",
81
- "@frockbot/plugin-tools": "0.2.4",
81
+ "@frockbot/plugin-tools": "0.3.0",
82
82
  "@types/bun": "1.3.6",
83
83
  "@types/node": "26.2.0",
84
84
  "@vitejs/plugin-vue": "6.0.8",
package/src/backend.ts CHANGED
@@ -560,6 +560,16 @@ export interface ShellBotBackendHost {
560
560
  * Durable Object has no honest way to dispatch one.
561
561
  */
562
562
  subagents?: SubagentDurableBindingV1;
563
+ invalidateComputerProjectionFile?(
564
+ userId: string,
565
+ botId: string,
566
+ kind: "screenshots" | "doctor",
567
+ ): void;
568
+ /** Package deadlines composed into the Bot authority's one durable alarm. */
569
+ scheduledDeadlines?(transaction: DurableObjectTransaction): Promise<number[]>;
570
+ scheduledWorkInFlight?(): boolean;
571
+ deferScheduledWork?(transaction: DurableObjectTransaction): Promise<void>;
572
+ settleScheduledWork?(): Promise<void>;
563
573
  }
564
574
 
565
575
  /** The narrow storage seam the Bot's announcement log is written through. */
@@ -655,6 +665,11 @@ export class ShellBotBackendContribution {
655
665
  */
656
666
  private readonly tasks: TaskStore;
657
667
  private readonly subagentBinding: SubagentDurableBindingV1 | undefined;
668
+ private readonly invalidateComputerProjectionFile?: ShellBotBackendHost["invalidateComputerProjectionFile"];
669
+ private readonly hostScheduledDeadlines?: ShellBotBackendHost["scheduledDeadlines"];
670
+ private readonly hostScheduledWorkInFlight?: ShellBotBackendHost["scheduledWorkInFlight"];
671
+ private readonly hostDeferScheduledWork?: ShellBotBackendHost["deferScheduledWork"];
672
+ private readonly hostSettleScheduledWork?: ShellBotBackendHost["settleScheduledWork"];
658
673
 
659
674
  constructor(host: ShellBotBackendHost) {
660
675
  this.ctx = host.state;
@@ -663,6 +678,12 @@ export class ShellBotBackendContribution {
663
678
  host.compileApplication ?? compileFoundationApplication;
664
679
  this.lifecycleAdmission = host.assertLifecycleActive;
665
680
  this.outboundFetch = host.outboundFetch;
681
+ this.invalidateComputerProjectionFile =
682
+ host.invalidateComputerProjectionFile;
683
+ this.hostScheduledDeadlines = host.scheduledDeadlines;
684
+ this.hostScheduledWorkInFlight = host.scheduledWorkInFlight;
685
+ this.hostDeferScheduledWork = host.deferScheduledWork;
686
+ this.hostSettleScheduledWork = host.settleScheduledWork;
666
687
  const routines = createBotRoutines(
667
688
  host.state.storage,
668
689
  createBotRoutineHookMinter(
@@ -696,7 +717,8 @@ export class ShellBotBackendContribution {
696
717
  terminalRecords: (input) => this.terminalPackageRecords(input),
697
718
  scheduledDeadlines: (transaction) =>
698
719
  this.scheduledDeadlines(transaction),
699
- scheduledWorkInFlight: () => false,
720
+ scheduledWorkInFlight: () =>
721
+ this.hostScheduledWorkInFlight?.() ?? false,
700
722
  deferScheduledWork: (transaction) =>
701
723
  this.deferScheduledWork(transaction),
702
724
  settleScheduledWork: () => this.settleScheduledWork(),
@@ -2405,6 +2427,9 @@ export class ShellBotBackendContribution {
2405
2427
  // reconciles a child that never reported, and the child runs the Turn it
2406
2428
  // was handed on its next alarm rather than on a floating promise.
2407
2429
  ...(await this.subagentDeadlines(transaction)),
2430
+ ...(this.hostScheduledDeadlines
2431
+ ? await this.hostScheduledDeadlines(transaction)
2432
+ : []),
2408
2433
  ];
2409
2434
  }
2410
2435
 
@@ -2448,6 +2473,7 @@ export class ShellBotBackendContribution {
2448
2473
  // A Routine's deadline is a debt, so the scheduler holds it rather than
2449
2474
  // moving it while other durable work remains in flight.
2450
2475
  await this.routineScheduler.defer(transaction);
2476
+ await this.hostDeferScheduledWork?.(transaction);
2451
2477
  }
2452
2478
 
2453
2479
  private async settleScheduledWork(): Promise<void> {
@@ -2456,6 +2482,7 @@ export class ShellBotBackendContribution {
2456
2482
  await this.reconcileOverdueTasks();
2457
2483
  await this.expireDueApprovals();
2458
2484
  await this.replayPendingWakeNotifications();
2485
+ await this.hostSettleScheduledWork?.();
2459
2486
  // The alarm that woke this object has been consumed. Re-arm on whatever is
2460
2487
  // owed next, or a Routine that fired once would never fire again.
2461
2488
  await this.ctx.storage.transaction((transaction) =>
@@ -3865,6 +3892,21 @@ export class ShellBotBackendContribution {
3865
3892
  // Prompt assembly reads the Bot DO's Step 1 lease record
3866
3893
  // directly; passing storage wakes no Computer.
3867
3894
  computerControlRecords: this.ctx.storage,
3895
+ ...(this.invalidateComputerProjectionFile
3896
+ ? {
3897
+ computerProjectionFiles: {
3898
+ invalidate: (
3899
+ botId: string,
3900
+ kind: "screenshots" | "doctor",
3901
+ ) =>
3902
+ this.invalidateComputerProjectionFile?.(
3903
+ identity.userId,
3904
+ botId,
3905
+ kind,
3906
+ ),
3907
+ },
3908
+ }
3909
+ : {}),
3868
3910
  // A computerUse child is the holder of the User-wide lease its
3869
3911
  // parent acquired. Its guarded commands must name that same
3870
3912
  // durable task owner or the shared fence would refuse itself.
@@ -4090,6 +4132,13 @@ export class ShellBotBackendContribution {
4090
4132
  return this.authority.validateIdentity(identity);
4091
4133
  }
4092
4134
 
4135
+ /** Recompute the Bot authority's one alarm inside a Package write transaction. */
4136
+ async refreshScheduledWork(
4137
+ transaction: DurableObjectTransaction,
4138
+ ): Promise<void> {
4139
+ await this.authority.refreshRecoveryAlarm(transaction);
4140
+ }
4141
+
4093
4142
  async listNotifications(): Promise<BotNotificationIntent[]> {
4094
4143
  return this.authority.listNotifications();
4095
4144
  }
@@ -609,10 +609,6 @@ function handleComposerKeydown(event: KeyboardEvent): void {
609
609
  <div class="bot-list">
610
610
  <k-slot name="frockbot.sidebar-bots" />
611
611
  </div>
612
- <div class="sidebar-computer">
613
- <k-slot name="frockbot.sidebar-computer" />
614
- </div>
615
-
616
612
  <div class="sidebar-bottom">
617
613
  <k-slot name="frockbot.sidebar-actions" />
618
614
  <k-slot name="frockbot.user-profile" />
@@ -620,15 +620,19 @@ export function decodePluginCatalog(value: unknown): PluginCatalogItem[] {
620
620
  !isRecord(candidate) ||
621
621
  // A Package that declares no configuration is serialised without the
622
622
  // key (JSON drops an undefined field), so the key is owned but optional.
623
- !hasExactFields(
624
- candidate,
625
- Object.hasOwn(candidate, "configuration")
626
- ? ["id", "displayName", "version", "contributions", "configuration"]
627
- : ["id", "displayName", "version", "contributions"],
628
- ) ||
623
+ !hasExactFields(candidate, [
624
+ "id",
625
+ "displayName",
626
+ "version",
627
+ "contributions",
628
+ ...(Object.hasOwn(candidate, "configuration") ? ["configuration"] : []),
629
+ ...(Object.hasOwn(candidate, "platformOwned") ? ["platformOwned"] : []),
630
+ ]) ||
629
631
  typeof candidate.id !== "string" ||
630
632
  typeof candidate.displayName !== "string" ||
631
633
  typeof candidate.version !== "string" ||
634
+ (candidate.platformOwned !== undefined &&
635
+ typeof candidate.platformOwned !== "boolean") ||
632
636
  !Array.isArray(candidate.contributions) ||
633
637
  candidate.contributions.length > 5 ||
634
638
  new Set(candidate.contributions).size !==
@@ -702,6 +706,7 @@ export function decodePluginCatalog(value: unknown): PluginCatalogItem[] {
702
706
  ? candidate.displayName
703
707
  : candidate.id,
704
708
  version: candidate.version,
709
+ ...(candidate.platformOwned === true ? { platformOwned: true } : {}),
705
710
  capabilities: decodedCapabilities,
706
711
  connectionTypes: decodedConnections,
707
712
  settings,
@@ -104,12 +104,6 @@
104
104
  scrollbar-width: thin;
105
105
  }
106
106
 
107
- .sidebar-computer {
108
- flex: 0 0 auto;
109
- padding: 8px 2px 10px;
110
- border-top: 1px solid var(--frock-border);
111
- }
112
-
113
107
  .sidebar-bottom {
114
108
  display: grid;
115
109
  gap: 2px;
package/src/shared.ts CHANGED
@@ -117,6 +117,8 @@ export interface PluginCatalogItem {
117
117
  packageId: string;
118
118
  displayName: string;
119
119
  version: string;
120
+ /** Backend-derived manifest fact; platform infrastructure has no User toggle. */
121
+ platformOwned?: boolean;
120
122
  capabilities: Array<{
121
123
  id: string;
122
124
  kind: "model" | "tool" | "memory" | "notification" | "computer";