@or3/intern-client 0.1.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,692 @@
1
+ export type UnknownRecord = Record<string, unknown>;
2
+
3
+ export class InternProtocolError extends Error {
4
+ readonly code = 'protocol';
5
+ readonly path: string;
6
+
7
+ constructor(path: string, message: string) {
8
+ super(`${path}: ${message}`);
9
+ this.name = 'InternProtocolError';
10
+ this.path = path;
11
+ }
12
+ }
13
+
14
+ export interface InternHealth extends UnknownRecord {
15
+ status: string;
16
+ runtimeAvailable: boolean;
17
+ jobRegistryAvailable: boolean;
18
+ approvalBrokerAvailable: boolean;
19
+ processId: number;
20
+ startedAt: string;
21
+ }
22
+
23
+ export interface InternReadiness extends UnknownRecord {
24
+ status: string;
25
+ ready: boolean;
26
+ summary?: UnknownRecord;
27
+ findings?: unknown[];
28
+ }
29
+
30
+ export interface InternCapabilities extends UnknownRecord {
31
+ runtimeProfile: string;
32
+ hosted: boolean;
33
+ hostId: string;
34
+ approvalBroker: UnknownRecord;
35
+ approvals: Record<string, string>;
36
+ execAvailable: boolean;
37
+ sandboxEnabled: boolean;
38
+ sandboxRequired: boolean;
39
+ networkPolicy: UnknownRecord;
40
+ }
41
+
42
+ export interface InternRunner extends UnknownRecord {
43
+ id: string;
44
+ display_name: string;
45
+ status: string;
46
+ auth_status: string;
47
+ supports: UnknownRecord;
48
+ chat_capabilities?: UnknownRecord;
49
+ }
50
+
51
+ export interface InternRunnerList extends UnknownRecord {
52
+ runners: InternRunner[];
53
+ default_runner?: string;
54
+ }
55
+
56
+ export interface InternSession extends UnknownRecord {
57
+ id: string;
58
+ app_session_key: string;
59
+ runner_id: string;
60
+ continuation_mode: string;
61
+ created_at: number;
62
+ updated_at: number;
63
+ native_session_ref?: string;
64
+ model?: string;
65
+ mode?: string;
66
+ isolation?: string;
67
+ cwd?: string;
68
+ max_turns?: number;
69
+ meta?: unknown;
70
+ }
71
+
72
+ export interface InternSessionList extends UnknownRecord {
73
+ sessions: InternSession[];
74
+ }
75
+
76
+ export interface InternTurn extends UnknownRecord {
77
+ id: string;
78
+ session_id: string;
79
+ sequence: number;
80
+ status: string;
81
+ continuation_mode: string;
82
+ requested_at: number;
83
+ started_at?: number;
84
+ completed_at?: number;
85
+ user_message?: string;
86
+ final_text?: string;
87
+ error?: string;
88
+ runner_run_id?: string;
89
+ runner_job_id?: string;
90
+ user_message_id?: number;
91
+ assistant_message_id?: number;
92
+ model?: string;
93
+ mode?: string;
94
+ isolation?: string;
95
+ cwd?: string;
96
+ }
97
+
98
+ export interface InternEvent extends UnknownRecord {
99
+ id: number;
100
+ turn_id: string;
101
+ seq: number;
102
+ ts: number;
103
+ type: string;
104
+ stream?: string;
105
+ text?: string;
106
+ job_id?: string;
107
+ payload?: unknown;
108
+ }
109
+
110
+ export interface InternApprovalDecision extends UnknownRecord {
111
+ request_id: number;
112
+ status?: string;
113
+ token?: string;
114
+ allowlist_id?: number;
115
+ session_key?: string;
116
+ }
117
+
118
+ export interface InternTurnList extends UnknownRecord {
119
+ turns: InternTurn[];
120
+ }
121
+
122
+ export interface InternEventList extends UnknownRecord {
123
+ events: InternEvent[];
124
+ }
125
+
126
+ export interface InternStartedTurn extends UnknownRecord {
127
+ session_id: string;
128
+ turn_id: string;
129
+ job_id: string;
130
+ status: string;
131
+ }
132
+
133
+ export interface InternActionAcknowledgement extends UnknownRecord {
134
+ status: string;
135
+ }
136
+
137
+ export interface InternTurnDecision extends UnknownRecord {
138
+ status: string;
139
+ decision: string;
140
+ route?: string;
141
+ approval_id?: number;
142
+ native_continued?: boolean;
143
+ fallback_to_token?: boolean;
144
+ allowlist_session?: boolean;
145
+ allowlist_id?: number;
146
+ token?: string;
147
+ }
148
+
149
+ export interface InternArtifact extends UnknownRecord {
150
+ id: string;
151
+ mime: string;
152
+ size_bytes: number;
153
+ offset: number;
154
+ read_bytes: number;
155
+ truncated: boolean;
156
+ content: string;
157
+ }
158
+
159
+ export interface InternApproval extends UnknownRecord {
160
+ id: string | number;
161
+ type: string;
162
+ status: string;
163
+ requested_at: number;
164
+ expires_at?: number;
165
+ resolved_at?: number;
166
+ preview?: string;
167
+ }
168
+
169
+ export interface InternApprovalList extends UnknownRecord {
170
+ items: InternApproval[];
171
+ }
172
+
173
+ export interface InternPairResult extends UnknownRecord {
174
+ certificate: UnknownRecord;
175
+ certificate_hash: string;
176
+ device: UnknownRecord;
177
+ }
178
+
179
+ export interface CreateInternSessionInput {
180
+ app_session_key: string;
181
+ runner_id: string;
182
+ continuation_mode?: string;
183
+ model?: string;
184
+ mode?: string;
185
+ isolation?: string;
186
+ cwd?: string;
187
+ max_turns?: number;
188
+ approval_autopilot?: boolean;
189
+ }
190
+
191
+ export interface StartInternTurnInput {
192
+ user_message: string;
193
+ attachments?: UnknownRecord[];
194
+ continuation_mode?: string;
195
+ model?: string;
196
+ mode?: string;
197
+ isolation?: string;
198
+ cwd?: string;
199
+ max_turns?: number;
200
+ timeout_seconds?: number;
201
+ meta?: UnknownRecord;
202
+ thinking_level?: string;
203
+ approval_token?: string;
204
+ approval_autopilot?: boolean;
205
+ runner_permission?: {
206
+ runner_id: string;
207
+ kind: string;
208
+ access: string;
209
+ target_path?: string;
210
+ };
211
+ }
212
+
213
+ export interface InternApprovalInput {
214
+ note?: string;
215
+ allow_session?: boolean;
216
+ allowlist?: boolean;
217
+ }
218
+
219
+ export interface InternPairInput {
220
+ rendezvous_id: string;
221
+ pairing_secret: string;
222
+ proposal: UnknownRecord;
223
+ trust_level: string;
224
+ expires_at?: number;
225
+ }
226
+
227
+ export type InternTurnDecisionAction = 'approve' | 'reject' | 'cancel';
228
+ export type InternApprovalDecisionAction = 'approve' | 'deny' | 'cancel';
229
+
230
+ function record(value: unknown, path: string): UnknownRecord {
231
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
232
+ throw new InternProtocolError(path, 'expected an object');
233
+ }
234
+ return value as UnknownRecord;
235
+ }
236
+
237
+ function stringAt(
238
+ input: UnknownRecord,
239
+ key: string,
240
+ path: string
241
+ ): string {
242
+ const value = input[key];
243
+ if (typeof value !== 'string') {
244
+ throw new InternProtocolError(`${path}.${key}`, 'expected a string');
245
+ }
246
+ return value;
247
+ }
248
+
249
+ function numberAt(
250
+ input: UnknownRecord,
251
+ key: string,
252
+ path: string
253
+ ): number {
254
+ const value = input[key];
255
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
256
+ throw new InternProtocolError(`${path}.${key}`, 'expected a finite number');
257
+ }
258
+ return value;
259
+ }
260
+
261
+ function booleanAt(
262
+ input: UnknownRecord,
263
+ key: string,
264
+ path: string
265
+ ): boolean {
266
+ const value = input[key];
267
+ if (typeof value !== 'boolean') {
268
+ throw new InternProtocolError(`${path}.${key}`, 'expected a boolean');
269
+ }
270
+ return value;
271
+ }
272
+
273
+ function optionalString(
274
+ input: UnknownRecord,
275
+ key: string,
276
+ path: string
277
+ ): string | undefined {
278
+ const value = input[key];
279
+ if (value === undefined) return undefined;
280
+ if (typeof value !== 'string') {
281
+ throw new InternProtocolError(`${path}.${key}`, 'expected a string');
282
+ }
283
+ return value;
284
+ }
285
+
286
+ function optionalNumber(
287
+ input: UnknownRecord,
288
+ key: string,
289
+ path: string
290
+ ): number | undefined {
291
+ const value = input[key];
292
+ if (value === undefined) return undefined;
293
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
294
+ throw new InternProtocolError(`${path}.${key}`, 'expected a finite number');
295
+ }
296
+ return value;
297
+ }
298
+
299
+ function optionalBoolean(
300
+ input: UnknownRecord,
301
+ key: string,
302
+ path: string
303
+ ): boolean | undefined {
304
+ const value = input[key];
305
+ if (value === undefined) return undefined;
306
+ if (typeof value !== 'boolean') {
307
+ throw new InternProtocolError(`${path}.${key}`, 'expected a boolean');
308
+ }
309
+ return value;
310
+ }
311
+
312
+ export function parseInternRecord(
313
+ value: unknown,
314
+ path = 'response'
315
+ ): UnknownRecord {
316
+ return { ...record(value, path) };
317
+ }
318
+
319
+ export function parseInternHealth(value: unknown): InternHealth {
320
+ const input = record(value, 'health');
321
+ return {
322
+ ...input,
323
+ status: stringAt(input, 'status', 'health'),
324
+ runtimeAvailable: booleanAt(input, 'runtimeAvailable', 'health'),
325
+ jobRegistryAvailable: booleanAt(
326
+ input,
327
+ 'jobRegistryAvailable',
328
+ 'health'
329
+ ),
330
+ approvalBrokerAvailable: booleanAt(
331
+ input,
332
+ 'approvalBrokerAvailable',
333
+ 'health'
334
+ ),
335
+ processId: numberAt(input, 'processId', 'health'),
336
+ startedAt: stringAt(input, 'startedAt', 'health'),
337
+ };
338
+ }
339
+
340
+ export function parseInternReadiness(value: unknown): InternReadiness {
341
+ const input = record(value, 'readiness');
342
+ const findings = input.findings;
343
+ if (findings !== undefined && !Array.isArray(findings)) {
344
+ throw new InternProtocolError(
345
+ 'readiness.findings',
346
+ 'expected an array'
347
+ );
348
+ }
349
+ return {
350
+ ...input,
351
+ status: stringAt(input, 'status', 'readiness'),
352
+ ready: booleanAt(input, 'ready', 'readiness'),
353
+ summary:
354
+ input.summary === undefined
355
+ ? undefined
356
+ : record(input.summary, 'readiness.summary'),
357
+ findings,
358
+ };
359
+ }
360
+
361
+ export function parseInternCapabilities(
362
+ value: unknown
363
+ ): InternCapabilities {
364
+ const input = record(value, 'capabilities');
365
+ const approvalInput = record(input.approvals, 'capabilities.approvals');
366
+ const approvals: Record<string, string> = {};
367
+ for (const [key, item] of Object.entries(approvalInput)) {
368
+ if (typeof item !== 'string') {
369
+ throw new InternProtocolError(
370
+ `capabilities.approvals.${key}`,
371
+ 'expected a string'
372
+ );
373
+ }
374
+ approvals[key] = item;
375
+ }
376
+ return {
377
+ ...input,
378
+ runtimeProfile: stringAt(input, 'runtimeProfile', 'capabilities'),
379
+ hosted: booleanAt(input, 'hosted', 'capabilities'),
380
+ hostId: stringAt(input, 'hostId', 'capabilities'),
381
+ approvalBroker: record(
382
+ input.approvalBroker,
383
+ 'capabilities.approvalBroker'
384
+ ),
385
+ approvals,
386
+ execAvailable: booleanAt(input, 'execAvailable', 'capabilities'),
387
+ sandboxEnabled: booleanAt(input, 'sandboxEnabled', 'capabilities'),
388
+ sandboxRequired: booleanAt(input, 'sandboxRequired', 'capabilities'),
389
+ networkPolicy: record(
390
+ input.networkPolicy,
391
+ 'capabilities.networkPolicy'
392
+ ),
393
+ };
394
+ }
395
+
396
+ export function parseInternRunnerList(value: unknown): InternRunnerList {
397
+ const input = record(value, 'runnerList');
398
+ if (!Array.isArray(input.runners)) {
399
+ throw new InternProtocolError('runnerList.runners', 'expected an array');
400
+ }
401
+ const runners = input.runners.map((item, index) => {
402
+ const runner = record(item, `runnerList.runners[${index}]`);
403
+ return {
404
+ ...runner,
405
+ id: stringAt(runner, 'id', `runnerList.runners[${index}]`),
406
+ display_name: stringAt(
407
+ runner,
408
+ 'display_name',
409
+ `runnerList.runners[${index}]`
410
+ ),
411
+ status: stringAt(
412
+ runner,
413
+ 'status',
414
+ `runnerList.runners[${index}]`
415
+ ),
416
+ auth_status: stringAt(
417
+ runner,
418
+ 'auth_status',
419
+ `runnerList.runners[${index}]`
420
+ ),
421
+ supports: record(
422
+ runner.supports,
423
+ `runnerList.runners[${index}].supports`
424
+ ),
425
+ chat_capabilities:
426
+ runner.chat_capabilities === undefined
427
+ ? undefined
428
+ : record(
429
+ runner.chat_capabilities,
430
+ `runnerList.runners[${index}].chat_capabilities`
431
+ ),
432
+ };
433
+ });
434
+ return {
435
+ ...input,
436
+ runners,
437
+ default_runner: optionalString(
438
+ input,
439
+ 'default_runner',
440
+ 'runnerList'
441
+ ),
442
+ };
443
+ }
444
+
445
+ export function parseInternSession(value: unknown): InternSession {
446
+ const input = record(value, 'session');
447
+ return {
448
+ ...input,
449
+ id: stringAt(input, 'id', 'session'),
450
+ app_session_key: stringAt(input, 'app_session_key', 'session'),
451
+ runner_id: stringAt(input, 'runner_id', 'session'),
452
+ continuation_mode: stringAt(
453
+ input,
454
+ 'continuation_mode',
455
+ 'session'
456
+ ),
457
+ created_at: numberAt(input, 'created_at', 'session'),
458
+ updated_at: numberAt(input, 'updated_at', 'session'),
459
+ native_session_ref: optionalString(
460
+ input,
461
+ 'native_session_ref',
462
+ 'session'
463
+ ),
464
+ model: optionalString(input, 'model', 'session'),
465
+ mode: optionalString(input, 'mode', 'session'),
466
+ isolation: optionalString(input, 'isolation', 'session'),
467
+ cwd: optionalString(input, 'cwd', 'session'),
468
+ max_turns: optionalNumber(input, 'max_turns', 'session'),
469
+ meta: input.meta,
470
+ };
471
+ }
472
+
473
+ export function parseInternSessionList(value: unknown): InternSessionList {
474
+ const input = record(value, 'sessionList');
475
+ if (!Array.isArray(input.sessions)) {
476
+ throw new InternProtocolError(
477
+ 'sessionList.sessions',
478
+ 'expected an array'
479
+ );
480
+ }
481
+ return {
482
+ ...input,
483
+ sessions: input.sessions.map(parseInternSession),
484
+ };
485
+ }
486
+
487
+ export function parseInternTurn(value: unknown): InternTurn {
488
+ const input = record(value, 'turn');
489
+ return {
490
+ ...input,
491
+ id: stringAt(input, 'id', 'turn'),
492
+ session_id: stringAt(input, 'session_id', 'turn'),
493
+ sequence: numberAt(input, 'sequence', 'turn'),
494
+ status: stringAt(input, 'status', 'turn'),
495
+ continuation_mode: stringAt(input, 'continuation_mode', 'turn'),
496
+ requested_at: numberAt(input, 'requested_at', 'turn'),
497
+ started_at: optionalNumber(input, 'started_at', 'turn'),
498
+ completed_at: optionalNumber(input, 'completed_at', 'turn'),
499
+ user_message: optionalString(input, 'user_message', 'turn'),
500
+ final_text: optionalString(input, 'final_text', 'turn'),
501
+ error: optionalString(input, 'error', 'turn'),
502
+ runner_run_id: optionalString(input, 'runner_run_id', 'turn'),
503
+ runner_job_id: optionalString(input, 'runner_job_id', 'turn'),
504
+ user_message_id: optionalNumber(input, 'user_message_id', 'turn'),
505
+ assistant_message_id: optionalNumber(
506
+ input,
507
+ 'assistant_message_id',
508
+ 'turn'
509
+ ),
510
+ model: optionalString(input, 'model', 'turn'),
511
+ mode: optionalString(input, 'mode', 'turn'),
512
+ isolation: optionalString(input, 'isolation', 'turn'),
513
+ cwd: optionalString(input, 'cwd', 'turn'),
514
+ };
515
+ }
516
+
517
+ export function parseInternEvent(value: unknown): InternEvent {
518
+ const input = record(value, 'event');
519
+ return {
520
+ ...input,
521
+ id: numberAt(input, 'id', 'event'),
522
+ turn_id: stringAt(input, 'turn_id', 'event'),
523
+ seq: numberAt(input, 'seq', 'event'),
524
+ ts: numberAt(input, 'ts', 'event'),
525
+ type: stringAt(input, 'type', 'event'),
526
+ stream: optionalString(input, 'stream', 'event'),
527
+ text: optionalString(input, 'text', 'event'),
528
+ job_id: optionalString(input, 'job_id', 'event'),
529
+ payload: input.payload,
530
+ };
531
+ }
532
+
533
+ export function parseInternApprovalDecision(
534
+ value: unknown
535
+ ): InternApprovalDecision {
536
+ const input = record(value, 'approvalDecision');
537
+ return {
538
+ ...input,
539
+ request_id: numberAt(input, 'request_id', 'approvalDecision'),
540
+ status: optionalString(input, 'status', 'approvalDecision'),
541
+ token: optionalString(input, 'token', 'approvalDecision'),
542
+ allowlist_id: optionalNumber(
543
+ input,
544
+ 'allowlist_id',
545
+ 'approvalDecision'
546
+ ),
547
+ session_key: optionalString(
548
+ input,
549
+ 'session_key',
550
+ 'approvalDecision'
551
+ ),
552
+ };
553
+ }
554
+
555
+ export function parseInternTurnList(value: unknown): InternTurnList {
556
+ const input = record(value, 'turnList');
557
+ if (!Array.isArray(input.turns)) {
558
+ throw new InternProtocolError('turnList.turns', 'expected an array');
559
+ }
560
+ return {
561
+ ...input,
562
+ turns: input.turns.map(parseInternTurn),
563
+ };
564
+ }
565
+
566
+ export function parseInternEventList(value: unknown): InternEventList {
567
+ const input = record(value, 'eventList');
568
+ if (!Array.isArray(input.events)) {
569
+ throw new InternProtocolError('eventList.events', 'expected an array');
570
+ }
571
+ return {
572
+ ...input,
573
+ events: input.events.map(parseInternEvent),
574
+ };
575
+ }
576
+
577
+ export function parseInternStartedTurn(value: unknown): InternStartedTurn {
578
+ const input = record(value, 'startedTurn');
579
+ return {
580
+ ...input,
581
+ session_id: stringAt(input, 'session_id', 'startedTurn'),
582
+ turn_id: stringAt(input, 'turn_id', 'startedTurn'),
583
+ job_id: stringAt(input, 'job_id', 'startedTurn'),
584
+ status: stringAt(input, 'status', 'startedTurn'),
585
+ };
586
+ }
587
+
588
+ export function parseInternActionAcknowledgement(
589
+ value: unknown
590
+ ): InternActionAcknowledgement {
591
+ const input = record(value, 'action');
592
+ return {
593
+ ...input,
594
+ status: stringAt(input, 'status', 'action'),
595
+ };
596
+ }
597
+
598
+ export function parseInternTurnDecision(value: unknown): InternTurnDecision {
599
+ const input = record(value, 'turnDecision');
600
+ return {
601
+ ...input,
602
+ status: stringAt(input, 'status', 'turnDecision'),
603
+ decision: stringAt(input, 'decision', 'turnDecision'),
604
+ route: optionalString(input, 'route', 'turnDecision'),
605
+ approval_id: optionalNumber(input, 'approval_id', 'turnDecision'),
606
+ native_continued: optionalBoolean(
607
+ input,
608
+ 'native_continued',
609
+ 'turnDecision'
610
+ ),
611
+ fallback_to_token: optionalBoolean(
612
+ input,
613
+ 'fallback_to_token',
614
+ 'turnDecision'
615
+ ),
616
+ allowlist_session: optionalBoolean(
617
+ input,
618
+ 'allowlist_session',
619
+ 'turnDecision'
620
+ ),
621
+ allowlist_id: optionalNumber(
622
+ input,
623
+ 'allowlist_id',
624
+ 'turnDecision'
625
+ ),
626
+ token: optionalString(input, 'token', 'turnDecision'),
627
+ };
628
+ }
629
+
630
+ export function parseInternArtifact(value: unknown): InternArtifact {
631
+ const input = record(value, 'artifact');
632
+ return {
633
+ ...input,
634
+ id: stringAt(input, 'id', 'artifact'),
635
+ mime: stringAt(input, 'mime', 'artifact'),
636
+ size_bytes: numberAt(input, 'size_bytes', 'artifact'),
637
+ offset: numberAt(input, 'offset', 'artifact'),
638
+ read_bytes: numberAt(input, 'read_bytes', 'artifact'),
639
+ truncated: booleanAt(input, 'truncated', 'artifact'),
640
+ content: stringAt(input, 'content', 'artifact'),
641
+ };
642
+ }
643
+
644
+ function parseInternApproval(value: unknown, index: number): InternApproval {
645
+ const path = `approvalList.items[${index}]`;
646
+ const input = record(value, path);
647
+ const id = input.id;
648
+ if (
649
+ (typeof id !== 'string' && typeof id !== 'number') ||
650
+ (typeof id === 'number' && !Number.isFinite(id))
651
+ ) {
652
+ throw new InternProtocolError(`${path}.id`, 'expected an ID');
653
+ }
654
+ return {
655
+ ...input,
656
+ id,
657
+ type: stringAt(input, 'type', path),
658
+ status: stringAt(input, 'status', path),
659
+ requested_at: numberAt(input, 'requested_at', path),
660
+ expires_at: optionalNumber(input, 'expires_at', path),
661
+ resolved_at: optionalNumber(input, 'resolved_at', path),
662
+ preview: optionalString(input, 'preview', path),
663
+ };
664
+ }
665
+
666
+ export function parseInternApprovalList(value: unknown): InternApprovalList {
667
+ const input = record(value, 'approvalList');
668
+ if (!Array.isArray(input.items)) {
669
+ throw new InternProtocolError(
670
+ 'approvalList.items',
671
+ 'expected an array'
672
+ );
673
+ }
674
+ return {
675
+ ...input,
676
+ items: input.items.map(parseInternApproval),
677
+ };
678
+ }
679
+
680
+ export function parseInternPairResult(value: unknown): InternPairResult {
681
+ const input = record(value, 'pairResult');
682
+ return {
683
+ ...input,
684
+ certificate: record(input.certificate, 'pairResult.certificate'),
685
+ certificate_hash: stringAt(
686
+ input,
687
+ 'certificate_hash',
688
+ 'pairResult'
689
+ ),
690
+ device: record(input.device, 'pairResult.device'),
691
+ };
692
+ }