Skip to content

Commit 47faa60

Browse files
rekmarksclaude
andcommitted
feat(extension): Add CapTP E() support for calling vat methods
- Import and initialize makeBackgroundKref to enable E() calls on vat objects - Expose captp.resolveKref and captp.krefOf on globalThis for console access - Refactor startDefaultSubcluster to return the bootstrap vat rootKref - Add greetBootstrapVat function that automatically calls hello() on the bootstrap vat after subcluster launch on startup - Update global.d.ts with captp type declaration for IDE support Co-Authored-By: Claude <[email protected]>
1 parent e16b112 commit 47faa60

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

packages/extension/src/background.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { E } from '@endo/eventual-send';
22
import {
33
makeBackgroundCapTP,
4+
makeBackgroundKref,
45
makeCapTPNotification,
56
isCapTPNotification,
67
getCapTPMessage,
@@ -116,6 +117,10 @@ async function main(): Promise<void> {
116117
logger.info(result);
117118
};
118119

120+
// Create background kref system for E() calls on vat objects
121+
const bgKref = makeBackgroundKref({ kernelFacade: kernelP });
122+
Object.assign(globalThis.captp, bgKref);
123+
119124
// Handle incoming CapTP messages from the kernel
120125
const drainPromise = offscreenStream.drain((message) => {
121126
if (isCapTPNotification(message)) {
@@ -128,7 +133,10 @@ async function main(): Promise<void> {
128133
drainPromise.catch(logger.error);
129134

130135
await ping(); // Wait for the kernel to be ready
131-
await startDefaultSubcluster(kernelP);
136+
const rootKref = await startDefaultSubcluster(kernelP);
137+
if (rootKref) {
138+
await greetBootstrapVat(rootKref);
139+
}
132140

133141
try {
134142
await drainPromise;
@@ -145,18 +153,33 @@ async function main(): Promise<void> {
145153
* Idempotently starts the default subcluster.
146154
*
147155
* @param kernelPromise - Promise for the kernel facade.
156+
* @returns The rootKref of the bootstrap vat if launched, undefined if subcluster already exists.
148157
*/
149158
async function startDefaultSubcluster(
150159
kernelPromise: Promise<KernelFacade>,
151-
): Promise<void> {
160+
): Promise<string | undefined> {
152161
const status = await E(kernelPromise).getStatus();
153162

154163
if (status.subclusters.length === 0) {
155164
const result = await E(kernelPromise).launchSubcluster(defaultSubcluster);
156165
logger.info(`Default subcluster launched: ${JSON.stringify(result)}`);
157-
} else {
158-
logger.info('Subclusters already exist. Not launching default subcluster.');
166+
return result.rootKref;
159167
}
168+
logger.info('Subclusters already exist. Not launching default subcluster.');
169+
return undefined;
170+
}
171+
172+
/**
173+
* Greets the bootstrap vat by calling its hello() method.
174+
*
175+
* @param rootKref - The kref of the bootstrap vat's root object.
176+
*/
177+
async function greetBootstrapVat(rootKref: string): Promise<void> {
178+
const rootPresence = captp.resolveKref(rootKref) as {
179+
hello: (from: string) => string;
180+
};
181+
const greeting = await E(rootPresence).hello('background');
182+
logger.info(`Got greeting from bootstrap vat: ${greeting}`);
160183
}
161184

162185
/**
@@ -178,7 +201,13 @@ function defineGlobals(): void {
178201
value: async () => kernelP,
179202
},
180203
});
181-
harden(globalThis.kernel);
204+
205+
Object.defineProperty(globalThis, 'captp', {
206+
configurable: false,
207+
enumerable: true,
208+
writable: false,
209+
value: {},
210+
});
182211

183212
Object.defineProperty(globalThis, 'E', {
184213
value: E,

packages/extension/src/global.d.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import type { KernelFacade } from '@metamask/kernel-browser-runtime';
1+
import type {
2+
BackgroundKref,
3+
KernelFacade,
4+
} from '@metamask/kernel-browser-runtime';
25

36
// Type declarations for kernel dev console API.
47
declare global {
@@ -17,6 +20,18 @@ declare global {
1720

1821
// eslint-disable-next-line no-var
1922
var kernel: KernelFacade | Promise<KernelFacade>;
23+
24+
/**
25+
* CapTP utilities for resolving krefs to E()-callable presences.
26+
*
27+
* @example
28+
* ```typescript
29+
* const alice = captp.resolveKref('ko1');
30+
* await E(alice).hello('console');
31+
* ```
32+
*/
33+
// eslint-disable-next-line no-var
34+
var captp: BackgroundKref;
2035
}
2136

2237
export {};

0 commit comments

Comments
 (0)