@simular-ai/sai-sdk 0.0.0-placeholder → 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,15 @@
1
+ import type { Http } from './http.js';
2
+ import { type LiveView, type Machine } from './types.js';
3
+ export type MachineRef = Machine | string;
4
+ /** Machines: the computers Sai works on. Cloud computers, or the customer's own PC with the Sai app. */
5
+ export declare class Machines {
6
+ private readonly http;
7
+ constructor(http: Http);
8
+ list(): Promise<Machine[]>;
9
+ get(machineId: string): Promise<Machine>;
10
+ /** A view-only stream of the screen (Apache Guacamole). The machine must be running. */
11
+ live(machine: MachineRef): Promise<LiveView>;
12
+ /** @internal */
13
+ resolveId(machine: MachineRef | undefined): Promise<string>;
14
+ }
15
+ export declare function idOf(machine: MachineRef): string;
@@ -0,0 +1,47 @@
1
+ import { BadRequestError, NotFoundError } from './errors.js';
2
+ import { parseMachine } from './types.js';
3
+ /** Machines: the computers Sai works on. Cloud computers, or the customer's own PC with the Sai app. */
4
+ export class Machines {
5
+ http;
6
+ constructor(http) {
7
+ this.http = http;
8
+ }
9
+ async list() {
10
+ const d = await this.http.json('GET', '/v1/agents/machines');
11
+ return (d.machines ?? []).map(parseMachine);
12
+ }
13
+ async get(machineId) {
14
+ const m = (await this.list()).find((x) => x.id === machineId);
15
+ if (!m)
16
+ throw new NotFoundError(`Machine ${machineId} not found on this account.`, { status: 404 });
17
+ return m;
18
+ }
19
+ /** A view-only stream of the screen (Apache Guacamole). The machine must be running. */
20
+ async live(machine) {
21
+ const id = idOf(machine);
22
+ const d = await this.http.json('POST', `/v1/agents/machines/${encodeURIComponent(id)}/live`);
23
+ return {
24
+ machineId: typeof d.machineId === 'string' ? d.machineId : id,
25
+ websocketUrl: String(d.websocketUrl),
26
+ width: Number(d.width ?? 0),
27
+ height: Number(d.height ?? 0),
28
+ };
29
+ }
30
+ /** @internal */
31
+ async resolveId(machine) {
32
+ if (machine)
33
+ return idOf(machine);
34
+ const machines = await this.list();
35
+ if (machines.length === 1)
36
+ return machines[0].id;
37
+ if (machines.length === 0) {
38
+ throw new BadRequestError('No computer on this account. Create one in the Sai app or the portal.', { status: 400 });
39
+ }
40
+ const names = machines.map((m) => (m.name ? `${m.id} (${m.name})` : m.id)).join(', ');
41
+ throw new BadRequestError(`Several computers on this account; pass machine. Candidates: ${names}`, { status: 400 });
42
+ }
43
+ }
44
+ export function idOf(machine) {
45
+ return typeof machine === 'string' ? machine : machine.id;
46
+ }
47
+ //# sourceMappingURL=machines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machines.js","sourceRoot":"","sources":["../src/machines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE5D,OAAO,EAAE,YAAY,EAA+B,MAAM,YAAY,CAAA;AAItE,wGAAwG;AACxG,MAAM,OAAO,QAAQ;IACU;IAA7B,YAA6B,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;IAAG,CAAC;IAE3C,KAAK,CAAC,IAAI;QACR,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAC5B,KAAK,EACL,qBAAqB,CACtB,CAAA;QACD,OAAO,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IAC7C,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,SAAiB;QACzB,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAA;QAC7D,IAAI,CAAC,CAAC;YACJ,MAAM,IAAI,aAAa,CAAC,WAAW,SAAS,6BAA6B,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC7F,OAAO,CAAC,CAAA;IACV,CAAC;IAED,wFAAwF;IACxF,KAAK,CAAC,IAAI,CAAC,OAAmB;QAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;QACxB,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAC5B,MAAM,EACN,uBAAuB,kBAAkB,CAAC,EAAE,CAAC,OAAO,CACrD,CAAA;QACD,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;YAC7D,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;YACpC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;YAC3B,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;SAC9B,CAAA;IACH,CAAC;IAED,gBAAgB;IAChB,KAAK,CAAC,SAAS,CAAC,OAA+B;QAC7C,IAAI,OAAO;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,CAAA;QACjC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QAClC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC,CAAC,CAAE,CAAC,EAAE,CAAA;QACjD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,eAAe,CACvB,uEAAuE,EACvE,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAA;QACH,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACrF,MAAM,IAAI,eAAe,CACvB,gEAAgE,KAAK,EAAE,EACvE,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAA;IACH,CAAC;CACF;AAED,MAAM,UAAU,IAAI,CAAC,OAAmB;IACtC,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAA;AAC3D,CAAC"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Sessions: a conversation with Sai on one computer. Sai decides every click.
3
+ *
4
+ * Maps to `/v1/agents/*`: `new-session`, `message` (wait=false), `events`,
5
+ * `approve`, `abort`. Every message gets a turn id (`turn.id`, read with
6
+ * `sai.turns`); a message with `inputs`, `outputSchema` or `successCriteria`
7
+ * is structured and its turn also returns a typed result.
8
+ */
9
+ import type { Http } from './http.js';
10
+ import { type MachineRef, type Machines } from './machines.js';
11
+ import { type Approval, type Attachment, type Check, type Event, type TurnRecord, type TurnRecordStatus, type TurnResult, type TurnStatus } from './types.js';
12
+ /**
13
+ * What an `onApproval` handler answers: a response (`yes`, `no`, `task`), a
14
+ * `[response, selections]` pair for a choice, or null to leave the approval
15
+ * pending (e.g. a human answers it in a browser).
16
+ */
17
+ export type ApprovalAnswer = string | [string, string[][]] | null;
18
+ export type ApprovalHandler = (approval: Approval) => ApprovalAnswer | Promise<ApprovalAnswer>;
19
+ export interface SendOptions {
20
+ /** An id from `sai.models.list()` (or `auto`); sticks to the session until changed. */
21
+ model?: string;
22
+ attachments?: Attachment[];
23
+ /** Values for the `{{name}}` placeholders in the message. Makes the message structured. */
24
+ inputs?: Record<string, string | number | boolean>;
25
+ /** JSON Schema (at most 32 KB) the turn's output must match. Makes the message structured. */
26
+ outputSchema?: Record<string, unknown>;
27
+ /**
28
+ * A guideline for a judge, or yes/no checks, the turn is checked against.
29
+ * Makes the message structured.
30
+ */
31
+ successCriteria?: string | Check[];
32
+ /** The same key again returns the earlier turn and sends nothing. */
33
+ idempotencyKey?: string;
34
+ /** Keep a screenshot and the action for each step (`sai.turns.trajectory()`). */
35
+ recordTrajectory?: boolean;
36
+ /**
37
+ * Run the turn this message starts without approval cards, as if "Trust for
38
+ * this task" had been answered; the grant ends with the turn. A message that
39
+ * steers a running turn changes nothing.
40
+ */
41
+ autonomous?: boolean;
42
+ }
43
+ export interface WaitOptions {
44
+ onApproval?: ApprovalHandler;
45
+ /** Throws a `TimeoutError` (DOMException) with the turn still running. */
46
+ timeoutMs?: number;
47
+ /** Seconds the server may hold one poll; it caps at 60. */
48
+ pollWait?: number;
49
+ }
50
+ export declare class Sessions {
51
+ private readonly http;
52
+ private readonly machines;
53
+ constructor(http: Http, machines: Machines);
54
+ /**
55
+ * Start a fresh conversation on a computer: the next message has no memory
56
+ * of earlier ones. `machine` may be omitted with one computer.
57
+ */
58
+ create(opts?: {
59
+ machine?: MachineRef;
60
+ }): Promise<Session>;
61
+ /** Reattach to a session started elsewhere, e.g. to poll or abort it. */
62
+ resume(sessionId: string, opts?: {
63
+ machine?: MachineRef;
64
+ }): Session;
65
+ }
66
+ /** A conversation with Sai. Each `send()` is a turn; turns share context. */
67
+ export declare class Session {
68
+ private readonly http;
69
+ machineId: string | null;
70
+ id: string | null;
71
+ constructor(http: Http, machineId: string | null, id: string | null);
72
+ /**
73
+ * Give Sai a task, or steer the running one. Returns at once. Sent while a
74
+ * turn is running, the message steers that turn (`turn.queued` is true).
75
+ *
76
+ * Any of `inputs`, `outputSchema` or `successCriteria` makes the message
77
+ * structured: the message is a template whose `{{name}}` placeholders are
78
+ * filled from `inputs`, the output must match `outputSchema`, and the turn
79
+ * is checked against `successCriteria`. `wait()` then also returns the
80
+ * turn's record in `result.record`. A structured message is refused with
81
+ * `ConflictError` (`session_busy`) while a turn is running. These go to the
82
+ * API as `options`.
83
+ */
84
+ send(message: string, opts?: SendOptions): Promise<Turn>;
85
+ /** `send()` then `wait()`: the answer, or where it stopped. */
86
+ run(message: string, opts?: SendOptions & WaitOptions): Promise<TurnResult>;
87
+ /** Stop the running turn. Pending approvals are denied. False if nothing was running. */
88
+ abort(): Promise<boolean>;
89
+ /**
90
+ * Answer an approval: `yes`, `no`, or `task` (allow for the rest of the task).
91
+ * A `choice` approval needs `selections`, one list of option values per
92
+ * question. Throws `LinkOnlyApprovalError` (with `approvalUrl`) when only a
93
+ * browser can answer it. Resolves to `approved`, `approved_task` or `denied`.
94
+ */
95
+ respond(approval: Approval | string, response?: string, opts?: {
96
+ selections?: string[][];
97
+ }): Promise<string>;
98
+ }
99
+ /**
100
+ * One message's work. Iterate `events()` to watch it, or `wait()` for the
101
+ * result. `id` is the turn the message started, or the running turn it joined
102
+ * (`sai.turns.get(turn)`); null when the message was answered without one.
103
+ */
104
+ export declare class Turn {
105
+ #private;
106
+ readonly session: Session;
107
+ private readonly http;
108
+ readonly queued: boolean;
109
+ readonly id: string | null;
110
+ private cursor;
111
+ private last;
112
+ private readonly structured;
113
+ private readonly replay;
114
+ private readonly local;
115
+ constructor(session: Session, http: Http, queued: boolean, done?: TurnResult | null, turn?: {
116
+ id: string | null;
117
+ structured: boolean;
118
+ replay?: TurnRecord;
119
+ });
120
+ get status(): TurnStatus;
121
+ /** The last known state, or null before the first poll. */
122
+ get result(): TurnResult | null;
123
+ /**
124
+ * Yield events until the turn is idle or errors. It keeps going through
125
+ * `needs_approval`: answer with `turn.respond(ev.approval, ...)` inside the
126
+ * loop, or let a human answer a link-only approval in a browser. Without
127
+ * `raw`, framing, reasoning and tool-call frames are skipped.
128
+ */
129
+ events(opts?: {
130
+ raw?: boolean;
131
+ pollWait?: number;
132
+ }): AsyncGenerator<Event>;
133
+ /**
134
+ * Wait until the turn is done, or stops on an approval nobody answered.
135
+ * Without `onApproval`, resolves with `status === 'needs_approval'` and the
136
+ * `approval` so the caller can decide. With it, the handler's answer is sent
137
+ * and waiting continues; a handler returning null leaves the approval to
138
+ * someone else (a link-only one to a human) and keeps waiting. For a
139
+ * structured message, it then waits for the turn's record (`result.record`:
140
+ * output, evidence), which is worked out after the turn.
141
+ */
142
+ wait(opts?: WaitOptions): Promise<TurnResult>;
143
+ respond(approval: Approval | string, response?: string, opts?: {
144
+ selections?: string[][];
145
+ }): Promise<string>;
146
+ abort(): Promise<boolean>;
147
+ }
148
+ /**
149
+ * Read the turn's record until its status is in `stop`. Throws a `TimeoutError`
150
+ * (DOMException) past `deadline` (epoch ms).
151
+ */
152
+ export declare function waitTurnRecord(http: Http, turnId: string, deadline: number | null, stop?: readonly TurnRecordStatus[]): Promise<TurnRecord>;
@@ -0,0 +1,378 @@
1
+ /**
2
+ * Sessions: a conversation with Sai on one computer. Sai decides every click.
3
+ *
4
+ * Maps to `/v1/agents/*`: `new-session`, `message` (wait=false), `events`,
5
+ * `approve`, `abort`. Every message gets a turn id (`turn.id`, read with
6
+ * `sai.turns`); a message with `inputs`, `outputSchema` or `successCriteria`
7
+ * is structured and its turn also returns a typed result.
8
+ */
9
+ import { ConflictError, LinkOnlyApprovalError, NotFoundError, RateLimitError } from './errors.js';
10
+ import { idOf } from './machines.js';
11
+ import { parseApproval, parseEvent, parseTurnRecord, parseUsage, } from './types.js';
12
+ const POLL_WAIT = 30;
13
+ /** Between turn reads; `GET /v1/agents/turns/{id}` never holds. */
14
+ const RECORD_POLL_INTERVAL_MS = 2_000;
15
+ export class Sessions {
16
+ http;
17
+ machines;
18
+ constructor(http, machines) {
19
+ this.http = http;
20
+ this.machines = machines;
21
+ }
22
+ /**
23
+ * Start a fresh conversation on a computer: the next message has no memory
24
+ * of earlier ones. `machine` may be omitted with one computer.
25
+ */
26
+ async create(opts = {}) {
27
+ const machineId = await this.machines.resolveId(opts.machine);
28
+ let sessionId = null;
29
+ try {
30
+ const d = await this.http.json('POST', '/v1/agents/new-session', {
31
+ json: { machineId, channel: 'api' },
32
+ });
33
+ sessionId = d.sessionId ?? null;
34
+ }
35
+ catch (err) {
36
+ // A free account's computer between claims has no conversation to
37
+ // rotate; the first message starts one.
38
+ if (!(err instanceof NotFoundError))
39
+ throw err;
40
+ }
41
+ return new Session(this.http, machineId, sessionId);
42
+ }
43
+ /** Reattach to a session started elsewhere, e.g. to poll or abort it. */
44
+ resume(sessionId, opts = {}) {
45
+ return new Session(this.http, opts.machine ? idOf(opts.machine) : null, sessionId);
46
+ }
47
+ }
48
+ /** A conversation with Sai. Each `send()` is a turn; turns share context. */
49
+ export class Session {
50
+ http;
51
+ machineId;
52
+ id;
53
+ constructor(http, machineId, id) {
54
+ this.http = http;
55
+ this.machineId = machineId;
56
+ this.id = id;
57
+ }
58
+ /**
59
+ * Give Sai a task, or steer the running one. Returns at once. Sent while a
60
+ * turn is running, the message steers that turn (`turn.queued` is true).
61
+ *
62
+ * Any of `inputs`, `outputSchema` or `successCriteria` makes the message
63
+ * structured: the message is a template whose `{{name}}` placeholders are
64
+ * filled from `inputs`, the output must match `outputSchema`, and the turn
65
+ * is checked against `successCriteria`. `wait()` then also returns the
66
+ * turn's record in `result.record`. A structured message is refused with
67
+ * `ConflictError` (`session_busy`) while a turn is running. These go to the
68
+ * API as `options`.
69
+ */
70
+ async send(message, opts = {}) {
71
+ const body = { message, wait: false };
72
+ if (this.machineId)
73
+ body.machineId = this.machineId;
74
+ if (this.id)
75
+ body.sessionId = this.id;
76
+ if (opts.model)
77
+ body.model = opts.model;
78
+ if (opts.attachments?.length)
79
+ body.attachments = opts.attachments.map((a) => a.raw);
80
+ if (opts.autonomous)
81
+ body.autonomous = true;
82
+ const options = {};
83
+ if (opts.inputs !== undefined)
84
+ options.inputs = opts.inputs;
85
+ if (opts.outputSchema !== undefined)
86
+ options.output_schema = opts.outputSchema;
87
+ if (opts.successCriteria !== undefined)
88
+ options.success_criteria = opts.successCriteria;
89
+ if (opts.idempotencyKey !== undefined)
90
+ options.idempotency_key = opts.idempotencyKey;
91
+ if (opts.recordTrajectory)
92
+ options.recordTrajectory = true;
93
+ if (Object.keys(options).length)
94
+ body.options = options;
95
+ const structured = [opts.inputs, opts.outputSchema, opts.successCriteria].some((v) => v !== undefined);
96
+ const d = await this.http.json('POST', '/v1/agents/message', {
97
+ json: body,
98
+ });
99
+ if (d.idempotent_replay) {
100
+ // The key was used before: this is that turn, and nothing was sent.
101
+ const record = parseTurnRecord(d);
102
+ this.id = record.sessionId ?? this.id;
103
+ this.machineId = record.machineId || this.machineId;
104
+ return new Turn(this, this.http, false, null, { id: record.id, structured, replay: record });
105
+ }
106
+ if (typeof d.sessionId !== 'string' || !d.sessionId) {
107
+ // Handled without starting a task (e.g. a plain acknowledgement): the reply is in `reply`,
108
+ // or in `error` on servers before `reply` existed.
109
+ const text = typeof d.reply === 'string' ? d.reply : typeof d.error === 'string' ? d.error : '';
110
+ return new Turn(this, this.http, false, localResult(this.id ?? '', text));
111
+ }
112
+ this.id = d.sessionId;
113
+ if (typeof d.machineId === 'string')
114
+ this.machineId = d.machineId;
115
+ const id = typeof d.turnId === 'string' ? d.turnId : null;
116
+ return new Turn(this, this.http, Boolean(d.queued), null, { id, structured });
117
+ }
118
+ /** `send()` then `wait()`: the answer, or where it stopped. */
119
+ async run(message, opts = {}) {
120
+ const turn = await this.send(message, opts);
121
+ return turn.wait(opts);
122
+ }
123
+ /** Stop the running turn. Pending approvals are denied. False if nothing was running. */
124
+ async abort() {
125
+ if (!this.id)
126
+ return false;
127
+ const d = await this.http.json('POST', '/v1/agents/abort', {
128
+ json: { sessionId: this.id },
129
+ });
130
+ return Boolean(d.aborted);
131
+ }
132
+ /**
133
+ * Answer an approval: `yes`, `no`, or `task` (allow for the rest of the task).
134
+ * A `choice` approval needs `selections`, one list of option values per
135
+ * question. Throws `LinkOnlyApprovalError` (with `approvalUrl`) when only a
136
+ * browser can answer it. Resolves to `approved`, `approved_task` or `denied`.
137
+ */
138
+ async respond(approval, response = 'yes', opts = {}) {
139
+ if (typeof approval !== 'string' && approval.isLinkOnly) {
140
+ throw new LinkOnlyApprovalError('This approval must be completed in a browser. Open approval.url.', { status: 409, code: 'link_only', body: { approvalUrl: approval.url } });
141
+ }
142
+ const body = {
143
+ approvalId: typeof approval === 'string' ? approval : approval.id,
144
+ response,
145
+ };
146
+ if (opts.selections)
147
+ body.selections = opts.selections;
148
+ const d = await this.http.json('POST', '/v1/agents/approve', {
149
+ json: body,
150
+ });
151
+ return d.status ?? '';
152
+ }
153
+ }
154
+ /**
155
+ * One message's work. Iterate `events()` to watch it, or `wait()` for the
156
+ * result. `id` is the turn the message started, or the running turn it joined
157
+ * (`sai.turns.get(turn)`); null when the message was answered without one.
158
+ */
159
+ export class Turn {
160
+ session;
161
+ http;
162
+ queued;
163
+ id;
164
+ cursor = null;
165
+ last;
166
+ structured;
167
+ replay;
168
+ // answered without starting a task, or an idempotent replay: no events to poll
169
+ local;
170
+ constructor(session, http, queued, done = null, turn = {
171
+ id: null,
172
+ structured: false,
173
+ }) {
174
+ this.session = session;
175
+ this.http = http;
176
+ this.queued = queued;
177
+ this.last = done;
178
+ this.id = turn.id;
179
+ this.structured = turn.structured;
180
+ this.replay = turn.replay ?? null;
181
+ this.local = done !== null || this.replay !== null;
182
+ }
183
+ get status() {
184
+ return this.last?.status ?? 'running';
185
+ }
186
+ /** The last known state, or null before the first poll. */
187
+ get result() {
188
+ return this.last;
189
+ }
190
+ /**
191
+ * Yield events until the turn is idle or errors. It keeps going through
192
+ * `needs_approval`: answer with `turn.respond(ev.approval, ...)` inside the
193
+ * loop, or let a human answer a link-only approval in a browser. Without
194
+ * `raw`, framing, reasoning and tool-call frames are skipped.
195
+ */
196
+ async *events(opts = {}) {
197
+ if (this.local)
198
+ return;
199
+ for (;;) {
200
+ const page = await this.#poll(opts.pollWait ?? POLL_WAIT);
201
+ for (const e of page.events ?? []) {
202
+ const ev = parseEvent(e);
203
+ if (opts.raw || ev.kind !== 'other')
204
+ yield ev;
205
+ }
206
+ if (page.status === 'idle' || page.status === 'error')
207
+ return;
208
+ }
209
+ }
210
+ /**
211
+ * Wait until the turn is done, or stops on an approval nobody answered.
212
+ * Without `onApproval`, resolves with `status === 'needs_approval'` and the
213
+ * `approval` so the caller can decide. With it, the handler's answer is sent
214
+ * and waiting continues; a handler returning null leaves the approval to
215
+ * someone else (a link-only one to a human) and keeps waiting. For a
216
+ * structured message, it then waits for the turn's record (`result.record`:
217
+ * output, evidence), which is worked out after the turn.
218
+ */
219
+ async wait(opts = {}) {
220
+ const deadline = opts.timeoutMs === undefined ? null : Date.now() + opts.timeoutMs;
221
+ if (this.replay) {
222
+ const record = this.replay.done
223
+ ? this.replay
224
+ : await waitTurnRecord(this.http, this.replay.id, deadline);
225
+ this.last = replayResult(record, record.sessionId ?? this.session.id ?? '');
226
+ return this.last;
227
+ }
228
+ if (this.local)
229
+ return this.last;
230
+ const answered = new Set();
231
+ for (;;) {
232
+ let pollWait = opts.pollWait ?? POLL_WAIT;
233
+ if (deadline !== null) {
234
+ const left = deadline - Date.now();
235
+ if (left <= 0) {
236
+ throw new DOMException(`Turn still ${this.status} after ${opts.timeoutMs}ms (session ${this.session.id}).`, 'TimeoutError');
237
+ }
238
+ pollWait = Math.max(1, Math.min(pollWait, Math.floor(left / 1000)));
239
+ }
240
+ const page = await this.#poll(pollWait);
241
+ if (page.status === 'idle' || page.status === 'error') {
242
+ if (this.structured && this.id) {
243
+ this.last = withRecord(this.last, await waitTurnRecord(this.http, this.id, deadline));
244
+ }
245
+ return this.last;
246
+ }
247
+ const approval = this.last?.approval;
248
+ if (page.status !== 'needs_approval' || !approval)
249
+ continue;
250
+ if (!opts.onApproval)
251
+ return this.last;
252
+ if (answered.has(approval.id))
253
+ continue;
254
+ const answer = await opts.onApproval(approval);
255
+ answered.add(approval.id);
256
+ if (answer === null)
257
+ continue;
258
+ const [response, selections] = typeof answer === 'string' ? [answer, undefined] : answer;
259
+ try {
260
+ await this.session.respond(approval, response, { selections });
261
+ }
262
+ catch (err) {
263
+ // answered elsewhere or expired; the next poll shows the new state
264
+ if (!(err instanceof ConflictError))
265
+ throw err;
266
+ }
267
+ }
268
+ }
269
+ respond(approval, response = 'yes', opts = {}) {
270
+ return this.session.respond(approval, response, opts);
271
+ }
272
+ abort() {
273
+ return this.session.abort();
274
+ }
275
+ async #poll(wait) {
276
+ let page;
277
+ for (;;) {
278
+ try {
279
+ page = await this.http.json('GET', '/v1/agents/events', {
280
+ params: { sessionId: this.session.id ?? '', wait, since: this.cursor ?? undefined },
281
+ timeoutMs: (wait + 30) * 1000,
282
+ });
283
+ break;
284
+ }
285
+ catch (err) {
286
+ if (!(err instanceof RateLimitError))
287
+ throw err;
288
+ await new Promise((r) => setTimeout(r, (err.retryAfter ?? 30) * 1000));
289
+ }
290
+ }
291
+ this.cursor = page.cursor ?? this.cursor;
292
+ let error = this.last?.error ?? null;
293
+ let errorCode = this.last?.errorCode ?? null;
294
+ for (const e of page.events ?? []) {
295
+ if (e.type === 'error') {
296
+ error = typeof e.errorText === 'string' ? e.errorText : error;
297
+ errorCode = typeof e.code === 'string' ? e.code : errorCode;
298
+ }
299
+ }
300
+ const status = page.status ?? 'running';
301
+ this.last = {
302
+ status,
303
+ text: page.text ?? '',
304
+ sessionId: page.sessionId ?? this.session.id ?? '',
305
+ approval: page.approval ? parseApproval(page.approval) : null,
306
+ error,
307
+ errorCode,
308
+ usage: parseUsage(page.usage),
309
+ sessionUsage: parseUsage(page.sessionUsage),
310
+ record: null,
311
+ ok: status === 'idle',
312
+ };
313
+ return page;
314
+ }
315
+ }
316
+ /**
317
+ * Read the turn's record until its status is in `stop`. Throws a `TimeoutError`
318
+ * (DOMException) past `deadline` (epoch ms).
319
+ */
320
+ export async function waitTurnRecord(http, turnId, deadline, stop = ['succeeded', 'failed']) {
321
+ for (;;) {
322
+ let record;
323
+ try {
324
+ record = parseTurnRecord(await http.json('GET', `/v1/agents/turns/${encodeURIComponent(turnId)}`));
325
+ }
326
+ catch (err) {
327
+ if (!(err instanceof RateLimitError))
328
+ throw err;
329
+ await sleep((err.retryAfter ?? 30) * 1000);
330
+ continue;
331
+ }
332
+ if (stop.includes(record.status))
333
+ return record;
334
+ if (deadline !== null && Date.now() + RECORD_POLL_INTERVAL_MS > deadline) {
335
+ throw new DOMException(`Turn ${turnId} still ${record.status}.`, 'TimeoutError');
336
+ }
337
+ await sleep(RECORD_POLL_INTERVAL_MS);
338
+ }
339
+ }
340
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
341
+ function withRecord(result, record) {
342
+ return { ...result, record, ok: result.status === 'idle' && record.ok };
343
+ }
344
+ // A turn that failed for these reasons still has the agent's answer; the turn itself did not break.
345
+ const ANSWERED_REASONS = ['output_invalid', 'criteria_not_met', 'criteria_unchecked'];
346
+ /** The result the live path would have returned for this finished turn, from its record. */
347
+ function replayResult(record, sessionId) {
348
+ const result = localResult(sessionId, record.rawAnswer || outputText(record.output));
349
+ if (record.status === 'failed' && !ANSWERED_REASONS.includes(record.reasonCode ?? '')) {
350
+ result.status = 'error';
351
+ result.text = '';
352
+ result.error = record.rawAnswer || `The turn failed (${record.reasonCode ?? 'unknown'}).`;
353
+ result.errorCode = record.errorCode;
354
+ }
355
+ result.usage = record.usage;
356
+ return withRecord(result, record);
357
+ }
358
+ /** `output` as text: a plain message's answer as is, an `outputSchema` object as JSON. */
359
+ function outputText(output) {
360
+ if (output === null || output === undefined)
361
+ return '';
362
+ return typeof output === 'string' ? output : JSON.stringify(output);
363
+ }
364
+ function localResult(sessionId, text) {
365
+ return {
366
+ status: 'idle',
367
+ text,
368
+ sessionId,
369
+ approval: null,
370
+ error: null,
371
+ errorCode: null,
372
+ usage: null,
373
+ sessionUsage: null,
374
+ record: null,
375
+ ok: true,
376
+ };
377
+ }
378
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}