@immediately-run/sdk 0.57.1 → 0.57.4

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.
Files changed (125) hide show
  1. package/dist/agentChatClient.cjs +112 -0
  2. package/dist/agentChatClient.cjs.map +1 -0
  3. package/dist/agentChatClient.d.cts +9 -0
  4. package/dist/agentChatClient.d.ts +9 -0
  5. package/dist/agentChatClient.js +89 -0
  6. package/dist/agentChatClient.js.map +1 -0
  7. package/dist/agentContext.cjs +69 -0
  8. package/dist/agentContext.cjs.map +1 -0
  9. package/dist/agentContext.d.cts +45 -0
  10. package/dist/agentContext.d.ts +45 -0
  11. package/dist/agentContext.js +45 -0
  12. package/dist/agentContext.js.map +1 -0
  13. package/dist/agentLoop.cjs +301 -0
  14. package/dist/agentLoop.cjs.map +1 -0
  15. package/dist/agentLoop.d.cts +267 -0
  16. package/dist/agentLoop.d.ts +267 -0
  17. package/dist/agentLoop.js +271 -0
  18. package/dist/agentLoop.js.map +1 -0
  19. package/dist/agentSteering.cjs +127 -0
  20. package/dist/agentSteering.cjs.map +1 -0
  21. package/dist/agentSteering.d.cts +80 -0
  22. package/dist/agentSteering.d.ts +80 -0
  23. package/dist/agentSteering.js +98 -0
  24. package/dist/agentSteering.js.map +1 -0
  25. package/dist/auth.cjs.map +1 -1
  26. package/dist/auth.d.cts +33 -2
  27. package/dist/auth.d.ts +33 -2
  28. package/dist/auth.js.map +1 -1
  29. package/dist/bundle.cjs +91 -0
  30. package/dist/bundle.cjs.map +1 -0
  31. package/dist/bundle.d.cts +63 -0
  32. package/dist/bundle.d.ts +63 -0
  33. package/dist/bundle.js +62 -0
  34. package/dist/bundle.js.map +1 -0
  35. package/dist/collectHeadings.cjs +59 -0
  36. package/dist/collectHeadings.cjs.map +1 -0
  37. package/dist/collectHeadings.d.cts +16 -0
  38. package/dist/collectHeadings.d.ts +16 -0
  39. package/dist/collectHeadings.js +36 -0
  40. package/dist/collectHeadings.js.map +1 -0
  41. package/dist/corpus.cjs +9 -58
  42. package/dist/corpus.cjs.map +1 -1
  43. package/dist/corpus.d.cts +3 -63
  44. package/dist/corpus.d.ts +3 -63
  45. package/dist/corpus.js +15 -57
  46. package/dist/corpus.js.map +1 -1
  47. package/dist/debug.cjs +115 -0
  48. package/dist/debug.cjs.map +1 -1
  49. package/dist/debug.js +115 -0
  50. package/dist/debug.js.map +1 -1
  51. package/dist/fence.cjs +49 -0
  52. package/dist/fence.cjs.map +1 -0
  53. package/dist/fence.d.cts +4 -0
  54. package/dist/fence.d.ts +4 -0
  55. package/dist/fence.js +26 -0
  56. package/dist/fence.js.map +1 -0
  57. package/dist/formFactor.cjs.map +1 -1
  58. package/dist/formFactor.d.cts +11 -2
  59. package/dist/formFactor.d.ts +11 -2
  60. package/dist/formFactor.js.map +1 -1
  61. package/dist/fs.cjs.map +1 -1
  62. package/dist/fs.d.cts +16 -6
  63. package/dist/fs.d.ts +16 -6
  64. package/dist/fs.js.map +1 -1
  65. package/dist/hooks.cjs.map +1 -1
  66. package/dist/hooks.d.cts +7 -0
  67. package/dist/hooks.d.ts +7 -0
  68. package/dist/hooks.js.map +1 -1
  69. package/dist/index.cjs +19 -1
  70. package/dist/index.cjs.map +1 -1
  71. package/dist/index.d.cts +11 -3
  72. package/dist/index.d.ts +11 -3
  73. package/dist/index.js +9 -0
  74. package/dist/index.js.map +1 -1
  75. package/dist/launch.cjs +45 -6
  76. package/dist/launch.cjs.map +1 -1
  77. package/dist/launch.d.cts +3 -0
  78. package/dist/launch.d.ts +3 -0
  79. package/dist/launch.js +45 -6
  80. package/dist/launch.js.map +1 -1
  81. package/dist/llm.cjs.map +1 -1
  82. package/dist/llm.d.cts +20 -3
  83. package/dist/llm.d.ts +20 -3
  84. package/dist/llm.js.map +1 -1
  85. package/dist/metadataQueryTool.cjs +271 -0
  86. package/dist/metadataQueryTool.cjs.map +1 -0
  87. package/dist/metadataQueryTool.d.cts +159 -0
  88. package/dist/metadataQueryTool.d.ts +159 -0
  89. package/dist/metadataQueryTool.js +241 -0
  90. package/dist/metadataQueryTool.js.map +1 -0
  91. package/dist/mounts.cjs.map +1 -1
  92. package/dist/mounts.d.cts +22 -3
  93. package/dist/mounts.d.ts +22 -3
  94. package/dist/mounts.js.map +1 -1
  95. package/dist/onFsChange.cjs +13 -1
  96. package/dist/onFsChange.cjs.map +1 -1
  97. package/dist/onFsChange.d.cts +21 -1
  98. package/dist/onFsChange.d.ts +21 -1
  99. package/dist/onFsChange.js +13 -1
  100. package/dist/onFsChange.js.map +1 -1
  101. package/dist/protocolSchemes.cjs +1 -0
  102. package/dist/protocolSchemes.cjs.map +1 -1
  103. package/dist/protocolSchemes.d.cts +1 -0
  104. package/dist/protocolSchemes.d.ts +1 -0
  105. package/dist/protocolSchemes.js +2 -0
  106. package/dist/protocolSchemes.js.map +1 -1
  107. package/dist/recents.cjs +41 -0
  108. package/dist/recents.cjs.map +1 -0
  109. package/dist/recents.d.cts +23 -0
  110. package/dist/recents.d.ts +23 -0
  111. package/dist/recents.js +17 -0
  112. package/dist/recents.js.map +1 -0
  113. package/dist/tasks.cjs +41 -7
  114. package/dist/tasks.cjs.map +1 -1
  115. package/dist/tasks.d.cts +136 -7
  116. package/dist/tasks.d.ts +136 -7
  117. package/dist/tasks.js +39 -7
  118. package/dist/tasks.js.map +1 -1
  119. package/dist/version.cjs +1 -1
  120. package/dist/version.cjs.map +1 -1
  121. package/dist/version.d.cts +1 -1
  122. package/dist/version.d.ts +1 -1
  123. package/dist/version.js +1 -1
  124. package/dist/version.js.map +1 -1
  125. package/package.json +6 -5
