@cef-ai/widget-runtime 2.2.0 → 2.2.2

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/entry.js CHANGED
@@ -7,7 +7,7 @@ import { createCefWalletGate } from './cef-wallet.js';
7
7
  import { autoSignIn } from './sign-in-ui.js';
8
8
  import { currentLinkContext } from './share-link.js';
9
9
  import { createIdentityResolver } from './resolve-identity.js';
10
- import { createVaultClient } from './vault-client.js';
10
+ import { createVaultClient, openHostVault } from './vault-client.js';
11
11
  import { toVaultSdkConfig } from './vault-sdk-config.js';
12
12
  import { createWidgetRuntime } from './runtime.js';
13
13
  import { captureAndUploadAudio, createVaultObjectUploader } from './audio/capture-upload.js';
@@ -155,19 +155,15 @@ function boot() {
155
155
  const id = await resolveSigningIdentity();
156
156
  const vaultSdkSigner = toVaultSdkSigner(id.publicKey, id.sigType, id.sign);
157
157
  // Same delegation preference as the vault client: an upload that signs
158
- // per chunk on a keyless session is a ceremony per chunk.
159
- // Same config builder as the main vault client above — in particular
160
- // the same `chainUrl`, since this `ensure({ onboard: false })` runs
161
- // the vault-delegate grant step too.
158
+ // per chunk on a keyless session is a ceremony per chunk. Same config
159
+ // builder too — in particular the same `chainUrl`, which the `ensure()`
160
+ // branch of `openHostVault` needs for its vault-delegate grant.
162
161
  const sdk = new VaultSDK(toVaultSdkConfig(manifest.endpoints, vaultSdkSigner, id.token, id.renewToken));
163
- // With a token that SDK has no signer, and `ensure()` does not read
164
- // `auth`: it needs the token handed to it, or it throws before the
165
- // first chunk. Without one the key stays absent so the signer path runs.
166
- const ensuredVault = await sdk.vault.ensure({
167
- onboard: false,
168
- ...(id.token ? { delegationToken: id.token } : {}),
169
- });
170
- return createVaultObjectUploader({ objects: ensuredVault.scope(manifest.scope).objects });
162
+ // The same vault the reader opened: the job runs where the event was
163
+ // published, so audio uploaded anywhere else is a URL into a database
164
+ // the agent is not in.
165
+ const uploadVault = await openHostVault(sdk.vault, id.context?.vaultId, id.token);
166
+ return createVaultObjectUploader({ objects: uploadVault.scope(manifest.scope).objects });
171
167
  })().catch((err) => { uploaderP = null; throw err; });
172
168
  return uploaderP;
173
169
  };
@@ -41,6 +41,26 @@ export declare class WidgetVaultUnreachableError extends Error {
41
41
  readonly reason: string;
42
42
  constructor(vaultId: string, cause?: unknown);
43
43
  }
