1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { policyCall } from 'atlibs/oauth/index.js'
import { hostCall, sessionXrpc } from 'atlibs/run-module/host-call.js'
import { runModule } from 'atlibs/run-module/index.js'
// The page logic, apart from the DOM so a test can run it: the cocore modules, each held to its own session.
export const NAMES = ['cocore-inference', 'cocore-keys']
/** The host's allowlist: cocore.dev/api/v1, each request with a service-auth token minted from the user's session. */
export const HTTP = { 'https://cocore.dev': { serviceAuth: { aud: 'did:web:cocore.dev', lxm: 'dev.cocore.inference.dispatch' } } }
/** Each module's session scope (records/<name>.json): the policy policyCall holds every run to. */
export async function loadPolicy(base, fetchImpl = globalThis.fetch) {
const scopes = await Promise.all(NAMES.map(async (name) => (await (await fetchImpl(new URL(`records/${name}.json`, base))).json()).clientMetadata.scope))
return {
sessions: Object.fromEntries(NAMES.map((name, i) => [name, { scope: scopes[i] }])),
modules: Object.fromEntries(NAMES.map((name) => [name, { session: name }])),
}
}
// A completion can take a minute or so: more than runModule's default 60 s of wall time.
const BUDGET = { wallMs: 180_000 }
/**
* Run one action as the signed-in session, held to that module's own scope; with no session, signed out
* (no token: the public model directory works, inference answers 401). Resolves to the run's result.
*/
export async function runAction({ ctx, policy, modules, session }, name, entry, fields) {
const call = session ? policyCall(policy, name, { [name]: hostCall({ ctx, xrpc: sessionXrpc(session), canHeader: false }) }) : hostCall({ ctx, canHeader: false })
const ran = await runModule(ctx, await modules[name], entry, session ? { ...fields, did: session.did } : fields, call, { budget: BUDGET, http: session ? HTTP : { 'https://cocore.dev': {} } })
if (ran.error !== undefined) throw new Error(ran.error)
return ran.result
}