package/dist/tasks.d.ts CHANGED
@@ -44,27 +44,156 @@ declare const capDir: (ref: {
44
44
  /**
45
45
  * Invoke another app via a task contract and await its typed result (Recipe B).
46
46
  * Rejects with a machine `.code` on refusal: `cancelled` (user dismissed the
47
- * overlay), `timeout` (§5.7.1 liveness), `forbidden` (undeclared task or a file
48
- * delegation you don't hold), `no-such-task`, `task-cycle`/`task-depth-exceeded`/
49
- * `task-version-mismatch`, or `invalid-params` (result failed the contract schema).
47
+ * overlay), `timeout` (§5.7.1 liveness), `forbidden` (missing `task:invoke`, or a
48
+ * file delegation you don't hold), `not-declared` (the task is missing from your
49
+ * `immediately.run.invokes`), `no-such-task` (no app is bound to that contract),
50
+ * `task-cycle`/`task-depth-exceeded`/`task-version-mismatch`, or `invalid-params`
51
+ * (result failed the contract schema). **Read `err.message`** — since R3-418 the host
52
+ * says which capability, which declaration or which param was at fault; the code alone
53
+ * does not distinguish them.
54
+ *
55
+ * Two things must BOTH be true before any invoke is admitted, and they are separate:
56
+ * 1. your `package.json` `immediately.run.invokes` lists the task (else `not-declared`);
57
+ * 2. your app holds the `task:invoke` capability — declare it in
58
+ * `immediately.run.capabilities` so the user can grant it (else `forbidden`).
59
+ * Declaring the invoke does not imply the capability.
60
+ *
61
+ * ── `pick-file`: `roots` is required (SPACES_UI_SPEC §4.1) ───────────────────
62
+ * ```ts
63
+ * import { invokeTask, capDir, requestMount } from '@immediately-run/sdk';
64
+ *
65
+ * const mount = await requestMount(); // the user picks a space
66
+ * // `invokeTask` returns `unknown` — name the result type, or the destructuring
67
+ * // below does not compile.
68
+ * const { root, path } = await invokeTask<{ root: number; path: string }>('pick-file', {
69
+ * // `SandboxMount.id` is optional (absent on the primary repo mount) — fall back to
70
+ * // `path`, which is always present and is what the host resolves against.
71
+ * roots: [capDir({ mountId: mount.id ?? mount.path, relPath: 'boards' }, { mode: 'ro' })],
72
+ * });
73
+ * ```
74
+ * - `roots` is a NON-EMPTY `DirCap[]` of directories you **already hold**. The result
75
+ * names its target as `{ root, path }` where `root` INDEXES `params.roots`, so
76
+ * `invokeTask('pick-file', {})` can never produce a valid result and is rejected.
77
+ * There is no rootless "pick from any of my spaces" mode by design: enumerating the
78
+ * user's spaces is the host's powerbox (`requestMount()`), and composing the two —
79
+ * as above — is that flow. See SPACES_UI_SPEC R-SPACES-5/R-SPACES-12.
80
+ * - Each `capDir` is attenuated against your own grant. **`{ mode: 'rw' }` over a space
81
+ * the user granted `ro` is refused `forbidden`** — the commonest failure, because the
82
+ * mount *was* granted and the path *is* inside it. Pass the mode you actually hold;
83
+ * `ro` is right for a plain pick.
84
+ * - The `requestMount()` grant is DURABLE and survives a cancelled pick: the user
85
+ * consented to the mount in host chrome, separately from the pick (SPACES_UI_SPEC §4.1).
86
+ * Reuse it for later picks rather than re-requesting.
87
+ *
88
+ * Off-host (plain `vite dev` — no host transport) it rejects with a plain
89
+ * "no host transport" error: there is no host to resolve the task binding.
50
90
  */
51
91
  declare const invokeTask: <R = unknown>(task: string, params?: Record<string, unknown>) => Promise<R>;
92
+ /** Bytes captured by the host, as `capturePhoto()` / `captureAudio()` return them.
93
+ * `bytes` is a transferable `ArrayBuffer` — write it to a space, decode it, upload
94
+ * it. You never receive a `MediaStream` or a `MediaStreamTrack`, and that is not an
95
+ * omission: a track cannot be transferred into an app frame at all
96
+ * (`DataCloneError`), and the frame's opaque origin cannot open a device itself
97
+ * (`getUserMedia` throws `SecurityError: Invalid security origin`). */
98
+ interface CaptureResult {
99
+ bytes: ArrayBuffer;
100
+ /** e.g. `image/jpeg`, `audio/webm`. Chosen by the HOST, not by you. */
101
+ mimeType: string;
102
+ /** How long the device was open, in ms. */
103
+ durationMs: number;
104
+ }
105
+ /** Optional hints for a capture. They deliberately name NOTHING — no device id, no
106
+ * camera index — because the host chooses everything about how the capture is
107
+ * performed. That is what lets the grant be a plain on/off instead of a per-call
108
+ * target list the way `net:fetch` needs. */
109
+ interface CaptureOptions {
110
+ /** Which way the camera should face, if the device has a choice. A HINT: the host
111
+ * may ignore it. Ignored for audio. */
112
+ facing?: 'user' | 'environment';
113
+ }
114
+ /**
115
+ * Take one photo, or record one audio clip, through the HOST's capture UI
116
+ * (`BROWSER_CAPABILITIES_SPEC` §3 grade 1).
117
+ *
118
+ * The host opens the device at its own origin, draws the viewfinder, and hands you
119
+ * the bytes when the user presses Done. **You are never in the loop while the device
120
+ * is live** — that is the point of the design, not a limitation of it:
121
+ *
122
+ * - The capture UI is drawn by the host, so a user can trust it the way they trust
123
+ * the sign-in dialog. Do not build a lookalike; imitating host chrome is spoofing.
124
+ * - While the device is open the host shows a persistent "camera on" / "microphone
125
+ * on" indicator in its own chrome, for the whole session. You cannot hide it and
126
+ * should not try to.
127
+ * - If the user cancels, this rejects `cancelled` and **nothing was recorded**. There
128
+ * is no partial result — do not write error handling that hopes for one.
129
+ *
130
+ * ```ts
131
+ * import { capturePhoto, requestMount, openFs } from '@immediately-run/sdk';
132
+ *
133
+ * try {
134
+ * const { bytes, mimeType } = await capturePhoto({ facing: 'environment' });
135
+ * const mount = await requestMount(); // the user picks a space to save into
136
+ * const fs = openFs(mount); // writeFile is a METHOD on the MountFs
137
+ * await fs.mkdir('photos', { recursive: true }); // writeFile does not create parents
138
+ * await fs.writeFile(`photos/latest.${mimeType === 'image/png' ? 'png' : 'jpg'}`, new Uint8Array(bytes));
139
+ * } catch (e) {
140
+ * if ((e as { code?: string }).code === 'cancelled') return; // the user said no
141
+ * throw e;
142
+ * }
143
+ * ```
144
+ * (The extension follows `mimeType` because the HOST chooses the format — do not assume
145
+ * JPEG. `openAppFs()` is the variant that writes to your own app space with no pick.)
146
+ *
147
+ * Two things must BOTH be true, exactly as for any other task:
148
+ * 1. `immediately.run.invokes` lists `capture-photo` (or `capture-audio`);
149
+ * 2. your app holds `task:invoke` **and** `device:camera` (or `device:microphone`)
150
+ * — declare them in `immediately.run.capabilities` so the user can grant them.
151
+ *
152
+ * Rejects with `.code`: `cancelled` (the user dismissed the capture — nothing was
153
+ * recorded), `forbidden` (you lack the capability; `message: 'browser-denied'` means
154
+ * the BROWSER refused immediately.run itself, which your consent cannot fix),
155
+ * `unavailable` (no such device on this machine, or it would not start),
156
+ * `unsupported` (this host cannot capture), `not-declared`, `timeout`.
157
+ *
158
+ * *Zero-platform alternative, still worth knowing:* `<input type="file"
159
+ * accept="image/*" capture="environment">` opens the OS camera from inside the
160
+ * sandbox (file choosers are not permission-gated). It needs no capability and no
161
+ * host support; it also gives you no indicator and no host-drawn surface.
162
+ */
163
+ declare const capturePhoto: (options?: CaptureOptions) => Promise<CaptureResult>;
164
+ /** Record one audio clip through the host's capture UI. See {@link capturePhoto} —
165
+ * every rule there applies verbatim, with `device:microphone` and `capture-audio`. */
166
+ declare const captureAudio: (options?: CaptureOptions) => Promise<CaptureResult>;
52
167
  /** The params this app was invoked with as a task callee. */
53
168
  interface TaskInput {
54
169
  task: string;
55
170
  params: Record<string, unknown>;
56
171
  }
57
- /** The task params this app was invoked with, or null if it isn't a task callee. */
172
+ /** The task params this app was invoked with, or null if it isn't a task callee.
173
+ * Off-host (plain `vite dev`) this is always `null` — there is no host to invoke
174
+ * this app as a callee. */
58
175
  declare const getTaskInput: () => TaskInput | null;
59
176
  /**
60
177
  * Finish the task, returning a result to the caller. The host validates it against
61
178
  * the contract's result schema before resolving the caller (`invalid-params` on
62
179
  * violation), then tears down this overlay.
180
+ *
181
+ * `result` must be STRUCTURED-CLONEABLE — it crosses a frame boundary. A DOM node, a
182
+ * function, a class instance with methods, a `MediaStreamTrack`: all `DataCloneError`.
183
+ * **That throws**, deliberately and loudly: the alternative is a caller left hanging to
184
+ * its `invokeTask` deadline while this app believes it answered.
185
+ *
186
+ * Off-host (plain `vite dev` — no host transport) this is a no-op: there is no caller
187
+ * to answer. That case, and only that case, is silent.
63
188
  */
64
189
  declare const completeTask: (result: unknown) => void;
65
- /** Abort the task; the caller's `invokeTask` rejects with `cancelled`. */
190
+ /** Abort the task; the caller's `invokeTask` rejects with `cancelled`.
191
+ * Off-host (plain `vite dev` — no host transport) this is a no-op; on-host a failed
192
+ * send throws rather than leaving the caller waiting, exactly as {@link completeTask}. */
66
193
  declare const cancelTask: () => void;
67
- /** React hook: the task input for this callee, re-rendering when it arrives. */
194
+ /** React hook: the task input for this callee, re-rendering when it arrives.
195
+ * Off-host (plain `vite dev`) it stays `null` forever — render the non-callee
196
+ * state rather than waiting on it. */
68
197
  declare const useTaskInput: () => TaskInput | null;
69
198
 
70
- export { type DirCap, type FileCap, type TaskInput, cancelTask, capDir, capFile, completeTask, getTaskInput, invokeTask, useTaskInput };
199
+ export { type CaptureOptions, type CaptureResult, type DirCap, type FileCap, type TaskInput, cancelTask, capDir, capFile, captureAudio, capturePhoto, completeTask, getTaskInput, invokeTask, useTaskInput };
package/dist/tasks.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import "./chunk-VHAA22YE.js";
2
2
  import { useEffect, useState } from "react";
3
3
  import { protocolRequest, sendMessage, addListener } from "./sandboxUtils";
4
+ import { transport } from "./hostTransport";
4
5
  import { PROTOCOL_TASK, TASK_CANCEL, TASK_COMPLETE, TASK_INPUT } from "./generated/protocol";
5
6
  import { SCHEMES } from "./protocolSchemes";
6
7
  const capFile = (ref, opts) => ({
@@ -24,15 +25,44 @@ const invokeTask = async (task, params = {}) => {
24
25
  }
25
26
  return res.data;
26
27
  };
28
+ const capturePhoto = (options = {}) => invokeTask("capture-photo", { ...options });
29
+ const captureAudio = (options = {}) => invokeTask("capture-audio", { ...options });
27
30
  let latestInput = null;
28
31
  const inputListeners = /* @__PURE__ */ new Set();
29
- addListener(TASK_INPUT, (m) => {
30
- latestInput = { task: m.task, params: m.params ?? {} };
31
- inputListeners.forEach((l) => l(latestInput));
32
- });
33
- const getTaskInput = () => latestInput;
34
- const completeTask = (result) => sendMessage(TASK_COMPLETE, { result });
35
- const cancelTask = () => sendMessage(TASK_CANCEL, {});
32
+ let inputListenerRegistered = false;
33
+ const ensureInputListener = () => {
34
+ if (inputListenerRegistered) return;
35
+ try {
36
+ addListener(TASK_INPUT, (m) => {
37
+ latestInput = { task: m.task, params: m.params ?? {} };
38
+ inputListeners.forEach((l) => l(latestInput));
39
+ });
40
+ } catch {
41
+ return;
42
+ }
43
+ inputListenerRegistered = true;
44
+ };
45
+ ensureInputListener();
46
+ const getTaskInput = () => {
47
+ ensureInputListener();
48
+ return latestInput;
49
+ };
50
+ const hostReachable = () => {
51
+ try {
52
+ transport();
53
+ return true;
54
+ } catch {
55
+ return false;
56
+ }
57
+ };
58
+ const completeTask = (result) => {
59
+ if (!hostReachable()) return;
60
+ sendMessage(TASK_COMPLETE, { result });
61
+ };
62
+ const cancelTask = () => {
63
+ if (!hostReachable()) return;
64
+ sendMessage(TASK_CANCEL, {});
65
+ };
36
66
  const useTaskInput = () => {
37
67
  const [input, setInput] = useState(getTaskInput);
38
68
  useEffect(() => {
@@ -49,6 +79,8 @@ export {
49
79
  cancelTask,
50
80
  capDir,
51
81
  capFile,
82
+ captureAudio,
83
+ capturePhoto,
52
84
  completeTask,
53
85
  getTaskInput,
54
86
  invokeTask,
package/dist/tasks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tasks.ts"],"sourcesContent":["// Task invocation — apps invoking apps (UI_AS_APPS_SPEC §5.7). The\n// `startActivityForResult` pattern: one app invokes another by TASK CONTRACT\n// (never by app name — the user's override picks the bound app), passes typed\n// params, and awaits a typed result. The callee runs in a host-owned overlay\n// under ITS OWN grants — data crosses, your authority does not (§5.7).\n//\n// Two roles:\n// - CALLER: `invokeTask(task, params)` (Recipe B — a deferred reply the host\n// holds open until the callee finishes). Delegate a file with `capFile(...)`:\n// the host resolves it against YOUR grants and mints an attenuated chroot.\n// - CALLEE: read `useTaskInput()`, then `completeTask(result)` / `cancelTask()`.\nimport { useEffect, useState } from 'react';\nimport { protocolRequest, sendMessage, addListener } from './sandboxUtils';\nimport { PROTOCOL_TASK, TASK_CANCEL, TASK_COMPLETE, TASK_INPUT } from './generated/protocol';\nimport { SCHEMES } from './protocolSchemes';\n\n// ── caller side ─────────────────────────────────────────────────────────────\n\n/** A delegated FILE capability marker for a task param (§5.7). */\nexport interface FileCap {\n $cap: 'file';\n mountId: string;\n relPath: string;\n mode: 'ro' | 'rw';\n}\n\n/**\n * Build a delegated file reference for a task param. The host resolves it against\n * YOUR OWN grants and mints an attenuated, task-scoped chroot for the callee — you\n * can only delegate a path you already hold (attenuation only, never escalation).\n *\n * file: capFile({ mountId: 'space:abc', relPath: 'photos/cat.jpg' }, { mode: 'rw' })\n */\nexport const capFile = (ref: { mountId: string; relPath: string }, opts: { mode: 'ro' | 'rw' }): FileCap => ({\n $cap: 'file',\n mountId: ref.mountId,\n relPath: ref.relPath,\n mode: opts.mode,\n});\n\n/** A delegated DIRECTORY capability marker for a task param (D2). Like {@link FileCap}\n * but `relPath` names a DIRECTORY: the host chroots the callee AT that directory\n * (the whole subtree). Used for the `pick-file` `roots` — one chroot per root. */\nexport interface DirCap {\n $cap: 'dir';\n mountId: string;\n relPath: string;\n mode: 'ro' | 'rw';\n}\n\n/**\n * Build a delegated DIRECTORY reference for a task param (the directory analogue of\n * {@link capFile}). The host resolves it against YOUR OWN grants and mints an\n * attenuated, task-scoped chroot of that directory for the callee — you can only\n * delegate a directory you already hold (attenuation only, never escalation):\n *\n * roots: [capDir({ mountId: 'space:abc', relPath: 'boards' }, { mode: 'rw' })]\n */\nexport const capDir = (ref: { mountId: string; relPath: string }, opts: { mode: 'ro' | 'rw' }): DirCap => ({\n $cap: 'dir',\n mountId: ref.mountId,\n relPath: ref.relPath,\n mode: opts.mode,\n});\n\n/**\n * Invoke another app via a task contract and await its typed result (Recipe B).\n * Rejects with a machine `.code` on refusal: `cancelled` (user dismissed the\n * overlay), `timeout` (§5.7.1 liveness), `forbidden` (undeclared task or a file\n * delegation you don't hold), `no-such-task`, `task-cycle`/`task-depth-exceeded`/\n * `task-version-mismatch`, or `invalid-params` (result failed the contract schema).\n */\nexport const invokeTask = async <R = unknown>(task: string, params: Record<string, unknown> = {}): Promise<R> => {\n const res = (await protocolRequest(SCHEMES[PROTOCOL_TASK], 'invoke', [{ task, params }])) as\n | { ok: true; data: R }\n | { ok: false; code?: string; message?: string }\n | undefined;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? `task '${task}' failed`) as Error & { code?: string };\n err.code = res?.code ?? 'unknown';\n throw err;\n }\n return res.data;\n};\n\n// ── callee side ─────────────────────────────────────────────────────────────\n\n/** The params this app was invoked with as a task callee. */\nexport interface TaskInput {\n task: string;\n params: Record<string, unknown>;\n}\n\nlet latestInput: TaskInput | null = null;\nconst inputListeners = new Set<(i: TaskInput) => void>();\n\n// The host delivers a `task-input` message to the callee's iframe right after it\n// mounts the overlay (the §5.7 \"params via the region's mount event\").\naddListener(TASK_INPUT, (m: { task: string; params?: Record<string, unknown> }) => {\n latestInput = { task: m.task, params: m.params ?? {} };\n inputListeners.forEach((l) => l(latestInput!));\n});\n\n/** The task params this app was invoked with, or null if it isn't a task callee. */\nexport const getTaskInput = (): TaskInput | null => latestInput;\n\n/**\n * Finish the task, returning a result to the caller. The host validates it against\n * the contract's result schema before resolving the caller (`invalid-params` on\n * violation), then tears down this overlay.\n */\nexport const completeTask = (result: unknown): void => sendMessage(TASK_COMPLETE, { result });\n\n/** Abort the task; the caller's `invokeTask` rejects with `cancelled`. */\nexport const cancelTask = (): void => sendMessage(TASK_CANCEL, {});\n\n/** React hook: the task input for this callee, re-rendering when it arrives. */\nexport const useTaskInput = (): TaskInput | null => {\n const [input, setInput] = useState<TaskInput | null>(getTaskInput);\n useEffect(() => {\n const l = (i: TaskInput) => setInput(i);\n inputListeners.add(l);\n if (latestInput) setInput(latestInput);\n return () => {\n inputListeners.delete(l);\n };\n }, []);\n return input;\n};\n"],"mappings":";AAWA,SAAS,WAAW,gBAAgB;AACpC,SAAS,iBAAiB,aAAa,mBAAmB;AAC1D,SAAS,eAAe,aAAa,eAAe,kBAAkB;AACtE,SAAS,eAAe;AAmBjB,MAAM,UAAU,CAAC,KAA2C,UAA0C;AAAA,EAC3G,MAAM;AAAA,EACN,SAAS,IAAI;AAAA,EACb,SAAS,IAAI;AAAA,EACb,MAAM,KAAK;AACb;AAoBO,MAAM,SAAS,CAAC,KAA2C,UAAyC;AAAA,EACzG,MAAM;AAAA,EACN,SAAS,IAAI;AAAA,EACb,SAAS,IAAI;AAAA,EACb,MAAM,KAAK;AACb;AASO,MAAM,aAAa,OAAoB,MAAc,SAAkC,CAAC,MAAkB;AAC/G,QAAM,MAAO,MAAM,gBAAgB,QAAQ,aAAa,GAAG,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,CAAC;AAIvF,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,SAAS,IAAI,UAAU;AAC7D,QAAI,OAAO,KAAK,QAAQ;AACxB,UAAM;AAAA,EACR;AACA,SAAO,IAAI;AACb;AAUA,IAAI,cAAgC;AACpC,MAAM,iBAAiB,oBAAI,IAA4B;AAIvD,YAAY,YAAY,CAAC,MAA0D;AACjF,gBAAc,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,UAAU,CAAC,EAAE;AACrD,iBAAe,QAAQ,CAAC,MAAM,EAAE,WAAY,CAAC;AAC/C,CAAC;AAGM,MAAM,eAAe,MAAwB;AAO7C,MAAM,eAAe,CAAC,WAA0B,YAAY,eAAe,EAAE,OAAO,CAAC;AAGrF,MAAM,aAAa,MAAY,YAAY,aAAa,CAAC,CAAC;AAG1D,MAAM,eAAe,MAAwB;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA2B,YAAY;AACjE,YAAU,MAAM;AACd,UAAM,IAAI,CAAC,MAAiB,SAAS,CAAC;AACtC,mBAAe,IAAI,CAAC;AACpB,QAAI,YAAa,UAAS,WAAW;AACrC,WAAO,MAAM;AACX,qBAAe,OAAO,CAAC;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,CAAC;AACL,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/tasks.ts"],"sourcesContent":["// Task invocation — apps invoking apps (UI_AS_APPS_SPEC §5.7). The\n// `startActivityForResult` pattern: one app invokes another by TASK CONTRACT\n// (never by app name — the user's override picks the bound app), passes typed\n// params, and awaits a typed result. The callee runs in a host-owned overlay\n// under ITS OWN grants — data crosses, your authority does not (§5.7).\n//\n// Two roles:\n// - CALLER: `invokeTask(task, params)` (Recipe B — a deferred reply the host\n// holds open until the callee finishes). Delegate a file with `capFile(...)`:\n// the host resolves it against YOUR grants and mints an attenuated chroot.\n// - CALLEE: read `useTaskInput()`, then `completeTask(result)` / `cancelTask()`.\n//\n// OFF-HOST (plain `vite dev`, node/jsdom tests — no sandbox, no host transport):\n// importing this module is always safe (R3-421 — no subpath may throw at import\n// time), and the surface degrades instead of crashing: `getTaskInput()` /\n// `useTaskInput()` stay `null` forever (you are never a task callee without a\n// host), `completeTask` / `cancelTask` are no-ops, and `invokeTask` rejects with\n// a \"no host transport\" error. Under the @immediately-run/dev-fs substrate the\n// transport resolves but no task ever arrives — same observable behaviour.\n// The no-op is scoped to the ABSENCE of a host: when there IS one, a failed send\n// throws instead of leaving the caller to hang out its deadline.\nimport { useEffect, useState } from 'react';\nimport { protocolRequest, sendMessage, addListener } from './sandboxUtils';\nimport { transport } from './hostTransport';\nimport { PROTOCOL_TASK, TASK_CANCEL, TASK_COMPLETE, TASK_INPUT } from './generated/protocol';\nimport { SCHEMES } from './protocolSchemes';\n\n// ── caller side ─────────────────────────────────────────────────────────────\n\n/** A delegated FILE capability marker for a task param (§5.7). */\nexport interface FileCap {\n $cap: 'file';\n mountId: string;\n relPath: string;\n mode: 'ro' | 'rw';\n}\n\n/**\n * Build a delegated file reference for a task param. The host resolves it against\n * YOUR OWN grants and mints an attenuated, task-scoped chroot for the callee — you\n * can only delegate a path you already hold (attenuation only, never escalation).\n *\n * file: capFile({ mountId: 'space:abc', relPath: 'photos/cat.jpg' }, { mode: 'rw' })\n */\nexport const capFile = (ref: { mountId: string; relPath: string }, opts: { mode: 'ro' | 'rw' }): FileCap => ({\n $cap: 'file',\n mountId: ref.mountId,\n relPath: ref.relPath,\n mode: opts.mode,\n});\n\n/** A delegated DIRECTORY capability marker for a task param (D2). Like {@link FileCap}\n * but `relPath` names a DIRECTORY: the host chroots the callee AT that directory\n * (the whole subtree). Used for the `pick-file` `roots` — one chroot per root. */\nexport interface DirCap {\n $cap: 'dir';\n mountId: string;\n relPath: string;\n mode: 'ro' | 'rw';\n}\n\n/**\n * Build a delegated DIRECTORY reference for a task param (the directory analogue of\n * {@link capFile}). The host resolves it against YOUR OWN grants and mints an\n * attenuated, task-scoped chroot of that directory for the callee — you can only\n * delegate a directory you already hold (attenuation only, never escalation):\n *\n * roots: [capDir({ mountId: 'space:abc', relPath: 'boards' }, { mode: 'rw' })]\n */\nexport const capDir = (ref: { mountId: string; relPath: string }, opts: { mode: 'ro' | 'rw' }): DirCap => ({\n $cap: 'dir',\n mountId: ref.mountId,\n relPath: ref.relPath,\n mode: opts.mode,\n});\n\n/**\n * Invoke another app via a task contract and await its typed result (Recipe B).\n * Rejects with a machine `.code` on refusal: `cancelled` (user dismissed the\n * overlay), `timeout` (§5.7.1 liveness), `forbidden` (missing `task:invoke`, or a\n * file delegation you don't hold), `not-declared` (the task is missing from your\n * `immediately.run.invokes`), `no-such-task` (no app is bound to that contract),\n * `task-cycle`/`task-depth-exceeded`/`task-version-mismatch`, or `invalid-params`\n * (result failed the contract schema). **Read `err.message`** — since R3-418 the host\n * says which capability, which declaration or which param was at fault; the code alone\n * does not distinguish them.\n *\n * Two things must BOTH be true before any invoke is admitted, and they are separate:\n * 1. your `package.json` `immediately.run.invokes` lists the task (else `not-declared`);\n * 2. your app holds the `task:invoke` capability — declare it in\n * `immediately.run.capabilities` so the user can grant it (else `forbidden`).\n * Declaring the invoke does not imply the capability.\n *\n * ── `pick-file`: `roots` is required (SPACES_UI_SPEC §4.1) ───────────────────\n * ```ts\n * import { invokeTask, capDir, requestMount } from '@immediately-run/sdk';\n *\n * const mount = await requestMount(); // the user picks a space\n * // `invokeTask` returns `unknown` — name the result type, or the destructuring\n * // below does not compile.\n * const { root, path } = await invokeTask<{ root: number; path: string }>('pick-file', {\n * // `SandboxMount.id` is optional (absent on the primary repo mount) — fall back to\n * // `path`, which is always present and is what the host resolves against.\n * roots: [capDir({ mountId: mount.id ?? mount.path, relPath: 'boards' }, { mode: 'ro' })],\n * });\n * ```\n * - `roots` is a NON-EMPTY `DirCap[]` of directories you **already hold**. The result\n * names its target as `{ root, path }` where `root` INDEXES `params.roots`, so\n * `invokeTask('pick-file', {})` can never produce a valid result and is rejected.\n * There is no rootless \"pick from any of my spaces\" mode by design: enumerating the\n * user's spaces is the host's powerbox (`requestMount()`), and composing the two —\n * as above — is that flow. See SPACES_UI_SPEC R-SPACES-5/R-SPACES-12.\n * - Each `capDir` is attenuated against your own grant. **`{ mode: 'rw' }` over a space\n * the user granted `ro` is refused `forbidden`** — the commonest failure, because the\n * mount *was* granted and the path *is* inside it. Pass the mode you actually hold;\n * `ro` is right for a plain pick.\n * - The `requestMount()` grant is DURABLE and survives a cancelled pick: the user\n * consented to the mount in host chrome, separately from the pick (SPACES_UI_SPEC §4.1).\n * Reuse it for later picks rather than re-requesting.\n *\n * Off-host (plain `vite dev` — no host transport) it rejects with a plain\n * \"no host transport\" error: there is no host to resolve the task binding.\n */\nexport const invokeTask = async <R = unknown>(task: string, params: Record<string, unknown> = {}): Promise<R> => {\n const res = (await protocolRequest(SCHEMES[PROTOCOL_TASK], 'invoke', [{ task, params }])) as\n | { ok: true; data: R }\n | { ok: false; code?: string; message?: string }\n | undefined;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? `task '${task}' failed`) as Error & { code?: string };\n err.code = res?.code ?? 'unknown';\n throw err;\n }\n return res.data;\n};\n\n// ── the host-provided CAPTURE contracts (R3-425) ────────────────────────────\n\n/** Bytes captured by the host, as `capturePhoto()` / `captureAudio()` return them.\n * `bytes` is a transferable `ArrayBuffer` — write it to a space, decode it, upload\n * it. You never receive a `MediaStream` or a `MediaStreamTrack`, and that is not an\n * omission: a track cannot be transferred into an app frame at all\n * (`DataCloneError`), and the frame's opaque origin cannot open a device itself\n * (`getUserMedia` throws `SecurityError: Invalid security origin`). */\nexport interface CaptureResult {\n bytes: ArrayBuffer;\n /** e.g. `image/jpeg`, `audio/webm`. Chosen by the HOST, not by you. */\n mimeType: string;\n /** How long the device was open, in ms. */\n durationMs: number;\n}\n\n/** Optional hints for a capture. They deliberately name NOTHING — no device id, no\n * camera index — because the host chooses everything about how the capture is\n * performed. That is what lets the grant be a plain on/off instead of a per-call\n * target list the way `net:fetch` needs. */\nexport interface CaptureOptions {\n /** Which way the camera should face, if the device has a choice. A HINT: the host\n * may ignore it. Ignored for audio. */\n facing?: 'user' | 'environment';\n}\n\n/**\n * Take one photo, or record one audio clip, through the HOST's capture UI\n * (`BROWSER_CAPABILITIES_SPEC` §3 grade 1).\n *\n * The host opens the device at its own origin, draws the viewfinder, and hands you\n * the bytes when the user presses Done. **You are never in the loop while the device\n * is live** — that is the point of the design, not a limitation of it:\n *\n * - The capture UI is drawn by the host, so a user can trust it the way they trust\n * the sign-in dialog. Do not build a lookalike; imitating host chrome is spoofing.\n * - While the device is open the host shows a persistent \"camera on\" / \"microphone\n * on\" indicator in its own chrome, for the whole session. You cannot hide it and\n * should not try to.\n * - If the user cancels, this rejects `cancelled` and **nothing was recorded**. There\n * is no partial result — do not write error handling that hopes for one.\n *\n * ```ts\n * import { capturePhoto, requestMount, openFs } from '@immediately-run/sdk';\n *\n * try {\n * const { bytes, mimeType } = await capturePhoto({ facing: 'environment' });\n * const mount = await requestMount(); // the user picks a space to save into\n * const fs = openFs(mount); // writeFile is a METHOD on the MountFs\n * await fs.mkdir('photos', { recursive: true }); // writeFile does not create parents\n * await fs.writeFile(`photos/latest.${mimeType === 'image/png' ? 'png' : 'jpg'}`, new Uint8Array(bytes));\n * } catch (e) {\n * if ((e as { code?: string }).code === 'cancelled') return; // the user said no\n * throw e;\n * }\n * ```\n * (The extension follows `mimeType` because the HOST chooses the format — do not assume\n * JPEG. `openAppFs()` is the variant that writes to your own app space with no pick.)\n *\n * Two things must BOTH be true, exactly as for any other task:\n * 1. `immediately.run.invokes` lists `capture-photo` (or `capture-audio`);\n * 2. your app holds `task:invoke` **and** `device:camera` (or `device:microphone`)\n * — declare them in `immediately.run.capabilities` so the user can grant them.\n *\n * Rejects with `.code`: `cancelled` (the user dismissed the capture — nothing was\n * recorded), `forbidden` (you lack the capability; `message: 'browser-denied'` means\n * the BROWSER refused immediately.run itself, which your consent cannot fix),\n * `unavailable` (no such device on this machine, or it would not start),\n * `unsupported` (this host cannot capture), `not-declared`, `timeout`.\n *\n * *Zero-platform alternative, still worth knowing:* `<input type=\"file\"\n * accept=\"image/*\" capture=\"environment\">` opens the OS camera from inside the\n * sandbox (file choosers are not permission-gated). It needs no capability and no\n * host support; it also gives you no indicator and no host-drawn surface.\n */\nexport const capturePhoto = (options: CaptureOptions = {}): Promise<CaptureResult> =>\n invokeTask<CaptureResult>('capture-photo', { ...options });\n\n/** Record one audio clip through the host's capture UI. See {@link capturePhoto} —\n * every rule there applies verbatim, with `device:microphone` and `capture-audio`. */\nexport const captureAudio = (options: CaptureOptions = {}): Promise<CaptureResult> =>\n invokeTask<CaptureResult>('capture-audio', { ...options });\n\n// ── callee side ─────────────────────────────────────────────────────────────\n\n/** The params this app was invoked with as a task callee. */\nexport interface TaskInput {\n task: string;\n params: Record<string, unknown>;\n}\n\nlet latestInput: TaskInput | null = null;\nconst inputListeners = new Set<(i: TaskInput) => void>();\nlet inputListenerRegistered = false;\n\n// Register the `task-input` listener IF a host transport is reachable; otherwise do\n// nothing (and let the next call retry — the same pattern as pushChannel's `start`).\n// Split out so both the module-eval attempt below and the first-use call sites share\n// one idempotent path.\nconst ensureInputListener = (): void => {\n if (inputListenerRegistered) return;\n try {\n addListener(TASK_INPUT, (m: { task: string; params?: Record<string, unknown> }) => {\n latestInput = { task: m.task, params: m.params ?? {} };\n inputListeners.forEach((l) => l(latestInput!));\n });\n } catch {\n return; // off-host: the transport resolver threw — no host to listen on\n }\n inputListenerRegistered = true;\n};\n\n// The host delivers a `task-input` message to the callee's iframe right after it\n// mounts the overlay (the §5.7 \"params via the region's mount event\"). That wire\n// message is a plain one-shot host→app message with NO replay/poll counterpart —\n// the contract (`@immediately-run/sandbox-protocol/sdk`) marks replayable state as\n// \"push … polled with request-*\" (mounts, theme, auth-state, …) and `task-input`\n// is not one of them — so a listener registered only on first use could miss an\n// input delivered between module evaluation and the app's first render. Hence:\n// register EAGERLY when a host transport is already present at module eval\n// (on-host, byte-for-byte the pre-R3-421 behaviour), and lazily-on-first-use\n// otherwise, so importing this module off-host (plain `vite dev`) never throws.\nensureInputListener();\n\n/** The task params this app was invoked with, or null if it isn't a task callee.\n * Off-host (plain `vite dev`) this is always `null` — there is no host to invoke\n * this app as a callee. */\nexport const getTaskInput = (): TaskInput | null => {\n ensureInputListener();\n return latestInput;\n};\n\n/**\n * Is a host transport reachable from this realm at all?\n *\n * The R3-421 off-host no-op below must mean EXACTLY \"there is nobody to answer\" —\n * plain `vite dev`, node, jsdom. A blanket try/catch around the send meant it also\n * swallowed a genuine failure against a REAL host (`DataCloneError` because the\n * result holds a DOM node, a function or a live class instance, being the usual\n * one): the host was then never told the task finished, and the caller's\n * `invokeTask` hung to its deadline with no diagnostic anywhere. Absence is\n * therefore decided BEFORE the send, and the send itself is left to throw.\n */\nconst hostReachable = (): boolean => {\n try {\n transport();\n return true;\n } catch {\n return false; // no injected bundler bus and no §4 discovery global — off-host\n }\n};\n\n/**\n * Finish the task, returning a result to the caller. The host validates it against\n * the contract's result schema before resolving the caller (`invalid-params` on\n * violation), then tears down this overlay.\n *\n * `result` must be STRUCTURED-CLONEABLE — it crosses a frame boundary. A DOM node, a\n * function, a class instance with methods, a `MediaStreamTrack`: all `DataCloneError`.\n * **That throws**, deliberately and loudly: the alternative is a caller left hanging to\n * its `invokeTask` deadline while this app believes it answered.\n *\n * Off-host (plain `vite dev` — no host transport) this is a no-op: there is no caller\n * to answer. That case, and only that case, is silent.\n */\nexport const completeTask = (result: unknown): void => {\n if (!hostReachable()) return; // off-host: no caller to answer — documented no-op\n // On-host, a failure here is REAL and the caller is waiting on this exact message.\n sendMessage(TASK_COMPLETE, { result });\n};\n\n/** Abort the task; the caller's `invokeTask` rejects with `cancelled`.\n * Off-host (plain `vite dev` — no host transport) this is a no-op; on-host a failed\n * send throws rather than leaving the caller waiting, exactly as {@link completeTask}. */\nexport const cancelTask = (): void => {\n if (!hostReachable()) return; // off-host: no caller to answer — documented no-op\n sendMessage(TASK_CANCEL, {});\n};\n\n/** React hook: the task input for this callee, re-rendering when it arrives.\n * Off-host (plain `vite dev`) it stays `null` forever — render the non-callee\n * state rather than waiting on it. */\nexport const useTaskInput = (): TaskInput | null => {\n const [input, setInput] = useState<TaskInput | null>(getTaskInput);\n useEffect(() => {\n const l = (i: TaskInput) => setInput(i);\n inputListeners.add(l);\n if (latestInput) setInput(latestInput);\n return () => {\n inputListeners.delete(l);\n };\n }, []);\n return input;\n};\n"],"mappings":";AAqBA,SAAS,WAAW,gBAAgB;AACpC,SAAS,iBAAiB,aAAa,mBAAmB;AAC1D,SAAS,iBAAiB;AAC1B,SAAS,eAAe,aAAa,eAAe,kBAAkB;AACtE,SAAS,eAAe;AAmBjB,MAAM,UAAU,CAAC,KAA2C,UAA0C;AAAA,EAC3G,MAAM;AAAA,EACN,SAAS,IAAI;AAAA,EACb,SAAS,IAAI;AAAA,EACb,MAAM,KAAK;AACb;AAoBO,MAAM,SAAS,CAAC,KAA2C,UAAyC;AAAA,EACzG,MAAM;AAAA,EACN,SAAS,IAAI;AAAA,EACb,SAAS,IAAI;AAAA,EACb,MAAM,KAAK;AACb;AAiDO,MAAM,aAAa,OAAoB,MAAc,SAAkC,CAAC,MAAkB;AAC/G,QAAM,MAAO,MAAM,gBAAgB,QAAQ,aAAa,GAAG,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,CAAC;AAIvF,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,SAAS,IAAI,UAAU;AAC7D,QAAI,OAAO,KAAK,QAAQ;AACxB,UAAM;AAAA,EACR;AACA,SAAO,IAAI;AACb;AA6EO,MAAM,eAAe,CAAC,UAA0B,CAAC,MACtD,WAA0B,iBAAiB,EAAE,GAAG,QAAQ,CAAC;AAIpD,MAAM,eAAe,CAAC,UAA0B,CAAC,MACtD,WAA0B,iBAAiB,EAAE,GAAG,QAAQ,CAAC;AAU3D,IAAI,cAAgC;AACpC,MAAM,iBAAiB,oBAAI,IAA4B;AACvD,IAAI,0BAA0B;AAM9B,MAAM,sBAAsB,MAAY;AACtC,MAAI,wBAAyB;AAC7B,MAAI;AACF,gBAAY,YAAY,CAAC,MAA0D;AACjF,oBAAc,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,UAAU,CAAC,EAAE;AACrD,qBAAe,QAAQ,CAAC,MAAM,EAAE,WAAY,CAAC;AAAA,IAC/C,CAAC;AAAA,EACH,QAAQ;AACN;AAAA,EACF;AACA,4BAA0B;AAC5B;AAYA,oBAAoB;AAKb,MAAM,eAAe,MAAwB;AAClD,sBAAoB;AACpB,SAAO;AACT;AAaA,MAAM,gBAAgB,MAAe;AACnC,MAAI;AACF,cAAU;AACV,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAeO,MAAM,eAAe,CAAC,WAA0B;AACrD,MAAI,CAAC,cAAc,EAAG;AAEtB,cAAY,eAAe,EAAE,OAAO,CAAC;AACvC;AAKO,MAAM,aAAa,MAAY;AACpC,MAAI,CAAC,cAAc,EAAG;AACtB,cAAY,aAAa,CAAC,CAAC;AAC7B;AAKO,MAAM,eAAe,MAAwB;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA2B,YAAY;AACjE,YAAU,MAAM;AACd,UAAM,IAAI,CAAC,MAAiB,SAAS,CAAC;AACtC,mBAAe,IAAI,CAAC;AACpB,QAAI,YAAa,UAAS,WAAW;AACrC,WAAO,MAAM;AACX,qBAAe,OAAO,CAAC;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,CAAC;AACL,SAAO;AACT;","names":[]}
package/dist/version.cjs CHANGED
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  SDK_VERSION: () => SDK_VERSION
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const SDK_VERSION = "0.57.1";
24
+ const SDK_VERSION = "0.57.4";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  SDK_VERSION
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// GENERATED by scripts/gen-version.mjs from package.json — do not edit by hand.\n// Regenerated on every build (prebuild); kept honest by version.test.ts.\n\n/** This SDK's package version, baked from package.json at build (SP2-6). */\nexport const SDK_VERSION = '0.57.1';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,MAAM,cAAc;","names":[]}
1
+ {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// GENERATED by scripts/gen-version.mjs from package.json — do not edit by hand.\n// Regenerated on every build (prebuild); kept honest by version.test.ts.\n\n/** This SDK's package version, baked from package.json at build (SP2-6). */\nexport const SDK_VERSION = '0.57.4';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,MAAM,cAAc;","names":[]}
@@ -1,4 +1,4 @@
1
1
  /** This SDK's package version, baked from package.json at build (SP2-6). */
2
- declare const SDK_VERSION = "0.57.1";
2
+ declare const SDK_VERSION = "0.57.4";
3
3
 
4
4
  export { SDK_VERSION };
package/dist/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /** This SDK's package version, baked from package.json at build (SP2-6). */
2
- declare const SDK_VERSION = "0.57.1";
2
+ declare const SDK_VERSION = "0.57.4";
3
3
 
4
4
  export { SDK_VERSION };
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./chunk-VHAA22YE.js";
2
- const SDK_VERSION = "0.57.1";
2
+ const SDK_VERSION = "0.57.4";
3
3
  export {
4
4
  SDK_VERSION
5
5
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// GENERATED by scripts/gen-version.mjs from package.json — do not edit by hand.\n// Regenerated on every build (prebuild); kept honest by version.test.ts.\n\n/** This SDK's package version, baked from package.json at build (SP2-6). */\nexport const SDK_VERSION = '0.57.1';\n"],"mappings":";AAIO,MAAM,cAAc;","names":[]}
1
+ {"version":3,"sources":["../src/version.ts"],"sourcesContent":["// GENERATED by scripts/gen-version.mjs from package.json — do not edit by hand.\n// Regenerated on every build (prebuild); kept honest by version.test.ts.\n\n/** This SDK's package version, baked from package.json at build (SP2-6). */\nexport const SDK_VERSION = '0.57.4';\n"],"mappings":";AAIO,MAAM,cAAc;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immediately-run/sdk",
3
- "version": "0.57.1",
3
+ "version": "0.57.4",
4
4
  "description": "Runtime SDK for code executing inside an immediately.run sandbox.",
5
5
  "license": "MIT",
6
6
  "repository": "github:immediately-run/immediately-run-sdk",
@@ -39,11 +39,12 @@
39
39
  "api:update": "node scripts/check-api-stability.mjs --update",
40
40
  "check:pins": "node scripts/check-dependency-pins.mjs --self-test && node scripts/check-dependency-pins.mjs",
41
41
  "check:publish-version": "node scripts/check-publish-version.mjs --self-test && node scripts/check-publish-version.mjs",
42
- "verify": "npm run check:pins && npm run check:publish-version && npm run format:check && npm run check:circular && npm run check:bundler:selftest && npm run check:bundler && npm run build && npm test && npm run test:safe-content && npm run test:metadata-e2e && npm run api:selftest && npm run api:check && npm run compat:selftest && npm run compat:previous && npm run protocol:check && npm run protocol:selftest && npm run check:ambient:selftest && npm run check:ambient && npm run check:selfhost:selftest && npm run check:selfhost && npm run verify:codegen-parity",
42
+ "verify": "npm run check:pins && npm run check:publish-version && npm run format:check && npm run check:circular && npm run check:bundler:selftest && npm run check:bundler && npm run build && npm test && npm run test:safe-content && npm run test:metadata-e2e && npm run test:subpath-imports && npm run api:selftest && npm run api:check && npm run compat:selftest && npm run compat:previous && npm run protocol:check && npm run protocol:selftest && npm run check:ambient:selftest && npm run check:ambient && npm run check:selfhost:selftest && npm run check:selfhost && npm run verify:codegen-parity",
43
43
  "docs": "typedoc --json docs/api.json && node scripts/gen-llms.mjs",
44
44
  "prepublishOnly": "npm run check:circular && npm run build && npm run api:selftest && npm run api:check",
45
45
  "test:safe-content": "node scripts/build-safecontent-e2e.mjs && node --test test/safeContent.e2e.mjs",
46
46
  "test:metadata-e2e": "node --test test/metadataHooks.e2e.mjs",
47
+ "test:subpath-imports": "node --test test/subpathImports.e2e.mjs",
47
48
  "protocol:selftest": "node scripts/check-protocol-snapshot.mjs --self-test",
48
49
  "compat:previous": "node scripts/check-previous-sdk-compat.mjs",
49
50
  "compat:selftest": "node scripts/check-previous-sdk-compat.mjs --self-test",
@@ -60,11 +61,11 @@
60
61
  "react-dom": "^19.0.0"
61
62
  },
62
63
  "dependencies": {
64
+ "@immediately-run/mdx-plugins": "0.5.0",
63
65
  "@immediately-run/platform-constants": "0.2.0",
64
- "@immediately-run/sandbox-protocol": "0.7.1",
65
- "react-error-boundary": "^6.0.0",
66
66
  "@immediately-run/safe-content": "0.1.0",
67
- "@immediately-run/mdx-plugins": "0.5.0"
67
+ "@immediately-run/sandbox-protocol": "0.7.6",
68
+ "react-error-boundary": "^6.0.0"
68
69
  },
69
70
  "devDependencies": {
70
71
  "@immediately-run/prettier-config": "0.1.0",