@immediately-run/sdk 0.53.0 → 0.55.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/dist/editor.cjs CHANGED
@@ -40,7 +40,7 @@ const editorRequest = async (method, arg) => {
40
40
  throw err;
41
41
  }
42
42
  };
43
- const openInEditor = (path) => editorRequest("open", { path });
43
+ const openInEditor = (path, selection) => editorRequest("open", selection ? { path, selection } : { path });
44
44
  const requestEdit = (target) => editorRequest("requestEdit", target ? { ...target } : {});
45
45
  const setActiveFile = (path) => editorRequest("setActive", { path });
46
46
  const closeFile = (path) => editorRequest("close", { path });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/editor.ts"],"sourcesContent":["import { protocolRequest } from './sandboxUtils';\nimport { SCHEMES } from './protocolSchemes';\nimport { PROTOCOL_EDITOR } from './generated/protocol';\n\n/**\n * Open a working-tree file in the immediately.run host editor (UI_AS_APPS_SPEC §4 —\n * the file explorer's click-to-open). This is an INTENT: the app asks, the HOST\n * validates the path and drives the CodeMirror editor — the editor itself stays\n * host-owned (§2 recursion boundary), so an app can never own or script it beyond\n * \"please show this file\".\n *\n * Requires the elevated `editor:open` capability — a previewed app does not hold it\n * (it must not move the host's focus), so only a system app whose binding grants it\n * (the file explorer) can call this; anyone else is refused at the gate.\n */\n\n/** An error from {@link openInEditor}, carrying a machine-readable `.code`. */\nexport interface EditorOpenError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:open`\n | 'not-found' // no such file in the live working tree (the host never creates)\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session to open files in\n | 'unknown';\n}\n\ntype EditorResult = { ok: true; data: unknown } | { ok: false; code: string; message: string };\n\nconst editorRequest = async (method: string, arg: Record<string, unknown>): Promise<void> => {\n const res = (await protocolRequest(SCHEMES[PROTOCOL_EDITOR], method, [arg])) as EditorResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? `editor ${method} failed`) as EditorWriteError;\n err.code = (res?.code as EditorWriteError['code']) ?? 'unknown';\n throw err;\n }\n};\n\n/**\n * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`\n * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects\n * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this\n * app may not open files.\n */\nexport const openInEditor = (path: string): Promise<void> => editorRequest('open', { path });\n\n/**\n * Where to land when entering the edit experience (EDITOR_FIRST_EDITING_SPEC §6\n * Delta A). v1 supports only an optional repo-relative `path` in the CURRENT repo\n * (self-scoped — the app you are already running; the host navigates within the\n * current route, never to another repo). A URI or `..` path is refused\n * `invalid-params`. Editing a file in one of your *mounts* (a space) is the\n * `edit-file` task, not this.\n */\nexport interface EditTarget {\n /** A repo-relative working-tree path in the current repo to focus once in edit\n * mode (e.g. `src/App.tsx`). Omit to edit the current route's entry. */\n path?: string;\n}\n\n/** An error from {@link requestEdit}, carrying a machine-readable `.code`. */\nexport interface RequestEditError extends Error {\n code:\n | 'read-only' // editing isn't possible here (a `ro` mount / anonymous viewer) — HIDE the affordance\n | 'forbidden' // the host refuses (e.g. a cross-repo / out-of-scope target)\n | 'invalid-params' // the target was malformed (URI / `..` / a non-current repo)\n | 'no-target' // there is no host editor session to enter\n | 'unknown';\n}\n\n/**\n * Ask the host to enter the **edit experience** for the app you are running —\n * the present→edit transition (`/present/...` → `/edit/...`) an app cannot make\n * itself. This is an INTENT (§2 recursion boundary): the app asks, the HOST\n * performs the visible, user-observable navigation and draws all editor chrome;\n * the app never navigates or paints chrome.\n *\n * Use it to offer an \"edit this\" affordance from a run/present-mode app that opens\n * the app's own source in the platform editor — instead of shipping a bespoke\n * in-app editor (EDITOR_FIRST_EDITING_SPEC §1).\n *\n * Resolves once the host begins the transition; rejects with a\n * {@link RequestEditError} (`.code`). Treat `read-only`/`forbidden` as \"editing is\n * not available — hide the affordance,\" never as an error to surface to the user.\n */\nexport const requestEdit = (target?: EditTarget): Promise<void> =>\n editorRequest('requestEdit', target ? { ...target } : {});\n\n// ---------------------------------------------------------------------------\n// Editor SESSION management (EDITOR_AS_APP_SPEC §5.1; editor-as-app plan Phase\n// 03). Unlike `openInEditor` (the explorer's cross-app intent, `editor:open`),\n// these drive the editor's OWN open-tab set + active file, so they are gated by\n// the editor app's `editor:document` capability — a file explorer holding only\n// `editor:open` cannot call them. The host re-validates the path against the live\n// working tree; the editor itself stays host-owned (§2 recursion boundary).\n// ---------------------------------------------------------------------------\n\n/** An error from a session intent ({@link setActiveFile} / {@link closeFile}),\n * carrying a machine-readable `.code`. */\nexport interface EditorSessionError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:document`\n | 'not-found' // no such file in the live working tree\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Switch the editor's active file to `path`, opening it (adding a tab) if it is\n * not already open — native `setActiveFile` parity. Rejects with an\n * {@link EditorSessionError} (`.code`) if the path is missing/invalid or this app\n * lacks `editor:document`. */\nexport const setActiveFile = (path: string): Promise<void> => editorRequest('setActive', { path });\n\n/** Close `path`'s tab in the editor (remove it from the open set) — native\n * `closeFile` parity. Rejects with an {@link EditorSessionError} (`.code`). */\nexport const closeFile = (path: string): Promise<void> => editorRequest('close', { path });\n\n// ---------------------------------------------------------------------------\n// Working-tree mutation (UI_AS_APPS_SPEC §4 / EDITOR_AS_APP_SPEC §5.2). The file\n// explorer NAMES a working-tree path and the HOST performs the COW write (and\n// refreshes the preview) — the app holds no write port; it asks. Gated by the\n// first-party `editor:write` capability, so only a first-party chrome app (the\n// file explorer) can call these; anyone else is refused at the gate.\n// ---------------------------------------------------------------------------\n\n/** An error from a working-tree mutation, carrying a machine-readable `.code`. */\nexport interface EditorWriteError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:write` (first-party-only)\n | 'not-found' // the target file/folder does not exist (delete/rename)\n | 'exists' // the target already exists (create/rename would clobber)\n | 'protected' // the host refuses to delete this file (e.g. package.json)\n | 'too-large' // an upload exceeds the host's size limit\n | 'invalid-params' // a path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Create an empty working-tree file at `path` and open it. Rejects `exists` if a\n * file is already there. */\nexport const createFile = (path: string): Promise<void> => editorRequest('createFile', { path });\n\n/** Create a working-tree folder at `path` (materialised with a `.gitkeep`). */\nexport const createFolder = (path: string): Promise<void> => editorRequest('createFolder', { path });\n\n/** Delete a working-tree file, or a folder and everything under it. Rejects\n * `protected` for files the host won't remove, `not-found` if absent. */\nexport const deleteEntry = (path: string): Promise<void> => editorRequest('deleteEntry', { path });\n\n/** Rename/move a working-tree file from `from` to `to`. Rejects `exists` if `to`\n * is taken, `not-found` if `from` is absent. */\nexport const renameEntry = (from: string, to: string): Promise<void> => editorRequest('rename', { from, to });\n\n/** Upload binary/text `bytes` to a working-tree file at `path`. Rejects\n * `too-large` past the host's size limit. The bytes are transferred (zero-copy). */\nexport const uploadFile = (path: string, bytes: Uint8Array): Promise<void> => editorRequest('upload', { path, bytes });\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAgC;AAChC,6BAAwB;AACxB,sBAAgC;AA0BhC,MAAM,gBAAgB,OAAO,QAAgB,QAAgD;AAC3F,QAAM,MAAO,UAAM,qCAAgB,+BAAQ,+BAAe,GAAG,QAAQ,CAAC,GAAG,CAAC;AAC1E,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU,MAAM,SAAS;AAC/D,QAAI,OAAQ,KAAK,QAAqC;AACtD,UAAM;AAAA,EACR;AACF;AAQO,MAAM,eAAe,CAAC,SAAgC,cAAc,QAAQ,EAAE,KAAK,CAAC;AAyCpF,MAAM,cAAc,CAAC,WAC1B,cAAc,eAAe,SAAS,EAAE,GAAG,OAAO,IAAI,CAAC,CAAC;AA0BnD,MAAM,gBAAgB,CAAC,SAAgC,cAAc,aAAa,EAAE,KAAK,CAAC;AAI1F,MAAM,YAAY,CAAC,SAAgC,cAAc,SAAS,EAAE,KAAK,CAAC;AAyBlF,MAAM,aAAa,CAAC,SAAgC,cAAc,cAAc,EAAE,KAAK,CAAC;AAGxF,MAAM,eAAe,CAAC,SAAgC,cAAc,gBAAgB,EAAE,KAAK,CAAC;AAI5F,MAAM,cAAc,CAAC,SAAgC,cAAc,eAAe,EAAE,KAAK,CAAC;AAI1F,MAAM,cAAc,CAAC,MAAc,OAA8B,cAAc,UAAU,EAAE,MAAM,GAAG,CAAC;AAIrG,MAAM,aAAa,CAAC,MAAc,UAAqC,cAAc,UAAU,EAAE,MAAM,MAAM,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/editor.ts"],"sourcesContent":["import { protocolRequest } from './sandboxUtils';\nimport { SCHEMES } from './protocolSchemes';\nimport { PROTOCOL_EDITOR } from './generated/protocol';\n\n/**\n * Open a working-tree file in the immediately.run host editor (UI_AS_APPS_SPEC §4 —\n * the file explorer's click-to-open). This is an INTENT: the app asks, the HOST\n * validates the path and drives the CodeMirror editor — the editor itself stays\n * host-owned (§2 recursion boundary), so an app can never own or script it beyond\n * \"please show this file\".\n *\n * Requires the elevated `editor:open` capability — a previewed app does not hold it\n * (it must not move the host's focus), so only a system app whose binding grants it\n * (the file explorer) can call this; anyone else is refused at the gate.\n */\n\n/** An error from {@link openInEditor}, carrying a machine-readable `.code`. */\nexport interface EditorOpenError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:open`\n | 'not-found' // no such file in the live working tree (the host never creates)\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session to open files in\n | 'unknown';\n}\n\ntype EditorResult = { ok: true; data: unknown } | { ok: false; code: string; message: string };\n\nconst editorRequest = async (method: string, arg: Record<string, unknown>): Promise<void> => {\n const res = (await protocolRequest(SCHEMES[PROTOCOL_EDITOR], method, [arg])) as EditorResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? `editor ${method} failed`) as EditorWriteError;\n err.code = (res?.code as EditorWriteError['code']) ?? 'unknown';\n throw err;\n }\n};\n\n/** Where in a file to land when opening it (R3-388). 1-indexed `line`, matching every\n * diagnostic producer that feeds it (`tsc`, `eslint`, `BuildError`) and both VS Code\n * and IntelliJ. A `line` past end-of-file CLAMPS to the last line rather than\n * erroring — a diagnostic outlives the edit that shortened the file, and landing\n * close beats refusing to navigate. */\nexport interface EditorSelection {\n line: number;\n column?: number;\n}\n\n/**\n * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`\n * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects\n * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this\n * app may not open files.\n *\n * Pass `selection` to land the caret on a specific line — what a problems list needs\n * to make a diagnostic clickable. It widens nothing: a selection says where to look\n * inside a file the caller could already open, and the capability is unchanged\n * (`editor:open`).\n *\n * Older hosts ignore the extra field and open the file at its existing position, so\n * a caller may pass it unconditionally.\n */\nexport const openInEditor = (path: string, selection?: EditorSelection): Promise<void> =>\n editorRequest('open', selection ? { path, selection } : { path });\n\n/**\n * Where to land when entering the edit experience (EDITOR_FIRST_EDITING_SPEC §6\n * Delta A). v1 supports only an optional repo-relative `path` in the CURRENT repo\n * (self-scoped — the app you are already running; the host navigates within the\n * current route, never to another repo). A URI or `..` path is refused\n * `invalid-params`. Editing a file in one of your *mounts* (a space) is the\n * `edit-file` task, not this.\n */\nexport interface EditTarget {\n /** A repo-relative working-tree path in the current repo to focus once in edit\n * mode (e.g. `src/App.tsx`). Omit to edit the current route's entry. */\n path?: string;\n}\n\n/** An error from {@link requestEdit}, carrying a machine-readable `.code`. */\nexport interface RequestEditError extends Error {\n code:\n | 'read-only' // editing isn't possible here (a `ro` mount / anonymous viewer) — HIDE the affordance\n | 'forbidden' // the host refuses (e.g. a cross-repo / out-of-scope target)\n | 'invalid-params' // the target was malformed (URI / `..` / a non-current repo)\n | 'no-target' // there is no host editor session to enter\n | 'unknown';\n}\n\n/**\n * Ask the host to enter the **edit experience** for the app you are running —\n * the present→edit transition (`/present/...` → `/edit/...`) an app cannot make\n * itself. This is an INTENT (§2 recursion boundary): the app asks, the HOST\n * performs the visible, user-observable navigation and draws all editor chrome;\n * the app never navigates or paints chrome.\n *\n * Use it to offer an \"edit this\" affordance from a run/present-mode app that opens\n * the app's own source in the platform editor — instead of shipping a bespoke\n * in-app editor (EDITOR_FIRST_EDITING_SPEC §1).\n *\n * Resolves once the host begins the transition; rejects with a\n * {@link RequestEditError} (`.code`). Treat `read-only`/`forbidden` as \"editing is\n * not available — hide the affordance,\" never as an error to surface to the user.\n */\nexport const requestEdit = (target?: EditTarget): Promise<void> =>\n editorRequest('requestEdit', target ? { ...target } : {});\n\n// ---------------------------------------------------------------------------\n// Editor SESSION management (EDITOR_AS_APP_SPEC §5.1; editor-as-app plan Phase\n// 03). Unlike `openInEditor` (the explorer's cross-app intent, `editor:open`),\n// these drive the editor's OWN open-tab set + active file, so they are gated by\n// the editor app's `editor:document` capability — a file explorer holding only\n// `editor:open` cannot call them. The host re-validates the path against the live\n// working tree; the editor itself stays host-owned (§2 recursion boundary).\n// ---------------------------------------------------------------------------\n\n/** An error from a session intent ({@link setActiveFile} / {@link closeFile}),\n * carrying a machine-readable `.code`. */\nexport interface EditorSessionError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:document`\n | 'not-found' // no such file in the live working tree\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Switch the editor's active file to `path`, opening it (adding a tab) if it is\n * not already open — native `setActiveFile` parity. Rejects with an\n * {@link EditorSessionError} (`.code`) if the path is missing/invalid or this app\n * lacks `editor:document`. */\nexport const setActiveFile = (path: string): Promise<void> => editorRequest('setActive', { path });\n\n/** Close `path`'s tab in the editor (remove it from the open set) — native\n * `closeFile` parity. Rejects with an {@link EditorSessionError} (`.code`). */\nexport const closeFile = (path: string): Promise<void> => editorRequest('close', { path });\n\n// ---------------------------------------------------------------------------\n// Working-tree mutation (UI_AS_APPS_SPEC §4 / EDITOR_AS_APP_SPEC §5.2). The file\n// explorer NAMES a working-tree path and the HOST performs the COW write (and\n// refreshes the preview) — the app holds no write port; it asks. Gated by the\n// first-party `editor:write` capability, so only a first-party chrome app (the\n// file explorer) can call these; anyone else is refused at the gate.\n// ---------------------------------------------------------------------------\n\n/** An error from a working-tree mutation, carrying a machine-readable `.code`. */\nexport interface EditorWriteError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:write` (first-party-only)\n | 'not-found' // the target file/folder does not exist (delete/rename)\n | 'exists' // the target already exists (create/rename would clobber)\n | 'protected' // the host refuses to delete this file (e.g. package.json)\n | 'too-large' // an upload exceeds the host's size limit\n | 'invalid-params' // a path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Create an empty working-tree file at `path` and open it. Rejects `exists` if a\n * file is already there. */\nexport const createFile = (path: string): Promise<void> => editorRequest('createFile', { path });\n\n/** Create a working-tree folder at `path` (materialised with a `.gitkeep`). */\nexport const createFolder = (path: string): Promise<void> => editorRequest('createFolder', { path });\n\n/** Delete a working-tree file, or a folder and everything under it. Rejects\n * `protected` for files the host won't remove, `not-found` if absent. */\nexport const deleteEntry = (path: string): Promise<void> => editorRequest('deleteEntry', { path });\n\n/** Rename/move a working-tree file from `from` to `to`. Rejects `exists` if `to`\n * is taken, `not-found` if `from` is absent. */\nexport const renameEntry = (from: string, to: string): Promise<void> => editorRequest('rename', { from, to });\n\n/** Upload binary/text `bytes` to a working-tree file at `path`. Rejects\n * `too-large` past the host's size limit. The bytes are transferred (zero-copy). */\nexport const uploadFile = (path: string, bytes: Uint8Array): Promise<void> => editorRequest('upload', { path, bytes });\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAgC;AAChC,6BAAwB;AACxB,sBAAgC;AA0BhC,MAAM,gBAAgB,OAAO,QAAgB,QAAgD;AAC3F,QAAM,MAAO,UAAM,qCAAgB,+BAAQ,+BAAe,GAAG,QAAQ,CAAC,GAAG,CAAC;AAC1E,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU,MAAM,SAAS;AAC/D,QAAI,OAAQ,KAAK,QAAqC;AACtD,UAAM;AAAA,EACR;AACF;AA0BO,MAAM,eAAe,CAAC,MAAc,cACzC,cAAc,QAAQ,YAAY,EAAE,MAAM,UAAU,IAAI,EAAE,KAAK,CAAC;AAyC3D,MAAM,cAAc,CAAC,WAC1B,cAAc,eAAe,SAAS,EAAE,GAAG,OAAO,IAAI,CAAC,CAAC;AA0BnD,MAAM,gBAAgB,CAAC,SAAgC,cAAc,aAAa,EAAE,KAAK,CAAC;AAI1F,MAAM,YAAY,CAAC,SAAgC,cAAc,SAAS,EAAE,KAAK,CAAC;AAyBlF,MAAM,aAAa,CAAC,SAAgC,cAAc,cAAc,EAAE,KAAK,CAAC;AAGxF,MAAM,eAAe,CAAC,SAAgC,cAAc,gBAAgB,EAAE,KAAK,CAAC;AAI5F,MAAM,cAAc,CAAC,SAAgC,cAAc,eAAe,EAAE,KAAK,CAAC;AAI1F,MAAM,cAAc,CAAC,MAAc,OAA8B,cAAc,UAAU,EAAE,MAAM,GAAG,CAAC;AAIrG,MAAM,aAAa,CAAC,MAAc,UAAqC,cAAc,UAAU,EAAE,MAAM,MAAM,CAAC;","names":[]}
package/dist/editor.d.cts CHANGED
@@ -13,13 +13,30 @@
13
13
  interface EditorOpenError extends Error {
14
14
  code: 'forbidden' | 'not-found' | 'invalid-params' | 'no-target' | 'unknown';
15
15
  }
16
+ /** Where in a file to land when opening it (R3-388). 1-indexed `line`, matching every
17
+ * diagnostic producer that feeds it (`tsc`, `eslint`, `BuildError`) and both VS Code
18
+ * and IntelliJ. A `line` past end-of-file CLAMPS to the last line rather than
19
+ * erroring — a diagnostic outlives the edit that shortened the file, and landing
20
+ * close beats refusing to navigate. */
21
+ interface EditorSelection {
22
+ line: number;
23
+ column?: number;
24
+ }
16
25
  /**
17
26
  * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`
18
27
  * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects
19
28
  * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this
20
29
  * app may not open files.
30
+ *
31
+ * Pass `selection` to land the caret on a specific line — what a problems list needs
32
+ * to make a diagnostic clickable. It widens nothing: a selection says where to look
33
+ * inside a file the caller could already open, and the capability is unchanged
34
+ * (`editor:open`).
35
+ *
36
+ * Older hosts ignore the extra field and open the file at its existing position, so
37
+ * a caller may pass it unconditionally.
21
38
  */
22
- declare const openInEditor: (path: string) => Promise<void>;
39
+ declare const openInEditor: (path: string, selection?: EditorSelection) => Promise<void>;
23
40
  /**
24
41
  * Where to land when entering the edit experience (EDITOR_FIRST_EDITING_SPEC §6
25
42
  * Delta A). v1 supports only an optional repo-relative `path` in the CURRENT repo
@@ -85,4 +102,4 @@ declare const renameEntry: (from: string, to: string) => Promise<void>;
85
102
  * `too-large` past the host's size limit. The bytes are transferred (zero-copy). */
86
103
  declare const uploadFile: (path: string, bytes: Uint8Array) => Promise<void>;
87
104
 
88
- export { type EditTarget, type EditorOpenError, type EditorSessionError, type EditorWriteError, type RequestEditError, closeFile, createFile, createFolder, deleteEntry, openInEditor, renameEntry, requestEdit, setActiveFile, uploadFile };
105
+ export { type EditTarget, type EditorOpenError, type EditorSelection, type EditorSessionError, type EditorWriteError, type RequestEditError, closeFile, createFile, createFolder, deleteEntry, openInEditor, renameEntry, requestEdit, setActiveFile, uploadFile };
package/dist/editor.d.ts CHANGED
@@ -13,13 +13,30 @@
13
13
  interface EditorOpenError extends Error {
14
14
  code: 'forbidden' | 'not-found' | 'invalid-params' | 'no-target' | 'unknown';
15
15
  }
16
+ /** Where in a file to land when opening it (R3-388). 1-indexed `line`, matching every
17
+ * diagnostic producer that feeds it (`tsc`, `eslint`, `BuildError`) and both VS Code
18
+ * and IntelliJ. A `line` past end-of-file CLAMPS to the last line rather than
19
+ * erroring — a diagnostic outlives the edit that shortened the file, and landing
20
+ * close beats refusing to navigate. */
21
+ interface EditorSelection {
22
+ line: number;
23
+ column?: number;
24
+ }
16
25
  /**
17
26
  * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`
18
27
  * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects
19
28
  * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this
20
29
  * app may not open files.
30
+ *
31
+ * Pass `selection` to land the caret on a specific line — what a problems list needs
32
+ * to make a diagnostic clickable. It widens nothing: a selection says where to look
33
+ * inside a file the caller could already open, and the capability is unchanged
34
+ * (`editor:open`).
35
+ *
36
+ * Older hosts ignore the extra field and open the file at its existing position, so
37
+ * a caller may pass it unconditionally.
21
38
  */
22
- declare const openInEditor: (path: string) => Promise<void>;
39
+ declare const openInEditor: (path: string, selection?: EditorSelection) => Promise<void>;
23
40
  /**
24
41
  * Where to land when entering the edit experience (EDITOR_FIRST_EDITING_SPEC §6
25
42
  * Delta A). v1 supports only an optional repo-relative `path` in the CURRENT repo
@@ -85,4 +102,4 @@ declare const renameEntry: (from: string, to: string) => Promise<void>;
85
102
  * `too-large` past the host's size limit. The bytes are transferred (zero-copy). */
86
103
  declare const uploadFile: (path: string, bytes: Uint8Array) => Promise<void>;
87
104
 
88
- export { type EditTarget, type EditorOpenError, type EditorSessionError, type EditorWriteError, type RequestEditError, closeFile, createFile, createFolder, deleteEntry, openInEditor, renameEntry, requestEdit, setActiveFile, uploadFile };
105
+ export { type EditTarget, type EditorOpenError, type EditorSelection, type EditorSessionError, type EditorWriteError, type RequestEditError, closeFile, createFile, createFolder, deleteEntry, openInEditor, renameEntry, requestEdit, setActiveFile, uploadFile };
package/dist/editor.js CHANGED
@@ -10,7 +10,7 @@ const editorRequest = async (method, arg) => {
10
10
  throw err;
11
11
  }
12
12
  };
