@rkat/sdk 0.5.1 → 0.6.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/README.md +65 -21
- package/dist/client.d.ts +226 -65
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1294 -176
- package/dist/client.js.map +1 -1
- package/dist/events.d.ts +162 -32
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +571 -97
- package/dist/events.js.map +1 -1
- package/dist/generated/types.d.ts +1876 -63
- package/dist/generated/types.d.ts.map +1 -1
- package/dist/generated/types.js +2 -2
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/mob.d.ts +33 -22
- package/dist/mob.d.ts.map +1 -1
- package/dist/mob.js +28 -19
- package/dist/mob.js.map +1 -1
- package/dist/realtime.d.ts +45 -0
- package/dist/realtime.d.ts.map +1 -0
- package/dist/realtime.js +166 -0
- package/dist/realtime.js.map +1 -0
- package/dist/session.d.ts +29 -22
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +28 -2
- package/dist/session.js.map +1 -1
- package/dist/types.d.ts +391 -38
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -2
- package/dist/types.js.map +1 -1
- package/package.json +6 -2
package/dist/client.js
CHANGED
|
@@ -25,9 +25,11 @@
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
import { spawn } from "node:child_process";
|
|
28
|
+
import { once } from "node:events";
|
|
28
29
|
import { chmodSync, existsSync, mkdirSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
29
30
|
import os from "node:os";
|
|
30
31
|
import path from "node:path";
|
|
32
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
31
33
|
import { createInterface } from "node:readline";
|
|
32
34
|
import { Buffer } from "node:buffer";
|
|
33
35
|
import { MeerkatError, CapabilityUnavailableError } from "./generated/errors.js";
|
|
@@ -40,31 +42,143 @@ import { EventSubscription } from "./subscription.js";
|
|
|
40
42
|
const MEERKAT_REPO = "lukacf/meerkat";
|
|
41
43
|
const MEERKAT_RELEASE_BINARY = "rkat-rpc";
|
|
42
44
|
const MEERKAT_BINARY_CACHE_ROOT = path.join(os.homedir(), ".cache", "meerkat", "bin", MEERKAT_RELEASE_BINARY);
|
|
45
|
+
const MOB_SPAWN_MANY_FAILURE_CAUSES = new Set([
|
|
46
|
+
"profile_not_found",
|
|
47
|
+
"member_not_found",
|
|
48
|
+
"member_already_exists",
|
|
49
|
+
"not_externally_addressable",
|
|
50
|
+
"invalid_transition",
|
|
51
|
+
"wiring_error",
|
|
52
|
+
"bridge_command_rejected",
|
|
53
|
+
"member_restore_failed",
|
|
54
|
+
"kickoff_wait_timed_out",
|
|
55
|
+
"ready_wait_timed_out",
|
|
56
|
+
"definition_error",
|
|
57
|
+
"flow_not_found",
|
|
58
|
+
"flow_failed",
|
|
59
|
+
"run_not_found",
|
|
60
|
+
"run_canceled",
|
|
61
|
+
"flow_turn_timed_out",
|
|
62
|
+
"frame_depth_limit_exceeded",
|
|
63
|
+
"frame_atomic_persistence_unavailable",
|
|
64
|
+
"spec_revision_conflict",
|
|
65
|
+
"schema_validation",
|
|
66
|
+
"insufficient_targets",
|
|
67
|
+
"topology_violation",
|
|
68
|
+
"bridge_delivery_rejected",
|
|
69
|
+
"supervisor_escalation",
|
|
70
|
+
"unsupported_for_mode",
|
|
71
|
+
"reset_barrier",
|
|
72
|
+
"storage_error",
|
|
73
|
+
"session_error",
|
|
74
|
+
"comms_error",
|
|
75
|
+
"callback_pending",
|
|
76
|
+
"stale_fence_token",
|
|
77
|
+
"stale_event_cursor",
|
|
78
|
+
"work_not_found",
|
|
79
|
+
"internal",
|
|
80
|
+
]);
|
|
81
|
+
function isMobSpawnManyFailureCause(value) {
|
|
82
|
+
return typeof value === "string" && MOB_SPAWN_MANY_FAILURE_CAUSES.has(value);
|
|
83
|
+
}
|
|
43
84
|
/**
|
|
44
|
-
* Normalize a SkillRef to the wire format
|
|
45
|
-
*
|
|
46
|
-
* SkillKey objects are converted from camelCase to snake_case.
|
|
47
|
-
* Legacy strings are parsed and emit a console warning.
|
|
85
|
+
* Normalize a structured SkillRef to the bare SkillKey wire format.
|
|
48
86
|
*/
|
|
49
|
-
function
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
console.warn(`[meerkat-sdk] legacy skill reference '${ref}' is deprecated; pass { sourceUuid, skillName } instead.`);
|
|
59
|
-
return { source_uuid: sourceUuid, skill_name: rest.join("/") };
|
|
87
|
+
function normalizeSkillKey(ref) {
|
|
88
|
+
if (ref === null ||
|
|
89
|
+
typeof ref !== "object" ||
|
|
90
|
+
typeof ref.sourceUuid !== "string" ||
|
|
91
|
+
typeof ref.skillName !== "string") {
|
|
92
|
+
throw new Error("Skill references must be SkillKey objects");
|
|
93
|
+
}
|
|
94
|
+
return { source_uuid: ref.sourceUuid, skill_name: ref.skillName };
|
|
60
95
|
}
|
|
61
|
-
function
|
|
96
|
+
function skillKeysToWire(refs) {
|
|
62
97
|
if (!refs)
|
|
63
98
|
return undefined;
|
|
64
|
-
return refs.map(
|
|
99
|
+
return refs.map(normalizeSkillKey);
|
|
100
|
+
}
|
|
101
|
+
function skillRefsToWire(refs) {
|
|
102
|
+
const keys = skillKeysToWire(refs);
|
|
103
|
+
return keys?.map((key) => ({ kind: "structured", ...key }));
|
|
104
|
+
}
|
|
105
|
+
function setIfDefined(payload, key, value) {
|
|
106
|
+
if (value !== undefined) {
|
|
107
|
+
payload[key] = value;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function mobSpawnPayload(mobId, spec) {
|
|
111
|
+
const payload = {
|
|
112
|
+
mob_id: mobId,
|
|
113
|
+
profile: spec.profile,
|
|
114
|
+
agent_identity: spec.agentIdentity,
|
|
115
|
+
};
|
|
116
|
+
setIfDefined(payload, "initial_message", spec.initialMessage);
|
|
117
|
+
setIfDefined(payload, "runtime_mode", spec.runtimeMode);
|
|
118
|
+
setIfDefined(payload, "backend", spec.backend);
|
|
119
|
+
setIfDefined(payload, "labels", spec.labels);
|
|
120
|
+
setIfDefined(payload, "context", spec.context);
|
|
121
|
+
setIfDefined(payload, "additional_instructions", spec.additionalInstructions);
|
|
122
|
+
setIfDefined(payload, "binding", spec.binding);
|
|
123
|
+
setIfDefined(payload, "shell_env", spec.shellEnv);
|
|
124
|
+
setIfDefined(payload, "auto_wire_parent", spec.autoWireParent);
|
|
125
|
+
setIfDefined(payload, "launch_mode", spec.launchMode);
|
|
126
|
+
setIfDefined(payload, "tool_access_policy", spec.toolAccessPolicy);
|
|
127
|
+
setIfDefined(payload, "budget_split_policy", spec.budgetSplitPolicy);
|
|
128
|
+
setIfDefined(payload, "inherited_tool_filter", spec.inheritedToolFilter);
|
|
129
|
+
setIfDefined(payload, "override_profile", spec.overrideProfile);
|
|
130
|
+
setIfDefined(payload, "auth_binding", spec.authBinding);
|
|
131
|
+
return payload;
|
|
132
|
+
}
|
|
133
|
+
function mobSpawnManySpecPayload(spec) {
|
|
134
|
+
const payload = {
|
|
135
|
+
profile: spec.profile,
|
|
136
|
+
agent_identity: spec.agentIdentity,
|
|
137
|
+
};
|
|
138
|
+
setIfDefined(payload, "initial_message", spec.initialMessage);
|
|
139
|
+
setIfDefined(payload, "runtime_mode", spec.runtimeMode);
|
|
140
|
+
setIfDefined(payload, "backend", spec.backend);
|
|
141
|
+
setIfDefined(payload, "labels", spec.labels);
|
|
142
|
+
setIfDefined(payload, "context", spec.context);
|
|
143
|
+
setIfDefined(payload, "additional_instructions", spec.additionalInstructions);
|
|
144
|
+
setIfDefined(payload, "auth_binding", spec.authBinding);
|
|
145
|
+
return payload;
|
|
146
|
+
}
|
|
147
|
+
function mobTurnStartPayload(mobId, agentIdentity, prompt, options) {
|
|
148
|
+
const payload = {
|
|
149
|
+
mob_id: mobId,
|
|
150
|
+
agent_identity: agentIdentity,
|
|
151
|
+
prompt: typeof prompt === "string"
|
|
152
|
+
? prompt
|
|
153
|
+
: prompt.map((block) => ({ ...block })),
|
|
154
|
+
};
|
|
155
|
+
const wireRefs = skillRefsToWire(options?.skillRefs);
|
|
156
|
+
if (wireRefs) {
|
|
157
|
+
payload.skill_refs = wireRefs;
|
|
158
|
+
}
|
|
159
|
+
if (options?.flowToolOverlay) {
|
|
160
|
+
payload.flow_tool_overlay = {
|
|
161
|
+
allowed_tools: options.flowToolOverlay.allowedTools,
|
|
162
|
+
blocked_tools: options.flowToolOverlay.blockedTools,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
setIfDefined(payload, "additional_instructions", options?.additionalInstructions);
|
|
166
|
+
setIfDefined(payload, "keep_alive", options?.keepAlive);
|
|
167
|
+
setIfDefined(payload, "model", options?.model);
|
|
168
|
+
setIfDefined(payload, "provider", options?.provider);
|
|
169
|
+
setIfDefined(payload, "max_tokens", options?.maxTokens);
|
|
170
|
+
setIfDefined(payload, "system_prompt", options?.systemPrompt);
|
|
171
|
+
setIfDefined(payload, "output_schema", options?.outputSchema);
|
|
172
|
+
setIfDefined(payload, "structured_output_retries", options?.structuredOutputRetries);
|
|
173
|
+
setIfDefined(payload, "provider_params", options?.providerParams);
|
|
174
|
+
setIfDefined(payload, "clear_provider_params", options?.clearProviderParams);
|
|
175
|
+
setIfDefined(payload, "auth_binding", options?.authBinding);
|
|
176
|
+
setIfDefined(payload, "clear_auth_binding", options?.clearAuthBinding);
|
|
177
|
+
return payload;
|
|
65
178
|
}
|
|
66
179
|
export class MeerkatClient {
|
|
67
180
|
process = null;
|
|
181
|
+
processStderr = "";
|
|
68
182
|
requestId = 0;
|
|
69
183
|
_capabilities = [];
|
|
70
184
|
_methods = new Set();
|
|
@@ -118,6 +232,31 @@ export class MeerkatClient {
|
|
|
118
232
|
this.process = spawn(this.rkatPath, args, {
|
|
119
233
|
stdio: ["pipe", "pipe", "pipe"],
|
|
120
234
|
});
|
|
235
|
+
const child = this.process;
|
|
236
|
+
this.processStderr = "";
|
|
237
|
+
child.stderr?.on("data", (chunk) => {
|
|
238
|
+
this.processStderr = (this.processStderr + String(chunk)).slice(-8192);
|
|
239
|
+
});
|
|
240
|
+
child.once("error", (error) => {
|
|
241
|
+
if (this.process === child) {
|
|
242
|
+
this.process = null;
|
|
243
|
+
this.rejectPendingRequests(new MeerkatError("PROCESS_ERROR", `Failed to start ${this.rkatPath}: ${error.message}`));
|
|
244
|
+
this.closeQueues();
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
child.once("close", (code, signal) => {
|
|
248
|
+
const expectedClose = this.process !== child;
|
|
249
|
+
if (this.process === child) {
|
|
250
|
+
this.process = null;
|
|
251
|
+
this.rl?.close();
|
|
252
|
+
this.rl = null;
|
|
253
|
+
}
|
|
254
|
+
if (!expectedClose) {
|
|
255
|
+
const suffix = this.processStderr.trim() ? `: ${this.processStderr.trim()}` : "";
|
|
256
|
+
this.rejectPendingRequests(new MeerkatError("PROCESS_EXITED", `${this.rkatPath} exited before replying (code ${code ?? "null"}, signal ${signal ?? "null"})${suffix}`));
|
|
257
|
+
this.closeQueues();
|
|
258
|
+
}
|
|
259
|
+
});
|
|
121
260
|
this.rl = createInterface({ input: this.process.stdout });
|
|
122
261
|
this.rl.on("line", (line) => this.handleLine(line));
|
|
123
262
|
// Handshake
|
|
@@ -153,14 +292,32 @@ export class MeerkatClient {
|
|
|
153
292
|
this.rl.close();
|
|
154
293
|
this.rl = null;
|
|
155
294
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
295
|
+
const process = this.process;
|
|
296
|
+
this.process = null;
|
|
297
|
+
if (process) {
|
|
298
|
+
process.stdin?.end();
|
|
299
|
+
const closed = once(process, "close").catch(() => []);
|
|
300
|
+
process.kill();
|
|
301
|
+
const timeout = delay(5000).then(() => "timeout");
|
|
302
|
+
const outcome = await Promise.race([closed, timeout]);
|
|
303
|
+
if (outcome === "timeout" && process.exitCode == null && process.signalCode == null) {
|
|
304
|
+
process.kill("SIGKILL");
|
|
305
|
+
await closed.catch(() => { });
|
|
306
|
+
}
|
|
307
|
+
process.stdin?.destroy();
|
|
308
|
+
process.stdout?.destroy();
|
|
309
|
+
process.stderr?.destroy();
|
|
159
310
|
}
|
|
311
|
+
this.rejectPendingRequests(new MeerkatError("CLIENT_CLOSED", "Client closed"));
|
|
312
|
+
this.closeQueues();
|
|
313
|
+
}
|
|
314
|
+
rejectPendingRequests(reason) {
|
|
160
315
|
for (const [, pending] of this.pendingRequests) {
|
|
161
|
-
pending.reject(
|
|
316
|
+
pending.reject(reason);
|
|
162
317
|
}
|
|
163
318
|
this.pendingRequests.clear();
|
|
319
|
+
}
|
|
320
|
+
closeQueues() {
|
|
164
321
|
for (const [, queue] of this.eventQueues) {
|
|
165
322
|
queue.put(null);
|
|
166
323
|
}
|
|
@@ -251,22 +408,74 @@ export class MeerkatClient {
|
|
|
251
408
|
const raw = await this.request("session/create", params);
|
|
252
409
|
return new DeferredSession(this, String(raw.session_id ?? ""), raw.session_ref != null ? String(raw.session_ref) : undefined);
|
|
253
410
|
}
|
|
411
|
+
async askHelp(question, options) {
|
|
412
|
+
const params = { question };
|
|
413
|
+
if (options?.prompt !== undefined)
|
|
414
|
+
params.prompt = options.prompt;
|
|
415
|
+
if (options?.executionMode !== undefined) {
|
|
416
|
+
params.execution_mode = options.executionMode;
|
|
417
|
+
}
|
|
418
|
+
if (options?.model !== undefined)
|
|
419
|
+
params.model = options.model;
|
|
420
|
+
if (options?.provider !== undefined)
|
|
421
|
+
params.provider = options.provider;
|
|
422
|
+
if (options?.maxTokens !== undefined)
|
|
423
|
+
params.max_tokens = options.maxTokens;
|
|
424
|
+
const raw = await this.request("help/ask", params);
|
|
425
|
+
return MeerkatClient.parseRunResult(raw);
|
|
426
|
+
}
|
|
254
427
|
// -- Session queries ----------------------------------------------------
|
|
255
|
-
async listSessions() {
|
|
256
|
-
const
|
|
428
|
+
async listSessions(options) {
|
|
429
|
+
const params = {};
|
|
430
|
+
if (options?.labels)
|
|
431
|
+
params.labels = options.labels;
|
|
432
|
+
if (options?.limit !== undefined)
|
|
433
|
+
params.limit = options.limit;
|
|
434
|
+
if (options?.offset !== undefined)
|
|
435
|
+
params.offset = options.offset;
|
|
436
|
+
const result = await this.request("session/list", params);
|
|
257
437
|
const sessions = result.sessions ?? [];
|
|
258
|
-
return sessions.map((s) => (
|
|
259
|
-
sessionId: String(s.session_id ?? ""),
|
|
260
|
-
sessionRef: s.session_ref != null ? String(s.session_ref) : undefined,
|
|
261
|
-
createdAt: String(s.created_at ?? ""),
|
|
262
|
-
updatedAt: String(s.updated_at ?? ""),
|
|
263
|
-
messageCount: Number(s.message_count ?? 0),
|
|
264
|
-
totalTokens: Number(s.total_tokens ?? 0),
|
|
265
|
-
isActive: Boolean(s.is_active),
|
|
266
|
-
}));
|
|
438
|
+
return sessions.map((s) => MeerkatClient.parseSessionInfo(s));
|
|
267
439
|
}
|
|
268
440
|
async readSession(sessionId) {
|
|
269
|
-
|
|
441
|
+
const raw = await this.request("session/read", { session_id: sessionId });
|
|
442
|
+
return MeerkatClient.parseSessionInfo(raw);
|
|
443
|
+
}
|
|
444
|
+
async sendExternalEvent(sessionId, eventType, payload, options) {
|
|
445
|
+
const params = {
|
|
446
|
+
session_id: sessionId,
|
|
447
|
+
kind: "generic_json",
|
|
448
|
+
event_type: eventType,
|
|
449
|
+
payload,
|
|
450
|
+
};
|
|
451
|
+
if (options?.blocks !== undefined) {
|
|
452
|
+
params.blocks = options.blocks;
|
|
453
|
+
}
|
|
454
|
+
return this.request("session/external_event", params);
|
|
455
|
+
}
|
|
456
|
+
async sendPeerResponseTerminal(sessionId, peerId, requestId, status, result, options) {
|
|
457
|
+
const params = {
|
|
458
|
+
session_id: sessionId,
|
|
459
|
+
peer_id: peerId,
|
|
460
|
+
request_id: requestId,
|
|
461
|
+
status,
|
|
462
|
+
result,
|
|
463
|
+
};
|
|
464
|
+
if (options?.displayName !== undefined) {
|
|
465
|
+
params.display_name = options.displayName;
|
|
466
|
+
}
|
|
467
|
+
return this.request("session/peer_response_terminal", params);
|
|
468
|
+
}
|
|
469
|
+
async injectContext(sessionId, text, options) {
|
|
470
|
+
const params = { session_id: sessionId, text };
|
|
471
|
+
if (options?.source !== undefined) {
|
|
472
|
+
params.source = options.source;
|
|
473
|
+
}
|
|
474
|
+
if (options?.idempotencyKey !== undefined) {
|
|
475
|
+
params.idempotency_key = options.idempotencyKey;
|
|
476
|
+
}
|
|
477
|
+
const result = await this.request("session/inject_context", params);
|
|
478
|
+
return { status: String(result.status ?? "") };
|
|
270
479
|
}
|
|
271
480
|
async readSessionHistory(sessionId, options) {
|
|
272
481
|
const params = {
|
|
@@ -297,21 +506,24 @@ export class MeerkatClient {
|
|
|
297
506
|
}
|
|
298
507
|
// -- Config -------------------------------------------------------------
|
|
299
508
|
async getConfig() {
|
|
300
|
-
|
|
509
|
+
const raw = await this.request("config/get", {});
|
|
510
|
+
return MeerkatClient.parseConfigEnvelope(raw);
|
|
301
511
|
}
|
|
302
512
|
async setConfig(config, options) {
|
|
303
513
|
const params = { config };
|
|
304
514
|
if (options?.expectedGeneration !== undefined) {
|
|
305
515
|
params.expected_generation = options.expectedGeneration;
|
|
306
516
|
}
|
|
307
|
-
|
|
517
|
+
const raw = await this.request("config/set", params);
|
|
518
|
+
return MeerkatClient.parseConfigEnvelope(raw);
|
|
308
519
|
}
|
|
309
520
|
async patchConfig(patch, options) {
|
|
310
521
|
const params = { patch };
|
|
311
522
|
if (options?.expectedGeneration !== undefined) {
|
|
312
523
|
params.expected_generation = options.expectedGeneration;
|
|
313
524
|
}
|
|
314
|
-
|
|
525
|
+
const raw = await this.request("config/patch", params);
|
|
526
|
+
return MeerkatClient.parseConfigEnvelope(raw);
|
|
315
527
|
}
|
|
316
528
|
async mcpAdd(params) {
|
|
317
529
|
const raw = await this.request("mcp/add", params);
|
|
@@ -340,13 +552,6 @@ export class MeerkatClient {
|
|
|
340
552
|
const result = await this.request("skills/list", {});
|
|
341
553
|
return result.skills ?? [];
|
|
342
554
|
}
|
|
343
|
-
async inspectSkill(id, options) {
|
|
344
|
-
const params = { id };
|
|
345
|
-
if (options?.source !== undefined) {
|
|
346
|
-
params.source = options.source;
|
|
347
|
-
}
|
|
348
|
-
return this.request("skills/inspect", params);
|
|
349
|
-
}
|
|
350
555
|
async getBlob(blobId) {
|
|
351
556
|
const result = await this.request("blob/get", { blob_id: blobId });
|
|
352
557
|
return {
|
|
@@ -355,6 +560,115 @@ export class MeerkatClient {
|
|
|
355
560
|
dataBase64: String(result.data ?? ""),
|
|
356
561
|
};
|
|
357
562
|
}
|
|
563
|
+
async getRuntimeHostInfo() {
|
|
564
|
+
return this.request("runtime/host_info", {});
|
|
565
|
+
}
|
|
566
|
+
async getRuntimeHostCapabilities() {
|
|
567
|
+
return this.request("runtime/capabilities", {});
|
|
568
|
+
}
|
|
569
|
+
async getRuntimeHostHealth() {
|
|
570
|
+
return this.request("runtime/health", {});
|
|
571
|
+
}
|
|
572
|
+
async requestApproval(params) {
|
|
573
|
+
return this.request("approval/request", params);
|
|
574
|
+
}
|
|
575
|
+
async listApprovals(params = {}) {
|
|
576
|
+
return this.request("approval/list", params);
|
|
577
|
+
}
|
|
578
|
+
async getApproval(params) {
|
|
579
|
+
return this.request("approval/get", params);
|
|
580
|
+
}
|
|
581
|
+
async decideApproval(params) {
|
|
582
|
+
return this.request("approval/decide", params);
|
|
583
|
+
}
|
|
584
|
+
async listArtifacts(params = {}) {
|
|
585
|
+
return this.request("artifact/list", params);
|
|
586
|
+
}
|
|
587
|
+
async getArtifact(params) {
|
|
588
|
+
return this.request("artifact/get", params);
|
|
589
|
+
}
|
|
590
|
+
async downloadArtifact(params) {
|
|
591
|
+
return this.request("artifact/download", params);
|
|
592
|
+
}
|
|
593
|
+
async latestEventCursor(params) {
|
|
594
|
+
return this.request("events/latest_cursor", params);
|
|
595
|
+
}
|
|
596
|
+
async listEventsSince(params) {
|
|
597
|
+
return this.request("events/list_since", params);
|
|
598
|
+
}
|
|
599
|
+
async eventSnapshot(params) {
|
|
600
|
+
return this.request("events/snapshot", params);
|
|
601
|
+
}
|
|
602
|
+
async getModelsCatalog() {
|
|
603
|
+
const result = await this.request("models/catalog", {});
|
|
604
|
+
return MeerkatClient.parseModelsCatalog(result);
|
|
605
|
+
}
|
|
606
|
+
async createSchedule(request) {
|
|
607
|
+
const result = await this.request("schedule/create", MeerkatClient.toWireCreateScheduleRequest(request));
|
|
608
|
+
return MeerkatClient.parseSchedule(result);
|
|
609
|
+
}
|
|
610
|
+
async getSchedule(scheduleId) {
|
|
611
|
+
const result = await this.request("schedule/get", { schedule_id: scheduleId });
|
|
612
|
+
return MeerkatClient.parseSchedule(result);
|
|
613
|
+
}
|
|
614
|
+
async listSchedules(_options) {
|
|
615
|
+
const params = {};
|
|
616
|
+
if (_options?.labels)
|
|
617
|
+
params.labels = _options.labels;
|
|
618
|
+
if (_options?.limit !== undefined)
|
|
619
|
+
params.limit = _options.limit;
|
|
620
|
+
if (_options?.offset !== undefined)
|
|
621
|
+
params.offset = _options.offset;
|
|
622
|
+
const result = await this.request("schedule/list", params);
|
|
623
|
+
const schedules = Array.isArray(result.schedules)
|
|
624
|
+
? result.schedules
|
|
625
|
+
: [];
|
|
626
|
+
return schedules.map((schedule) => MeerkatClient.parseSchedule(schedule));
|
|
627
|
+
}
|
|
628
|
+
async updateSchedule(request) {
|
|
629
|
+
const params = {
|
|
630
|
+
schedule_id: request.scheduleId,
|
|
631
|
+
...MeerkatClient.toWireUpdateSchedulePatch(request.update),
|
|
632
|
+
};
|
|
633
|
+
const result = await this.request("schedule/update", params);
|
|
634
|
+
return MeerkatClient.parseSchedule(result);
|
|
635
|
+
}
|
|
636
|
+
async pauseSchedule(scheduleId) {
|
|
637
|
+
const result = await this.request("schedule/pause", { schedule_id: scheduleId });
|
|
638
|
+
return MeerkatClient.parseSchedule(result);
|
|
639
|
+
}
|
|
640
|
+
async resumeSchedule(scheduleId) {
|
|
641
|
+
const result = await this.request("schedule/resume", { schedule_id: scheduleId });
|
|
642
|
+
return MeerkatClient.parseSchedule(result);
|
|
643
|
+
}
|
|
644
|
+
async deleteSchedule(scheduleId) {
|
|
645
|
+
const result = await this.request("schedule/delete", { schedule_id: scheduleId });
|
|
646
|
+
return MeerkatClient.parseSchedule(result);
|
|
647
|
+
}
|
|
648
|
+
async listScheduleOccurrences(scheduleId, options) {
|
|
649
|
+
const params = { schedule_id: scheduleId };
|
|
650
|
+
if (options?.includeTerminal !== undefined) {
|
|
651
|
+
params.include_terminal = options.includeTerminal;
|
|
652
|
+
}
|
|
653
|
+
const result = await this.request("schedule/occurrences", params);
|
|
654
|
+
const occurrences = Array.isArray(result.occurrences)
|
|
655
|
+
? result.occurrences.map((occurrence) => MeerkatClient.parseScheduleOccurrence(occurrence))
|
|
656
|
+
: [];
|
|
657
|
+
return { occurrences };
|
|
658
|
+
}
|
|
659
|
+
async listScheduleTools() {
|
|
660
|
+
const result = await this.request("schedule/tools", {});
|
|
661
|
+
const tools = Array.isArray(result.tools)
|
|
662
|
+
? result.tools
|
|
663
|
+
: [];
|
|
664
|
+
return { tools };
|
|
665
|
+
}
|
|
666
|
+
async callScheduleTool(request) {
|
|
667
|
+
return this.request("schedule/call", {
|
|
668
|
+
name: request.name,
|
|
669
|
+
arguments: request.arguments ?? {},
|
|
670
|
+
});
|
|
671
|
+
}
|
|
358
672
|
async subscribeSessionEvents(sessionId) {
|
|
359
673
|
return this.openEventSubscription("session/stream_open", { session_id: sessionId }, "session/stream_close", MeerkatClient.parseAgentEventEnvelope);
|
|
360
674
|
}
|
|
@@ -381,83 +695,167 @@ export class MeerkatClient {
|
|
|
381
695
|
const status = typeof rawStatus === "string"
|
|
382
696
|
? rawStatus
|
|
383
697
|
: (typeof rawStatus === "object" && rawStatus !== null
|
|
384
|
-
?
|
|
385
|
-
:
|
|
698
|
+
? Object.keys(rawStatus)[0]
|
|
699
|
+
: undefined);
|
|
700
|
+
if (!status) {
|
|
701
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/status response: missing status");
|
|
702
|
+
}
|
|
386
703
|
return { mobId: String(result.mob_id ?? mobId), status };
|
|
387
704
|
}
|
|
388
705
|
async listMobMembers(mobId) {
|
|
389
706
|
const result = await this.request("mob/members", { mob_id: mobId });
|
|
390
707
|
const members = result.members ?? [];
|
|
391
|
-
return members.map((member) =>
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
: undefined,
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
?
|
|
414
|
-
: undefined
|
|
415
|
-
: undefined,
|
|
416
|
-
|
|
708
|
+
return members.map((member) => {
|
|
709
|
+
const agentIdentity = String(member.agent_identity ?? "");
|
|
710
|
+
const memberRef = typeof member.member_ref === "string" && member.member_ref.length > 0
|
|
711
|
+
? member.member_ref
|
|
712
|
+
: undefined;
|
|
713
|
+
if (!agentIdentity || !memberRef) {
|
|
714
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/members response: missing identity-native member fields");
|
|
715
|
+
}
|
|
716
|
+
return {
|
|
717
|
+
agentIdentity,
|
|
718
|
+
memberRef,
|
|
719
|
+
profile: String(member.profile_name ?? member.profile ?? member.role ?? ""),
|
|
720
|
+
peerId: member.peer_id != null ? String(member.peer_id) : undefined,
|
|
721
|
+
externalPeerSpecs: member.external_peer_specs && typeof member.external_peer_specs === "object"
|
|
722
|
+
? Object.fromEntries(Object.entries(member.external_peer_specs).map(([key, value]) => [key, (value ?? {})]))
|
|
723
|
+
: undefined,
|
|
724
|
+
runtimeMode: member.runtime_mode != null ? String(member.runtime_mode) : undefined,
|
|
725
|
+
state: member.state != null ? String(member.state) : undefined,
|
|
726
|
+
wiredTo: Array.isArray(member.wired_to)
|
|
727
|
+
? member.wired_to.map((peer) => String(peer))
|
|
728
|
+
: undefined,
|
|
729
|
+
labels: member.labels && typeof member.labels === "object"
|
|
730
|
+
? Object.fromEntries(Object.entries(member.labels).map(([key, value]) => [key, String(value)]))
|
|
731
|
+
: undefined,
|
|
732
|
+
status: member.status != null ? String(member.status) : undefined,
|
|
733
|
+
error: member.error != null ? String(member.error) : undefined,
|
|
734
|
+
isFinal: member.is_final != null ? Boolean(member.is_final) : undefined,
|
|
735
|
+
};
|
|
736
|
+
});
|
|
417
737
|
}
|
|
418
|
-
async sendMobMemberContent(mobId,
|
|
738
|
+
async sendMobMemberContent(mobId, agentIdentity, content, options) {
|
|
419
739
|
const result = await this.request("mob/member_send", {
|
|
420
740
|
mob_id: mobId,
|
|
421
|
-
|
|
741
|
+
agent_identity: agentIdentity,
|
|
422
742
|
content,
|
|
423
743
|
handling_mode: options?.handlingMode,
|
|
424
744
|
render_metadata: options?.renderMetadata,
|
|
425
745
|
});
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
746
|
+
const memberRef = typeof result.member_ref === "string" && result.member_ref.length > 0
|
|
747
|
+
? result.member_ref
|
|
748
|
+
: undefined;
|
|
749
|
+
if (!memberRef) {
|
|
750
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/member_send response: missing member_ref");
|
|
429
751
|
}
|
|
430
752
|
return {
|
|
431
|
-
|
|
432
|
-
? result.
|
|
433
|
-
:
|
|
434
|
-
|
|
753
|
+
agentIdentity: typeof result.agent_identity === "string" && result.agent_identity.length > 0
|
|
754
|
+
? result.agent_identity
|
|
755
|
+
: agentIdentity,
|
|
756
|
+
memberRef,
|
|
435
757
|
handlingMode: result.handling_mode === "steer" || result.handling_mode === "queue"
|
|
436
758
|
? result.handling_mode
|
|
437
759
|
: (options?.handlingMode ?? "queue"),
|
|
438
760
|
};
|
|
439
761
|
}
|
|
440
762
|
async spawnMobMember(mobId, options) {
|
|
441
|
-
|
|
763
|
+
const result = await this.request("mob/spawn", mobSpawnPayload(mobId, options));
|
|
764
|
+
const memberRef = typeof result.member_ref === "string" && result.member_ref.length > 0
|
|
765
|
+
? result.member_ref
|
|
766
|
+
: undefined;
|
|
767
|
+
if (!memberRef) {
|
|
768
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn response: missing member_ref");
|
|
769
|
+
}
|
|
770
|
+
return {
|
|
771
|
+
mobId: String(result.mob_id ?? mobId),
|
|
772
|
+
agentIdentity: typeof result.agent_identity === "string" && result.agent_identity.length > 0
|
|
773
|
+
? result.agent_identity
|
|
774
|
+
: options.agentIdentity,
|
|
775
|
+
memberRef,
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
async spawnMobMembers(mobId, specs) {
|
|
779
|
+
const result = await this.request("mob/spawn_many", {
|
|
442
780
|
mob_id: mobId,
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
781
|
+
specs: specs.map(mobSpawnManySpecPayload),
|
|
782
|
+
});
|
|
783
|
+
if (!Array.isArray(result.results)) {
|
|
784
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: results must be a list");
|
|
785
|
+
}
|
|
786
|
+
const entries = result.results;
|
|
787
|
+
return entries.map((entry) => {
|
|
788
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
789
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: malformed result entry");
|
|
790
|
+
}
|
|
791
|
+
const record = entry;
|
|
792
|
+
const entryKeys = Object.keys(record);
|
|
793
|
+
if (entryKeys.some((key) => key !== "status" && key !== "result") ||
|
|
794
|
+
"ok" in record ||
|
|
795
|
+
"error" in record ||
|
|
796
|
+
"agent_identity" in record ||
|
|
797
|
+
"member_ref" in record) {
|
|
798
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: legacy result carrier fields are not allowed");
|
|
799
|
+
}
|
|
800
|
+
const status = record.status;
|
|
801
|
+
const rawResult = record.result;
|
|
802
|
+
if (status !== "spawned" && status !== "failed") {
|
|
803
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: invalid result status");
|
|
804
|
+
}
|
|
805
|
+
if (!rawResult || typeof rawResult !== "object" || Array.isArray(rawResult)) {
|
|
806
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: missing result payload");
|
|
807
|
+
}
|
|
808
|
+
const resultRecord = rawResult;
|
|
809
|
+
if (status === "spawned") {
|
|
810
|
+
if (Object.keys(resultRecord).some((key) => key !== "agent_identity" && key !== "member_ref")) {
|
|
811
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: spawned result has unknown fields");
|
|
812
|
+
}
|
|
813
|
+
const agentIdentity = resultRecord.agent_identity;
|
|
814
|
+
const memberRef = resultRecord.member_ref;
|
|
815
|
+
if (typeof agentIdentity !== "string" || agentIdentity.length === 0) {
|
|
816
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: spawned result missing agent_identity");
|
|
817
|
+
}
|
|
818
|
+
if (typeof memberRef !== "string" || memberRef.length === 0) {
|
|
819
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: spawned result missing member_ref");
|
|
820
|
+
}
|
|
821
|
+
return {
|
|
822
|
+
status,
|
|
823
|
+
result: {
|
|
824
|
+
agent_identity: agentIdentity,
|
|
825
|
+
member_ref: memberRef,
|
|
826
|
+
},
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
if (Object.keys(resultRecord).some((key) => key !== "cause" && key !== "message")) {
|
|
830
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: failed result has unknown fields");
|
|
831
|
+
}
|
|
832
|
+
const cause = resultRecord.cause;
|
|
833
|
+
if (!isMobSpawnManyFailureCause(cause)) {
|
|
834
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: failed result has invalid cause");
|
|
835
|
+
}
|
|
836
|
+
const message = resultRecord.message;
|
|
837
|
+
if (typeof message !== "string" || message.length === 0) {
|
|
838
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_many response: failed result missing message");
|
|
839
|
+
}
|
|
840
|
+
return {
|
|
841
|
+
status,
|
|
842
|
+
result: {
|
|
843
|
+
cause,
|
|
844
|
+
message,
|
|
845
|
+
},
|
|
846
|
+
};
|
|
452
847
|
});
|
|
453
848
|
}
|
|
454
|
-
async retireMobMember(mobId,
|
|
455
|
-
await this.request("mob/retire", {
|
|
849
|
+
async retireMobMember(mobId, agentIdentity) {
|
|
850
|
+
await this.request("mob/retire", {
|
|
851
|
+
mob_id: mobId,
|
|
852
|
+
agent_identity: agentIdentity,
|
|
853
|
+
});
|
|
456
854
|
}
|
|
457
|
-
async respawnMobMember(mobId,
|
|
855
|
+
async respawnMobMember(mobId, agentIdentity, initialMessage) {
|
|
458
856
|
const result = await this.request("mob/respawn", {
|
|
459
857
|
mob_id: mobId,
|
|
460
|
-
|
|
858
|
+
agent_identity: agentIdentity,
|
|
461
859
|
initial_message: initialMessage,
|
|
462
860
|
});
|
|
463
861
|
const status = String(result.status ?? "completed");
|
|
@@ -468,21 +866,35 @@ export class MeerkatClient {
|
|
|
468
866
|
if (!receipt || typeof receipt !== "object") {
|
|
469
867
|
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/respawn response: missing receipt");
|
|
470
868
|
}
|
|
869
|
+
const memberRef = typeof receipt.member_ref === "string" && receipt.member_ref.length > 0
|
|
870
|
+
? receipt.member_ref
|
|
871
|
+
: undefined;
|
|
872
|
+
if (!memberRef) {
|
|
873
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/respawn response: receipt missing member_ref");
|
|
874
|
+
}
|
|
471
875
|
return {
|
|
472
876
|
status: status === "topology_restore_failed" ? "topology_restore_failed" : "completed",
|
|
473
877
|
receipt: {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
newSessionId: receipt.new_session_id != null ? String(receipt.new_session_id) : undefined,
|
|
878
|
+
agentIdentity: receipt.identity != null ? String(receipt.identity) : agentIdentity,
|
|
879
|
+
memberRef,
|
|
477
880
|
},
|
|
478
881
|
failedPeerIds: rawFailed.map((peerId) => String(peerId)),
|
|
479
882
|
};
|
|
480
883
|
}
|
|
481
|
-
async forceCancelMobMember(mobId,
|
|
482
|
-
await this.request("mob/force_cancel", {
|
|
884
|
+
async forceCancelMobMember(mobId, agentIdentity) {
|
|
885
|
+
await this.request("mob/force_cancel", {
|
|
886
|
+
mob_id: mobId,
|
|
887
|
+
agent_identity: agentIdentity,
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
async mobTurnStart(mobId, agentIdentity, prompt, options) {
|
|
891
|
+
return await this.request("mob/turn_start", mobTurnStartPayload(mobId, agentIdentity, prompt, options));
|
|
483
892
|
}
|
|
484
|
-
async mobMemberStatus(mobId,
|
|
485
|
-
const result = await this.request("mob/member_status", {
|
|
893
|
+
async mobMemberStatus(mobId, agentIdentity) {
|
|
894
|
+
const result = await this.request("mob/member_status", {
|
|
895
|
+
mob_id: mobId,
|
|
896
|
+
agent_identity: agentIdentity,
|
|
897
|
+
});
|
|
486
898
|
const rawConnectivity = result.peer_connectivity && typeof result.peer_connectivity === "object"
|
|
487
899
|
? result.peer_connectivity
|
|
488
900
|
: undefined;
|
|
@@ -492,7 +904,9 @@ export class MeerkatClient {
|
|
|
492
904
|
error: result.error != null ? String(result.error) : undefined,
|
|
493
905
|
tokensUsed: Number(result.tokens_used ?? 0),
|
|
494
906
|
isFinal: Boolean(result.is_final),
|
|
495
|
-
|
|
907
|
+
liveAttachmentStatus: typeof result.realtime_attachment_status === "string"
|
|
908
|
+
? result.realtime_attachment_status
|
|
909
|
+
: undefined,
|
|
496
910
|
peerConnectivity: rawConnectivity
|
|
497
911
|
? {
|
|
498
912
|
reachablePeerCount: Number(rawConnectivity.reachable_peer_count ?? 0),
|
|
@@ -508,8 +922,94 @@ export class MeerkatClient {
|
|
|
508
922
|
: [],
|
|
509
923
|
}
|
|
510
924
|
: undefined,
|
|
925
|
+
currentSessionId: typeof result.current_session_id === "string" && result.current_session_id.length > 0
|
|
926
|
+
? result.current_session_id
|
|
927
|
+
: undefined,
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Point-in-time aggregate of a mob's status plus its member list.
|
|
932
|
+
* Wraps the `mob/snapshot` RPC (DELETE_ME C2).
|
|
933
|
+
*/
|
|
934
|
+
async mobSnapshot(mobId) {
|
|
935
|
+
const result = await this.request("mob/snapshot", { mob_id: mobId });
|
|
936
|
+
return {
|
|
937
|
+
mobId: String(result.mob_id ?? mobId),
|
|
938
|
+
status: String(result.status ?? "unknown"),
|
|
939
|
+
members: Array.isArray(result.members) ? result.members : [],
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* Destroy a mob and surface the structured `MobDestroyReport`.
|
|
944
|
+
* Wraps the `mob/destroy` RPC (DELETE_ME C3). Unlike `mob/lifecycle`
|
|
945
|
+
* with `action: "destroy"`, this dedicated endpoint has a predictable
|
|
946
|
+
* response shape that does not require branching on an action string.
|
|
947
|
+
*/
|
|
948
|
+
async mobDestroy(mobId) {
|
|
949
|
+
const result = await this.request("mob/destroy", { mob_id: mobId });
|
|
950
|
+
const report = result.destroy_report && typeof result.destroy_report === "object"
|
|
951
|
+
? result.destroy_report
|
|
952
|
+
: {};
|
|
953
|
+
return {
|
|
954
|
+
mobId: String(result.mob_id ?? mobId),
|
|
955
|
+
ok: Boolean(result.ok ?? false),
|
|
956
|
+
destroyReport: report,
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Rotate the supervisor bridge for all members of a mob.
|
|
961
|
+
* Wraps the `mob/rotate_supervisor` RPC (DELETE_ME C10). Returns the
|
|
962
|
+
* full `SupervisorRotationReport` so operators can inspect per-member
|
|
963
|
+
* rotation outcomes instead of getting a bare `ok: true`.
|
|
964
|
+
*/
|
|
965
|
+
async mobRotateSupervisor(mobId) {
|
|
966
|
+
const result = await this.request("mob/rotate_supervisor", { mob_id: mobId });
|
|
967
|
+
return result;
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Submit a unit of work to a mob member through the work lane.
|
|
971
|
+
* Wraps the `mob/submit_work` RPC (DELETE_ME C4). Work lane was
|
|
972
|
+
* Rust-only prior to this; `origin` is `"external"` for
|
|
973
|
+
* user-originated turns and `"internal"` for mob-orchestration work.
|
|
974
|
+
* When `workRef` is omitted the server generates a fresh UUID.
|
|
975
|
+
*/
|
|
976
|
+
async mobSubmitWork(args) {
|
|
977
|
+
const params = {
|
|
978
|
+
member_ref: args.memberRef,
|
|
979
|
+
content: args.content,
|
|
980
|
+
origin: args.origin ?? "external",
|
|
981
|
+
};
|
|
982
|
+
if (args.workRef !== undefined) {
|
|
983
|
+
params.work_ref = args.workRef;
|
|
984
|
+
}
|
|
985
|
+
const result = await this.request("mob/submit_work", params);
|
|
986
|
+
return {
|
|
987
|
+
mobId: String(result.mob_id ?? ""),
|
|
988
|
+
workRef: String(result.work_ref ?? ""),
|
|
989
|
+
memberRef: String(result.member_ref ?? args.memberRef),
|
|
511
990
|
};
|
|
512
991
|
}
|
|
992
|
+
/**
|
|
993
|
+
* Cancel a previously submitted unit of work.
|
|
994
|
+
* Wraps the `mob/cancel_work` RPC (DELETE_ME C4).
|
|
995
|
+
*/
|
|
996
|
+
async mobCancelWork(mobId, workRef) {
|
|
997
|
+
const result = await this.request("mob/cancel_work", {
|
|
998
|
+
mob_id: mobId,
|
|
999
|
+
work_ref: workRef,
|
|
1000
|
+
});
|
|
1001
|
+
return { ok: Boolean(result.ok ?? false) };
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Cancel all in-flight work for a specific mob member.
|
|
1005
|
+
* Wraps the `mob/cancel_all_work` RPC (DELETE_ME C4).
|
|
1006
|
+
*/
|
|
1007
|
+
async mobCancelAllWork(args) {
|
|
1008
|
+
const result = await this.request("mob/cancel_all_work", {
|
|
1009
|
+
member_ref: args.memberRef,
|
|
1010
|
+
});
|
|
1011
|
+
return { ok: Boolean(result.ok ?? false) };
|
|
1012
|
+
}
|
|
513
1013
|
async waitMobKickoff(mobId, options) {
|
|
514
1014
|
const params = { mob_id: mobId };
|
|
515
1015
|
if (options?.memberIds !== undefined) {
|
|
@@ -522,17 +1022,70 @@ export class MeerkatClient {
|
|
|
522
1022
|
const members = Array.isArray(result.members) ? result.members : [];
|
|
523
1023
|
return members.map((entry) => {
|
|
524
1024
|
const member = entry && typeof entry === "object" ? entry : {};
|
|
1025
|
+
const agentIdentity = String(member.agent_identity ?? "");
|
|
1026
|
+
if (!agentIdentity) {
|
|
1027
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/wait_kickoff response: member missing agent_identity");
|
|
1028
|
+
}
|
|
1029
|
+
const status = MeerkatClient.requireStringField(member, "status", "Invalid mob/wait_kickoff response");
|
|
1030
|
+
const tokensUsed = MeerkatClient.requireNumberField(member, "tokens_used", "Invalid mob/wait_kickoff response");
|
|
1031
|
+
const isFinal = MeerkatClient.requireBooleanField(member, "is_final", "Invalid mob/wait_kickoff response");
|
|
525
1032
|
const rawConnectivity = member.peer_connectivity && typeof member.peer_connectivity === "object"
|
|
526
1033
|
? member.peer_connectivity
|
|
527
1034
|
: undefined;
|
|
528
1035
|
return {
|
|
529
|
-
|
|
530
|
-
status
|
|
1036
|
+
agentIdentity,
|
|
1037
|
+
status,
|
|
531
1038
|
outputPreview: member.output_preview != null ? String(member.output_preview) : undefined,
|
|
532
1039
|
error: member.error != null ? String(member.error) : undefined,
|
|
533
|
-
tokensUsed
|
|
534
|
-
isFinal
|
|
535
|
-
|
|
1040
|
+
tokensUsed,
|
|
1041
|
+
isFinal,
|
|
1042
|
+
peerConnectivity: rawConnectivity
|
|
1043
|
+
? {
|
|
1044
|
+
reachablePeerCount: Number(rawConnectivity.reachable_peer_count ?? 0),
|
|
1045
|
+
unknownPeerCount: Number(rawConnectivity.unknown_peer_count ?? 0),
|
|
1046
|
+
unreachablePeers: Array.isArray(rawConnectivity.unreachable_peers)
|
|
1047
|
+
? rawConnectivity.unreachable_peers.map((peer) => {
|
|
1048
|
+
const rawPeer = peer && typeof peer === "object" ? peer : {};
|
|
1049
|
+
return {
|
|
1050
|
+
peer: String(rawPeer.peer ?? ""),
|
|
1051
|
+
reason: rawPeer.reason != null ? String(rawPeer.reason) : undefined,
|
|
1052
|
+
};
|
|
1053
|
+
})
|
|
1054
|
+
: [],
|
|
1055
|
+
}
|
|
1056
|
+
: undefined,
|
|
1057
|
+
};
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
async waitMobReady(mobId, options) {
|
|
1061
|
+
const params = { mob_id: mobId };
|
|
1062
|
+
if (options?.memberIds !== undefined) {
|
|
1063
|
+
params.member_ids = options.memberIds;
|
|
1064
|
+
}
|
|
1065
|
+
if (options?.timeoutMs !== undefined) {
|
|
1066
|
+
params.timeout_ms = options.timeoutMs;
|
|
1067
|
+
}
|
|
1068
|
+
const result = await this.request("mob/wait_ready", params);
|
|
1069
|
+
const members = Array.isArray(result.members) ? result.members : [];
|
|
1070
|
+
return members.map((entry) => {
|
|
1071
|
+
const member = entry && typeof entry === "object" ? entry : {};
|
|
1072
|
+
const agentIdentity = String(member.agent_identity ?? "");
|
|
1073
|
+
if (!agentIdentity) {
|
|
1074
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/wait_ready response: member missing agent_identity");
|
|
1075
|
+
}
|
|
1076
|
+
const status = MeerkatClient.requireStringField(member, "status", "Invalid mob/wait_ready response");
|
|
1077
|
+
const tokensUsed = MeerkatClient.requireNumberField(member, "tokens_used", "Invalid mob/wait_ready response");
|
|
1078
|
+
const isFinal = MeerkatClient.requireBooleanField(member, "is_final", "Invalid mob/wait_ready response");
|
|
1079
|
+
const rawConnectivity = member.peer_connectivity && typeof member.peer_connectivity === "object"
|
|
1080
|
+
? member.peer_connectivity
|
|
1081
|
+
: undefined;
|
|
1082
|
+
return {
|
|
1083
|
+
agentIdentity,
|
|
1084
|
+
status,
|
|
1085
|
+
outputPreview: member.output_preview != null ? String(member.output_preview) : undefined,
|
|
1086
|
+
error: member.error != null ? String(member.error) : undefined,
|
|
1087
|
+
tokensUsed,
|
|
1088
|
+
isFinal,
|
|
536
1089
|
peerConnectivity: rawConnectivity
|
|
537
1090
|
? {
|
|
538
1091
|
reachablePeerCount: Number(rawConnectivity.reachable_peer_count ?? 0),
|
|
@@ -554,36 +1107,67 @@ export class MeerkatClient {
|
|
|
554
1107
|
async wait_mob_kickoff(mobId, options) {
|
|
555
1108
|
return this.waitMobKickoff(mobId, options);
|
|
556
1109
|
}
|
|
1110
|
+
async wait_mob_ready(mobId, options) {
|
|
1111
|
+
return this.waitMobReady(mobId, options);
|
|
1112
|
+
}
|
|
557
1113
|
async spawnMobHelper(mobId, prompt, options) {
|
|
1114
|
+
const roleName = options?.roleName ?? options?.profileName;
|
|
558
1115
|
const result = await this.request("mob/spawn_helper", {
|
|
559
1116
|
mob_id: mobId,
|
|
560
1117
|
prompt,
|
|
561
|
-
|
|
562
|
-
|
|
1118
|
+
agent_identity: options?.agentIdentity,
|
|
1119
|
+
role_name: roleName,
|
|
563
1120
|
runtime_mode: options?.runtimeMode,
|
|
564
1121
|
backend: options?.backend,
|
|
565
1122
|
});
|
|
1123
|
+
const resultIdentity = typeof result.agent_identity === "string" && result.agent_identity.length > 0
|
|
1124
|
+
? result.agent_identity
|
|
1125
|
+
: options?.agentIdentity;
|
|
1126
|
+
if (!resultIdentity) {
|
|
1127
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_helper response: missing agent identity");
|
|
1128
|
+
}
|
|
1129
|
+
const memberRef = typeof result.member_ref === "string" && result.member_ref.length > 0
|
|
1130
|
+
? result.member_ref
|
|
1131
|
+
: undefined;
|
|
1132
|
+
if (!memberRef) {
|
|
1133
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/spawn_helper response: missing member_ref");
|
|
1134
|
+
}
|
|
566
1135
|
return {
|
|
567
1136
|
output: result.output != null ? String(result.output) : undefined,
|
|
568
1137
|
tokensUsed: Number(result.tokens_used ?? 0),
|
|
569
|
-
|
|
1138
|
+
agentIdentity: resultIdentity,
|
|
1139
|
+
memberRef,
|
|
570
1140
|
};
|
|
571
1141
|
}
|
|
572
1142
|
async forkMobHelper(mobId, sourceMemberId, prompt, options) {
|
|
1143
|
+
const roleName = options?.roleName ?? options?.profileName;
|
|
573
1144
|
const result = await this.request("mob/fork_helper", {
|
|
574
1145
|
mob_id: mobId,
|
|
575
1146
|
source_member_id: sourceMemberId,
|
|
576
1147
|
prompt,
|
|
577
|
-
|
|
578
|
-
|
|
1148
|
+
agent_identity: options?.agentIdentity,
|
|
1149
|
+
role_name: roleName,
|
|
579
1150
|
fork_context: options?.forkContext,
|
|
580
1151
|
runtime_mode: options?.runtimeMode,
|
|
581
1152
|
backend: options?.backend,
|
|
582
1153
|
});
|
|
1154
|
+
const resultIdentity = typeof result.agent_identity === "string" && result.agent_identity.length > 0
|
|
1155
|
+
? result.agent_identity
|
|
1156
|
+
: options?.agentIdentity;
|
|
1157
|
+
if (!resultIdentity) {
|
|
1158
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/fork_helper response: missing agent identity");
|
|
1159
|
+
}
|
|
1160
|
+
const memberRef = typeof result.member_ref === "string" && result.member_ref.length > 0
|
|
1161
|
+
? result.member_ref
|
|
1162
|
+
: undefined;
|
|
1163
|
+
if (!memberRef) {
|
|
1164
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid mob/fork_helper response: missing member_ref");
|
|
1165
|
+
}
|
|
583
1166
|
return {
|
|
584
1167
|
output: result.output != null ? String(result.output) : undefined,
|
|
585
1168
|
tokensUsed: Number(result.tokens_used ?? 0),
|
|
586
|
-
|
|
1169
|
+
agentIdentity: resultIdentity,
|
|
1170
|
+
memberRef,
|
|
587
1171
|
};
|
|
588
1172
|
}
|
|
589
1173
|
async wireMobMembers(mobId, member, peer) {
|
|
@@ -601,15 +1185,68 @@ export class MeerkatClient {
|
|
|
601
1185
|
async mobLifecycle(mobId, action) {
|
|
602
1186
|
await this.request("mob/lifecycle", { mob_id: mobId, action });
|
|
603
1187
|
}
|
|
604
|
-
async appendMobSystemContext(mobId,
|
|
1188
|
+
async appendMobSystemContext(mobId, agentIdentity, text, options) {
|
|
605
1189
|
return this.request("mob/append_system_context", {
|
|
606
1190
|
mob_id: mobId,
|
|
607
|
-
|
|
1191
|
+
agent_identity: agentIdentity,
|
|
608
1192
|
text,
|
|
609
1193
|
source: options?.source,
|
|
610
1194
|
idempotency_key: options?.idempotencyKey,
|
|
611
1195
|
});
|
|
612
1196
|
}
|
|
1197
|
+
async readMobEvents(mobId, options) {
|
|
1198
|
+
const params = { mob_id: mobId };
|
|
1199
|
+
if (options?.afterCursor !== undefined) {
|
|
1200
|
+
params.after_cursor = options.afterCursor;
|
|
1201
|
+
}
|
|
1202
|
+
if (options?.limit !== undefined) {
|
|
1203
|
+
params.limit = options.limit;
|
|
1204
|
+
}
|
|
1205
|
+
const result = await this.request("mob/events", params);
|
|
1206
|
+
const events = Array.isArray(result.events)
|
|
1207
|
+
? result.events
|
|
1208
|
+
: [];
|
|
1209
|
+
return { events };
|
|
1210
|
+
}
|
|
1211
|
+
async mobIngressInteraction(params) {
|
|
1212
|
+
return this.request("mob/ingress_interaction", params);
|
|
1213
|
+
}
|
|
1214
|
+
async createMobProfile(name, profile) {
|
|
1215
|
+
const raw = await this.request("mob/profile/create", {
|
|
1216
|
+
name,
|
|
1217
|
+
profile,
|
|
1218
|
+
});
|
|
1219
|
+
return MeerkatClient.parseMobProfileLookup(raw);
|
|
1220
|
+
}
|
|
1221
|
+
async getMobProfile(name) {
|
|
1222
|
+
const raw = await this.request("mob/profile/get", { name });
|
|
1223
|
+
return MeerkatClient.parseMobProfileLookup(raw);
|
|
1224
|
+
}
|
|
1225
|
+
async listMobProfiles() {
|
|
1226
|
+
const raw = await this.request("mob/profile/list", {});
|
|
1227
|
+
const profiles = Array.isArray(raw.profiles)
|
|
1228
|
+
? raw.profiles
|
|
1229
|
+
: [];
|
|
1230
|
+
return profiles.map((profile) => MeerkatClient.parseMobProfileLookup(profile));
|
|
1231
|
+
}
|
|
1232
|
+
async updateMobProfile(name, profile, expectedRevision) {
|
|
1233
|
+
const raw = await this.request("mob/profile/update", {
|
|
1234
|
+
name,
|
|
1235
|
+
profile,
|
|
1236
|
+
expected_revision: expectedRevision,
|
|
1237
|
+
});
|
|
1238
|
+
return MeerkatClient.parseMobProfileLookup(raw);
|
|
1239
|
+
}
|
|
1240
|
+
async deleteMobProfile(name, expectedRevision) {
|
|
1241
|
+
const raw = await this.request("mob/profile/delete", {
|
|
1242
|
+
name,
|
|
1243
|
+
expected_revision: expectedRevision,
|
|
1244
|
+
});
|
|
1245
|
+
return {
|
|
1246
|
+
name: String(raw.name ?? name),
|
|
1247
|
+
deletedRevision: Number(raw.deleted_revision ?? expectedRevision),
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
613
1250
|
async listMobFlows(mobId) {
|
|
614
1251
|
const result = await this.request("mob/flows", { mob_id: mobId });
|
|
615
1252
|
return result.flows ?? [];
|
|
@@ -628,8 +1265,8 @@ export class MeerkatClient {
|
|
|
628
1265
|
async subscribeMobEvents(mobId) {
|
|
629
1266
|
return this.openEventSubscription("mob/stream_open", { mob_id: mobId }, "mob/stream_close", MeerkatClient.parseAttributedMobEvent);
|
|
630
1267
|
}
|
|
631
|
-
async subscribeMobMemberEvents(mobId,
|
|
632
|
-
return this.openEventSubscription("mob/stream_open", { mob_id: mobId,
|
|
1268
|
+
async subscribeMobMemberEvents(mobId, agentIdentity) {
|
|
1269
|
+
return this.openEventSubscription("mob/stream_open", { mob_id: mobId, agent_identity: agentIdentity }, "mob/stream_close", MeerkatClient.parseAgentEventEnvelope);
|
|
633
1270
|
}
|
|
634
1271
|
async openEventSubscription(openMethod, params, closeMethod, parse) {
|
|
635
1272
|
const result = this.process?.stdin
|
|
@@ -668,14 +1305,59 @@ export class MeerkatClient {
|
|
|
668
1305
|
});
|
|
669
1306
|
}
|
|
670
1307
|
static parseAgentEventEnvelope(raw) {
|
|
1308
|
+
const eventId = MeerkatClient.parseOptionalString(raw.event_id ?? raw.eventId);
|
|
1309
|
+
const source = MeerkatClient.parseEventSourceIdentity(raw.source);
|
|
1310
|
+
const sourceId = MeerkatClient.parseOptionalString(raw.source_id ?? raw.sourceId);
|
|
1311
|
+
const seq = MeerkatClient.parseOptionalNumber(raw.seq);
|
|
1312
|
+
const timestampMs = MeerkatClient.parseOptionalNumber(raw.timestamp_ms ?? raw.timestampMs);
|
|
1313
|
+
const payloadRaw = raw.payload;
|
|
1314
|
+
const payload = payloadRaw && typeof payloadRaw === "object"
|
|
1315
|
+
? parseCoreEvent(payloadRaw)
|
|
1316
|
+
: undefined;
|
|
671
1317
|
return {
|
|
672
|
-
eventId
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
1318
|
+
...(eventId != null ? { eventId } : {}),
|
|
1319
|
+
...(source != null ? { source } : {}),
|
|
1320
|
+
...(sourceId != null ? { sourceId } : {}),
|
|
1321
|
+
...(seq != null ? { seq } : {}),
|
|
1322
|
+
...(timestampMs != null ? { timestampMs } : {}),
|
|
1323
|
+
...(payload ? { payload } : {}),
|
|
677
1324
|
};
|
|
678
1325
|
}
|
|
1326
|
+
static parseEventSourceIdentity(raw) {
|
|
1327
|
+
if (!raw || typeof raw !== "object") {
|
|
1328
|
+
return undefined;
|
|
1329
|
+
}
|
|
1330
|
+
const record = raw;
|
|
1331
|
+
const type = MeerkatClient.parseOptionalString(record.type);
|
|
1332
|
+
switch (type) {
|
|
1333
|
+
case "session": {
|
|
1334
|
+
const sessionId = MeerkatClient.parseOptionalString(record.session_id ?? record.sessionId);
|
|
1335
|
+
return sessionId != null ? { type: "session", sessionId } : undefined;
|
|
1336
|
+
}
|
|
1337
|
+
case "runtime": {
|
|
1338
|
+
const runtimeId = MeerkatClient.parseOptionalString(record.runtime_id ?? record.runtimeId);
|
|
1339
|
+
return runtimeId != null ? { type: "runtime", runtimeId } : undefined;
|
|
1340
|
+
}
|
|
1341
|
+
case "interaction": {
|
|
1342
|
+
const interactionId = MeerkatClient.parseOptionalString(record.interaction_id ?? record.interactionId);
|
|
1343
|
+
return interactionId != null ? { type: "interaction", interactionId } : undefined;
|
|
1344
|
+
}
|
|
1345
|
+
case "callback":
|
|
1346
|
+
return { type: "callback" };
|
|
1347
|
+
case "external": {
|
|
1348
|
+
const sourceId = MeerkatClient.parseOptionalString(record.source_id ?? record.sourceId);
|
|
1349
|
+
return sourceId != null ? { type: "external", sourceId } : undefined;
|
|
1350
|
+
}
|
|
1351
|
+
default:
|
|
1352
|
+
return undefined;
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
static parseOptionalString(raw) {
|
|
1356
|
+
return typeof raw === "string" ? raw : undefined;
|
|
1357
|
+
}
|
|
1358
|
+
static parseOptionalNumber(raw) {
|
|
1359
|
+
return typeof raw === "number" && Number.isFinite(raw) ? raw : undefined;
|
|
1360
|
+
}
|
|
679
1361
|
static parseAttributedMobEvent(raw) {
|
|
680
1362
|
return {
|
|
681
1363
|
source: String(raw.source ?? ""),
|
|
@@ -691,15 +1373,15 @@ export class MeerkatClient {
|
|
|
691
1373
|
if (wireRefs) {
|
|
692
1374
|
params.skill_refs = wireRefs;
|
|
693
1375
|
}
|
|
694
|
-
if (options?.skillReferences) {
|
|
695
|
-
params.skill_references = options.skillReferences;
|
|
696
|
-
}
|
|
697
1376
|
if (options?.flowToolOverlay) {
|
|
698
1377
|
params.flow_tool_overlay = {
|
|
699
1378
|
allowed_tools: options.flowToolOverlay.allowedTools,
|
|
700
1379
|
blocked_tools: options.flowToolOverlay.blockedTools,
|
|
701
1380
|
};
|
|
702
1381
|
}
|
|
1382
|
+
if (options?.additionalInstructions != null) {
|
|
1383
|
+
params.additional_instructions = options.additionalInstructions;
|
|
1384
|
+
}
|
|
703
1385
|
if (options?.keepAlive != null)
|
|
704
1386
|
params.keep_alive = options.keepAlive;
|
|
705
1387
|
if (options?.model)
|
|
@@ -735,15 +1417,32 @@ export class MeerkatClient {
|
|
|
735
1417
|
if (wireRefs) {
|
|
736
1418
|
params.skill_refs = wireRefs;
|
|
737
1419
|
}
|
|
738
|
-
if (options?.skillReferences) {
|
|
739
|
-
params.skill_references = options.skillReferences;
|
|
740
|
-
}
|
|
741
1420
|
if (options?.flowToolOverlay) {
|
|
742
1421
|
params.flow_tool_overlay = {
|
|
743
1422
|
allowed_tools: options.flowToolOverlay.allowedTools,
|
|
744
1423
|
blocked_tools: options.flowToolOverlay.blockedTools,
|
|
745
1424
|
};
|
|
746
1425
|
}
|
|
1426
|
+
if (options?.additionalInstructions != null) {
|
|
1427
|
+
params.additional_instructions = options.additionalInstructions;
|
|
1428
|
+
}
|
|
1429
|
+
if (options?.keepAlive != null)
|
|
1430
|
+
params.keep_alive = options.keepAlive;
|
|
1431
|
+
if (options?.model)
|
|
1432
|
+
params.model = options.model;
|
|
1433
|
+
if (options?.provider)
|
|
1434
|
+
params.provider = options.provider;
|
|
1435
|
+
if (options?.maxTokens)
|
|
1436
|
+
params.max_tokens = options.maxTokens;
|
|
1437
|
+
if (options?.systemPrompt)
|
|
1438
|
+
params.system_prompt = options.systemPrompt;
|
|
1439
|
+
if (options?.outputSchema)
|
|
1440
|
+
params.output_schema = options.outputSchema;
|
|
1441
|
+
if (options?.structuredOutputRetries != null) {
|
|
1442
|
+
params.structured_output_retries = options.structuredOutputRetries;
|
|
1443
|
+
}
|
|
1444
|
+
if (options?.providerParams)
|
|
1445
|
+
params.provider_params = options.providerParams;
|
|
747
1446
|
const rpcRequest = { jsonrpc: "2.0", id: requestId, method: "turn/start", params };
|
|
748
1447
|
this.process.stdin.write(JSON.stringify(rpcRequest) + "\n");
|
|
749
1448
|
return new EventStream({
|
|
@@ -762,6 +1461,51 @@ export class MeerkatClient {
|
|
|
762
1461
|
async _archive(sessionId) {
|
|
763
1462
|
await this.request("session/archive", { session_id: sessionId });
|
|
764
1463
|
}
|
|
1464
|
+
static retiredRuntimeSessionControlError() {
|
|
1465
|
+
return new MeerkatError("METHOD_NOT_FOUND", "Retired runtime session control methods are no longer supported by the public RPC surface.");
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* @internal
|
|
1469
|
+
* @deprecated Retired runtime/session control RPC method; always fails before transport.
|
|
1470
|
+
*/
|
|
1471
|
+
async _runtimeStatus(_params) {
|
|
1472
|
+
throw MeerkatClient.retiredRuntimeSessionControlError();
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* @internal
|
|
1476
|
+
* @deprecated Retired runtime/session control RPC method; always fails before transport.
|
|
1477
|
+
*/
|
|
1478
|
+
async _runtimeSubmit(_params) {
|
|
1479
|
+
throw MeerkatClient.retiredRuntimeSessionControlError();
|
|
1480
|
+
}
|
|
1481
|
+
/**
|
|
1482
|
+
* @internal
|
|
1483
|
+
* @deprecated Retired runtime/session control RPC method; always fails before transport.
|
|
1484
|
+
*/
|
|
1485
|
+
async _runtimeSubmission(_params) {
|
|
1486
|
+
throw MeerkatClient.retiredRuntimeSessionControlError();
|
|
1487
|
+
}
|
|
1488
|
+
/**
|
|
1489
|
+
* @internal
|
|
1490
|
+
* @deprecated Retired runtime/session control RPC method; always fails before transport.
|
|
1491
|
+
*/
|
|
1492
|
+
async _runtimeSubmissions(_params) {
|
|
1493
|
+
throw MeerkatClient.retiredRuntimeSessionControlError();
|
|
1494
|
+
}
|
|
1495
|
+
/**
|
|
1496
|
+
* @internal
|
|
1497
|
+
* @deprecated Retired runtime/session control RPC method; always fails before transport.
|
|
1498
|
+
*/
|
|
1499
|
+
async _runtimeRetire(_params) {
|
|
1500
|
+
throw MeerkatClient.retiredRuntimeSessionControlError();
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* @internal
|
|
1504
|
+
* @deprecated Retired runtime/session control RPC method; always fails before transport.
|
|
1505
|
+
*/
|
|
1506
|
+
async _runtimeReset(_params) {
|
|
1507
|
+
throw MeerkatClient.retiredRuntimeSessionControlError();
|
|
1508
|
+
}
|
|
765
1509
|
/** @internal */
|
|
766
1510
|
async _send(sessionId, command) {
|
|
767
1511
|
return this.send(sessionId, command);
|
|
@@ -770,57 +1514,138 @@ export class MeerkatClient {
|
|
|
770
1514
|
async _peers(sessionId) {
|
|
771
1515
|
return this.peers(sessionId);
|
|
772
1516
|
}
|
|
1517
|
+
/**
|
|
1518
|
+
* Send a typed comms command. Invalid discriminators (`source`, `stream`,
|
|
1519
|
+
* `handling_mode`, `status`) are rejected at the server's typed-serde
|
|
1520
|
+
* boundary.
|
|
1521
|
+
*/
|
|
773
1522
|
async send(sessionId, command) {
|
|
774
|
-
|
|
1523
|
+
const result = await this.request("comms/send", { session_id: sessionId, ...command });
|
|
1524
|
+
return MeerkatClient.parseCommsSendReceipt(result);
|
|
775
1525
|
}
|
|
776
1526
|
async peers(sessionId) {
|
|
777
1527
|
return this.request("comms/peers", { session_id: sessionId });
|
|
778
1528
|
}
|
|
779
|
-
async
|
|
780
|
-
const result = await this.request("
|
|
781
|
-
|
|
782
|
-
|
|
1529
|
+
async runtimeRealtimeAttachmentStatus(sessionId) {
|
|
1530
|
+
const result = await this.request("session/realtime_attachment_status", {
|
|
1531
|
+
session_id: sessionId,
|
|
1532
|
+
});
|
|
1533
|
+
if (typeof result.status !== "string" || result.status.length === 0) {
|
|
1534
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid session/realtime_attachment_status response: missing status");
|
|
783
1535
|
}
|
|
784
1536
|
return result;
|
|
785
1537
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
1538
|
+
/** Idempotent spawn: spawns or returns the existing member entry. */
|
|
1539
|
+
async mobEnsureMember(mobId, spec) {
|
|
1540
|
+
return await this.request("mob/ensure_member", {
|
|
1541
|
+
mob_id: mobId,
|
|
1542
|
+
spec,
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
/** Declarative reconcile: converge roster to the desired spec list. */
|
|
1546
|
+
async mobReconcile(mobId, desired, options) {
|
|
1547
|
+
const params = { mob_id: mobId, desired };
|
|
1548
|
+
if (options !== undefined)
|
|
1549
|
+
params.options = options;
|
|
1550
|
+
return await this.request("mob/reconcile", params);
|
|
1551
|
+
}
|
|
1552
|
+
/** Label-filtered member listing. */
|
|
1553
|
+
async mobListMembersMatching(mobId, filter) {
|
|
1554
|
+
return await this.request("mob/list_members_matching", {
|
|
1555
|
+
mob_id: mobId,
|
|
1556
|
+
filter,
|
|
1557
|
+
});
|
|
792
1558
|
}
|
|
793
|
-
async
|
|
794
|
-
const result = await this.request("
|
|
795
|
-
if (typeof result.
|
|
796
|
-
throw new MeerkatError("INVALID_RESPONSE", "Invalid
|
|
1559
|
+
async realtimeOpenInfo(request) {
|
|
1560
|
+
const result = await this.request("realtime/open_info", request);
|
|
1561
|
+
if (typeof result.ws_url !== "string" || result.ws_url.length === 0) {
|
|
1562
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid realtime/open_info response: missing ws_url");
|
|
797
1563
|
}
|
|
798
1564
|
return result;
|
|
799
1565
|
}
|
|
800
|
-
async
|
|
801
|
-
const result = await this.request("
|
|
802
|
-
if (typeof result.
|
|
803
|
-
throw new MeerkatError("INVALID_RESPONSE", "Invalid
|
|
1566
|
+
async realtimeStatus(params) {
|
|
1567
|
+
const result = await this.request("realtime/status", params);
|
|
1568
|
+
if (typeof result.status !== "object" || result.status === null) {
|
|
1569
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid realtime/status response: missing status");
|
|
804
1570
|
}
|
|
805
1571
|
return result;
|
|
806
1572
|
}
|
|
807
|
-
async
|
|
808
|
-
const result = await this.request("
|
|
809
|
-
if (result === null) {
|
|
810
|
-
|
|
811
|
-
}
|
|
812
|
-
if (typeof result !== "object" || result === null) {
|
|
813
|
-
throw new MeerkatError("INVALID_RESPONSE", "Invalid input/state response: expected object or null");
|
|
1573
|
+
async realtimeCapabilities(params) {
|
|
1574
|
+
const result = await this.request("realtime/capabilities", params);
|
|
1575
|
+
if (typeof result.capabilities !== "object" || result.capabilities === null) {
|
|
1576
|
+
throw new MeerkatError("INVALID_RESPONSE", "Invalid realtime/capabilities response: missing capabilities");
|
|
814
1577
|
}
|
|
815
1578
|
return result;
|
|
816
1579
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
1580
|
+
// -- Auth + realm (Phase 4d) --------------------------------------------
|
|
1581
|
+
//
|
|
1582
|
+
// These wrappers cover the RPC catalog's auth/* and realm/* methods.
|
|
1583
|
+
// Write-side methods (auth/profile/create, delete, login/start,
|
|
1584
|
+
// login/complete, login/device_start, logout) are currently server-stubbed
|
|
1585
|
+
// with typed INVALID_REQUEST pointing to the CLI; the wrappers surface
|
|
1586
|
+
// whatever the server returns so they stay honest about the state.
|
|
1587
|
+
async realmList() {
|
|
1588
|
+
return this.request("realm/list", {});
|
|
1589
|
+
}
|
|
1590
|
+
async realmGet(realmId) {
|
|
1591
|
+
return this.request("realm/get", { realm_id: realmId });
|
|
1592
|
+
}
|
|
1593
|
+
async authProfileList(realmId) {
|
|
1594
|
+
return this.request("auth/profile/list", { realm_id: realmId });
|
|
1595
|
+
}
|
|
1596
|
+
async authProfileGet(realmId, bindingId, profileId) {
|
|
1597
|
+
const params = {
|
|
1598
|
+
realm_id: realmId,
|
|
1599
|
+
binding_id: bindingId,
|
|
1600
|
+
};
|
|
1601
|
+
if (profileId)
|
|
1602
|
+
params.profile_id = profileId;
|
|
1603
|
+
return this.request("auth/profile/get", params);
|
|
1604
|
+
}
|
|
1605
|
+
async authProfileCreate(params) {
|
|
1606
|
+
return this.request("auth/profile/create", params);
|
|
1607
|
+
}
|
|
1608
|
+
async authProfileDelete(realmId, bindingId, profileId) {
|
|
1609
|
+
const params = {
|
|
1610
|
+
realm_id: realmId,
|
|
1611
|
+
binding_id: bindingId,
|
|
1612
|
+
};
|
|
1613
|
+
if (profileId)
|
|
1614
|
+
params.profile_id = profileId;
|
|
1615
|
+
return this.request("auth/profile/delete", params);
|
|
1616
|
+
}
|
|
1617
|
+
async authLoginStart(params) {
|
|
1618
|
+
return this.request("auth/login/start", params);
|
|
1619
|
+
}
|
|
1620
|
+
async authLoginComplete(params) {
|
|
1621
|
+
return this.request("auth/login/complete", params);
|
|
1622
|
+
}
|
|
1623
|
+
async authLoginDeviceStart(params) {
|
|
1624
|
+
return this.request("auth/login/device_start", params);
|
|
1625
|
+
}
|
|
1626
|
+
async authLoginDeviceComplete(params) {
|
|
1627
|
+
return this.request("auth/login/device_complete", params);
|
|
1628
|
+
}
|
|
1629
|
+
async authLoginProvisionApiKey(params) {
|
|
1630
|
+
return this.request("auth/login/provision_api_key", params);
|
|
1631
|
+
}
|
|
1632
|
+
async authStatusGet(realmId, bindingId, profileId) {
|
|
1633
|
+
const params = {
|
|
1634
|
+
realm_id: realmId,
|
|
1635
|
+
binding_id: bindingId,
|
|
1636
|
+
};
|
|
1637
|
+
if (profileId !== undefined)
|
|
1638
|
+
params.profile_id = profileId;
|
|
1639
|
+
return this.request("auth/status/get", params);
|
|
1640
|
+
}
|
|
1641
|
+
async authLogout(realmId, bindingId, profileId) {
|
|
1642
|
+
const params = {
|
|
1643
|
+
realm_id: realmId,
|
|
1644
|
+
binding_id: bindingId,
|
|
1645
|
+
};
|
|
1646
|
+
if (profileId !== undefined)
|
|
1647
|
+
params.profile_id = profileId;
|
|
1648
|
+
return this.request("auth/logout", params);
|
|
824
1649
|
}
|
|
825
1650
|
// -- Transport ----------------------------------------------------------
|
|
826
1651
|
handleLine(line) {
|
|
@@ -961,6 +1786,33 @@ export class MeerkatClient {
|
|
|
961
1786
|
}
|
|
962
1787
|
return String(raw);
|
|
963
1788
|
}
|
|
1789
|
+
static requireRecord(raw, field, context) {
|
|
1790
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
1791
|
+
throw new MeerkatError("INVALID_RESPONSE", `${context}: missing ${field}`);
|
|
1792
|
+
}
|
|
1793
|
+
return raw;
|
|
1794
|
+
}
|
|
1795
|
+
static requireStringField(raw, field, context) {
|
|
1796
|
+
const value = raw[field];
|
|
1797
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
1798
|
+
throw new MeerkatError("INVALID_RESPONSE", `${context}: missing ${field}`);
|
|
1799
|
+
}
|
|
1800
|
+
return value;
|
|
1801
|
+
}
|
|
1802
|
+
static requireNumberField(raw, field, context, displayField = field) {
|
|
1803
|
+
const value = raw[field];
|
|
1804
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1805
|
+
throw new MeerkatError("INVALID_RESPONSE", `${context}: ${displayField} must be number`);
|
|
1806
|
+
}
|
|
1807
|
+
return value;
|
|
1808
|
+
}
|
|
1809
|
+
static requireBooleanField(raw, field, context) {
|
|
1810
|
+
const value = raw[field];
|
|
1811
|
+
if (typeof value !== "boolean") {
|
|
1812
|
+
throw new MeerkatError("INVALID_RESPONSE", `${context}: ${field} must be boolean`);
|
|
1813
|
+
}
|
|
1814
|
+
return value;
|
|
1815
|
+
}
|
|
964
1816
|
static parseSkillDiagnostics(raw) {
|
|
965
1817
|
if (!raw || typeof raw !== "object")
|
|
966
1818
|
return undefined;
|
|
@@ -1006,15 +1858,16 @@ export class MeerkatClient {
|
|
|
1006
1858
|
}
|
|
1007
1859
|
}
|
|
1008
1860
|
static parseRunResult(data) {
|
|
1009
|
-
const
|
|
1861
|
+
const context = "Invalid run result";
|
|
1862
|
+
const usageRaw = MeerkatClient.requireRecord(data.usage, "usage", context);
|
|
1010
1863
|
const usage = {
|
|
1011
|
-
inputTokens:
|
|
1012
|
-
outputTokens:
|
|
1864
|
+
inputTokens: MeerkatClient.requireNumberField(usageRaw, "input_tokens", context, "usage.input_tokens"),
|
|
1865
|
+
outputTokens: MeerkatClient.requireNumberField(usageRaw, "output_tokens", context, "usage.output_tokens"),
|
|
1013
1866
|
cacheCreationTokens: usageRaw?.cache_creation_tokens != null
|
|
1014
|
-
?
|
|
1867
|
+
? MeerkatClient.requireNumberField(usageRaw, "cache_creation_tokens", context, "usage.cache_creation_tokens")
|
|
1015
1868
|
: undefined,
|
|
1016
1869
|
cacheReadTokens: usageRaw?.cache_read_tokens != null
|
|
1017
|
-
?
|
|
1870
|
+
? MeerkatClient.requireNumberField(usageRaw, "cache_read_tokens", context, "usage.cache_read_tokens")
|
|
1018
1871
|
: undefined,
|
|
1019
1872
|
};
|
|
1020
1873
|
const rawWarnings = data.schema_warnings;
|
|
@@ -1023,18 +1876,258 @@ export class MeerkatClient {
|
|
|
1023
1876
|
path: String(w.path ?? ""),
|
|
1024
1877
|
message: String(w.message ?? ""),
|
|
1025
1878
|
}));
|
|
1879
|
+
const rawExtractionError = data.extraction_error;
|
|
1880
|
+
const extractionError = rawExtractionError && typeof rawExtractionError === "object"
|
|
1881
|
+
? {
|
|
1882
|
+
lastOutput: String(rawExtractionError.last_output ?? ""),
|
|
1883
|
+
attempts: MeerkatClient.requireNumberField(rawExtractionError, "attempts", context, "extraction_error.attempts"),
|
|
1884
|
+
reason: String(rawExtractionError.reason ?? ""),
|
|
1885
|
+
}
|
|
1886
|
+
: undefined;
|
|
1026
1887
|
return {
|
|
1027
1888
|
sessionId: String(data.session_id ?? ""),
|
|
1028
1889
|
sessionRef: data.session_ref != null ? String(data.session_ref) : undefined,
|
|
1029
1890
|
text: String(data.text ?? ""),
|
|
1030
|
-
turns:
|
|
1031
|
-
toolCalls:
|
|
1891
|
+
turns: MeerkatClient.requireNumberField(data, "turns", context),
|
|
1892
|
+
toolCalls: MeerkatClient.requireNumberField(data, "tool_calls", context),
|
|
1032
1893
|
usage,
|
|
1894
|
+
terminalCauseKind: typeof data.terminal_cause_kind === "string"
|
|
1895
|
+
? data.terminal_cause_kind
|
|
1896
|
+
: undefined,
|
|
1033
1897
|
structuredOutput: data.structured_output,
|
|
1898
|
+
extractionError,
|
|
1034
1899
|
schemaWarnings,
|
|
1035
1900
|
skillDiagnostics: MeerkatClient.parseSkillDiagnostics(data.skill_diagnostics),
|
|
1036
1901
|
};
|
|
1037
1902
|
}
|
|
1903
|
+
static parseSessionInfo(data) {
|
|
1904
|
+
const labelsRaw = data.labels && typeof data.labels === "object"
|
|
1905
|
+
? data.labels
|
|
1906
|
+
: {};
|
|
1907
|
+
const labels = Object.fromEntries(Object.entries(labelsRaw).map(([key, value]) => [key, String(value)]));
|
|
1908
|
+
return {
|
|
1909
|
+
sessionId: String(data.session_id ?? ""),
|
|
1910
|
+
sessionRef: data.session_ref != null ? String(data.session_ref) : undefined,
|
|
1911
|
+
createdAt: Number(data.created_at ?? 0),
|
|
1912
|
+
updatedAt: Number(data.updated_at ?? 0),
|
|
1913
|
+
messageCount: Number(data.message_count ?? 0),
|
|
1914
|
+
isActive: Boolean(data.is_active),
|
|
1915
|
+
totalTokens: data.total_tokens != null ? Number(data.total_tokens) : undefined,
|
|
1916
|
+
model: data.model != null ? String(data.model) : undefined,
|
|
1917
|
+
provider: data.provider != null ? String(data.provider) : undefined,
|
|
1918
|
+
lastAssistantText: data.last_assistant_text != null ? String(data.last_assistant_text) : undefined,
|
|
1919
|
+
labels,
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1922
|
+
static parseConfigEnvelope(data) {
|
|
1923
|
+
const rawConfig = data.config && typeof data.config === "object"
|
|
1924
|
+
? data.config
|
|
1925
|
+
: {};
|
|
1926
|
+
const rawResolvedPaths = data.resolved_paths && typeof data.resolved_paths === "object"
|
|
1927
|
+
? data.resolved_paths
|
|
1928
|
+
: undefined;
|
|
1929
|
+
const resolvedPaths = rawResolvedPaths
|
|
1930
|
+
? Object.fromEntries(Object.entries(rawResolvedPaths).map(([key, value]) => [key, String(value)]))
|
|
1931
|
+
: undefined;
|
|
1932
|
+
return {
|
|
1933
|
+
config: rawConfig,
|
|
1934
|
+
generation: Number(data.generation ?? 0),
|
|
1935
|
+
realmId: data.realm_id != null ? String(data.realm_id) : undefined,
|
|
1936
|
+
instanceId: data.instance_id != null ? String(data.instance_id) : undefined,
|
|
1937
|
+
backend: data.backend != null ? String(data.backend) : undefined,
|
|
1938
|
+
resolvedPaths,
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
static parseCommsSendReceipt(data) {
|
|
1942
|
+
return {
|
|
1943
|
+
...data,
|
|
1944
|
+
requestId: data.request_id != null ? String(data.request_id) : undefined,
|
|
1945
|
+
interactionId: data.interaction_id != null ? String(data.interaction_id) : undefined,
|
|
1946
|
+
inputId: data.input_id != null ? String(data.input_id) : undefined,
|
|
1947
|
+
};
|
|
1948
|
+
}
|
|
1949
|
+
static parseModelsCatalog(data) {
|
|
1950
|
+
const providersRaw = Array.isArray(data.providers)
|
|
1951
|
+
? data.providers
|
|
1952
|
+
: [];
|
|
1953
|
+
let contractVersion = { major: 0, minor: 0, patch: 0 };
|
|
1954
|
+
if (data.contract_version && typeof data.contract_version === "object") {
|
|
1955
|
+
const contractVersionRaw = data.contract_version;
|
|
1956
|
+
contractVersion = {
|
|
1957
|
+
major: Number(contractVersionRaw.major ?? 0),
|
|
1958
|
+
minor: Number(contractVersionRaw.minor ?? 0),
|
|
1959
|
+
patch: Number(contractVersionRaw.patch ?? 0),
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1962
|
+
else if (typeof data.contract_version === "string") {
|
|
1963
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(data.contract_version);
|
|
1964
|
+
if (match) {
|
|
1965
|
+
contractVersion = {
|
|
1966
|
+
major: Number(match[1]),
|
|
1967
|
+
minor: Number(match[2]),
|
|
1968
|
+
patch: Number(match[3]),
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
return {
|
|
1973
|
+
contractVersion,
|
|
1974
|
+
providers: providersRaw.map((provider) => ({
|
|
1975
|
+
provider: String(provider.provider ?? ""),
|
|
1976
|
+
defaultModelId: String(provider.default_model_id ?? ""),
|
|
1977
|
+
models: Array.isArray(provider.models)
|
|
1978
|
+
? provider.models.map((model) => ({
|
|
1979
|
+
id: String(model.id ?? ""),
|
|
1980
|
+
displayName: String(model.display_name ?? ""),
|
|
1981
|
+
tier: String(model.tier ?? "supported") === "recommended"
|
|
1982
|
+
? "recommended"
|
|
1983
|
+
: "supported",
|
|
1984
|
+
contextWindow: model.context_window != null ? Number(model.context_window) : undefined,
|
|
1985
|
+
maxOutputTokens: model.max_output_tokens != null ? Number(model.max_output_tokens) : undefined,
|
|
1986
|
+
serverId: model.server_id != null ? String(model.server_id) : undefined,
|
|
1987
|
+
profile: model.profile && typeof model.profile === "object"
|
|
1988
|
+
? {
|
|
1989
|
+
modelFamily: String(model.profile.model_family ?? ""),
|
|
1990
|
+
supportsTemperature: Boolean(model.profile.supports_temperature),
|
|
1991
|
+
supportsThinking: Boolean(model.profile.supports_thinking),
|
|
1992
|
+
supportsReasoning: Boolean(model.profile.supports_reasoning),
|
|
1993
|
+
inlineVideo: Boolean(model.profile.inline_video),
|
|
1994
|
+
paramsSchema: model.profile.params_schema,
|
|
1995
|
+
}
|
|
1996
|
+
: undefined,
|
|
1997
|
+
}))
|
|
1998
|
+
: [],
|
|
1999
|
+
})),
|
|
2000
|
+
};
|
|
2001
|
+
}
|
|
2002
|
+
static parseSchedule(data) {
|
|
2003
|
+
const labelsRaw = data.labels && typeof data.labels === "object"
|
|
2004
|
+
? data.labels
|
|
2005
|
+
: {};
|
|
2006
|
+
return {
|
|
2007
|
+
scheduleId: String(data.schedule_id ?? ""),
|
|
2008
|
+
phase: String(data.phase ?? ""),
|
|
2009
|
+
revision: typeof data.revision === "object" && data.revision !== null
|
|
2010
|
+
? Number(data.revision["0"] ?? 0)
|
|
2011
|
+
: Number(data.revision ?? 0),
|
|
2012
|
+
name: data.name != null ? String(data.name) : undefined,
|
|
2013
|
+
description: data.description != null ? String(data.description) : undefined,
|
|
2014
|
+
trigger: data.trigger && typeof data.trigger === "object"
|
|
2015
|
+
? data.trigger
|
|
2016
|
+
: {},
|
|
2017
|
+
target: data.target && typeof data.target === "object"
|
|
2018
|
+
? data.target
|
|
2019
|
+
: {},
|
|
2020
|
+
misfirePolicy: data.misfire_policy != null
|
|
2021
|
+
? data.misfire_policy
|
|
2022
|
+
: undefined,
|
|
2023
|
+
overlapPolicy: data.overlap_policy != null ? String(data.overlap_policy) : undefined,
|
|
2024
|
+
missingTargetPolicy: data.missing_target_policy != null ? String(data.missing_target_policy) : undefined,
|
|
2025
|
+
planningHorizonDays: data.planning_horizon_days != null ? Number(data.planning_horizon_days) : undefined,
|
|
2026
|
+
planningHorizonOccurrences: data.planning_horizon_occurrences != null
|
|
2027
|
+
? Number(data.planning_horizon_occurrences)
|
|
2028
|
+
: undefined,
|
|
2029
|
+
nextOccurrenceOrdinal: typeof data.next_occurrence_ordinal === "object"
|
|
2030
|
+
? Number(data.next_occurrence_ordinal["0"] ?? 0)
|
|
2031
|
+
: data.next_occurrence_ordinal != null
|
|
2032
|
+
? Number(data.next_occurrence_ordinal)
|
|
2033
|
+
: undefined,
|
|
2034
|
+
planningCursorUtc: data.planning_cursor_utc != null ? String(data.planning_cursor_utc) : undefined,
|
|
2035
|
+
createdAtUtc: data.created_at_utc != null ? String(data.created_at_utc) : undefined,
|
|
2036
|
+
updatedAtUtc: data.updated_at_utc != null ? String(data.updated_at_utc) : undefined,
|
|
2037
|
+
deletedAtUtc: data.deleted_at_utc != null ? String(data.deleted_at_utc) : undefined,
|
|
2038
|
+
labels: Object.fromEntries(Object.entries(labelsRaw).map(([key, value]) => [key, String(value)])),
|
|
2039
|
+
};
|
|
2040
|
+
}
|
|
2041
|
+
static parseScheduleOccurrence(data) {
|
|
2042
|
+
return {
|
|
2043
|
+
occurrenceId: String(data.occurrence_id ?? ""),
|
|
2044
|
+
scheduleId: String(data.schedule_id ?? ""),
|
|
2045
|
+
scheduleRevision: typeof data.schedule_revision === "object" && data.schedule_revision !== null
|
|
2046
|
+
? Number(data.schedule_revision["0"] ?? 0)
|
|
2047
|
+
: Number(data.schedule_revision ?? 0),
|
|
2048
|
+
occurrenceOrdinal: typeof data.occurrence_ordinal === "object" && data.occurrence_ordinal !== null
|
|
2049
|
+
? Number(data.occurrence_ordinal["0"] ?? 0)
|
|
2050
|
+
: Number(data.occurrence_ordinal ?? 0),
|
|
2051
|
+
phase: String(data.phase ?? ""),
|
|
2052
|
+
dueAtUtc: String(data.due_at_utc ?? ""),
|
|
2053
|
+
triggerSnapshot: data.trigger_snapshot && typeof data.trigger_snapshot === "object"
|
|
2054
|
+
? data.trigger_snapshot
|
|
2055
|
+
: {},
|
|
2056
|
+
targetSnapshot: data.target_snapshot && typeof data.target_snapshot === "object"
|
|
2057
|
+
? data.target_snapshot
|
|
2058
|
+
: {},
|
|
2059
|
+
misfirePolicy: data.misfire_policy != null
|
|
2060
|
+
? data.misfire_policy
|
|
2061
|
+
: undefined,
|
|
2062
|
+
overlapPolicy: data.overlap_policy != null ? String(data.overlap_policy) : undefined,
|
|
2063
|
+
missingTargetPolicy: data.missing_target_policy != null ? String(data.missing_target_policy) : undefined,
|
|
2064
|
+
claimedBy: data.claimed_by != null ? String(data.claimed_by) : undefined,
|
|
2065
|
+
leaseExpiresAtUtc: data.lease_expires_at_utc != null ? String(data.lease_expires_at_utc) : undefined,
|
|
2066
|
+
deliveryCorrelationId: data.delivery_correlation_id != null ? String(data.delivery_correlation_id) : undefined,
|
|
2067
|
+
lastReceipt: data.last_receipt && typeof data.last_receipt === "object"
|
|
2068
|
+
? data.last_receipt
|
|
2069
|
+
: undefined,
|
|
2070
|
+
failureClass: data.failure_class != null ? String(data.failure_class) : undefined,
|
|
2071
|
+
failureDetail: data.failure_detail != null ? String(data.failure_detail) : undefined,
|
|
2072
|
+
attemptCount: data.attempt_count != null ? Number(data.attempt_count) : undefined,
|
|
2073
|
+
createdAtUtc: data.created_at_utc != null ? String(data.created_at_utc) : undefined,
|
|
2074
|
+
claimedAtUtc: data.claimed_at_utc != null ? String(data.claimed_at_utc) : undefined,
|
|
2075
|
+
dispatchedAtUtc: data.dispatched_at_utc != null ? String(data.dispatched_at_utc) : undefined,
|
|
2076
|
+
completedAtUtc: data.completed_at_utc != null ? String(data.completed_at_utc) : undefined,
|
|
2077
|
+
supersededByRevision: typeof data.superseded_by_revision === "object" && data.superseded_by_revision !== null
|
|
2078
|
+
? Number(data.superseded_by_revision["0"] ?? 0)
|
|
2079
|
+
: data.superseded_by_revision != null
|
|
2080
|
+
? Number(data.superseded_by_revision)
|
|
2081
|
+
: undefined,
|
|
2082
|
+
};
|
|
2083
|
+
}
|
|
2084
|
+
static parseMobProfileLookup(data) {
|
|
2085
|
+
if (Boolean(data.not_found)) {
|
|
2086
|
+
return {
|
|
2087
|
+
notFound: true,
|
|
2088
|
+
name: String(data.name ?? ""),
|
|
2089
|
+
};
|
|
2090
|
+
}
|
|
2091
|
+
return {
|
|
2092
|
+
notFound: false,
|
|
2093
|
+
name: String(data.name ?? ""),
|
|
2094
|
+
profile: data.profile && typeof data.profile === "object"
|
|
2095
|
+
? data.profile
|
|
2096
|
+
: undefined,
|
|
2097
|
+
revision: data.revision != null ? Number(data.revision) : undefined,
|
|
2098
|
+
createdAt: data.created_at != null ? String(data.created_at) : undefined,
|
|
2099
|
+
updatedAt: data.updated_at != null ? String(data.updated_at) : undefined,
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
static toWireCreateScheduleRequest(request) {
|
|
2103
|
+
return {
|
|
2104
|
+
name: request.name,
|
|
2105
|
+
description: request.description,
|
|
2106
|
+
trigger: request.trigger,
|
|
2107
|
+
target: request.target,
|
|
2108
|
+
misfire_policy: request.misfirePolicy,
|
|
2109
|
+
overlap_policy: request.overlapPolicy,
|
|
2110
|
+
missing_target_policy: request.missingTargetPolicy,
|
|
2111
|
+
labels: request.labels,
|
|
2112
|
+
planning_horizon_days: request.planningHorizonDays,
|
|
2113
|
+
planning_horizon_occurrences: request.planningHorizonOccurrences,
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
static toWireUpdateSchedulePatch(update) {
|
|
2117
|
+
return {
|
|
2118
|
+
expected_revision: update.expectedRevision,
|
|
2119
|
+
name: update.name,
|
|
2120
|
+
description: update.description,
|
|
2121
|
+
trigger: update.trigger,
|
|
2122
|
+
target: update.target,
|
|
2123
|
+
misfire_policy: update.misfirePolicy,
|
|
2124
|
+
overlap_policy: update.overlapPolicy,
|
|
2125
|
+
missing_target_policy: update.missingTargetPolicy,
|
|
2126
|
+
planning_horizon_days: update.planningHorizonDays,
|
|
2127
|
+
planning_horizon_occurrences: update.planningHorizonOccurrences,
|
|
2128
|
+
labels: update.labels,
|
|
2129
|
+
};
|
|
2130
|
+
}
|
|
1038
2131
|
static parseSessionHistory(data) {
|
|
1039
2132
|
const rawMessages = Array.isArray(data.messages)
|
|
1040
2133
|
? data.messages
|
|
@@ -1050,6 +2143,10 @@ export class MeerkatClient {
|
|
|
1050
2143
|
};
|
|
1051
2144
|
}
|
|
1052
2145
|
static parseSessionMessage(data) {
|
|
2146
|
+
const role = String(data.role ?? "");
|
|
2147
|
+
const contentValue = role === "system_notice" && data.content == null && data.body != null
|
|
2148
|
+
? String(data.body)
|
|
2149
|
+
: data.content;
|
|
1053
2150
|
const rawToolCalls = Array.isArray(data.tool_calls)
|
|
1054
2151
|
? data.tool_calls
|
|
1055
2152
|
: [];
|
|
@@ -1060,8 +2157,9 @@ export class MeerkatClient {
|
|
|
1060
2157
|
? data.results
|
|
1061
2158
|
: [];
|
|
1062
2159
|
return {
|
|
1063
|
-
role
|
|
1064
|
-
|
|
2160
|
+
role,
|
|
2161
|
+
createdAt: String(data.created_at ?? ""),
|
|
2162
|
+
content: contentValue != null ? MeerkatClient.parseContentInput(contentValue) : undefined,
|
|
1065
2163
|
toolCalls: rawToolCalls.map((toolCall) => ({
|
|
1066
2164
|
id: String(toolCall.id ?? ""),
|
|
1067
2165
|
name: String(toolCall.name ?? ""),
|
|
@@ -1119,12 +2217,22 @@ export class MeerkatClient {
|
|
|
1119
2217
|
}
|
|
1120
2218
|
static parseSessionAssistantBlock(data) {
|
|
1121
2219
|
const blockData = data.data ?? {};
|
|
2220
|
+
const blobRef = blockData.blob_ref;
|
|
2221
|
+
const revisedPrompt = blockData.revised_prompt != null && typeof blockData.revised_prompt === "object"
|
|
2222
|
+
? blockData.revised_prompt
|
|
2223
|
+
: undefined;
|
|
1122
2224
|
return {
|
|
1123
2225
|
blockType: String(data.block_type ?? ""),
|
|
1124
2226
|
text: blockData.text != null ? String(blockData.text) : undefined,
|
|
1125
2227
|
id: blockData.id != null ? String(blockData.id) : undefined,
|
|
1126
2228
|
name: blockData.name != null ? String(blockData.name) : undefined,
|
|
1127
2229
|
args: blockData.args,
|
|
2230
|
+
imageId: blockData.image_id != null ? String(blockData.image_id) : undefined,
|
|
2231
|
+
blobId: blobRef?.blob_id != null ? String(blobRef.blob_id) : undefined,
|
|
2232
|
+
mediaType: blockData.media_type != null ? String(blockData.media_type) : undefined,
|
|
2233
|
+
width: blockData.width != null ? Number(blockData.width) : undefined,
|
|
2234
|
+
height: blockData.height != null ? Number(blockData.height) : undefined,
|
|
2235
|
+
revisedPrompt,
|
|
1128
2236
|
meta: blockData.meta,
|
|
1129
2237
|
};
|
|
1130
2238
|
}
|
|
@@ -1226,13 +2334,23 @@ export class MeerkatClient {
|
|
|
1226
2334
|
params.budget_limits = options.budgetLimits;
|
|
1227
2335
|
if (options.providerParams != null)
|
|
1228
2336
|
params.provider_params = options.providerParams;
|
|
1229
|
-
if (options.preloadSkills != null)
|
|
1230
|
-
params.preload_skills = options.preloadSkills;
|
|
2337
|
+
if (options.preloadSkills != null) {
|
|
2338
|
+
params.preload_skills = skillKeysToWire(options.preloadSkills);
|
|
2339
|
+
}
|
|
1231
2340
|
const wireRefs = skillRefsToWire(options.skillRefs);
|
|
1232
2341
|
if (wireRefs)
|
|
1233
2342
|
params.skill_refs = wireRefs;
|
|
1234
|
-
if (options.
|
|
1235
|
-
params.
|
|
2343
|
+
if (options.labels != null)
|
|
2344
|
+
params.labels = options.labels;
|
|
2345
|
+
if (options.additionalInstructions != null) {
|
|
2346
|
+
params.additional_instructions = options.additionalInstructions;
|
|
2347
|
+
}
|
|
2348
|
+
if (options.appContext !== undefined)
|
|
2349
|
+
params.app_context = options.appContext;
|
|
2350
|
+
if (options.shellEnv != null)
|
|
2351
|
+
params.shell_env = options.shellEnv;
|
|
2352
|
+
if (options.externalTools != null)
|
|
2353
|
+
params.external_tools = options.externalTools;
|
|
1236
2354
|
return params;
|
|
1237
2355
|
}
|
|
1238
2356
|
// -- Binary resolution --------------------------------------------------
|
|
@@ -1393,9 +2511,9 @@ export class MeerkatClient {
|
|
|
1393
2511
|
static buildArgs(legacy, options) {
|
|
1394
2512
|
if (legacy)
|
|
1395
2513
|
return ["rpc"];
|
|
2514
|
+
const args = ["--realtime-ws", "127.0.0.1:0"];
|
|
1396
2515
|
if (!options)
|
|
1397
|
-
return
|
|
1398
|
-
const args = [];
|
|
2516
|
+
return args;
|
|
1399
2517
|
if (options.isolated)
|
|
1400
2518
|
args.push("--isolated");
|
|
1401
2519
|
if (options.realmId)
|