44
+ /**
45
+ * THE VAULT A WIDGET WORKS IN — the one the host named, else the caller's.
46
+ *
47
+ * There is deliberately no third branch. A named vault that will not open is an
48
+ * error, never a quiet fall-through to `ensure()`: the fall-through is
49
+ * indistinguishable from an empty result, and being indistinguishable from an
50
+ * empty result is the bug.
51
+ *
52
+ * Shared by the reader and the audio uploader, which each used to decide this
53
+ * for themselves — and only one of them knew about `context.vaultId`.
54
+ *
55
+ * Generic so both `VaultLike` and the real vault-sdk handle fit without `any`.
56
+ */
57
+ export declare function openHostVault<V>(vaultNs: {
58
+ ensure: (opts?: {
59
+ onboard?: boolean;
60
+ delegationToken?: string;
61
+ }) => Promise<V>;
62
+ byId?: (vaultId: string) => Promise<V>;
63
+ }, hostVaultId: string | undefined, hostToken?: string): Promise<V>;
44
64
  interface VaultLike {
45
65
  id: string;
46
66
  agents: {
@@ -29,6 +29,41 @@ export class WidgetVaultUnreachableError extends Error {
29
29
  this.reason = reason;
30
30
  }
31
31
  }
32
+ /**
33
+ * THE VAULT A WIDGET WORKS IN — the one the host named, else the caller's.
34
+ *
35
+ * There is deliberately no third branch. A named vault that will not open is an
36
+ * error, never a quiet fall-through to `ensure()`: the fall-through is
37
+ * indistinguishable from an empty result, and being indistinguishable from an
38
+ * empty result is the bug.
39
+ *
40
+ * Shared by the reader and the audio uploader, which each used to decide this
41
+ * for themselves — and only one of them knew about `context.vaultId`.
42
+ *
43
+ * Generic so both `VaultLike` and the real vault-sdk handle fit without `any`.
44
+ */
45
+ export async function openHostVault(vaultNs, hostVaultId, hostToken) {
46
+ if (!hostVaultId) {
47
+ // `onboard: false` preserves the old lightweight ensure(): claim the vault
48
+ // with a wallet-built delegation token, skipping the gateway onboarding
49
+ // status/bootstrap round-trip (widgets assume a provisioned wallet).
50
+ return vaultNs.ensure({
51
+ onboard: false,
52
+ ...(hostToken ? { delegationToken: hostToken } : {}),
53
+ });
54
+ }
55
+ if (typeof vaultNs.byId !== 'function') {
56
+ throw new WidgetVaultUnreachableError(hostVaultId);
57
+ }
58
+ try {
59
+ return await vaultNs.byId(hostVaultId);
60
+ }
61
+ catch (err) {
62
+ // Not found, no access, network — all one answer to the reader: this is
63
+ // not your vault and nothing here can show you what is in it.
64
+ throw new WidgetVaultUnreachableError(hostVaultId, err);
65
+ }
66
+ }
32
67
  /**
33
68
  * Normalise the raw result from cubbies.query into a uniform QueryResult.
34
69
  * The platform returns `{columns: string[], rows: unknown[][]}` (positional).
@@ -90,37 +125,10 @@ hostVaultId) {
90
125
  let sdk;
91
126
  let vaultP;
92
127
  const getSdk = () => (sdk ?? (sdk = makeSdk()));
93
- /**
94
- * THE VAULT THIS WIDGET READS — the one the host named, else the caller's.
95
- *
96
- * There is deliberately no third branch. A named vault that will not open is
97
- * an error, never a quiet fall-through to `ensure()`: the fall-through is
98
- * indistinguishable from an empty result, and being indistinguishable from an
99
- * empty result is the bug.
100
- */
101
- const openVault = async () => {
102
- if (!hostVaultId) {
103
- // `onboard: false` preserves the old lightweight ensure(): claim the vault
104
- // with a wallet-built delegation token, skipping the gateway onboarding
105
- // status/bootstrap round-trip (widgets assume a provisioned wallet).
106
- return getSdk().vault.ensure({
107
- onboard: false,
108
- ...(hostToken ? { delegationToken: hostToken } : {}),
109
- });
110
- }
111
- const vaultNs = getSdk().vault;
112
- if (typeof vaultNs.byId !== 'function') {
113
- throw new WidgetVaultUnreachableError(hostVaultId);
114
- }
115
- try {
116
- return await vaultNs.byId(hostVaultId);
117
- }
118
- catch (err) {
119
- // Not found, no access, network — all one answer to the reader: this is
120
- // not your vault and nothing here can show you what is in it.
121
- throw new WidgetVaultUnreachableError(hostVaultId, err);
122
- }
123
- };
128
+ // `async` so a synchronous throw from `makeSdk()` lands as a rejected promise
129
+ // rather than in the caller's frame — `getVault()` is only ever awaited today,
130
+ // but the `vaultP` memo below assumes a promise either way.
131
+ const openVault = async () => openHostVault(getSdk().vault, hostVaultId, hostToken);
124
132
  const getVault = () => {
125
133
  vaultP ?? (vaultP = openVault().catch((err) => {
126
134
  vaultP = undefined;