13
- const openInEditor = (path) => editorRequest("open", { path });
13
+ const openInEditor = (path, selection) => editorRequest("open", selection ? { path, selection } : { path });
14
14
  const requestEdit = (target) => editorRequest("requestEdit", target ? { ...target } : {});
15
15
  const setActiveFile = (path) => editorRequest("setActive", { path });
16
16
  const closeFile = (path) => editorRequest("close", { path });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/editor.ts"],"sourcesContent":["import { protocolRequest } from './sandboxUtils';\nimport { SCHEMES } from './protocolSchemes';\nimport { PROTOCOL_EDITOR } from './generated/protocol';\n\n/**\n * Open a working-tree file in the immediately.run host editor (UI_AS_APPS_SPEC §4 —\n * the file explorer's click-to-open). This is an INTENT: the app asks, the HOST\n * validates the path and drives the CodeMirror editor — the editor itself stays\n * host-owned (§2 recursion boundary), so an app can never own or script it beyond\n * \"please show this file\".\n *\n * Requires the elevated `editor:open` capability — a previewed app does not hold it\n * (it must not move the host's focus), so only a system app whose binding grants it\n * (the file explorer) can call this; anyone else is refused at the gate.\n */\n\n/** An error from {@link openInEditor}, carrying a machine-readable `.code`. */\nexport interface EditorOpenError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:open`\n | 'not-found' // no such file in the live working tree (the host never creates)\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session to open files in\n | 'unknown';\n}\n\ntype EditorResult = { ok: true; data: unknown } | { ok: false; code: string; message: string };\n\nconst editorRequest = async (method: string, arg: Record<string, unknown>): Promise<void> => {\n const res = (await protocolRequest(SCHEMES[PROTOCOL_EDITOR], method, [arg])) as EditorResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? `editor ${method} failed`) as EditorWriteError;\n err.code = (res?.code as EditorWriteError['code']) ?? 'unknown';\n throw err;\n }\n};\n\n/**\n * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`\n * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects\n * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this\n * app may not open files.\n */\nexport const openInEditor = (path: string): Promise<void> => editorRequest('open', { path });\n\n/**\n * Where to land when entering the edit experience (EDITOR_FIRST_EDITING_SPEC §6\n * Delta A). v1 supports only an optional repo-relative `path` in the CURRENT repo\n * (self-scoped — the app you are already running; the host navigates within the\n * current route, never to another repo). A URI or `..` path is refused\n * `invalid-params`. Editing a file in one of your *mounts* (a space) is the\n * `edit-file` task, not this.\n */\nexport interface EditTarget {\n /** A repo-relative working-tree path in the current repo to focus once in edit\n * mode (e.g. `src/App.tsx`). Omit to edit the current route's entry. */\n path?: string;\n}\n\n/** An error from {@link requestEdit}, carrying a machine-readable `.code`. */\nexport interface RequestEditError extends Error {\n code:\n | 'read-only' // editing isn't possible here (a `ro` mount / anonymous viewer) — HIDE the affordance\n | 'forbidden' // the host refuses (e.g. a cross-repo / out-of-scope target)\n | 'invalid-params' // the target was malformed (URI / `..` / a non-current repo)\n | 'no-target' // there is no host editor session to enter\n | 'unknown';\n}\n\n/**\n * Ask the host to enter the **edit experience** for the app you are running —\n * the present→edit transition (`/present/...` → `/edit/...`) an app cannot make\n * itself. This is an INTENT (§2 recursion boundary): the app asks, the HOST\n * performs the visible, user-observable navigation and draws all editor chrome;\n * the app never navigates or paints chrome.\n *\n * Use it to offer an \"edit this\" affordance from a run/present-mode app that opens\n * the app's own source in the platform editor — instead of shipping a bespoke\n * in-app editor (EDITOR_FIRST_EDITING_SPEC §1).\n *\n * Resolves once the host begins the transition; rejects with a\n * {@link RequestEditError} (`.code`). Treat `read-only`/`forbidden` as \"editing is\n * not available — hide the affordance,\" never as an error to surface to the user.\n */\nexport const requestEdit = (target?: EditTarget): Promise<void> =>\n editorRequest('requestEdit', target ? { ...target } : {});\n\n// ---------------------------------------------------------------------------\n// Editor SESSION management (EDITOR_AS_APP_SPEC §5.1; editor-as-app plan Phase\n// 03). Unlike `openInEditor` (the explorer's cross-app intent, `editor:open`),\n// these drive the editor's OWN open-tab set + active file, so they are gated by\n// the editor app's `editor:document` capability — a file explorer holding only\n// `editor:open` cannot call them. The host re-validates the path against the live\n// working tree; the editor itself stays host-owned (§2 recursion boundary).\n// ---------------------------------------------------------------------------\n\n/** An error from a session intent ({@link setActiveFile} / {@link closeFile}),\n * carrying a machine-readable `.code`. */\nexport interface EditorSessionError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:document`\n | 'not-found' // no such file in the live working tree\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Switch the editor's active file to `path`, opening it (adding a tab) if it is\n * not already open — native `setActiveFile` parity. Rejects with an\n * {@link EditorSessionError} (`.code`) if the path is missing/invalid or this app\n * lacks `editor:document`. */\nexport const setActiveFile = (path: string): Promise<void> => editorRequest('setActive', { path });\n\n/** Close `path`'s tab in the editor (remove it from the open set) — native\n * `closeFile` parity. Rejects with an {@link EditorSessionError} (`.code`). */\nexport const closeFile = (path: string): Promise<void> => editorRequest('close', { path });\n\n// ---------------------------------------------------------------------------\n// Working-tree mutation (UI_AS_APPS_SPEC §4 / EDITOR_AS_APP_SPEC §5.2). The file\n// explorer NAMES a working-tree path and the HOST performs the COW write (and\n// refreshes the preview) — the app holds no write port; it asks. Gated by the\n// first-party `editor:write` capability, so only a first-party chrome app (the\n// file explorer) can call these; anyone else is refused at the gate.\n// ---------------------------------------------------------------------------\n\n/** An error from a working-tree mutation, carrying a machine-readable `.code`. */\nexport interface EditorWriteError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:write` (first-party-only)\n | 'not-found' // the target file/folder does not exist (delete/rename)\n | 'exists' // the target already exists (create/rename would clobber)\n | 'protected' // the host refuses to delete this file (e.g. package.json)\n | 'too-large' // an upload exceeds the host's size limit\n | 'invalid-params' // a path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Create an empty working-tree file at `path` and open it. Rejects `exists` if a\n * file is already there. */\nexport const createFile = (path: string): Promise<void> => editorRequest('createFile', { path });\n\n/** Create a working-tree folder at `path` (materialised with a `.gitkeep`). */\nexport const createFolder = (path: string): Promise<void> => editorRequest('createFolder', { path });\n\n/** Delete a working-tree file, or a folder and everything under it. Rejects\n * `protected` for files the host won't remove, `not-found` if absent. */\nexport const deleteEntry = (path: string): Promise<void> => editorRequest('deleteEntry', { path });\n\n/** Rename/move a working-tree file from `from` to `to`. Rejects `exists` if `to`\n * is taken, `not-found` if `from` is absent. */\nexport const renameEntry = (from: string, to: string): Promise<void> => editorRequest('rename', { from, to });\n\n/** Upload binary/text `bytes` to a working-tree file at `path`. Rejects\n * `too-large` past the host's size limit. The bytes are transferred (zero-copy). */\nexport const uploadFile = (path: string, bytes: Uint8Array): Promise<void> => editorRequest('upload', { path, bytes });\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,eAAe;AACxB,SAAS,uBAAuB;AA0BhC,MAAM,gBAAgB,OAAO,QAAgB,QAAgD;AAC3F,QAAM,MAAO,MAAM,gBAAgB,QAAQ,eAAe,GAAG,QAAQ,CAAC,GAAG,CAAC;AAC1E,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU,MAAM,SAAS;AAC/D,QAAI,OAAQ,KAAK,QAAqC;AACtD,UAAM;AAAA,EACR;AACF;AAQO,MAAM,eAAe,CAAC,SAAgC,cAAc,QAAQ,EAAE,KAAK,CAAC;AAyCpF,MAAM,cAAc,CAAC,WAC1B,cAAc,eAAe,SAAS,EAAE,GAAG,OAAO,IAAI,CAAC,CAAC;AA0BnD,MAAM,gBAAgB,CAAC,SAAgC,cAAc,aAAa,EAAE,KAAK,CAAC;AAI1F,MAAM,YAAY,CAAC,SAAgC,cAAc,SAAS,EAAE,KAAK,CAAC;AAyBlF,MAAM,aAAa,CAAC,SAAgC,cAAc,cAAc,EAAE,KAAK,CAAC;AAGxF,MAAM,eAAe,CAAC,SAAgC,cAAc,gBAAgB,EAAE,KAAK,CAAC;AAI5F,MAAM,cAAc,CAAC,SAAgC,cAAc,eAAe,EAAE,KAAK,CAAC;AAI1F,MAAM,cAAc,CAAC,MAAc,OAA8B,cAAc,UAAU,EAAE,MAAM,GAAG,CAAC;AAIrG,MAAM,aAAa,CAAC,MAAc,UAAqC,cAAc,UAAU,EAAE,MAAM,MAAM,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/editor.ts"],"sourcesContent":["import { protocolRequest } from './sandboxUtils';\nimport { SCHEMES } from './protocolSchemes';\nimport { PROTOCOL_EDITOR } from './generated/protocol';\n\n/**\n * Open a working-tree file in the immediately.run host editor (UI_AS_APPS_SPEC §4 —\n * the file explorer's click-to-open). This is an INTENT: the app asks, the HOST\n * validates the path and drives the CodeMirror editor — the editor itself stays\n * host-owned (§2 recursion boundary), so an app can never own or script it beyond\n * \"please show this file\".\n *\n * Requires the elevated `editor:open` capability — a previewed app does not hold it\n * (it must not move the host's focus), so only a system app whose binding grants it\n * (the file explorer) can call this; anyone else is refused at the gate.\n */\n\n/** An error from {@link openInEditor}, carrying a machine-readable `.code`. */\nexport interface EditorOpenError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:open`\n | 'not-found' // no such file in the live working tree (the host never creates)\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session to open files in\n | 'unknown';\n}\n\ntype EditorResult = { ok: true; data: unknown } | { ok: false; code: string; message: string };\n\nconst editorRequest = async (method: string, arg: Record<string, unknown>): Promise<void> => {\n const res = (await protocolRequest(SCHEMES[PROTOCOL_EDITOR], method, [arg])) as EditorResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? `editor ${method} failed`) as EditorWriteError;\n err.code = (res?.code as EditorWriteError['code']) ?? 'unknown';\n throw err;\n }\n};\n\n/** Where in a file to land when opening it (R3-388). 1-indexed `line`, matching every\n * diagnostic producer that feeds it (`tsc`, `eslint`, `BuildError`) and both VS Code\n * and IntelliJ. A `line` past end-of-file CLAMPS to the last line rather than\n * erroring — a diagnostic outlives the edit that shortened the file, and landing\n * close beats refusing to navigate. */\nexport interface EditorSelection {\n line: number;\n column?: number;\n}\n\n/**\n * Ask the host to open `path` (a repo-relative working-tree path, e.g. `src/App.tsx`\n * or `/src/App.tsx`) in the editor. Resolves once the editor switches to it; rejects\n * with an {@link EditorOpenError} (`.code`) if the path is invalid, missing, or this\n * app may not open files.\n *\n * Pass `selection` to land the caret on a specific line — what a problems list needs\n * to make a diagnostic clickable. It widens nothing: a selection says where to look\n * inside a file the caller could already open, and the capability is unchanged\n * (`editor:open`).\n *\n * Older hosts ignore the extra field and open the file at its existing position, so\n * a caller may pass it unconditionally.\n */\nexport const openInEditor = (path: string, selection?: EditorSelection): Promise<void> =>\n editorRequest('open', selection ? { path, selection } : { path });\n\n/**\n * Where to land when entering the edit experience (EDITOR_FIRST_EDITING_SPEC §6\n * Delta A). v1 supports only an optional repo-relative `path` in the CURRENT repo\n * (self-scoped — the app you are already running; the host navigates within the\n * current route, never to another repo). A URI or `..` path is refused\n * `invalid-params`. Editing a file in one of your *mounts* (a space) is the\n * `edit-file` task, not this.\n */\nexport interface EditTarget {\n /** A repo-relative working-tree path in the current repo to focus once in edit\n * mode (e.g. `src/App.tsx`). Omit to edit the current route's entry. */\n path?: string;\n}\n\n/** An error from {@link requestEdit}, carrying a machine-readable `.code`. */\nexport interface RequestEditError extends Error {\n code:\n | 'read-only' // editing isn't possible here (a `ro` mount / anonymous viewer) — HIDE the affordance\n | 'forbidden' // the host refuses (e.g. a cross-repo / out-of-scope target)\n | 'invalid-params' // the target was malformed (URI / `..` / a non-current repo)\n | 'no-target' // there is no host editor session to enter\n | 'unknown';\n}\n\n/**\n * Ask the host to enter the **edit experience** for the app you are running —\n * the present→edit transition (`/present/...` → `/edit/...`) an app cannot make\n * itself. This is an INTENT (§2 recursion boundary): the app asks, the HOST\n * performs the visible, user-observable navigation and draws all editor chrome;\n * the app never navigates or paints chrome.\n *\n * Use it to offer an \"edit this\" affordance from a run/present-mode app that opens\n * the app's own source in the platform editor — instead of shipping a bespoke\n * in-app editor (EDITOR_FIRST_EDITING_SPEC §1).\n *\n * Resolves once the host begins the transition; rejects with a\n * {@link RequestEditError} (`.code`). Treat `read-only`/`forbidden` as \"editing is\n * not available — hide the affordance,\" never as an error to surface to the user.\n */\nexport const requestEdit = (target?: EditTarget): Promise<void> =>\n editorRequest('requestEdit', target ? { ...target } : {});\n\n// ---------------------------------------------------------------------------\n// Editor SESSION management (EDITOR_AS_APP_SPEC §5.1; editor-as-app plan Phase\n// 03). Unlike `openInEditor` (the explorer's cross-app intent, `editor:open`),\n// these drive the editor's OWN open-tab set + active file, so they are gated by\n// the editor app's `editor:document` capability — a file explorer holding only\n// `editor:open` cannot call them. The host re-validates the path against the live\n// working tree; the editor itself stays host-owned (§2 recursion boundary).\n// ---------------------------------------------------------------------------\n\n/** An error from a session intent ({@link setActiveFile} / {@link closeFile}),\n * carrying a machine-readable `.code`. */\nexport interface EditorSessionError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:document`\n | 'not-found' // no such file in the live working tree\n | 'invalid-params' // the path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Switch the editor's active file to `path`, opening it (adding a tab) if it is\n * not already open — native `setActiveFile` parity. Rejects with an\n * {@link EditorSessionError} (`.code`) if the path is missing/invalid or this app\n * lacks `editor:document`. */\nexport const setActiveFile = (path: string): Promise<void> => editorRequest('setActive', { path });\n\n/** Close `path`'s tab in the editor (remove it from the open set) — native\n * `closeFile` parity. Rejects with an {@link EditorSessionError} (`.code`). */\nexport const closeFile = (path: string): Promise<void> => editorRequest('close', { path });\n\n// ---------------------------------------------------------------------------\n// Working-tree mutation (UI_AS_APPS_SPEC §4 / EDITOR_AS_APP_SPEC §5.2). The file\n// explorer NAMES a working-tree path and the HOST performs the COW write (and\n// refreshes the preview) — the app holds no write port; it asks. Gated by the\n// first-party `editor:write` capability, so only a first-party chrome app (the\n// file explorer) can call these; anyone else is refused at the gate.\n// ---------------------------------------------------------------------------\n\n/** An error from a working-tree mutation, carrying a machine-readable `.code`. */\nexport interface EditorWriteError extends Error {\n code:\n | 'forbidden' // the frame lacks `editor:write` (first-party-only)\n | 'not-found' // the target file/folder does not exist (delete/rename)\n | 'exists' // the target already exists (create/rename would clobber)\n | 'protected' // the host refuses to delete this file (e.g. package.json)\n | 'too-large' // an upload exceeds the host's size limit\n | 'invalid-params' // a path was empty / contained `..` / looked like a URI\n | 'no-target' // there is no host editor session\n | 'unknown';\n}\n\n/** Create an empty working-tree file at `path` and open it. Rejects `exists` if a\n * file is already there. */\nexport const createFile = (path: string): Promise<void> => editorRequest('createFile', { path });\n\n/** Create a working-tree folder at `path` (materialised with a `.gitkeep`). */\nexport const createFolder = (path: string): Promise<void> => editorRequest('createFolder', { path });\n\n/** Delete a working-tree file, or a folder and everything under it. Rejects\n * `protected` for files the host won't remove, `not-found` if absent. */\nexport const deleteEntry = (path: string): Promise<void> => editorRequest('deleteEntry', { path });\n\n/** Rename/move a working-tree file from `from` to `to`. Rejects `exists` if `to`\n * is taken, `not-found` if `from` is absent. */\nexport const renameEntry = (from: string, to: string): Promise<void> => editorRequest('rename', { from, to });\n\n/** Upload binary/text `bytes` to a working-tree file at `path`. Rejects\n * `too-large` past the host's size limit. The bytes are transferred (zero-copy). */\nexport const uploadFile = (path: string, bytes: Uint8Array): Promise<void> => editorRequest('upload', { path, bytes });\n"],"mappings":";AAAA,SAAS,uBAAuB;AAChC,SAAS,eAAe;AACxB,SAAS,uBAAuB;AA0BhC,MAAM,gBAAgB,OAAO,QAAgB,QAAgD;AAC3F,QAAM,MAAO,MAAM,gBAAgB,QAAQ,eAAe,GAAG,QAAQ,CAAC,GAAG,CAAC;AAC1E,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU,MAAM,SAAS;AAC/D,QAAI,OAAQ,KAAK,QAAqC;AACtD,UAAM;AAAA,EACR;AACF;AA0BO,MAAM,eAAe,CAAC,MAAc,cACzC,cAAc,QAAQ,YAAY,EAAE,MAAM,UAAU,IAAI,EAAE,KAAK,CAAC;AAyC3D,MAAM,cAAc,CAAC,WAC1B,cAAc,eAAe,SAAS,EAAE,GAAG,OAAO,IAAI,CAAC,CAAC;AA0BnD,MAAM,gBAAgB,CAAC,SAAgC,cAAc,aAAa,EAAE,KAAK,CAAC;AAI1F,MAAM,YAAY,CAAC,SAAgC,cAAc,SAAS,EAAE,KAAK,CAAC;AAyBlF,MAAM,aAAa,CAAC,SAAgC,cAAc,cAAc,EAAE,KAAK,CAAC;AAGxF,MAAM,eAAe,CAAC,SAAgC,cAAc,gBAAgB,EAAE,KAAK,CAAC;AAI5F,MAAM,cAAc,CAAC,SAAgC,cAAc,eAAe,EAAE,KAAK,CAAC;AAI1F,MAAM,cAAc,CAAC,MAAc,OAA8B,cAAc,UAAU,EAAE,MAAM,GAAG,CAAC;AAIrG,MAAM,aAAa,CAAC,MAAc,UAAqC,cAAc,UAAU,EAAE,MAAM,MAAM,CAAC;","names":[]}
package/dist/feed.cjs ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var feed_exports = {};
20
+ __export(feed_exports, {
21
+ feedFetch: () => feedFetch
22
+ });
23
+ module.exports = __toCommonJS(feed_exports);
24
+ var import_sandboxUtils = require("./sandboxUtils");
25
+ var import_protocolSchemes = require("./protocolSchemes");
26
+ var import_protocol = require("./generated/protocol");
27
+ const feedFetch = async (instanceId, params = {}) => {
28
+ const res = await (0, import_sandboxUtils.protocolRequest)(import_protocolSchemes.SCHEMES[import_protocol.PROTOCOL_FEED], "fetch", [{ instanceId, params }]);
29
+ if (!res || res.ok !== true) {
30
+ const err = new Error(res?.message ?? "feedFetch failed");
31
+ err.code = (res && "code" in res ? res.code : void 0) ?? "unknown";
32
+ throw err;
33
+ }
34
+ return res.data;
35
+ };
36
+ // Annotate the CommonJS export names for ESM import in node:
37
+ 0 && (module.exports = {
38
+ feedFetch
39
+ });
40
+ //# sourceMappingURL=feed.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/feed.ts"],"sourcesContent":["// feedFetch — the connector's egress, and the difference between it and `hostFetch`\n// is the whole of D2 (`reckoner/docs/specs/CONNECTOR_EGRESS_FIXING_SPEC.md` §2).\n//\n// `hostFetch(url, init)` takes a URL. The host checks it against your effective\n// allowlist, but *within* that allowlist your app picks which host, which path and\n// what body, on every call. That is fine for an app whose logic you control.\n//\n// It is not fine for a **connector** — an app whose job is to pump bytes from a feed\n// into a document, where the bytes it fetched are, in effect, a program steering it\n// (`REPORTING_SPREADSHEET §3.2` RB-1). An allowlist bounds the host *set*; it does\n// nothing about per-call choice inside that set, and nothing at all about the body.\n//\n// So `feedFetch` does not take a URL. It takes a **feed-instance id** and a typed\n// **param object**, and the host constructs the request from a template it compiled,\n// at grant time, from your app's trusted feed configuration. Your code cannot name a\n// target, so content your code just read cannot name one either.\n//\n// What that means in practice when you write a connector:\n//\n// • the origin, path and method come from your manifest's `feed:fetch` config —\n// not from this call, and not from anything you fetched;\n// • `params` fill only the slots the template declared, and each is typed\n// (an ISO-8601 instant, a bounded integer, or one of a declared enum). A value\n// that is not what the slot declared is rejected — including, incidentally,\n// anything URL-shaped;\n// • **pagination is not yours.** The host mints the cursor, keeps it, and spends it;\n// you neither supply nor receive one. A cursor you round-tripped would be either\n// bytes you authored or a function of bytes you fetched, and both are exactly what\n// this surface exists to prevent;\n// • a `POST`/body feed's body comes from the template too. There is no parameter\n// that carries body bytes.\n//\n// Hold `feed:fetch` **instead of** `net:fetch`, not alongside it. An app holding\n// `net:fetch` has the URL surface back regardless of any template it was also given,\n// which is why they are two capabilities and not one with a flag.\n\nimport { protocolRequest } from './sandboxUtils';\nimport { SCHEMES } from './protocolSchemes';\nimport { PROTOCOL_FEED } from './generated/protocol';\n\n/** Values a feed template's declared slots accept. The host validates each against\n * the slot's declared type; anything else is `invalid-params`. */\nexport type FeedParams = Record<string, string | number>;\n\n/** The serialized response from {@link feedFetch} — the same shape `hostFetch`\n * returns, because reading a feed should feel like reading a fetch. The difference\n * is entirely in what you may ASK for. */\nexport interface FeedFetchResponse {\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body: string;\n /** True if the body hit the host's size cap and was truncated. */\n truncated: boolean;\n}\n\n/**\n * Fire one of your app's configured feeds through the host.\n *\n * ```ts\n * // `instanceId` comes from the host when the feed is launched — it is opaque,\n * // host-minted, and bound to your app; you never construct one.\n * const res = await feedFetch(instanceId, { since: '2026-08-01T00:00:00Z' });\n * const rows = JSON.parse(res.body);\n * ```\n *\n * A reachable server's reply — including a non-2xx status — RESOLVES; inspect\n * `.status`. Everything else REJECTS with an {@link Error} carrying a machine `.code`:\n *\n * - `forbidden` — you do not hold `feed:fetch`, or `instanceId` is not one of yours.\n * **The two are deliberately indistinguishable**, so this is not an oracle for which\n * feeds exist.\n * - `invalid-params` — a param the template does not declare, a value that is not what\n * its slot declared, or a body that would exceed the template's cap. Naming a cursor\n * slot lands here too: the cursor is the host's, not a parameter.\n * - `budget` — this instance's request budget is spent. It bounds runaway loops; it is\n * a tripwire, not containment.\n * - `unsupported` — the host's pinned egress path is unavailable. `feedFetch`\n * deliberately has **no fallback**: the alternative path does no DNS resolution and no\n * socket pinning, and silently downgrading a credentialed feed onto it is the hazard\n * this whole mechanism removes. A connector that cannot use the pinned path does not\n * fetch.\n * - `blocked` / `redirect` / `too-large` / `network` — the same server-side SSRF,\n * per-hop redirect and size guards every proxied fetch meets.\n */\n// The parameter is spelled structurally rather than as `FeedParams`, deliberately: the\n// wire descriptor in `@immediately-run/sandbox-protocol` records the type that actually\n// crosses the boundary, and an SDK-local alias name in a CROSS-REPO wire contract would\n// describe this package rather than the protocol. `FeedParams` stays exported as the\n// name callers write.\nexport const feedFetch = async (\n instanceId: string,\n params: Record<string, string | number> = {},\n): Promise<FeedFetchResponse> => {\n const res = (await protocolRequest(SCHEMES[PROTOCOL_FEED], 'fetch', [{ instanceId, params }])) as\n | { ok: true; data: FeedFetchResponse }\n | { ok: false; code?: string; message?: string }\n | undefined;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? 'feedFetch failed') as Error & { code?: string };\n err.code = (res && 'code' in res ? res.code : undefined) ?? 'unknown';\n throw err;\n }\n return res.data;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCA,0BAAgC;AAChC,6BAAwB;AACxB,sBAA8B;AAoDvB,MAAM,YAAY,OACvB,YACA,SAA0C,CAAC,MACZ;AAC/B,QAAM,MAAO,UAAM,qCAAgB,+BAAQ,6BAAa,GAAG,SAAS,CAAC,EAAE,YAAY,OAAO,CAAC,CAAC;AAI5F,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,kBAAkB;AACxD,QAAI,QAAQ,OAAO,UAAU,MAAM,IAAI,OAAO,WAAc;AAC5D,UAAM;AAAA,EACR;AACA,SAAO,IAAI;AACb;","names":[]}
@@ -0,0 +1,46 @@
1
+ /** Values a feed template's declared slots accept. The host validates each against
2
+ * the slot's declared type; anything else is `invalid-params`. */
3
+ type FeedParams = Record<string, string | number>;
4
+ /** The serialized response from {@link feedFetch} — the same shape `hostFetch`
5
+ * returns, because reading a feed should feel like reading a fetch. The difference
6
+ * is entirely in what you may ASK for. */
7
+ interface FeedFetchResponse {
8
+ status: number;
9
+ statusText: string;
10
+ headers: Record<string, string>;
11
+ body: string;
12
+ /** True if the body hit the host's size cap and was truncated. */
13
+ truncated: boolean;
14
+ }
15
+ /**
16
+ * Fire one of your app's configured feeds through the host.
17
+ *
18
+ * ```ts
19
+ * // `instanceId` comes from the host when the feed is launched — it is opaque,
20
+ * // host-minted, and bound to your app; you never construct one.
21
+ * const res = await feedFetch(instanceId, { since: '2026-08-01T00:00:00Z' });
22
+ * const rows = JSON.parse(res.body);
23
+ * ```
24
+ *
25
+ * A reachable server's reply — including a non-2xx status — RESOLVES; inspect
26
+ * `.status`. Everything else REJECTS with an {@link Error} carrying a machine `.code`:
27
+ *
28
+ * - `forbidden` — you do not hold `feed:fetch`, or `instanceId` is not one of yours.
29
+ * **The two are deliberately indistinguishable**, so this is not an oracle for which
30
+ * feeds exist.
31
+ * - `invalid-params` — a param the template does not declare, a value that is not what
32
+ * its slot declared, or a body that would exceed the template's cap. Naming a cursor
33
+ * slot lands here too: the cursor is the host's, not a parameter.
34
+ * - `budget` — this instance's request budget is spent. It bounds runaway loops; it is
35
+ * a tripwire, not containment.
36
+ * - `unsupported` — the host's pinned egress path is unavailable. `feedFetch`
37
+ * deliberately has **no fallback**: the alternative path does no DNS resolution and no
38
+ * socket pinning, and silently downgrading a credentialed feed onto it is the hazard
39
+ * this whole mechanism removes. A connector that cannot use the pinned path does not
40
+ * fetch.
41
+ * - `blocked` / `redirect` / `too-large` / `network` — the same server-side SSRF,
42
+ * per-hop redirect and size guards every proxied fetch meets.
43
+ */
44
+ declare const feedFetch: (instanceId: string, params?: Record<string, string | number>) => Promise<FeedFetchResponse>;
45
+
46
+ export { type FeedFetchResponse, type FeedParams, feedFetch };
package/dist/feed.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ /** Values a feed template's declared slots accept. The host validates each against
2
+ * the slot's declared type; anything else is `invalid-params`. */
3
+ type FeedParams = Record<string, string | number>;
4
+ /** The serialized response from {@link feedFetch} — the same shape `hostFetch`
5
+ * returns, because reading a feed should feel like reading a fetch. The difference
6
+ * is entirely in what you may ASK for. */
7
+ interface FeedFetchResponse {
8
+ status: number;
9
+ statusText: string;
10
+ headers: Record<string, string>;
11
+ body: string;
12
+ /** True if the body hit the host's size cap and was truncated. */
13
+ truncated: boolean;
14
+ }
15
+ /**
16
+ * Fire one of your app's configured feeds through the host.
17
+ *
18
+ * ```ts
19
+ * // `instanceId` comes from the host when the feed is launched — it is opaque,
20
+ * // host-minted, and bound to your app; you never construct one.
21
+ * const res = await feedFetch(instanceId, { since: '2026-08-01T00:00:00Z' });
22
+ * const rows = JSON.parse(res.body);
23
+ * ```
24
+ *
25
+ * A reachable server's reply — including a non-2xx status — RESOLVES; inspect
26
+ * `.status`. Everything else REJECTS with an {@link Error} carrying a machine `.code`:
27
+ *
28
+ * - `forbidden` — you do not hold `feed:fetch`, or `instanceId` is not one of yours.
29
+ * **The two are deliberately indistinguishable**, so this is not an oracle for which
30
+ * feeds exist.
31
+ * - `invalid-params` — a param the template does not declare, a value that is not what
32
+ * its slot declared, or a body that would exceed the template's cap. Naming a cursor
33
+ * slot lands here too: the cursor is the host's, not a parameter.
34
+ * - `budget` — this instance's request budget is spent. It bounds runaway loops; it is
35
+ * a tripwire, not containment.
36
+ * - `unsupported` — the host's pinned egress path is unavailable. `feedFetch`
37
+ * deliberately has **no fallback**: the alternative path does no DNS resolution and no
38
+ * socket pinning, and silently downgrading a credentialed feed onto it is the hazard
39
+ * this whole mechanism removes. A connector that cannot use the pinned path does not
40
+ * fetch.
41
+ * - `blocked` / `redirect` / `too-large` / `network` — the same server-side SSRF,
42
+ * per-hop redirect and size guards every proxied fetch meets.
43
+ */
44
+ declare const feedFetch: (instanceId: string, params?: Record<string, string | number>) => Promise<FeedFetchResponse>;
45
+
46
+ export { type FeedFetchResponse, type FeedParams, feedFetch };
package/dist/feed.js ADDED
@@ -0,0 +1,17 @@
1
+ import "./chunk-VHAA22YE.js";
2
+ import { protocolRequest } from "./sandboxUtils";
3
+ import { SCHEMES } from "./protocolSchemes";
4
+ import { PROTOCOL_FEED } from "./generated/protocol";
5
+ const feedFetch = async (instanceId, params = {}) => {
6
+ const res = await protocolRequest(SCHEMES[PROTOCOL_FEED], "fetch", [{ instanceId, params }]);
7
+ if (!res || res.ok !== true) {
8
+ const err = new Error(res?.message ?? "feedFetch failed");
9
+ err.code = (res && "code" in res ? res.code : void 0) ?? "unknown";
10
+ throw err;
11
+ }
12
+ return res.data;
13
+ };
14
+ export {
15
+ feedFetch
16
+ };
17
+ //# sourceMappingURL=feed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/feed.ts"],"sourcesContent":["// feedFetch — the connector's egress, and the difference between it and `hostFetch`\n// is the whole of D2 (`reckoner/docs/specs/CONNECTOR_EGRESS_FIXING_SPEC.md` §2).\n//\n// `hostFetch(url, init)` takes a URL. The host checks it against your effective\n// allowlist, but *within* that allowlist your app picks which host, which path and\n// what body, on every call. That is fine for an app whose logic you control.\n//\n// It is not fine for a **connector** — an app whose job is to pump bytes from a feed\n// into a document, where the bytes it fetched are, in effect, a program steering it\n// (`REPORTING_SPREADSHEET §3.2` RB-1). An allowlist bounds the host *set*; it does\n// nothing about per-call choice inside that set, and nothing at all about the body.\n//\n// So `feedFetch` does not take a URL. It takes a **feed-instance id** and a typed\n// **param object**, and the host constructs the request from a template it compiled,\n// at grant time, from your app's trusted feed configuration. Your code cannot name a\n// target, so content your code just read cannot name one either.\n//\n// What that means in practice when you write a connector:\n//\n// • the origin, path and method come from your manifest's `feed:fetch` config —\n// not from this call, and not from anything you fetched;\n// • `params` fill only the slots the template declared, and each is typed\n// (an ISO-8601 instant, a bounded integer, or one of a declared enum). A value\n// that is not what the slot declared is rejected — including, incidentally,\n// anything URL-shaped;\n// • **pagination is not yours.** The host mints the cursor, keeps it, and spends it;\n// you neither supply nor receive one. A cursor you round-tripped would be either\n// bytes you authored or a function of bytes you fetched, and both are exactly what\n// this surface exists to prevent;\n// • a `POST`/body feed's body comes from the template too. There is no parameter\n// that carries body bytes.\n//\n// Hold `feed:fetch` **instead of** `net:fetch`, not alongside it. An app holding\n// `net:fetch` has the URL surface back regardless of any template it was also given,\n// which is why they are two capabilities and not one with a flag.\n\nimport { protocolRequest } from './sandboxUtils';\nimport { SCHEMES } from './protocolSchemes';\nimport { PROTOCOL_FEED } from './generated/protocol';\n\n/** Values a feed template's declared slots accept. The host validates each against\n * the slot's declared type; anything else is `invalid-params`. */\nexport type FeedParams = Record<string, string | number>;\n\n/** The serialized response from {@link feedFetch} — the same shape `hostFetch`\n * returns, because reading a feed should feel like reading a fetch. The difference\n * is entirely in what you may ASK for. */\nexport interface FeedFetchResponse {\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body: string;\n /** True if the body hit the host's size cap and was truncated. */\n truncated: boolean;\n}\n\n/**\n * Fire one of your app's configured feeds through the host.\n *\n * ```ts\n * // `instanceId` comes from the host when the feed is launched — it is opaque,\n * // host-minted, and bound to your app; you never construct one.\n * const res = await feedFetch(instanceId, { since: '2026-08-01T00:00:00Z' });\n * const rows = JSON.parse(res.body);\n * ```\n *\n * A reachable server's reply — including a non-2xx status — RESOLVES; inspect\n * `.status`. Everything else REJECTS with an {@link Error} carrying a machine `.code`:\n *\n * - `forbidden` — you do not hold `feed:fetch`, or `instanceId` is not one of yours.\n * **The two are deliberately indistinguishable**, so this is not an oracle for which\n * feeds exist.\n * - `invalid-params` — a param the template does not declare, a value that is not what\n * its slot declared, or a body that would exceed the template's cap. Naming a cursor\n * slot lands here too: the cursor is the host's, not a parameter.\n * - `budget` — this instance's request budget is spent. It bounds runaway loops; it is\n * a tripwire, not containment.\n * - `unsupported` — the host's pinned egress path is unavailable. `feedFetch`\n * deliberately has **no fallback**: the alternative path does no DNS resolution and no\n * socket pinning, and silently downgrading a credentialed feed onto it is the hazard\n * this whole mechanism removes. A connector that cannot use the pinned path does not\n * fetch.\n * - `blocked` / `redirect` / `too-large` / `network` — the same server-side SSRF,\n * per-hop redirect and size guards every proxied fetch meets.\n */\n// The parameter is spelled structurally rather than as `FeedParams`, deliberately: the\n// wire descriptor in `@immediately-run/sandbox-protocol` records the type that actually\n// crosses the boundary, and an SDK-local alias name in a CROSS-REPO wire contract would\n// describe this package rather than the protocol. `FeedParams` stays exported as the\n// name callers write.\nexport const feedFetch = async (\n instanceId: string,\n params: Record<string, string | number> = {},\n): Promise<FeedFetchResponse> => {\n const res = (await protocolRequest(SCHEMES[PROTOCOL_FEED], 'fetch', [{ instanceId, params }])) as\n | { ok: true; data: FeedFetchResponse }\n | { ok: false; code?: string; message?: string }\n | undefined;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? 'feedFetch failed') as Error & { code?: string };\n err.code = (res && 'code' in res ? res.code : undefined) ?? 'unknown';\n throw err;\n }\n return res.data;\n};\n"],"mappings":";AAoCA,SAAS,uBAAuB;AAChC,SAAS,eAAe;AACxB,SAAS,qBAAqB;AAoDvB,MAAM,YAAY,OACvB,YACA,SAA0C,CAAC,MACZ;AAC/B,QAAM,MAAO,MAAM,gBAAgB,QAAQ,aAAa,GAAG,SAAS,CAAC,EAAE,YAAY,OAAO,CAAC,CAAC;AAI5F,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,kBAAkB;AACxD,QAAI,QAAQ,OAAO,UAAU,MAAM,IAAI,OAAO,WAAc;AAC5D,UAAM;AAAA,EACR;AACA,SAAO,IAAI;AACb;","names":[]}
package/dist/index.cjs CHANGED
@@ -53,6 +53,7 @@ __reExport(index_exports, require("./catalog"), module.exports);
53
53
  __reExport(index_exports, require("./ipc"), module.exports);
54
54
  __reExport(index_exports, require("./dnd"), module.exports);
55
55
  __reExport(index_exports, require("./netFetch"), module.exports);
56
+ __reExport(index_exports, require("./feed"), module.exports);
56
57
  __reExport(index_exports, require("./secrets"), module.exports);
57
58
  __reExport(index_exports, require("./llm"), module.exports);
58
59
  __reExport(index_exports, require("./diagnostics"), module.exports);
@@ -102,6 +103,7 @@ __reExport(index_exports, require("./safeContent"), module.exports);
102
103
  ...require("./ipc"),
103
104
  ...require("./dnd"),
104
105
  ...require("./netFetch"),
106
+ ...require("./feed"),
105
107
  ...require("./secrets"),
106
108
  ...require("./llm"),
107
109
  ...require("./diagnostics"),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './MDXProvider';\nexport * from './routing';\nexport * from './boot';\nexport * from './components/Include';\n// Only the component is public. `stripFrontmatter`/`appMountRelative` are module-level\n// exports so they can be unit-tested directly, NOT public API — the SDK's surface is\n// backwards-compatible forever, so an internal helper exported for a test's convenience is a\n// permanent commitment made for the wrong reason.\nexport { SafeInclude } from './components/SafeInclude';\nexport * from './sourceCache';\nexport * from './components/MDXComponents';\nexport * from './linkSpace';\nexport * from './corpus';\nexport * from './components/MountImage';\nexport * from './components/Routes';\nexport * from './hooks';\n// R3-276: the supported way for a viewer app to provide its own metadata store,\n// replacing a wholesale re-provision of `TinkerableContext` in app code.\nexport * from './metadataSource';\n// The deprecated injected-bundler adapters, re-exported so their deprecation notices\n// are visible in the published docs (R3-278; the window only narrows).\nexport { getInjectedMetadataEmitter, getInjectedMetadataSnapshot } from './injectedBundler';\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './editor';\nexport * from './formFactor';\nexport * from './chromeState';\nexport * from './hostAttention';\nexport * from './region';\nexport * from './mounts';\nexport * from './analytics';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './ipc';\nexport * from './dnd';\nexport * from './netFetch';\nexport * from './secrets';\nexport * from './llm';\nexport * from './diagnostics';\nexport * from './vcs';\nexport * from './onFsChange';\nexport * from './fs';\nexport * from './debug';\nexport * from './tasks';\nexport * from './launch';\nexport * from './runtime';\nexport * from './irMarkers';\nexport * from './ready';\nexport * from './loading';\nexport * from './protocolStream';\nexport * from './protocolDeadline';\nexport * from './sandboxTypes';\nexport * from './safeContent';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAc,0BAAd;AACA,0BAAc,sBADd;AAEA,0BAAc,mBAFd;AAGA,0BAAc,iCAHd;AAQA,yBAA4B;AAC5B,0BAAc,0BATd;AAUA,0BAAc,uCAVd;AAWA,0BAAc,wBAXd;AAYA,0BAAc,qBAZd;AAaA,0BAAc,oCAbd;AAcA,0BAAc,gCAdd;AAeA,0BAAc,oBAfd;AAkBA,0BAAc,6BAlBd;AAqBA,6BAAwE;AACxE,0BAAc,mBAtBd;AAuBA,0BAAc,oBAvBd;AAwBA,0BAAc,4BAxBd;AAyBA,0BAAc,qBAzBd;AA0BA,0BAAc,yBA1Bd;AA2BA,0BAAc,0BA3Bd;AA4BA,0BAAc,4BA5Bd;AA6BA,0BAAc,qBA7Bd;AA8BA,0BAAc,qBA9Bd;AA+BA,0BAAc,wBA/Bd;AAgCA,0BAAc,yBAhCd;AAiCA,0BAAc,sBAjCd;AAkCA,0BAAc,kBAlCd;AAmCA,0BAAc,kBAnCd;AAoCA,0BAAc,uBApCd;AAqCA,0BAAc,sBArCd;AAsCA,0BAAc,kBAtCd;AAuCA,0BAAc,0BAvCd;AAwCA,0BAAc,kBAxCd;AAyCA,0BAAc,yBAzCd;AA0CA,0BAAc,iBA1Cd;AA2CA,0BAAc,oBA3Cd;AA4CA,0BAAc,oBA5Cd;AA6CA,0BAAc,qBA7Cd;AA8CA,0BAAc,sBA9Cd;AA+CA,0BAAc,wBA/Cd;AAgDA,0BAAc,oBAhDd;AAiDA,0BAAc,sBAjDd;AAkDA,0BAAc,6BAlDd;AAmDA,0BAAc,+BAnDd;AAoDA,0BAAc,2BApDd;AAqDA,0BAAc,0BArDd;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './MDXProvider';\nexport * from './routing';\nexport * from './boot';\nexport * from './components/Include';\n// Only the component is public. `stripFrontmatter`/`appMountRelative` are module-level\n// exports so they can be unit-tested directly, NOT public API — the SDK's surface is\n// backwards-compatible forever, so an internal helper exported for a test's convenience is a\n// permanent commitment made for the wrong reason.\nexport { SafeInclude } from './components/SafeInclude';\nexport * from './sourceCache';\nexport * from './components/MDXComponents';\nexport * from './linkSpace';\nexport * from './corpus';\nexport * from './components/MountImage';\nexport * from './components/Routes';\nexport * from './hooks';\n// R3-276: the supported way for a viewer app to provide its own metadata store,\n// replacing a wholesale re-provision of `TinkerableContext` in app code.\nexport * from './metadataSource';\n// The deprecated injected-bundler adapters, re-exported so their deprecation notices\n// are visible in the published docs (R3-278; the window only narrows).\nexport { getInjectedMetadataEmitter, getInjectedMetadataSnapshot } from './injectedBundler';\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './editor';\nexport * from './formFactor';\nexport * from './chromeState';\nexport * from './hostAttention';\nexport * from './region';\nexport * from './mounts';\nexport * from './analytics';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './ipc';\nexport * from './dnd';\nexport * from './netFetch';\nexport * from './feed';\nexport * from './secrets';\nexport * from './llm';\nexport * from './diagnostics';\nexport * from './vcs';\nexport * from './onFsChange';\nexport * from './fs';\nexport * from './debug';\nexport * from './tasks';\nexport * from './launch';\nexport * from './runtime';\nexport * from './irMarkers';\nexport * from './ready';\nexport * from './loading';\nexport * from './protocolStream';\nexport * from './protocolDeadline';\nexport * from './sandboxTypes';\nexport * from './safeContent';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAc,0BAAd;AACA,0BAAc,sBADd;AAEA,0BAAc,mBAFd;AAGA,0BAAc,iCAHd;AAQA,yBAA4B;AAC5B,0BAAc,0BATd;AAUA,0BAAc,uCAVd;AAWA,0BAAc,wBAXd;AAYA,0BAAc,qBAZd;AAaA,0BAAc,oCAbd;AAcA,0BAAc,gCAdd;AAeA,0BAAc,oBAfd;AAkBA,0BAAc,6BAlBd;AAqBA,6BAAwE;AACxE,0BAAc,mBAtBd;AAuBA,0BAAc,oBAvBd;AAwBA,0BAAc,4BAxBd;AAyBA,0BAAc,qBAzBd;AA0BA,0BAAc,yBA1Bd;AA2BA,0BAAc,0BA3Bd;AA4BA,0BAAc,4BA5Bd;AA6BA,0BAAc,qBA7Bd;AA8BA,0BAAc,qBA9Bd;AA+BA,0BAAc,wBA/Bd;AAgCA,0BAAc,yBAhCd;AAiCA,0BAAc,sBAjCd;AAkCA,0BAAc,kBAlCd;AAmCA,0BAAc,kBAnCd;AAoCA,0BAAc,uBApCd;AAqCA,0BAAc,mBArCd;AAsCA,0BAAc,sBAtCd;AAuCA,0BAAc,kBAvCd;AAwCA,0BAAc,0BAxCd;AAyCA,0BAAc,kBAzCd;AA0CA,0BAAc,yBA1Cd;AA2CA,0BAAc,iBA3Cd;AA4CA,0BAAc,oBA5Cd;AA6CA,0BAAc,oBA7Cd;AA8CA,0BAAc,qBA9Cd;AA+CA,0BAAc,sBA/Cd;AAgDA,0BAAc,wBAhDd;AAiDA,0BAAc,oBAjDd;AAkDA,0BAAc,sBAlDd;AAmDA,0BAAc,6BAnDd;AAoDA,0BAAc,+BApDd;AAqDA,0BAAc,2BArDd;AAsDA,0BAAc,0BAtDd;","names":[]}
package/dist/index.d.cts CHANGED
@@ -15,7 +15,7 @@ export { getInjectedMetadataEmitter, getInjectedMetadataSnapshot } from './injec
15
15
  export { AuthState, AuthStatus, SandboxUser, getAuthState, onAuthChange, useAuth } from './auth.cjs';
16
16
  export { HostTheme, getHostTheme, onHostThemeChange, setHostTheme, useHostTheme } from './theme.cjs';
17
17
  export { EditorContext, getEditorContext, onEditorContextChange, useEditorContext } from './editorContext.cjs';
18
- export { EditTarget, EditorOpenError, EditorSessionError, EditorWriteError, RequestEditError, closeFile, createFile, createFolder, deleteEntry, openInEditor, renameEntry, requestEdit, setActiveFile, uploadFile } from './editor.cjs';
18
+ export { EditTarget, EditorOpenError, EditorSelection, EditorSessionError, EditorWriteError, RequestEditError, closeFile, createFile, createFolder, deleteEntry, openInEditor, renameEntry, requestEdit, setActiveFile, uploadFile } from './editor.cjs';
19
19
  export { FormFactor, FormFactorClass, Orientation, getFormFactor, onFormFactorChange, useFormFactor } from './formFactor.cjs';
20
20
  export { ChromeState, getChromeState, onChromeStateChange, useChromeState } from './chromeState.cjs';
21
21
  export { HostAttention, HostAttentionKind, NO_HOST_ATTENTION, getHostAttention, onHostAttentionChange, useHostAttention } from './hostAttention.cjs';
@@ -27,6 +27,7 @@ export { ApiMethod, getCatalog, invoke, invokeStream, onCatalogChange, useCatalo
27
27
  export { RegionMessage, onRegionMessage, postToRegion, revealRegion, useRegionMessage } from './ipc.cjs';
28
28
  export { DraggableItem, DroppedItem, ItemDragError, cancelItemDrag, onItemDrop, startItemDrag, useDroppedItem } from './dnd.cjs';
29
29
  export { HostFetchInit, HostFetchResponse, HostFetchStreamEvent, HostFetchStreamResult, hostFetch, hostFetchStream } from './netFetch.cjs';
30
+ export { FeedFetchResponse, FeedParams, feedFetch } from './feed.cjs';
30
31
  export { SecretError, SecretGrant, SecretHints, SecretQuery, SecretType, SecretView, getSecrets, onSecretsChange, requestAddSecret, requestSecret, revokeSecret, useSecrets } from './secrets.cjs';
31
32
  export { ChatDelta, ChatFeatures, ChatMessage, ChatProviderInfo, ChatProviderState, ChatRequest, ChatResult, ChatRole, ChatStopReason, ContentPart, ToolDef, chat, describeChat, describeChatState, normalizeProviderInfo, onChatProviderChange, onChatProviderStateChange, useChatProvider, useChatProviderState } from './llm.cjs';
32
33
  export { BuildError, ConsoleEntry, ConsoleLevel, Diagnostics, DiagnosticsProvenance, getDiagnostics, onDiagnosticsChange, useDiagnostics } from './diagnostics.cjs';
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export { getInjectedMetadataEmitter, getInjectedMetadataSnapshot } from './injec
15
15
  export { AuthState, AuthStatus, SandboxUser, getAuthState, onAuthChange, useAuth } from './auth.js';
16
16
  export { HostTheme, getHostTheme, onHostThemeChange, setHostTheme, useHostTheme } from './theme.js';
17
17
  export { EditorContext, getEditorContext, onEditorContextChange, useEditorContext } from './editorContext.js';
18
- export { EditTarget, EditorOpenError, EditorSessionError, EditorWriteError, RequestEditError, closeFile, createFile, createFolder, deleteEntry, openInEditor, renameEntry, requestEdit, setActiveFile, uploadFile } from './editor.js';
18
+ export { EditTarget, EditorOpenError, EditorSelection, EditorSessionError, EditorWriteError, RequestEditError, closeFile, createFile, createFolder, deleteEntry, openInEditor, renameEntry, requestEdit, setActiveFile, uploadFile } from './editor.js';
19
19
  export { FormFactor, FormFactorClass, Orientation, getFormFactor, onFormFactorChange, useFormFactor } from './formFactor.js';
20
20
  export { ChromeState, getChromeState, onChromeStateChange, useChromeState } from './chromeState.js';
21
21
  export { HostAttention, HostAttentionKind, NO_HOST_ATTENTION, getHostAttention, onHostAttentionChange, useHostAttention } from './hostAttention.js';
@@ -27,6 +27,7 @@ export { ApiMethod, getCatalog, invoke, invokeStream, onCatalogChange, useCatalo
27
27
  export { RegionMessage, onRegionMessage, postToRegion, revealRegion, useRegionMessage } from './ipc.js';
28
28
  export { DraggableItem, DroppedItem, ItemDragError, cancelItemDrag, onItemDrop, startItemDrag, useDroppedItem } from './dnd.js';
29
29
  export { HostFetchInit, HostFetchResponse, HostFetchStreamEvent, HostFetchStreamResult, hostFetch, hostFetchStream } from './netFetch.js';
30
+ export { FeedFetchResponse, FeedParams, feedFetch } from './feed.js';
30
31
  export { SecretError, SecretGrant, SecretHints, SecretQuery, SecretType, SecretView, getSecrets, onSecretsChange, requestAddSecret, requestSecret, revokeSecret, useSecrets } from './secrets.js';
31
32
  export { ChatDelta, ChatFeatures, ChatMessage, ChatProviderInfo, ChatProviderState, ChatRequest, ChatResult, ChatRole, ChatStopReason, ContentPart, ToolDef, chat, describeChat, describeChatState, normalizeProviderInfo, onChatProviderChange, onChatProviderStateChange, useChatProvider, useChatProviderState } from './llm.js';
32
33
  export { BuildError, ConsoleEntry, ConsoleLevel, Diagnostics, DiagnosticsProvenance, getDiagnostics, onDiagnosticsChange, useDiagnostics } from './diagnostics.js';
package/dist/index.js CHANGED
@@ -28,6 +28,7 @@ export * from "./catalog";
28
28
  export * from "./ipc";
29
29
  export * from "./dnd";
30
30
  export * from "./netFetch";
31
+ export * from "./feed";
31
32
  export * from "./secrets";
32
33
  export * from "./llm";
33
34
  export * from "./diagnostics";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './MDXProvider';\nexport * from './routing';\nexport * from './boot';\nexport * from './components/Include';\n// Only the component is public. `stripFrontmatter`/`appMountRelative` are module-level\n// exports so they can be unit-tested directly, NOT public API — the SDK's surface is\n// backwards-compatible forever, so an internal helper exported for a test's convenience is a\n// permanent commitment made for the wrong reason.\nexport { SafeInclude } from './components/SafeInclude';\nexport * from './sourceCache';\nexport * from './components/MDXComponents';\nexport * from './linkSpace';\nexport * from './corpus';\nexport * from './components/MountImage';\nexport * from './components/Routes';\nexport * from './hooks';\n// R3-276: the supported way for a viewer app to provide its own metadata store,\n// replacing a wholesale re-provision of `TinkerableContext` in app code.\nexport * from './metadataSource';\n// The deprecated injected-bundler adapters, re-exported so their deprecation notices\n// are visible in the published docs (R3-278; the window only narrows).\nexport { getInjectedMetadataEmitter, getInjectedMetadataSnapshot } from './injectedBundler';\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './editor';\nexport * from './formFactor';\nexport * from './chromeState';\nexport * from './hostAttention';\nexport * from './region';\nexport * from './mounts';\nexport * from './analytics';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './ipc';\nexport * from './dnd';\nexport * from './netFetch';\nexport * from './secrets';\nexport * from './llm';\nexport * from './diagnostics';\nexport * from './vcs';\nexport * from './onFsChange';\nexport * from './fs';\nexport * from './debug';\nexport * from './tasks';\nexport * from './launch';\nexport * from './runtime';\nexport * from './irMarkers';\nexport * from './ready';\nexport * from './loading';\nexport * from './protocolStream';\nexport * from './protocolDeadline';\nexport * from './sandboxTypes';\nexport * from './safeContent';\n"],"mappings":";AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAKd,SAAS,mBAAmB;AAC5B,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,SAAS,4BAA4B,mCAAmC;AACxE,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './MDXProvider';\nexport * from './routing';\nexport * from './boot';\nexport * from './components/Include';\n// Only the component is public. `stripFrontmatter`/`appMountRelative` are module-level\n// exports so they can be unit-tested directly, NOT public API — the SDK's surface is\n// backwards-compatible forever, so an internal helper exported for a test's convenience is a\n// permanent commitment made for the wrong reason.\nexport { SafeInclude } from './components/SafeInclude';\nexport * from './sourceCache';\nexport * from './components/MDXComponents';\nexport * from './linkSpace';\nexport * from './corpus';\nexport * from './components/MountImage';\nexport * from './components/Routes';\nexport * from './hooks';\n// R3-276: the supported way for a viewer app to provide its own metadata store,\n// replacing a wholesale re-provision of `TinkerableContext` in app code.\nexport * from './metadataSource';\n// The deprecated injected-bundler adapters, re-exported so their deprecation notices\n// are visible in the published docs (R3-278; the window only narrows).\nexport { getInjectedMetadataEmitter, getInjectedMetadataSnapshot } from './injectedBundler';\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './editor';\nexport * from './formFactor';\nexport * from './chromeState';\nexport * from './hostAttention';\nexport * from './region';\nexport * from './mounts';\nexport * from './analytics';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './ipc';\nexport * from './dnd';\nexport * from './netFetch';\nexport * from './feed';\nexport * from './secrets';\nexport * from './llm';\nexport * from './diagnostics';\nexport * from './vcs';\nexport * from './onFsChange';\nexport * from './fs';\nexport * from './debug';\nexport * from './tasks';\nexport * from './launch';\nexport * from './runtime';\nexport * from './irMarkers';\nexport * from './ready';\nexport * from './loading';\nexport * from './protocolStream';\nexport * from './protocolDeadline';\nexport * from './sandboxTypes';\nexport * from './safeContent';\n"],"mappings":";AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAKd,SAAS,mBAAmB;AAC5B,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,SAAS,4BAA4B,mCAAmC;AACxE,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -29,6 +29,7 @@ const SCHEMES = {
29
29
  [import_protocol.PROTOCOL_CONTRIBUTE]: schemeOf(import_protocol.PROTOCOL_CONTRIBUTE),
30
30
  [import_protocol.PROTOCOL_DND]: schemeOf(import_protocol.PROTOCOL_DND),
31
31
  [import_protocol.PROTOCOL_EDITOR]: schemeOf(import_protocol.PROTOCOL_EDITOR),
32
+ [import_protocol.PROTOCOL_FEED]: schemeOf(import_protocol.PROTOCOL_FEED),
32
33
  [import_protocol.PROTOCOL_FETCH]: schemeOf(import_protocol.PROTOCOL_FETCH),
33
34
  [import_protocol.PROTOCOL_IPC]: schemeOf(import_protocol.PROTOCOL_IPC),
34
35
  [import_protocol.PROTOCOL_LAUNCH]: schemeOf(import_protocol.PROTOCOL_LAUNCH),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protocolSchemes.ts"],"sourcesContent":["// The `protocol-<scheme>` SCHEMES, derived from the wire names.\n//\n// `protocolRequest(scheme, method, params)` takes the scheme — `'theme'` — while the\n// wire name the frame dispatches on is `'protocol-theme'`; the frame adds the prefix.\n// So the typed service wrappers cannot pass the published `PROTOCOL_*` constant\n// directly, and spelling the scheme inline would put a second, unguarded copy of the\n// name back in the tree — exactly what R3-274c removes.\n//\n// Instead the schemes are *derived* from the wire names, keyed BY the wire name:\n//\n// protocolRequest(SCHEMES[PROTOCOL_THEME], 'set', [{ theme }])\n//\n// Keying by the constant is what makes the derivation unfalsifiable — there is no\n// second place to name the family, so there is no pair to get wrong. `schemeOf`\n// returns a template-literal conditional, so each value has a literal type (`'theme'`),\n// which buys two more things:\n//\n// - a wire name that stops matching `protocol-*` stops compiling here, rather than\n// silently producing an empty scheme at runtime;\n// - `check-protocol-snapshot.mjs` resolves `SCHEMES[PROTOCOL_THEME]` through the type\n// checker exactly like a plain literal, so the call sites stay visible to the gate.\n//\n// One export, deliberately: `./*` is a public subpath, so every name added here is\n// public API forever (ways_of_working §6, additive-only).\n//\n// This module is NOT generated — the derivation is the content — so it lives outside\n// `src/generated/`.\nimport {\n PROTOCOL_ANALYTICS,\n PROTOCOL_CONTRIBUTE,\n PROTOCOL_DND,\n PROTOCOL_EDITOR,\n PROTOCOL_FETCH,\n PROTOCOL_IPC,\n PROTOCOL_LAUNCH,\n PROTOCOL_LLM,\n PROTOCOL_SECRETS,\n PROTOCOL_SETTINGS,\n PROTOCOL_SPACES,\n PROTOCOL_TASK,\n PROTOCOL_THEME,\n PROTOCOL_VCS,\n} from './generated/protocol';\n\nconst PREFIX = 'protocol-';\n\n/** The scheme half of a `protocol-<scheme>` wire name. */\ntype SchemeOf<N extends string> = N extends `${typeof PREFIX}${infer S}` ? S : never;\n\n/**\n * `'protocol-theme'` → `'theme'`, as a literal type.\n *\n * The cast is the only place the derivation is asserted rather than computed; the\n * `N extends \\`protocol-${string}\\`` bound is what makes it sound — a wire name that is\n * not scheme-shaped is a compile error at the call, not a `never` at runtime.\n */\nconst schemeOf = <N extends `${typeof PREFIX}${string}`>(name: N): SchemeOf<N> =>\n name.slice(PREFIX.length) as SchemeOf<N>;\n\n/** Every `protocol-*` scheme the SDK speaks, keyed by its wire name. */\nexport const SCHEMES = {\n [PROTOCOL_ANALYTICS]: schemeOf(PROTOCOL_ANALYTICS),\n [PROTOCOL_CONTRIBUTE]: schemeOf(PROTOCOL_CONTRIBUTE),\n [PROTOCOL_DND]: schemeOf(PROTOCOL_DND),\n [PROTOCOL_EDITOR]: schemeOf(PROTOCOL_EDITOR),\n [PROTOCOL_FETCH]: schemeOf(PROTOCOL_FETCH),\n [PROTOCOL_IPC]: schemeOf(PROTOCOL_IPC),\n [PROTOCOL_LAUNCH]: schemeOf(PROTOCOL_LAUNCH),\n [PROTOCOL_LLM]: schemeOf(PROTOCOL_LLM),\n [PROTOCOL_SECRETS]: schemeOf(PROTOCOL_SECRETS),\n [PROTOCOL_SETTINGS]: schemeOf(PROTOCOL_SETTINGS),\n [PROTOCOL_SPACES]: schemeOf(PROTOCOL_SPACES),\n [PROTOCOL_TASK]: schemeOf(PROTOCOL_TASK),\n [PROTOCOL_THEME]: schemeOf(PROTOCOL_THEME),\n [PROTOCOL_VCS]: schemeOf(PROTOCOL_VCS),\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BA,sBAeO;AAEP,MAAM,SAAS;AAYf,MAAM,WAAW,CAAwC,SACvD,KAAK,MAAM,OAAO,MAAM;AAGnB,MAAM,UAAU;AAAA,EACrB,CAAC,kCAAkB,GAAG,SAAS,kCAAkB;AAAA,EACjD,CAAC,mCAAmB,GAAG,SAAS,mCAAmB;AAAA,EACnD,CAAC,4BAAY,GAAG,SAAS,4BAAY;AAAA,EACrC,CAAC,+BAAe,GAAG,SAAS,+BAAe;AAAA,EAC3C,CAAC,8BAAc,GAAG,SAAS,8BAAc;AAAA,EACzC,CAAC,4BAAY,GAAG,SAAS,4BAAY;AAAA,EACrC,CAAC,+BAAe,GAAG,SAAS,+BAAe;AAAA,EAC3C,CAAC,4BAAY,GAAG,SAAS,4BAAY;AAAA,EACrC,CAAC,gCAAgB,GAAG,SAAS,gCAAgB;AAAA,EAC7C,CAAC,iCAAiB,GAAG,SAAS,iCAAiB;AAAA,EAC/C,CAAC,+BAAe,GAAG,SAAS,+BAAe;AAAA,EAC3C,CAAC,6BAAa,GAAG,SAAS,6BAAa;AAAA,EACvC,CAAC,8BAAc,GAAG,SAAS,8BAAc;AAAA,EACzC,CAAC,4BAAY,GAAG,SAAS,4BAAY;AACvC;","names":[]}
1
+ {"version":3,"sources":["../src/protocolSchemes.ts"],"sourcesContent":["// The `protocol-<scheme>` SCHEMES, derived from the wire names.\n//\n// `protocolRequest(scheme, method, params)` takes the scheme — `'theme'` — while the\n// wire name the frame dispatches on is `'protocol-theme'`; the frame adds the prefix.\n// So the typed service wrappers cannot pass the published `PROTOCOL_*` constant\n// directly, and spelling the scheme inline would put a second, unguarded copy of the\n// name back in the tree — exactly what R3-274c removes.\n//\n// Instead the schemes are *derived* from the wire names, keyed BY the wire name:\n//\n// protocolRequest(SCHEMES[PROTOCOL_THEME], 'set', [{ theme }])\n//\n// Keying by the constant is what makes the derivation unfalsifiable — there is no\n// second place to name the family, so there is no pair to get wrong. `schemeOf`\n// returns a template-literal conditional, so each value has a literal type (`'theme'`),\n// which buys two more things:\n//\n// - a wire name that stops matching `protocol-*` stops compiling here, rather than\n// silently producing an empty scheme at runtime;\n// - `check-protocol-snapshot.mjs` resolves `SCHEMES[PROTOCOL_THEME]` through the type\n// checker exactly like a plain literal, so the call sites stay visible to the gate.\n//\n// One export, deliberately: `./*` is a public subpath, so every name added here is\n// public API forever (ways_of_working §6, additive-only).\n//\n// This module is NOT generated — the derivation is the content — so it lives outside\n// `src/generated/`.\nimport {\n PROTOCOL_ANALYTICS,\n PROTOCOL_CONTRIBUTE,\n PROTOCOL_DND,\n PROTOCOL_EDITOR,\n PROTOCOL_FEED,\n PROTOCOL_FETCH,\n PROTOCOL_IPC,\n PROTOCOL_LAUNCH,\n PROTOCOL_LLM,\n PROTOCOL_SECRETS,\n PROTOCOL_SETTINGS,\n PROTOCOL_SPACES,\n PROTOCOL_TASK,\n PROTOCOL_THEME,\n PROTOCOL_VCS,\n} from './generated/protocol';\n\nconst PREFIX = 'protocol-';\n\n/** The scheme half of a `protocol-<scheme>` wire name. */\ntype SchemeOf<N extends string> = N extends `${typeof PREFIX}${infer S}` ? S : never;\n\n/**\n * `'protocol-theme'` → `'theme'`, as a literal type.\n *\n * The cast is the only place the derivation is asserted rather than computed; the\n * `N extends \\`protocol-${string}\\`` bound is what makes it sound — a wire name that is\n * not scheme-shaped is a compile error at the call, not a `never` at runtime.\n */\nconst schemeOf = <N extends `${typeof PREFIX}${string}`>(name: N): SchemeOf<N> =>\n name.slice(PREFIX.length) as SchemeOf<N>;\n\n/** Every `protocol-*` scheme the SDK speaks, keyed by its wire name. */\nexport const SCHEMES = {\n [PROTOCOL_ANALYTICS]: schemeOf(PROTOCOL_ANALYTICS),\n [PROTOCOL_CONTRIBUTE]: schemeOf(PROTOCOL_CONTRIBUTE),\n [PROTOCOL_DND]: schemeOf(PROTOCOL_DND),\n [PROTOCOL_EDITOR]: schemeOf(PROTOCOL_EDITOR),\n [PROTOCOL_FEED]: schemeOf(PROTOCOL_FEED),\n [PROTOCOL_FETCH]: schemeOf(PROTOCOL_FETCH),\n [PROTOCOL_IPC]: schemeOf(PROTOCOL_IPC),\n [PROTOCOL_LAUNCH]: schemeOf(PROTOCOL_LAUNCH),\n [PROTOCOL_LLM]: schemeOf(PROTOCOL_LLM),\n [PROTOCOL_SECRETS]: schemeOf(PROTOCOL_SECRETS),\n [PROTOCOL_SETTINGS]: schemeOf(PROTOCOL_SETTINGS),\n [PROTOCOL_SPACES]: schemeOf(PROTOCOL_SPACES),\n [PROTOCOL_TASK]: schemeOf(PROTOCOL_TASK),\n [PROTOCOL_THEME]: schemeOf(PROTOCOL_THEME),\n [PROTOCOL_VCS]: schemeOf(PROTOCOL_VCS),\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BA,sBAgBO;AAEP,MAAM,SAAS;AAYf,MAAM,WAAW,CAAwC,SACvD,KAAK,MAAM,OAAO,MAAM;AAGnB,MAAM,UAAU;AAAA,EACrB,CAAC,kCAAkB,GAAG,SAAS,kCAAkB;AAAA,EACjD,CAAC,mCAAmB,GAAG,SAAS,mCAAmB;AAAA,EACnD,CAAC,4BAAY,GAAG,SAAS,4BAAY;AAAA,EACrC,CAAC,+BAAe,GAAG,SAAS,+BAAe;AAAA,EAC3C,CAAC,6BAAa,GAAG,SAAS,6BAAa;AAAA,EACvC,CAAC,8BAAc,GAAG,SAAS,8BAAc;AAAA,EACzC,CAAC,4BAAY,GAAG,SAAS,4BAAY;AAAA,EACrC,CAAC,+BAAe,GAAG,SAAS,+BAAe;AAAA,EAC3C,CAAC,4BAAY,GAAG,SAAS,4BAAY;AAAA,EACrC,CAAC,gCAAgB,GAAG,SAAS,gCAAgB;AAAA,EAC7C,CAAC,iCAAiB,GAAG,SAAS,iCAAiB;AAAA,EAC/C,CAAC,+BAAe,GAAG,SAAS,+BAAe;AAAA,EAC3C,CAAC,6BAAa,GAAG,SAAS,6BAAa;AAAA,EACvC,CAAC,8BAAc,GAAG,SAAS,8BAAc;AAAA,EACzC,CAAC,4BAAY,GAAG,SAAS,4BAAY;AACvC;","names":[]}
@@ -4,6 +4,7 @@ declare const SCHEMES: {
4
4
  readonly "protocol-contribute": "contribute";
5
5
  readonly "protocol-dnd": "dnd";
6
6
  readonly "protocol-editor": "editor";
7
+ readonly "protocol-feed": "feed";
7
8
  readonly "protocol-fetch": "fetch";
8
9
  readonly "protocol-ipc": "ipc";
9
10
  readonly "protocol-launch": "launch";
@@ -4,6 +4,7 @@ declare const SCHEMES: {
4
4
  readonly "protocol-contribute": "contribute";
5
5
  readonly "protocol-dnd": "dnd";
6
6
  readonly "protocol-editor": "editor";
7
+ readonly "protocol-feed": "feed";
7
8
  readonly "protocol-fetch": "fetch";
8
9
  readonly "protocol-ipc": "ipc";
9
10
  readonly "protocol-launch": "launch";
@@ -4,6 +4,7 @@ import {
4
4
  PROTOCOL_CONTRIBUTE,
5
5
  PROTOCOL_DND,
6
6
  PROTOCOL_EDITOR,
7
+ PROTOCOL_FEED,
7
8
  PROTOCOL_FETCH,
8
9
  PROTOCOL_IPC,
9
10
  PROTOCOL_LAUNCH,
@@ -22,6 +23,7 @@ const SCHEMES = {
22
23
  [PROTOCOL_CONTRIBUTE]: schemeOf(PROTOCOL_CONTRIBUTE),
23
24
  [PROTOCOL_DND]: schemeOf(PROTOCOL_DND),
24
25
  [PROTOCOL_EDITOR]: schemeOf(PROTOCOL_EDITOR),
26
+ [PROTOCOL_FEED]: schemeOf(PROTOCOL_FEED),
25
27
  [PROTOCOL_FETCH]: schemeOf(PROTOCOL_FETCH),
26
28
  [PROTOCOL_IPC]: schemeOf(PROTOCOL_IPC),
27
29
  [PROTOCOL_LAUNCH]: schemeOf(PROTOCOL_LAUNCH),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/protocolSchemes.ts"],"sourcesContent":["// The `protocol-<scheme>` SCHEMES, derived from the wire names.\n//\n// `protocolRequest(scheme, method, params)` takes the scheme — `'theme'` — while the\n// wire name the frame dispatches on is `'protocol-theme'`; the frame adds the prefix.\n// So the typed service wrappers cannot pass the published `PROTOCOL_*` constant\n// directly, and spelling the scheme inline would put a second, unguarded copy of the\n// name back in the tree — exactly what R3-274c removes.\n//\n// Instead the schemes are *derived* from the wire names, keyed BY the wire name:\n//\n// protocolRequest(SCHEMES[PROTOCOL_THEME], 'set', [{ theme }])\n//\n// Keying by the constant is what makes the derivation unfalsifiable — there is no\n// second place to name the family, so there is no pair to get wrong. `schemeOf`\n// returns a template-literal conditional, so each value has a literal type (`'theme'`),\n// which buys two more things:\n//\n// - a wire name that stops matching `protocol-*` stops compiling here, rather than\n// silently producing an empty scheme at runtime;\n// - `check-protocol-snapshot.mjs` resolves `SCHEMES[PROTOCOL_THEME]` through the type\n// checker exactly like a plain literal, so the call sites stay visible to the gate.\n//\n// One export, deliberately: `./*` is a public subpath, so every name added here is\n// public API forever (ways_of_working §6, additive-only).\n//\n// This module is NOT generated — the derivation is the content — so it lives outside\n// `src/generated/`.\nimport {\n PROTOCOL_ANALYTICS,\n PROTOCOL_CONTRIBUTE,\n PROTOCOL_DND,\n PROTOCOL_EDITOR,\n PROTOCOL_FETCH,\n PROTOCOL_IPC,\n PROTOCOL_LAUNCH,\n PROTOCOL_LLM,\n PROTOCOL_SECRETS,\n PROTOCOL_SETTINGS,\n PROTOCOL_SPACES,\n PROTOCOL_TASK,\n PROTOCOL_THEME,\n PROTOCOL_VCS,\n} from './generated/protocol';\n\nconst PREFIX = 'protocol-';\n\n/** The scheme half of a `protocol-<scheme>` wire name. */\ntype SchemeOf<N extends string> = N extends `${typeof PREFIX}${infer S}` ? S : never;\n\n/**\n * `'protocol-theme'` → `'theme'`, as a literal type.\n *\n * The cast is the only place the derivation is asserted rather than computed; the\n * `N extends \\`protocol-${string}\\`` bound is what makes it sound — a wire name that is\n * not scheme-shaped is a compile error at the call, not a `never` at runtime.\n */\nconst schemeOf = <N extends `${typeof PREFIX}${string}`>(name: N): SchemeOf<N> =>\n name.slice(PREFIX.length) as SchemeOf<N>;\n\n/** Every `protocol-*` scheme the SDK speaks, keyed by its wire name. */\nexport const SCHEMES = {\n [PROTOCOL_ANALYTICS]: schemeOf(PROTOCOL_ANALYTICS),\n [PROTOCOL_CONTRIBUTE]: schemeOf(PROTOCOL_CONTRIBUTE),\n [PROTOCOL_DND]: schemeOf(PROTOCOL_DND),\n [PROTOCOL_EDITOR]: schemeOf(PROTOCOL_EDITOR),\n [PROTOCOL_FETCH]: schemeOf(PROTOCOL_FETCH),\n [PROTOCOL_IPC]: schemeOf(PROTOCOL_IPC),\n [PROTOCOL_LAUNCH]: schemeOf(PROTOCOL_LAUNCH),\n [PROTOCOL_LLM]: schemeOf(PROTOCOL_LLM),\n [PROTOCOL_SECRETS]: schemeOf(PROTOCOL_SECRETS),\n [PROTOCOL_SETTINGS]: schemeOf(PROTOCOL_SETTINGS),\n [PROTOCOL_SPACES]: schemeOf(PROTOCOL_SPACES),\n [PROTOCOL_TASK]: schemeOf(PROTOCOL_TASK),\n [PROTOCOL_THEME]: schemeOf(PROTOCOL_THEME),\n [PROTOCOL_VCS]: schemeOf(PROTOCOL_VCS),\n} as const;\n"],"mappings":";AA2BA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,MAAM,SAAS;AAYf,MAAM,WAAW,CAAwC,SACvD,KAAK,MAAM,OAAO,MAAM;AAGnB,MAAM,UAAU;AAAA,EACrB,CAAC,kBAAkB,GAAG,SAAS,kBAAkB;AAAA,EACjD,CAAC,mBAAmB,GAAG,SAAS,mBAAmB;AAAA,EACnD,CAAC,YAAY,GAAG,SAAS,YAAY;AAAA,EACrC,CAAC,eAAe,GAAG,SAAS,eAAe;AAAA,EAC3C,CAAC,cAAc,GAAG,SAAS,cAAc;AAAA,EACzC,CAAC,YAAY,GAAG,SAAS,YAAY;AAAA,EACrC,CAAC,eAAe,GAAG,SAAS,eAAe;AAAA,EAC3C,CAAC,YAAY,GAAG,SAAS,YAAY;AAAA,EACrC,CAAC,gBAAgB,GAAG,SAAS,gBAAgB;AAAA,EAC7C,CAAC,iBAAiB,GAAG,SAAS,iBAAiB;AAAA,EAC/C,CAAC,eAAe,GAAG,SAAS,eAAe;AAAA,EAC3C,CAAC,aAAa,GAAG,SAAS,aAAa;AAAA,EACvC,CAAC,cAAc,GAAG,SAAS,cAAc;AAAA,EACzC,CAAC,YAAY,GAAG,SAAS,YAAY;AACvC;","names":[]}
1
+ {"version":3,"sources":["../src/protocolSchemes.ts"],"sourcesContent":["// The `protocol-<scheme>` SCHEMES, derived from the wire names.\n//\n// `protocolRequest(scheme, method, params)` takes the scheme — `'theme'` — while the\n// wire name the frame dispatches on is `'protocol-theme'`; the frame adds the prefix.\n// So the typed service wrappers cannot pass the published `PROTOCOL_*` constant\n// directly, and spelling the scheme inline would put a second, unguarded copy of the\n// name back in the tree — exactly what R3-274c removes.\n//\n// Instead the schemes are *derived* from the wire names, keyed BY the wire name:\n//\n// protocolRequest(SCHEMES[PROTOCOL_THEME], 'set', [{ theme }])\n//\n// Keying by the constant is what makes the derivation unfalsifiable — there is no\n// second place to name the family, so there is no pair to get wrong. `schemeOf`\n// returns a template-literal conditional, so each value has a literal type (`'theme'`),\n// which buys two more things:\n//\n// - a wire name that stops matching `protocol-*` stops compiling here, rather than\n// silently producing an empty scheme at runtime;\n// - `check-protocol-snapshot.mjs` resolves `SCHEMES[PROTOCOL_THEME]` through the type\n// checker exactly like a plain literal, so the call sites stay visible to the gate.\n//\n// One export, deliberately: `./*` is a public subpath, so every name added here is\n// public API forever (ways_of_working §6, additive-only).\n//\n// This module is NOT generated — the derivation is the content — so it lives outside\n// `src/generated/`.\nimport {\n PROTOCOL_ANALYTICS,\n PROTOCOL_CONTRIBUTE,\n PROTOCOL_DND,\n PROTOCOL_EDITOR,\n PROTOCOL_FEED,\n PROTOCOL_FETCH,\n PROTOCOL_IPC,\n PROTOCOL_LAUNCH,\n PROTOCOL_LLM,\n PROTOCOL_SECRETS,\n PROTOCOL_SETTINGS,\n PROTOCOL_SPACES,\n PROTOCOL_TASK,\n PROTOCOL_THEME,\n PROTOCOL_VCS,\n} from './generated/protocol';\n\nconst PREFIX = 'protocol-';\n\n/** The scheme half of a `protocol-<scheme>` wire name. */\ntype SchemeOf<N extends string> = N extends `${typeof PREFIX}${infer S}` ? S : never;\n\n/**\n * `'protocol-theme'` → `'theme'`, as a literal type.\n *\n * The cast is the only place the derivation is asserted rather than computed; the\n * `N extends \\`protocol-${string}\\`` bound is what makes it sound — a wire name that is\n * not scheme-shaped is a compile error at the call, not a `never` at runtime.\n */\nconst schemeOf = <N extends `${typeof PREFIX}${string}`>(name: N): SchemeOf<N> =>\n name.slice(PREFIX.length) as SchemeOf<N>;\n\n/** Every `protocol-*` scheme the SDK speaks, keyed by its wire name. */\nexport const SCHEMES = {\n [PROTOCOL_ANALYTICS]: schemeOf(PROTOCOL_ANALYTICS),\n [PROTOCOL_CONTRIBUTE]: schemeOf(PROTOCOL_CONTRIBUTE),\n [PROTOCOL_DND]: schemeOf(PROTOCOL_DND),\n [PROTOCOL_EDITOR]: schemeOf(PROTOCOL_EDITOR),\n [PROTOCOL_FEED]: schemeOf(PROTOCOL_FEED),\n [PROTOCOL_FETCH]: schemeOf(PROTOCOL_FETCH),\n [PROTOCOL_IPC]: schemeOf(PROTOCOL_IPC),\n [PROTOCOL_LAUNCH]: schemeOf(PROTOCOL_LAUNCH),\n [PROTOCOL_LLM]: schemeOf(PROTOCOL_LLM),\n [PROTOCOL_SECRETS]: schemeOf(PROTOCOL_SECRETS),\n [PROTOCOL_SETTINGS]: schemeOf(PROTOCOL_SETTINGS),\n [PROTOCOL_SPACES]: schemeOf(PROTOCOL_SPACES),\n [PROTOCOL_TASK]: schemeOf(PROTOCOL_TASK),\n [PROTOCOL_THEME]: schemeOf(PROTOCOL_THEME),\n [PROTOCOL_VCS]: schemeOf(PROTOCOL_VCS),\n} as const;\n"],"mappings":";AA2BA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,MAAM,SAAS;AAYf,MAAM,WAAW,CAAwC,SACvD,KAAK,MAAM,OAAO,MAAM;AAGnB,MAAM,UAAU;AAAA,EACrB,CAAC,kBAAkB,GAAG,SAAS,kBAAkB;AAAA,EACjD,CAAC,mBAAmB,GAAG,SAAS,mBAAmB;AAAA,EACnD,CAAC,YAAY,GAAG,SAAS,YAAY;AAAA,EACrC,CAAC,eAAe,GAAG,SAAS,eAAe;AAAA,EAC3C,CAAC,aAAa,GAAG,SAAS,aAAa;AAAA,EACvC,CAAC,cAAc,GAAG,SAAS,cAAc;AAAA,EACzC,CAAC,YAAY,GAAG,SAAS,YAAY;AAAA,EACrC,CAAC,eAAe,GAAG,SAAS,eAAe;AAAA,EAC3C,CAAC,YAAY,GAAG,SAAS,YAAY;AAAA,EACrC,CAAC,gBAAgB,GAAG,SAAS,gBAAgB;AAAA,EAC7C,CAAC,iBAAiB,GAAG,SAAS,iBAAiB;AAAA,EAC/C,CAAC,eAAe,GAAG,SAAS,eAAe;AAAA,EAC3C,CAAC,aAAa,GAAG,SAAS,aAAa;AAAA,EACvC,CAAC,cAAc,GAAG,SAAS,cAAc;AAAA,EACzC,CAAC,YAAY,GAAG,SAAS,YAAY;AACvC;","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.53.0";
24
+ const SDK_VERSION = "0.55.0";
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.53.0';\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.55.0';\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.53.0";
2
+ declare const SDK_VERSION = "0.55.0";
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.53.0";
2
+ declare const SDK_VERSION = "0.55.0";
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.53.0";
2
+ const SDK_VERSION = "0.55.0";
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.53.0';\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.55.0';\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.53.0",
3
+ "version": "0.55.0",
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",
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "@immediately-run/platform-constants": "0.2.0",
64
- "@immediately-run/sandbox-protocol": "0.6.0",
64
+ "@immediately-run/sandbox-protocol": "0.7.1",
65
65
  "react-error-boundary": "^6.0.0",
66
66
  "@immediately-run/safe-content": "0.1.0",
67
67
  "@immediately-run/mdx-plugins": "0.5.0"