@rkat/sdk 0.3.4 → 0.4.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/client.d.ts +101 -84
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +490 -310
- package/dist/client.js.map +1 -1
- package/dist/events.d.ts +239 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +160 -0
- package/dist/events.js.map +1 -0
- package/dist/generated/types.d.ts +1 -1
- package/dist/generated/types.js +2 -2
- package/dist/index.d.ts +25 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -3
- package/dist/index.js.map +1 -1
- package/dist/session.d.ts +86 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +125 -0
- package/dist/session.js.map +1 -0
- package/dist/streaming.d.ts +52 -14
- package/dist/streaming.d.ts.map +1 -1
- package/dist/streaming.js +138 -60
- package/dist/streaming.js.map +1 -1
- package/dist/types.d.ts +96 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +1 -1
- package/dist/capabilities.d.ts +0 -24
- package/dist/capabilities.d.ts.map +0 -1
- package/dist/capabilities.js +0 -36
- package/dist/capabilities.js.map +0 -1
- package/dist/skills.d.ts +0 -41
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js +0 -57
- package/dist/skills.js.map +0 -1
package/dist/client.js
CHANGED
|
@@ -1,25 +1,471 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Meerkat client — spawns rkat-rpc
|
|
2
|
+
* Meerkat client — spawns rkat-rpc and communicates via JSON-RPC.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { MeerkatClient } from "@rkat/sdk";
|
|
7
|
+
*
|
|
8
|
+
* const client = new MeerkatClient();
|
|
9
|
+
* await client.connect();
|
|
10
|
+
*
|
|
11
|
+
* const session = await client.createSession("Hello!");
|
|
12
|
+
* console.log(session.text);
|
|
13
|
+
*
|
|
14
|
+
* const result = await session.turn("Tell me more");
|
|
15
|
+
* console.log(result.text);
|
|
16
|
+
*
|
|
17
|
+
* for await (const event of session.stream("Explain in detail")) {
|
|
18
|
+
* if (event.type === "text_delta") {
|
|
19
|
+
* process.stdout.write(event.delta);
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* await session.archive();
|
|
24
|
+
* await client.close();
|
|
25
|
+
* ```
|
|
3
26
|
*/
|
|
4
27
|
import { spawn } from "node:child_process";
|
|
5
28
|
import { chmodSync, existsSync, mkdirSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
6
29
|
import os from "node:os";
|
|
7
30
|
import path from "node:path";
|
|
8
31
|
import { createInterface } from "node:readline";
|
|
9
|
-
import { MeerkatError } from "./generated/errors.js";
|
|
32
|
+
import { MeerkatError, CapabilityUnavailableError } from "./generated/errors.js";
|
|
10
33
|
import { CONTRACT_VERSION } from "./generated/types.js";
|
|
34
|
+
import { Session } from "./session.js";
|
|
35
|
+
import { EventStream, AsyncQueue } from "./streaming.js";
|
|
11
36
|
const MEERKAT_REPO = "lukacf/meerkat";
|
|
12
37
|
const MEERKAT_RELEASE_BINARY = "rkat-rpc";
|
|
13
38
|
const MEERKAT_BINARY_CACHE_ROOT = path.join(os.homedir(), ".cache", "meerkat", "bin", MEERKAT_RELEASE_BINARY);
|
|
39
|
+
/**
|
|
40
|
+
* Normalize a SkillRef to the wire format { source_uuid, skill_name }.
|
|
41
|
+
*
|
|
42
|
+
* SkillKey objects are converted from camelCase to snake_case.
|
|
43
|
+
* Legacy strings are parsed and emit a console warning.
|
|
44
|
+
*/
|
|
45
|
+
function normalizeSkillRef(ref) {
|
|
46
|
+
if (typeof ref !== "string") {
|
|
47
|
+
return { source_uuid: ref.sourceUuid, skill_name: ref.skillName };
|
|
48
|
+
}
|
|
49
|
+
const value = ref.startsWith("/") ? ref.slice(1) : ref;
|
|
50
|
+
const [sourceUuid, ...rest] = value.split("/");
|
|
51
|
+
if (!sourceUuid || rest.length === 0) {
|
|
52
|
+
throw new Error(`Invalid skill reference '${ref}'. Expected '<source_uuid>/<skill_name>'.`);
|
|
53
|
+
}
|
|
54
|
+
console.warn(`[meerkat-sdk] legacy skill reference '${ref}' is deprecated; pass { sourceUuid, skillName } instead.`);
|
|
55
|
+
return { source_uuid: sourceUuid, skill_name: rest.join("/") };
|
|
56
|
+
}
|
|
57
|
+
function skillRefsToWire(refs) {
|
|
58
|
+
if (!refs)
|
|
59
|
+
return undefined;
|
|
60
|
+
return refs.map(normalizeSkillRef);
|
|
61
|
+
}
|
|
14
62
|
export class MeerkatClient {
|
|
15
63
|
process = null;
|
|
16
64
|
requestId = 0;
|
|
17
|
-
|
|
65
|
+
_capabilities = [];
|
|
18
66
|
rkatPath;
|
|
19
67
|
pendingRequests = new Map();
|
|
68
|
+
eventQueues = new Map();
|
|
69
|
+
rl = null;
|
|
20
70
|
constructor(rkatPath = "rkat-rpc") {
|
|
21
71
|
this.rkatPath = rkatPath;
|
|
22
72
|
}
|
|
73
|
+
// -- Connection ---------------------------------------------------------
|
|
74
|
+
async connect(options) {
|
|
75
|
+
if (options?.realmId && options?.isolated) {
|
|
76
|
+
throw new MeerkatError("INVALID_ARGS", "realmId and isolated cannot both be set");
|
|
77
|
+
}
|
|
78
|
+
const resolved = await MeerkatClient.resolveBinaryPath(this.rkatPath);
|
|
79
|
+
this.rkatPath = resolved.command;
|
|
80
|
+
const args = MeerkatClient.buildArgs(resolved.useLegacySubcommand, options);
|
|
81
|
+
if (resolved.useLegacySubcommand && args.length > 1) {
|
|
82
|
+
throw new MeerkatError("LEGACY_BINARY_UNSUPPORTED", "Realm/context options require the standalone rkat-rpc binary. Install rkat-rpc and retry.");
|
|
83
|
+
}
|
|
84
|
+
this.process = spawn(this.rkatPath, args, {
|
|
85
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
86
|
+
});
|
|
87
|
+
this.rl = createInterface({ input: this.process.stdout });
|
|
88
|
+
this.rl.on("line", (line) => this.handleLine(line));
|
|
89
|
+
// Handshake
|
|
90
|
+
const initResult = await this.request("initialize", {});
|
|
91
|
+
const serverVersion = String(initResult.contract_version ?? "");
|
|
92
|
+
if (!MeerkatClient.checkVersionCompatible(serverVersion, CONTRACT_VERSION)) {
|
|
93
|
+
throw new MeerkatError("VERSION_MISMATCH", `Server version ${serverVersion} incompatible with SDK ${CONTRACT_VERSION}`);
|
|
94
|
+
}
|
|
95
|
+
// Fetch capabilities
|
|
96
|
+
const capsResult = await this.request("capabilities/get", {});
|
|
97
|
+
const rawCaps = capsResult.capabilities ?? [];
|
|
98
|
+
this._capabilities = rawCaps.map((cap) => ({
|
|
99
|
+
id: String(cap.id ?? ""),
|
|
100
|
+
description: String(cap.description ?? ""),
|
|
101
|
+
status: MeerkatClient.normalizeStatus(cap.status),
|
|
102
|
+
}));
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
async close() {
|
|
106
|
+
if (this.rl) {
|
|
107
|
+
this.rl.close();
|
|
108
|
+
this.rl = null;
|
|
109
|
+
}
|
|
110
|
+
if (this.process) {
|
|
111
|
+
this.process.kill();
|
|
112
|
+
this.process = null;
|
|
113
|
+
}
|
|
114
|
+
for (const [, pending] of this.pendingRequests) {
|
|
115
|
+
pending.reject(new MeerkatError("CLIENT_CLOSED", "Client closed"));
|
|
116
|
+
}
|
|
117
|
+
this.pendingRequests.clear();
|
|
118
|
+
for (const [, queue] of this.eventQueues) {
|
|
119
|
+
queue.put(null);
|
|
120
|
+
}
|
|
121
|
+
this.eventQueues.clear();
|
|
122
|
+
}
|
|
123
|
+
// -- Session lifecycle --------------------------------------------------
|
|
124
|
+
/**
|
|
125
|
+
* Create a new session, run the first turn, and return a {@link Session}.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* const session = await client.createSession("Summarise this project", {
|
|
130
|
+
* model: "claude-sonnet-4-5",
|
|
131
|
+
* });
|
|
132
|
+
* console.log(session.text);
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
async createSession(prompt, options) {
|
|
136
|
+
const params = MeerkatClient.buildCreateParams(prompt, options);
|
|
137
|
+
const raw = await this.request("session/create", params);
|
|
138
|
+
const result = MeerkatClient.parseRunResult(raw);
|
|
139
|
+
return new Session(this, result);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Create a new session and stream typed events from the first turn.
|
|
143
|
+
*
|
|
144
|
+
* Returns an {@link EventStream} `AsyncIterable<AgentEvent>`.
|
|
145
|
+
*/
|
|
146
|
+
createSessionStreaming(prompt, options) {
|
|
147
|
+
if (!this.process?.stdin) {
|
|
148
|
+
throw new MeerkatError("NOT_CONNECTED", "Client not connected");
|
|
149
|
+
}
|
|
150
|
+
const params = MeerkatClient.buildCreateParams(prompt, options);
|
|
151
|
+
this.requestId++;
|
|
152
|
+
const requestId = this.requestId;
|
|
153
|
+
const queue = new AsyncQueue();
|
|
154
|
+
const responsePromise = this.registerRequest(requestId);
|
|
155
|
+
// When response arrives, bind the queue to the session_id
|
|
156
|
+
const wrappedPromise = responsePromise.then((result) => {
|
|
157
|
+
const sid = String(result.session_id ?? "");
|
|
158
|
+
if (sid) {
|
|
159
|
+
this.eventQueues.set(sid, queue);
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
});
|
|
163
|
+
const rpcRequest = { jsonrpc: "2.0", id: requestId, method: "session/create", params };
|
|
164
|
+
this.process.stdin.write(JSON.stringify(rpcRequest) + "\n");
|
|
165
|
+
return new EventStream({
|
|
166
|
+
sessionId: "",
|
|
167
|
+
eventQueue: queue,
|
|
168
|
+
responsePromise: wrappedPromise,
|
|
169
|
+
parseResult: MeerkatClient.parseRunResult,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
// -- Session queries ----------------------------------------------------
|
|
173
|
+
async listSessions() {
|
|
174
|
+
const result = await this.request("session/list", {});
|
|
175
|
+
const sessions = result.sessions ?? [];
|
|
176
|
+
return sessions.map((s) => ({
|
|
177
|
+
sessionId: String(s.session_id ?? ""),
|
|
178
|
+
sessionRef: s.session_ref != null ? String(s.session_ref) : undefined,
|
|
179
|
+
createdAt: String(s.created_at ?? ""),
|
|
180
|
+
updatedAt: String(s.updated_at ?? ""),
|
|
181
|
+
messageCount: Number(s.message_count ?? 0),
|
|
182
|
+
totalTokens: Number(s.total_tokens ?? 0),
|
|
183
|
+
isActive: Boolean(s.is_active),
|
|
184
|
+
}));
|
|
185
|
+
}
|
|
186
|
+
async readSession(sessionId) {
|
|
187
|
+
return this.request("session/read", { session_id: sessionId });
|
|
188
|
+
}
|
|
189
|
+
// -- Capabilities -------------------------------------------------------
|
|
190
|
+
get capabilities() {
|
|
191
|
+
return this._capabilities;
|
|
192
|
+
}
|
|
193
|
+
hasCapability(capabilityId) {
|
|
194
|
+
return this._capabilities.some((c) => c.id === capabilityId && c.status === "Available");
|
|
195
|
+
}
|
|
196
|
+
requireCapability(capabilityId) {
|
|
197
|
+
if (!this.hasCapability(capabilityId)) {
|
|
198
|
+
throw new CapabilityUnavailableError("CAPABILITY_UNAVAILABLE", `Capability '${capabilityId}' is not available`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// -- Config -------------------------------------------------------------
|
|
202
|
+
async getConfig() {
|
|
203
|
+
return this.request("config/get", {});
|
|
204
|
+
}
|
|
205
|
+
async setConfig(config, options) {
|
|
206
|
+
const params = { config };
|
|
207
|
+
if (options?.expectedGeneration !== undefined) {
|
|
208
|
+
params.expected_generation = options.expectedGeneration;
|
|
209
|
+
}
|
|
210
|
+
await this.request("config/set", params);
|
|
211
|
+
}
|
|
212
|
+
async patchConfig(patch, options) {
|
|
213
|
+
const params = { patch };
|
|
214
|
+
if (options?.expectedGeneration !== undefined) {
|
|
215
|
+
params.expected_generation = options.expectedGeneration;
|
|
216
|
+
}
|
|
217
|
+
return this.request("config/patch", params);
|
|
218
|
+
}
|
|
219
|
+
// -- Skills ---------------------------------------------------------------
|
|
220
|
+
async listSkills() {
|
|
221
|
+
const result = await this.request("skills/list", {});
|
|
222
|
+
return result.skills ?? [];
|
|
223
|
+
}
|
|
224
|
+
async inspectSkill(id, options) {
|
|
225
|
+
const params = { id };
|
|
226
|
+
if (options?.source !== undefined) {
|
|
227
|
+
params.source = options.source;
|
|
228
|
+
}
|
|
229
|
+
return this.request("skills/inspect", params);
|
|
230
|
+
}
|
|
231
|
+
// -- Internal methods used by Session -----------------------------------
|
|
232
|
+
/** @internal */
|
|
233
|
+
async _startTurn(sessionId, prompt, options) {
|
|
234
|
+
const params = { session_id: sessionId, prompt };
|
|
235
|
+
const wireRefs = skillRefsToWire(options?.skillRefs);
|
|
236
|
+
if (wireRefs) {
|
|
237
|
+
params.skill_refs = wireRefs;
|
|
238
|
+
}
|
|
239
|
+
if (options?.skillReferences) {
|
|
240
|
+
params.skill_references = options.skillReferences;
|
|
241
|
+
}
|
|
242
|
+
const raw = await this.request("turn/start", params);
|
|
243
|
+
return MeerkatClient.parseRunResult(raw);
|
|
244
|
+
}
|
|
245
|
+
/** @internal */
|
|
246
|
+
_startTurnStreaming(sessionId, prompt, options, session) {
|
|
247
|
+
if (!this.process?.stdin) {
|
|
248
|
+
throw new MeerkatError("NOT_CONNECTED", "Client not connected");
|
|
249
|
+
}
|
|
250
|
+
this.requestId++;
|
|
251
|
+
const requestId = this.requestId;
|
|
252
|
+
const queue = new AsyncQueue();
|
|
253
|
+
this.eventQueues.set(sessionId, queue);
|
|
254
|
+
const responsePromise = this.registerRequest(requestId);
|
|
255
|
+
const params = { session_id: sessionId, prompt };
|
|
256
|
+
const wireRefs = skillRefsToWire(options?.skillRefs);
|
|
257
|
+
if (wireRefs) {
|
|
258
|
+
params.skill_refs = wireRefs;
|
|
259
|
+
}
|
|
260
|
+
if (options?.skillReferences) {
|
|
261
|
+
params.skill_references = options.skillReferences;
|
|
262
|
+
}
|
|
263
|
+
const rpcRequest = { jsonrpc: "2.0", id: requestId, method: "turn/start", params };
|
|
264
|
+
this.process.stdin.write(JSON.stringify(rpcRequest) + "\n");
|
|
265
|
+
return new EventStream({
|
|
266
|
+
sessionId,
|
|
267
|
+
eventQueue: queue,
|
|
268
|
+
responsePromise,
|
|
269
|
+
parseResult: MeerkatClient.parseRunResult,
|
|
270
|
+
session,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
/** @internal */
|
|
274
|
+
async _interrupt(sessionId) {
|
|
275
|
+
await this.request("turn/interrupt", { session_id: sessionId });
|
|
276
|
+
}
|
|
277
|
+
/** @internal */
|
|
278
|
+
async _archive(sessionId) {
|
|
279
|
+
await this.request("session/archive", { session_id: sessionId });
|
|
280
|
+
}
|
|
281
|
+
/** @internal */
|
|
282
|
+
async _send(sessionId, command) {
|
|
283
|
+
return this.request("comms/send", { session_id: sessionId, ...command });
|
|
284
|
+
}
|
|
285
|
+
/** @internal */
|
|
286
|
+
async _peers(sessionId) {
|
|
287
|
+
return this.request("comms/peers", { session_id: sessionId });
|
|
288
|
+
}
|
|
289
|
+
// -- Transport ----------------------------------------------------------
|
|
290
|
+
handleLine(line) {
|
|
291
|
+
let data;
|
|
292
|
+
try {
|
|
293
|
+
data = JSON.parse(line);
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if ("id" in data && typeof data.id === "number") {
|
|
299
|
+
const pending = this.pendingRequests.get(data.id);
|
|
300
|
+
if (pending) {
|
|
301
|
+
this.pendingRequests.delete(data.id);
|
|
302
|
+
const error = data.error;
|
|
303
|
+
if (error) {
|
|
304
|
+
pending.reject(new MeerkatError(String(error.code ?? "UNKNOWN"), String(error.message ?? "Unknown error")));
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
pending.resolve((data.result ?? {}));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
else if ("method" in data) {
|
|
312
|
+
const params = (data.params ?? {});
|
|
313
|
+
const sessionId = String(params.session_id ?? "");
|
|
314
|
+
const event = params.event;
|
|
315
|
+
if (event) {
|
|
316
|
+
const queue = this.eventQueues.get(sessionId);
|
|
317
|
+
if (queue) {
|
|
318
|
+
queue.put(event);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
request(method, params) {
|
|
324
|
+
if (!this.process?.stdin) {
|
|
325
|
+
throw new MeerkatError("NOT_CONNECTED", "Client not connected");
|
|
326
|
+
}
|
|
327
|
+
this.requestId++;
|
|
328
|
+
const id = this.requestId;
|
|
329
|
+
const rpcRequest = { jsonrpc: "2.0", id, method, params };
|
|
330
|
+
const promise = this.registerRequest(id);
|
|
331
|
+
this.process.stdin.write(JSON.stringify(rpcRequest) + "\n");
|
|
332
|
+
return promise;
|
|
333
|
+
}
|
|
334
|
+
registerRequest(id) {
|
|
335
|
+
return new Promise((resolve, reject) => {
|
|
336
|
+
this.pendingRequests.set(id, { resolve, reject });
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
// -- Static helpers -----------------------------------------------------
|
|
340
|
+
static normalizeStatus(raw) {
|
|
341
|
+
if (typeof raw === "string")
|
|
342
|
+
return raw;
|
|
343
|
+
if (typeof raw === "object" && raw !== null) {
|
|
344
|
+
// Rust can emit externally-tagged enums for status:
|
|
345
|
+
// { DisabledByPolicy: { description: "..." } }
|
|
346
|
+
return Object.keys(raw)[0] ?? "Unknown";
|
|
347
|
+
}
|
|
348
|
+
return String(raw);
|
|
349
|
+
}
|
|
350
|
+
static parseSkillDiagnostics(raw) {
|
|
351
|
+
if (!raw || typeof raw !== "object")
|
|
352
|
+
return undefined;
|
|
353
|
+
const data = raw;
|
|
354
|
+
const sourceHealthRaw = data.source_health;
|
|
355
|
+
const rawQuarantined = Array.isArray(data.quarantined)
|
|
356
|
+
? data.quarantined
|
|
357
|
+
: [];
|
|
358
|
+
const quarantined = rawQuarantined
|
|
359
|
+
.filter((item) => typeof item === "object" && item !== null)
|
|
360
|
+
.map((item) => ({
|
|
361
|
+
sourceUuid: String(item.source_uuid ?? ""),
|
|
362
|
+
skillId: String(item.skill_id ?? ""),
|
|
363
|
+
location: String(item.location ?? ""),
|
|
364
|
+
errorCode: String(item.error_code ?? ""),
|
|
365
|
+
errorClass: String(item.error_class ?? ""),
|
|
366
|
+
message: String(item.message ?? ""),
|
|
367
|
+
firstSeenUnixSecs: Number(item.first_seen_unix_secs ?? 0),
|
|
368
|
+
lastSeenUnixSecs: Number(item.last_seen_unix_secs ?? 0),
|
|
369
|
+
}));
|
|
370
|
+
return {
|
|
371
|
+
sourceHealth: {
|
|
372
|
+
state: String(sourceHealthRaw?.state ?? ""),
|
|
373
|
+
invalidRatio: Number(sourceHealthRaw?.invalid_ratio ?? 0),
|
|
374
|
+
invalidCount: Number(sourceHealthRaw?.invalid_count ?? 0),
|
|
375
|
+
totalCount: Number(sourceHealthRaw?.total_count ?? 0),
|
|
376
|
+
failureStreak: Number(sourceHealthRaw?.failure_streak ?? 0),
|
|
377
|
+
handshakeFailed: Boolean(sourceHealthRaw?.handshake_failed ?? false),
|
|
378
|
+
},
|
|
379
|
+
quarantined,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
static checkVersionCompatible(server, client) {
|
|
383
|
+
try {
|
|
384
|
+
const s = server.split(".").map(Number);
|
|
385
|
+
const c = client.split(".").map(Number);
|
|
386
|
+
if (s[0] === 0 && c[0] === 0)
|
|
387
|
+
return s[1] === c[1];
|
|
388
|
+
return s[0] === c[0];
|
|
389
|
+
}
|
|
390
|
+
catch {
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
static parseRunResult(data) {
|
|
395
|
+
const usageRaw = data.usage;
|
|
396
|
+
const usage = {
|
|
397
|
+
inputTokens: Number(usageRaw?.input_tokens ?? 0),
|
|
398
|
+
outputTokens: Number(usageRaw?.output_tokens ?? 0),
|
|
399
|
+
cacheCreationTokens: usageRaw?.cache_creation_tokens != null
|
|
400
|
+
? Number(usageRaw.cache_creation_tokens)
|
|
401
|
+
: undefined,
|
|
402
|
+
cacheReadTokens: usageRaw?.cache_read_tokens != null
|
|
403
|
+
? Number(usageRaw.cache_read_tokens)
|
|
404
|
+
: undefined,
|
|
405
|
+
};
|
|
406
|
+
const rawWarnings = data.schema_warnings;
|
|
407
|
+
const schemaWarnings = rawWarnings?.map((w) => ({
|
|
408
|
+
provider: String(w.provider ?? ""),
|
|
409
|
+
path: String(w.path ?? ""),
|
|
410
|
+
message: String(w.message ?? ""),
|
|
411
|
+
}));
|
|
412
|
+
return {
|
|
413
|
+
sessionId: String(data.session_id ?? ""),
|
|
414
|
+
sessionRef: data.session_ref != null ? String(data.session_ref) : undefined,
|
|
415
|
+
text: String(data.text ?? ""),
|
|
416
|
+
turns: Number(data.turns ?? 0),
|
|
417
|
+
toolCalls: Number(data.tool_calls ?? 0),
|
|
418
|
+
usage,
|
|
419
|
+
structuredOutput: data.structured_output,
|
|
420
|
+
schemaWarnings,
|
|
421
|
+
skillDiagnostics: MeerkatClient.parseSkillDiagnostics(data.skill_diagnostics),
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
static buildCreateParams(prompt, options) {
|
|
425
|
+
const params = { prompt };
|
|
426
|
+
if (!options)
|
|
427
|
+
return params;
|
|
428
|
+
if (options.model)
|
|
429
|
+
params.model = options.model;
|
|
430
|
+
if (options.provider)
|
|
431
|
+
params.provider = options.provider;
|
|
432
|
+
if (options.systemPrompt)
|
|
433
|
+
params.system_prompt = options.systemPrompt;
|
|
434
|
+
if (options.maxTokens)
|
|
435
|
+
params.max_tokens = options.maxTokens;
|
|
436
|
+
if (options.outputSchema)
|
|
437
|
+
params.output_schema = options.outputSchema;
|
|
438
|
+
if (options.structuredOutputRetries != null && options.structuredOutputRetries !== 2) {
|
|
439
|
+
params.structured_output_retries = options.structuredOutputRetries;
|
|
440
|
+
}
|
|
441
|
+
if (options.hooksOverride)
|
|
442
|
+
params.hooks_override = options.hooksOverride;
|
|
443
|
+
if (options.enableBuiltins)
|
|
444
|
+
params.enable_builtins = true;
|
|
445
|
+
if (options.enableShell)
|
|
446
|
+
params.enable_shell = true;
|
|
447
|
+
if (options.enableSubagents)
|
|
448
|
+
params.enable_subagents = true;
|
|
449
|
+
if (options.enableMemory)
|
|
450
|
+
params.enable_memory = true;
|
|
451
|
+
if (options.hostMode)
|
|
452
|
+
params.host_mode = true;
|
|
453
|
+
if (options.commsName)
|
|
454
|
+
params.comms_name = options.commsName;
|
|
455
|
+
if (options.peerMeta != null)
|
|
456
|
+
params.peer_meta = options.peerMeta;
|
|
457
|
+
if (options.providerParams)
|
|
458
|
+
params.provider_params = options.providerParams;
|
|
459
|
+
if (options.preloadSkills != null)
|
|
460
|
+
params.preload_skills = options.preloadSkills;
|
|
461
|
+
const wireRefs = skillRefsToWire(options.skillRefs);
|
|
462
|
+
if (wireRefs)
|
|
463
|
+
params.skill_refs = wireRefs;
|
|
464
|
+
if (options.skillReferences != null)
|
|
465
|
+
params.skill_references = options.skillReferences;
|
|
466
|
+
return params;
|
|
467
|
+
}
|
|
468
|
+
// -- Binary resolution --------------------------------------------------
|
|
23
469
|
static commandPath(command) {
|
|
24
470
|
if (path.isAbsolute(command)) {
|
|
25
471
|
return existsSync(command) ? command : null;
|
|
@@ -59,39 +505,20 @@ export class MeerkatClient {
|
|
|
59
505
|
const architecture = os.arch();
|
|
60
506
|
if (process.platform === "darwin") {
|
|
61
507
|
if (architecture === "arm64") {
|
|
62
|
-
return {
|
|
63
|
-
target: "aarch64-apple-darwin",
|
|
64
|
-
archiveExt: "tar.gz",
|
|
65
|
-
binaryName: "rkat-rpc",
|
|
66
|
-
};
|
|
508
|
+
return { target: "aarch64-apple-darwin", archiveExt: "tar.gz", binaryName: "rkat-rpc" };
|
|
67
509
|
}
|
|
68
|
-
throw new MeerkatError("UNSUPPORTED_PLATFORM", `Unsupported macOS architecture '${architecture}'
|
|
510
|
+
throw new MeerkatError("UNSUPPORTED_PLATFORM", `Unsupported macOS architecture '${architecture}'.`);
|
|
69
511
|
}
|
|
70
512
|
if (process.platform === "linux") {
|
|
71
|
-
if (architecture === "x64")
|
|
72
|
-
return {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
binaryName: "rkat-rpc",
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
if (architecture === "arm64") {
|
|
79
|
-
return {
|
|
80
|
-
target: "aarch64-unknown-linux-gnu",
|
|
81
|
-
archiveExt: "tar.gz",
|
|
82
|
-
binaryName: "rkat-rpc",
|
|
83
|
-
};
|
|
84
|
-
}
|
|
513
|
+
if (architecture === "x64")
|
|
514
|
+
return { target: "x86_64-unknown-linux-gnu", archiveExt: "tar.gz", binaryName: "rkat-rpc" };
|
|
515
|
+
if (architecture === "arm64")
|
|
516
|
+
return { target: "aarch64-unknown-linux-gnu", archiveExt: "tar.gz", binaryName: "rkat-rpc" };
|
|
85
517
|
throw new MeerkatError("UNSUPPORTED_PLATFORM", `Unsupported Linux architecture '${architecture}'.`);
|
|
86
518
|
}
|
|
87
519
|
if (process.platform === "win32") {
|
|
88
|
-
if (architecture === "x64")
|
|
89
|
-
return {
|
|
90
|
-
target: "x86_64-pc-windows-msvc",
|
|
91
|
-
archiveExt: "zip",
|
|
92
|
-
binaryName: "rkat-rpc.exe",
|
|
93
|
-
};
|
|
94
|
-
}
|
|
520
|
+
if (architecture === "x64")
|
|
521
|
+
return { target: "x86_64-pc-windows-msvc", archiveExt: "zip", binaryName: "rkat-rpc.exe" };
|
|
95
522
|
throw new MeerkatError("UNSUPPORTED_PLATFORM", `Unsupported Windows architecture '${architecture}'.`);
|
|
96
523
|
}
|
|
97
524
|
throw new MeerkatError("UNSUPPORTED_PLATFORM", `Unsupported platform '${process.platform}'.`);
|
|
@@ -100,12 +527,8 @@ export class MeerkatClient {
|
|
|
100
527
|
return new Promise((resolve, reject) => {
|
|
101
528
|
const proc = spawn(command, args, { stdio: ["ignore", "inherit", "pipe"] });
|
|
102
529
|
let stderr = "";
|
|
103
|
-
proc.stderr?.on("data", (chunk) => {
|
|
104
|
-
|
|
105
|
-
});
|
|
106
|
-
proc.on("error", (error) => {
|
|
107
|
-
reject(error);
|
|
108
|
-
});
|
|
530
|
+
proc.stderr?.on("data", (chunk) => { stderr += String(chunk); });
|
|
531
|
+
proc.on("error", (error) => { reject(error); });
|
|
109
532
|
proc.on("close", (code) => {
|
|
110
533
|
if (code === 0) {
|
|
111
534
|
resolve();
|
|
@@ -118,12 +541,10 @@ export class MeerkatClient {
|
|
|
118
541
|
static async extractZip(archivePath, destinationDir) {
|
|
119
542
|
try {
|
|
120
543
|
await MeerkatClient.runCommand("tar", ["-xf", archivePath, "-C", destinationDir]);
|
|
121
|
-
return;
|
|
122
544
|
}
|
|
123
|
-
catch
|
|
545
|
+
catch {
|
|
124
546
|
await MeerkatClient.runCommand("powershell", [
|
|
125
|
-
"-NoProfile",
|
|
126
|
-
"-Command",
|
|
547
|
+
"-NoProfile", "-Command",
|
|
127
548
|
`Expand-Archive -LiteralPath '${archivePath.replaceAll("'", "''")}' -DestinationPath '${destinationDir.replaceAll("'", "''")}' -Force`,
|
|
128
549
|
]);
|
|
129
550
|
}
|
|
@@ -136,9 +557,8 @@ export class MeerkatClient {
|
|
|
136
557
|
const baseDir = path.join(MEERKAT_BINARY_CACHE_ROOT, `v${version}`, target);
|
|
137
558
|
mkdirSync(baseDir, { recursive: true });
|
|
138
559
|
const cached = path.join(baseDir, binaryName);
|
|
139
|
-
if (existsSync(cached))
|
|
560
|
+
if (existsSync(cached))
|
|
140
561
|
return cached;
|
|
141
|
-
}
|
|
142
562
|
const response = await fetch(url);
|
|
143
563
|
if (!response.ok) {
|
|
144
564
|
throw new MeerkatError("BINARY_DOWNLOAD_FAILED", `Failed to download binary from ${url} (HTTP ${response.status})`);
|
|
@@ -163,9 +583,8 @@ export class MeerkatClient {
|
|
|
163
583
|
}
|
|
164
584
|
catch { /* best-effort cleanup */ }
|
|
165
585
|
}
|
|
166
|
-
if (process.platform !== "win32")
|
|
586
|
+
if (process.platform !== "win32")
|
|
167
587
|
chmodSync(cached, 0o755);
|
|
168
|
-
}
|
|
169
588
|
return cached;
|
|
170
589
|
}
|
|
171
590
|
static async resolveBinaryPath(requestedPath) {
|
|
@@ -173,293 +592,54 @@ export class MeerkatClient {
|
|
|
173
592
|
if (overridden) {
|
|
174
593
|
const candidate = MeerkatClient.resolveCandidatePath(overridden);
|
|
175
594
|
if (!candidate) {
|
|
176
|
-
throw new MeerkatError("BINARY_NOT_FOUND", `Binary not found at MEERKAT_BIN_PATH='${overridden}'
|
|
595
|
+
throw new MeerkatError("BINARY_NOT_FOUND", `Binary not found at MEERKAT_BIN_PATH='${overridden}'.`);
|
|
177
596
|
}
|
|
178
|
-
return {
|
|
179
|
-
command: candidate,
|
|
180
|
-
useLegacySubcommand: path.basename(candidate) === "rkat",
|
|
181
|
-
};
|
|
597
|
+
return { command: candidate, useLegacySubcommand: path.basename(candidate) === "rkat" };
|
|
182
598
|
}
|
|
183
599
|
if (requestedPath !== "rkat-rpc") {
|
|
184
600
|
const candidate = MeerkatClient.resolveCandidatePath(requestedPath);
|
|
185
601
|
if (!candidate) {
|
|
186
|
-
throw new MeerkatError("BINARY_NOT_FOUND", `Binary not found at '${requestedPath}'
|
|
602
|
+
throw new MeerkatError("BINARY_NOT_FOUND", `Binary not found at '${requestedPath}'.`);
|
|
187
603
|
}
|
|
188
|
-
return {
|
|
189
|
-
command: candidate,
|
|
190
|
-
useLegacySubcommand: path.basename(candidate) === "rkat",
|
|
191
|
-
};
|
|
604
|
+
return { command: candidate, useLegacySubcommand: path.basename(candidate) === "rkat" };
|
|
192
605
|
}
|
|
193
606
|
const defaultBinary = MeerkatClient.commandPath("rkat-rpc");
|
|
194
|
-
if (defaultBinary)
|
|
195
|
-
return {
|
|
196
|
-
command: defaultBinary,
|
|
197
|
-
useLegacySubcommand: false,
|
|
198
|
-
};
|
|
199
|
-
}
|
|
607
|
+
if (defaultBinary)
|
|
608
|
+
return { command: defaultBinary, useLegacySubcommand: false };
|
|
200
609
|
try {
|
|
201
610
|
const downloaded = await MeerkatClient.ensureDownloadedBinary();
|
|
202
611
|
return { command: downloaded, useLegacySubcommand: false };
|
|
203
612
|
}
|
|
204
613
|
catch (error) {
|
|
205
614
|
const legacy = MeerkatClient.commandPath("rkat");
|
|
206
|
-
if (legacy)
|
|
615
|
+
if (legacy)
|
|
207
616
|
return { command: legacy, useLegacySubcommand: true };
|
|
208
|
-
}
|
|
209
617
|
if (error instanceof MeerkatError)
|
|
210
618
|
throw error;
|
|
211
619
|
throw new MeerkatError("BINARY_NOT_FOUND", `Could not find '${MEERKAT_RELEASE_BINARY}' and auto-download failed.`);
|
|
212
620
|
}
|
|
213
621
|
}
|
|
214
|
-
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
this.rkatPath = resolved.command;
|
|
622
|
+
static buildArgs(legacy, options) {
|
|
623
|
+
if (legacy)
|
|
624
|
+
return ["rpc"];
|
|
625
|
+
if (!options)
|
|
626
|
+
return [];
|
|
220
627
|
const args = [];
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
options
|
|
225
|
-
|
|
226
|
-
options
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
args.push("
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
args.push("--isolated");
|
|
237
|
-
}
|
|
238
|
-
if (options?.realmId) {
|
|
239
|
-
args.push("--realm", options.realmId);
|
|
240
|
-
}
|
|
241
|
-
if (options?.instanceId) {
|
|
242
|
-
args.push("--instance", options.instanceId);
|
|
243
|
-
}
|
|
244
|
-
if (options?.realmBackend) {
|
|
245
|
-
args.push("--realm-backend", options.realmBackend);
|
|
246
|
-
}
|
|
247
|
-
if (options?.stateRoot) {
|
|
248
|
-
args.push("--state-root", options.stateRoot);
|
|
249
|
-
}
|
|
250
|
-
if (options?.contextRoot) {
|
|
251
|
-
args.push("--context-root", options.contextRoot);
|
|
252
|
-
}
|
|
253
|
-
if (options?.userConfigRoot) {
|
|
254
|
-
args.push("--user-config-root", options.userConfigRoot);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
this.process = spawn(this.rkatPath, args, {
|
|
258
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
259
|
-
});
|
|
260
|
-
const rl = createInterface({ input: this.process.stdout });
|
|
261
|
-
rl.on("line", (line) => {
|
|
262
|
-
try {
|
|
263
|
-
const response = JSON.parse(line);
|
|
264
|
-
if ("id" in response &&
|
|
265
|
-
typeof response.id === "number" &&
|
|
266
|
-
this.pendingRequests.has(response.id)) {
|
|
267
|
-
const pending = this.pendingRequests.get(response.id);
|
|
268
|
-
this.pendingRequests.delete(response.id);
|
|
269
|
-
const error = response.error;
|
|
270
|
-
if (error) {
|
|
271
|
-
pending.reject(new MeerkatError(String(error.code ?? "UNKNOWN"), String(error.message ?? "Unknown error")));
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
pending.resolve(response.result ?? {});
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
// Ignore non-JSON lines
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
// Initialize
|
|
283
|
-
const initResult = (await this.request("initialize", {}));
|
|
284
|
-
const serverVersion = String(initResult.contract_version ?? "");
|
|
285
|
-
if (!this.checkVersionCompatible(serverVersion, CONTRACT_VERSION)) {
|
|
286
|
-
throw new MeerkatError("VERSION_MISMATCH", `Server version ${serverVersion} incompatible with SDK ${CONTRACT_VERSION}`);
|
|
287
|
-
}
|
|
288
|
-
// Fetch capabilities
|
|
289
|
-
const capsResult = (await this.request("capabilities/get", {}));
|
|
290
|
-
this.capabilities = {
|
|
291
|
-
contract_version: String(capsResult.contract_version ?? ""),
|
|
292
|
-
capabilities: (capsResult.capabilities ?? []).map((cap) => ({
|
|
293
|
-
id: String(cap.id ?? ""),
|
|
294
|
-
description: String(cap.description ?? ""),
|
|
295
|
-
status: MeerkatClient.normalizeStatus(cap.status),
|
|
296
|
-
})),
|
|
297
|
-
};
|
|
298
|
-
return this;
|
|
299
|
-
}
|
|
300
|
-
async close() {
|
|
301
|
-
if (this.process) {
|
|
302
|
-
this.process.kill();
|
|
303
|
-
this.process = null;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
async createSession(params) {
|
|
307
|
-
const result = (await this.request("session/create", params));
|
|
308
|
-
return this.parseRunResult(result);
|
|
309
|
-
}
|
|
310
|
-
async startTurn(sessionId, prompt, options) {
|
|
311
|
-
const result = (await this.request("turn/start", {
|
|
312
|
-
session_id: sessionId,
|
|
313
|
-
prompt,
|
|
314
|
-
...options,
|
|
315
|
-
}));
|
|
316
|
-
return this.parseRunResult(result);
|
|
317
|
-
}
|
|
318
|
-
async interrupt(sessionId) {
|
|
319
|
-
await this.request("turn/interrupt", { session_id: sessionId });
|
|
320
|
-
}
|
|
321
|
-
async listSessions() {
|
|
322
|
-
const result = (await this.request("session/list", {}));
|
|
323
|
-
return result.sessions ?? [];
|
|
324
|
-
}
|
|
325
|
-
async readSession(sessionId) {
|
|
326
|
-
return (await this.request("session/read", {
|
|
327
|
-
session_id: sessionId,
|
|
328
|
-
}));
|
|
329
|
-
}
|
|
330
|
-
async archiveSession(sessionId) {
|
|
331
|
-
await this.request("session/archive", { session_id: sessionId });
|
|
332
|
-
}
|
|
333
|
-
async getCapabilities() {
|
|
334
|
-
if (this.capabilities)
|
|
335
|
-
return this.capabilities;
|
|
336
|
-
const result = (await this.request("capabilities/get", {}));
|
|
337
|
-
return {
|
|
338
|
-
contract_version: String(result.contract_version ?? ""),
|
|
339
|
-
capabilities: [],
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
hasCapability(capabilityId) {
|
|
343
|
-
if (!this.capabilities)
|
|
344
|
-
return false;
|
|
345
|
-
return this.capabilities.capabilities.some((c) => c.id === capabilityId && c.status === "Available");
|
|
346
|
-
}
|
|
347
|
-
requireCapability(capabilityId) {
|
|
348
|
-
if (!this.hasCapability(capabilityId)) {
|
|
349
|
-
throw new MeerkatError("CAPABILITY_UNAVAILABLE", `Capability '${capabilityId}' is not available`);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
// --- Config ---
|
|
353
|
-
async getConfig() {
|
|
354
|
-
return (await this.request("config/get", {}));
|
|
355
|
-
}
|
|
356
|
-
async setConfig(config) {
|
|
357
|
-
await this.request("config/set", config);
|
|
358
|
-
}
|
|
359
|
-
async patchConfig(patch) {
|
|
360
|
-
return (await this.request("config/patch", patch));
|
|
361
|
-
}
|
|
362
|
-
/**
|
|
363
|
-
* Send a canonical comms command to a session.
|
|
364
|
-
*
|
|
365
|
-
* @param sessionId - Target session ID
|
|
366
|
-
* @param command - Command fields (kind, to, body, intent, params, etc.)
|
|
367
|
-
* @returns Receipt info on success
|
|
368
|
-
*/
|
|
369
|
-
async send(sessionId, command) {
|
|
370
|
-
return (await this.request("comms/send", {
|
|
371
|
-
session_id: sessionId,
|
|
372
|
-
...command,
|
|
373
|
-
}));
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Send a command and open a stream in one call.
|
|
377
|
-
*
|
|
378
|
-
* @param sessionId - Target session ID
|
|
379
|
-
* @param command - Command fields (kind, to, body, etc.)
|
|
380
|
-
* @returns Receipt and stream info
|
|
381
|
-
*/
|
|
382
|
-
async sendAndStream(sessionId, command) {
|
|
383
|
-
return (await this.request("comms/send", {
|
|
384
|
-
session_id: sessionId,
|
|
385
|
-
stream: "reserve_interaction",
|
|
386
|
-
...command,
|
|
387
|
-
}));
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
* List peers visible to a session's comms runtime.
|
|
391
|
-
*
|
|
392
|
-
* @param sessionId - Target session ID
|
|
393
|
-
* @returns Object with `{ peers: [...] }`
|
|
394
|
-
*/
|
|
395
|
-
async peers(sessionId) {
|
|
396
|
-
return (await this.request("comms/peers", {
|
|
397
|
-
session_id: sessionId,
|
|
398
|
-
}));
|
|
399
|
-
}
|
|
400
|
-
// --- Internal ---
|
|
401
|
-
/**
|
|
402
|
-
* Normalize a CapabilityStatus from the wire.
|
|
403
|
-
* Available is the string "Available", but other variants are
|
|
404
|
-
* externally-tagged objects like {"DisabledByPolicy": {"description": "..."}}.
|
|
405
|
-
* We normalize to the variant name string.
|
|
406
|
-
*/
|
|
407
|
-
static normalizeStatus(raw) {
|
|
408
|
-
if (typeof raw === "string")
|
|
409
|
-
return raw;
|
|
410
|
-
if (typeof raw === "object" && raw !== null) {
|
|
411
|
-
const keys = Object.keys(raw);
|
|
412
|
-
return keys[0] ?? "Unknown";
|
|
413
|
-
}
|
|
414
|
-
return String(raw);
|
|
415
|
-
}
|
|
416
|
-
request(method, params) {
|
|
417
|
-
if (!this.process?.stdin) {
|
|
418
|
-
throw new MeerkatError("NOT_CONNECTED", "Client not connected");
|
|
419
|
-
}
|
|
420
|
-
this.requestId++;
|
|
421
|
-
const id = this.requestId;
|
|
422
|
-
const request = {
|
|
423
|
-
jsonrpc: "2.0",
|
|
424
|
-
id,
|
|
425
|
-
method,
|
|
426
|
-
params,
|
|
427
|
-
};
|
|
428
|
-
return new Promise((resolve, reject) => {
|
|
429
|
-
this.pendingRequests.set(id, { resolve, reject });
|
|
430
|
-
this.process.stdin.write(JSON.stringify(request) + "\n");
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
checkVersionCompatible(server, client) {
|
|
434
|
-
try {
|
|
435
|
-
const s = server.split(".").map(Number);
|
|
436
|
-
const c = client.split(".").map(Number);
|
|
437
|
-
if (s[0] === 0 && c[0] === 0)
|
|
438
|
-
return s[1] === c[1];
|
|
439
|
-
return s[0] === c[0];
|
|
440
|
-
}
|
|
441
|
-
catch {
|
|
442
|
-
return false;
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
parseRunResult(data) {
|
|
446
|
-
const usage = data.usage;
|
|
447
|
-
return {
|
|
448
|
-
session_id: String(data.session_id ?? ""),
|
|
449
|
-
session_ref: data.session_ref == null ? undefined : String(data.session_ref),
|
|
450
|
-
text: String(data.text ?? ""),
|
|
451
|
-
turns: Number(data.turns ?? 0),
|
|
452
|
-
tool_calls: Number(data.tool_calls ?? 0),
|
|
453
|
-
usage: {
|
|
454
|
-
input_tokens: Number(usage?.input_tokens ?? 0),
|
|
455
|
-
output_tokens: Number(usage?.output_tokens ?? 0),
|
|
456
|
-
total_tokens: Number(usage?.total_tokens ?? 0),
|
|
457
|
-
cache_creation_tokens: usage?.cache_creation_tokens,
|
|
458
|
-
cache_read_tokens: usage?.cache_read_tokens,
|
|
459
|
-
},
|
|
460
|
-
structured_output: data.structured_output,
|
|
461
|
-
schema_warnings: data.schema_warnings,
|
|
462
|
-
};
|
|
628
|
+
if (options.isolated)
|
|
629
|
+
args.push("--isolated");
|
|
630
|
+
if (options.realmId)
|
|
631
|
+
args.push("--realm", options.realmId);
|
|
632
|
+
if (options.instanceId)
|
|
633
|
+
args.push("--instance", options.instanceId);
|
|
634
|
+
if (options.realmBackend)
|
|
635
|
+
args.push("--realm-backend", options.realmBackend);
|
|
636
|
+
if (options.stateRoot)
|
|
637
|
+
args.push("--state-root", options.stateRoot);
|
|
638
|
+
if (options.contextRoot)
|
|
639
|
+
args.push("--context-root", options.contextRoot);
|
|
640
|
+
if (options.userConfigRoot)
|
|
641
|
+
args.push("--user-config-root", options.userConfigRoot);
|
|
642
|
+
return args;
|
|
463
643
|
}
|
|
464
644
|
}
|
|
465
645
|
//# sourceMappingURL=client.js.map
|