@ocno/oryn-sdk 0.0.0-stage → 0.1.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.
@@ -0,0 +1,3 @@
1
+ # Contributing
2
+
3
+ Public API changes require type tests, runtime tests, and a semantic-versioning decision. Run `pnpm typecheck && pnpm test && pnpm build` before proposing a change.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OCNO
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,185 @@
1
- # Temporary Holding Version
1
+ # Oryn SDK
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Local AI for ordinary websites.** `@ocno/oryn-sdk` is a TypeScript-first ESM client for Oryn Browser. Request a model, submit a job, and receive streaming text, structured data, or media artifacts through one framework-independent API.
4
+
5
+ **[Quickstart](#stream-your-first-response) · [API reference](docs/api-reference.md) · [Recipes](docs/recipes.md)**
6
+
7
+ - No runtime dependencies on React, Electron, Node.js, Python, or an inference engine.
8
+ - Safe to import and create during server-side rendering.
9
+ - Typed model requests, job events, artifacts, and task contracts.
10
+ - Browser-owned permission, model choice, and origin isolation.
11
+
12
+ > **Developer alpha · 0.1.0**
13
+ >
14
+ > LocalAI requires a compatible Oryn Browser. Installing this package alone does not provide model execution.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install @ocno/oryn-sdk
20
+ ```
21
+
22
+ The package exports ESM and TypeScript declarations. Execute Local AI feature work in the browser, from a deliberate user action. Serve production integrations over HTTPS; use loopback origins for development.
23
+
24
+ ## Stream your first response
25
+
26
+ This function requests a chat model, streams text into your callback, handles terminal failure/cancellation, and releases the session. Call it from your Send button and pass an `AbortController` signal from your Cancel button.
27
+
28
+ ```ts
29
+ import {
30
+ createLocalAIClient,
31
+ invokeStream,
32
+ LocalAIError,
33
+ } from "@ocno/oryn-sdk";
34
+
35
+ export async function streamReply(
36
+ prompt: string,
37
+ appendText: (text: string) => void,
38
+ signal: AbortSignal,
39
+ ): Promise<void> {
40
+ const localAI = createLocalAIClient();
41
+ const capabilities = await localAI.getCapabilities();
42
+ if (!capabilities.runtimeAvailable) {
43
+ throw new Error("Open this page in Oryn with Local AI available.");
44
+ }
45
+
46
+ const session = await localAI.models.request(
47
+ {
48
+ role: "chat",
49
+ requirements: {
50
+ task: "text-generation",
51
+ inputModalities: ["text"],
52
+ outputModalities: ["text"],
53
+ capabilities: { chat: true, streaming: true },
54
+ },
55
+ },
56
+ { signal, onProgress: (progress) => console.info(progress.stage) },
57
+ );
58
+
59
+ try {
60
+ for await (const event of invokeStream(
61
+ localAI,
62
+ {
63
+ sessionId: session.sessionId,
64
+ input: { messages: [{ role: "user", content: prompt }] },
65
+ },
66
+ { signal },
67
+ )) {
68
+ if (event.event === "job.output.delta" && event.data.channel === "text") {
69
+ appendText(String(event.data.delta));
70
+ } else if (event.event === "job.failed") {
71
+ throw new LocalAIError(event.data.error);
72
+ } else if (event.event === "job.cancelled") {
73
+ throw new LocalAIError({
74
+ code: "REQUEST_ABORTED",
75
+ message: "Generation was cancelled.",
76
+ });
77
+ }
78
+ }
79
+ } finally {
80
+ await localAI.models.releaseSession(session.sessionId);
81
+ }
82
+ }
83
+ ```
84
+
85
+ A capability-only request lets Oryn resolve a matching model. It may require model choice, permission, or a download; it can fail if no executable match exists. To suggest a particular model, use the [model selection recipe](docs/recipes.md#choose-a-model).
86
+
87
+ `invokeStream()` yields **all** job events, including terminal failure and cancellation. It does not convert those terminal events into thrown errors. `invokeAndWait()` does that conversion for callers that want a final result. Both helpers subscribe before submitting the job.
88
+
89
+ ## The request lifecycle
90
+
91
+ ![SDK lifecycle: detect capabilities, resolve a model with browser consent, receive a session, invoke a queued job, observe events and a terminal outcome, then release sessions and artifacts.](docs/images/request-lifecycle.png)
92
+
93
+ [View the full-size lifecycle diagram](docs/images/request-lifecycle.svg).
94
+
95
+ | Concept | Meaning |
96
+ | --- | --- |
97
+ | **Client** | A lightweight wrapper around Oryn's injected website bridge |
98
+ | **Model request** | Your task, preferred model or capability requirements, and substitution policy |
99
+ | **Session** | An origin-bound handle to the resolved model and its effective task capabilities |
100
+ | **Job** | One asynchronous invocation, with queue/progress/output and a terminal event |
101
+ | **Artifact** | An opaque capability for binary input or output |
102
+
103
+ A session can be reused across jobs. The quickstart releases it after one response for clarity; a chat app can keep one while the conversation UI is active. Release it when the feature is disposed.
104
+
105
+ ## Detect Oryn and provide a fallback
106
+
107
+ ```ts
108
+ import { createLocalAIClient } from "@ocno/oryn-sdk";
109
+
110
+ export async function canUseLocalAI(): Promise<boolean> {
111
+ const localAI = createLocalAIClient();
112
+ return (await localAI.getCapabilities()).runtimeAvailable;
113
+ }
114
+ ```
115
+
116
+ Outside Oryn, `getCapabilities()` resolves with `runtimeAvailable: false`. Privileged operations reject with `LocalAIError` code `RUNTIME_NOT_AVAILABLE`. Importing and creating the client are SSR-safe; model requests and jobs belong in client-side code.
117
+
118
+ Build your own explanation, disable the local action, or offer a clearly disclosed fallback. You can optionally create the client with `{ showOrynBrowserAlert: true }` to show a website-owned Oryn explanation once per document outside Oryn. It is off by default and is not a trusted permission prompt.
119
+
120
+ ## Pick the right invocation API
121
+
122
+ | API | Use it when | Completion behavior |
123
+ | --- | --- | --- |
124
+ | `invokeAndWait(client, request, options)` | You need the final structured/media result | Resolves on completion; rejects on job failure or cancellation |
125
+ | `invokeStream(client, request, options)` | You need incremental text, progress, or previews | Yields events through the terminal event; inspect its outcome |
126
+ | `client.invoke(request)` + `client.subscribe(listener)` | You manage your own job state | Returns a job reference; subscribe before invocation and filter by job ID |
127
+
128
+ Pass `signal` to model requests and helpers for cancellation. `client.cancel(jobId)` targets a known job directly. Breaking out of a stream only unsubscribes the helper; it does not cancel the underlying job. Read the [cancellation notes](docs/api-reference.md#cancellation-and-cleanup) before building a custom job manager.
129
+
130
+ ## Work with files and results
131
+
132
+ Use `artifacts.create(fileOrBlob)` for binary input and put the returned ID in the task input. Results use one of three shapes:
133
+
134
+ | `result.kind` | Payload |
135
+ | --- | --- |
136
+ | `structured` | `result.value`: task-specific JSON |
137
+ | `artifact` | `result.artifact`: metadata for an image, audio file, video, or other output |
138
+ | `multi` | `result.outputs`: a list of result envelopes |
139
+
140
+ Display media with `artifacts.getUrl(id)`, read complete bytes with `artifacts.readBlob(id)`, or open a trusted save dialog with `artifacts.saveAs(id)`. Release artifacts after their final consumer is finished. An upload is a separate, explicit website action.
141
+
142
+ See [transcription](docs/recipes.md#transcribe-a-wav-file) and [media outputs](docs/recipes.md#display-save-and-upload-an-output) for complete examples. Artifact IDs and URLs do not expose local paths and should not be treated as permanent links.
143
+
144
+ ## Handle expected failures
145
+
146
+ Use `LocalAIError.code`, not the English message, for application behavior. Common cases include:
147
+
148
+ | Code | Suggested UI |
149
+ | --- | --- |
150
+ | `RUNTIME_NOT_AVAILABLE`, `RUNTIME_STARTING` | Show availability state or a fallback |
151
+ | `USER_DENIED`, `PERMISSION_DENIED` | Respect the decision and leave the feature idle |
152
+ | `NO_EXECUTABLE_MODEL`, `MODEL_NOT_EXECUTABLE` | Explain the unmet model/task requirement |
153
+ | `MODEL_OUT_OF_MEMORY`, `RESOURCE_REQUIREMENTS_UNSATISFIABLE` | Offer a smaller compatible model or lower supported settings |
154
+ | `JOB_QUEUE_FULL` | Keep the input and let the user retry later |
155
+ | `REQUEST_ABORTED`, `JOB_CANCELLED` | Treat cancellation as an ordinary outcome |
156
+
157
+ Browser/Engine failures are sanitized at the bridge. Application code and some local validation or network operations can also throw ordinary JavaScript errors, so retain a general error path.
158
+
159
+ ## Task profiles and compatibility
160
+
161
+ Check `capabilities.features.taskProfiles` before opting into versioned task requirements. A returned `session.taskProfile` describes effective features, parameter bounds/defaults, limits, and streaming channels. Requirements must not silently disappear on an older browser; if a feature is necessary for your app, explain that it is unavailable.
162
+
163
+ `SharedTaskInputs`, `SharedTaskOutputs`, and `validateSharedTaskInput` support additional typed tasks. Their presence describes data contracts, not availability of a model on a particular device. See the [typed-task recipe](docs/recipes.md#use-a-typed-task-contract).
164
+
165
+ The npm version and `localAI.sdkVersion` identify the SDK. `browserApiVersion` identifies the injected browser API; task contracts carry their own revisions. Check feature flags and effective profiles instead of inferring support from the SDK version alone. The current `0.1.0` API is a developer alpha and may evolve before a stable release.
166
+
167
+ ## Develop the SDK
168
+
169
+ From this directory:
170
+
171
+ ```bash
172
+ pnpm install --frozen-lockfile
173
+ pnpm typecheck
174
+ pnpm test
175
+ pnpm build
176
+ pnpm pack
177
+ ```
178
+
179
+ The `dist` and `docs` directories, this README, and the MIT license are included in the package. Documentation examples are checked against the SDK types from the full workspace with `node scripts/check-public-docs.mjs`.
180
+
181
+ Read [CONTRIBUTING.md](CONTRIBUTING.md) for API change requirements and [SECURITY.md](SECURITY.md) for sensitive reports.
182
+
183
+ ## License
184
+
185
+ Oryn SDK is licensed under the [MIT License](LICENSE).
package/SECURITY.md ADDED
@@ -0,0 +1,3 @@
1
+ # Security
2
+
3
+ Do not report capability-boundary vulnerabilities in a public issue. Until a public security contact is configured, contact the project owner privately.