@tarkahq/sdk 0.0.0-stage → 0.3.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/LICENSE +201 -0
- package/NOTICE +69 -0
- package/README.md +700 -2
- package/api-source.json +38 -0
- package/dist/cjs/client.d.ts +114 -0
- package/dist/cjs/client.js +174 -0
- package/dist/cjs/errors.d.ts +27 -0
- package/dist/cjs/errors.js +78 -0
- package/dist/cjs/generated/google/api/annotations.d.ts +1 -0
- package/dist/cjs/generated/google/api/annotations.js +10 -0
- package/dist/cjs/generated/google/api/http.d.ts +395 -0
- package/dist/cjs/generated/google/api/http.js +421 -0
- package/dist/cjs/generated/google/protobuf/descriptor.d.ts +873 -0
- package/dist/cjs/generated/google/protobuf/descriptor.js +3992 -0
- package/dist/cjs/generated/google/protobuf/empty.d.ts +35 -0
- package/dist/cjs/generated/google/protobuf/empty.js +58 -0
- package/dist/cjs/generated/google/protobuf/struct.d.ts +127 -0
- package/dist/cjs/generated/google/protobuf/struct.js +529 -0
- package/dist/cjs/generated/google/protobuf/timestamp.d.ts +128 -0
- package/dist/cjs/generated/google/protobuf/timestamp.js +95 -0
- package/dist/cjs/generated/protoc-gen-openapiv2/options/annotations.d.ts +1 -0
- package/dist/cjs/generated/protoc-gen-openapiv2/options/annotations.js +10 -0
- package/dist/cjs/generated/protoc-gen-openapiv2/options/openapiv2.d.ts +983 -0
- package/dist/cjs/generated/protoc-gen-openapiv2/options/openapiv2.js +4874 -0
- package/dist/cjs/generated/tarka/access/v1/access.d.ts +322 -0
- package/dist/cjs/generated/tarka/access/v1/access.js +2979 -0
- package/dist/cjs/generated/tarka/channels/v1/channels.d.ts +370 -0
- package/dist/cjs/generated/tarka/channels/v1/channels.js +3603 -0
- package/dist/cjs/generated/tarka/gateway/v1/gateway.d.ts +804 -0
- package/dist/cjs/generated/tarka/gateway/v1/gateway.js +8081 -0
- package/dist/cjs/generated/tarka/iam/v1/iam.d.ts +1291 -0
- package/dist/cjs/generated/tarka/iam/v1/iam.js +13207 -0
- package/dist/cjs/generated/tarka/inference/v1/inference.d.ts +699 -0
- package/dist/cjs/generated/tarka/inference/v1/inference.js +7058 -0
- package/dist/cjs/generated/tarka/provisioning/v1/agent_secrets.d.ts +70 -0
- package/dist/cjs/generated/tarka/provisioning/v1/agent_secrets.js +603 -0
- package/dist/cjs/generated/tarka/provisioning/v1/billing_quote.d.ts +171 -0
- package/dist/cjs/generated/tarka/provisioning/v1/billing_quote.js +1588 -0
- package/dist/cjs/generated/tarka/provisioning/v1/job.d.ts +168 -0
- package/dist/cjs/generated/tarka/provisioning/v1/job.js +1505 -0
- package/dist/cjs/generated/tarka/provisioning/v1/provisioning.d.ts +2644 -0
- package/dist/cjs/generated/tarka/provisioning/v1/provisioning.js +19501 -0
- package/dist/cjs/generated/tarka/provisioning/v1/registry_credentials.d.ts +89 -0
- package/dist/cjs/generated/tarka/provisioning/v1/registry_credentials.js +856 -0
- package/dist/cjs/generated/tarka/provisioning/v1/sandbox.d.ts +431 -0
- package/dist/cjs/generated/tarka/provisioning/v1/sandbox.js +3203 -0
- package/dist/cjs/generated/tarka/provisioning/v1/source_builds.d.ts +291 -0
- package/dist/cjs/generated/tarka/provisioning/v1/source_builds.js +3920 -0
- package/dist/cjs/grpc.d.ts +12 -0
- package/dist/cjs/grpc.js +55 -0
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.js +21 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/resources/inference.d.ts +293 -0
- package/dist/cjs/resources/inference.js +451 -0
- package/dist/cjs/resources/provisioning.d.ts +389 -0
- package/dist/cjs/resources/provisioning.js +552 -0
- package/dist/cjs/resources/sandboxes.d.ts +360 -0
- package/dist/cjs/resources/sandboxes.js +732 -0
- package/dist/cjs/rpc-types.d.ts +36 -0
- package/dist/cjs/rpc-types.js +29 -0
- package/dist/cjs/runtime.d.ts +99 -0
- package/dist/cjs/runtime.js +473 -0
- package/dist/cjs/transport.d.ts +60 -0
- package/dist/cjs/transport.js +114 -0
- package/dist/cjs/types.d.ts +309 -0
- package/dist/cjs/types.js +2 -0
- package/dist/esm/client.d.ts +114 -0
- package/dist/esm/client.js +169 -0
- package/dist/esm/errors.d.ts +27 -0
- package/dist/esm/errors.js +71 -0
- package/dist/esm/generated/google/api/annotations.d.ts +1 -0
- package/dist/esm/generated/google/api/annotations.js +7 -0
- package/dist/esm/generated/google/api/http.d.ts +395 -0
- package/dist/esm/generated/google/api/http.js +418 -0
- package/dist/esm/generated/google/protobuf/descriptor.d.ts +873 -0
- package/dist/esm/generated/google/protobuf/descriptor.js +3977 -0
- package/dist/esm/generated/google/protobuf/empty.d.ts +35 -0
- package/dist/esm/generated/google/protobuf/empty.js +55 -0
- package/dist/esm/generated/google/protobuf/struct.d.ts +127 -0
- package/dist/esm/generated/google/protobuf/struct.js +524 -0
- package/dist/esm/generated/google/protobuf/timestamp.d.ts +128 -0
- package/dist/esm/generated/google/protobuf/timestamp.js +92 -0
- package/dist/esm/generated/protoc-gen-openapiv2/options/annotations.d.ts +1 -0
- package/dist/esm/generated/protoc-gen-openapiv2/options/annotations.js +7 -0
- package/dist/esm/generated/protoc-gen-openapiv2/options/openapiv2.d.ts +983 -0
- package/dist/esm/generated/protoc-gen-openapiv2/options/openapiv2.js +4859 -0
- package/dist/esm/generated/tarka/access/v1/access.d.ts +322 -0
- package/dist/esm/generated/tarka/access/v1/access.js +2976 -0
- package/dist/esm/generated/tarka/channels/v1/channels.d.ts +370 -0
- package/dist/esm/generated/tarka/channels/v1/channels.js +3600 -0
- package/dist/esm/generated/tarka/gateway/v1/gateway.d.ts +804 -0
- package/dist/esm/generated/tarka/gateway/v1/gateway.js +8077 -0
- package/dist/esm/generated/tarka/iam/v1/iam.d.ts +1291 -0
- package/dist/esm/generated/tarka/iam/v1/iam.js +13203 -0
- package/dist/esm/generated/tarka/inference/v1/inference.d.ts +699 -0
- package/dist/esm/generated/tarka/inference/v1/inference.js +7055 -0
- package/dist/esm/generated/tarka/provisioning/v1/agent_secrets.d.ts +70 -0
- package/dist/esm/generated/tarka/provisioning/v1/agent_secrets.js +600 -0
- package/dist/esm/generated/tarka/provisioning/v1/billing_quote.d.ts +171 -0
- package/dist/esm/generated/tarka/provisioning/v1/billing_quote.js +1585 -0
- package/dist/esm/generated/tarka/provisioning/v1/job.d.ts +168 -0
- package/dist/esm/generated/tarka/provisioning/v1/job.js +1500 -0
- package/dist/esm/generated/tarka/provisioning/v1/provisioning.d.ts +2644 -0
- package/dist/esm/generated/tarka/provisioning/v1/provisioning.js +19496 -0
- package/dist/esm/generated/tarka/provisioning/v1/registry_credentials.d.ts +89 -0
- package/dist/esm/generated/tarka/provisioning/v1/registry_credentials.js +853 -0
- package/dist/esm/generated/tarka/provisioning/v1/sandbox.d.ts +431 -0
- package/dist/esm/generated/tarka/provisioning/v1/sandbox.js +3192 -0
- package/dist/esm/generated/tarka/provisioning/v1/source_builds.d.ts +291 -0
- package/dist/esm/generated/tarka/provisioning/v1/source_builds.js +3917 -0
- package/dist/esm/grpc.d.ts +12 -0
- package/dist/esm/grpc.js +11 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/resources/inference.d.ts +293 -0
- package/dist/esm/resources/inference.js +437 -0
- package/dist/esm/resources/provisioning.d.ts +389 -0
- package/dist/esm/resources/provisioning.js +531 -0
- package/dist/esm/resources/sandboxes.d.ts +360 -0
- package/dist/esm/resources/sandboxes.js +718 -0
- package/dist/esm/rpc-types.d.ts +36 -0
- package/dist/esm/rpc-types.js +26 -0
- package/dist/esm/runtime.d.ts +99 -0
- package/dist/esm/runtime.js +466 -0
- package/dist/esm/transport.d.ts +60 -0
- package/dist/esm/transport.js +110 -0
- package/dist/esm/types.d.ts +309 -0
- package/dist/esm/types.js +1 -0
- package/package.json +155 -4
package/README.md
CHANGED
|
@@ -1,3 +1,701 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Tarka JavaScript SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The official Tarka SDK for JavaScript and TypeScript. A resource API for
|
|
4
|
+
inference, organizations, compute, storage, Git, and sandboxes, backed by
|
|
5
|
+
generated protobuf bindings from the same contract as the
|
|
6
|
+
[Python SDK](https://github.com/TarkaHQ/sdk-python).
|
|
7
|
+
|
|
8
|
+
```js
|
|
9
|
+
const models = await client.models.list();
|
|
10
|
+
const text = await client.chat.text({ model, prompt: "Hello!" });
|
|
11
|
+
const sandbox = await client.org(orgId).sandboxes.create({ template });
|
|
12
|
+
const result = await sandbox.run('print("Hello from Tarka")');
|
|
13
|
+
console.log(result.status, result.stdout);
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- Node.js 22+, with ESM, CommonJS, and TypeScript declarations.
|
|
17
|
+
- Wrappers for all 60 RPCs in the pinned API contract.
|
|
18
|
+
- Arrays from lists, entities from reads and writes, async iterables from streams.
|
|
19
|
+
- Organization context, readable statuses, and recoverable sandbox operations.
|
|
20
|
+
- Two direct runtime dependencies: `@grpc/grpc-js` and `@bufbuild/protobuf`.
|
|
21
|
+
- Raw transport access stays under `client.grpc` and `@tarkahq/sdk/grpc`.
|
|
22
|
+
|
|
23
|
+
This version targets Node.js, including server applications. Browser and edge
|
|
24
|
+
runtimes without Node's HTTP/2 support are outside its scope.
|
|
25
|
+
|
|
26
|
+
Inference uses `tarka.inference.v1.InferenceService`. Regenerate native gRPC
|
|
27
|
+
clients when upgrading from the previous inference namespace; RPC paths and
|
|
28
|
+
generated import paths now use `v1`. The resource API is unchanged.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
The intended npm package name is `@tarkahq/sdk`. This repository does not imply
|
|
33
|
+
that the package is already published. To use this version locally:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
git clone https://github.com/TarkaHQ/sdk-javascript.git
|
|
37
|
+
cd sdk-javascript
|
|
38
|
+
npm ci
|
|
39
|
+
npm pack
|
|
40
|
+
# From your application directory:
|
|
41
|
+
npm install /path/to/sdk-javascript/tarkahq-sdk-0.3.0.tgz
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
After publication, use `npm install @tarkahq/sdk`. Consumers need neither
|
|
45
|
+
`protoc` nor an API checkout; the package includes generated code and types.
|
|
46
|
+
|
|
47
|
+
## Quick start
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
import { TarkaClient } from "@tarkahq/sdk";
|
|
51
|
+
|
|
52
|
+
const accessToken = process.env.TARKA_API_KEY;
|
|
53
|
+
const model = process.env.TARKA_MODEL;
|
|
54
|
+
if (!accessToken || !model) {
|
|
55
|
+
throw new Error("Set TARKA_API_KEY and TARKA_MODEL");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const client = new TarkaClient({ accessToken, timeoutMs: 30_000 });
|
|
59
|
+
try {
|
|
60
|
+
console.log(await client.models.list());
|
|
61
|
+
console.log(
|
|
62
|
+
await client.chat.text({
|
|
63
|
+
model,
|
|
64
|
+
prompt: "Say hello in Nepali.",
|
|
65
|
+
maxTokens: 100,
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
} finally {
|
|
69
|
+
client.close();
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
CommonJS: `const { TarkaClient } = require("@tarkahq/sdk")`.
|
|
74
|
+
Reuse one client across requests and close it on application shutdown.
|
|
75
|
+
`close()` is idempotent and closes only connections owned by the SDK.
|
|
76
|
+
Runnable, type-checked scripts are in [examples](examples).
|
|
77
|
+
|
|
78
|
+
TypeScript declarations are included for ESM and CommonJS; no separate `@types`
|
|
79
|
+
package is needed. Public methods and types include JSDoc for editor hovers,
|
|
80
|
+
parameter descriptions, defaults, result semantics, and examples. JavaScript
|
|
81
|
+
editors use the same declarations for autocomplete and hover documentation.
|
|
82
|
+
Enable `// @ts-check` to also check types in a JavaScript file:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
// @ts-check
|
|
86
|
+
import { TarkaClient } from "@tarkahq/sdk";
|
|
87
|
+
|
|
88
|
+
/** @type {import("@tarkahq/sdk").ChatInput} */
|
|
89
|
+
const input = { model: "your-model-alias", prompt: "Hello", maxTokens: 100 };
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {TarkaClient} client
|
|
93
|
+
* @param {import("@tarkahq/sdk").ChatInput} input
|
|
94
|
+
* @returns {Promise<string>}
|
|
95
|
+
*/
|
|
96
|
+
async function reply(client, input) {
|
|
97
|
+
return client.chat.text(input);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Hover over input fields as well as methods for their documentation. For example,
|
|
102
|
+
`timeoutMs` describes the client wait budget, `timeoutSeconds` describes the
|
|
103
|
+
server limit, and chat `metadata` is distinguished from transport metadata.
|
|
104
|
+
See [the JavaScript example](examples/chat.mjs) for a complete script. Explicit
|
|
105
|
+
JSDoc annotations are useful for reusable helpers; direct SDK calls already
|
|
106
|
+
infer their inputs and results.
|
|
107
|
+
|
|
108
|
+
The default endpoint is `grpc.tarka.rest:443`. The SDK uses TLS and bearer
|
|
109
|
+
authentication. Pass the token itself without `Bearer`. Environment variables
|
|
110
|
+
are read by your application, not implicitly by the SDK.
|
|
111
|
+
|
|
112
|
+
Use an account access token for provisioning. Inference accepts suitably scoped
|
|
113
|
+
`tk_live_...` keys; sandboxes accept account tokens or keys with the `sandboxes`
|
|
114
|
+
scope. Organization membership, product access, and model policy still apply.
|
|
115
|
+
|
|
116
|
+
## API conventions
|
|
117
|
+
|
|
118
|
+
| Operation | Convention |
|
|
119
|
+
| -------------------- | ------------------------------------------------------------------------------ |
|
|
120
|
+
| List | `list()` returns an array directly; no `.data`, `.items`, or service envelope. |
|
|
121
|
+
| Get | `get(id)` returns the entity. |
|
|
122
|
+
| Create / update | Return the entity; no request or response wrapper objects. |
|
|
123
|
+
| Delete | Resolves to `undefined` (`Promise<void>`). |
|
|
124
|
+
| Revoke / cancel | Return the updated entity. |
|
|
125
|
+
| Stream | An `AsyncIterable`; consume with `for await`. |
|
|
126
|
+
| Request settings | `timeoutMs`, `signal`, and plain-object `metadata`. |
|
|
127
|
+
| Organization context | Bind once with `client.org(orgId)`; nested calls omit `orgId`. |
|
|
128
|
+
| Sandbox entities | Lists, gets, creates, and waits return the same handle types. |
|
|
129
|
+
|
|
130
|
+
Calls with no input need no `{}`. Request settings go directly to input-free
|
|
131
|
+
methods, or after the input for other methods:
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
await client.models.list({ timeoutMs: 10_000 });
|
|
135
|
+
await client.models.get(model, { timeoutMs: 10_000 });
|
|
136
|
+
await client.chat.text({ model, prompt: "Hello" }, { timeoutMs: 10_000 });
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Methods with optional filters or input can be called with no arguments.
|
|
140
|
+
To supply only request settings to those methods, pass `undefined` for the input:
|
|
141
|
+
`client.catalog.list(undefined, { timeoutMs: 10_000 })`.
|
|
142
|
+
|
|
143
|
+
Creation of API keys and storage credentials returns the normal entity fields
|
|
144
|
+
plus its one-time secret. For example, an API key has `id`, `label`, and `secret`,
|
|
145
|
+
rather than `{ apiKey, plaintextKey }`. Store the secret securely at creation;
|
|
146
|
+
list calls do not return it.
|
|
147
|
+
|
|
148
|
+
## Chat, models, and Responses
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
const models = await client.models.list();
|
|
152
|
+
const modelInfo = await client.models.get(model);
|
|
153
|
+
const catalog = await client.catalog.list({ modality: "text" });
|
|
154
|
+
|
|
155
|
+
const completion = await client.chat.create({
|
|
156
|
+
model,
|
|
157
|
+
messages: [{ role: "user", content: "Explain HTTP/2 briefly." }],
|
|
158
|
+
temperature: 0.2,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
for await (const text of client.chat.streamText({
|
|
162
|
+
model,
|
|
163
|
+
system: "Be concise.",
|
|
164
|
+
prompt: "Explain HTTP/2 briefly.",
|
|
165
|
+
})) {
|
|
166
|
+
process.stdout.write(text);
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Supply either `prompt` with an optional `system`, or a non-empty `messages`
|
|
171
|
+
array. `create()` returns the full completion, including usage and tool calls;
|
|
172
|
+
`stream()` returns full chunks. `text()` selects choice 0 and rejects if it
|
|
173
|
+
contains no text. `streamText()` yields choice 0's text deltas, skipping usage
|
|
174
|
+
and tool-call chunks. Streaming mode is selected by the method.
|
|
175
|
+
|
|
176
|
+
`models` describes the inference-visible models. `catalog` exposes the control
|
|
177
|
+
plane model catalog, including provisioning information and modality filtering.
|
|
178
|
+
|
|
179
|
+
The JSON APIs accept ordinary OpenAI-compatible objects, retaining their
|
|
180
|
+
original field names, and return the response body directly. They support
|
|
181
|
+
forward-compatible fields without protobuf envelope objects:
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
const completion = await client.chat.json.create({
|
|
185
|
+
model,
|
|
186
|
+
messages: [{ role: "user", content: "Hello" }],
|
|
187
|
+
max_tokens: 100,
|
|
188
|
+
});
|
|
189
|
+
console.log(completion.choices);
|
|
190
|
+
|
|
191
|
+
const response = await client.responses.create({ model, input: "Hello" });
|
|
192
|
+
console.log(response.id);
|
|
193
|
+
|
|
194
|
+
for await (const event of client.responses.stream({ model, input: "Hello" })) {
|
|
195
|
+
console.log(event.type, event.data);
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
JSON streams yield `{ type, data }`. Both JSON chat and Responses select
|
|
200
|
+
`stream: false` for `create()` and `stream: true` for `stream()`.
|
|
201
|
+
Responses also provides `get(id)`, `cancel(id)`, and `delete(id)`.
|
|
202
|
+
JSON outputs use `JsonObject` / `JsonValue`; narrow dynamic values before using
|
|
203
|
+
them in TypeScript. The typed chat API provides completion-specific types.
|
|
204
|
+
|
|
205
|
+
## OCR and audio
|
|
206
|
+
|
|
207
|
+
```js
|
|
208
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
209
|
+
|
|
210
|
+
const text = await client.ocr.text({ model: ocrModel, image: imageUrl });
|
|
211
|
+
const transcript = await client.audio.transcriptions.text({
|
|
212
|
+
model: transcriptionModel,
|
|
213
|
+
file: await readFile("recording.wav"),
|
|
214
|
+
filename: "recording.wav",
|
|
215
|
+
});
|
|
216
|
+
const speech = await client.audio.speech.create({
|
|
217
|
+
model: speechModel,
|
|
218
|
+
input: "Hello from Tarka.",
|
|
219
|
+
});
|
|
220
|
+
await writeFile("speech.audio", speech.data);
|
|
221
|
+
console.log(speech.contentType);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
OCR takes either `image` or a non-empty `images` array. It offers `create()` and
|
|
225
|
+
`stream()` for complete results, plus `text()` and `streamText()` for strings.
|
|
226
|
+
Both `audio.transcriptions` and `audio.translations` offer `create()` and `text()`.
|
|
227
|
+
|
|
228
|
+
`audio.speech.create()` collects the response into `{ data: Buffer, contentType }`.
|
|
229
|
+
Use `audio.speech.stream()` for large outputs; it yields chunks of the same shape.
|
|
230
|
+
`audio.voices` provides `create({ model, name, sample, consentSignedBy,
|
|
231
|
+
consentDate, ... })`, `get(id)`, and `delete(id)` for voice cloning.
|
|
232
|
+
|
|
233
|
+
## Organizations, keys, compute, storage, and Git
|
|
234
|
+
|
|
235
|
+
```js
|
|
236
|
+
const user = await client.user.get();
|
|
237
|
+
const org = client.org(user.defaultOrgId); // No network request.
|
|
238
|
+
|
|
239
|
+
const keys = await org.apiKeys.list();
|
|
240
|
+
const key = await org.apiKeys.create({
|
|
241
|
+
label: "my-app",
|
|
242
|
+
scopes: ["inference"],
|
|
243
|
+
});
|
|
244
|
+
const usage = await org.usage.summary();
|
|
245
|
+
|
|
246
|
+
const bucket = await org.storage.buckets.create({ name: "my-data" });
|
|
247
|
+
const credential = await org.storage
|
|
248
|
+
.credentials(bucket.id)
|
|
249
|
+
.create({ label: "worker" });
|
|
250
|
+
// credential includes accessKeyId, secretAccessKey, endpoint, and region.
|
|
251
|
+
|
|
252
|
+
const repository = await org.repositories.create({
|
|
253
|
+
name: "my-project",
|
|
254
|
+
initialize: true,
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
The complete resource surface is below. IDs are strings, inputs are objects,
|
|
259
|
+
and each method accepts request settings in the last argument.
|
|
260
|
+
|
|
261
|
+
| Resource | Methods |
|
|
262
|
+
| ---------------------------------------------- | ------------------------------------------------------------------------- |
|
|
263
|
+
| `client.models` | `list()`, `get(id)` |
|
|
264
|
+
| `client.catalog` | `list({ modality? }?)` |
|
|
265
|
+
| `client.chat` | `create(input)`, `stream(input)`, `text(input)`, `streamText(input)` |
|
|
266
|
+
| `client.chat.json` | `create(body)`, `stream(body)` |
|
|
267
|
+
| `client.responses` | `create(body)`, `stream(body)`, `get(id)`, `cancel(id)`, `delete(id)` |
|
|
268
|
+
| `client.ocr` | `create(input)`, `stream(input)`, `text(input)`, `streamText(input)` |
|
|
269
|
+
| `client.audio.transcriptions`, `.translations` | `create(input)`, `text(input)` |
|
|
270
|
+
| `client.audio.speech` | `create(input)`, `stream(input)` |
|
|
271
|
+
| `client.audio.voices` | `create(input)`, `get(id)`, `delete(id)` |
|
|
272
|
+
| `client.user` | `get()`, `bootstrap({ orgName? }?)` |
|
|
273
|
+
| `client.organizations` | `list()`, `get(id)`, `create({ name, slug? })` |
|
|
274
|
+
| `client.git` | `ensureAccess()` |
|
|
275
|
+
| `org` | `get()`, `update({ name })` |
|
|
276
|
+
| `org.members` | `list()` |
|
|
277
|
+
| `org.accessRequests` | `list({ product?, limit? }?)`, `create({ product, ... })` |
|
|
278
|
+
| `org.apiKeys` | `list()`, `create({ label?, scopes?, ... }?)`, `revoke(id, { reason? }?)` |
|
|
279
|
+
| `org.quotas` | `get()`, `update({ allowAllModels, ... })` |
|
|
280
|
+
| `org.usage` | `list({ limit? }?)`, `summary()` |
|
|
281
|
+
| `org.compute.resources` | `list({ resourceType? }?)`, `get(id)` |
|
|
282
|
+
| `org.compute.inferenceServices` | `create({ name, modelAlias, ... })` |
|
|
283
|
+
| `org.compute.agentHosts` | `create({ name, image, ... })` |
|
|
284
|
+
| `org.compute.jobs` | `create({ name, image, command?, ... })` |
|
|
285
|
+
| `org.storage.buckets` | `list()`, `create({ name })`, `delete(id)` |
|
|
286
|
+
| `org.storage.credentials(bucketId)` | `list()`, `create({ label? }?)`, `revoke(id)` |
|
|
287
|
+
| `org.repositories` | `list()`, `create({ name, ... })`, `delete(id)` |
|
|
288
|
+
| `org.sandboxes` | `list()`, `get(id)`, `create({ template, ... })`, `delete(id)` |
|
|
289
|
+
| `org.sandboxes.templates` | `list()`, `get(id)`, `create(input)`, `delete(id)` |
|
|
290
|
+
| `sandbox.executions` | `get(id)`, `create({ code, ... })` |
|
|
291
|
+
|
|
292
|
+
`org.quotas.update()` replaces the policy: omitted optional limits become
|
|
293
|
+
unlimited. Pass the desired full policy, including `allowedModelAliases` when
|
|
294
|
+
restricting models. List filters use the server's default limits; lists do not
|
|
295
|
+
silently fetch additional pages. Exported input and result types describe every
|
|
296
|
+
field and appear in editor completion.
|
|
297
|
+
|
|
298
|
+
## Sandboxes and templates
|
|
299
|
+
|
|
300
|
+
```js
|
|
301
|
+
const sandboxes = client.org(orgId).sandboxes;
|
|
302
|
+
const templates = await sandboxes.templates.list();
|
|
303
|
+
const sandbox = await sandboxes.create({ template, timeoutSeconds: 600 });
|
|
304
|
+
|
|
305
|
+
const execution = await sandbox.run(
|
|
306
|
+
'print("hello from Tarka")',
|
|
307
|
+
{ timeoutSeconds: 30 },
|
|
308
|
+
{ timeoutMs: 60_000 },
|
|
309
|
+
);
|
|
310
|
+
console.log(execution.status, execution.stdout, execution.stderr);
|
|
311
|
+
await sandbox.delete();
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
`run()` waits for readiness, submits code, then waits for completion within
|
|
315
|
+
**one total timeout**. To submit without waiting, call `sandbox.execute(code)`
|
|
316
|
+
or `sandbox.executions.create({ code })`; both return an `Execution` handle.
|
|
317
|
+
Fetch one with `sandbox.executions.get(id)` and finish waiting with `execution.wait()`.
|
|
318
|
+
|
|
319
|
+
`Sandbox`, `SandboxTemplate`, and `Execution` handles expose `id`, `status`,
|
|
320
|
+
`info` (the latest snapshot), `refresh()`, and `toJSON()`. Refreshing and waiting
|
|
321
|
+
update the existing handle and return it. `list()`, `get()`, and `create()`
|
|
322
|
+
return the same handle type for a resource. Handles keep their organization
|
|
323
|
+
and resource IDs; you never pass that context again.
|
|
324
|
+
|
|
325
|
+
Sandbox and template handles add `waitUntilReady()` and `delete()`.
|
|
326
|
+
Execution handles add `wait()`, `stdout`, `stderr`, `exitCode`, and `outputTruncated`.
|
|
327
|
+
Statuses are readable strings such as `"ready"`, `"running"`, `"succeeded"`,
|
|
328
|
+
`"failed"`, and `"timed_out"`; runtimes are `"python"` or `"node"`.
|
|
329
|
+
|
|
330
|
+
A finished execution is returned even when the code failed or reached its server
|
|
331
|
+
time limit: inspect `status`, `exitCode`, `stderr`, and `outputTruncated`.
|
|
332
|
+
Waiting on a failed sandbox/template or an unknown execution status throws
|
|
333
|
+
`ResourceStateError`, with `resource` and the server snapshot in `info`.
|
|
334
|
+
|
|
335
|
+
Create a template with exactly one dependency manifest. There are no protobuf
|
|
336
|
+
`oneof` tags in the public input:
|
|
337
|
+
|
|
338
|
+
```js
|
|
339
|
+
const template = await sandboxes.templates.create({
|
|
340
|
+
alias: "python-with-numpy",
|
|
341
|
+
baseTemplateAlias: "your-python-base-alias",
|
|
342
|
+
requirementsTxt: "numpy==2.0.0",
|
|
343
|
+
});
|
|
344
|
+
await template.waitUntilReady({ timeoutMs: 300_000 });
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
The alternatives are `packageJson` and `pyprojectToml`, each containing the file
|
|
348
|
+
contents as a string. Discover available base templates with `templates.list()`.
|
|
349
|
+
|
|
350
|
+
## Timeouts and recovery
|
|
351
|
+
|
|
352
|
+
Every request accepts `{ timeoutMs, signal, metadata }`. `timeoutMs` must be
|
|
353
|
+
finite and non-negative; zero expires immediately. It overrides the client's
|
|
354
|
+
default. Without a per-call or client timeout, ordinary RPCs have no SDK deadline.
|
|
355
|
+
For a stream, the timeout covers its entire lifetime, not just gaps between chunks.
|
|
356
|
+
|
|
357
|
+
Sandbox `run()`, `waitUntilReady()`, and execution `wait()` default to a **60-second
|
|
358
|
+
total budget**, overriding the client default, with a **1-second poll interval**.
|
|
359
|
+
Set `pollIntervalMs` to change polling. The budget includes requests and delays.
|
|
360
|
+
`timeoutSeconds` in resource input is a server-side lifetime/execution limit;
|
|
361
|
+
`timeoutMs` in request settings limits how long the client waits.
|
|
362
|
+
|
|
363
|
+
Timeout or cancellation does not establish that a mutation failed. Code may
|
|
364
|
+
still be running remotely. The sandbox helpers attach recovery context and a
|
|
365
|
+
typed `resume()` to transient failures:
|
|
366
|
+
|
|
367
|
+
```js
|
|
368
|
+
import { ExecutionOperationError } from "@tarkahq/sdk";
|
|
369
|
+
|
|
370
|
+
let execution;
|
|
371
|
+
try {
|
|
372
|
+
execution = await sandbox.run('print("hello")', undefined, {
|
|
373
|
+
timeoutMs: 10_000,
|
|
374
|
+
});
|
|
375
|
+
} catch (error) {
|
|
376
|
+
if (!(error instanceof ExecutionOperationError)) throw error;
|
|
377
|
+
console.log(error.code, error.recovery);
|
|
378
|
+
execution = await error.resume({ timeoutMs: 60_000 });
|
|
379
|
+
}
|
|
380
|
+
console.log(execution.status, execution.stdout);
|
|
381
|
+
await sandbox.delete();
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
- If an execution ID is known, `resume()` polls that execution. It does not
|
|
385
|
+
submit the code again.
|
|
386
|
+
- If creation/submission was not acknowledged, `resume()` repeats the original
|
|
387
|
+
request with the same idempotency key, allowing the server to deduplicate it.
|
|
388
|
+
- If `run()` timed out before readiness, recovery waits for readiness and then
|
|
389
|
+
submits the preserved code and key.
|
|
390
|
+
- A resumed `run()` still waits for execution completion. A resumed `execute()`
|
|
391
|
+
only completes submission, just like the original method.
|
|
392
|
+
- Recovery starts a fresh timeout and cancellation scope. The previous aborted
|
|
393
|
+
signal and deadline are discarded. Metadata and polling interval are retained
|
|
394
|
+
unless overridden. A further transient failure carries another resumable error.
|
|
395
|
+
|
|
396
|
+
`SandboxOperationError`, `TemplateOperationError`, and `ExecutionOperationError`
|
|
397
|
+
all extend `OperationError<T>` and `TarkaError`. Each provides `code`, `recovery`,
|
|
398
|
+
and `resume(options?)`, returning the original operation's entity type.
|
|
399
|
+
Recovery details include the operation, organization, available resource IDs,
|
|
400
|
+
and idempotency key. Code, stdin, and manifests are kept privately for replay;
|
|
401
|
+
they are not included in `recovery` or serialized error fields.
|
|
402
|
+
|
|
403
|
+
Keys are generated automatically for sandbox/template creation and execution.
|
|
404
|
+
You can supply your own `idempotencyKey` for durable application workflows.
|
|
405
|
+
The API contract guarantees deduplication for **24 hours**, with unchanged
|
|
406
|
+
request content. Resume within that window; replay after it can create a new
|
|
407
|
+
resource or execution. The SDK does not automatically retry mutations or resume
|
|
408
|
+
partially consumed inference streams.
|
|
409
|
+
|
|
410
|
+
An error's `resume()` lives in memory. Across process restarts, save your chosen
|
|
411
|
+
key and original input for unacknowledged mutations, or save IDs and reattach:
|
|
412
|
+
|
|
413
|
+
```js
|
|
414
|
+
const sandbox = await client.org(orgId).sandboxes.get(sandboxId);
|
|
415
|
+
const execution = await sandbox.executions.get(executionId);
|
|
416
|
+
await execution.wait({ timeoutMs: 60_000 });
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Aborting a wait stops polling; it does not delete the sandbox or necessarily
|
|
420
|
+
stop submitted code. Keep the sandbox available while recovering, then delete
|
|
421
|
+
it when finished. Other provisioning mutations lack this idempotency contract:
|
|
422
|
+
after a timeout, inspect their state before deciding whether to retry.
|
|
423
|
+
|
|
424
|
+
## Streaming, cancellation, and errors
|
|
425
|
+
|
|
426
|
+
```js
|
|
427
|
+
import { TarkaError } from "@tarkahq/sdk";
|
|
428
|
+
|
|
429
|
+
const controller = new AbortController();
|
|
430
|
+
try {
|
|
431
|
+
for await (const text of client.chat.streamText(
|
|
432
|
+
{ model, prompt: "Write a short sentence." },
|
|
433
|
+
{
|
|
434
|
+
timeoutMs: 60_000,
|
|
435
|
+
signal: controller.signal,
|
|
436
|
+
metadata: { "x-request-id": "my-request" },
|
|
437
|
+
},
|
|
438
|
+
)) {
|
|
439
|
+
process.stdout.write(text);
|
|
440
|
+
}
|
|
441
|
+
} catch (error) {
|
|
442
|
+
if (error instanceof TarkaError && error.code === "deadline_exceeded") {
|
|
443
|
+
console.error("The request timed out");
|
|
444
|
+
} else {
|
|
445
|
+
throw error;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Streams start on iteration and preserve Node stream backpressure. Calling
|
|
451
|
+
`controller.abort()` cancels the active RPC; breaking out of `for await` also
|
|
452
|
+
cancels it. Metadata accepts strings, Buffers, and arrays of those values;
|
|
453
|
+
binary keys must end in `-bin`.
|
|
454
|
+
|
|
455
|
+
Resource methods normalize transport failures to `TarkaError`, with a readable
|
|
456
|
+
`message`, string `code`, plain trailing `metadata`, and the original error as
|
|
457
|
+
`cause`. Typical codes include `deadline_exceeded`, `cancelled`, `unavailable`,
|
|
458
|
+
`unauthenticated`, `permission_denied`, `not_found`, and `invalid_argument`.
|
|
459
|
+
Local argument validation throws `TypeError`. Native gRPC error objects and
|
|
460
|
+
numeric status codes are available only through `client.grpc` calls.
|
|
461
|
+
|
|
462
|
+
## Values and serialization
|
|
463
|
+
|
|
464
|
+
Public fields use camelCase, except opaque OpenAI JSON bodies. Bytes are Node
|
|
465
|
+
`Buffer`s, timestamps are `Date`s, and 64-bit integers are `bigint`s to preserve
|
|
466
|
+
precision. Use bigint literals for input limits, such as `1_000_000n`. Optional
|
|
467
|
+
values remain `undefined`; explicit zero and false are preserved.
|
|
468
|
+
|
|
469
|
+
Sandbox `JSON.stringify(handle)` serializes its latest snapshot. For other
|
|
470
|
+
entities containing bigints, choose a JSON representation explicitly:
|
|
471
|
+
|
|
472
|
+
```js
|
|
473
|
+
const json = JSON.stringify(usage, (_key, value) =>
|
|
474
|
+
typeof value === "bigint" ? value.toString() : value,
|
|
475
|
+
);
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Advanced gRPC access
|
|
479
|
+
|
|
480
|
+
Normal application code needs only `@tarkahq/sdk`. Every underlying RPC remains
|
|
481
|
+
available through `client.grpc`, with generated envelopes, enums, and native
|
|
482
|
+
call options and errors:
|
|
483
|
+
|
|
484
|
+
```js
|
|
485
|
+
const response = await client.grpc.inference.listModels();
|
|
486
|
+
await client.grpc.provisioning.getCurrentUser({ timeoutMs: 10_000 });
|
|
487
|
+
await client.grpc.sandboxes.listSandboxes({ orgId });
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Transport utilities and generated codecs are isolated in these exports:
|
|
491
|
+
|
|
492
|
+
```js
|
|
493
|
+
import {
|
|
494
|
+
Channel,
|
|
495
|
+
credentials,
|
|
496
|
+
status,
|
|
497
|
+
createChannel,
|
|
498
|
+
createServiceClient,
|
|
499
|
+
} from "@tarkahq/sdk/grpc";
|
|
500
|
+
import {
|
|
501
|
+
ChatCompletionRequest,
|
|
502
|
+
InferenceServiceDefinition,
|
|
503
|
+
} from "@tarkahq/sdk/grpc/inference/v1";
|
|
504
|
+
import { UsageSummary } from "@tarkahq/sdk/grpc/provisioning/v1";
|
|
505
|
+
import { ExecuteRequest } from "@tarkahq/sdk/grpc/sandboxes/v1";
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
`@tarkahq/sdk/grpc` also exports `inference`, `provisioning`, and `sandboxes`
|
|
509
|
+
codec namespaces. Codecs offer `create`, `fromPartial`, `encode`, `decode`,
|
|
510
|
+
`fromJSON`, and `toJSON`. Raw enums are numeric and raw oneofs use
|
|
511
|
+
`{ $case, value }`. Native call options support absolute `deadline`, gRPC
|
|
512
|
+
`Metadata`, credentials, and interceptors in addition to SDK request settings.
|
|
513
|
+
The earlier deadline wins when both `deadline` and `timeoutMs` are given.
|
|
514
|
+
|
|
515
|
+
Use `channelCredentials: credentials.createSsl(ca)` for custom TLS roots,
|
|
516
|
+
`target` for a different endpoint, and `channelOptions` for gRPC configuration.
|
|
517
|
+
The authenticated `createChannel(accessToken, options)` helper requires TLS.
|
|
518
|
+
Alternatively, supply a channel whose authentication and lifecycle you own:
|
|
519
|
+
|
|
520
|
+
```js
|
|
521
|
+
const channel = new Channel(
|
|
522
|
+
"localhost:50051",
|
|
523
|
+
credentials.createInsecure(),
|
|
524
|
+
{},
|
|
525
|
+
);
|
|
526
|
+
const local = new TarkaClient({ channel, timeoutMs: 10_000 });
|
|
527
|
+
try {
|
|
528
|
+
await local.models.list();
|
|
529
|
+
} finally {
|
|
530
|
+
channel.close();
|
|
531
|
+
}
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
An injected channel cannot be combined with `accessToken`, `target`, or channel
|
|
535
|
+
configuration. `client.close()` leaves caller-owned channels open.
|
|
536
|
+
|
|
537
|
+
## Migrating from 0.1
|
|
538
|
+
|
|
539
|
+
Version 0.2 deliberately makes resource wrappers the default API.
|
|
540
|
+
|
|
541
|
+
| Before | Now |
|
|
542
|
+
| ------------------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
543
|
+
| `client.inference.listModels()` | `client.models.list()`; returns the array |
|
|
544
|
+
| `client.provisioning.getCurrentUser()` | `client.user.get()` |
|
|
545
|
+
| `client.provisioning.createApiKey({ orgId, ...input })` | `client.org(orgId).apiKeys.create(input)`; secret is `.secret` |
|
|
546
|
+
| `client.sandboxes.forOrg(orgId)` | `client.org(orgId).sandboxes` |
|
|
547
|
+
| `sandbox.getExecution(id)` | `sandbox.executions.get(id)`; returns an `Execution` handle |
|
|
548
|
+
| `sandbox.run(code, { timeoutMs, timeoutSeconds })` | `sandbox.run(code, { timeoutSeconds }, { timeoutMs })` |
|
|
549
|
+
| Numeric sandbox/execution statuses | String statuses, such as `"ready"` and `"succeeded"` |
|
|
550
|
+
| Sandbox lists returning plain snapshots | Lists of `Sandbox` handles; use `.info` for snapshots |
|
|
551
|
+
| `SandboxStateError` / `ExecutionStateError` | `ResourceStateError`, with `.resource` and `.info` |
|
|
552
|
+
| Native SDK errors with numeric codes | `TarkaError` with string codes; resumable operation errors for sandbox recovery |
|
|
553
|
+
| Direct services / `client.channel` | `client.grpc.inference`, `.provisioning`, `.sandboxes`, `.channel` |
|
|
554
|
+
| Transport imports from package root | Imports from `@tarkahq/sdk/grpc` |
|
|
555
|
+
| `@tarkahq/sdk/inference/v2` (and other codec paths) | `@tarkahq/sdk/grpc/inference/v1` (and corresponding service paths) |
|
|
556
|
+
|
|
557
|
+
Raw RPC signatures remain available under `grpc`, including optional empty
|
|
558
|
+
requests and the older `rpc({}, options)` form.
|
|
559
|
+
|
|
560
|
+
## Development and generation
|
|
561
|
+
|
|
562
|
+
Building and testing need only this repository. Regeneration also needs the
|
|
563
|
+
authoritative API checkout, normally at `../api`, at the revision recorded in
|
|
564
|
+
`api-source.json`:
|
|
565
|
+
|
|
566
|
+
```sh
|
|
567
|
+
npm ci
|
|
568
|
+
npm run generate # Uses ../api
|
|
569
|
+
npm run generate -- --api-dir /path/to/api
|
|
570
|
+
npm run check:generated # Compares without modifying files
|
|
571
|
+
npm run verify # Format, types, tests, build, package test
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
`scripts/generate.mjs` discovers every `.proto` under `api/proto/tarka` and runs
|
|
575
|
+
the pinned `protoc` from `grpc-tools` with the pinned `ts-proto` plugin. Annotation
|
|
576
|
+
imports live in `proto/third_party`; well-known types come from `grpc-tools`.
|
|
577
|
+
There is no global compiler requirement or runtime code generation.
|
|
578
|
+
|
|
579
|
+
Generated TypeScript is checked in under `src/generated`; do not edit it by
|
|
580
|
+
hand. `api-source.json` records the API commit, source/import hashes, and
|
|
581
|
+
generator settings. Generation does not fetch or change the API checkout.
|
|
582
|
+
When the contract adds an RPC, add its resource wrapper: the coverage test
|
|
583
|
+
asserts that every generated RPC is exercised through the public resource API.
|
|
584
|
+
|
|
585
|
+
CI checks generation against the recorded revision and verifies Node 22 and 24.
|
|
586
|
+
Tests use local gRPC servers, including TLS/authentication, streaming,
|
|
587
|
+
cancellation, all 60 wrapped RPCs, and recovery after lost acknowledgements.
|
|
588
|
+
They do not require Tarka credentials or call production. The package test
|
|
589
|
+
installs a tarball into an isolated consumer, checks TypeScript types, and runs
|
|
590
|
+
ESM and CommonJS consumers. That test needs npm registry access for dependencies.
|
|
591
|
+
|
|
592
|
+
## Preparing an npm release
|
|
593
|
+
|
|
594
|
+
1. Confirm the package name and access to the `@tarkahq` scope.
|
|
595
|
+
2. Select the API revision, regenerate, and review generated and wrapper changes.
|
|
596
|
+
3. Set the version in `package.json` and `package-lock.json`.
|
|
597
|
+
4. Run `npm run check:generated`, `npm run verify`, and `npm pack --dry-run`.
|
|
598
|
+
5. Run the `SDK release` workflow on `main` with `publish=true` after reviewing its package artifact.
|
|
599
|
+
|
|
600
|
+
There is no automatic publication workflow.
|
|
601
|
+
|
|
602
|
+
## License
|
|
603
|
+
|
|
604
|
+
Apache-2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
|
|
605
|
+
|
|
606
|
+
## Gateway connection settings
|
|
607
|
+
|
|
608
|
+
Gateway create, update, get and list responses expose `endpoints` when routing
|
|
609
|
+
is configured. `apiBaseUrl` accepts published operation paths;
|
|
610
|
+
`apiAudience` is the exact OAuth resource without `/api`. `mcpUrl` and
|
|
611
|
+
`mcpAudience` are the same MCP endpoint. `issuer` identifies the environment's
|
|
612
|
+
OAuth issuer. Use these server-provided settings instead of constructing URLs.
|
|
613
|
+
They are available for setup before publication and do not grant access.
|
|
614
|
+
|
|
615
|
+
`client.gateway.listPrivateServices()` lists controller-observed services for an
|
|
616
|
+
organization and realm. Set a target's `serviceId` and `servicePath` instead of
|
|
617
|
+
`url` for a private destination. Only a `ready` service can be published; a
|
|
618
|
+
redeployment requires a new gateway publication. Its exact credential scope is
|
|
619
|
+
`tarka-service://<service-id>` in `allowedOrigins`.
|
|
620
|
+
|
|
621
|
+
## Trusted agent harness
|
|
622
|
+
|
|
623
|
+
Use `RuntimeClient` in trusted server-side harness code. The token provider must
|
|
624
|
+
supply a current OAuth token with `runtime.execute` for the realm's exact runtime
|
|
625
|
+
resource. The server derives the customer, agent and consent; platform API keys
|
|
626
|
+
cannot establish that identity.
|
|
627
|
+
|
|
628
|
+
```ts
|
|
629
|
+
import { RuntimeClient } from "@tarkahq/sdk";
|
|
630
|
+
|
|
631
|
+
const runtime = new RuntimeClient({
|
|
632
|
+
origin: gatewayOrigin,
|
|
633
|
+
realmId,
|
|
634
|
+
tokenProvider: currentRuntimeOAuthToken,
|
|
635
|
+
});
|
|
636
|
+
await runtime.withRun(
|
|
637
|
+
{
|
|
638
|
+
gateway_id: gatewayId,
|
|
639
|
+
transport: "api",
|
|
640
|
+
permissions: [{ resource: capabilityId, action: "invoke" }],
|
|
641
|
+
},
|
|
642
|
+
async (run) => {
|
|
643
|
+
const response = await run.api("/records");
|
|
644
|
+
const toolResult = await response.json();
|
|
645
|
+
// Pass only the approved result to the model.
|
|
646
|
+
},
|
|
647
|
+
);
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
For MCP, start with `transport: "mcp"` and pass `run.mcpFetch` as the MCP
|
|
651
|
+
Streamable HTTP transport's fetch implementation, using `run.audience` as its
|
|
652
|
+
endpoint. It rejects every other URL and supplies only the narrow run bearer.
|
|
653
|
+
|
|
654
|
+
Keep the client, run handle and parent token provider outside model-visible
|
|
655
|
+
state, prompts, tool arguments, workspace files and logs. Register specific tool
|
|
656
|
+
closures. Metadata, JSON serialization and normal inspection omit credentials.
|
|
657
|
+
The SDK does not isolate hostile code in its own process.
|
|
658
|
+
|
|
659
|
+
The harness serializes renewal and renews near expiry on demand. An uncertain
|
|
660
|
+
renewal disables later tool calls; issuance and tool actions are never retried
|
|
661
|
+
automatically. `withRun` completes on success and attempts cancellation if the
|
|
662
|
+
callback fails, preserving the callback's error. `finish()` explicitly stops a
|
|
663
|
+
run. Read streamed responses promptly: rotating a credential while an earlier
|
|
664
|
+
stream remains open may cause that stream's authorization check to terminate it.
|
|
665
|
+
|
|
666
|
+
### Independent messaging consumers
|
|
667
|
+
|
|
668
|
+
An assigned agent worker uses its autonomous Ory token for the runtime audience
|
|
669
|
+
after the customer links a provider account and approves the channel's tools.
|
|
670
|
+
Both customer and agent need channel `use` permission. Identity and tool scope
|
|
671
|
+
come from the gateway.
|
|
672
|
+
|
|
673
|
+
```ts
|
|
674
|
+
for await (const message of runtime.messages(channelId, { signal })) {
|
|
675
|
+
// Give only prompt to the model as user input. Build tool closures around
|
|
676
|
+
// message.api(...) or message.mcpFetch inside trusted harness code.
|
|
677
|
+
const result = await executeAgentTurn(message.prompt, message);
|
|
678
|
+
await message.reply(result);
|
|
679
|
+
}
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
`claimMessage(channelId)` returns one message or `null`. The iterator polls
|
|
683
|
+
successfully empty queues every five seconds and cancels an unfinished run on
|
|
684
|
+
advance or exit. A private `reply()` finishes the run, accepts at most 2,000
|
|
685
|
+
Unicode characters and has no recipient argument. Failed or uncertain claims
|
|
686
|
+
and replies propagate without retry. Keep the message handle outside model
|
|
687
|
+
state; inspection and JSON serialization omit its prompt and credentials.
|
|
688
|
+
|
|
689
|
+
## Publishing
|
|
690
|
+
|
|
691
|
+
The `SDK release` workflow runs verification, creates the npm tarball and a
|
|
692
|
+
SHA-256 checksum, and uploads them as a reviewable artifact. A dry run is the
|
|
693
|
+
default. Publishing runs only on `main` with `publish=true`, uses the exact tested
|
|
694
|
+
tarball, and attaches it to a GitHub release.
|
|
695
|
+
|
|
696
|
+
Configure npm's trusted publisher for `@tarkahq/sdk`, owner `TarkaHQ`, repository
|
|
697
|
+
`sdk-javascript`, workflow `release.yml`, environment `npm`, and the publish
|
|
698
|
+
permission. The package owner must establish the package and publisher identity
|
|
699
|
+
before the first automated release. The workflow uses a GitHub-hosted runner and
|
|
700
|
+
OIDC, with no stored npm token. npm does not generate provenance from a private
|
|
701
|
+
source repository. See [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/).
|