@simular-ai/sai-sdk 0.0.0-stage → 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,66 @@
1
+ import type { Sai } from './client.js';
2
+ import type { Credential, Http } from './http.js';
3
+ import { type Enrollment, type Tenant, type TenantMachine, type TenantPage, type TenantToken } from './types.js';
4
+ export type TenantRef = Tenant | string;
5
+ export type TenantMachineRef = TenantMachine | string;
6
+ /** `tenants.client()` exchanges again when its token has less than this left. */
7
+ export declare const TOKEN_REFRESH_MARGIN_MS: number;
8
+ /** Tenants: your customers, under an Organisation. Every call takes an Organisation Key. */
9
+ export declare class Tenants {
10
+ private readonly http;
11
+ private readonly orgId;
12
+ private readonly withCredential;
13
+ constructor(http: Http, orgId: string | undefined, withCredential: (credential: Credential) => Sai);
14
+ /** `externalId` is your id for the customer, unique in the Organisation, and cannot change later. */
15
+ create(name: string, opts?: {
16
+ externalId?: string;
17
+ metadata?: Record<string, string>;
18
+ }): Promise<Tenant>;
19
+ /**
20
+ * One page, newest first. `externalId` finds the Tenant with that id (zero or one) and
21
+ * cannot be combined with `status`.
22
+ */
23
+ list(opts?: {
24
+ status?: string;
25
+ externalId?: string;
26
+ limit?: number;
27
+ cursor?: string;
28
+ }): Promise<TenantPage>;
29
+ get(tenant: TenantRef): Promise<Tenant>;
30
+ /**
31
+ * `metadata` replaces the whole map. `status: 'disabled'` stops the Tenant's tokens and
32
+ * machines; `status: 'active'` brings it back.
33
+ */
34
+ update(tenant: TenantRef, opts: {
35
+ name?: string;
36
+ metadata?: Record<string, string>;
37
+ status?: string;
38
+ }): Promise<Tenant>;
39
+ /** Disables the Tenant and revokes every machine. Its data is kept: erase it from the console. */
40
+ delete(tenant: TenantRef): Promise<void>;
41
+ /** A single-use code that enrolls one computer into the Tenant. It expires in 15 minutes. */
42
+ createEnrollment(tenant: TenantRef): Promise<Enrollment>;
43
+ /**
44
+ * Exchange the Organisation Key for a one-hour token that acts as the Tenant. `orgId`
45
+ * defaults to the client's `orgId` (`SAI_ORG_ID`).
46
+ */
47
+ token(tenant: TenantRef, opts?: {
48
+ orgId?: string;
49
+ }): Promise<TenantToken>;
50
+ /**
51
+ * A client that acts as the Tenant. It exchanges a token now, and again before a request
52
+ * when the token has less than five minutes left. Uses this client's Organisation Key.
53
+ */
54
+ client(tenant: TenantRef, opts?: {
55
+ orgId?: string;
56
+ }): Promise<Sai>;
57
+ }
58
+ /** A Tenant's enrolled computers. Every call takes an Organisation Key. */
59
+ export declare class TenantMachines {
60
+ private readonly http;
61
+ constructor(http: Http);
62
+ list(tenant: TenantRef): Promise<TenantMachine[]>;
63
+ get(tenant: TenantRef, machineId: string): Promise<TenantMachine>;
64
+ /** Signs the machine out at once. To bring it back, enroll it again with a new code. */
65
+ revoke(tenant: TenantRef, machine: TenantMachineRef): Promise<void>;
66
+ }
@@ -0,0 +1,97 @@
1
+ import { parseEnrollment, parseTenant, parseTenantMachine, parseTenantToken, } from './types.js';
2
+ /** `tenants.client()` exchanges again when its token has less than this left. */
3
+ export const TOKEN_REFRESH_MARGIN_MS = 5 * 60 * 1000;
4
+ const q = encodeURIComponent;
5
+ const tenantPath = (tenant) => `/v1/tenants/${q(typeof tenant === 'string' ? tenant : tenant.id)}`;
6
+ /** Tenants: your customers, under an Organisation. Every call takes an Organisation Key. */
7
+ export class Tenants {
8
+ http;
9
+ orgId;
10
+ withCredential;
11
+ constructor(http, orgId, withCredential) {
12
+ this.http = http;
13
+ this.orgId = orgId;
14
+ this.withCredential = withCredential;
15
+ }
16
+ /** `externalId` is your id for the customer, unique in the Organisation, and cannot change later. */
17
+ async create(name, opts = {}) {
18
+ return parseTenant(await this.http.json('POST', '/v1/tenants', {
19
+ json: { name, externalId: opts.externalId, metadata: opts.metadata },
20
+ }));
21
+ }
22
+ /**
23
+ * One page, newest first. `externalId` finds the Tenant with that id (zero or one) and
24
+ * cannot be combined with `status`.
25
+ */
26
+ async list(opts = {}) {
27
+ const d = await this.http.json('GET', '/v1/tenants', { params: opts });
28
+ return { tenants: (d.tenants ?? []).map(parseTenant), nextCursor: d.nextCursor ?? null };
29
+ }
30
+ async get(tenant) {
31
+ return parseTenant(await this.http.json('GET', tenantPath(tenant)));
32
+ }
33
+ /**
34
+ * `metadata` replaces the whole map. `status: 'disabled'` stops the Tenant's tokens and
35
+ * machines; `status: 'active'` brings it back.
36
+ */
37
+ async update(tenant, opts) {
38
+ return parseTenant(await this.http.json('PATCH', tenantPath(tenant), { json: opts }));
39
+ }
40
+ /** Disables the Tenant and revokes every machine. Its data is kept: erase it from the console. */
41
+ async delete(tenant) {
42
+ await this.http.request('DELETE', tenantPath(tenant));
43
+ }
44
+ /** A single-use code that enrolls one computer into the Tenant. It expires in 15 minutes. */
45
+ async createEnrollment(tenant) {
46
+ return parseEnrollment(await this.http.json('POST', `${tenantPath(tenant)}/enrollments`));
47
+ }
48
+ /**
49
+ * Exchange the Organisation Key for a one-hour token that acts as the Tenant. `orgId`
50
+ * defaults to the client's `orgId` (`SAI_ORG_ID`).
51
+ */
52
+ async token(tenant, opts = {}) {
53
+ const orgId = opts.orgId ?? this.orgId;
54
+ if (!orgId) {
55
+ throw new Error('No Organisation id: pass orgId here or to new Sai(), or set SAI_ORG_ID.');
56
+ }
57
+ const id = typeof tenant === 'string' ? tenant : tenant.id;
58
+ return parseTenantToken(await this.http.json('POST', `/v1/orgs/${q(orgId)}/tenants/${q(id)}/token`));
59
+ }
60
+ /**
61
+ * A client that acts as the Tenant. It exchanges a token now, and again before a request
62
+ * when the token has less than five minutes left. Uses this client's Organisation Key.
63
+ */
64
+ async client(tenant, opts = {}) {
65
+ let current = await this.token(tenant, opts);
66
+ let pending;
67
+ return this.withCredential(async () => {
68
+ if (current.expiresAt - Date.now() >= TOKEN_REFRESH_MARGIN_MS)
69
+ return current.token;
70
+ pending ??= this.token(tenant, opts).finally(() => {
71
+ pending = undefined;
72
+ });
73
+ current = await pending;
74
+ return current.token;
75
+ });
76
+ }
77
+ }
78
+ /** A Tenant's enrolled computers. Every call takes an Organisation Key. */
79
+ export class TenantMachines {
80
+ http;
81
+ constructor(http) {
82
+ this.http = http;
83
+ }
84
+ async list(tenant) {
85
+ const d = await this.http.json('GET', `${tenantPath(tenant)}/machines`);
86
+ return (d.machines ?? []).map(parseTenantMachine);
87
+ }
88
+ async get(tenant, machineId) {
89
+ return parseTenantMachine(await this.http.json('GET', `${tenantPath(tenant)}/machines/${q(machineId)}`));
90
+ }
91
+ /** Signs the machine out at once. To bring it back, enroll it again with a new code. */
92
+ async revoke(tenant, machine) {
93
+ const id = typeof machine === 'string' ? machine : machine.id;
94
+ await this.http.request('DELETE', `${tenantPath(tenant)}/machines/${q(id)}`);
95
+ }
96
+ }
97
+ //# sourceMappingURL=tenants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenants.js","sourceRoot":"","sources":["../src/tenants.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Turns: what a message to Sai started or joined. Every message gets a turn id
3
+ * (`turn.id`); this reads the turn's record: status, output, evidence, usage,
4
+ * and its trajectory when the message set `recordTrajectory`.
5
+ *
6
+ * Maps to `/v1/agents/turns/*`.
7
+ */
8
+ import type { Http } from './http.js';
9
+ import { type TrajectoryStep, type TurnRecord } from './types.js';
10
+ /** A turn id, a `Turn`, or a `TurnRecord`. */
11
+ export type TurnRef = string | {
12
+ id: string | null;
13
+ };
14
+ export declare class Turns {
15
+ private readonly http;
16
+ constructor(http: Http);
17
+ /** The turn's record now. Never waits: `finalizing` while the result is worked out. */
18
+ get(turn: TurnRef): Promise<TurnRecord>;
19
+ /**
20
+ * Read the turn until it is `succeeded`, `failed` or `needs_input`. On
21
+ * `needs_input`, answer the approval on the turn's session
22
+ * (`sai.sessions.resume(record.sessionId)`) and wait again. `timeoutMs`
23
+ * throws a `TimeoutError` (DOMException) with the turn unfinished.
24
+ */
25
+ wait(turn: TurnRef, opts?: {
26
+ timeoutMs?: number;
27
+ }): Promise<TurnRecord>;
28
+ /** The steps the agent took, in order. Recorded only when the message set `recordTrajectory`. */
29
+ trajectory(turn: TurnRef): Promise<TrajectoryStep[]>;
30
+ /** The screen before step `index` (the last one is after the turn), as JPEG bytes. */
31
+ screenshot(turn: TurnRef, index: number): Promise<Uint8Array>;
32
+ }
package/dist/turns.js ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Turns: what a message to Sai started or joined. Every message gets a turn id
3
+ * (`turn.id`); this reads the turn's record: status, output, evidence, usage,
4
+ * and its trajectory when the message set `recordTrajectory`.
5
+ *
6
+ * Maps to `/v1/agents/turns/*`.
7
+ */
8
+ import { waitTurnRecord } from './sessions.js';
9
+ import { parseTrajectoryStep, parseTurnRecord, } from './types.js';
10
+ const idOf = (turn) => {
11
+ const id = typeof turn === 'string' ? turn : turn.id;
12
+ if (!id)
13
+ throw new Error('This turn has no id: the message was answered without starting one.');
14
+ return encodeURIComponent(id);
15
+ };
16
+ export class Turns {
17
+ http;
18
+ constructor(http) {
19
+ this.http = http;
20
+ }
21
+ /** The turn's record now. Never waits: `finalizing` while the result is worked out. */
22
+ async get(turn) {
23
+ return parseTurnRecord(await this.http.json('GET', `/v1/agents/turns/${idOf(turn)}`));
24
+ }
25
+ /**
26
+ * Read the turn until it is `succeeded`, `failed` or `needs_input`. On
27
+ * `needs_input`, answer the approval on the turn's session
28
+ * (`sai.sessions.resume(record.sessionId)`) and wait again. `timeoutMs`
29
+ * throws a `TimeoutError` (DOMException) with the turn unfinished.
30
+ */
31
+ async wait(turn, opts = {}) {
32
+ const deadline = opts.timeoutMs === undefined ? null : Date.now() + opts.timeoutMs;
33
+ return waitTurnRecord(this.http, decodeURIComponent(idOf(turn)), deadline, [
34
+ 'succeeded',
35
+ 'failed',
36
+ 'needs_input',
37
+ ]);
38
+ }
39
+ /** The steps the agent took, in order. Recorded only when the message set `recordTrajectory`. */
40
+ async trajectory(turn) {
41
+ const d = await this.http.json('GET', `/v1/agents/turns/${idOf(turn)}/trajectory`);
42
+ return (d.steps ?? []).map(parseTrajectoryStep);
43
+ }
44
+ /** The screen before step `index` (the last one is after the turn), as JPEG bytes. */
45
+ async screenshot(turn, index) {
46
+ const res = await this.http.request('GET', `/v1/agents/turns/${idOf(turn)}/trajectory/screenshots/${index}`);
47
+ return new Uint8Array(await res.arrayBuffer());
48
+ }
49
+ }
50
+ //# sourceMappingURL=turns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turns.js","sourceRoot":"","sources":["../src/turns.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EACL,mBAAmB,EACnB,eAAe,GAGhB,MAAM,YAAY,CAAA;AAKnB,MAAM,IAAI,GAAG,CAAC,IAAa,EAAU,EAAE;IACrC,MAAM,EAAE,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAA;IACpD,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAA;IAC/F,OAAO,kBAAkB,CAAC,EAAE,CAAC,CAAA;AAC/B,CAAC,CAAA;AAED,MAAM,OAAO,KAAK;IACa;IAA7B,YAA6B,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;IAAG,CAAC;IAE3C,uFAAuF;IACvF,KAAK,CAAC,GAAG,CAAC,IAAa;QACrB,OAAO,eAAe,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,oBAAoB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;IACvF,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,IAAa,EAAE,OAA+B,EAAE;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAA;QAClF,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE;YACzE,WAAW;YACX,QAAQ;YACR,aAAa;SACd,CAAC,CAAA;IACJ,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,UAAU,CAAC,IAAa;QAC5B,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAC5B,KAAK,EACL,oBAAoB,IAAI,CAAC,IAAI,CAAC,aAAa,CAC5C,CAAA;QACD,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;IACjD,CAAC;IAED,sFAAsF;IACtF,KAAK,CAAC,UAAU,CAAC,IAAa,EAAE,KAAa;QAC3C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CACjC,KAAK,EACL,oBAAoB,IAAI,CAAC,IAAI,CAAC,2BAA2B,KAAK,EAAE,CACjE,CAAA;QACD,OAAO,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAA;IAChD,CAAC;CACF"}
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Response objects. Each keeps the server's JSON in `raw`, so a field the SDK
3
+ * does not model yet is still reachable.
4
+ */
5
+ type Json = Record<string, unknown>;
6
+ export interface Account {
7
+ userId: string;
8
+ planId: string | null;
9
+ planTitle: string;
10
+ free: boolean;
11
+ unlimited: boolean;
12
+ /** Spendable credit in USD; null on the unlimited plan or when billing could not be reached. */
13
+ creditsUsd: number | null;
14
+ raw: Json;
15
+ }
16
+ export declare function parseAccount(d: Json): Account;
17
+ export interface Model {
18
+ id: string;
19
+ name: string;
20
+ provider: string;
21
+ tier: string;
22
+ costTier: string;
23
+ allowed: boolean;
24
+ raw: Json;
25
+ }
26
+ export declare function parseModel(d: Json): Model;
27
+ export interface Machine {
28
+ id: string;
29
+ name: string | null;
30
+ /** `cloud` (hosted by Simular) or `own` (a desktop with the Sai app). */
31
+ kind: string;
32
+ /** True when a message can reach it now (a hibernated cloud computer wakes on the first message). */
33
+ online: boolean;
34
+ /**
35
+ * `running`, `starting`, `asleep`, `creating` or `unknown`; `null` on servers that do not
36
+ * send it yet. Prefer it over `status`.
37
+ */
38
+ state: string | null;
39
+ /** @deprecated The server's internal lifecycle value; it may gain values at any time. Use `state`. */
40
+ status: string | null;
41
+ canWake: boolean;
42
+ raw: Json;
43
+ }
44
+ export declare function parseMachine(d: Json): Machine;
45
+ /** One of your customers under an Organisation. */
46
+ export interface Tenant {
47
+ id: string;
48
+ name: string;
49
+ /** Your id for the customer. Unique in the Organisation; set on create only. */
50
+ externalId: string | null;
51
+ metadata: Record<string, string>;
52
+ /** `active` or `disabled`. */
53
+ status: string;
54
+ /** Unix time in milliseconds. */
55
+ createdAt: number;
56
+ disabledAt: number | null;
57
+ machineCount: number;
58
+ raw: Json;
59
+ }
60
+ export declare function parseTenant(d: Json): Tenant;
61
+ export interface TenantPage {
62
+ tenants: Tenant[];
63
+ /** Pass as `cursor` for the next page; null on the last page. */
64
+ nextCursor: string | null;
65
+ }
66
+ /** A Tenant's own computer, running the Sai runtime. */
67
+ export interface TenantMachine {
68
+ id: string;
69
+ name: string | null;
70
+ platform: string | null;
71
+ status: string;
72
+ /** True when the machine reported in the last 3 minutes. */
73
+ online: boolean;
74
+ lastSeen: number | null;
75
+ runtimeVersion: string | null;
76
+ raw: Json;
77
+ }
78
+ export declare function parseTenantMachine(d: Json): TenantMachine;
79
+ export interface Enrollment {
80
+ /** Single use. Treat it as a secret until the Sai runtime redeems it. */
81
+ token: string;
82
+ /** Unix time in milliseconds, 15 minutes after it was created. */
83
+ expiresAt: number;
84
+ raw: Json;
85
+ }
86
+ export declare function parseEnrollment(d: Json): Enrollment;
87
+ export interface TenantToken {
88
+ /** Pass as `new Sai({ apiKey })` to act as the Tenant on sessions, machines and turns. */
89
+ token: string;
90
+ /** Unix time in milliseconds, an hour after the exchange. There is no refresh: exchange again. */
91
+ expiresAt: number;
92
+ tenantId: string;
93
+ raw: Json;
94
+ }
95
+ export declare function parseTenantToken(d: Json): TenantToken;
96
+ /** A file uploaded with `sai.files.upload()`. Pass it in `attachments`. */
97
+ export interface Attachment {
98
+ fileId: string;
99
+ name: string;
100
+ mime: string;
101
+ size: number;
102
+ raw: Json;
103
+ }
104
+ export declare function parseAttachment(d: Json): Attachment;
105
+ /** A view-only Guacamole stream of a computer's screen. The URL carries a token: keep it private. */
106
+ export interface LiveView {
107
+ machineId: string;
108
+ websocketUrl: string;
109
+ width: number;
110
+ height: number;
111
+ }
112
+ /** Sai is waiting for permission (or for an answer to a choice question). */
113
+ export interface Approval {
114
+ id: string;
115
+ title: string;
116
+ description: string;
117
+ /** `exec`, `choice`, ...; a `choice` needs `selections` when approved. */
118
+ type: string;
119
+ /** True: a human must answer in a browser at `url`; the API cannot. */
120
+ isLinkOnly: boolean;
121
+ url: string | null;
122
+ command: string | null;
123
+ questions: Json[];
124
+ raw: Json;
125
+ }
126
+ export declare function parseApproval(d: Json): Approval;
127
+ export interface Usage {
128
+ inputTokens: number;
129
+ outputTokens: number;
130
+ cacheReadTokens: number;
131
+ cacheWriteTokens: number;
132
+ costUsd: number;
133
+ modelCalls: number;
134
+ byModel: Json;
135
+ }
136
+ export declare function parseUsage(d: unknown): Usage | null;
137
+ /** The SDK's event kinds. `other` only appears with `events({ raw: true })`. */
138
+ export declare const EVENT_KINDS: readonly ["step", "message", "approval", "tool_error", "error", "finished", "other"];
139
+ export type EventKind = (typeof EVENT_KINDS)[number];
140
+ /**
141
+ * One thing that happened in a turn. `kind` is the SDK's name; `type` is the
142
+ * wire type.
143
+ */
144
+ export interface Event {
145
+ kind: EventKind;
146
+ type: string;
147
+ text: string | null;
148
+ approval: Approval | null;
149
+ /** `insufficient_credits` / `free_computer_time_exhausted` on errors: stop retrying today. */
150
+ code: string | null;
151
+ raw: Json;
152
+ }
153
+ export declare function parseEvent(d: Json): Event;
154
+ /** Turn statuses: `running` while polling, then one of the three below. */
155
+ export declare const TURN_STATUSES: readonly ["running", "idle", "needs_approval", "error"];
156
+ export type TurnStatus = (typeof TURN_STATUSES)[number];
157
+ /**
158
+ * Where a turn stopped. `status` is `idle` (done: `text` is the answer),
159
+ * `error`, or `needs_approval` (waiting on `approval`; answer it and call
160
+ * `wait()` again). `record` is the turn's record for a structured message (one
161
+ * with `inputs`, `outputSchema` or `successCriteria`).
162
+ */
163
+ export interface TurnResult {
164
+ status: TurnStatus;
165
+ text: string;
166
+ sessionId: string;
167
+ approval: Approval | null;
168
+ error: string | null;
169
+ errorCode: string | null;
170
+ usage: Usage | null;
171
+ sessionUsage: Usage | null;
172
+ record: TurnRecord | null;
173
+ /** Idle, and for a structured message, the turn succeeded. */
174
+ ok: boolean;
175
+ }
176
+ /** One yes/no constraint a structured message's turn is checked against after it ends. */
177
+ export interface Check {
178
+ /** Letters, digits, `_` or `-`; at most 64 characters. */
179
+ id: string;
180
+ check: string;
181
+ /** Also return one sentence of evidence for this check (an extra model call). */
182
+ returnEvidence?: boolean;
183
+ }
184
+ /** The verdict on one success criterion. */
185
+ export interface Evidence {
186
+ /** The check's id; null for a natural-language `successCriteria`. */
187
+ id: string | null;
188
+ passed: boolean;
189
+ /** The probability that the check holds (`Check` criteria only). */
190
+ score: number | null;
191
+ /** Always for a natural-language criteria; for a `Check`, only with `returnEvidence`. */
192
+ evidence: string | null;
193
+ }
194
+ /** Turn record statuses, from `GET /v1/agents/turns/{id}`. */
195
+ export declare const TURN_RECORD_STATUSES: readonly ["running", "needs_input", "finalizing", "succeeded", "failed"];
196
+ export type TurnRecordStatus = (typeof TURN_RECORD_STATUSES)[number];
197
+ /**
198
+ * A turn's record. `status` is `running`, `needs_input` (an approval or
199
+ * question is pending), `finalizing` (the agent is done; output and checks are
200
+ * being worked out), `succeeded` or `failed`. On `failed`, `reasonCode` says
201
+ * why: `agent_error` (with `errorCode` when known), `machine_unavailable`,
202
+ * `not_started`, and for a structured message `output_invalid` (see `rawAnswer`
203
+ * and `outputErrors`), `criteria_not_met` or `criteria_unchecked`.
204
+ */
205
+ export interface TurnRecord {
206
+ id: string;
207
+ sessionId: string | null;
208
+ machineId: string;
209
+ status: TurnRecordStatus;
210
+ /** The agent's final text; with `outputSchema`, an object matching it. */
211
+ output: unknown;
212
+ reasonCode: string | null;
213
+ rawAnswer: string | null;
214
+ /** `insufficient_credits` or `free_computer_time_exhausted`, for a known `agent_error`. */
215
+ errorCode: string | null;
216
+ outputErrors: string[];
217
+ /** Empty for a plain message. */
218
+ evidence: Evidence[];
219
+ /** Tokens of every model call the agent made in the turn. */
220
+ usage: Usage | null;
221
+ recordTrajectory: boolean;
222
+ /** At least one step was stored (`sai.turns.trajectory()`). */
223
+ trajectoryRecorded: boolean;
224
+ template: string | null;
225
+ inputs: Json | null;
226
+ /** True when `idempotencyKey` matched an earlier turn: this is that turn, and nothing was sent. */
227
+ replayed: boolean;
228
+ done: boolean;
229
+ ok: boolean;
230
+ raw: Json;
231
+ }
232
+ export declare function parseTurnRecord(d: Json): TurnRecord;
233
+ /** One step the agent took: what it did, and why. Fetch its screen with `sai.turns.screenshot()`. */
234
+ export interface TrajectoryStep {
235
+ index: number;
236
+ /** The screenshot taken when the turn ended, after the last step. */
237
+ final: boolean;
238
+ timestamp: string;
239
+ title: string | null;
240
+ code: string | null;
241
+ /** The agent's text before the action. */
242
+ rationale: string | null;
243
+ error: string | null;
244
+ hasScreenshot: boolean;
245
+ raw: Json;
246
+ }
247
+ export declare function parseTrajectoryStep(d: Json): TrajectoryStep;
248
+ export interface ExecError {
249
+ /** `exception`, `timeout` or `interrupted`. */
250
+ kind: string;
251
+ message: string;
252
+ stack: string | null;
253
+ }
254
+ /** What one Simulang block returned. A block that threw is still a result: check `error`. */
255
+ export interface ExecResult {
256
+ result: unknown;
257
+ logs: string[];
258
+ error: ExecError | null;
259
+ /** The screenshot the block captured (page/app snapshot, pageContent), decoded. */
260
+ screenshot: Uint8Array | null;
261
+ /** `image/jpeg` or `image/png`. */
262
+ screenshotMimeType: string | null;
263
+ /** @deprecated Use `screenshot`. Not always PNG; see `screenshotMimeType`. */
264
+ screenshotPng?: Uint8Array | null;
265
+ screenshotOmitted: boolean;
266
+ variables: Json[];
267
+ durationMs: number;
268
+ ok: boolean;
269
+ raw: Json;
270
+ }
271
+ export declare function parseExecResult(d: Json): ExecResult;
272
+ /** One input of learned code: a `{{name}}` in the template and a key of `main`'s `params`. */
273
+ export interface LearnParameter {
274
+ name: string;
275
+ defaultValue: string;
276
+ description: string | null;
277
+ }
278
+ /** How learned code did on one run, for `sai.learn.create(..., { initialCode, evaluations })`. */
279
+ export interface Evaluation {
280
+ inputs: Record<string, string | number | boolean>;
281
+ /** The run's result from `lease.exec()` / `lease.run()`; its screenshot is not sent. */
282
+ result?: ExecResult;
283
+ /** A judgement of the run, or its id. */
284
+ judgement?: Judgement | string;
285
+ passed?: boolean;
286
+ note?: string;
287
+ }
288
+ /**
289
+ * The result of `sai.learn.create()`: Simulang code made from recorded turns, or a repair of
290
+ * code you sent. Run it with `lease.run(learned, inputs)`. Research preview.
291
+ */
292
+ export interface LearnResult {
293
+ id: string;
294
+ /** `convert` (code from turns) or `heal` (a repair of `initialCode`). */
295
+ mode: 'convert' | 'heal';
296
+ /** `failed` when the code still has `validation.errors`, or the request failed (`error`). */
297
+ status: 'succeeded' | 'failed' | 'running';
298
+ title: string | null;
299
+ /** The task with `{{name}}` placeholders: send it to `session.send()` with `inputs` to run it with the agent. */
300
+ template: string | null;
301
+ parameters: LearnParameter[];
302
+ /** `async function main(params = { ... })`. */
303
+ code: string;
304
+ outputSchema: Json | null;
305
+ validation: {
306
+ errors: string[];
307
+ warnings: string[];
308
+ };
309
+ /** For `heal`: what changed and why. */
310
+ changes: string | null;
311
+ sourceTurns: string[];
312
+ usage: Usage | null;
313
+ /** The error code when the request failed, e.g. `trajectory_not_recorded`. */
314
+ error: string | null;
315
+ /** True when `idempotencyKey` matched an earlier call: this is that call's result. */
316
+ replayed: boolean;
317
+ ok: boolean;
318
+ raw: Json;
319
+ }
320
+ export declare function parseLearnResult(d: Json): LearnResult;
321
+ /** The verdict on one criterion of a judgement. */
322
+ export interface CriterionResult {
323
+ /** The check's id; null for a natural-language criteria. */
324
+ id: string | null;
325
+ check: string;
326
+ /** `unverifiable` when the record cannot show it. */
327
+ verdict: 'passed' | 'failed' | 'unverifiable';
328
+ score: number | null;
329
+ evidence: string | null;
330
+ }
331
+ /** The result of `sai.judge.create()`. It never changes the turns it judged. Research preview. */
332
+ export interface Judgement {
333
+ id: string;
334
+ verdict: 'passed' | 'failed' | 'unverifiable' | null;
335
+ summary: string | null;
336
+ task: string | null;
337
+ criteria: CriterionResult[];
338
+ turns: string[];
339
+ usage: Usage | null;
340
+ replayed: boolean;
341
+ ok: boolean;
342
+ raw: Json;
343
+ }
344
+ export declare function parseJudgement(d: Json): Judgement;
345
+ export {};